code wiki / _hdl_build / nx_css_cascade_test.nx

nx_css_cascade_test.nx source

↩ module page · 136 lines · 6830 B

1// nx_css_cascade_test.nx -- styling rung 2: HTML + a UA stylesheet -> per-element COMPUTED styles. 2// The cascade (nx_css_apply / nx_css_selector_match) requires rules + elements to share ONE src buffer, 3// so we build a combined [HTML][CSS] buffer: element tag offsets land in the HTML part, rule selector 4// offsets in the CSS part, one shared src -> selector "h1" byte-matches tag "h1". Composes the rung-1 5// extractor + nx_css_tokenize/parse + nx_css_apply. expect_exit: 0. 6import "nx_syscalls.nx" 7import "nx_html_tokenizer.nx" 8import "nx_dom_query.nx" 9import "nx_css_selector_match.nx" 10import "nx_css_tokenize.nx" 11import "nx_css_parse.nx" 12import "nx_css_apply.nx" 13 14func cc_slen(s: *u8) -> i64 { var k: i64 = 0; while s[k] != (0 as u8) { k = k + 1 } return k } 15func cc_puts(s: *u8) -> i64 { sys_write(1, s, cc_slen(s)); return 0 } 16func cc_pn(v: i64) -> i64 { let b: *u8=sys_mmap(20); var m: i64=v; let t: *u8=sys_mmap(20); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=48+(m%10);m=m/10;k=k+1}; var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1}; sys_write(1,b,k); return 0 } 17 18// rung-1 extractor (self-contained here; moves to a library when wired into the render). 19func cc_extract(html: *u8, hlen: i64, elements: *CssElement, maxn: i64) -> i64 { 20 let c: *HtmlCursor = sys_mmap(24) as *HtmlCursor 21 nx_html_cursor_init(c, html, hlen) 22 let tok: *HtmlToken = sys_mmap(56) as *HtmlToken 23 let ao: *i64 = sys_mmap(8) as *i64 24 let al: *i64 = sys_mmap(8) as *i64 25 let bo: *i64 = sys_mmap(8) as *i64 26 let bl: *i64 = sys_mmap(8) as *i64 27 var n: i64 = 0 28 while 1 == 1 { 29 nx_html_next_token(c, tok) 30 if tok.kind == NX_HTML_TOK_EOF { return n } 31 if n >= maxn { return n } 32 var is_elem: i64 = 0 33 if tok.kind == NX_HTML_TOK_START_TAG { is_elem = 1 } 34 if tok.kind == NX_HTML_TOK_SELF_CLOSING { is_elem = 1 } 35 if is_elem == 1 { 36 let e: *CssElement = ((elements as i64) + n * NX_CSS_ELEMENT_BYTES) as *CssElement 37 e.src = html 38 e.tag_off = tok.name_off 39 e.tag_len = tok.name_len 40 if nx_dom_find_attr(html, tok.src_off, tok.src_len, "id\x00" as *u8, ao, al) == 1 { e.id_off = ao[0]; e.id_len = al[0] } else { e.id_off = 0; e.id_len = 0 } 41 if nx_dom_find_attr(html, tok.src_off, tok.src_len, "class\x00" as *u8, bo, bl) == 1 { e.class_off = bo[0]; e.class_len = bl[0] } else { e.class_off = 0; e.class_len = 0 } 42 n = n + 1 43 } 44 } 45 return n 46} 47 48// does the combined-buffer region [off,off+len) byte-equal NUL-terminated lit? 49func cc_region_is(src: *u8, off: i64, len: i64, lit: *u8) -> i64 { 50 let ll: i64 = cc_slen(lit) 51 if len != ll { return 0 } 52 var i: i64 = 0 53 while i < ll { if (src[off + i] & 0xff) != (lit[i] & 0xff) { return 0 } i = i + 1 } 54 return 1 55} 56 57func main() -> i64 { 58 let htmls: *u8 = "<html><body><h1 id='t'>Hi</h1><a href='/y'>L</a><p>x</p></body></html>\x00" 59 let csss: *u8 = "h1{font-size:32px}a{color:#0000ff}\x00" 60 let hlen: i64 = cc_slen(htmls) 61 let clen: i64 = cc_slen(csss) 62 let total: i64 = hlen + clen 63 64 // combined [HTML][CSS] buffer, shared src for tags + selectors 65 let buf: *u8 = sys_mmap(total + 16) 66 var i: i64 = 0 67 while i < hlen { buf[i] = htmls[i]; i = i + 1 } 68 i = 0 69 while i < clen { buf[hlen + i] = csss[i]; i = i + 1 } 70 71 // rung-1: elements from the HTML part (el.src = combined buffer) 72 let elements: *CssElement = (sys_mmap(NX_CSS_ELEMENT_BYTES * 64) as nx_size) as *CssElement 73 let n_elem: i64 = cc_extract(buf, hlen, elements, 64) 74 75 // parse the CSS region (cursor positioned at hlen) -> rules + decls (offsets in the CSS part) 76 let cur: *CssCursor = (sys_mmap(NX_CSS_CURSOR_BYTES) as nx_size) as *CssCursor 77 nx_css_cursor_init(cur, buf, total) 78 cur.pos = hlen 79 let tok: *CssToken = (sys_mmap(NX_CSS_TOKEN_BYTES) as nx_size) as *CssToken 80 let rules: *CssRule = (sys_mmap(NX_CSS_RULE_BYTES * 32) as nx_size) as *CssRule 81 let decls: *CssDeclaration = (sys_mmap(NX_CSS_DECLARATION_BYTES * 64) as nx_size) as *CssDeclaration 82 let st: *CssParseState = (sys_mmap(128) as nx_size) as *CssParseState 83 nx_css_parse_state_init(st, cur, tok, rules, 32, decls, 64) 84 let prc: i64 = nx_css_parse(st) 85 86 // cascade: rules x elements -> computed (element_idx + prop + val), shared src = combined buffer 87 let computed: *CssComputedDecl = (sys_mmap(NX_CSS_COMPUTED_DECL_BYTES * 128) as nx_size) as *CssComputedDecl 88 let cb: *i64 = (sys_mmap(8)) as *i64 89 let arc: i64 = nx_css_apply(buf, rules, st.rule_count, decls, st.decl_count, elements, n_elem, computed, 128, cb) 90 let ncomp: i64 = cb[0] 91 92 var pass: i64 = 0 93 var tot: i64 = 0 94 cc_puts("nx_css_cascade gate (styling rung 2: HTML + UA stylesheet -> computed styles)\n" as *u8) 95 96 // ---- KAT1: parse produced 2 rules ---- 97 var r1: i64 = 0 98 if st.rule_count == 2 { r1 = 1 } 99 if r1 == 1 { cc_puts(" PASS KAT1 parsed 2 rules (h1, a)\n" as *u8); pass=pass+1 } else { cc_puts(" FAIL KAT1 rules=" as *u8); cc_pn(st.rule_count); cc_puts(" parse_rc=" as *u8); cc_pn(prc); cc_puts("\n" as *u8) } 100 tot = tot + 1 101 102 // ---- KAT2: cascade produced computed decls; h1(el 2) gets font-size:32px ---- 103 var r2: i64 = 0 104 var j: i64 = 0 105 while j < ncomp { 106 let cd: *CssComputedDecl = ((computed as i64) + j * NX_CSS_COMPUTED_DECL_BYTES) as *CssComputedDecl 107 if cd.element_idx == 2 { 108 if cc_region_is(buf, cd.prop_off, cd.prop_len, "font-size\x00" as *u8) == 1 { 109 if cc_region_is(buf, cd.val_off, cd.val_len, "32\x00" as *u8) == 1 { r2 = 1 } // dimension: val="32", unit="px" separate 110 } 111 } 112 j = j + 1 113 } 114 if r2 == 1 { cc_puts(" PASS KAT2 h1 (element 2) computed font-size = 32px\n" as *u8); pass=pass+1 } else { cc_puts(" FAIL KAT2 h1 font-size (ncomp=" as *u8); cc_pn(ncomp); cc_puts(" apply_rc=" as *u8); cc_pn(arc); cc_puts(")\n" as *u8) } 115 tot = tot + 1 116 117 // ---- KAT3: a(el 3) gets color #0000ff ---- 118 var r3: i64 = 0 119 j = 0 120 while j < ncomp { 121 let cd: *CssComputedDecl = ((computed as i64) + j * NX_CSS_COMPUTED_DECL_BYTES) as *CssComputedDecl 122 if cd.element_idx == 3 { 123 if cc_region_is(buf, cd.prop_off, cd.prop_len, "color\x00" as *u8) == 1 { 124 if cc_region_is(buf, cd.val_off, cd.val_len, "0000ff\x00" as *u8) == 1 { r3 = 1 } 125 } 126 } 127 j = j + 1 128 } 129 if r3 == 1 { cc_puts(" PASS KAT3 a (element 3) computed color = #0000ff\n" as *u8); pass=pass+1 } else { cc_puts(" FAIL KAT3 a color\n" as *u8) } 130 tot = tot + 1 131 132 cc_puts("---- nx_css_cascade gate: passed " as *u8); cc_pn(pass); cc_puts(" / " as *u8); cc_pn(tot); cc_puts("\n" as *u8) 133 if pass == tot { sys_exit(0); return 0 } 134 sys_exit(1) 135 return 1 136}