aboutsummaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
Diffstat (limited to 'config')
-rw-r--r--config/webpack.config.js65
-rw-r--r--config/webpack/loaders/scoped-loader.js15
-rw-r--r--config/webpack/plugins/create-manifest-webpack-plugin/index.js36
-rw-r--r--config/webpack/plugins/inject-script-webpack-plugin.js71
-rw-r--r--config/webpack/utils/generate-script-build-config.js64
-rw-r--r--config/webpack/utils/inline-javascript.js5
-rw-r--r--config/webpack/utils/script-runtime.js15
7 files changed, 147 insertions, 124 deletions
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 3f09a5a..b4cd6cd 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -5,16 +5,71 @@ process.env.ROOT_DIR = path.resolve(__dirname, "..");
process.env.CONFIG_DIR = path.resolve(process.env.ROOT_DIR, "config");
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 CreateManifestPlugin = require(path.resolve(process.env.CONFIG_DIR, "webpack/plugins/create-manifest-webpack-plugin"));
+const SanitizeScriptsImportPlugin = require(path.resolve(process.env.CONFIG_DIR, "webpack/plugins/sanitize-scripts-import-webpack-plugin"));
+const InjectScriptPlugin = require(path.resolve(process.env.CONFIG_DIR, "webpack/plugins/inject-script-webpack-plugin"));
+const { inlineJavascript } = require(path.resolve(process.env.CONFIG_DIR, "webpack/utils/inline-javascript"));
+const { getScriptRuntimeFromType } = require(path.resolve(process.env.CONFIG_DIR, "webpack/utils/script-runtime"));
const scripts = require(path.resolve(process.env.SOURCE_DIR, "scripts.json"));
let scriptBuildConfigs = [];
-for (const scriptType in scripts) {
- scriptBuildConfigs.push(generateScriptBuildConfig(scriptType));
+let injectedScriptsCount = 0;
+
+const allScripts = {
+ document_start: {
+ ...(scripts.before || {}),
+ ...(scripts.injected || {}),
+ ...(scripts.injected_and_loaded || {})
+ },
+ document_end: scripts.rendered,
+ document_idle: scripts.loaded
+};
+
+for (const scriptRuntime in allScripts) {
+ if (allScripts[scriptRuntime]) {
+ const importStatements = Object.keys(allScripts[scriptRuntime]).map(script =>
+ `import "${path.resolve(process.env.SOURCE_DIR, "scripts", script)}";`
+ ).join("\n");
+
+ scriptBuildConfigs.push({
+ entry: inlineJavascript(importStatements),
+ name: scriptRuntime,
+ mode: "production",
+ output: {
+ filename: `${scriptRuntime}.js`
+ },
+ resolve: {
+ extensions: ["", ".ts", ".js"],
+ alias: {
+ "@": process.env.SOURCE_DIR
+ }
+ },
+ module: {
+ rules: [
+ {
+ test: /\.tsx?$/,
+ loader: "ts-loader",
+ options: {
+ configFile: "config/tsconfig.json"
+ }
+ },
+ {
+ test: new RegExp(`^${path.resolve(process.env.SOURCE_DIR, "scripts")}`),
+ loader: path.resolve(process.env.CONFIG_DIR, "webpack/loaders/scoped-loader")
+ }
+ ]
+ },
+ plugins: [
+ new SanitizeScriptsImportPlugin()
+ ].concat(
+ scriptRuntime === "document_start"
+ ? [new InjectScriptPlugin()]
+ : []
+ )
+ });
+ }
}
scriptBuildConfigs.push({
diff --git a/config/webpack/loaders/scoped-loader.js b/config/webpack/loaders/scoped-loader.js
index 3b68ba6..1be58a4 100644
--- a/config/webpack/loaders/scoped-loader.js
+++ b/config/webpack/loaders/scoped-loader.js
@@ -1,5 +1,18 @@
const path = require("path");
+const scripts = require(path.resolve(process.env.SOURCE_DIR, "scripts.json"));
+
+const getScriptType = scriptName => {
+ for (const scriptType in scripts) {
+ if (scripts[scriptType][scriptName]) {
+ return scriptType;
+ }
+ }
+ return "undefined_script";
+};
+
module.exports = function (source) {
- return `/**\t${path.basename(this.resourcePath)}\t**/\n(() => {\n${source}\n})();`
+ return `/*<--\t${getScriptType(path.basename(this.resourcePath))}\t-->*/
+(() => {\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 6bbb485..7748cd9 100644
--- a/config/webpack/plugins/create-manifest-webpack-plugin/index.js
+++ b/config/webpack/plugins/create-manifest-webpack-plugin/index.js
@@ -2,32 +2,16 @@ const { sources } = require("webpack");
const path = require("path");
const { version } = require(path.resolve(process.env.ROOT_DIR, "package.json"));
-
-const getRunAt = scriptType => {
- switch (scriptType) {
- case "before":
- case "injected":
- case "injected_and_loaded":
- return "document_start";
-
- case "rendered":
- return "document_end";
-
- case "loaded":
- default:
- return "document_idle";
- }
-};
+const { getScriptRuntimeFromType } = require(path.resolve(process.env.CONFIG_DIR, "webpack/utils/script-runtime"));
class CreateManifestPlugin {
constructor({ scripts }) {
this.scripts = {};
this.manifest = require("./manifest-template.json");
- this.scripts.before = scripts.before || {};
- this.scripts.injected = scripts.injected || {};
- this.scripts.injected_and_loaded = scripts.injected_and_loaded || {};
- this.scripts.rendered = scripts.rendered || {};
- this.scripts.loaded = scripts.loaded || {};
+ for (const scriptType in scripts) {
+ const scriptRuntime = getScriptRuntimeFromType(scriptType);
+ this.scripts[scriptRuntime] = { ...this.scripts[scriptRuntime], ...scripts[scriptType] };
+ }
}
apply(compiler) {
@@ -42,9 +26,9 @@ class CreateManifestPlugin {
this.manifest.version = version;
this.manifest.content_scripts = []
- for (const scriptType in this.scripts) {
- if (Object.keys(this.scripts[scriptType]).length > 0) {
- const currentScripts = this.scripts[scriptType];
+ for (const scriptRuntime in this.scripts) {
+ if (Object.keys(this.scripts[scriptRuntime]).length > 0) {
+ const currentScripts = this.scripts[scriptRuntime];
let paths = {};
for (const scriptName in currentScripts) {
@@ -58,8 +42,8 @@ class CreateManifestPlugin {
for (const scriptPath in paths) {
this.manifest.content_scripts.push({
matches: [`*://banglarbhumi.gov.in/${scriptPath}`],
- js: [`${scriptType}.js`],
- run_at: getRunAt(scriptType)
+ js: [`${scriptRuntime}.js`],
+ run_at: scriptRuntime
});
}
}
diff --git a/config/webpack/plugins/inject-script-webpack-plugin.js b/config/webpack/plugins/inject-script-webpack-plugin.js
index 213e691..592751d 100644
--- a/config/webpack/plugins/inject-script-webpack-plugin.js
+++ b/config/webpack/plugins/inject-script-webpack-plugin.js
@@ -1,12 +1,13 @@
const { sources } = require("webpack");
const terser = require("terser");
-class InjectScriptPlugin {
- constructor({ onload, isFirst }) {
- this.onload = !!onload;
- this.isFirst = !!isFirst;
- }
+const getScriptCodeScoped = (scriptCode, loaded) => scriptCode
+ ? (loaded
+ ? `document.addEventListener(\"DOMContentLoaded\", () => {${scriptCode}});`
+ : `(() => {${scriptCode}})();`)
+ : "";
+class InjectScriptPlugin {
apply(compiler) {
compiler.hooks.compilation.tap("InjectScriptPlugin", compilation => {
compilation.hooks.processAssets.tapPromise(
@@ -18,32 +19,54 @@ class InjectScriptPlugin {
async assets => {
for (const assetName in assets) {
if (assetName.endsWith(".js")) {
- let currentAssetContent = compilation.getAsset(assetName).source.source();
- let start = `(() => {
- const o = new MutationObserver(() => {
- const s = document.querySelector("head > script:nth-child(54)");
- if (s) {
- s.innerHTML
- `;
- let end = "";
- if (!this.isFirst) {
- start += "+";
+ let scriptEnd = 0;
+ const currentAssetContent = compilation.getAsset(assetName).source.source();
+ const scripts = {
+ before: "",
+ injected: "",
+ injected_and_loaded: ""
+ };
+ while (true) {
+ const start = currentAssetContent.indexOf("/*<--\t", scriptEnd + 1);
+ if (start < 0) {
+ break;
+ } else {
+ const end = currentAssetContent.indexOf("\t-->*/", start + 1);
+ if (end < 0) {
+ throw Error("Failed to parse some scripts");
+ } else {
+ const scriptType = currentAssetContent.substring(start + 6, end);
+ scriptEnd = currentAssetContent.indexOf("\n/*<---->*/", end + 1)
+ if (scriptEnd < 0) {
+ break;
+ }
+ scripts[scriptType.trim()] += currentAssetContent.substring(end + 6, scriptEnd);
+ scriptEnd += 11;
+ }
+ }
}
- start += "= `";
- if (this.onload) {
- start += "document.addEventListener(\"DOMContentLoaded\", () => {";
- end += "});";
+ for (const scriptType in scripts) {
+ const currentScriptCode = (await terser.minify(scripts[scriptType].replaceAll("`", "\\`"))).code;
+ scripts[scriptType] = currentScriptCode
+ ? (scriptType === "injected_and_loaded"
+ ? `document.addEventListener(\"DOMContentLoaded\", () => {${currentScriptCode}});`
+ : `(() => {${currentScriptCode}})();`)
+ : "";
}
- end += `\`;
+ const injectedCode = (scripts.injected || scripts.injected_and_loaded)
+ ? `const o = new MutationObserver(() => {
+ const s = document.querySelector("head > script:nth-child(54)");
+ if (s) {
+ s.innerHTML = \`${scripts.injected}${scripts.injected_and_loaded}\`;
o.disconnect();
}
});
- o.observe(document, {childList: true, subtree: true});
- })();`;
- const content = (await terser.minify(currentAssetContent.replaceAll("`", "\\`"))).code;
+ o.observe(document, {childList: true, subtree: true});`
+ : "";
+ const resultantCode = scripts.before + injectedCode;
compilation.updateAsset(
assetName,
- new sources.RawSource(start + content + end)
+ new sources.RawSource(resultantCode)
);
}
}
diff --git a/config/webpack/utils/generate-script-build-config.js b/config/webpack/utils/generate-script-build-config.js
deleted file mode 100644
index a6f9f54..0000000
--- a/config/webpack/utils/generate-script-build-config.js
+++ /dev/null
@@ -1,64 +0,0 @@
-const fs = require("fs");
-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 scripts = require(path.resolve(process.env.SOURCE_DIR, "scripts.json"));
-
-const getImportStatementForScript = script => {
- const importPath = path.resolve(process.env.SOURCE_DIR, "scripts", script);
- return `import "${importPath}";`;
-};
-
-const getVirtualEntry = scriptType => {
- const importStatements = Object.keys(scripts[scriptType]).map(getImportStatementForScript).join("\n");
-
- return inlineJavascript(importStatements);
-}
-
-let injectedScriptsCount = 0;
-const generateScriptBuildConfig = scriptType => {
- return {
- entry: getVirtualEntry(scriptType),
- name: scriptType,
- mode: "production",
- output: {
- filename: `${scriptType}.js`
- },
- resolve: {
- extensions: ["", ".ts", ".js"],
- alias: {
- "@": process.env.SOURCE_DIR
- }
- },
- module: {
- rules: [
- {
- test: /\.tsx?$/,
- loader: "ts-loader",
- options: {
- configFile: "config/tsconfig.json"
- }
- },
- {
- test: new RegExp(`^${path.resolve(process.env.SOURCE_DIR, "scripts")}`),
- loader: path.resolve(process.env.CONFIG_DIR, "webpack/loaders/scoped-loader")
- }
- ]
- },
- plugins: [
- new SanitizeScriptsImportPlugin()
- ].concat(
- scriptType.startsWith("injected")
- ? [new InjectScriptPlugin({
- onload: scriptType === "injected_and_loaded",
- isFirst: injectedScriptsCount++ <= 0
- })]
- : []
- )
- };
-};
-
-module.exports = generateScriptBuildConfig;
diff --git a/config/webpack/utils/inline-javascript.js b/config/webpack/utils/inline-javascript.js
index b9348cc..ea344a4 100644
--- a/config/webpack/utils/inline-javascript.js
+++ b/config/webpack/utils/inline-javascript.js
@@ -1,4 +1 @@
-module.exports = code => {
- const base64 = Buffer.from(code).toString("base64");
- return `data:text/javascript;base64,${base64}`;
-};
+module.exports.inlineJavascript = code => `data:text/javascript;base64,${Buffer.from(code).toString("base64")}`;
diff --git a/config/webpack/utils/script-runtime.js b/config/webpack/utils/script-runtime.js
new file mode 100644
index 0000000..394e87e
--- /dev/null
+++ b/config/webpack/utils/script-runtime.js
@@ -0,0 +1,15 @@
+module.exports.getScriptRuntimeFromType = scriptType => {
+ switch (scriptType) {
+ case "before":
+ case "injected":
+ case "injected_and_loaded":
+ return "document_start";
+
+ case "rendered":
+ return "document_end";
+
+ case "loaded":
+ default:
+ return "document_idle";
+ }
+};