Skip to content

Commit c26dc42

Browse files
kckernclaude
andcommitted
test(parity): JST latex, allowed only where live dropped verses Node prints
/jst.john.3.16, /jst.john.3.16;18 and /jst.john.3.16;john.3.16 in latex. Live read LDS only and printed nothing or only John 3:16; Node prints each block in its own version (decision 2026-10-23). allow.mjs gains a "re:<regex> && check:<name>" key; the latexMissingVerses check passes only when every live verse is in Node's output and Node has more, and the path must contain a JST piece. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 215ad9e commit c26dc42

4 files changed

Lines changed: 41 additions & 1 deletion

File tree

‎apps/web/test/parity/allow.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
"html re:^/([A-Za-z0-9*.]+/)?(\\d+|[1-4]?[A-Za-z&]+\\.?\\d+([.:]\\d+)+)[a-z]$": "Subverse letter on a reference-shaped path (book.chapter.verse or a verse id, then one letter: john.3.16a, kjv/1ne.3.7b, fax/1879l): PHP's /\\d[a-z]$/ drops the digit with the letter (john.3.16a is John 3:1); Node keeps the verse — owner decision not to reproduce",
1111
"html re:^/([A-Za-z0-9*.]+/)?(?![Gg][Ee][Nn])[A-Za-z]+(-[A-Za-z]+)+\\d+$ && live:<title>Genesis 1–50Exodus ": "Live expands unbounded multi-book ranges from junk URLs; Node caps the range to protect the server (controller decision 2026-10-20). Only paths shaped /[<version>/]<word>-<word><digit> whose first word is not Genesis, and only when live's title lists every book from Genesis 1 on: the unresolved start PHP read as verse 1 (about 2 MB). Node expands at most 1000 verses (the package's own limit) and shows the block as not found",
1212
"asset /js/main.js": "Google sign-in removed: dead on live (owner decision #11, 2026-10-22)",
13-
"* check:staleSectionHeading": "Live heads a passage whose first verse starts a section with § but not §¶ (a psalm superscription, NIV Ps. 23:1 \"§A psalm of David.¶▼…\", or after a division label, NET Ps. 90:1 \"Book 4 (Psalms 90-106)§A prayer…\") with the section before it (\"Psalm 22\" and an ellipsis on /niv/ps.23); Node heads it with the section at that verse, and a whole chapter that is one section gets section nav as with §¶; a label before §¶ (NIV Ps. 1:1 \"§Psalms 1–41§¶…\") keeps its passage without live's heading (owner decision 2026-10-22). Allowed only where live shows that heading and ellipsis ending right before the first verse, the first verse's live raw text starts a section, Node's heading is the raw heading with the section's range on live's tag, and nothing else differs but the nav labels of the same links"
13+
"* check:staleSectionHeading": "Live heads a passage whose first verse starts a section with § but not §¶ (a psalm superscription, NIV Ps. 23:1 \"§A psalm of David.¶▼…\", or after a division label, NET Ps. 90:1 \"Book 4 (Psalms 90-106)§A prayer…\") with the section before it (\"Psalm 22\" and an ellipsis on /niv/ps.23); Node heads it with the section at that verse, and a whole chapter that is one section gets section nav as with §¶; a label before §¶ (NIV Ps. 1:1 \"§Psalms 1–41§¶…\") keeps its passage without live's heading (owner decision 2026-10-22). Allowed only where live shows that heading and ellipsis ending right before the first verse, the first verse's live raw text starts a section, Node's heading is the raw heading with the section's range on live's tag, and nothing else differs but the nav labels of the same links",
14+
"latex re:(^|[/;])jst\\. && check:latexMissingVerses": "PHP latex read LDS only and dropped JST verses; Node renders each block's version (decision 2026-10-23). Only for references with a JST piece, and only where every live verse is in Node's output and Node has more (live empty or missing verses)"
1415
}

