aboutsummaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
authorArpit Chakladar <arpitchakladar+git@gmail.com>2026-07-13 23:32:26 +0530
committerGitHub <noreply@github.com>2026-07-13 23:32:26 +0530
commitce401d03e75bcbfd1cdfa963954e0807219fb80d (patch)
tree52a813c1705a952312c20c328b00fa845a3453f9 /config
parent98e7019c61ea0ffe344ef7ce809d38d62254a9fc (diff)
parentdfba7ff6fff7bde33b40a343a2318b35c429b40f (diff)
downloadbanglar-bhumi-utils-ce401d03e75bcbfd1cdfa963954e0807219fb80d.tar.gz
banglar-bhumi-utils-ce401d03e75bcbfd1cdfa963954e0807219fb80d.zip
Merge pull request #6 from arpitchakladar/adding-documentation-comments
Adding documentation comments
Diffstat (limited to 'config')
-rw-r--r--config/tsconfig.json26
-rw-r--r--config/webpack.config.js238
-rw-r--r--config/webpack/loader/arrange-shared-module-loader.js16
-rw-r--r--config/webpack/loader/count-imports-loader.js9
-rw-r--r--config/webpack/loader/to-string-loader.js12
-rw-r--r--config/webpack/plugins/create-injected-shared-modules-webpack-plugin.js25
-rw-r--r--config/webpack/plugins/create-manifest-webpack-plugin/index.js48
-rw-r--r--config/webpack/plugins/create-rules-webpack-plugin.js16
-rw-r--r--config/webpack/plugins/inject-script-webpack-plugin.js23
-rw-r--r--config/webpack/utils/build-file.js12
-rw-r--r--config/webpack/utils/injected-code.js22
-rw-r--r--config/webpack/utils/inline-javascript.js11
-rw-r--r--config/webpack/utils/script-runtime.js13
-rw-r--r--config/webpack/utils/scripts.js14
-rw-r--r--config/webpack/utils/shared-modules.js12
15 files changed, 192 insertions, 305 deletions
diff --git a/config/tsconfig.json b/config/tsconfig.json
deleted file mode 100644
index ec61595..0000000
--- a/config/tsconfig.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "files": [
- "../src/html.d.ts"
- ],
- "compilerOptions": {
- "outDir": "dist",
- "sourceMap": true,
- "strict": true,
- "noImplicitReturns": true,
- "noImplicitAny": true,
- "module": "es2022",
- "moduleResolution": "node",
- "target": "es2021",
- "allowJs": true,
- "allowSyntheticDefaultImports": true,
- "skipLibCheck": true,
- "moduleDetection": "force",
- "baseUrl": "../",
- "paths": {
- "@/*": ["src/*"]
- }
- },
- "exclude": [
- "../node_modules/**/*"
- ]
-}
diff --git a/config/webpack.config.js b/config/webpack.config.js
deleted file mode 100644
index 8fd3f15..0000000
--- a/config/webpack.config.js
+++ /dev/null
@@ -1,238 +0,0 @@
-import path from "path";
-import fs from "fs";
-import { fileURLToPath } from "url";
-import webpack from "webpack";
-import { merge } from "webpack-merge";
-import CopyPlugin from "copy-webpack-plugin";
-
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
-
-global.ROOT_DIR = path.resolve(__dirname, "..");
-global.CONFIG_DIR = path.resolve(ROOT_DIR, "config");
-global.SOURCE_DIR = path.resolve(ROOT_DIR, "src");
-global.production = process.env.NODE_ENV === "production";
-
-import CreateManifestPlugin from "./webpack/plugins/create-manifest-webpack-plugin/index.js";
-import CreateRulesPlugin from "./webpack/plugins/create-rules-webpack-plugin.js";
-import InjectScriptPlugin from "./webpack/plugins/inject-script-webpack-plugin.js";
-import CreateInjectedSharedModulesPlugin from "./webpack/plugins/create-injected-shared-modules-webpack-plugin.js";
-
-import { inlineJavascript } from "./webpack/utils/inline-javascript.js";
-import { getScriptRuntimeFromType } from "./webpack/utils/script-runtime.js";
-import { getFileName } from "./webpack/utils/build-file.js";
-
-import scripts from "./webpack/utils/scripts.js";
-import sharedModules from "./webpack/utils/shared-modules.js";
-
-const sharedModulesImportedCount = {};
-
-for (const sharedModule of sharedModules) {
- sharedModulesImportedCount[sharedModule] = 0;
-}
-
-const injectedSharedModulesImportedCount = {};
-
-for (const sharedModule of sharedModules) {
- injectedSharedModulesImportedCount[sharedModule] = 0;
-}
-
-const backgroundScriptEntries = {};
-const uninjectedScriptEntries = {};
-const injectedAfterScriptEntries = {};
-const injectedBeforeScriptEntries = {};
-const sharedModuleEntries = {};
-const sharedModuleExternals = {};
-
-const backgroundScriptImports = fs.readdirSync(path.resolve(SOURCE_DIR, "background"))
- .map(scriptName => `import "${path.resolve(SOURCE_DIR, "background", scriptName)}";`)
- .join("\n");
-backgroundScriptEntries["background script"] = {
- import: inlineJavascript(backgroundScriptImports),
- filename: "background.js"
-};
-
-for (const scriptPath in scripts) {
- for (const scriptType in scripts[scriptPath]) {
- const currentScripts = scripts[scriptPath][scriptType];
- let scriptEntries;
- let destinationFolder = "scripts";
-
- switch (scriptType) {
- case "injected":
- scriptEntries = injectedAfterScriptEntries;
- destinationFolder = "scripts/injected";
- break;
-
- default:
- scriptEntries = uninjectedScriptEntries;
- }
-
- scriptEntries[`${scriptType} - "${scriptPath}"`] = {
- import: inlineJavascript(currentScripts.map(script => `import "${path.resolve(SOURCE_DIR, "scripts", script)}";`).join("\n")),
- filename: `${destinationFolder}/${getFileName(scriptType, scriptPath)}.js`
- };
- }
-}
-
-for (const sharedModule of sharedModules) {
- const sharedModuleNameHash = getFileName(sharedModule, "shared");
- const sharedModuleGlobalVariableName = `$${sharedModuleNameHash.substring(sharedModuleNameHash.length - 16)}`;
- sharedModuleEntries[sharedModule] = {
- import: path.resolve(SOURCE_DIR, "shared", sharedModule),
- filename: `shared/${sharedModuleNameHash}.js`,
- library: {
- name: sharedModuleGlobalVariableName,
- type: "var"
- }
- };
- sharedModuleExternals[`@/shared/${sharedModule}`] = sharedModuleGlobalVariableName;
-}
-
-const commonOptions = {
- mode: "production",
- target: "web",
- resolve: {
- extensions: [".ts", ".js", ".html"],
- alias: {
- "@": global.SOURCE_DIR,
- },
- },
- module: {
- rules: [
- {
- test: /\.ts$/,
- loader: "ts-loader",
- options: {
- configFile: "config/tsconfig.json",
- }
- },
- {
- test: /\.html$/,
- loader: path.resolve(CONFIG_DIR, "webpack/loader/to-string-loader.js"),
- },
- ],
- },
- optimization: {
- minimize: process.env.NODE_ENV === "production",
- runtimeChunk: false,
- },
- output: {
- iife: true,
- },
- plugins: [
- new webpack.optimize.LimitChunkCountPlugin({
- maxChunks: 1,
- }),
- ],
-};
-
-const sharedModuleOptions = {
- externals: sharedModuleExternals,
- externalsType: "var",
- module: {
- rules: [
- {
- test: /banglar-bhumi-utils\/src\/.*.(^.?|\.[^d]|[^.]d|[^.][^d])\.(t|j)s$/,
- loader: path.resolve(CONFIG_DIR, "webpack/loader/count-imports-loader.js"),
- options: {
- sharedModulesImportedCount,
- },
- enforce: "post",
- }
- ]
- }
-};
-
-const backgroundScriptConfiguration = merge(
- commonOptions,
- sharedModuleOptions,
- {
- entry: backgroundScriptEntries,
- },
-);
-
-const uninjectedScriptConfiguration = merge(
- commonOptions,
- sharedModuleOptions,
- {
- entry: uninjectedScriptEntries
- }
-);
-
-const injectedScriptConfiguration = merge(
- commonOptions,
- {
- externals: sharedModuleExternals,
- externalsType: "var",
- module: {
- rules: [
- {
- test: /banglar-bhumi-utils\/src\/.*.(^.?|\.[^d]|[^.]d|[^.][^d])\.(t|j)s$/,
- loader: path.resolve(CONFIG_DIR, "webpack/loader/count-imports-loader.js"),
- options: {
- sharedModulesImportedCount: injectedSharedModulesImportedCount
- },
- enforce: "post"
- }
- ]
- },
- entry: injectedAfterScriptEntries,
- plugins: [
- new InjectScriptPlugin()
- ]
- }
-);
-
-const sortedSharedModules = []
-
-const sharedModulesConfiguration = merge(
- commonOptions,
- sharedModuleOptions,
- {
- entry: sharedModuleEntries,
- plugins: [
- new CopyPlugin({
- patterns: [
- {
- from: path.resolve("static"),
- to: "./",
- },
- {
- from: path.resolve("src/offscreen"),
- to: "./offscreen",
- },
- ],
- }),
- new CreateInjectedSharedModulesPlugin({
- injectedSharedModulesImportedCount,
- sortedSharedModules
- }),
- new CreateRulesPlugin(),
- new CreateManifestPlugin({
- sharedModulesImportedCount,
- injectedSharedModulesImportedCount,
- sortedSharedModules
- })
- ],
- module: {
- rules: [
- {
- test: /banglar-bhumi-utils\/src\/.*.(^.?|\.[^d]|[^.]d|[^.][^d])\.(t|j)s$/,
- loader: path.resolve(CONFIG_DIR, "webpack/loader/arrange-shared-module-loader.js"),
- options: {
- sortedSharedModules
- },
- enforce: "post"
- }
- ]
- }
- }
-);
-
-export default [
- backgroundScriptConfiguration,
- uninjectedScriptConfiguration,
- injectedScriptConfiguration,
- sharedModulesConfiguration
-];
diff --git a/config/webpack/loader/arrange-shared-module-loader.js b/config/webpack/loader/arrange-shared-module-loader.js
index 2265185..63fd62d 100644
--- a/config/webpack/loader/arrange-shared-module-loader.js
+++ b/config/webpack/loader/arrange-shared-module-loader.js
@@ -1,8 +1,18 @@
import path from "path";
+
import { ImportManager } from "import-manager";
import sharedModules from "../utils/shared-modules.js";
+/**
+ * Webpack loader that arranges shared modules in dependency order.
+ * As each shared module is processed, its own shared-module dependencies
+ * are inserted before it in the global `sortedSharedModules` array so that
+ * the final output respects the import graph.
+ *
+ * @param {string} source - The source code of the current module.
+ * @returns {string} The unmodified source (this loader is side-effect only).
+ */
export default function(source) {
const currentSharedModuleName = path.basename(this.resourcePath.substring(0, this.resourcePath.length - 3));
@@ -17,7 +27,11 @@ export default function(source) {
if (moduleIndex >= 0) {
const currentSharedModuleName = sharedModules[moduleIndex];
- if (!(sortedSharedModules.includes(currentSharedModuleName) || modulesToBeIncluded.includes(currentSharedModuleName))) {
+ const alreadyIncluded = (
+ sortedSharedModules.includes(currentSharedModuleName)
+ || modulesToBeIncluded.includes(currentSharedModuleName));
+
+ if (!alreadyIncluded) {
modulesToBeIncluded.push(currentSharedModuleName);
}
}
diff --git a/config/webpack/loader/count-imports-loader.js b/config/webpack/loader/count-imports-loader.js
index 2586332..ef832bf 100644
--- a/config/webpack/loader/count-imports-loader.js
+++ b/config/webpack/loader/count-imports-loader.js
@@ -1,6 +1,15 @@
import { ImportManager } from "import-manager";
+
import sharedModules from "../utils/shared-modules.js";
+/**
+ * Webpack loader that counts how many times each shared module is imported.
+ * This count is used later to determine which shared modules need to be
+ * included in the compiled output.
+ *
+ * @param {string} source - The source code of the current module.
+ * @returns {string} The unmodified source (this loader is side-effect only).
+ */
export default function(source) {
const { sharedModulesImportedCount } = this.getOptions();
const manager = new ImportManager(source);
diff --git a/config/webpack/loader/to-string-loader.js b/config/webpack/loader/to-string-loader.js
index 248574a..025ea5e 100644
--- a/config/webpack/loader/to-string-loader.js
+++ b/config/webpack/loader/to-string-loader.js
@@ -1,7 +1,17 @@
+/**
+ * Webpack loader that converts HTML template files into JavaScript modules.
+ * It escapes template literals and replaces `$name$` placeholders with
+ * `${name}` interpolation syntax so the exported function can accept a
+ * replacements object.
+ *
+ * @param {string} source - Raw HTML file content.
+ * @returns {string} A JS module that exports a function accepting
+ * replacement values and returning the interpolated HTML string.
+ */
export default function(source) {
source = source
.replaceAll("\\", "\\\\")
- .replaceAll("`","\\`")
+ .replaceAll("`", "\\`")
.replaceAll("${", "\\${");
const replacements = {};
diff --git a/config/webpack/plugins/create-injected-shared-modules-webpack-plugin.js b/config/webpack/plugins/create-injected-shared-modules-webpack-plugin.js
index 695d4ef..c94ae86 100644
--- a/config/webpack/plugins/create-injected-shared-modules-webpack-plugin.js
+++ b/config/webpack/plugins/create-injected-shared-modules-webpack-plugin.js
@@ -1,31 +1,44 @@
import path from "path";
-import fs from "fs";
+
import webpack from "webpack";
import { getFileName } from "../utils/build-file.js";
+/**
+ * Webpack plugin that generates an injected shared-modules bundle.
+ * After all assets are processed, it creates a small JS file that
+ * calls the script injector for each shared module that was imported
+ * by injected scripts.
+ */
class CreateInjectedSharedModulesPlugin {
+ /**
+ * @param {{ injectedSharedModulesImportedCount: Record<string, number>, sortedSharedModules: string[] }} options
+ */
constructor({ injectedSharedModulesImportedCount, sortedSharedModules }) {
this.injectedSharedModulesImportedCount = injectedSharedModulesImportedCount;
this.sortedSharedModules = sortedSharedModules;
}
+ /**
+ * @param {import("webpack").Compiler} compiler
+ * @returns {void}
+ */
apply(compiler) {
- compiler.hooks.compilation.tap("CreateInjectedSharedModulesPlugin", compilation => {
+ compiler.hooks.compilation.tap("CreateInjectedSharedModulesPlugin", (compilation) => {
compilation.hooks.processAssets.tap(
{
name: "CreateInjectedSharedModulesPlugin",
stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
},
- assets => {
+ (_assets) => {
const injectedSharedScripts = this.sortedSharedModules
- .filter(sharedModule => this.injectedSharedModulesImportedCount[sharedModule] > 0)
- .map(sharedModule => `shared/${getFileName(sharedModule, "shared")}.js`);
+ .filter((sharedModule) => this.injectedSharedModulesImportedCount[sharedModule] > 0)
+ .map((sharedModule) => `shared/${getFileName(sharedModule, "shared")}.js`);
if (injectedSharedScripts.length > 0) {
const scriptInjectorModuleName = getFileName("script-injector", "shared", true);
const injectionCode = injectedSharedScripts
- .map(injectedScript => `$${scriptInjectorModuleName}.injectScriptHead("shared/${path.basename(injectedScript)}");`)
+ .map((injectedScript) => `$${scriptInjectorModuleName}.injectScriptHead("shared/${path.basename(injectedScript)}");`)
.join("");
compilation.emitAsset(
`shared/${getFileName("injected-shared-modules", "shared")}.js`,
diff --git a/config/webpack/plugins/create-manifest-webpack-plugin/index.js b/config/webpack/plugins/create-manifest-webpack-plugin/index.js
index 6f1e2be..95d0be8 100644
--- a/config/webpack/plugins/create-manifest-webpack-plugin/index.js
+++ b/config/webpack/plugins/create-manifest-webpack-plugin/index.js
@@ -1,31 +1,53 @@
-import webpack from "webpack";
-import path from "path";
import fs from "fs";
+import path from "path";
+
+import webpack from "webpack";
-import { getScriptRuntimeFromType } from "../../utils/script-runtime.js";
import { getFileName } from "../../utils/build-file.js";
+import { getScriptRuntimeFromType } from "../../utils/script-runtime.js";
import scripts from "../../utils/scripts.js";
+
const manifest = JSON.parse(
fs.readFileSync(
- path.resolve("config/webpack/plugins/create-manifest-webpack-plugin/manifest-template.json"),
- ),
+ path.resolve("config/webpack/plugins/create-manifest-webpack-plugin/manifest-template.json")
+ )
);
+/**
+ * Webpack plugin that dynamically generates the extension's
+ * `manifest.json` asset. It reads the template, resolves the
+ * current version from `package.json`, and builds `content_scripts`
+ * entries by matching script definitions from `scripts.json` against
+ * page URL patterns. Shared modules, injected scripts, and
+ * web-accessible resources are added automatically based on import
+ * counts collected during the build.
+ */
class CreateManifestPlugin {
+ /**
+ * @param {{
+ * sharedModulesImportedCount: Record<string, number>,
+ * injectedSharedModulesImportedCount: Record<string, number>,
+ * sortedSharedModules: string[]
+ * }} options
+ */
constructor({ sharedModulesImportedCount, injectedSharedModulesImportedCount, sortedSharedModules }) {
this.sharedModulesImportedCount = sharedModulesImportedCount;
this.injectedSharedModulesImportedCount = injectedSharedModulesImportedCount;
this.sortedSharedModules = sortedSharedModules;
}
+ /**
+ * @param {import("webpack").Compiler} compiler
+ * @returns {void}
+ */
apply(compiler) {
- compiler.hooks.compilation.tap("CreateManifestPlugin", compilation => {
+ compiler.hooks.compilation.tap("CreateManifestPlugin", (compilation) => {
compilation.hooks.processAssets.tap(
{
name: "CreateManifestPlugin",
stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
},
- assets => {
+ (assets) => {
manifest.version = JSON.parse(fs.readFileSync((path.resolve(ROOT_DIR, "package.json")))).version;
manifest.content_scripts = [];
let resources = [];
@@ -50,12 +72,12 @@ class CreateManifestPlugin {
}
manifest.content_scripts.push({
- matches: [`*://banglarbhumi.gov.in/BanglarBhumi/*`],
+ matches: ["*://banglarbhumi.gov.in/BanglarBhumi/*"],
js: this.sortedSharedModules
- .filter(sharedModule => this.sharedModulesImportedCount[sharedModule] > 0)
- .map(sharedModule => `shared/${getFileName(sharedModule, "shared")}.js`)
+ .filter((sharedModule) => this.sharedModulesImportedCount[sharedModule] > 0)
+ .map((sharedModule) => `shared/${getFileName(sharedModule, "shared")}.js`)
.concat(arrangedScripts["*"]["document_start"])
- .filter(x => x != null),
+ .filter((x) => x != null),
run_at: "document_start"
});
@@ -83,8 +105,8 @@ class CreateManifestPlugin {
}
const injectedSharedModules = this.sortedSharedModules
- .filter(sharedModule => this.injectedSharedModulesImportedCount[sharedModule] > 0)
- .map(sharedModule => `shared/${getFileName(sharedModule, "shared")}.js`);
+ .filter((sharedModule) => this.injectedSharedModulesImportedCount[sharedModule] > 0)
+ .map((sharedModule) => `shared/${getFileName(sharedModule, "shared")}.js`);
if (injectedSharedModules.length > 0) {
resources = resources.concat(injectedSharedModules);
diff --git a/config/webpack/plugins/create-rules-webpack-plugin.js b/config/webpack/plugins/create-rules-webpack-plugin.js
index 5573ddf..ce2fbef 100644
--- a/config/webpack/plugins/create-rules-webpack-plugin.js
+++ b/config/webpack/plugins/create-rules-webpack-plugin.js
@@ -1,16 +1,26 @@
-import path from "path";
import fs from "fs";
+import path from "path";
+
import webpack from "webpack";
+/**
+ * Webpack plugin that reads all JSON rule files from `src/rules/`,
+ * assigns sequential IDs to each rule, and emits a single `rules.json`
+ * asset used by `declarativeNetRequest`.
+ */
class CreateRulesPlugin {
+ /**
+ * @param {import("webpack").Compiler} compiler
+ * @returns {void}
+ */
apply(compiler) {
- compiler.hooks.compilation.tap("CreateRulesPlugin", compilation => {
+ compiler.hooks.compilation.tap("CreateRulesPlugin", (compilation) => {
compilation.hooks.processAssets.tap(
{
name: "CreateRulesPlugin",
stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
},
- assets => {
+ (_assets) => {
const ruleFileNames = fs.readdirSync(path.resolve(SOURCE_DIR, "rules"));
const rules = [];
let ruleId = 1;
diff --git a/config/webpack/plugins/inject-script-webpack-plugin.js b/config/webpack/plugins/inject-script-webpack-plugin.js
index 2b60022..16b2e98 100644
--- a/config/webpack/plugins/inject-script-webpack-plugin.js
+++ b/config/webpack/plugins/inject-script-webpack-plugin.js
@@ -1,29 +1,42 @@
-import webpack from "webpack";
import path from "path";
+import webpack from "webpack";
+
import { getFileName } from "../utils/build-file.js";
import { getInjectedCode } from "../utils/injected-code.js";
+/**
+ * Webpack plugin that post-processes every `.js` asset to replace
+ * extension-asset URL placeholders with runtime lookup code, and
+ * emits an additional "injected" script that the content script
+ * injects into the page via the script-injector module.
+ */
class InjectScriptPlugin {
+ /**
+ * @param {import("webpack").Compiler} compiler
+ * @returns {void}
+ */
apply(compiler) {
- compiler.hooks.compilation.tap("InjectScriptPlugin", compilation => {
+ compiler.hooks.compilation.tap("InjectScriptPlugin", (compilation) => {
compilation.hooks.processAssets.tapPromise(
{
name: "InjectScriptPlugin",
stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
additionalAssets: true
},
- async assets => {
+ async(assets) => {
for (const assetName in assets) {
if (/\.js$/.test(assetName)) {
- const injectedCodeResponse = getInjectedCode(compilation.getAsset(assetName).source.source())
+ const assetSource = compilation.getAsset(assetName).source.source();
+ const injectedCodeResponse = getInjectedCode(assetSource);
const scriptInjectorModuleName = getFileName("script-injector", "shared", true);
compilation.updateAsset(
assetName,
new webpack.sources.RawSource(injectedCodeResponse[0])
);
+ const injectedFileName = `scripts/injected/${path.basename(assetName)}`;
assets["scripts/" + path.basename(assetName)] = new webpack.sources.RawSource(
- `$${scriptInjectorModuleName}.injectScriptHead("scripts/injected/${path.basename(assetName)}", ${injectedCodeResponse[1]});`
+ `$${scriptInjectorModuleName}.injectScriptHead("${injectedFileName}", ${injectedCodeResponse[1]});`
);
}
}
diff --git a/config/webpack/utils/build-file.js b/config/webpack/utils/build-file.js
index 6945911..e09747d 100644
--- a/config/webpack/utils/build-file.js
+++ b/config/webpack/utils/build-file.js
@@ -1,6 +1,16 @@
import crypto from "crypto";
-export const getFileName = (fileName, prefix, justHash = false) => {
+/**
+ * Generates a deterministic output filename for a module.
+ * In production the result is a short MD5 hash; in development the
+ * original name is preserved alongside the hash for easier debugging.
+ *
+ * @param {string} fileName - The original module filename.
+ * @param {string} prefix - A namespace prefix (e.g. "shared", "injected").
+ * @param {boolean} justHash - When true, always return only the hash part.
+ * @returns {string} The transformed filename.
+ */
+export function getFileName(fileName, prefix, justHash = false) {
let hash = crypto
.createHash("md5")
.update(`${prefix}-${fileName}`)
diff --git a/config/webpack/utils/injected-code.js b/config/webpack/utils/injected-code.js
index a2884f6..f2e51c8 100644
--- a/config/webpack/utils/injected-code.js
+++ b/config/webpack/utils/injected-code.js
@@ -1,13 +1,29 @@
import crypto from "crypto";
-const getHash = url =>
+/**
+ * Computes an MD5 hash suffix (last 16 hex characters) for a given URL.
+ * Used to create unique attribute names for injected script data.
+ *
+ * @param {string} url - The URL to hash.
+ * @returns {string} A 16-character hex hash.
+ */
+const getHash = (url) =>
crypto
.createHash("md5")
.update(url)
.digest("hex")
.substring(16);
-export const getInjectedCode = code => {
+/**
+ * Transforms extension asset URL placeholders (`"$l{ url }l$"`) in the
+ * compiled JavaScript into `document.currentScript.getAttribute("data-<hash>")`
+ * lookups. The mapping of hashes to resolved `chrome.runtime.getURL()` calls
+ * is returned separately so the injector script can embed it as data attributes.
+ *
+ * @param {string} code - The compiled JavaScript bundle.
+ * @returns {[string, string]} A tuple of [transformedCode, extensionAssetsJSON].
+ */
+export function getInjectedCode(code) {
const extensionAssets = {};
let i = 0;
@@ -34,7 +50,7 @@ export const getInjectedCode = code => {
}
const extensionAssetsCode = Object.entries(extensionAssets).map(
- asset => `"${asset[0]}": chrome.runtime.getURL("${asset[1]}")`
+ (asset) => `"${asset[0]}": chrome.runtime.getURL("${asset[1]}")`
).join(",");
return [code, `{${extensionAssetsCode}}`];
diff --git a/config/webpack/utils/inline-javascript.js b/config/webpack/utils/inline-javascript.js
index 456dc11..501f852 100644
--- a/config/webpack/utils/inline-javascript.js
+++ b/config/webpack/utils/inline-javascript.js
@@ -1 +1,10 @@
-export const inlineJavascript = code => `data:text/javascript;base64,${Buffer.from(code).toString("base64")}`;
+/**
+ * Wraps JavaScript source code in a base64-encoded data URI so it can be
+ * used as an inline webpack entry point without writing a physical file.
+ *
+ * @param {string} code - The JavaScript source to inline.
+ * @returns {string} A `data:text/javascript;base64,…` URI.
+ */
+export function inlineJavascript(code) {
+ return `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
index a7c02f7..2745d54 100644
--- a/config/webpack/utils/script-runtime.js
+++ b/config/webpack/utils/script-runtime.js
@@ -1,4 +1,15 @@
-export const getScriptRuntimeFromType = scriptType => {
+/**
+ * Maps a human-readable script type to a Chrome content-script
+ * `run_at` value.
+ *
+ * - `"before"`, `"injected-after"`, `"injected-before"` → `document_start`
+ * - `"rendered"` → `document_end`
+ * - `"loaded"` (or unknown) → `document_idle`
+ *
+ * @param {string} scriptType - The script type from scripts.json.
+ * @returns {string} The corresponding `run_at` value.
+ */
+export function getScriptRuntimeFromType(scriptType) {
switch (scriptType) {
case "before":
case "injected-after":
diff --git a/config/webpack/utils/scripts.js b/config/webpack/utils/scripts.js
index af58e0a..d5a0cdc 100644
--- a/config/webpack/utils/scripts.js
+++ b/config/webpack/utils/scripts.js
@@ -1,10 +1,18 @@
-import path from "path";
import fs from "fs";
+import path from "path";
+/**
+ * Reads `src/scripts.json` and re-indexes it so the outer key is the
+ * URL path fragment and the inner key is the script type. This makes it
+ * trivial to look up which scripts run on which page.
+ *
+ * @returns {Record<string, Record<string, string[]>>} e.g.
+ * `{ "*": { "injected": ["stop-blocking.ts"] }, "MuteApplication.action": … }`
+ */
const scripts = JSON.parse(
fs.readFileSync(
- path.resolve("./src/scripts.json"),
- ),
+ path.resolve("./src/scripts.json")
+ )
);
const formattedScripts = {};
diff --git a/config/webpack/utils/shared-modules.js b/config/webpack/utils/shared-modules.js
index 2b16fa5..c9c9618 100644
--- a/config/webpack/utils/shared-modules.js
+++ b/config/webpack/utils/shared-modules.js
@@ -1,6 +1,12 @@
-import path from "path";
import fs from "fs";
+import path from "path";
+/**
+ * Scans `src/shared/` and returns the list of shared module filenames
+ * (with the `.ts` extension stripped), excluding `import-shared.js`.
+ *
+ * @returns {string[]} e.g. `["generate-web-page", "intercept-jquery-ajax", …]`
+ */
export default fs.readdirSync(path.resolve("src/shared"))
- .filter(sharedModule => !sharedModule.endsWith("import-shared.js"))
- .map(sharedModule => sharedModule.substring(0, sharedModule.length - 3));
+ .filter((sharedModule) => !sharedModule.endsWith("import-shared.js"))
+ .map((sharedModule) => sharedModule.substring(0, sharedModule.length - 3));