-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from Gunock/feature/init
Feature/init
- Loading branch information
Showing
30 changed files
with
4,527 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
name: ci | ||
|
||
on: [push] | ||
|
||
permissions: | ||
contents: read | ||
|
||
env: | ||
NODE_VERSION: '20' | ||
|
||
jobs: | ||
ci-ChromeExtension: | ||
name: Chrome extension CI | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Setup Node.js | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: ${{ env.NODE_VERSION }} | ||
cache: 'yarn' | ||
cache-dependency-path: 'yarn.lock' | ||
registry-url: 'https://npm.pkg.github.com' | ||
|
||
- name: Install dependencies | ||
run: yarn install --frozen-lockfile | ||
|
||
- name: Lint the code | ||
run: yarn run lint | ||
|
||
- name: Build the code | ||
run: yarn run build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
node_modules/ | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
.idea/ | ||
dist/ | ||
out/ | ||
*.crx | ||
*.pem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
dist/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"semi": true, | ||
"tabWidth": 2, | ||
"printWidth": 100, | ||
"singleQuote": true, | ||
"jsxSingleQuote": true, | ||
"trailingComma": "none", | ||
"bracketSameLine": false, | ||
"bracketSpacing": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,88 @@ | ||
# chrome-extension-boilerplate-react-vite | ||
<img src="assets/img/icon-128.png" width="64"/> | ||
|
||
# Chrome Extension (MV3) Boilerplate with React 18 and Vite 5 | ||
|
||
[//]: # 'TODO: Publish the template on NPM' | ||
[//]: # '[![npm](https://img.shields.io/npm/v/chrome-extension-boilerplate-react)](https://www.npmjs.com/package/chrome-extension-boilerplate-react)' | ||
[//]: # '[![npm-download](https://img.shields.io/npm/dw/chrome-extension-boilerplate-react)](https://www.npmjs.com/package/chrome-extension-boilerplate-react)' | ||
[//]: # '[![npm](https://img.shields.io/npm/dm/chrome-extension-boilerplate-react)](https://www.npmjs.com/package/chrome-extension-boilerplate-react)' | ||
|
||
This repository contains a boilerplate for building Chrome Extensions with React 18, TypeScript, and Vite 5. | ||
This boilerplate is inspired by and adapted | ||
from [chrome-extension-boilerplate-react](https://github.com/lxieyang/chrome-extension-boilerplate-react). | ||
|
||
## Features | ||
|
||
This is a basic Chrome Extensions boilerplate to help you write modular and modern Javascript code and load CSS easily. | ||
This boilerplate is updated with: | ||
|
||
- [Chrome Extension Manifest V3](https://developer.chrome.com/docs/extensions/mv3/intro/mv3-overview/) | ||
- [React 18](https://reactjs.org) | ||
- [MUI](https://mui.com/) | ||
- ESLint: | ||
- [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) | ||
- [eslint-config-prettier](https://www.npmjs.com/package/eslint-config-prettier) | ||
- [eslint-plugin-simple-import-sort](https://www.npmjs.com/package/eslint-plugin-simple-import-sort) | ||
- [typescript-eslint](https://www.npmjs.com/package/typescript-eslint) | ||
- [Prettier](https://prettier.io/) | ||
- [TypeScript](https://www.typescriptlang.org/) | ||
|
||
I have avoided using CRXJS Vite Plugin on purpose as it's last update was in 2022, and it could possibly have some | ||
issues with newer versions of Vite. | ||
|
||
Please open up an issue to nudge me to keep the npm packages up-to-date. | ||
|
||
## Installing and Running | ||
|
||
### Procedures: | ||
|
||
1. Check if your [Node.js](https://nodejs.org/) version is >= **18**. | ||
2. Clone this repository. | ||
3. Change the package's `name`, `description`, and `repository` fields in `package.json`. | ||
4. Change the name of your extension on `src/manifest.json`. | ||
5. Run `yarn install` to install the dependencies. | ||
6. Run `yarn dist` | ||
7. Load your extension on Chrome following: | ||
1. Access `chrome://extensions/` | ||
2. Turn the `Developer mode` switch on (top right corner) | ||
3. Click on `Load unpacked` | ||
4. Select the `dist` folder. | ||
8. Happy hacking. | ||
|
||
## Structure | ||
|
||
All your extension's code must be placed in the `src` folder. | ||
|
||
The boilerplate is already prepared to have a popup, a background script, and a content script. | ||
This example Chrome extension implements logic which lets the user scrape the page title. | ||
It was done so to demonstrate some of the [chrome API](https://developer.chrome.com/docs/extensions/reference/api) | ||
functionality. | ||
|
||
## TypeScript | ||
|
||
This boilerplate supports TypeScript! Everything that can be written in TypeScript is written in TypeScript. | ||
|
||
## Change Watchers | ||
|
||
This boilerplate has watch scripts for the popup (`yarn watch:popup`), background script (`yarn watch:background`), and | ||
content script (`yarn watch:content`). | ||
`yarn dist` has to be run first to copy assets, `manifest.json` and Chrome extension files to the `dist` folder. | ||
|
||
## Packing | ||
|
||
After the development of your extension run the command | ||
|
||
``` | ||
$ yarn dist | ||
``` | ||
|
||
Now, the content of `dist` folder will be the extension ready to be submitted to the Chrome Web Store. Just take a look | ||
at the [official guide](https://developer.chrome.com/webstore/publish) to more infos about publishing. | ||
|
||
## Resources: | ||
|
||
- [Chrome Extension documentation](https://developer.chrome.com/extensions/getstarted) | ||
|
||
--- | ||
|
||
Tomasz Kiljańczyk | [Website](https://github.com/Gunock) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// @ts-check | ||
|
||
import eslint from '@eslint/js'; | ||
import eslintConfigPrettier from 'eslint-config-prettier'; | ||
import reactJsxRuntime from 'eslint-plugin-react/configs/jsx-runtime.js'; | ||
import reactRecommended from 'eslint-plugin-react/configs/recommended.js'; | ||
import simpleImportSort from 'eslint-plugin-simple-import-sort'; | ||
import tseslint from 'typescript-eslint'; | ||
|
||
export default tseslint.config( | ||
{ | ||
ignores: ['dist'] | ||
}, | ||
eslint.configs.recommended, | ||
...tseslint.configs.recommended, | ||
reactRecommended, | ||
reactJsxRuntime, | ||
eslintConfigPrettier, | ||
{ | ||
plugins: { | ||
'simple-import-sort': simpleImportSort | ||
}, | ||
rules: { | ||
'simple-import-sort/imports': 'warn', | ||
'simple-import-sort/exports': 'warn' | ||
} | ||
} | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<!doctype html> | ||
|
||
<!-- Chrome Extension language is not determined by language set in HTML tag --> | ||
<!--suppress HtmlRequiredLangAttribute --> | ||
<html> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<meta http-equiv="X-UA-Compatible" content="ie=edge" /> | ||
<title>Chrome Extension React</title> | ||
|
||
<link rel="stylesheet" href="src/popup/styles/index.css" /> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script type="module" src="src/popup/index.tsx"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"manifest_version": 3, | ||
"name": "Chrome Extension with React & Vite", | ||
"version": "1.0.0", | ||
"description": "A chrome extension boilerplate built with React 18 and Vite 5", | ||
"icons": { | ||
"34": "assets/icons/icon-34.png", | ||
"128": "assets/icons/icon-128.png" | ||
}, | ||
"action": { | ||
"default_title": "Chrome Extension React", | ||
"default_popup": "popup/index.html", | ||
"default_icon": "assets/icons/icon-34.png" | ||
}, | ||
"content_scripts": [ | ||
{ | ||
"js": ["content/index.js"], | ||
"matches": ["*://*/*"] | ||
} | ||
], | ||
"background": { | ||
"service_worker": "background/index.js" | ||
}, | ||
"web_accessible_resources": [ | ||
{ | ||
"resources": ["assets/icons/*.png"], | ||
"matches": [], | ||
"extension_ids": [] | ||
} | ||
], | ||
"permissions": ["storage", "tabs", "activeTab"], | ||
"host_permissions": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
{ | ||
"name": "chrome-extension-boilerplate-react-vite", | ||
"version": "1.0.0", | ||
"description": "A chrome extension boilerplate built with React 18 and Vite 5", | ||
"license": "MIT", | ||
"type": "module", | ||
"scripts": { | ||
"lint": "eslint .", | ||
"lint:fix": "eslint . --fix", | ||
"format": "prettier --write .", | ||
"watch": "yarn dist && yarn watch:popup", | ||
"watch:background": "vite --config vite.config.background.ts build --watch", | ||
"watch:content": "vite --config vite.config.content.ts build --watch", | ||
"watch:popup": "vite --config vite.config.popup.ts build --watch", | ||
"build": "yarn build:background && yarn build:content && yarn build:popup", | ||
"build:background": "vite --config vite.config.background.ts build", | ||
"build:content": "vite --config vite.config.content.ts build", | ||
"build:popup": "vite --config vite.config.popup.ts build", | ||
"clean": "rimraf dist", | ||
"copy:static": "copyfiles manifest.json assets/**/* dist", | ||
"dist:dev": "yarn lint && yarn dist", | ||
"dist": "yarn clean && yarn build && yarn copy:static" | ||
}, | ||
"dependencies": { | ||
"@emotion/react": "^11.11.4", | ||
"@emotion/styled": "^11.11.0", | ||
"@fontsource/roboto": "^5.0.12", | ||
"@mui/icons-material": "^5.15.14", | ||
"@mui/material": "^5.15.14", | ||
"@mui/system": "^5.15.14", | ||
"axios": "^1.6.8", | ||
"react": "^18.2.0", | ||
"react-dom": "^18.2.0", | ||
"react-router-dom": "^6.22.3" | ||
}, | ||
"devDependencies": { | ||
"@eslint/js": "^8.57.0", | ||
"@types/react": "^18.2.69", | ||
"@types/react-dom": "^18.2.22", | ||
"@typescript-eslint/eslint-plugin": "^7.3.1", | ||
"@typescript-eslint/parser": "^7.3.1", | ||
"@vitejs/plugin-react": "^4.2.1", | ||
"chrome-types": "^0.1.274", | ||
"copyfiles": "^2.4.1", | ||
"eslint": "^8.57.0", | ||
"eslint-config-prettier": "^9.1.0", | ||
"eslint-plugin-react": "^7.34.1", | ||
"eslint-plugin-simple-import-sort": "^12.0.0", | ||
"prettier": "^3.2.5", | ||
"rimraf": "^5.0.5", | ||
"typescript": "5.4.3", | ||
"typescript-eslint": "^7.3.1", | ||
"vite": "^5.2.6" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
chrome.runtime.onInstalled.addListener(() => { | ||
chrome.storage.local.clear(); | ||
}); | ||
|
||
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { | ||
// TODO: Here you can add logic such as e.g. disable popup button on specific pages | ||
console.debug('tabId', tabId, 'changeInfo', changeInfo, 'tab', tab); | ||
}); | ||
|
||
export {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
export enum ChromeMessageType { | ||
SCRAPER_COMMAND, | ||
SCRAPING_RESULTS | ||
} | ||
|
||
export class ChromeMessage<T> { | ||
readonly type: ChromeMessageType; | ||
readonly payload: T; | ||
|
||
constructor(type: ChromeMessageType, payload: T) { | ||
this.type = type; | ||
this.payload = payload; | ||
} | ||
} | ||
|
||
export class ChromeApiWrapper { | ||
public static async sendTabMessage<T>(message: ChromeMessage<T>): Promise<void> { | ||
const currentTab = await this.getCurrentTab(); | ||
if (currentTab == null) { | ||
throw new Error('Could not find current tab'); | ||
} | ||
|
||
await chrome.tabs.sendMessage(currentTab.id ?? 0, message); | ||
} | ||
|
||
public static async getCurrentTab(): Promise<chrome.tabs.Tab | null> { | ||
const dateStarted = Date.now(); | ||
|
||
// Prevents code from failing when used too soon | ||
while (Date.now() - dateStarted < 5000) { | ||
const tabs = await chrome.tabs.query({active: true, lastFocusedWindow: true}); | ||
|
||
const currentTab = tabs[0]; | ||
if (currentTab?.status === 'complete') { | ||
return currentTab; | ||
} | ||
|
||
await new Promise((r) => setTimeout(r, 50)); | ||
} | ||
|
||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export enum ScraperCommand { | ||
SCRAPE | ||
} | ||
|
||
export interface ScraperMessage { | ||
command: ScraperCommand; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import {ChromeMessage, ChromeMessageType} from '../common/chrome-api-wrapper'; | ||
import {ScraperCommand, ScraperMessage} from '../common/types/scraper'; | ||
|
||
async function handleScrapeCommand() { | ||
const pageTitle = document.title; | ||
const message = new ChromeMessage(ChromeMessageType.SCRAPING_RESULTS, pageTitle); | ||
await chrome.runtime.sendMessage(chrome.runtime.id, message); | ||
} | ||
|
||
chrome.runtime.onMessage.addListener((message: ChromeMessage<ScraperMessage>) => { | ||
console.debug('Received message', message); | ||
if (message.type !== ChromeMessageType.SCRAPER_COMMAND) { | ||
return false; | ||
} | ||
|
||
if (message.payload.command === ScraperCommand.SCRAPE) { | ||
handleScrapeCommand().catch((error) => console.error(error)); | ||
} | ||
|
||
return false; | ||
}); | ||
|
||
console.debug('Chrome plugin content script loaded'); | ||
|
||
export {}; |
Oops, something went wrong.