‎apps/web/test/parity/allow.mjs‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// "<format> live:<regex>": "reason" every request whose live body the regex matches (for live
66
// responses that are broken whatever the path, e.g. a PHP fatal error)
77
// "<format> re:<regex> && live:<regex>": "reason" both: the path and the live body
8+
// "<format> re:<regex> && check:<name>": "reason" both: the path and the check
89
// "<format> check:<name>": "reason" every request where the named check (CHECKS) passes on the
910
// compared responses ({ live, node } canonical, plus what
1011
// run.mjs looked up for it): for a known live bug that Node
@@ -20,15 +21,31 @@ const CHECKS = {
2021
// passage_script.php dropped the first verse of every later section (single_heading)
2122
// dropRaw: live's raw entries of the dropped verses (run.mjs singleHeadingRaw)
2223
singleHeadingDrop: ({ live, node, dropRaw }) => typeof live === 'string' && typeof node === 'string' && singleHeadingDrops(live, node, dropRaw),
24+
// PHP latex read the request's version only and dropped verses (JST) Node prints: every live
25+
// verse is in Node's output, and Node has more
26+
latexMissingVerses: ({ live, node }) => {
27+
if (typeof live !== 'string' || typeof node !== 'string') return false;
28+
const verses = text => [...text.matchAll(/\\versemarker\{\\thescriptureverse\}([^\\]*)/g)].map(m => m[1].trim());
29+
const l = verses(live), n = verses(node);
30+
return n.length > l.length && l.every(v => n.includes(v));
31+
},
2332
};
2433

2534
const PATTERN = /^(\S+) (re|live):(.*)$/s;
2635
const CHECK = /^(\S+) check:(\S+)$/;
2736
const BOTH = /^(\S+) re:(.*?) && live:(.*)$/s;
37+
const PATH_CHECK = /^(\S+) re:(.*?) && check:(\S+)$/s;
2838

2939
function compile(allow) {
3040
const patterns = [];
3141
for (const [key, reason] of Object.entries(allow)) {
42+
const pathCheck = key.match(PATH_CHECK);
43+
if (pathCheck) {
44+
try {
45+
if (CHECKS[pathCheck[3]]) patterns.push({ format: pathCheck[1], path: new RegExp(pathCheck[2]), check: CHECKS[pathCheck[3]], reason });
46+
} catch { /* ignored */ }
47+
continue;
48+
}
3249
const check = key.match(CHECK);
3350
if (check) {
3451
if (CHECKS[check[2]]) patterns.push({ format: check[1], check: CHECKS[check[2]], reason });

‎apps/web/test/parity/allow.test.js‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,21 @@ describe('allow.json: latex of junk pieces after a leading cross-book range', ()
108108
});
109109
});
110110

111+
112+
describe('allowReason: "<format> re:<regex> && check:<name>" (latex JST verses)', () => {
113+
const a = { 'latex re:(^|[/;])jst\\. && check:latexMissingVerses': 'PHP latex read LDS only' };
114+
const verse = t => `\\versenum \\marks\\versemarker{\\thescriptureverse}${t} `;
115+
const live = `STATUS 200\n\\begin{scripturechapter} ${verse('For God so loved the world.')}\\end{scripturechapter}`;
116+
const node = `STATUS 200\n\\begin{scripturechapter} ${verse('Only Begotten.')}\\end{scripturechapter}\n\\begin{scripturechapter} ${verse('For God so loved the world.')}\\end{scripturechapter}`;
117+
test('allowed when live lacks verses Node prints and has none Node lacks', () => {
118+
expect(allowReason(a, 'latex', '/jst.john.3.16;john.3.16', '', { live, node })).toBe('PHP latex read LDS only');
119+
expect(allowReason(a, 'latex', '/jst.john.3.16', '', { live: 'STATUS 200\n', node })).toBe('PHP latex read LDS only');
120+
});
121+
test('not when live has a verse Node lacks, or nothing is missing', () => {
122+
expect(allowReason(a, 'latex', '/jst.john.3.16;john.3.16', '', { live: live.replace('loved', 'hated'), node })).toBeUndefined();
123+
expect(allowReason(a, 'latex', '/jst.john.3.16;john.3.16', '', { live: node, node })).toBeUndefined();
124+
});
125+
test('not without a JST piece', () => {
126+
expect(allowReason(a, 'latex', '/john.3.16;1ne.1.1', '', { live, node })).toBeUndefined();
127+
});
128+
});

‎apps/web/test/parity/corpus.mjs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ const EXTRA = [
8585
['raw', '/john.3.16;jst.john.3.16;18'],
8686
['meta', '/jst.john.3.16;18'],
8787
['meta', '/john.3.16;jst.john.3.16;john.1.1'],
88+
// latex prints each block in its own version; live dropped JST verses (decision 2026-10-23)
89+
['latex', '/jst.john.3.16'],
90+
['latex', '/jst.john.3.16;18'],
91+
['latex', '/jst.john.3.16;john.3.16'],
8892
['raw', '/jst.john.3.16'],
8993
['passage', '/passage?ref=Malachi+4%3A6&version=KJV&hversion=KJV&options%5Bstart%5D=23144&options%5Bend%5D=23147&searchterm='],
9094
];

0 commit comments

Comments
 (0)