Initial commit

This commit is contained in:
Jonas Pfalzgraf 2025-01-17 14:00:37 +01:00 committed by GitHub
commit ac40ec106d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 1651 additions and 0 deletions

35
.editorconfig Normal file
View file

@ -0,0 +1,35 @@
root = true
[*]
indent_style = tab
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.{js,ts,svg,md}]
charset = utf-8
[*.{ts,js}]
indent_style = tab
indent_size = 4
[package.json]
indent_style = space
indent_size = 2
[*.{sass,scss}]
indent_style = space
indent_size = 2
[*.{css,less}]
indent_style = space
indent_size = 2
[*.{json,yml,yaml}]
indent_style = space

71
.github/workflows/codeql-analysis.yml vendored Normal file
View file

@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: ["main"]
pull_request:
# The branches below must be a subset of the branches above
branches: ["main"]
schedule:
- cron: "37 13 * * 4"
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ["javascript"]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

694
.gitignore vendored Normal file
View file

@ -0,0 +1,694 @@
# Created by https://www.toptal.com/developers/gitignore/api/visualstudio,visualstudiocode,webstorm,phpstorm,intellij
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudio,visualstudiocode,webstorm,phpstorm,intellij
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# 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
# AWS User-specific
.idea/**/aws.xml
# 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/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# 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
# SonarLint plugin
.idea/sonarlint/
# 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
# https://plugins.jetbrains.com/plugin/7973-sonarlint
.idea/**/sonarlint/
# SonarQube Plugin
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
.idea/**/sonarIssues.xml
# Markdown Navigator plugin
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
.idea/**/markdown-navigator.xml
.idea/**/markdown-navigator-enh.xml
.idea/**/markdown-navigator/
# Cache file creation bug
# See https://youtrack.jetbrains.com/issue/JBR-2257
.idea/$CACHE_FILE$
# CodeStream plugin
# https://plugins.jetbrains.com/plugin/12206-codestream
.idea/codestream.xml
# Azure Toolkit for IntelliJ plugin
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
.idea/**/azureSettings.xml
### PhpStorm ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
# AWS User-specific
# Generated files
# Sensitive or high-churn files
# Gradle
# 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/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
# Mongo Explorer plugin
# File-based project format
# IntelliJ
# mpeltonen/sbt-idea plugin
# JIRA plugin
# Cursive Clojure plugin
# SonarLint plugin
# Crashlytics plugin (for Android Studio and IntelliJ)
# Editor-based Rest Client
# Android studio 3.1+ serialized cache file
### PhpStorm Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
# https://plugins.jetbrains.com/plugin/7973-sonarlint
# SonarQube Plugin
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
# Markdown Navigator plugin
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
# Cache file creation bug
# See https://youtrack.jetbrains.com/issue/JBR-2257
# CodeStream plugin
# https://plugins.jetbrains.com/plugin/12206-codestream
# Azure Toolkit for IntelliJ plugin
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
.ionide
# Support for Project snippet scope
.vscode/*.code-snippets
# Ignore code-workspaces
*.code-workspace
### WebStorm ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
# AWS User-specific
# Generated files
# Sensitive or high-churn files
# Gradle
# 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/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
# Mongo Explorer plugin
# File-based project format
# IntelliJ
# mpeltonen/sbt-idea plugin
# JIRA plugin
# Cursive Clojure plugin
# SonarLint plugin
# Crashlytics plugin (for Android Studio and IntelliJ)
# Editor-based Rest Client
# Android studio 3.1+ serialized cache file
### WebStorm Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
# https://plugins.jetbrains.com/plugin/7973-sonarlint
# SonarQube Plugin
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
# Markdown Navigator plugin
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
# Cache file creation bug
# See https://youtrack.jetbrains.com/issue/JBR-2257
# CodeStream plugin
# https://plugins.jetbrains.com/plugin/12206-codestream
# Azure Toolkit for IntelliJ plugin
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
### 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/main/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# 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
nunit-*.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/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# 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
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.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
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# 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
# NuGet Symbol Packages
*.snupkg
# 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
*.appxbundle
*.appxupload
# 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/
# 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
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# 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 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
# 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/
# 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/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
# Local History for Visual Studio Code
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
### VisualStudio Patch ###
# Additional files built by Visual Studio
# End of https://www.toptal.com/developers/gitignore/api/visualstudio,visualstudiocode,webstorm,phpstorm,intellij
dist
tools/syncConfig.js
tools/parse.js
tools/v2.js
tools/clean.js
package-lock.json

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Jonas Pfalzgraf
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.

38
README.md Normal file
View file

@ -0,0 +1,38 @@
# BrowserExtensionTemplate
[![GitHub issues](https://img.shields.io/github/issues/JosunLP/BrowserExtensionTemplate?style=for-the-badge)](https://github.com/JosunLP/BrowserExtensionTemplate/issues)
[![GitHub forks](https://img.shields.io/github/forks/JosunLP/BrowserExtensionTemplate?style=for-the-badge)](https://github.com/JosunLP/BrowserExtensionTemplate/network)
[![GitHub stars](https://img.shields.io/github/stars/JosunLP/BrowserExtensionTemplate?style=for-the-badge)](https://github.com/JosunLP/BrowserExtensionTemplate/stargazers)
[![GitHub license](https://img.shields.io/github/license/JosunLP/BrowserExtensionTemplate?style=for-the-badge)](https://github.com/JosunLP/BrowserExtensionTemplate)
[![Twitter URL](https://img.shields.io/twitter/url?logo=twitter&style=for-the-badge&url=https%3A%2F%2Fgithub.com%2FJosunLP%2FBrowserExtensionTemplate)](https://twitter.com/intent/tweet?text=Look+what+i+found+on+GitHub+%23Developer%2C+%23SoftwareDeveloper%3A&url=https%3A%2F%2Fgithub.com%2FJosunLP%2FBrowserExtensionTemplate)
[![CodeFactor](https://www.codefactor.io/repository/github/josunlp/browserextensiontemplate/badge?style=for-the-badge)](https://www.codefactor.io/repository/github/josunlp/browserextensiontemplate)
[![Known Vulnerabilities](https://snyk.io/test/github/JosunLP/BrowserExtensionTemplate/badge.svg?style=for-the-badge)](https://snyk.io/test/github/JosunLP/BrowserExtensionTemplate)
## Description
A basic template based on SASS and TypeScript to create browser extensions without directly relying on a larger framework.
## Installation
You can download the source code from [GitHub](https://github.com/JosunLP/BrowserExtensionTemplate). Just copy it in your project and run `npm install` to install the dependencies.
The basic configuration, wich will sync with `npm run sync` with the `package.json` file and the `manifest.json` file, is in `app.config.json`.
Alternatively, you can fork the project and run `npm install` in the forked project.
## Usage
Your sourcecode can be written in the `src` folder. The `public` folder contains static files like images, html and the manifest.json.
With the `npm run deploy-v3` command you can deploy the extension to the dist folder, ready to be published to the chrome web store.
With the `npm run deploy-v2` command you can deploy the extension to the dist folder, ready to be published to the firefox web store.
This is necessary because the firefox web store needs the `manifest.json` file to be present in the version v2.
## License
This project is licensed under the [MIT license](https://opensource.org/licenses/MIT).
## Contributing
This project is open source. Feel free to fork and contribute!
## Author
Jonas Pfalzgraf

29
app.config.json Normal file
View file

@ -0,0 +1,29 @@
{
"AppData": {
"id": "browser_extension_template",
"name": "Browser Extension Template",
"version": "0.0.1",
"description": "A basic template based on SASS and TypeScript to create browser extensions without directly relying on a larger framework.",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com:JosunLP/BrowserExtensionTemplate.git"
},
"license": "MIT",
"homepage": "https://github.com/JosunLP/BrowserExtensionTemplate",
"bugs": {
"url": "https://github.com/JosunLP/BrowserExtensionTemplate/issues"
},
"authors": [
{
"name": "Jonas Pfalzgraf",
"email": "info@josunlp.de"
}
]
},
"htmlTemplatePairs": [
{
"key": "{{BET}}",
"value": "Browser Extension Template"
}
]
}

46
package.json Normal file
View file

@ -0,0 +1,46 @@
{
"name": "browser_extension_template",
"version": "0.0.1",
"private": true,
"scripts": {
"deploy-v3": "npx rimraf ./dist/ && npm run build-tooling && npm run sync && npm run build && node ./tools/parse.js",
"deploy-v2": "npm run deploy-v3 && node ./tools/v2.js",
"build": "vite build",
"build-tooling": "tsc --project ./tooling.tsconfig.json",
"watch": "vite build --watch",
"sync": "npm run build-tooling && node ./tools/syncConfig.js"
},
"devDependencies": {
"@types/chrome": "^0.0.268",
"@types/node": "^20.13.0",
"@webcomponents/webcomponentsjs": "^2.8.0",
"sass": "^1.77.4",
"vite": "^5.2.12",
"vite-tsconfig-paths": "^4.3.2"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
],
"authors": [
{
"name": "Jonas Pfalzgraf",
"email": "info@josunlp.de"
}
],
"description": "A basic template based on SASS and TypeScript to create browser extensions without directly relying on a larger framework.",
"homepage": "https://github.com/JosunLP/BrowserExtensionTemplate",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com:JosunLP/BrowserExtensionTemplate.git"
},
"bugs": {
"url": "https://github.com/JosunLP/BrowserExtensionTemplate/issues"
},
"dependencies": {
"@webcomponents/custom-elements": "^1.6.0",
"bootstrap": "^5.3.3"
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
public/icons/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

BIN
public/icons/icon128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
public/icons/icon16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

BIN
public/icons/icon48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

26
public/manifest.json Normal file
View file

@ -0,0 +1,26 @@
{
"name": "Browser Extension Template",
"version": "0.0.1",
"manifest_version": 3,
"description": "A basic template based on SASS and TypeScript to create browser extensions without directly relying on a larger framework.",
"homepage_url": "https://github.com/JosunLP/BrowserExtensionTemplate",
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},
"action": {
"default_icon": "icons/icon16.png",
"default_title": "BrowserExtensionTemplate",
"default_popup": "popup.html"
},
"options_ui": {
"page": "options.html"
},
"permissions": [
"notifications"
],
"background": {
"service_worker": "background.js"
}
}

25
public/options.html Normal file
View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="./favicon.ico">
<title>{{BET}} Options</title>
</head>
<body>
<noscript>
<strong>We're sorry but {{BET}} doesn't work properly without JavaScript enabled. Please enable it to
continue.</strong>
</noscript>
<div id="app">
<img src="./icons/icon128.png" class="logo" />
<h1>Settings</h1>
<div id="settings">
</div>
</div>
<footer>
<script type="module" src="./settings.js"></script>
</footer>
</body>
</html>

25
public/popup.html Normal file
View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="./favicon.ico">
<title>{{BET}}</title>
</head>
<body>
<noscript>
<strong>We're sorry but {{BET}} doesn't work properly without JavaScript enabled. Please enable it to
continue.</strong>
</noscript>
<div id="app">
<img src="./icons/icon128.png" class="logo" />
<h1>{{BET}}</h1>
<div id="content">
</div>
</div>
<footer>
<script type="module" src="./app.js"></script>
</footer>
</body>
</html>

31
src/app.ts Normal file
View file

@ -0,0 +1,31 @@
import { Session } from "./classes/session"
import "./sass/app.sass"
class App {
private static contentEntry: string = "content"
constructor() {
this.drawData()
this.main()
}
async main(): Promise<void> {
console.log("Hello World")
}
async drawData(): Promise<void> {
const session = Session.getInstance()
const contentRoot = <HTMLDivElement>document.getElementById(App.contentEntry)
const body = document.createElement("div")
const title = document.createElement("h1")
const text = document.createElement("p")
title.innerText = "Hello World"
text.innerText = session.contentTest
body.appendChild(title)
body.appendChild(text)
contentRoot.appendChild(body)
}
}
new App();

BIN
src/assets/logo.afdesign Normal file

Binary file not shown.

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

9
src/background.ts Normal file
View file

@ -0,0 +1,9 @@
class Background {
constructor() {
this.main();
}
async main(): Promise<void> {}
}
new Background();

55
src/classes/session.ts Normal file
View file

@ -0,0 +1,55 @@
export class Session {
private static instance: Session;
private constructor() {
}
static getInstance() {
if (!Session.instance && !Session.load()) {
Session.instance = new Session();
}
if (!Session.instance && Session.load()) {
Session.instance = <Session>Session.load();
}
Session.save();
return Session.instance;
}
public static save() {
localStorage.setItem('session', JSON.stringify(this.instance));
}
public static load(): Session | null {
const session = localStorage.getItem('session');
if (session) {
const obj = <Session>JSON.parse(session);
const result = new Session();
result.contentTest = obj.contentTest;
return result;
}
return null;
}
public static reloadSession() {
const session = localStorage.getItem('session');
if (session) {
const obj = <Session>JSON.parse(session);
const result = new Session();
result.contentTest = obj.contentTest;
Session.instance = result;
}
}
public static resetSession() {
localStorage.removeItem('session');
sessionStorage.removeItem('session');
this.instance = new Session();
Session.save();
location.reload();
}
public readonly sessionId: string = crypto.randomUUID();
public contentTest: string = 'This is a simple example of a web application';
}

63
src/components/button.ts Normal file
View file

@ -0,0 +1,63 @@
import { customButton } from "../types/buttonType";
export class BasicButton {
private type: customButton;
private text: string;
private id: string | undefined;
private className: string | undefined;
constructor(type: customButton, text: string, id?: string, className?: string) {
this.type = type;
this.text = text;
this.id = id;
this.className = className;
}
public render(): string {
const result = document.createElement('button');
result.type = "button";
result.className = this.type;
result.textContent = this.text;
switch (this.type) {
case "primary":
result.className = "btn btn-primary";
break;
case "success":
result.className = "btn btn-success";
break;
case "danger":
result.className = "btn btn-danger";
break;
case "warning":
result.className = "btn btn-warning";
break;
case "info":
result.className = "btn btn-info";
break;
case "light":
result.className = "btn btn-light";
break;
case "dark":
result.className = "btn btn-dark";
break;
default:
result.className = "btn btn-primary";
break;
}
if (this.id) {
result.id = this.id;
}
if (this.className) {
result.className += ' ' + this.className;
}
return result.outerHTML;
}
}

6
src/sass/_content.sass Normal file
View file

@ -0,0 +1,6 @@
@import mixin
#textbox
text-align: left
padding: 2rem
@include noselect

93
src/sass/_mixin.sass Normal file
View file

@ -0,0 +1,93 @@
@import "root"
@mixin respond-to($media)
@if $media == handhelds
@media only screen and (max-device-width: 40rem)
@content
@else if $media == medium-screens
@media only screen and (min-device-width: 40rem)
@content
@else if $media == wide-screens
@media only screen and (min-width: 1000px)
@content
@mixin partialButton
width: 5rem !important
height: 2rem !important
text-align: center !important
margin: 0.5rem !important
border-color: $seccond-color !important
border-radius: 0.5rem !important
@include respond-to(handhelds)
font-size: 3rem
@include respond-to(medium-screens)
font-size: 1.5rem
@mixin hoverMe
&:hover
button
color: grey !important
@mixin shadow
box-shadow: 0px 0px 30px silver
@mixin noselect
-webkit-touch-callout: none
-webkit-user-select: none
-khtml-user-select: none
-moz-user-select: none
-ms-user-select: none
user-select: none
pointer-events: none
.form-group
margin-left: 2rem
margin-right: 2rem
margin-bottom: 0.5rem
flex-wrap: wrap
justify-content: center
display: flex
@mixin formBasic
display: block
padding: 2rem
background: $background-color-content
border-radius: 0.7rem
min-height: 20rem
margin: auto
margin-top: 2rem
margin-bottom: 2rem
@include shadow
@include respond-to(handhelds)
font-size: 2.5em
margin-left: -0.8em
margin-right: -0.8em
border-radius: 0
@include respond-to(medium-screens)
max-width: 40rem
@include respond-to(wide-screens)
max-width: 40rem
input
@include respond-to(handhelds)
font-size: 3rem
border-radius: 0.5rem
.check
position: static
@include respond-to(handhelds)
width: 2rem !important
height: 2rem !important
button
@include respond-to(handhelds)
font-size: 3rem
padding: 1rem
border-radius: 1rem

26
src/sass/_root.sass Normal file
View file

@ -0,0 +1,26 @@
$main-font: 'Ubuntu', 'Staatliches'
$main-font-color: white
$main-font-color-hover: lightgrey
$main-font-color-focus: lightgrey
$main-font-color-disabled: lightgrey
$main-font-color-active: lightgrey
$main-uschrift-font: 'Ubuntu', Arial
$primary-color: #007bff
$primary-color-hover: #0069d9
$primary-color-focus: #0062cc
$primary-color-disabled: #0069d9
$primary-color-active: #0062cc
$background-color-content-shadow: #0069d9
$seccond-color: #6c757d
$seccondary-color: darkgrey
$seccondary-color-hover: black
$seccondary-color-focus: black
$seccondary-color-disabled: black
$seccondary-color-active: black
$background-color: #77B2FF
$background-color-content: rgb(198, 223, 255)
$background-color-content-hover: rgb(198, 223, 255)
$background-color-content-focus: rgb(198, 223, 255)
$background-color-content-active: rgb(198, 223, 255)
$background-color-content-disabled: rgb(198, 223, 255)
$logo-image: url('../icons/icon128.png')

49
src/sass/app.sass Normal file
View file

@ -0,0 +1,49 @@
@import 'root'
@import 'mixin'
@import 'content'
@import "../../node_modules/bootstrap/scss/bootstrap"
body
height: 30rem
width: 30rem
background-color: $background-color
text-align: center
margin: auto
padding: 1rem
color: $main-font-color
p
font-size: 1rem
font-weight: bold
margin: auto
padding: auto
color: $main-font-color
text-align: center
font-family: 'Roboto', sans-serif
h1, h2
@include noselect
form
@include formBasic
.logo
width: 5rem
height: auto
padding-top: 2rem
@include noselect
svg
@include noselect
table
color: $main-font-color !important
th
@include noselect
a
color: $main-font-color
&:hover
color: $background-color-content

33
src/settings.ts Normal file
View file

@ -0,0 +1,33 @@
import { Session } from "./classes/session";
import { BasicButton } from "./components/button";
import "./sass/app.sass";
class Settings {
private session = Session.getInstance();
constructor() {
this.renderSettings();
}
private async renderSettings(): Promise<void> {
const settings = <HTMLDivElement>document.getElementById('settings');
const saveButton = new BasicButton('success', 'Save', 'saveSettings').render();
settings.innerHTML = `
<div class="form-group">
<label for="contentTest">Content Test</label>
<input type="text" class="form-control text-input" id="contentTest" placeholder="Enter content test" value="${this.session.contentTest}">
</div>
`;
settings.innerHTML += saveButton;
const saveSettings = <HTMLButtonElement>document.getElementById('saveSettings');
saveSettings.addEventListener('click', () => {
this.session.contentTest = (<HTMLInputElement>document.getElementById('contentTest')).value;
Session.save();
Session.reloadSession();
});
}
}
new Settings();

1
src/types/buttonType.ts Normal file
View file

@ -0,0 +1 @@
export type customButton = "neutral" | "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark";

31
tooling.tsconfig.json Normal file
View file

@ -0,0 +1,31 @@
{
"compilerOptions": {
"target": "ESNext",
"lib": [
"ESNext"
],
"module": "ESNext",
"outDir": "./tools/",
"rootDir": "./tools/",
"removeComments": true,
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"types": [
"node",
"chrome"
]
},
"include": [
"./tools/*.ts"
],
"exclude": [
"node_modules",
"./src/*.ts",
"./src/**/*.ts",
"./dist/*.ts",
"./dist/*.js"
]
}

