mirror of
https://github.com/zhigang1992/connect.git
synced 2026-03-26 02:04:15 +08:00
init commit
This commit is contained in:
675
packages/app/.gitignore
vendored
Executable file
675
packages/app/.gitignore
vendored
Executable file
@@ -0,0 +1,675 @@
|
||||
### Project specifics ###
|
||||
dist/
|
||||
node_modules/
|
||||
|
||||
|
||||
|
||||
# Created by https://www.gitignore.io/api/node,macos,linux,eclipse,windows,intellij,visualstudio,microsoftoffice,visualstudiocode
|
||||
# Edit at https://www.gitignore.io/?templates=node,macos,linux,eclipse,windows,intellij,visualstudio,microsoftoffice,visualstudiocode
|
||||
|
||||
### Eclipse ###
|
||||
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.settings/
|
||||
.loadpath
|
||||
.recommenders
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# PyDev specific (Python IDE for Eclipse)
|
||||
*.pydevproject
|
||||
|
||||
# CDT-specific (C/C++ Development Tooling)
|
||||
.cproject
|
||||
|
||||
# CDT- autotools
|
||||
.autotools
|
||||
|
||||
# Java annotation processor (APT)
|
||||
.factorypath
|
||||
|
||||
# PDT-specific (PHP Development Tools)
|
||||
.buildpath
|
||||
|
||||
# sbteclipse plugin
|
||||
.target
|
||||
|
||||
# Tern plugin
|
||||
.tern-project
|
||||
|
||||
# TeXlipse plugin
|
||||
.texlipse
|
||||
|
||||
# STS (Spring Tool Suite)
|
||||
.springBeans
|
||||
|
||||
# Code Recommenders
|
||||
.recommenders/
|
||||
|
||||
# Annotation Processing
|
||||
.apt_generated/
|
||||
|
||||
# Scala IDE specific (Scala & Java development for Eclipse)
|
||||
.cache-main
|
||||
.scala_dependencies
|
||||
.worksheet
|
||||
|
||||
### Eclipse Patch ###
|
||||
# Eclipse Core
|
||||
.project
|
||||
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
|
||||
# Annotation Processing
|
||||
.apt_generated
|
||||
|
||||
.sts4-cache/
|
||||
|
||||
### Intellij ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### Intellij Patch ###
|
||||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||
|
||||
# *.iml
|
||||
# modules.xml
|
||||
# .idea/misc.xml
|
||||
# *.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
.idea/sonarlint
|
||||
|
||||
### Linux ###
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### MicrosoftOffice ###
|
||||
|
||||
# Word temporary
|
||||
~$*.doc*
|
||||
|
||||
# Word Auto Backup File
|
||||
Backup of *.doc*
|
||||
|
||||
# Excel temporary
|
||||
~$*.xls*
|
||||
|
||||
# Excel Backup File
|
||||
*.xlk
|
||||
|
||||
# PowerPoint temporary
|
||||
~$*.ppt*
|
||||
|
||||
# Visio autosave temporary files
|
||||
*.~vsd*
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like jest
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
#DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
|
||||
### Windows ###
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
### VisualStudio ###
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
# ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true
|
||||
**/wwwroot/lib/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# End of https://www.gitignore.io/api/node,macos,linux,eclipse,windows,intellij,visualstudio,microsoftoffice,visualstudiocode
|
||||
83
packages/app/.idea/markdown-navigator.xml
generated
Normal file
83
packages/app/.idea/markdown-navigator.xml
generated
Normal file
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownProjectSettings" wasCopied="true">
|
||||
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" showGitHubPageIfSynced="false" allowBrowsingInPreview="false" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="false" showSelectionInPreview="true" openRemoteLinks="true" replaceUnicodeEmoji="false" lastLayoutSetsDefault="false">
|
||||
<PanelProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
|
||||
</PanelProvider>
|
||||
</PreviewSettings>
|
||||
<ParserSettings gitHubSyntaxChange="false" emojiShortcuts="1" emojiImages="0">
|
||||
<PegdownExtensions>
|
||||
<option name="ABBREVIATIONS" value="false" />
|
||||
<option name="ANCHORLINKS" value="true" />
|
||||
<option name="ASIDE" value="false" />
|
||||
<option name="ATXHEADERSPACE" value="true" />
|
||||
<option name="AUTOLINKS" value="true" />
|
||||
<option name="DEFINITIONS" value="false" />
|
||||
<option name="DEFINITION_BREAK_DOUBLE_BLANK_LINE" value="false" />
|
||||
<option name="FENCED_CODE_BLOCKS" value="true" />
|
||||
<option name="FOOTNOTES" value="false" />
|
||||
<option name="HARDWRAPS" value="false" />
|
||||
<option name="HTML_DEEP_PARSER" value="false" />
|
||||
<option name="INSERTED" value="false" />
|
||||
<option name="QUOTES" value="false" />
|
||||
<option name="RELAXEDHRULES" value="true" />
|
||||
<option name="SMARTS" value="false" />
|
||||
<option name="STRIKETHROUGH" value="true" />
|
||||
<option name="SUBSCRIPT" value="false" />
|
||||
<option name="SUPERSCRIPT" value="false" />
|
||||
<option name="SUPPRESS_HTML_BLOCKS" value="false" />
|
||||
<option name="SUPPRESS_INLINE_HTML" value="false" />
|
||||
<option name="TABLES" value="true" />
|
||||
<option name="TASKLISTITEMS" value="true" />
|
||||
<option name="TOC" value="false" />
|
||||
<option name="WIKILINKS" value="false" />
|
||||
</PegdownExtensions>
|
||||
<ParserOptions>
|
||||
<option name="ADMONITION_EXT" value="false" />
|
||||
<option name="ATTRIBUTES_EXT" value="false" />
|
||||
<option name="COMMONMARK_LISTS" value="true" />
|
||||
<option name="DUMMY" value="false" />
|
||||
<option name="EMOJI_SHORTCUTS" value="true" />
|
||||
<option name="ENUMERATED_REFERENCES_EXT" value="false" />
|
||||
<option name="FLEXMARK_FRONT_MATTER" value="false" />
|
||||
<option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="false" />
|
||||
<option name="GFM_TABLE_RENDERING" value="true" />
|
||||
<option name="GITBOOK_URL_ENCODING" value="false" />
|
||||
<option name="GITHUB_LISTS" value="false" />
|
||||
<option name="GITHUB_WIKI_LINKS" value="false" />
|
||||
<option name="GITLAB_EXT" value="false" />
|
||||
<option name="GITLAB_MATH_EXT" value="false" />
|
||||
<option name="GITLAB_MERMAID_EXT" value="false" />
|
||||
<option name="HEADER_ID_NON_ASCII_TO_LOWERCASE" value="false" />
|
||||
<option name="HEADER_ID_NO_DUPED_DASHES" value="false" />
|
||||
<option name="JEKYLL_FRONT_MATTER" value="false" />
|
||||
<option name="MACROS_EXT" value="false" />
|
||||
<option name="NO_TEXT_ATTRIBUTES" value="false" />
|
||||
<option name="PARSE_HTML_ANCHOR_ID" value="false" />
|
||||
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
|
||||
</ParserOptions>
|
||||
</ParserSettings>
|
||||
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" embedUrlContent="false" addPageHeader="true" embedImages="false" embedHttpImages="false" imageUriSerials="false" addDocTypeHtml="true" noParaTags="false">
|
||||
<GeneratorProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
|
||||
</GeneratorProvider>
|
||||
<headerTop />
|
||||
<headerBottom />
|
||||
<bodyTop />
|
||||
<bodyBottom />
|
||||
</HtmlSettings>
|
||||
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssUriSerial="false" isCssTextEnabled="false" isDynamicPageWidth="true">
|
||||
<StylesheetProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.css" providerName="Default Swing Stylesheet" />
|
||||
</StylesheetProvider>
|
||||
<ScriptProviders />
|
||||
<cssText />
|
||||
<cssUriHistory />
|
||||
</CssSettings>
|
||||
<HtmlExportSettings updateOnSave="false" parentDir="" targetDir="" cssDir="" scriptDir="" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetPathType="2" targetExt="" useTargetExt="false" noCssNoScripts="false" useElementStyleAttribute="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
|
||||
<LinkMapSettings>
|
||||
<textMaps />
|
||||
</LinkMapSettings>
|
||||
</component>
|
||||
</project>
|
||||
6
packages/app/.idea/misc.xml
generated
Normal file
6
packages/app/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
</project>
|
||||
6
packages/app/.idea/vcs.xml
generated
Normal file
6
packages/app/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
21
packages/app/LICENSE
Executable file
21
packages/app/LICENSE
Executable file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 ymdevs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
51
packages/app/README.md
Executable file
51
packages/app/README.md
Executable file
@@ -0,0 +1,51 @@
|
||||
<div align="center">
|
||||
|
||||
# Web Extension Starter
|
||||
|
||||
</div>
|
||||
|
||||
This project containes a minimal setup for developing a performant and well structured web extension. The extension contains a demonstration counter that is displayed on the popup and options pages as well as any open tab.
|
||||
|
||||
## Good to know before using:
|
||||
* [Typescript](https://www.typescriptlang.org/)
|
||||
* [React](https://reactjs.org/)
|
||||
* [redux](https://redux.js.org/)
|
||||
* [styled-components](https://www.styled-components.com/)
|
||||
|
||||
|
||||
|
||||
## Requirements:
|
||||
* [NodeJS](https://nodejs.org/en/) - Javascript runtime
|
||||
* [VSCode](https://code.visualstudio.com/) - Recomended editor
|
||||
* [Chrome](https://www.google.com/chrome/) or [Firefox](https://www.mozilla.org/en-US/firefox/) - Web browser
|
||||
|
||||
## How to run:
|
||||
### In terminal or command prompt
|
||||
|
||||
```
|
||||
install dependencies
|
||||
- npm install
|
||||
Transpile the code
|
||||
- npm run dev (only transpiles the code)
|
||||
- npm run watch (transpiles and watches for code changes)
|
||||
|
||||
|
||||
yarn commands will work too if yarn is installed.
|
||||
```
|
||||
|
||||
### In Chrome web browser
|
||||
1. Go to: [**chrome://extensions**](chrome://extensions)
|
||||
2. Toggle: "**developer mode**" on.
|
||||
3. Click on: "**Load unpacked**"
|
||||
4. Select the newly created folder "**dist**" from the project folder.
|
||||
5. Thats it.
|
||||
|
||||
### In Firefox web browser
|
||||
1. Go to: [**about:debugging**](about:debugging)
|
||||
2. Select: "**Enable add-on debugging**"
|
||||
3. Click on: "**Load Temporary Add-on…**"
|
||||
4. Open the newly created folder "**dist**" from the project folder, and choose the "**manifest.json**" file.
|
||||
5. Thats it.
|
||||
|
||||
## License
|
||||
MIT
|
||||
186
packages/app/jest.config.js
Executable file
186
packages/app/jest.config.js
Executable file
@@ -0,0 +1,186 @@
|
||||
// For a detailed explanation regarding each configuration property, visit:
|
||||
// https://jestjs.io/docs/en/configuration.html
|
||||
|
||||
module.exports = {
|
||||
// All imported modules in your tests should be mocked automatically
|
||||
// automock: false,
|
||||
|
||||
// Stop running tests after `n` failures
|
||||
// bail: 0,
|
||||
|
||||
// Respect "browser" field in package.json when resolving modules
|
||||
// browser: false,
|
||||
|
||||
// The directory where Jest should store its cached dependency information
|
||||
// cacheDirectory: "C:\\Users\\Boobalay\\AppData\\Local\\Temp\\jest",
|
||||
|
||||
// Automatically clear mock calls and instances between every test
|
||||
// clearMocks: false,
|
||||
|
||||
// Indicates whether the coverage information should be collected while executing the test
|
||||
// collectCoverage: false,
|
||||
|
||||
// An array of glob patterns indicating a set of files for which coverage information should be collected
|
||||
collectCoverageFrom: ['src/**/*.{ts,tsx}'],
|
||||
|
||||
// The directory where Jest should output its coverage files
|
||||
// coverageDirectory: null,
|
||||
|
||||
// An array of regexp pattern strings used to skip coverage collection
|
||||
// coveragePathIgnorePatterns: [
|
||||
// "\\\\node_modules\\\\"
|
||||
// ],
|
||||
|
||||
// A list of reporter names that Jest uses when writing coverage reports
|
||||
// coverageReporters: [
|
||||
// "json",
|
||||
// "text",
|
||||
// "lcov",
|
||||
// "clover"
|
||||
// ],
|
||||
|
||||
// An object that configures minimum threshold enforcement for coverage results
|
||||
// coverageThreshold: null,
|
||||
|
||||
// A path to a custom dependency extractor
|
||||
// dependencyExtractor: null,
|
||||
|
||||
// Make calling deprecated APIs throw helpful error messages
|
||||
// errorOnDeprecated: false,
|
||||
|
||||
// Force coverage collection from ignored files usin a array of glob patterns
|
||||
// forceCoverageMatch: [],
|
||||
|
||||
// A path to a module which exports an async function that is triggered once before all test suites
|
||||
// globalSetup: null,
|
||||
|
||||
// A path to a module which exports an async function that is triggered once after all test suites
|
||||
// globalTeardown: null,
|
||||
|
||||
// A set of global variables that need to be available in all test environments
|
||||
// globals: {},
|
||||
|
||||
// An array of directory names to be searched recursively up from the requiring module's location
|
||||
// moduleDirectories: [
|
||||
// "node_modules"
|
||||
// ],
|
||||
|
||||
// An array of file extensions your modules use
|
||||
moduleFileExtensions: [
|
||||
"js",
|
||||
"json",
|
||||
"jsx",
|
||||
"ts",
|
||||
"tsx",
|
||||
"node"
|
||||
],
|
||||
|
||||
// A map from regular expressions to module names that allow to stub out resources with a single module
|
||||
// moduleNameMapper: {},
|
||||
|
||||
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
|
||||
// modulePathIgnorePatterns: [],
|
||||
|
||||
// Activates notifications for test results
|
||||
// notify: false,
|
||||
|
||||
// An enum that specifies notification mode. Requires { notify: true }
|
||||
// notifyMode: "failure-change",
|
||||
|
||||
// A preset that is used as a base for Jest's configuration
|
||||
// preset: null,
|
||||
|
||||
// Run tests from one or more projects
|
||||
// projects: null,
|
||||
|
||||
// Use this configuration option to add custom reporters to Jest
|
||||
// reporters: undefined,
|
||||
|
||||
// Automatically reset mock state between every test
|
||||
// resetMocks: false,
|
||||
|
||||
// Reset the module registry before running each individual test
|
||||
// resetModules: false,
|
||||
|
||||
// A path to a custom resolver
|
||||
// resolver: null,
|
||||
|
||||
// Automatically restore mock state between every test
|
||||
// restoreMocks: false,
|
||||
|
||||
// The root directory that Jest should scan for tests and modules within
|
||||
// rootDir: null,
|
||||
|
||||
// A list of paths to directories that Jest should use to search for files in
|
||||
roots: [
|
||||
"<rootDir>/tests",
|
||||
"<rootDir>/src"
|
||||
],
|
||||
|
||||
// Allows you to use a custom runner instead of Jest's default test runner
|
||||
// runner: "jest-runner",
|
||||
|
||||
// The paths to modules that run some code to configure or set up the testing environment before each test
|
||||
// setupFiles: [],
|
||||
|
||||
// A list of paths to modules that run some code to configure or set up the testing framework before each test
|
||||
// setupFilesAfterEnv: [],
|
||||
|
||||
// A list of paths to snapshot serializer modules Jest should use for snapshot testing
|
||||
// snapshotSerializers: [],
|
||||
|
||||
// The test environment that will be used for testing
|
||||
testEnvironment: "jsdom",
|
||||
|
||||
// Options that will be passed to the testEnvironment
|
||||
// testEnvironmentOptions: {},
|
||||
|
||||
// Adds a location field to test results
|
||||
// testLocationInResults: false,
|
||||
|
||||
// The glob patterns Jest uses to detect test files
|
||||
// testMatch: [
|
||||
// "**/tests/**/*.[jt]s?(x)",
|
||||
// "**/?(*.)+(spec|test).[tj]s?(x)"
|
||||
// ],
|
||||
|
||||
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
|
||||
// testPathIgnorePatterns: [
|
||||
// "\\\\node_modules\\\\"
|
||||
// ],
|
||||
|
||||
// The regexp pattern or array of patterns that Jest uses to detect test files
|
||||
testRegex: "/tests/.*\.test\.tsx?$",
|
||||
|
||||
// This option allows the use of a custom results processor
|
||||
// testResultsProcessor: null,
|
||||
|
||||
// This option allows use of a custom test runner
|
||||
// testRunner: "jasmine2",
|
||||
|
||||
// This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
|
||||
// testURL: "http://localhost",
|
||||
|
||||
// Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"
|
||||
// timers: "real",
|
||||
|
||||
// A map from regular expressions to paths to transformers
|
||||
transform: { "^.+\\.tsx?$": "ts-jest" },
|
||||
|
||||
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
|
||||
// transformIgnorePatterns: [
|
||||
// "\\\\node_modules\\\\"
|
||||
// ],
|
||||
|
||||
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
|
||||
// unmockedModulePathPatterns: undefined,
|
||||
|
||||
// Indicates whether each individual test should be reported during the run
|
||||
// verbose: null,
|
||||
|
||||
// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
|
||||
// watchPathIgnorePatterns: [],
|
||||
|
||||
// Whether to use watchman for file crawling
|
||||
// watchman: true,
|
||||
};
|
||||
53
packages/app/package.json
Executable file
53
packages/app/package.json
Executable file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "web-extension-starter",
|
||||
"version": "1.0.0",
|
||||
"description": "A web browser extension starter - based on Typescript, React, Redux, Styled-Component, Webpack, and more. Runs on Chrome and Firefox.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "cross-env NODE_ENV=development webpack -d",
|
||||
"prod": "cross-env NODE_ENV=production webpack -p",
|
||||
"watch": "cross-env NODE_ENV=watch webpack -d",
|
||||
"clean": "rm -rf ./dist",
|
||||
"clean:all": "rm -rf ./dist && rm -rf ./coverage && rm -rf ./node_modules",
|
||||
"test": "jest",
|
||||
"test:coverage": "jest --collect-coverage"
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react": "^16.8.6",
|
||||
"react-chrome-redux": "^2.0.0-alpha.5",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-redux": "^7.1.0",
|
||||
"redux": "4.0.1",
|
||||
"styled-components": "^4.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chrome": "^0.0.86",
|
||||
"@types/jest": "^24.0.15",
|
||||
"@types/node": "^12.6.2",
|
||||
"@types/react": "^16.8.23",
|
||||
"@types/react-dom": "^16.8.4",
|
||||
"@types/react-redux": "^7.1.1",
|
||||
"@types/react-test-renderer": "^16.8.2",
|
||||
"@types/redux": "^3.6.0",
|
||||
"@types/styled-components": "4.1.8",
|
||||
"@types/webpack": "^4.4.35",
|
||||
"awesome-typescript-loader": "^5.2.1",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"copy-webpack-plugin": "^5.0.3",
|
||||
"cross-env": "^5.2.0",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"jest": "^24.8.0",
|
||||
"react-test-renderer": "^16.8.6",
|
||||
"ts-jest": "^24.0.2",
|
||||
"tslint": "^5.18.0",
|
||||
"typescript": "^3.5.3",
|
||||
"webpack": "^4.35.3",
|
||||
"webpack-chrome-extension-reloader": "^1.3.0",
|
||||
"webpack-cli": "^3.3.5"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/ymdevs/Web-Extension-Starter.git"
|
||||
}
|
||||
}
|
||||
BIN
packages/app/src/assets/icon-128.png
Executable file
BIN
packages/app/src/assets/icon-128.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
BIN
packages/app/src/assets/icon-48.png
Executable file
BIN
packages/app/src/assets/icon-48.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
12
packages/app/src/assets/icon.svg
Executable file
12
packages/app/src/assets/icon.svg
Executable file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE svg >
|
||||
<svg id="icon" width="500px" height="500px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" version="1.1">
|
||||
<g id="logo">
|
||||
<circle fill="rgb(190, 190, 190)" cx="50" cy="50" r="50" />
|
||||
<circle fill="rgb(135, 153, 217)" cx="47" cy="50" r="44" />
|
||||
<path fill="rgb(240, 240, 240)"
|
||||
d=" M 81, 45
|
||||
A 50, 50 0 0,0 58, 17
|
||||
A 30, 30 0 0,1 42, 18
|
||||
A 50, 50 0 0,1 81, 45" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 423 B |
10
packages/app/src/html/options.html
Executable file
10
packages/app/src/html/options.html
Executable file
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="options-root"></div>
|
||||
</body>
|
||||
</html>
|
||||
10
packages/app/src/html/popup.html
Executable file
10
packages/app/src/html/popup.html
Executable file
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="popup-root"></div>
|
||||
</body>
|
||||
</html>
|
||||
43
packages/app/src/manifest.json
Executable file
43
packages/app/src/manifest.json
Executable file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "Web Extension Starter",
|
||||
"author": "ymdevs",
|
||||
"version": "1.0.0",
|
||||
"description": "A web browser extension starter - based on Typescript, React, Redux, Styled-Component, Webpack, and more. Runs on Chrome and Firefox.",
|
||||
"icons": {
|
||||
"128": "assets/icon-128.png"
|
||||
},
|
||||
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
|
||||
"permissions": [
|
||||
"activeTab",
|
||||
"alarms",
|
||||
"bookmarks",
|
||||
"cookies",
|
||||
"storage",
|
||||
"tabs",
|
||||
"webRequest",
|
||||
"webRequestBlocking",
|
||||
"*://*/*"
|
||||
],
|
||||
"manifest_version": 2,
|
||||
"background": {
|
||||
"scripts": [
|
||||
"background.js"
|
||||
],
|
||||
"persistent": true
|
||||
},
|
||||
"browser_action": {
|
||||
"default_title": "Web Extension Starter",
|
||||
"default_icon": "assets/icon-48.png",
|
||||
"default_popup": "popup.html"
|
||||
},
|
||||
"options_ui": {
|
||||
"page": "options.html",
|
||||
"open_in_tab": true
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"js": ["counter.js"],
|
||||
"matches": ["*://*/*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
14
packages/app/src/ts/background/AppConfig.ts
Executable file
14
packages/app/src/ts/background/AppConfig.ts
Executable file
@@ -0,0 +1,14 @@
|
||||
import { Store } from 'redux';
|
||||
import { IAppState, saveState } from './store';
|
||||
|
||||
const autoSaveAppState = (store: Store<IAppState>) => {
|
||||
chrome.tabs.onRemoved.addListener(() => saveState(store.getState()));
|
||||
chrome.windows.onRemoved.addListener(() => saveState(store.getState()));
|
||||
|
||||
const saveFrequency = 30000; // 30seconds * 1000milliseconds / 1second
|
||||
setInterval(() => (saveState(store.getState())), saveFrequency);
|
||||
};
|
||||
|
||||
export const configureApp = (store: Store<IAppState>) => {
|
||||
autoSaveAppState(store);
|
||||
};
|
||||
13
packages/app/src/ts/background/index.ts
Executable file
13
packages/app/src/ts/background/index.ts
Executable file
@@ -0,0 +1,13 @@
|
||||
import { Store, wrapStore } from 'react-chrome-redux';
|
||||
import { createStore } from 'redux';
|
||||
import { configureApp } from './AppConfig';
|
||||
import reducers, { IAppState, loadState } from './store';
|
||||
|
||||
const preloadedState = loadState();
|
||||
const store: Store<IAppState> = createStore(reducers, preloadedState);
|
||||
|
||||
configureApp(store);
|
||||
|
||||
wrapStore(store, {
|
||||
portName: 'ExPort' // Communication port between the background component and views such as browser tabs.
|
||||
});
|
||||
9
packages/app/src/ts/background/store/counter/actions.ts
Executable file
9
packages/app/src/ts/background/store/counter/actions.ts
Executable file
@@ -0,0 +1,9 @@
|
||||
import { Action } from 'redux';
|
||||
|
||||
export type CounterActionTypes = 'INCREMENT' | 'DECREMENT';
|
||||
export type CounterPayload = number;
|
||||
|
||||
export type CounterActions = Action<CounterActionTypes, CounterPayload>;
|
||||
|
||||
export const increment = (payload: CounterPayload = 1) => ({ type: 'INCREMENT', payload });
|
||||
export const decrement = (payload: CounterPayload = 1) => ({ type: 'DECREMENT', payload });
|
||||
2
packages/app/src/ts/background/store/counter/index.ts
Executable file
2
packages/app/src/ts/background/store/counter/index.ts
Executable file
@@ -0,0 +1,2 @@
|
||||
export * from './actions';
|
||||
export * from './reducer';
|
||||
26
packages/app/src/ts/background/store/counter/reducer.ts
Executable file
26
packages/app/src/ts/background/store/counter/reducer.ts
Executable file
@@ -0,0 +1,26 @@
|
||||
import { Reducer} from 'redux';
|
||||
import { CounterActions } from './actions';
|
||||
|
||||
export interface ICounter {
|
||||
clicksMade: number;
|
||||
}
|
||||
|
||||
const initialState: ICounter = {
|
||||
clicksMade: 0
|
||||
};
|
||||
|
||||
const counter: Reducer<ICounter, CounterActions> = (state = initialState, action) => {
|
||||
const { payload } = action;
|
||||
switch (action.type) {
|
||||
case 'INCREMENT':
|
||||
return { ...state, clicksMade: state.clicksMade + (payload || 1) };
|
||||
|
||||
case 'DECREMENT':
|
||||
return { ...state, clicksMade: state.clicksMade - (payload || 1) };
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default counter;
|
||||
50
packages/app/src/ts/background/store/index.ts
Executable file
50
packages/app/src/ts/background/store/index.ts
Executable file
@@ -0,0 +1,50 @@
|
||||
import { combineReducers } from 'redux';
|
||||
import counter, { ICounter } from './counter/reducer';
|
||||
import settings, { IAppSettings } from './settings/reducer';
|
||||
|
||||
import 'redux';
|
||||
// Enhance the Action interface with the option of a payload.
|
||||
// While still importing the Action interface from redux.
|
||||
declare module 'redux' {
|
||||
export interface Action<T = any, P = any> {
|
||||
type: T;
|
||||
payload?: P;
|
||||
}
|
||||
}
|
||||
|
||||
type OnSuccess = () => void;
|
||||
type OnError = (e: Error) => void;
|
||||
|
||||
export interface IAppState {
|
||||
counter: ICounter;
|
||||
settings: IAppSettings;
|
||||
}
|
||||
|
||||
export const loadState = (): IAppState | undefined => {
|
||||
try {
|
||||
const serializedState = localStorage.getItem('appstate');
|
||||
if (serializedState === null) {
|
||||
return undefined;
|
||||
}
|
||||
return JSON.parse(serializedState);
|
||||
} catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export const saveState = (appstate: IAppState, success: OnSuccess = () => {}, error: OnError = () => {}) => {
|
||||
try {
|
||||
const serializedState = JSON.stringify(appstate);
|
||||
localStorage.setItem('appstate', serializedState);
|
||||
success();
|
||||
} catch (e) {
|
||||
error(e);
|
||||
}
|
||||
};
|
||||
|
||||
const reducers = combineReducers<IAppState>({
|
||||
counter,
|
||||
settings
|
||||
});
|
||||
|
||||
export default reducers;
|
||||
8
packages/app/src/ts/background/store/settings/actions.ts
Executable file
8
packages/app/src/ts/background/store/settings/actions.ts
Executable file
@@ -0,0 +1,8 @@
|
||||
import { Action } from 'redux';
|
||||
|
||||
export type ThemeActionTypes = 'DARK_THEME' | 'LIGHT_THEME';
|
||||
|
||||
export type SettingsActions = Action<ThemeActionTypes>;
|
||||
|
||||
export const setDarkTheme = () => ({ type: 'DARK_THEME' });
|
||||
export const setLightTheme = () => ({ type: 'LIGHT_THEME' });
|
||||
2
packages/app/src/ts/background/store/settings/index.ts
Executable file
2
packages/app/src/ts/background/store/settings/index.ts
Executable file
@@ -0,0 +1,2 @@
|
||||
export * from './actions';
|
||||
export * from './reducer';
|
||||
26
packages/app/src/ts/background/store/settings/reducer.ts
Executable file
26
packages/app/src/ts/background/store/settings/reducer.ts
Executable file
@@ -0,0 +1,26 @@
|
||||
import { Reducer } from 'redux';
|
||||
import { ThemeTypes } from './../../../components/styles/themes';
|
||||
import { SettingsActions } from './actions';
|
||||
|
||||
export interface IAppSettings {
|
||||
theme: ThemeTypes;
|
||||
}
|
||||
|
||||
const initialState: IAppSettings = {
|
||||
theme: 'light'
|
||||
};
|
||||
|
||||
const settings: Reducer<IAppSettings, SettingsActions> = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case 'DARK_THEME':
|
||||
return { ...state, theme: 'dark' };
|
||||
|
||||
case 'LIGHT_THEME':
|
||||
return { ...state, theme: 'light' };
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default settings;
|
||||
11
packages/app/src/ts/components/styles/GlobalStyle.tsx
Executable file
11
packages/app/src/ts/components/styles/GlobalStyle.tsx
Executable file
@@ -0,0 +1,11 @@
|
||||
import { createGlobalStyle } from 'styled-components';
|
||||
|
||||
const GlobalStyle = createGlobalStyle`
|
||||
body {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export default GlobalStyle;
|
||||
8
packages/app/src/ts/components/styles/styled-components.ts
Executable file
8
packages/app/src/ts/components/styles/styled-components.ts
Executable file
@@ -0,0 +1,8 @@
|
||||
import 'styled-components';
|
||||
// Enhance the DefaultTheme interface with new attributes.
|
||||
// While still importing the DefaultTheme interface from styled-components.
|
||||
declare module 'styled-components' {
|
||||
export interface DefaultTheme {
|
||||
backgroundColor: string;
|
||||
}
|
||||
}
|
||||
16
packages/app/src/ts/components/styles/themes/index.ts
Executable file
16
packages/app/src/ts/components/styles/themes/index.ts
Executable file
@@ -0,0 +1,16 @@
|
||||
import { DefaultTheme } from 'styled-components';
|
||||
|
||||
export type ThemeTypes = 'light' | 'dark';
|
||||
|
||||
export const lightTheme: DefaultTheme = {
|
||||
backgroundColor: 'lightblue'
|
||||
};
|
||||
|
||||
export const darkTheme: DefaultTheme = {
|
||||
backgroundColor: '#181818'
|
||||
};
|
||||
|
||||
export const themes = {
|
||||
light: lightTheme,
|
||||
dark: darkTheme,
|
||||
};
|
||||
90
packages/app/src/ts/containers/Counter.tsx
Executable file
90
packages/app/src/ts/containers/Counter.tsx
Executable file
@@ -0,0 +1,90 @@
|
||||
import * as React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Dispatch } from 'redux';
|
||||
import styled from 'styled-components';
|
||||
import { IAppState } from '../background/store';
|
||||
import { decrement, increment } from '../background/store/counter/actions';
|
||||
import { ICounter } from '../background/store/counter/reducer';
|
||||
|
||||
interface ICounterProps {
|
||||
counter: ICounter;
|
||||
dispatch: Dispatch;
|
||||
}
|
||||
|
||||
class Counter extends React.Component<ICounterProps> {
|
||||
increment = () => {
|
||||
this.props.dispatch(increment());
|
||||
}
|
||||
decrement = () => {
|
||||
this.props.dispatch(decrement());
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<CounterContainer >
|
||||
<Display>
|
||||
{this.props.counter.clicksMade}
|
||||
</Display>
|
||||
<Controls>
|
||||
<Button onClick={this.increment}>+</Button>
|
||||
<Button onClick={this.decrement}>-</Button>
|
||||
</Controls>
|
||||
</CounterContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: IAppState) => {
|
||||
return {
|
||||
counter: state.counter,
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(Counter);
|
||||
|
||||
const CounterContainer = styled('div')`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
min-width: 100px;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
background-color: ${p => p.theme.backgroundColor};
|
||||
`;
|
||||
|
||||
const Display = styled('div')`
|
||||
font-size: 48px;
|
||||
justify-self: center;
|
||||
`;
|
||||
|
||||
const Controls = styled('div')`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
min-width: 200px;
|
||||
`;
|
||||
|
||||
// Thanks to: https://codepen.io/FelipeMarcos/pen/tfhEg?editors=1100
|
||||
const Button = styled('button')`
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding: 10px 30px;
|
||||
border: 1px solid transparent;
|
||||
border-bottom: 4px solid rgba(0,0,0,0.21);
|
||||
border-radius: 4px;
|
||||
background: linear-gradient(rgba(27,188,194,1) 0%, rgba(24,163,168,1) 100%);
|
||||
|
||||
color: white;
|
||||
font-size: 22px;
|
||||
text-shadow: 0 1px 0 rgba(0,0,0,0.15);
|
||||
text-decoration: none;
|
||||
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
user-select: none;
|
||||
|
||||
&:active {
|
||||
background: #169499;
|
||||
}
|
||||
`;
|
||||
44
packages/app/src/ts/contentScripts/counter/containers/CounterApp.tsx
Executable file
44
packages/app/src/ts/contentScripts/counter/containers/CounterApp.tsx
Executable file
@@ -0,0 +1,44 @@
|
||||
import * as React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Dispatch } from 'redux';
|
||||
import styled, { ThemeProvider } from 'styled-components';
|
||||
import { IAppState } from '../../../background/store';
|
||||
import { themes, ThemeTypes } from '../../../components/styles/themes';
|
||||
import Counter from '../../../containers/Counter';
|
||||
|
||||
interface ICounterApp {
|
||||
theme: ThemeTypes;
|
||||
dispatch: Dispatch;
|
||||
}
|
||||
|
||||
class CounterApp extends React.Component<ICounterApp> {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ThemeProvider theme={themes[this.props.theme]}>
|
||||
<React.Fragment>
|
||||
<CounterAppContainer >
|
||||
<Counter />
|
||||
</CounterAppContainer>
|
||||
</React.Fragment>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: IAppState) => {
|
||||
return {
|
||||
theme: state.settings.theme
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(CounterApp);
|
||||
|
||||
const CounterAppContainer = styled('div')`
|
||||
position: fixed;
|
||||
z-index: 9;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: ${p => p.theme.backgroundColor};
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
`;
|
||||
21
packages/app/src/ts/contentScripts/counter/index.tsx
Executable file
21
packages/app/src/ts/contentScripts/counter/index.tsx
Executable file
@@ -0,0 +1,21 @@
|
||||
import * as React from 'react';
|
||||
import { Store } from 'react-chrome-redux';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import CounterApp from './containers/CounterApp';
|
||||
|
||||
import { createDomAnchor } from '../../scripts/dom';
|
||||
|
||||
createDomAnchor('counter-root');
|
||||
|
||||
const store = new Store({
|
||||
portName: 'ExPort' // Communication port between the background component and views such as browser tabs.
|
||||
});
|
||||
|
||||
store.ready().then(() => {
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<CounterApp />
|
||||
</Provider>
|
||||
, document.getElementById('counter-root'));
|
||||
});
|
||||
52
packages/app/src/ts/options/containers/OptionsApp.tsx
Executable file
52
packages/app/src/ts/options/containers/OptionsApp.tsx
Executable file
@@ -0,0 +1,52 @@
|
||||
import * as React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Dispatch } from 'redux';
|
||||
import styled, { ThemeProvider } from 'styled-components';
|
||||
import { IAppState } from '../../background/store';
|
||||
import GlobalStyle from '../../components/styles/GlobalStyle';
|
||||
import { themes, ThemeTypes } from '../../components/styles/themes';
|
||||
import Counter from '../../containers/Counter';
|
||||
|
||||
interface IOptionsApp {
|
||||
theme: ThemeTypes;
|
||||
dispatch: Dispatch;
|
||||
}
|
||||
|
||||
class OptionsApp extends React.Component<IOptionsApp> {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ThemeProvider theme={themes[this.props.theme]}>
|
||||
<React.Fragment>
|
||||
<GlobalStyle />
|
||||
<OptionsAppContainer>
|
||||
<Counter/>
|
||||
</OptionsAppContainer>
|
||||
</React.Fragment>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: IAppState) => {
|
||||
return {
|
||||
theme: state.settings.theme
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(OptionsApp);
|
||||
|
||||
const OptionsAppContainer = styled('div')`
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
height: 90vh;
|
||||
width: 90vw;
|
||||
left: 5vw;
|
||||
top: 5vh;
|
||||
background-color: ${p => p.theme.backgroundColor};
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
`;
|
||||
17
packages/app/src/ts/options/index.tsx
Executable file
17
packages/app/src/ts/options/index.tsx
Executable file
@@ -0,0 +1,17 @@
|
||||
import * as React from 'react';
|
||||
import { Store } from 'react-chrome-redux';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import OptionsApp from './containers/OptionsApp';
|
||||
|
||||
const store = new Store({
|
||||
portName: 'ExPort' // Communication port between the background component and views such as browser tabs.
|
||||
});
|
||||
|
||||
store.ready().then(() => {
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<OptionsApp />
|
||||
</Provider>
|
||||
, document.getElementById('options-root'));
|
||||
});
|
||||
50
packages/app/src/ts/popup/containers/PopupApp.tsx
Executable file
50
packages/app/src/ts/popup/containers/PopupApp.tsx
Executable file
@@ -0,0 +1,50 @@
|
||||
import * as React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Dispatch } from 'redux';
|
||||
import styled, { ThemeProvider } from 'styled-components';
|
||||
import { IAppState } from '../../background/store';
|
||||
import GlobalStyle from '../../components/styles/GlobalStyle';
|
||||
import { themes, ThemeTypes } from '../../components/styles/themes';
|
||||
import Counter from '../../containers/Counter';
|
||||
|
||||
interface IPopupApp {
|
||||
theme: ThemeTypes;
|
||||
dispatch: Dispatch;
|
||||
}
|
||||
|
||||
class PopupApp extends React.Component<IPopupApp> {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ThemeProvider theme={themes[this.props.theme]}>
|
||||
<React.Fragment>
|
||||
<GlobalStyle />
|
||||
<PopupAppContainer>
|
||||
<Counter />
|
||||
</PopupAppContainer>
|
||||
</React.Fragment>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: IAppState) => {
|
||||
return {
|
||||
theme: state.settings.theme
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(PopupApp);
|
||||
|
||||
const PopupAppContainer = styled('div')`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
height: 200px;
|
||||
width: 300px;
|
||||
margin: 10px;
|
||||
background-color: ${p => p.theme.backgroundColor};
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
`;
|
||||
17
packages/app/src/ts/popup/index.tsx
Executable file
17
packages/app/src/ts/popup/index.tsx
Executable file
@@ -0,0 +1,17 @@
|
||||
import * as React from 'react';
|
||||
import { Store } from 'react-chrome-redux';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import PopupApp from './containers/PopupApp';
|
||||
|
||||
const store = new Store({
|
||||
portName: 'ExPort' // Communication port between the background component and views such as browser tabs.
|
||||
});
|
||||
|
||||
store.ready().then(() => {
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<PopupApp />
|
||||
</Provider>
|
||||
, document.getElementById('popup-root'));
|
||||
});
|
||||
5
packages/app/src/ts/scripts/dom.ts
Executable file
5
packages/app/src/ts/scripts/dom.ts
Executable file
@@ -0,0 +1,5 @@
|
||||
export const createDomAnchor = (anchorId: string) => {
|
||||
const anchor = document.createElement('div');
|
||||
anchor.id = anchorId;
|
||||
document.body.insertBefore(anchor, document.body.childNodes[0]);
|
||||
};
|
||||
11
packages/app/tests/ts/components/styles/GlobalStyle.test.tsx
Executable file
11
packages/app/tests/ts/components/styles/GlobalStyle.test.tsx
Executable file
@@ -0,0 +1,11 @@
|
||||
import renderer from 'react-test-renderer';
|
||||
import GlobalStyle from '../../../../src/ts/components/styles/GlobalStyle';
|
||||
|
||||
describe('Testing Global Style', () => {
|
||||
|
||||
test('GlobalStyle Snapshot.', () => {
|
||||
// @ts-ignore
|
||||
const wow = renderer.create(GlobalStyle.globalStyle.rules).toJSON();
|
||||
expect(wow).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Testing Global Style GlobalStyle Snapshot. 1`] = `
|
||||
"
|
||||
body {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
||||
"
|
||||
`;
|
||||
8
packages/app/tests/ts/components/styles/themes/index.test.ts
Executable file
8
packages/app/tests/ts/components/styles/themes/index.test.ts
Executable file
@@ -0,0 +1,8 @@
|
||||
import { themes } from '../../../../../src/ts/components/styles/themes';
|
||||
|
||||
describe('Testing themes configuration', () => {
|
||||
test('Theme object containes a dark and a light property', () => {
|
||||
expect(themes).toHaveProperty('light');
|
||||
expect(themes).toHaveProperty('dark');
|
||||
});
|
||||
});
|
||||
9
packages/app/tests/ts/scripts/dom.test.ts
Executable file
9
packages/app/tests/ts/scripts/dom.test.ts
Executable file
@@ -0,0 +1,9 @@
|
||||
import { createDomAnchor } from '../../../src/ts/scripts/dom';
|
||||
|
||||
describe('Testing DOM scripts', () => {
|
||||
const ANCHOR_ID = 'anchorId';
|
||||
test('createDomAnchor - creates the first body element with an id', () => {
|
||||
createDomAnchor(ANCHOR_ID);
|
||||
expect(document.body.children[0].id).toBe(ANCHOR_ID);
|
||||
});
|
||||
});
|
||||
60
packages/app/tsconfig.json
Executable file
60
packages/app/tsconfig.json
Executable file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
|
||||
"module": "es2016", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
"lib": ["es2016", "dom"], /* Specify library files to be included in the compilation. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
"jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
// "outDir": "./", /* Redirect output structure to the directory. */
|
||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
"removeComments": true, /* Do not emit comments to output. */
|
||||
"noEmit": true, /* Do not emit outputs. */
|
||||
"importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
"downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
"strictNullChecks": true, /* Enable strict null checks. */
|
||||
"strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
"strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
"strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
"noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
"alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
"noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
"noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
"noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
}
|
||||
}
|
||||
18
packages/app/tslint.json
Executable file
18
packages/app/tslint.json
Executable file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"defaultSeverity": "error",
|
||||
"extends": [ "tslint:recommended" ],
|
||||
"jsRules": {},
|
||||
"rules": {
|
||||
"arrow-parens": false,
|
||||
"indent": [ true, "tabs", 4 ],
|
||||
"interface-name": false,
|
||||
"jsx-wrap-multiline": false,
|
||||
"max-line-length": [true, {"limit": 120, "ignore-pattern": "^import |^export {(.*?)}|class [a-zA-Z]+ implements |//"}],
|
||||
"member-access": [ true, "no-public" ],
|
||||
"no-empty": [ true, "allow-empty-functions" ],
|
||||
"object-literal-sort-keys": false,
|
||||
"quotemark": [ true, "single", "jsx-double" ],
|
||||
"trailing-comma": [ true, { "multiline": "ignore", "singleline": "never" }]
|
||||
},
|
||||
"rulesDirectory": []
|
||||
}
|
||||
30
packages/app/utils/consoleColors.js
Executable file
30
packages/app/utils/consoleColors.js
Executable file
@@ -0,0 +1,30 @@
|
||||
const consoleColors = {
|
||||
reset: '\x1b[0m',
|
||||
bold: '\x1b[1m',
|
||||
dim: '\x1b[2m',
|
||||
underscore: '\x1b[4m',
|
||||
blink: '\x1b[5m',
|
||||
reverse: '\x1b[7m',
|
||||
hidden: '\x1b[8m',
|
||||
|
||||
black: '\x1b[30m',
|
||||
red: '\x1b[31m',
|
||||
green: '\x1b[32m',
|
||||
yellow: '\x1b[33m',
|
||||
blue: '\x1b[34m',
|
||||
magenta: '\x1b[35m',
|
||||
cyan: '\x1b[36m',
|
||||
white: '\x1b[37m',
|
||||
gray: '\x1b[90m',
|
||||
|
||||
bgBlack: '\x1b[40m',
|
||||
bgRed: '\x1b[41m',
|
||||
bgGreen: '\x1b[42m',
|
||||
bgYellow: '\x1b[43m',
|
||||
bgBlue: '\x1b[44m',
|
||||
bgMagenta: '\x1b[45m',
|
||||
bgCyan: '\x1b[46m',
|
||||
bgWhite: '\x9B[47m',
|
||||
};
|
||||
|
||||
module.exports = consoleColors;
|
||||
58
packages/app/utils/locateContentScripts.js
Executable file
58
packages/app/utils/locateContentScripts.js
Executable file
@@ -0,0 +1,58 @@
|
||||
const path = require('path');
|
||||
const { readdirSync, lstatSync } = require('fs');
|
||||
const { red, yellow, reset, bold, blink, dim} = require('./consoleColors');
|
||||
|
||||
const isDirectory = (source) => {
|
||||
return lstatSync(source).isDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* findContentEntryFile - Will return the index file in a path. Supports files ending with js, ts and tsx.
|
||||
* Throws error if more than one index file is present in the folder with the supported extensions.
|
||||
* returns undefined if no file exists.
|
||||
* @param contentPath - String representaion of the content path.
|
||||
* @returns - The index file name if exists in the given path.
|
||||
*/
|
||||
const findContentEntryFile = (contentPath) => {
|
||||
const files = readdirSync(contentPath).filter((name) => /index.(js|ts|tsx)/.test(name));
|
||||
if (!files || files.length < 1) {
|
||||
console.log(`${yellow}Could not find any index files in path:${reset}\n${contentPath}\n`);
|
||||
return undefined;
|
||||
}
|
||||
else if (files.length == 1) {
|
||||
return files.pop();
|
||||
}
|
||||
else {
|
||||
throw `${red}Found ${files.length} index files, ${files}, in path:${reset}\n${contentPath}\nOnly one should be set.\n`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getDirectories - scans a folder and returns a list directories within.
|
||||
* If a directory was found,
|
||||
* an object containing the full path and folder name will be returned in the list.
|
||||
* @param rootPath - String representaion of the root path.
|
||||
* @returns - A list of objects containing path and folder name
|
||||
*/
|
||||
const getDirectories = (rootPath) => {
|
||||
return readdirSync(rootPath)
|
||||
.map(name => {
|
||||
return {
|
||||
path: path.join(rootPath, name),
|
||||
folderName: name
|
||||
}
|
||||
})
|
||||
.filter((dir) => isDirectory(dir.path));
|
||||
}
|
||||
|
||||
const locateContentScripts = (rootPath) => {
|
||||
const entries = {};
|
||||
const directories = getDirectories(rootPath);
|
||||
directories.forEach((dir) => {
|
||||
const entryFile = findContentEntryFile(dir.path);
|
||||
if (entryFile) { entries[dir.folderName] = path.join(dir.path, entryFile) }
|
||||
})
|
||||
return entries;
|
||||
}
|
||||
|
||||
module.exports = locateContentScripts;
|
||||
88
packages/app/webpack.config.js
Executable file
88
packages/app/webpack.config.js
Executable file
@@ -0,0 +1,88 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const CleanWebpackPlugin = require('clean-webpack-plugin');
|
||||
const { CheckerPlugin } = require('awesome-typescript-loader');
|
||||
const ChromeExtensionReloader = require('webpack-chrome-extension-reloader');
|
||||
const locateContentScripts = require('./utils/locateContentScripts');
|
||||
|
||||
const sourceRootPath = path.join(__dirname, 'src');
|
||||
const contentScriptsPath = path.join(sourceRootPath, 'ts', 'contentScripts');
|
||||
const distRootPath = path.join(__dirname, 'dist');
|
||||
const nodeEnv = process.env.NODE_ENV ? process.env.NODE_ENV : 'development';
|
||||
const webBrowser = process.env.WEB_BROWSER ? process.env.WEB_BROWSER : 'chrome';
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
background: path.join(sourceRootPath, 'ts', 'background', 'index.ts'),
|
||||
options: path.join(sourceRootPath, 'ts', 'options', 'index.tsx'),
|
||||
popup: path.join(sourceRootPath, 'ts', 'popup', 'index.tsx'),
|
||||
...locateContentScripts(contentScriptsPath)
|
||||
},
|
||||
output: {
|
||||
path: distRootPath,
|
||||
filename: '[name].js',
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.ts', '.tsx', '.json'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{ test: /\.(js|ts|tsx)?$/, loader: "awesome-typescript-loader", exclude: /node_modules/ },
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new CheckerPlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.join(sourceRootPath, 'html', 'options.html'),
|
||||
inject: 'body',
|
||||
filename: 'options.html',
|
||||
title: 'Web Extension Starter - Options Page',
|
||||
chunks: ['options'],
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.join(sourceRootPath, 'html', 'popup.html'),
|
||||
inject: 'body',
|
||||
filename: 'popup.html',
|
||||
title: 'Web Extension Starter - Popup Page',
|
||||
chunks: ['popup'],
|
||||
}),
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: path.join(sourceRootPath, 'assets'),
|
||||
to: path.join(distRootPath, 'assets'),
|
||||
test: /\.(jpg|jpeg|png|gif|svg)?$/,
|
||||
},
|
||||
{
|
||||
from: path.join(sourceRootPath, 'manifest.json'),
|
||||
to: path.join(distRootPath, 'manifest.json'),
|
||||
toType: 'file',
|
||||
}
|
||||
]),
|
||||
new webpack.DefinePlugin({
|
||||
'NODE_ENV': JSON.stringify(nodeEnv),
|
||||
'WEB_BROWSER': JSON.stringify(webBrowser),
|
||||
}),
|
||||
],
|
||||
}
|
||||
|
||||
if (nodeEnv === 'watch') {
|
||||
module.exports.watch = true;
|
||||
module.exports.plugins.push(
|
||||
new ChromeExtensionReloader({
|
||||
port: 9128,
|
||||
reloadPage: true,
|
||||
entries: {
|
||||
background: 'background',
|
||||
options: 'options',
|
||||
popup: 'popup',
|
||||
contentScript: ['counter'],
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (nodeEnv === 'production') {
|
||||
module.exports.plugins.push(new CleanWebpackPlugin(distRootPath, { verbose: true, dry: false }));
|
||||
}
|
||||
5968
packages/app/yarn.lock
Normal file
5968
packages/app/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user