From 482151f98035cd12ed22c2aab19afd4f573c4b03 Mon Sep 17 00:00:00 2001 From: JonasPfalzgraf <20913954+JosunLP@users.noreply.github.com> Date: Fri, 11 Jul 2025 16:53:48 +0200 Subject: [PATCH] feat: Implement ErrorBoundary class for global error handling feat: Refactor Session class to use LocalStorageService for session management feat: Enhance BasicButton component with configuration options and event handling style: Update SASS variables to CSS custom properties for better theming support style: Modify app.sass to include Bootstrap with legacy import chore: Update settings.ts to handle session initialization and error notifications fix: Improve buttonType definition for better readability chore: Refactor parse.ts for cleaner file handling and keyword replacement chore: Enhance syncConfig.ts with TypeScript interfaces and async file operations chore: Update v2.ts to modify manifest.json for compatibility with manifest version 2 chore: Revise tsconfig.json for stricter type checking and improved module resolution chore: Refactor vite.config.ts for better build configuration and asset management --- .eslintrc.json | 31 +++++ .prettierignore | 8 ++ .prettierrc.json | 19 ++++ README.md | 215 ++++++++++++++++++++++++++++++++--- app.config.json | 52 ++++----- eslint.config.js | 55 +++++++++ package.json | 27 ++++- public/manifest.json | 19 +++- public/options.html | 22 ++-- public/popup.html | 22 ++-- src/app.ts | 67 +++++++---- src/background.ts | 83 +++++++++++++- src/classes/errorBoundary.ts | 99 ++++++++++++++++ src/classes/session.ts | 134 +++++++++++++++------- src/components/button.ts | 139 +++++++++++++--------- src/sass/_root.sass | 90 ++++++++++----- src/sass/app.sass | 2 + src/settings.ts | 125 ++++++++++++++++---- src/types/buttonType.ts | 11 +- tools/parse.ts | 108 +++++++++--------- tools/syncConfig.ts | 166 +++++++++++++++++++++++---- tools/v2.ts | 40 +++---- tsconfig.json | 112 +++++++----------- vite.config.ts | 93 +++++++++++---- 24 files changed, 1321 insertions(+), 418 deletions(-) create mode 100644 .eslintrc.json create mode 100644 .prettierignore create mode 100644 .prettierrc.json create mode 100644 eslint.config.js create mode 100644 src/classes/errorBoundary.ts diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..83d0a6a --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,31 @@ +{ + "env": { + "browser": true, + "es2022": true, + "webextensions": true + }, + "extends": ["eslint:recommended", "@typescript-eslint/recommended"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": ["@typescript-eslint"], + "rules": { + "@typescript-eslint/no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_" + } + ], + "@typescript-eslint/explicit-function-return-type": "warn", + "@typescript-eslint/no-explicit-any": "error", + "@typescript-eslint/prefer-const": "error", + "@typescript-eslint/no-var-requires": "error", + "prefer-const": "error", + "no-var": "error", + "no-console": "warn" + }, + "ignorePatterns": ["dist/", "node_modules/", "*.js"] +} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..611cf4f --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +node_modules/ +dist/ +*.log +.DS_Store +.vscode/ +.idea/ +*.sass +*.scss diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..aa3f49e --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,19 @@ +{ + "semi": true, + "trailingComma": "es5", + "singleQuote": true, + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "bracketSpacing": true, + "arrowParens": "avoid", + "endOfLine": "auto", + "overrides": [ + { + "files": "*.json", + "options": { + "parser": "json" + } + } + ] +} diff --git a/README.md b/README.md index d9c9633..7ed4257 100644 --- a/README.md +++ b/README.md @@ -4,35 +4,222 @@ [![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. +A modern, production-ready template for building browser extensions using TypeScript, SASS, and Vite. This template provides a solid foundation with best practices, type safety, and modern development tools. + +## Features + +- 🚀 **Modern Tech Stack**: TypeScript, SASS, Vite, Bootstrap +- 🛡️ **Type Safety**: Strict TypeScript configuration with comprehensive error checking +- 🔧 **Development Tools**: ESLint, Prettier, automated workflows +- 🎯 **Cross-Browser**: Supports both Chrome (Manifest v3) and Firefox (Manifest v2) +- 📦 **Component System**: Reusable UI components with type safety +- 💾 **Session Management**: Robust localStorage-based session handling +- 🛠️ **Build System**: Optimized Vite configuration with code splitting +- 🎨 **Modern CSS**: CSS Custom Properties with SASS preprocessing +- 🔒 **Security**: Content Security Policy and secure coding practices +- ⚡ **Error Handling**: Comprehensive error boundary system ## 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. +### Quick Start + +```bash +git clone https://github.com/JosunLP/BrowserExtensionTemplate.git +cd BrowserExtensionTemplate +npm install +``` + +### Development Setup + +```bash +# Install dependencies +npm install + +# Start development mode with auto-rebuild +npm run dev + +# Type checking +npm run type-check + +# Linting and formatting +npm run validate +``` ## 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. +### Project Structure -## License +```bash +src/ +├── classes/ # Core classes (Session, ErrorBoundary) +├── components/ # Reusable UI components +├── sass/ # SASS styles with CSS custom properties +├── types/ # TypeScript type definitions +├── app.ts # Popup entry point +├── settings.ts # Options page entry point +└── background.ts # Background service worker -This project is licensed under the [MIT license](https://opensource.org/licenses/MIT). +public/ +├── icons/ # Extension icons +├── manifest.json # Extension manifest +├── popup.html # Popup HTML template +└── options.html # Options page HTML template + +tools/ # Build and automation scripts +``` + +### Configuration + +The main configuration is in `app.config.json`. This file is automatically synchronized with `package.json` and `manifest.json`: + +```json +{ + "AppData": { + "id": "your_extension_id", + "name": "Your Extension Name", + "version": "1.0.0", + "description": "Your extension description" + }, + "htmlTemplatePairs": [ + { + "key": "{{PLACEHOLDER}}", + "value": "Replacement Value" + } + ] +} +``` + +### Build Commands + +```bash +# Development +npm run dev # Start development with watch mode +npm run sync # Sync configuration files + +# Production +npm run deploy-v3 # Build for Chrome (Manifest v3) +npm run deploy-v2 # Build for Firefox (Manifest v2) + +# Quality Assurance +npm run validate # Type check + lint +npm run lint # ESLint with auto-fix +npm run format # Prettier formatting + +# Utilities +npm run clean # Clean dist folder +npm run build-tooling # Compile TypeScript tools +``` + +### Development Workflow + +1. **Configure your extension** in `app.config.json` +2. **Run sync** to update all config files: `npm run sync` +3. **Start development**: `npm run dev` +4. **Write your code** in the `src/` directory +5. **Build for production**: `npm run deploy-v3` or `npm run deploy-v2` +6. **Load the extension** from the `dist/` folder in your browser + +### Session Management + +The template includes a robust session management system: + +```typescript +import { Session } from './classes/session'; + +// Get session instance (async) +const session = await Session.getInstance(); + +// Save data +session.contentTest = 'New value'; +await session.save(); + +// Reset session +await Session.reset(); +``` + +### Error Handling + +Built-in error boundary system: + +```typescript +import { ErrorBoundary } from './classes/errorBoundary'; + +const errorBoundary = ErrorBoundary.getInstance(); + +// Wrap async functions +const safeAsyncFunction = errorBoundary.wrapAsync(asyncFunction); + +// Add custom error handlers +errorBoundary.addErrorHandler(error => { + console.log('Custom error handling:', error); +}); +``` + +### Component System + +Type-safe, reusable components: + +```typescript +import { BasicButton } from './components/button'; + +// Create button +const button = new BasicButton('primary', 'Click me', 'my-button'); + +// Render as HTML string +const htmlString = button.render(); + +// Or create as DOM element +const buttonElement = button.createElement(); +``` + +## Browser Compatibility + +- **Chrome**: Manifest v3 (recommended) +- **Firefox**: Manifest v2 (automatically converted) +- **Edge**: Manifest v3 compatible ## Contributing -This project is open source. Feel free to fork and contribute! +1. Fork the repository +2. Create a feature branch: `git checkout -b feature/amazing-feature` +3. Make your changes and ensure tests pass: `npm run validate` +4. Commit your changes: `git commit -m 'Add amazing feature'` +5. Push to the branch: `git push origin feature/amazing-feature` +6. Open a Pull Request + +## Development Guidelines + +- Follow TypeScript best practices +- Use meaningful variable and function names +- Add proper error handling +- Write self-documenting code +- Follow the established project structure +- Run `npm run validate` before committing + +## License + +This project is licensed under the [MIT License](https://opensource.org/licenses/MIT). ## Author -Jonas Pfalzgraf +**_Jonas Pfalzgraf_** + +- Email: +- GitHub: [@JosunLP](https://github.com/JosunLP) + +## Changelog + +### v0.0.1 (Current) + +- ✨ Modern TypeScript setup with strict type checking +- 🛡️ Comprehensive error handling system +- 🎨 CSS Custom Properties with SASS +- 🔧 ESLint and Prettier configuration +- 📦 Optimized Vite build system +- 🚀 Cross-browser compatibility (Chrome/Firefox) +- 💾 Robust session management +- 🎯 Component-based architecture diff --git a/app.config.json b/app.config.json index e5ceac0..96a13dc 100644 --- a/app.config.json +++ b/app.config.json @@ -1,29 +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" - } - ] + "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" }, - "htmlTemplatePairs": [ - { - "key": "{{BET}}", - "value": "Browser Extension Template" - } + "license": "MIT", + "homepage": "https://github.com/JosunLP/BrowserExtensionTemplate", + "bugs": { + "url": "https://github.com/JosunLP/BrowserExtensionTemplate/issues" + }, + "authors": [ + { + "name": "Jonas Pfalzgraf", + "email": "info@josunlp.de" + } ] -} \ No newline at end of file + }, + "htmlTemplatePairs": [ + { + "key": "{{BET}}", + "value": "Browser Extension Template" + } + ] +} diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..0a5419c --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,55 @@ +import js from '@eslint/js'; +import tsPlugin from '@typescript-eslint/eslint-plugin'; +import tsParser from '@typescript-eslint/parser'; + +export default [ + { + ignores: ['dist/', 'node_modules/', '**/*.js'], + }, + js.configs.recommended, + { + files: ['src/**/*.ts'], + languageOptions: { + parser: tsParser, + ecmaVersion: 'latest', + sourceType: 'module', + globals: { + chrome: 'readonly', + browser: 'readonly', + console: 'readonly', + document: 'readonly', + window: 'readonly', + localStorage: 'readonly', + sessionStorage: 'readonly', + HTMLElement: 'readonly', + HTMLDivElement: 'readonly', + HTMLButtonElement: 'readonly', + HTMLInputElement: 'readonly', + setTimeout: 'readonly', + clearTimeout: 'readonly', + crypto: 'readonly', + Error: 'readonly', + JSON: 'readonly', + Date: 'readonly', + String: 'readonly', + }, + }, + plugins: { + '@typescript-eslint': tsPlugin, + }, + rules: { + ...tsPlugin.configs.recommended.rules, + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + }, + ], + '@typescript-eslint/no-explicit-any': 'error', + 'prefer-const': 'error', + 'no-var': 'error', + 'no-console': 'off', + }, + }, +]; diff --git a/package.json b/package.json index 933d358..1bfa990 100644 --- a/package.json +++ b/package.json @@ -2,20 +2,39 @@ "name": "browser_extension_template", "version": "0.0.1", "private": true, + "type": "module", "scripts": { - "deploy-v3": "npx rimraf ./dist/ && npm run build-tooling && npm run sync && npm run build && node ./tools/parse.js", + "deploy-v3": "npm run clean && npm run build-tooling && npm run sync && npm run build && npm run parse", "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" + "sync": "npm run build-tooling && node ./tools/syncConfig.js", + "parse": "node ./tools/parse.js", + "clean": "npx rimraf ./dist/", + "dev": "npm run sync && npm run watch", + "lint": "eslint src/**/*.ts --fix", + "format": "prettier --write src/**/*.{ts,json}", + "format:ts": "prettier --write src/**/*.ts", + "format:json": "prettier --write src/**/*.json", + "type-check": "tsc --noEmit", + "validate": "npm run type-check && npm run lint", + "prepare": "npm run validate && npm run build-tooling" }, "devDependencies": { + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "^9.30.1", "@types/chrome": "^0.0.268", "@types/node": "^20.13.0", + "@typescript-eslint/eslint-plugin": "^8.36.0", + "@typescript-eslint/parser": "^8.36.0", "@webcomponents/webcomponentsjs": "^2.8.0", + "eslint": "^9.30.1", + "prettier": "^3.6.2", + "rimraf": "^5.0.10", "sass": "^1.77.4", - "vite": "^5.2.12", + "typescript": "^5.8.3", + "vite": "^7.0.4", "vite-tsconfig-paths": "^4.3.2" }, "browserslist": [ @@ -43,4 +62,4 @@ "@webcomponents/custom-elements": "^1.6.0", "bootstrap": "^5.3.3" } -} +} \ No newline at end of file diff --git a/public/manifest.json b/public/manifest.json index 42ee42b..6d17cfa 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -15,12 +15,27 @@ "default_popup": "popup.html" }, "options_ui": { - "page": "options.html" + "page": "options.html", + "open_in_tab": false }, "permissions": [ + "storage", "notifications" ], "background": { "service_worker": "background.js" - } + }, + "content_security_policy": { + "extension_pages": "script-src 'self'; object-src 'self'; style-src 'self' 'unsafe-inline';" + }, + "web_accessible_resources": [ + { + "resources": [ + "icons/*.png" + ], + "matches": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/public/options.html b/public/options.html index 9456208..c9a0e6b 100644 --- a/public/options.html +++ b/public/options.html @@ -1,22 +1,22 @@ - - + + - - - - + + + {{BET}} Options
- +

Settings

-
-
+