72
tools/parse.ts Normal file
View file

@ -0,0 +1,72 @@
import * as fs from "fs";
import * as path from "path";
const appConfig = JSON.parse(fs.readFileSync("./app.config.json", "utf8"));
const DEPLOY_TARGET = "./dist/";
function findCssFileNames(source: string): string[] {
let files: string[] = [];
const dir = fs.readdirSync(source);
dir.forEach(function (file: string) {
const sourceFile = path.join(source, file);
const stat = fs.lstatSync(sourceFile);
if (stat.isDirectory()) {
files = files.concat(findCssFileNames(sourceFile));
} else {
if (path.extname(sourceFile) == ".css") {
files.push(file);
}
}
});
return files;
}
function findHtmlFilesRecursive(source: string): string[] {
let files: string[] = [];
const dir = fs.readdirSync(source);
dir.forEach(function (file: string) {
const sourceFile = path.join(source, file);
const stat = fs.lstatSync(sourceFile);
if (stat.isDirectory()) {
files = files.concat(findHtmlFilesRecursive(sourceFile));
} else {
if (path.extname(sourceFile) == ".html") {
files.push(sourceFile);
}
}
});
return files;
}
function replaceKeywordsInHtmlFile(file: string) {
let content = fs.readFileSync(file, "utf8");
const pairs: { key: string; value: string }[] = appConfig.htmlTemplatePairs;
pairs.forEach(function (pair: { key: string; value: string }) {
//@ts-ignore
content = content.replaceAll(pair.key, pair.value);
});
file = file.replace("public\\", DEPLOY_TARGET);
fs.writeFileSync(file, content);
}
function buildHtmlFiles(source: string) {
const files = findHtmlFilesRecursive(source);
files.forEach(function (file: string) {
replaceKeywordsInHtmlFile(file);
});
}
findCssFileNames(DEPLOY_TARGET).forEach((file: string) => {
const files = findHtmlFilesRecursive(DEPLOY_TARGET);
files.forEach(function (htmlFile: string) {
let content = fs.readFileSync(htmlFile, "utf8");
content = content.replace(
"</head>",
`<link rel="stylesheet" href="./assets/${file}">\n</head>`
);
fs.writeFileSync(htmlFile, content);
});
});
buildHtmlFiles(DEPLOY_TARGET);
console.log("Parsed Files: ", findHtmlFilesRecursive(DEPLOY_TARGET));

