Illustrations/web/static/js/source-validator.v1.js

96 lines
3.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* source-validator.v1.js
Centralizes logic for deciding if a "Source" string should link to WOL.
Exposes:
- SourceValidator.isWOLSource(text) -> boolean
- SourceValidator.buildWOLSearchURL(text) -> string
*/
window.SourceValidator = (function () {
// Publications / codes that produce valid WOL links.
// Added: uw, su, re, lvs, rs (rs was already present).
const PUB_CODES = [
"wp","ws","yb","mwb","w","g","ap","apf","be","bh","br","bt","btg","cf","cl","ct","dp",
"fg","fy","gt","hb","im","ip","it","jv","ka","kj","kl","lf","lff","ll","ly","my","od",
"pe","po","pt","rr","rs","sg","sh","si","td","tp","tr","ts","un","jy",
"uw","su","re","lvs","lp","yy","yp2","yp"// new
];
// Year validation rules (applies only if a year can be parsed from the source).
// Watchtower (w/wp/ws) back to 1950; Awake (g) back to 1970.
const YEAR_RULES = [
{ codes: ["w","wp","ws"], minYear: 1950 },
{ codes: ["g"], minYear: 1970 }
];
// Normalize helper
function normalize(s) { return (s || "").trim().toLowerCase(); }
// Choose the longest matching code at the start (so "ws" beats "w").
const PUB_CODES_SORTED = [...PUB_CODES].sort((a,b)=>b.length-a.length);
function leadingCode(textLower) {
for (const code of PUB_CODES_SORTED) {
if (textLower.startsWith(code)) return code;
}
return null;
}
// Try to extract a year that appears right after the leading code (allow spaces),
// accepting either 4-digit (e.g., 1955, 2001) or 2-digit (e.g., 55, 95, 12) forms.
function extractYearAfterCode(textLower, code) {
let s = textLower.slice(code.length).trim();
// 1) Look for a 4-digit year first
let m = s.match(/\b(1[89]\d{2}|20\d{2})\b/); // 1800-2099 (broad, but OK)
if (m) {
return parseInt(m[1], 10);
}
// 2) If not found, accept a 2-digit year at the *start* of the remainder,
// or right after an optional space: e.g., "w55 1/1", "w 95", "g70 1/22"
m = s.match(/^\s*(\d{2})\b/);
if (m) {
const yy = parseInt(m[1], 10);
// Infer century based on publication + threshold logic
// - For Watchtower: 5099 -> 19501999; 0049 -> 20002049
// - For Awake: 7099 -> 19701999; 0069 -> 20002069
if (code === "g") {
return yy >= 70 ? (1900 + yy) : (2000 + yy);
}
if (code === "w" || code === "wp" || code === "ws") {
return yy >= 50 ? (1900 + yy) : (2000 + yy);
}
// For other pubs, if they ever include 2-digit years, assume 1900+yy≥70 else 2000+yy
return yy >= 70 ? (1900 + yy) : (2000 + yy);
}
// No recognizable year → don't enforce year limits
return null;
}
function passesYearRuleIfPresent(textLower, code) {
const rule = YEAR_RULES.find(r => r.codes.includes(code));
if (!rule) return true; // no year rule for this pub
const y = extractYearAfterCode(textLower, code);
if (y == null) return true; // no year present → allow
return y >= rule.minYear;
}
function isWOLSource(text) {
const t = normalize(text);
if (!t) return false;
const code = leadingCode(t);
if (!code) return false;
// If starts with a known pub code, its WOL-capable — but enforce year rules where applicable.
return passesYearRuleIfPresent(t, code);
}
function buildWOLSearchURL(text) {
const q = encodeURIComponent(text || "");
return `https://wol.jw.org/en/wol/l/r1/lp-e?q=${q}`;
}
return { isWOLSource, buildWOLSearchURL };
})();