aboutsummaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
Diffstat (limited to 'config')
-rw-r--r--config/webpack.config.js14
-rw-r--r--config/webpack/loader/arrange-shared-module-loader.js9
-rw-r--r--config/webpack/loader/count-imports-loader.js8
-rw-r--r--config/webpack/loader/to-string-loader.js10
-rw-r--r--config/webpack/plugins/create-injected-shared-modules-webpack-plugin.js12
-rw-r--r--config/webpack/plugins/create-manifest-webpack-plugin/index.js19
-rw-r--r--config/webpack/plugins/create-rules-webpack-plugin.js8
-rw-r--r--config/webpack/plugins/inject-script-webpack-plugin.js9
-rw-r--r--config/webpack/utils/build-file.js10
-rw-r--r--config/webpack/utils/injected-code.js16
-rw-r--r--config/webpack/utils/inline-javascript.js7
-rw-r--r--config/webpack/utils/script-runtime.js11
-rw-r--r--config/webpack/utils/scripts.js8
-rw-r--r--config/webpack/utils/shared-modules.js6
14 files changed, 147 insertions, 0 deletions
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 8fd3f15..347d204 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -1,3 +1,17 @@
+/**
+ * Webpack configuration for the Banglar Bhumi Utils Chrome extension.
+ *
+ * Produces four separate bundles:
+ * 1. **Background script** – service worker entry point.
+ * 2. **Uninjected scripts** – content scripts that run as-is.
+ * 3. **Injected scripts** – content scripts that are further processed
+ * so they can be injected into the page DOM.
+ * 4. **Shared modules** – libraries compiled as standalone files and
+ * referenced via global variables (`$<hash>`).
+ *
+ * Custom loaders and plugins handle dependency ordering, import counting,
+ * asset-URL rewriting, manifest generation, and declarative-net-rule creation.
+ */
import path from "path";
import fs from "fs";
import { fileURLToPath } from "url";
diff --git a/config/webpack/loader/arrange-shared-module-loader.js b/config/webpack/loader/arrange-shared-module-loader.js
index 2265185..d4c22a9 100644
--- a/config/webpack/loader/arrange-shared-module-loader.js
+++ b/config/webpack/loader/arrange-shared-module-loader.js
@@ -3,6 +3,15 @@ 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));
diff --git a/config/webpack/loader/count-imports-loader.js b/config/webpack/loader/count-imports-loader.js
index 2586332..3342921 100644
--- a/config/webpack/loader/count-imports-loader.js
+++ b/config/webpack/loader/count-imports-loader.js
@@ -1,6 +1,14 @@
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..244ae7a 100644
--- a/config/webpack/loader/to-string-loader.js
+++ b/config/webpack/loader/to-string-loader.js
@@ -1,3 +1,13 @@
+/**
+ * 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("\\", "\\\\")
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..2adb017 100644
--- a/config/webpack/plugins/create-injected-shared-modules-webpack-plugin.js
+++ b/config/webpack/plugins/create-injected-shared-modules-webpack-plugin.js
@@ -4,12 +4,24 @@ 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
+ */
apply(compiler) {
compiler.hooks.compilation.tap("CreateInjectedSharedModulesPlugin", compilation => {
compilation.hooks.processAssets.tap(
diff --git a/config/webpack/plugins/create-manifest-webpack-plugin/index.js b/config/webpack/plugins/create-manifest-webpack-plugin/index.js
index 6f1e2be..f012f1e 100644
--- a/config/webpack/plugins/create-manifest-webpack-plugin/index.js
+++ b/config/webpack/plugins/create-manifest-webpack-plugin/index.js
@@ -11,13 +11,32 @@ const manifest = JSON.parse(
),
);
+/**
+ * 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
+ */
apply(compiler) {
compiler.hooks.compilation.tap("CreateManifestPlugin", compilation => {
compilation.hooks.processAssets.tap(
diff --git a/config/webpack/plugins/create-rules-webpack-plugin.js b/config/webpack/plugins/create-rules-webpack-plugin.js
index 5573ddf..55b60f7 100644
--- a/config/webpack/plugins/create-rules-webpack-plugin.js
+++ b/config/webpack/plugins/create-rules-webpack-plugin.js
@@ -2,7 +2,15 @@ import path from "path";
import fs from "fs";
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
+ */
apply(compiler) {
compiler.hooks.compilation.tap("CreateRulesPlugin", compilation => {
compilation.hooks.processAssets.tap(
diff --git a/config/webpack/plugins/inject-script-webpack-plugin.js b/config/webpack/plugins/inject-script-webpack-plugin.js
index 2b60022..43c5d9f 100644
--- a/config/webpack/plugins/inject-script-webpack-plugin.js
+++ b/config/webpack/plugins/inject-script-webpack-plugin.js
@@ -4,7 +4,16 @@ import path from "path";
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
+ */
apply(compiler) {
compiler.hooks.compilation.tap("InjectScriptPlugin", compilation => {
compilation.hooks.processAssets.tapPromise(
diff --git a/config/webpack/utils/build-file.js b/config/webpack/utils/build-file.js
index 6945911..17f0b03 100644
--- a/config/webpack/utils/build-file.js
+++ b/config/webpack/utils/build-file.js
@@ -1,5 +1,15 @@
import crypto from "crypto";
+/**
+ * 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 const getFileName = (fileName, prefix, justHash = false) => {
let hash = crypto
.createHash("md5")
diff --git a/config/webpack/utils/injected-code.js b/config/webpack/utils/injected-code.js
index a2884f6..2b8f750 100644
--- a/config/webpack/utils/injected-code.js
+++ b/config/webpack/utils/injected-code.js
@@ -1,5 +1,12 @@
import crypto from "crypto";
+/**
+ * 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")
@@ -7,6 +14,15 @@ const getHash = url =>
.digest("hex")
.substring(16);
+/**
+ * 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 const getInjectedCode = code => {
const extensionAssets = {};
let i = 0;
diff --git a/config/webpack/utils/inline-javascript.js b/config/webpack/utils/inline-javascript.js
index 456dc11..205bda4 100644
--- a/config/webpack/utils/inline-javascript.js
+++ b/config/webpack/utils/inline-javascript.js
@@ -1 +1,8 @@
+/**
+ * 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 const 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
index a7c02f7..1c23922 100644
--- a/config/webpack/utils/script-runtime.js
+++ b/config/webpack/utils/script-runtime.js
@@ -1,3 +1,14 @@
+/**
+ * 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 const getScriptRuntimeFromType = scriptType => {
switch (scriptType) {
case "before":
diff --git a/config/webpack/utils/scripts.js b/config/webpack/utils/scripts.js
index af58e0a..09a2fc0 100644
--- a/config/webpack/utils/scripts.js
+++ b/config/webpack/utils/scripts.js
@@ -1,6 +1,14 @@
import path from "path";
import fs from "fs";
+/**
+ * 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"),
diff --git a/config/webpack/utils/shared-modules.js b/config/webpack/utils/shared-modules.js
index 2b16fa5..74ee555 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";
+/**
+ * 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));