23
tools/syncConfig.ts Normal file
View file

@ -0,0 +1,23 @@
// @ts-ignore
const fs = require('fs');
const appConfig = JSON.parse(fs.readFileSync('./app.config.json', 'utf8'));
const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
const manifestJson = JSON.parse(fs.readFileSync('./public/manifest.json', 'utf8'));
pkg.version = appConfig.AppData.version;
pkg.name = appConfig.AppData.id;
pkg.authors = appConfig.AppData.authors;
pkg.description = appConfig.AppData.description;
pkg.homepage = appConfig.AppData.homepage;
pkg.license = appConfig.AppData.license;
pkg.repository = appConfig.AppData.repository;
pkg.bugs = appConfig.AppData.bugs;
manifestJson.version = appConfig.AppData.version;
manifestJson.name = appConfig.AppData.name;
manifestJson.description = appConfig.AppData.description;
manifestJson.homepage_url = appConfig.AppData.homepage;
fs.writeFileSync('./package.json', JSON.stringify(pkg, null, 2));
fs.writeFileSync('./public/manifest.json', JSON.stringify(manifestJson, null, 2));

46
tools/v2.ts Normal file
View file

@ -0,0 +1,46 @@
// @ts-ignore
const fs = require('fs');
const manifest = JSON.parse(fs.readFileSync('./dist/manifest.json', 'utf8'));
manifest.manifest_version = 2
manifest.background.scripts = []
manifest.background.scripts.push(manifest.background.service_worker)
delete manifest.background.type
delete manifest.background.service_worker
manifest.background.persistent = true
if (manifest.host_permissions) {
manifest.permissions.push(manifest.host_permissions)
}
if (manifest.optional_host_permissions) {
manifest.permissions.push(manifest.optional_host_permissions)
}
delete manifest.host_permissions
delete manifest.optional_host_permissions
let newContentSecurityPolicy = ""
try {
for (const policy of manifest.content_security_policy) {
newContentSecurityPolicy += policy.key + "'" + policy.value + "'" + " "
}
} catch (e) {
newContentSecurityPolicy = "default-src 'self'"
}
manifest.content_security_policy = newContentSecurityPolicy
try {
manifest.web_accessible_resources = manifest.web_accessible_resources.resources
} catch (e) {
manifest.web_accessible_resources = []
}
if (manifest.action) {
manifest.browser_action = manifest.action
}
delete manifest.action
fs.writeFileSync('./dist/manifest.json', JSON.stringify(manifest, null, 2));

