Restore the novel script's lost module-scope constants (#74) #75

Merged
sulthan merged 1 commits from fix/74-novel-missing-constants into main 2026-08-10 18:12:04 +07:00
2 changed files with 32 additions and 0 deletions
+7
View File
@@ -25,6 +25,13 @@
// This script owns the novel library; the manga script is a separate install
// with its own prefix, so the two never share a cache, a queue or a panel.
const STORE_PREFIX = "bmgr:novel:";
const CACHE_KEY = STORE_PREFIX + "cache";
// Per-device record of when each series was last checked for new chapters.
// Deliberately not synced: each device does its own checking.
const LASTCHECKED_KEY = STORE_PREFIX + "lastchecked";
const LATEST_CHECK_THROTTLE_MS = 4 * 60 * 60 * 1000;
const LATEST_CHECK_BATCH = 1; // series fetched per navigation // series fetched per navigation
// Which library this script's rows belong to. The manga script is a separate
// install that declares "manga"; the backend keeps whichever it is told.
+25
View File
@@ -165,3 +165,28 @@ test("kindOf defaults a missing kind to manga", () => {
test("kindOf passes through novel", () => {
assert.equal(kindOf({ kind: "novel" }), "novel");
});
// ============================================================
// Source guard
//
// Issue #74: the novel script was split off the manga one and lost four
// module-scope constants. The reads sit inside try/catch or a fire-and-forget
// promise, so the ReferenceError never surfaced — nothing but a static check
// catches this class.
// ============================================================
test("every SCREAMING_CASE constant the script uses is declared in it", () => {
const fs = require("node:fs");
for (const f of ["novel-bookmark.user.js", "manga-bookmark.user.js"]) {
const src = fs.readFileSync(require.resolve("../" + f), "utf8")
// comments and strings carry prose and SVG path data in the same shape
.replace(/\/\/[^\n]*|\/\*[\s\S]*?\*\/|"[^"\n]*"|'[^'\n]*'|`[\s\S]*?`/g, " ");
const declared = new Set(
[...src.matchAll(/\b(?:const|let|var|function)\s+([A-Z][A-Z0-9_]{2,})\b/g)].map((m) => m[1]),
);
for (const name of new Set(src.match(/\b[A-Z][A-Z0-9_]{2,}\b/g) || [])) {
if (name.startsWith("GM_") || name in globalThis) continue;
assert.ok(declared.has(name), `${f} uses ${name} but never declares it`);
}
}
});