Merge pull request #1 from abhijithvijayan/react-typescript
Just sync with original Repo
@ -1,27 +1,12 @@
|
|||||||
{
|
{
|
||||||
"extends":["onepass"],
|
"extends": [
|
||||||
|
"@abhijithvijayan/eslint-config/typescript",
|
||||||
|
"@abhijithvijayan/eslint-config/react"
|
||||||
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-console": 0,
|
"no-console": "off",
|
||||||
"no-extend-native": 0,
|
"no-extend-native": "off",
|
||||||
"react/jsx-filename-extension": [1, { "extensions": [".jsx", "tsx"] }],
|
"react/jsx-props-no-spreading": "off",
|
||||||
"react/jsx-props-no-spreading": 0,
|
"jsx-a11y/label-has-associated-control": "off"
|
||||||
"jsx-a11y/label-has-associated-control": 0,
|
}
|
||||||
"prettier/prettier": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"trailingComma": "es5",
|
|
||||||
"singleQuote": true,
|
|
||||||
"printWidth": 120,
|
|
||||||
"tabWidth": 4
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"settings": {
|
|
||||||
"import/resolver": {
|
|
||||||
"node": {
|
|
||||||
"extensions": [".js", ".jsx", ".ts", ".tsx"],
|
|
||||||
"moduleDirectory": ["node_modules", "src/"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
147315
.yarn/releases/yarn-1.21.1.js
vendored
@ -1 +0,0 @@
|
|||||||
yarnPath: .yarn/releases/yarn-1.21.1.js
|
|
||||||
72
README.md
@ -1,6 +1,21 @@
|
|||||||
<h1 align="center">🚀 web-extension-starter</h1>
|
<h1 align="center">🚀 web-extension-starter</h1>
|
||||||
<h3 align="center">TypeScript + React Version</h3>
|
<h3 align="center">TypeScript + React Version</h3>
|
||||||
<p align="center">Web Extension starter to build "Write Once Run on Any Browser" extension</p>
|
<p align="center">Web Extension starter to build "Write Once Run on Any Browser" extension</p>
|
||||||
|
<div align="center">
|
||||||
|
<a href="https://travis-ci.com/abhijithvijayan/web-extension-starter">
|
||||||
|
<img src="https://travis-ci.com/abhijithvijayan/web-extension-starter.svg?branch=react-typescript" alt="Travis Build" />
|
||||||
|
</a>
|
||||||
|
</a>
|
||||||
|
<a href="https://david-dm.org/abhijithvijayan/web-extension-starter">
|
||||||
|
<img src="https://img.shields.io/david/abhijithvijayan/web-extension-starter.svg?colorB=orange" alt="DEPENDENCIES" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/abhijithvijayan/web-extension-starter/blob/master/LICENSE">
|
||||||
|
<img src="https://img.shields.io/github/license/abhijithvijayan/web-extension-starter.svg" alt="LICENSE" />
|
||||||
|
</a>
|
||||||
|
<a href="https://twitter.com/intent/tweet?text=Check%20out%20web-extension-starter%21%20by%20%40_abhijithv%0A%0AWeb%20Extension%20starter%20to%20build%20%22Write%20Once%20Run%20on%20Any%20Browser%22%20extension.%20https%3A%2F%2Fgithub.com%2Fabhijithvijayan%2Fweb-extension-starter%0A%0A%23javascript%20%23react%20%23typescript%20%23sass%20%23webextension%20%23chrome%20%23firefox%20%23opera">
|
||||||
|
<img src="https://img.shields.io/twitter/url/http/shields.io.svg?style=social" alt="TWEET" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
<h3 align="center">🙋♂️ Made by <a href="https://twitter.com/_abhijithv">@abhijithvijayan</a></h3>
|
<h3 align="center">🙋♂️ Made by <a href="https://twitter.com/_abhijithv">@abhijithvijayan</a></h3>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Donate:
|
Donate:
|
||||||
@ -14,6 +29,8 @@
|
|||||||
</p>
|
</p>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
❤️ it? ⭐️ it on [GitHub](https://github.com/abhijithvijayan/web-extension-starter) or [Tweet](https://twitter.com/intent/tweet?text=Check%20out%20web-extension-starter%21%20by%20%40_abhijithv%0A%0AWeb%20Extension%20starter%20to%20build%20%22Write%20Once%20Run%20on%20Any%20Browser%22%20extension.%20https%3A%2F%2Fgithub.com%2Fabhijithvijayan%2Fweb-extension-starter%0A%0A%23javascript%20%23react%20%23typescript%20%23sass%20%23webextension%20%23chrome%20%23firefox%20%23opera) about it.
|
||||||
|
|
||||||
👶🏼 Looking for [Non React/TypeScript Version](https://github.com/abhijithvijayan/web-extension-starter/tree/master) instead?
|
👶🏼 Looking for [Non React/TypeScript Version](https://github.com/abhijithvijayan/web-extension-starter/tree/master) instead?
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
@ -41,17 +58,20 @@
|
|||||||
## Use this template
|
## Use this template
|
||||||
|
|
||||||
Create a new directory and run
|
Create a new directory and run
|
||||||
|
|
||||||
```
|
```
|
||||||
curl -fsSL https://github.com/abhijithvijayan/web-extension-starter/archive/react-typescript.tar.gz | tar -xz --strip-components=1
|
curl -fsSL https://github.com/abhijithvijayan/web-extension-starter/archive/react-typescript.tar.gz | tar -xz --strip-components=1
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🚀 Quick Start
|
## 🚀 Quick Start
|
||||||
|
|
||||||
Ensure you have
|
Ensure you have
|
||||||
|
|
||||||
- [Node.js](https://nodejs.org) 10 or later installed
|
- [Node.js](https://nodejs.org) 10 or later installed
|
||||||
- [Yarn](https://yarnpkg.com) v1 or v2 installed
|
- [Yarn](https://yarnpkg.com) v1 or v2 installed
|
||||||
|
|
||||||
Then run the following:
|
Then run the following:
|
||||||
|
|
||||||
- `yarn install` to install dependencies.
|
- `yarn install` to install dependencies.
|
||||||
- `yarn run dev:chrome` to start the development server for chrome extension
|
- `yarn run dev:chrome` to start the development server for chrome extension
|
||||||
- `yarn run dev:firefox` to start the development server for firefox addon
|
- `yarn run dev:firefox` to start the development server for firefox addon
|
||||||
@ -75,25 +95,34 @@ Then run the following:
|
|||||||
|
|
||||||
- **Load extension in browser**
|
- **Load extension in browser**
|
||||||
|
|
||||||
- ### Chrome
|
- ### Chrome
|
||||||
|
|
||||||
- Go to the browser address bar and type `chrome://extensions`
|
- Go to the browser address bar and type `chrome://extensions`
|
||||||
- Check the `Developer Mode` button to enable it.
|
- Check the `Developer Mode` button to enable it.
|
||||||
- Click on the `Load Unpacked Extension…` button.
|
- Click on the `Load Unpacked Extension…` button.
|
||||||
- Select your extension’s extracted directory.
|
- Select your extension’s extracted directory.
|
||||||
|
|
||||||
- ### Firefox
|
- ### Firefox
|
||||||
|
|
||||||
- Load the Add-on via `about:debugging` as temporary Add-on.
|
- Load the Add-on via `about:debugging` as temporary Add-on.
|
||||||
- Choose the `manifest.json` file in the extracted directory
|
- Choose the `manifest.json` file in the extracted directory
|
||||||
|
|
||||||
- ### Opera
|
- ### Opera
|
||||||
|
|
||||||
|
- Load the extension via `opera:extensions`
|
||||||
|
- Check the `Developer Mode` and load as unpacked from extension’s extracted directory.
|
||||||
|
|
||||||
|
### Production
|
||||||
|
|
||||||
|
- `yarn run build` builds the extension for all the browsers to `extension/BROWSER` directory respectively.
|
||||||
|
|
||||||
|
Note: By default the `manifest.json` is set with version `0.0.0`. The webpack loader will update the version in the build with that of the `package.json` version. In order to release a new version, update version in `package.json` and run script.
|
||||||
|
|
||||||
|
If you don't want to use `package.json` version, you can disable the option [here](https://github.com/abhijithvijayan/web-extension-starter/blob/e10158c4a49948dea9fdca06592876d9ca04e028/webpack.config.js#L79).
|
||||||
|
|
||||||
- Load the extension via `opera:extensions`
|
|
||||||
- Check the `Developer Mode` and load as unpacked from extension’s extracted directory.
|
|
||||||
|
|
||||||
### Generating browser specific manifest.json
|
### Generating browser specific manifest.json
|
||||||
Update `src/manifest/index.js` file with browser vendor prefixed manifest keys
|
|
||||||
|
Update `source/manifest.json` file with browser vendor prefixed manifest keys
|
||||||
|
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
@ -130,16 +159,17 @@ if the vendor is `chrome` or `opera`, this compiles to:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
See the original [README](https://github.com/abhijithvijayan/wext-manifest) of wext-manifest package for more details
|
See the original [README](https://github.com/abhijithvijayan/wext-manifest-loader) of `wext-manifest-loader` package for more details
|
||||||
|
|
||||||
### Production
|
## Bugs
|
||||||
|
|
||||||
- `yarn run build` builds the extension for all the browsers to `extension/BROWSER` directory respectively.
|
Please file an issue [here](https://github.com/abhijithvijayan/web-extension-starter/issues/new) for bugs, missing documentation, or unexpected behavior.
|
||||||
|
|
||||||
## Show your support
|
### Linting & TypeScript Config
|
||||||
|
|
||||||
Give a ⭐️ if this project helped you!
|
- Shared Eslint & Prettier Configuration - [`@abhijithvijayan/eslint-config`](https://www.npmjs.com/package/@abhijithvijayan/eslint-config)
|
||||||
|
- Shared TypeScript Configuration - [`@abhijithvijayan/tsconfig`](https://www.npmjs.com/package/@abhijithvijayan/tsconfig)
|
||||||
|
|
||||||
## Licence
|
## License
|
||||||
|
|
||||||
Code released under the [MIT License](LICENSE).
|
MIT © [Abhijith Vijayan](https://abhijithvijayan.in)
|
||||||
|
|||||||
66
package.json
@ -18,63 +18,65 @@
|
|||||||
"build:firefox": "cross-env NODE_ENV=production cross-env TARGET_BROWSER=firefox webpack",
|
"build:firefox": "cross-env NODE_ENV=production cross-env TARGET_BROWSER=firefox webpack",
|
||||||
"build:opera": "cross-env NODE_ENV=production cross-env TARGET_BROWSER=opera webpack",
|
"build:opera": "cross-env NODE_ENV=production cross-env TARGET_BROWSER=opera webpack",
|
||||||
"build": "yarn run build:chrome && yarn run build:firefox && yarn run build:opera",
|
"build": "yarn run build:chrome && yarn run build:firefox && yarn run build:opera",
|
||||||
"lint": "eslint . --ext .ts",
|
"lint": "eslint . --ext .ts,.tsx",
|
||||||
"lint:fix": "eslint . --ext .ts --fix"
|
"lint:fix": "eslint . --ext .ts,.tsx --fix"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.9.2",
|
"@babel/runtime": "^7.9.6",
|
||||||
|
"advanced-css-reset": "^1.1.1",
|
||||||
|
"emoji-log": "^1.0.2",
|
||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
"webext-base-css": "^1.0.0",
|
"webext-base-css": "^1.1.0",
|
||||||
"webextension-polyfill-ts": "^0.14.0"
|
"webextension-polyfill-ts": "^0.15.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.9.0",
|
"@abhijithvijayan/eslint-config": "^1.4.0",
|
||||||
|
"@abhijithvijayan/tsconfig": "^1.1.2",
|
||||||
|
"@babel/core": "^7.9.6",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||||
"@babel/plugin-proposal-object-rest-spread": "^7.9.0",
|
"@babel/plugin-proposal-object-rest-spread": "^7.9.6",
|
||||||
"@babel/plugin-transform-destructuring": "^7.8.8",
|
"@babel/plugin-transform-destructuring": "^7.9.5",
|
||||||
"@babel/plugin-transform-runtime": "^7.9.0",
|
"@babel/plugin-transform-runtime": "^7.9.6",
|
||||||
"@babel/preset-env": "^7.9.0",
|
"@babel/preset-env": "^7.9.6",
|
||||||
"@babel/preset-react": "^7.9.4",
|
"@babel/preset-react": "^7.9.4",
|
||||||
"@babel/preset-typescript": "^7.9.0",
|
"@babel/preset-typescript": "^7.9.0",
|
||||||
"@types/react": "^16.9.27",
|
"@types/react": "^16.9.35",
|
||||||
"@types/react-dom": "^16.9.5",
|
"@types/react-dom": "^16.9.8",
|
||||||
"@types/webpack": "^4.41.9",
|
"@types/webpack": "^4.41.13",
|
||||||
"@typescript-eslint/eslint-plugin": "^2.26.0",
|
"@typescript-eslint/eslint-plugin": "^2.34.0",
|
||||||
"@typescript-eslint/parser": "^2.26.0",
|
"@typescript-eslint/parser": "^2.34.0",
|
||||||
"autoprefixer": "^9.7.5",
|
"autoprefixer": "^9.8.0",
|
||||||
"babel-eslint": "10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"babel-loader": "^8.1.0",
|
"babel-loader": "^8.1.0",
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
"copy-webpack-plugin": "^5.1.1",
|
"copy-webpack-plugin": "^5.1.1",
|
||||||
"cross-env": "^6.0.3",
|
"cross-env": "^6.0.3",
|
||||||
"css-loader": "^3.4.2",
|
"css-loader": "^3.5.3",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^6.8.0",
|
||||||
"eslint-config-airbnb": "^18.1.0",
|
"eslint-config-airbnb": "^18.1.0",
|
||||||
"eslint-config-onepass": "2.2.0",
|
"eslint-config-prettier": "^6.11.0",
|
||||||
"eslint-config-prettier": "^6.10.1",
|
|
||||||
"eslint-plugin-html": "^6.0.0",
|
|
||||||
"eslint-plugin-import": "^2.20.2",
|
"eslint-plugin-import": "^2.20.2",
|
||||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||||
"eslint-plugin-prettier": "^3.1.2",
|
"eslint-plugin-prettier": "^3.1.3",
|
||||||
"eslint-plugin-react": "^7.19.0",
|
"eslint-plugin-react": "^7.20.0",
|
||||||
"eslint-plugin-react-hooks": "^3.0.0",
|
"eslint-plugin-react-hooks": "^2.5.1",
|
||||||
"fork-ts-checker-webpack-plugin": "^4.1.2",
|
"fork-ts-checker-webpack-plugin": "^4.1.3",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
"mini-css-extract-plugin": "^0.9.0",
|
"mini-css-extract-plugin": "^0.9.0",
|
||||||
"node-sass": "^4.13.1",
|
"node-sass": "^4.14.1",
|
||||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
||||||
"postcss-loader": "^3.0.0",
|
"postcss-loader": "^3.0.0",
|
||||||
"prettier": "^2.0.2",
|
"prettier": "^2.0.5",
|
||||||
"resolve-url-loader": "^3.1.1",
|
"resolve-url-loader": "^3.1.1",
|
||||||
"sass-loader": "^8.0.2",
|
"sass-loader": "^8.0.2",
|
||||||
"terser-webpack-plugin": "^2.3.5",
|
"terser-webpack-plugin": "^2.3.6",
|
||||||
"typescript": "^3.8.3",
|
"typescript": "^3.9.3",
|
||||||
"webpack": "^4.42.1",
|
"webpack": "^4.43.0",
|
||||||
"webpack-cli": "^3.3.11",
|
"webpack-cli": "^3.3.11",
|
||||||
"webpack-extension-reloader": "^1.1.4",
|
"webpack-extension-reloader": "^1.1.4",
|
||||||
"wext-manifest": "^2.2.0",
|
"wext-manifest-loader": "^2.0.0",
|
||||||
"write-webpack-plugin": "^1.1.0",
|
"wext-manifest-webpack-plugin": "^1.1.1",
|
||||||
"zip-webpack-plugin": "^3.0.0"
|
"zip-webpack-plugin": "^3.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
6
source/Background/index.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import 'emoji-log';
|
||||||
|
import {browser} from 'webextension-polyfill-ts';
|
||||||
|
|
||||||
|
browser.runtime.onInstalled.addListener((): void => {
|
||||||
|
console.emoji('🦄', 'extension installed');
|
||||||
|
});
|
||||||
32
source/Options/Options.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import './styles.scss';
|
||||||
|
|
||||||
|
const Options: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<form>
|
||||||
|
<p>
|
||||||
|
<label htmlFor="name">Name</label>
|
||||||
|
<br />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="name"
|
||||||
|
name="name"
|
||||||
|
spellCheck="false"
|
||||||
|
autoComplete="off"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label htmlFor="logging">
|
||||||
|
<input type="checkbox" name="logging" /> Show the features enabled
|
||||||
|
on each page in the console
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Options;
|
||||||
55
source/Popup/Popup.tsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {browser, Tabs} from 'webextension-polyfill-ts';
|
||||||
|
|
||||||
|
import './styles.scss';
|
||||||
|
|
||||||
|
function openWebPage(url: string): Promise<Tabs.Tab> {
|
||||||
|
return browser.tabs.create({url});
|
||||||
|
}
|
||||||
|
|
||||||
|
const Popup: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<section id="popup">
|
||||||
|
<h2>WEB-EXTENSION-STARTER</h2>
|
||||||
|
<button
|
||||||
|
id="options__button"
|
||||||
|
type="button"
|
||||||
|
onClick={(): Promise<Tabs.Tab> => {
|
||||||
|
return openWebPage('options.html');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Options Page
|
||||||
|
</button>
|
||||||
|
<div className="links__holder">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={(): Promise<Tabs.Tab> => {
|
||||||
|
return openWebPage(
|
||||||
|
'https://github.com/abhijithvijayan/web-extension-starter'
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
GitHub
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={(): Promise<Tabs.Tab> => {
|
||||||
|
return openWebPage(
|
||||||
|
'https://www.buymeacoffee.com/abhijithvijayan'
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Buy Me A Coffee
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Popup;
|
||||||
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
75
source/manifest.json
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"manifest_version": 2,
|
||||||
|
"name": "Sample WebExtension",
|
||||||
|
"version": "0.0.0",
|
||||||
|
|
||||||
|
"icons": {
|
||||||
|
"16": "assets/icons/favicon-16.png",
|
||||||
|
"32": "assets/icons/favicon-32.png",
|
||||||
|
"48": "assets/icons/favicon-48.png",
|
||||||
|
"128": "assets/icons/favicon-128.png"
|
||||||
|
},
|
||||||
|
"description": "Sample description",
|
||||||
|
"homepage_url": "https://github.com/abhijithvijayan/web-extension-starter",
|
||||||
|
"short_name": "Sample Name",
|
||||||
|
|
||||||
|
"permissions": [
|
||||||
|
"activeTab",
|
||||||
|
"storage",
|
||||||
|
"http://*/*",
|
||||||
|
"https://*/*"
|
||||||
|
],
|
||||||
|
|
||||||
|
"content_security_policy": "script-src 'self'; object-src 'self'",
|
||||||
|
|
||||||
|
"__chrome|firefox__author": "abhijithvijayan",
|
||||||
|
"__opera__developer": {
|
||||||
|
"name": "abhijithvijayan"
|
||||||
|
},
|
||||||
|
|
||||||
|
"__firefox__applications": {
|
||||||
|
"gecko": {
|
||||||
|
"id": "{754FB1AD-CC3B-4856-B6A0-7786F8CA9D17}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"__chrome__minimum_chrome_version": "49",
|
||||||
|
"__opera__minimum_opera_version": "36",
|
||||||
|
|
||||||
|
"browser_action": {
|
||||||
|
"default_popup": "popup.html",
|
||||||
|
"default_icon": {
|
||||||
|
"16": "assets/icons/favicon-16.png",
|
||||||
|
"32": "assets/icons/favicon-32.png",
|
||||||
|
"48": "assets/icons/favicon-48.png",
|
||||||
|
"128": "assets/icons/favicon-128.png"
|
||||||
|
},
|
||||||
|
"default_title": "tiny title",
|
||||||
|
"__chrome|opera__chrome_style": false,
|
||||||
|
"__firefox__browser_style": false
|
||||||
|
},
|
||||||
|
|
||||||
|
"__chrome|opera__options_page": "options.html",
|
||||||
|
"options_ui": {
|
||||||
|
"page": "options.html",
|
||||||
|
"open_in_tab": true,
|
||||||
|
"__chrome__chrome_style": false
|
||||||
|
},
|
||||||
|
|
||||||
|
"background": {
|
||||||
|
"scripts": [
|
||||||
|
"js/background.bundle.js"
|
||||||
|
],
|
||||||
|
"__chrome|opera__persistent": false
|
||||||
|
},
|
||||||
|
|
||||||
|
"content_scripts": [{
|
||||||
|
"matches": [
|
||||||
|
"http://*/*",
|
||||||
|
"https://*/*"
|
||||||
|
],
|
||||||
|
"js": [
|
||||||
|
"js/contentScript.bundle.js"
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
10
source/styles/_reset.scss
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
@import '~advanced-css-reset/dist/reset.css';
|
||||||
|
|
||||||
|
// Add your custom reset rules here
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
@ -1,5 +0,0 @@
|
|||||||
import { browser } from 'webextension-polyfill-ts';
|
|
||||||
|
|
||||||
browser.runtime.onInstalled.addListener((): void => {
|
|
||||||
console.log('extension installed');
|
|
||||||
});
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
import './styles.scss';
|
|
||||||
|
|
||||||
const Options: React.FC = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<form>
|
|
||||||
<p>
|
|
||||||
<label htmlFor="name">Name</label>
|
|
||||||
<br />
|
|
||||||
<input type="text" id="name" name="name" spellCheck="false" autoComplete="off" required />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label htmlFor="logging">
|
|
||||||
<input type="checkbox" name="logging" /> Show the features enabled on each page in the console
|
|
||||||
</label>
|
|
||||||
</p>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Options;
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { browser, Tabs } from 'webextension-polyfill-ts';
|
|
||||||
|
|
||||||
import './styles.scss';
|
|
||||||
|
|
||||||
function openWebPage(url: string): Promise<Tabs.Tab> {
|
|
||||||
return browser.tabs.create({ url });
|
|
||||||
}
|
|
||||||
|
|
||||||
const Popup: React.FC = () => {
|
|
||||||
return (
|
|
||||||
<section id="popup">
|
|
||||||
<h2>WEB-EXTENSION-STARTER</h2>
|
|
||||||
<button
|
|
||||||
id="options__button"
|
|
||||||
type="button"
|
|
||||||
onClick={(): Promise<Tabs.Tab> => {
|
|
||||||
return openWebPage('options.html');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Options Page
|
|
||||||
</button>
|
|
||||||
<div className="links__holder">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={(): Promise<Tabs.Tab> => {
|
|
||||||
return openWebPage('https://github.com/abhijithvijayan/web-extension-starter');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
GitHub
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={(): Promise<Tabs.Tab> => {
|
|
||||||
return openWebPage('https://www.buymeacoffee.com/abhijithvijayan');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Buy Me A Coffee
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Popup;
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
const pkg = require('../../package.json');
|
|
||||||
|
|
||||||
const manifestInput = {
|
|
||||||
manifest_version: 2,
|
|
||||||
name: 'Sample WebExtension',
|
|
||||||
version: pkg.version,
|
|
||||||
|
|
||||||
icons: {
|
|
||||||
'16': 'assets/icons/favicon-16.png',
|
|
||||||
'32': 'assets/icons/favicon-32.png',
|
|
||||||
'48': 'assets/icons/favicon-48.png',
|
|
||||||
'128': 'assets/icons/favicon-128.png',
|
|
||||||
},
|
|
||||||
|
|
||||||
description: 'Sample description',
|
|
||||||
homepage_url: 'https://github.com/abhijithvijayan/web-extension-starter',
|
|
||||||
short_name: 'Sample Name',
|
|
||||||
|
|
||||||
permissions: ['activeTab', 'storage', 'http://*/*', 'https://*/*'],
|
|
||||||
content_security_policy: "script-src 'self' 'unsafe-eval'; object-src 'self'",
|
|
||||||
|
|
||||||
'__chrome|firefox__author': 'abhijithvijayan',
|
|
||||||
__opera__developer: {
|
|
||||||
name: 'abhijithvijayan',
|
|
||||||
},
|
|
||||||
|
|
||||||
__firefox__applications: {
|
|
||||||
gecko: { id: '{754FB1AD-CC3B-4856-B6A0-7786F8CA9D17}' },
|
|
||||||
},
|
|
||||||
|
|
||||||
__chrome__minimum_chrome_version: '49',
|
|
||||||
__opera__minimum_opera_version: '36',
|
|
||||||
|
|
||||||
browser_action: {
|
|
||||||
default_popup: 'popup.html',
|
|
||||||
default_icon: {
|
|
||||||
'16': 'assets/icons/favicon-16.png',
|
|
||||||
'32': 'assets/icons/favicon-32.png',
|
|
||||||
'48': 'assets/icons/favicon-48.png',
|
|
||||||
'128': 'assets/icons/favicon-128.png',
|
|
||||||
},
|
|
||||||
default_title: 'tiny title',
|
|
||||||
'__chrome|opera__chrome_style': false,
|
|
||||||
__firefox__browser_style: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
'__chrome|opera__options_page': 'options.html',
|
|
||||||
|
|
||||||
options_ui: {
|
|
||||||
page: 'options.html',
|
|
||||||
open_in_tab: true,
|
|
||||||
__chrome__chrome_style: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
background: {
|
|
||||||
scripts: ['js/background.bundle.js'],
|
|
||||||
'__chrome|opera__persistent': false,
|
|
||||||
},
|
|
||||||
|
|
||||||
content_scripts: [
|
|
||||||
{
|
|
||||||
matches: ['http://*/*', 'https://*/*'],
|
|
||||||
js: ['js/contentScript.bundle.js'],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = manifestInput;
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
// Forked from Normalize.css, Reboot.css, Sanitize.css, and Untouched.css
|
|
||||||
|
|
||||||
*,
|
|
||||||
*:before,
|
|
||||||
*:after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
*:focus {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol,
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:link {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
@ -1,48 +1,21 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"extends": "@abhijithvijayan/tsconfig",
|
||||||
"outDir": "dist",
|
"compilerOptions": {
|
||||||
/* for manifest/index.js */
|
"target": "es5", // ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'.
|
||||||
"allowJs": true,
|
"module": "esnext", // Module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.
|
||||||
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
|
|
||||||
"module": "esnext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
|
||||||
"jsx": "react",
|
|
||||||
"lib": [
|
"lib": [
|
||||||
"dom",
|
"dom",
|
||||||
"dom.iterable",
|
"dom.iterable",
|
||||||
"esnext"
|
"esnext"
|
||||||
],
|
],
|
||||||
"removeComments": true, /* Do not emit comments to output. */
|
"declaration": false,
|
||||||
"noEmit": true, /* Do not emit outputs. */
|
"isolatedModules": true,
|
||||||
"noEmitOnError": true,
|
|
||||||
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
|
|
||||||
/* Strict Type-Checking Options */
|
|
||||||
"strict": true,
|
|
||||||
"noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
|
||||||
|
|
||||||
/* Additional Checks */
|
/* Additional Checks */
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"noUnusedParameters": true, /* Report errors on unused parameters. */
|
|
||||||
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
},
|
||||||
/* Module Resolution Options */
|
"include": [
|
||||||
"moduleResolution": "node",
|
"source",
|
||||||
"resolveJsonModule": true,
|
"webpack.config.ts"
|
||||||
"declaration": true,
|
|
||||||
"pretty": true,
|
|
||||||
"newLine": "lf",
|
|
||||||
"stripInternal": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"src/**/*", "src/manifest/index.js"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -1,167 +1,191 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
const wextManifest = require('wext-manifest');
|
|
||||||
const ZipPlugin = require('zip-webpack-plugin');
|
const ZipPlugin = require('zip-webpack-plugin');
|
||||||
const TerserPlugin = require('terser-webpack-plugin');
|
const TerserPlugin = require('terser-webpack-plugin');
|
||||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
const WriteWebpackPlugin = require('write-webpack-plugin');
|
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
|
||||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
|
||||||
const ExtensionReloader = require('webpack-extension-reloader');
|
const ExtensionReloader = require('webpack-extension-reloader');
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
|
const WextManifestWebpackPlugin = require('wext-manifest-webpack-plugin');
|
||||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||||
|
|
||||||
const manifestInput = require('./src/manifest');
|
|
||||||
|
|
||||||
const viewsPath = path.join(__dirname, 'views');
|
const viewsPath = path.join(__dirname, 'views');
|
||||||
const sourcePath = path.join(__dirname, 'src');
|
const sourcePath = path.join(__dirname, 'source');
|
||||||
const destPath = path.join(__dirname, 'extension');
|
const destPath = path.join(__dirname, 'extension');
|
||||||
const nodeEnv = process.env.NODE_ENV || 'development';
|
const nodeEnv = process.env.NODE_ENV || 'development';
|
||||||
const targetBrowser = process.env.TARGET_BROWSER;
|
const targetBrowser = process.env.TARGET_BROWSER;
|
||||||
const manifest = wextManifest[targetBrowser](manifestInput);
|
|
||||||
|
|
||||||
const extensionReloaderPlugin =
|
const extensionReloaderPlugin =
|
||||||
nodeEnv === 'development'
|
nodeEnv === 'development'
|
||||||
? new ExtensionReloader({
|
? new ExtensionReloader({
|
||||||
port: 9090,
|
port: 9090,
|
||||||
reloadPage: true,
|
reloadPage: true,
|
||||||
entries: {
|
entries: {
|
||||||
// TODO: reload manifest on update
|
// TODO: reload manifest on update
|
||||||
contentScript: 'contentScript',
|
contentScript: 'contentScript',
|
||||||
background: 'background',
|
background: 'background',
|
||||||
extensionPage: ['popup', 'options'],
|
extensionPage: ['popup', 'options'],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
: () => {
|
: () => {
|
||||||
this.apply = () => {};
|
this.apply = () => {};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getExtensionFileType = browser => {
|
const getExtensionFileType = (browser) => {
|
||||||
if (browser === 'opera') {
|
if (browser === 'opera') {
|
||||||
return 'crx';
|
return 'crx';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (browser === 'firefox') {
|
if (browser === 'firefox') {
|
||||||
return 'xpi';
|
return 'xpi';
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'zip';
|
return 'zip';
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
mode: nodeEnv,
|
devtool: false, // https://github.com/webpack/webpack/issues/1194#issuecomment-560382342
|
||||||
|
|
||||||
entry: {
|
stats: {
|
||||||
background: path.join(sourcePath, 'Background', 'index.ts'),
|
all: false,
|
||||||
contentScript: path.join(sourcePath, 'ContentScript', 'index.ts'),
|
builtAt: true,
|
||||||
popup: path.join(sourcePath, 'Popup', 'index.tsx'),
|
errors: true,
|
||||||
options: path.join(sourcePath, 'Options', 'index.tsx'),
|
hash: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
mode: nodeEnv,
|
||||||
|
|
||||||
|
entry: {
|
||||||
|
manifest: path.join(sourcePath, 'manifest.json'),
|
||||||
|
background: path.join(sourcePath, 'Background', 'index.ts'),
|
||||||
|
contentScript: path.join(sourcePath, 'ContentScript', 'index.ts'),
|
||||||
|
popup: path.join(sourcePath, 'Popup', 'index.tsx'),
|
||||||
|
options: path.join(sourcePath, 'Options', 'index.tsx'),
|
||||||
|
},
|
||||||
|
|
||||||
|
output: {
|
||||||
|
path: path.join(destPath, targetBrowser),
|
||||||
|
filename: 'js/[name].bundle.js',
|
||||||
|
},
|
||||||
|
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.ts', '.tsx', '.js', '.json'],
|
||||||
|
alias: {
|
||||||
|
'webextension-polyfill-ts': path.resolve(
|
||||||
|
path.join(__dirname, 'node_modules', 'webextension-polyfill-ts')
|
||||||
|
),
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
|
||||||
output: {
|
module: {
|
||||||
filename: 'js/[name].bundle.js',
|
rules: [
|
||||||
path: path.join(destPath, targetBrowser),
|
{
|
||||||
},
|
type: 'javascript/auto', // prevent webpack handling json with its own loaders,
|
||||||
|
test: /manifest\.json$/,
|
||||||
resolve: {
|
use: {
|
||||||
extensions: ['.ts', '.tsx', '.js', '.json'],
|
loader: 'wext-manifest-loader',
|
||||||
alias: {
|
options: {
|
||||||
'webextension-polyfill-ts': path.resolve(path.join(__dirname, 'node_modules', 'webextension-polyfill-ts')),
|
usePackageJSONVersion: true, // set to false to not use package.json version for manifest
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
exclude: /node_modules/,
|
||||||
|
},
|
||||||
module: {
|
{
|
||||||
rules: [
|
test: /\.(js|ts)x?$/,
|
||||||
{
|
loader: 'babel-loader',
|
||||||
test: /\.(js|ts)x?$/,
|
exclude: /node_modules/,
|
||||||
loader: 'babel-loader',
|
},
|
||||||
exclude: /node_modules/,
|
{
|
||||||
|
test: /\.(sa|sc|c)ss$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: MiniCssExtractPlugin.loader, // It creates a CSS file per JS file which contains CSS
|
||||||
|
},
|
||||||
|
{
|
||||||
|
loader: 'css-loader', // Takes the CSS files and returns the CSS with imports and url(...) for Webpack
|
||||||
|
options: {
|
||||||
|
sourceMap: true,
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
test: /\.(sa|sc|c)ss$/,
|
{
|
||||||
use: [
|
loader: 'postcss-loader', // For autoprefixer
|
||||||
{
|
options: {
|
||||||
loader: MiniCssExtractPlugin.loader, // It creates a CSS file per JS file which contains CSS
|
ident: 'postcss',
|
||||||
},
|
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
|
||||||
{
|
plugins: [require('autoprefixer')()],
|
||||||
loader: 'css-loader', // Takes the CSS files and returns the CSS with imports and url(...) for Webpack
|
|
||||||
options: {
|
|
||||||
sourceMap: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
loader: 'postcss-loader', // For autoprefixer
|
|
||||||
options: {
|
|
||||||
ident: 'postcss',
|
|
||||||
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
|
|
||||||
plugins: [require('autoprefixer')()],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'resolve-url-loader', // Rewrites relative paths in url() statements
|
|
||||||
'sass-loader', // Takes the Sass/SCSS file and compiles to the CSS
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
'resolve-url-loader', // Rewrites relative paths in url() statements
|
||||||
|
'sass-loader', // Takes the Sass/SCSS file and compiles to the CSS
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [
|
|
||||||
new ForkTsCheckerWebpackPlugin(),
|
|
||||||
// environmental variables
|
|
||||||
new webpack.EnvironmentPlugin(['NODE_ENV', 'TARGET_BROWSER']),
|
|
||||||
// delete previous build files
|
|
||||||
new CleanWebpackPlugin({
|
|
||||||
cleanOnceBeforeBuildPatterns: [
|
|
||||||
path.join(process.cwd(), `extension/${targetBrowser}`),
|
|
||||||
path.join(process.cwd(), `extension/${targetBrowser}.${getExtensionFileType(targetBrowser)}`),
|
|
||||||
],
|
|
||||||
cleanStaleWebpackAssets: false,
|
|
||||||
verbose: true,
|
|
||||||
}),
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
template: path.join(viewsPath, 'popup.html'),
|
|
||||||
inject: 'body',
|
|
||||||
chunks: ['popup'],
|
|
||||||
filename: 'popup.html',
|
|
||||||
}),
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
template: path.join(viewsPath, 'options.html'),
|
|
||||||
inject: 'body',
|
|
||||||
chunks: ['options'],
|
|
||||||
filename: 'options.html',
|
|
||||||
}),
|
|
||||||
// write css file(s) to build folder
|
|
||||||
new MiniCssExtractPlugin({ filename: 'css/[name].css' }),
|
|
||||||
// copy static assets
|
|
||||||
new CopyWebpackPlugin([{ from: 'src/assets', to: 'assets' }]),
|
|
||||||
// write manifest.json
|
|
||||||
new WriteWebpackPlugin([{ name: manifest.name, data: Buffer.from(manifest.content) }]),
|
|
||||||
// plugin to enable browser reloading in development mode
|
|
||||||
extensionReloaderPlugin,
|
|
||||||
],
|
],
|
||||||
|
},
|
||||||
|
|
||||||
optimization: {
|
plugins: [
|
||||||
minimizer: [
|
// Plugin to not generate js bundle for manifest entry
|
||||||
new TerserPlugin({
|
new WextManifestWebpackPlugin(),
|
||||||
cache: true,
|
// Generate sourcemaps
|
||||||
parallel: true,
|
new webpack.SourceMapDevToolPlugin({filename: false}),
|
||||||
terserOptions: {
|
new ForkTsCheckerWebpackPlugin(),
|
||||||
output: {
|
// environmental variables
|
||||||
comments: false,
|
new webpack.EnvironmentPlugin(['NODE_ENV', 'TARGET_BROWSER']),
|
||||||
},
|
// delete previous build files
|
||||||
},
|
new CleanWebpackPlugin({
|
||||||
extractComments: false,
|
cleanOnceBeforeBuildPatterns: [
|
||||||
}),
|
path.join(process.cwd(), `extension/${targetBrowser}`),
|
||||||
new OptimizeCSSAssetsPlugin({
|
path.join(
|
||||||
cssProcessorPluginOptions: {
|
process.cwd(),
|
||||||
preset: ['default', { discardComments: { removeAll: true } }],
|
`extension/${targetBrowser}.${getExtensionFileType(targetBrowser)}`
|
||||||
},
|
),
|
||||||
}),
|
],
|
||||||
new ZipPlugin({
|
cleanStaleWebpackAssets: false,
|
||||||
path: destPath,
|
verbose: true,
|
||||||
extension: `${getExtensionFileType(targetBrowser)}`,
|
}),
|
||||||
filename: `${targetBrowser}`,
|
new HtmlWebpackPlugin({
|
||||||
}),
|
template: path.join(viewsPath, 'popup.html'),
|
||||||
],
|
inject: 'body',
|
||||||
},
|
chunks: ['popup'],
|
||||||
|
filename: 'popup.html',
|
||||||
|
}),
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: path.join(viewsPath, 'options.html'),
|
||||||
|
inject: 'body',
|
||||||
|
chunks: ['options'],
|
||||||
|
filename: 'options.html',
|
||||||
|
}),
|
||||||
|
// write css file(s) to build folder
|
||||||
|
new MiniCssExtractPlugin({filename: 'css/[name].css'}),
|
||||||
|
// copy static assets
|
||||||
|
new CopyWebpackPlugin([{from: 'source/assets', to: 'assets'}]),
|
||||||
|
// plugin to enable browser reloading in development mode
|
||||||
|
extensionReloaderPlugin,
|
||||||
|
],
|
||||||
|
|
||||||
|
optimization: {
|
||||||
|
minimizer: [
|
||||||
|
new TerserPlugin({
|
||||||
|
cache: true,
|
||||||
|
parallel: true,
|
||||||
|
terserOptions: {
|
||||||
|
output: {
|
||||||
|
comments: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extractComments: false,
|
||||||
|
}),
|
||||||
|
new OptimizeCSSAssetsPlugin({
|
||||||
|
cssProcessorPluginOptions: {
|
||||||
|
preset: ['default', {discardComments: {removeAll: true}}],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new ZipPlugin({
|
||||||
|
path: destPath,
|
||||||
|
extension: `${getExtensionFileType(targetBrowser)}`,
|
||||||
|
filename: `${targetBrowser}`,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||