code wiki / _hdl_build / nx_fold_punct_gate.nx

nx_fold_punct_gate.nx source

↩ module page · 59 lines · 3572 B

1// nx_fold_punct_gate.nx -- regression gate for the browser text pipeline: HTML entity DECODE -> UTF-8 2// -> ASCII FOLD, the exact path br_draw_fb paints. Locks the 2026-07-10 fix that made typographic 3// punctuation (&mdash; &middot; &rsquo; &rsaquo; &hellip; arrows) render instead of vanishing to blank 4// gaps in the 5x7 font, WITHOUT regressing accent-fold (é->e) or ASCII passthrough. Found by dogfooding 5// the Nishi browser on our own /compare pages. license_tier: ORIGINAL expect_exit: 0 6import "nx_html_entities.nx" 7 8func fg_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 9func fg_check(pass: i64, label: *u8, fails: *i64) -> i64 { 10 fg_w(" " as *u8); fg_w(label); fg_w(": " as *u8) 11 if pass==1 { fg_w("PASS\n" as *u8) } else { fg_w("FAIL\n" as *u8); fails[0]=fails[0]+1 } 12 return 0 13} 14// decode src (an entity-bearing string) then fold to ASCII; compare to want. returns 1 match. 15func fg_pipe_eq(src: *u8, slen: i64, want: *u8) -> i64 { 16 let dec: *u8 = sys_mmap(1024) 17 let fold: *u8 = sys_mmap(1024) 18 let dn: i64 = nx_html_decode_entities(src, 0, slen, dec, 1024) 19 let fn: i64 = nx_fold_ascii(dec, 0, dn, fold, 1024) 20 var wl: i64 = 0 21 while want[wl]!=(0 as u8) { wl=wl+1 } 22 if fn != wl { return 0 } 23 var i: i64=0 24 while i<fn { if fold[i]!=want[i] { return 0 } i=i+1 } 25 return 1 26} 27 28func main() -> i64 { 29 let fails: *i64 = sys_mmap(16) as *i64 30 fails[0]=0 31 fg_w("=== nx_fold_punct_gate -- entity-decode -> ASCII-fold (the browser paint pipeline) ===\n" as *u8) 32 33 // the FIX: typographic punctuation now folds to a readable ASCII byte (was blank) 34 fg_check(fg_pipe_eq("a&mdash;b" as *u8, 9, "a-b" as *u8), "T1 &mdash; -> '-' (was blank gap)" as *u8, fails) 35 fg_check(fg_pipe_eq("a&middot;b" as *u8, 10, "a*b" as *u8), "T2 &middot; -> '*'" as *u8, fails) 36 fg_check(fg_pipe_eq("it&rsquo;s" as *u8, 10, "it's" as *u8), "T3 &rsquo; -> apostrophe" as *u8, fails) 37 fg_check(fg_pipe_eq("A&rsaquo;B" as *u8, 10, "A>B" as *u8), "T4 &rsaquo; -> '>' (was undecoded literal)" as *u8, fails) 38 fg_check(fg_pipe_eq("x&hellip;" as *u8, 9, "x." as *u8), "T5 &hellip; -> '.'" as *u8, fails) 39 fg_check(fg_pipe_eq("&larr;&rarr;" as *u8, 12, "<>" as *u8), "T6 arrows &larr;&rarr; -> '<' '>'" as *u8, fails) 40 fg_check(fg_pipe_eq("&ldquo;hi&rdquo;" as *u8, 16, "\x22hi\x22" as *u8), "T7 curly quotes -> straight quotes" as *u8, fails) 41 42 // NO REGRESSION: accents still fold to base letter; ASCII passes through 43 fg_check(fg_pipe_eq("caf&eacute;" as *u8, 11, "cafe" as *u8), "T8 &eacute; -> 'e' (accent fold intact)" as *u8, fails) 44 fg_check(fg_pipe_eq("plain text" as *u8, 10, "plain text" as *u8), "T9 ASCII passthrough unchanged" as *u8, fails) 45 fg_check(fg_pipe_eq("a&amp;b&lt;c" as *u8, 12, "a&b<c" as *u8), "T10 core entities &amp;&lt; still decode" as *u8, fails) 46 47 // NEG-CONTROL: non-Latin (Cyrillic UTF-8) cleanly SKIPS (no byte-gaps), not garbage 48 let cyr: *u8 = sys_mmap(16) 49 cyr[0]=0xD0 as u8; cyr[1]=0xBF as u8; cyr[2]=0xD0 as u8; cyr[3]=0xB0 as u8 // "па" (2 Cyrillic cps) 50 let fold: *u8 = sys_mmap(64) 51 let fn: i64 = nx_fold_ascii(cyr, 0, 4, fold, 64) 52 fg_check((fn==0) as i64, "T11 NEG Cyrillic folds to empty (skipped clean, no blank-gap bytes)" as *u8, fails) 53 54 fg_w(" fails=" as *u8) 55 if fails[0]==0 { fg_w("0\nVERDICT: GREEN (punctuation renders; accents + ASCII + core entities intact; non-Latin skips clean)\n" as *u8); sys_exit(0) } 56 fg_w("nonzero\nVERDICT: RED\n" as *u8) 57 sys_exit(1) 58 return 1 59}