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}