From 5191a9f87edce296fb19c57eac825addd198ea03 Mon Sep 17 00:00:00 2001 From: sun-yryr Date: Sat, 6 Dec 2025 00:35:21 +0900 Subject: [PATCH 1/2] feat: webpack generate manifest.json for each browsers --- .gitignore | 1 + manifest.json => manifest.template.json | 3 +- package.json | 7 ++- scripts/transform-manifest.js | 64 +++++++++++++++++++++++++ webpack.config.js | 11 ++++- 5 files changed, 83 insertions(+), 3 deletions(-) rename manifest.json => manifest.template.json (83%) create mode 100644 scripts/transform-manifest.js diff --git a/.gitignore b/.gitignore index d4b284b0..e9d3bcf9 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ # production /dist +/dist-* # misc .DS_Store diff --git a/manifest.json b/manifest.template.json similarity index 83% rename from manifest.json rename to manifest.template.json index 478d57c7..32459694 100644 --- a/manifest.json +++ b/manifest.template.json @@ -6,7 +6,8 @@ "permissions": ["alarms", "notifications", "storage"], "optional_permissions": ["tabs"], "background": { - "service_worker": "background.js", + "__chrome__service_worker": "background.js", + "__firefox__scripts": ["background.js"], "type": "module" }, "action": { diff --git a/package.json b/package.json index 8447e423..06a87170 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,12 @@ "scripts": { "start": "webpack serve", "watch": "tsc --noEmit --watch", - "build": "rm -rf dist; webpack --mode production", + "build:chrome-mv3": "rm -rf dist-chrome-mv3; BROWSER=chrome webpack --mode production", + "build:firefox-mv3": "rm -rf dist-firefox-mv3; BROWSER=firefox webpack --mode production", + "build:all": "npm run build:chrome-mv3 && npm run build:firefox-mv3", + "zip:chrome-mv3": "cd dist-chrome-mv3 && zip -r ../dist-chrome-mv3.zip .", + "zip:firefox-mv3": "cd dist-firefox-mv3 && zip -r ../dist-firefox-mv3.zip .", + "zip:all": "npm run zip:chrome-mv3 && npm run zip:firefox-mv3", "test": "jest", "lint:check": "eslint \"src/**/*.ts\" \"src/**/*.tsx\"", "lint:fix": "eslint --fix \"src/**/*.ts\" \"src/**/*.tsx\"" diff --git a/scripts/transform-manifest.js b/scripts/transform-manifest.js new file mode 100644 index 00000000..a7374145 --- /dev/null +++ b/scripts/transform-manifest.js @@ -0,0 +1,64 @@ +/** + * Transforms the manifest.json file for the given browser. + * @param {string} browser - The browser to transform the manifest.json for. + * @returns {function} - A function that transforms the manifest.json file. + */ +function transform(browser) { + /** + * Transforms the manifest.json file for the given browser. + * @param {Buffer} buffer - The buffer to transform. + * @returns {string} - The transformed manifest.json file. + */ + return (buffer) => { + const manifest = JSON.parse(buffer.toString()); + + transformObject(manifest, browser); + + return JSON.stringify(manifest, null, 2); + }; +} + +const browserKeyPattern = /^__(.+?)__(.+)$/; + +/** + * Recursively traverses the object and transforms the browser-specific keys. + * @param {object} obj - The object to transform. + * @param {string} browser - The browser to transform the object for. + */ +function transformObject(obj, browser) { + if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) { + return; + } + + const keysToProcess = Object.keys(obj); + const keysToAdd = {}; + const keysToDelete = []; + + for (const key of keysToProcess) { + const match = key.match(browserKeyPattern); + if (match) { + const [, keyBrowser, actualKey] = match; + + if (keyBrowser === browser) { + keysToAdd[actualKey] = obj[key]; + keysToDelete.push(key); + } else { + keysToDelete.push(key); + } + } else { + transformObject(obj[key], browser); + } + } + + for (const [newKey, value] of Object.entries(keysToAdd)) { + obj[newKey] = value; + } + + for (const keyToDelete of keysToDelete) { + delete obj[keyToDelete]; + } +} + +module.exports = { + transform, +}; diff --git a/webpack.config.js b/webpack.config.js index 4527dcd7..61804f92 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -4,6 +4,10 @@ const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin; const CopyPlugin = require("copy-webpack-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin"); +const { transform } = require("./scripts/transform-manifest"); + +const browser = process.env.BROWSER || "chrome"; +const outputDir = `dist-${browser}-mv3`; module.exports = { module: { @@ -41,6 +45,7 @@ module.exports = { output: { filename: "[name].js", publicPath: "/", + path: path.resolve(__dirname, outputDir), }, mode: "development", devServer: { @@ -64,7 +69,11 @@ module.exports = { }), new CopyPlugin({ patterns: [ - { from: "manifest.json", to: "." }, + { + from: "manifest.template.json", + to: "manifest.json", + transform: transform(browser), + }, { from: "images", to: "images" }, ], }), From 2f055514eb76206575aa5e85052329af7239dd05 Mon Sep 17 00:00:00 2001 From: sun-yryr Date: Sat, 6 Dec 2025 00:50:27 +0900 Subject: [PATCH 2/2] chore: fix ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 526179e3..c1194f30 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,6 @@ jobs: - run: yarn install --frozen-lockfile - name: yarn build and test run: | - yarn build + yarn build:all yarn test yarn lint:check