75
tsconfig.json Normal file
View file

@ -0,0 +1,75 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "ESNext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */,
"module": "ESNext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
"lib": ["ESNext", "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": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
"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": "./public/js/app.js", /* Concatenate and emit output to single file. */
"outDir": "./dist/js/" /* 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 */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
"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'). */
"moduleResolution": "node",
/* 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. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
/* 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. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* 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. */
/* Advanced Options */
"skipLibCheck": true /* Skip type checking of declaration files. */,
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"include": ["./src/**/*.ts", "./src/*.ts"],
"exclude": ["node_modules", "./tools/*.ts", "./dist/*.ts", "./dist/*.js"],
"types": ["node", "chrome"]
}

28
vite.config.ts Normal file
View file

@ -0,0 +1,28 @@
import { defineConfig } from "vite";
import { resolve } from "path";
import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
build: {
rollupOptions: {
input: {
app: resolve(__dirname, "src/app.ts"),
settings: resolve(__dirname, "src/settings.ts"),
background: resolve(__dirname, "src/background.ts"),
},
output: {
entryFileNames: "[name].js",
dir: resolve(__dirname, "dist"),
},
},
sourcemap: true,
},
plugins: [tsconfigPaths()],
resolve: {
extensions: [".tsx", ".ts", ".scss", ".sass"],
},
esbuild: {
include: /.*\.tsx?$/,
exclude: [/node_modules/, /dist/],
},
});