diff options
| -rw-r--r-- | config/webpack.config.js | 36 | ||||
| -rw-r--r-- | config/webpack/loaders/scoped-loader.js | 8 | ||||
| -rw-r--r-- | config/webpack/plugins/create-manifest-webpack-plugin/index.js | 11 | ||||
| -rw-r--r-- | config/webpack/plugins/inject-script-webpack-plugin.js | 33 | ||||
| -rw-r--r-- | config/webpack/plugins/sanitize-scripts-import-webpack-plugin.js | 10 | ||||
| -rw-r--r-- | config/webpack/utils/generate-script-build-config.js | 14 | ||||
| -rw-r--r-- | config/webpack/utils/inline-javascript.js | 4 | ||||
| -rw-r--r-- | src/scripts.json (renamed from src/manifest.json) | 0 | ||||
| -rw-r--r-- | src/scripts/block-unnecessary.ts | 35 |
9 files changed, 78 insertions, 73 deletions
diff --git a/config/webpack.config.js b/config/webpack.config.js index e7ffaa7..3f09a5a 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -7,23 +7,31 @@ process.env.SOURCE_DIR = path.resolve(process.env.ROOT_DIR, "src"); const CreateManifestPlugin = require("./webpack/plugins/create-manifest-webpack-plugin"); const generateScriptBuildConfig = require("./webpack/utils/generate-script-build-config"); +const inlineJavascript = require("./webpack/utils/inline-javascript"); -const manifest = require(path.resolve(process.env.SOURCE_DIR, "manifest.json")); +const scripts = require(path.resolve(process.env.SOURCE_DIR, "scripts.json")); -let scripts = []; +let scriptBuildConfigs = []; -for (const scriptType in manifest) { - scripts.push(generateScriptBuildConfig(scriptType)); +for (const scriptType in scripts) { + scriptBuildConfigs.push(generateScriptBuildConfig(scriptType)); } -scripts[scripts.length - 1].plugins = (scripts[scripts.length - 1].plugins || []).concat([ - new CopyPlugin({ - patterns: [{ - from: path.resolve(process.env.ROOT_DIR, "static"), - to: "./" - }] - }), - new CreateManifestPlugin({ scripts: manifest }) -]); +scriptBuildConfigs.push({ + name: "manifest", + entry: inlineJavascript(""), + output: { + filename: `manifest.json` + }, + plugins: [ + new CopyPlugin({ + patterns: [{ + from: path.resolve(process.env.ROOT_DIR, "static"), + to: "./" + }] + }), + new CreateManifestPlugin({ scripts }) + ] +}); -module.exports = scripts; +module.exports = scriptBuildConfigs; diff --git a/config/webpack/loaders/scoped-loader.js b/config/webpack/loaders/scoped-loader.js index 701afc2..3b68ba6 100644 --- a/config/webpack/loaders/scoped-loader.js +++ b/config/webpack/loaders/scoped-loader.js @@ -1,3 +1,5 @@ -module.exports = source => `(() => { -${source} -})();`; +const path = require("path"); + +module.exports = function (source) { + return `/**\t${path.basename(this.resourcePath)}\t**/\n(() => {\n${source}\n})();` +}; diff --git a/config/webpack/plugins/create-manifest-webpack-plugin/index.js b/config/webpack/plugins/create-manifest-webpack-plugin/index.js index 4a07380..6bbb485 100644 --- a/config/webpack/plugins/create-manifest-webpack-plugin/index.js +++ b/config/webpack/plugins/create-manifest-webpack-plugin/index.js @@ -1,3 +1,4 @@ +const { sources } = require("webpack"); const path = require("path"); const { version } = require(path.resolve(process.env.ROOT_DIR, "package.json")); @@ -34,10 +35,10 @@ class CreateManifestPlugin { compilation.hooks.processAssets.tap( { name: "CreateManifestPlugin", - stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE, + stage: compiler.webpack.Compilation.PROCESS_ASSETS_ADDITIONAL, additionalAssets: true }, - assets => { + () => { this.manifest.version = version; this.manifest.content_scripts = [] @@ -64,8 +65,10 @@ class CreateManifestPlugin { } } - const { RawSource } = compiler.webpack.sources; - assets["manifest.json"] = new RawSource(Buffer.from(JSON.stringify(this.manifest))); + compilation.updateAsset( + "manifest.json", + new sources.RawSource(JSON.stringify(this.manifest)) + ); } ); }); diff --git a/config/webpack/plugins/inject-script-webpack-plugin.js b/config/webpack/plugins/inject-script-webpack-plugin.js index 6568514..213e691 100644 --- a/config/webpack/plugins/inject-script-webpack-plugin.js +++ b/config/webpack/plugins/inject-script-webpack-plugin.js @@ -1,23 +1,6 @@ const { sources } = require("webpack"); const terser = require("terser"); -const propectualIndexOf = (string, characterList, start) => { - if (start > 0) { - let i = 0; - let x = start; - while (i < characterList.length) { - x = string.indexOf(characterList[i], x + 1); - if (x < 0) { - return -1; - } - i++; - } - return x; - } else { - return -1; - } -}; - class InjectScriptPlugin { constructor({ onload, isFirst }) { this.onload = !!onload; @@ -36,11 +19,11 @@ class InjectScriptPlugin { for (const assetName in assets) { if (assetName.endsWith(".js")) { let currentAssetContent = compilation.getAsset(assetName).source.source(); - let start = ` - const observer = new MutationObserver(mutations => { - const script = document.querySelector("head > script:nth-child(54)"); - if (script) { - script.innerHTML + let start = `(() => { + const o = new MutationObserver(() => { + const s = document.querySelector("head > script:nth-child(54)"); + if (s) { + s.innerHTML `; let end = ""; if (!this.isFirst) { @@ -52,11 +35,11 @@ class InjectScriptPlugin { end += "});"; } end += `\`; - observer.disconnect(); + o.disconnect(); } }); - observer.observe(document, {childList: true, subtree: true}); - `; + o.observe(document, {childList: true, subtree: true}); + })();`; const content = (await terser.minify(currentAssetContent.replaceAll("`", "\\`"))).code; compilation.updateAsset( assetName, diff --git a/config/webpack/plugins/sanitize-scripts-import-webpack-plugin.js b/config/webpack/plugins/sanitize-scripts-import-webpack-plugin.js index 61ce804..37c2cf4 100644 --- a/config/webpack/plugins/sanitize-scripts-import-webpack-plugin.js +++ b/config/webpack/plugins/sanitize-scripts-import-webpack-plugin.js @@ -1,15 +1,13 @@ const { sources } = require("webpack"); -const propectualIndexOf = (string, characterList, start) => { +const perpectualIndexOf = (string, characterList, start) => { if (start > 0) { - let i = 0; let x = start; - while (i < characterList.length) { + for (let i = 0; i < characterList.length; i++) { x = string.indexOf(characterList[i], x + 1); if (x < 0) { return -1; } - i++; } return x; } else { @@ -33,8 +31,8 @@ class SanitizeScriptsImportPlugin { let previouslyEnded = 0; let code = ""; while (true) { - const start = propectualIndexOf(currentAssetContent, ["\n/***/", "\n/***/", "\n"], previouslyEnded + 1); - previouslyEnded = propectualIndexOf(currentAssetContent, ["\n/***/"], start + 1); + const start = perpectualIndexOf(currentAssetContent, ["\n/***/", "\n/***/", "\n"], previouslyEnded + 1); + previouslyEnded = perpectualIndexOf(currentAssetContent, ["\n/***/"], start + 1); if (previouslyEnded < 0) { break; } else { diff --git a/config/webpack/utils/generate-script-build-config.js b/config/webpack/utils/generate-script-build-config.js index f8e1697..a6f9f54 100644 --- a/config/webpack/utils/generate-script-build-config.js +++ b/config/webpack/utils/generate-script-build-config.js @@ -3,10 +3,9 @@ const path = require("path"); const SanitizeScriptsImportPlugin = require("../plugins/sanitize-scripts-import-webpack-plugin"); const InjectScriptPlugin = require("../plugins/inject-script-webpack-plugin"); +const inlineJavascript = require("./inline-javascript"); -const manifest = require(path.resolve(process.env.SOURCE_DIR, "manifest.json")); - -let count = 0; +const scripts = require(path.resolve(process.env.SOURCE_DIR, "scripts.json")); const getImportStatementForScript = script => { const importPath = path.resolve(process.env.SOURCE_DIR, "scripts", script); @@ -14,15 +13,16 @@ const getImportStatementForScript = script => { }; const getVirtualEntry = scriptType => { - const string = Object.keys(manifest[scriptType]).map(getImportStatementForScript).join("\n"); + const importStatements = Object.keys(scripts[scriptType]).map(getImportStatementForScript).join("\n"); - const base64 = Buffer.from(string).toString("base64"); - return `data:text/javascript;base64,${base64}`; + return inlineJavascript(importStatements); } +let injectedScriptsCount = 0; const generateScriptBuildConfig = scriptType => { return { entry: getVirtualEntry(scriptType), + name: scriptType, mode: "production", output: { filename: `${scriptType}.js` @@ -54,7 +54,7 @@ const generateScriptBuildConfig = scriptType => { scriptType.startsWith("injected") ? [new InjectScriptPlugin({ onload: scriptType === "injected_and_loaded", - isFirst: count++ <= 0 + isFirst: injectedScriptsCount++ <= 0 })] : [] ) diff --git a/config/webpack/utils/inline-javascript.js b/config/webpack/utils/inline-javascript.js new file mode 100644 index 0000000..b9348cc --- /dev/null +++ b/config/webpack/utils/inline-javascript.js @@ -0,0 +1,4 @@ +module.exports = code => { + const base64 = Buffer.from(code).toString("base64"); + return `data:text/javascript;base64,${base64}`; +}; diff --git a/src/manifest.json b/src/scripts.json index 8e8d0bd..8e8d0bd 100644 --- a/src/manifest.json +++ b/src/scripts.json diff --git a/src/scripts/block-unnecessary.ts b/src/scripts/block-unnecessary.ts index 4163778..bec90a5 100644 --- a/src/scripts/block-unnecessary.ts +++ b/src/scripts/block-unnecessary.ts @@ -1,23 +1,30 @@ -type ConditionalString = string | undefined; -let blocked: ConditionalString[] = [ - "head > script:nth-child(34)", - "head > script:nth-child(43)" +let replace: (any[] | undefined)[] = [ + ["head > script:nth-child(34)", { src: "" }], + ["head > script:nth-child(35)", { src: "https://code.jquery.com/jquery-1.12.4.min.js", crossorigin: "anonymous" }], + ["head > script:nth-child(43)", { src: "" }] ]; let count = 0; +let notDone = false; -const observer = new MutationObserver(mutations => { - for (let i = 0; i < blocked.length; i++) { - if (blocked[i]) { - const element = document.querySelector(blocked[i]!) as HTMLElement | null; +const observer = new MutationObserver(() => { + if (notDone) { + const meta = document.querySelector("head > meta:nth-child(2)"); + if (meta) { + meta.setAttribute("http-equiv", "Content-Security-Policy"); + meta.setAttribute("content", "default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *"); + } + } + for (let i = 0; i < replace.length; i++) { + if (replace[i]) { + const element = document.querySelector(replace[i]![0]) as HTMLElement | null; if (element) { - if (element instanceof HTMLScriptElement) { - element.src = ""; - } else if (element instanceof HTMLLinkElement && element.getAttribute("rel") === "stylesheet") { - element.href = ""; + const attributes = replace[i]![1]; + for (const attribute in attributes) { + element.setAttribute(attribute, attributes[attribute]); } - blocked[i] = undefined; + replace[i] = undefined; count++; - if (count >= blocked.length) { + if (count >= replace.length) { observer.disconnect(); break; } |
