code wiki / _hdl_build / nx_css_extract_test.nx
nx_css_extract_test.nx source
↩ module page · 111 lines · 5808 B
1// nx_css_extract_test.nx -- styling rung 1: extract a CssElement[] (tag/id/class per element, in
2// document order) automatically from real HTML, so the cascade (nx_css_apply) has something to match.
3// Today CssElement[] is hand-built (css_apply_test); this is the missing auto-extractor. Composes the
4// gated nx_html_tokenizer (element walk) + nx_dom_query (nx_dom_find_attr for id/class). Self-contained
5// + gated; the function moves to a library when wired into the render. expect_exit: 0.
6import "nx_syscalls.nx"
7import "nx_html_tokenizer.nx"
8import "nx_dom_query.nx"
9import "nx_css_selector_match.nx"
10
11// HTML bytes -> CssElement[] (one per START_TAG / SELF_CLOSING, document order). Returns count.
12func nx_css_extract_elements(html: *u8, hlen: i64, elements: *CssElement, maxn: i64) -> i64 {
13 let c: *HtmlCursor = sys_mmap(24) as *HtmlCursor
14 nx_html_cursor_init(c, html, hlen)
15 let tok: *HtmlToken = sys_mmap(56) as *HtmlToken
16 let ioff: *i64 = sys_mmap(8) as *i64
17 let ilen: *i64 = sys_mmap(8) as *i64
18 let coff: *i64 = sys_mmap(8) as *i64
19 let clen: *i64 = sys_mmap(8) as *i64
20 var n: i64 = 0
21 while 1 == 1 {
22 nx_html_next_token(c, tok)
23 if tok.kind == NX_HTML_TOK_EOF { return n }
24 if n >= maxn { return n }
25 var is_elem: i64 = 0
26 if tok.kind == NX_HTML_TOK_START_TAG { is_elem = 1 }
27 if tok.kind == NX_HTML_TOK_SELF_CLOSING { is_elem = 1 }
28 if is_elem == 1 {
29 let e: *CssElement = ((elements as i64) + n * NX_CSS_ELEMENT_BYTES) as *CssElement
30 e.src = html
31 e.tag_off = tok.name_off
32 e.tag_len = tok.name_len
33 if nx_dom_find_attr(html, tok.src_off, tok.src_len, "id\x00" as *u8, ioff, ilen) == 1 {
34 e.id_off = ioff[0]; e.id_len = ilen[0]
35 } else { e.id_off = 0; e.id_len = 0 }
36 if nx_dom_find_attr(html, tok.src_off, tok.src_len, "class\x00" as *u8, coff, clen) == 1 {
37 e.class_off = coff[0]; e.class_len = clen[0]
38 } else { e.class_off = 0; e.class_len = 0 }
39 n = n + 1
40 }
41 }
42 return n
43}
44
45// ===================== GATE =====================
46func ce_puts(s: *u8) -> i64 { var k: i64=0; while s[k]!=(0 as u8){k=k+1} sys_write(1,s,k); return 0 }
47func ce_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 }
48// does element e's tag byte-equal the literal `lit`?
49func ce_tag_is(e: *CssElement, lit: *u8) -> i64 {
50 var ll: i64 = 0
51 while lit[ll] != (0 as u8) { ll = ll + 1 }
52 if e.tag_len != ll { return 0 }
53 var i: i64 = 0
54 while i < ll { if (e.src[e.tag_off + i] & 0xff) != (lit[i] & 0xff) { return 0 } i = i + 1 }
55 return 1
56}
57func ce_val_is(src: *u8, off: i64, len: i64, lit: *u8) -> i64 {
58 var ll: i64 = 0
59 while lit[ll] != (0 as u8) { ll = ll + 1 }
60 if len != ll { return 0 }
61 var i: i64 = 0
62 while i < ll { if (src[off + i] & 0xff) != (lit[i] & 0xff) { return 0 } i = i + 1 }
63 return 1
64}
65func el_at(elements: *CssElement, i: i64) -> *CssElement { return ((elements as i64) + i * NX_CSS_ELEMENT_BYTES) as *CssElement }
66
67func main() -> i64 {
68 let html: *u8 = "<html><body><h1 id='t' class='title big'>Hi</h1><p>x</p><a href='/y'>L</a><img id='im' src='/p.png'></body></html>\x00"
69 var hlen: i64 = 0
70 while html[hlen] != (0 as u8) { hlen = hlen + 1 }
71 let elements: *CssElement = (sys_mmap(NX_CSS_ELEMENT_BYTES * 64) as nx_size) as *CssElement
72 let n: i64 = nx_css_extract_elements(html, hlen, elements, 64)
73
74 var pass: i64 = 0
75 var tot: i64 = 0
76 ce_puts("nx_css_extract gate (styling rung 1: HTML -> CssElement[] tag/id/class)\n" as *u8)
77
78 // ---- KAT1: element COUNT (html, body, h1, p, a, img = 6) ----
79 var r1: i64 = 0
80 if n == 6 { r1 = 1 }
81 if r1 == 1 { ce_puts(" PASS KAT1 element count = 6 (html/body/h1/p/a/img incl void)\n" as *u8); pass=pass+1 } else { ce_puts(" FAIL KAT1 count = " as *u8); ce_pn(n); ce_puts("\n" as *u8) }
82 tot = tot + 1
83
84 // ---- KAT2: tags in document order ----
85 var r2: i64 = 1
86 if ce_tag_is(el_at(elements, 0), "html\x00" as *u8) == 0 { r2 = 0 }
87 if ce_tag_is(el_at(elements, 1), "body\x00" as *u8) == 0 { r2 = 0 }
88 if ce_tag_is(el_at(elements, 2), "h1\x00" as *u8) == 0 { r2 = 0 }
89 if ce_tag_is(el_at(elements, 3), "p\x00" as *u8) == 0 { r2 = 0 }
90 if ce_tag_is(el_at(elements, 4), "a\x00" as *u8) == 0 { r2 = 0 }
91 if ce_tag_is(el_at(elements, 5), "img\x00" as *u8) == 0 { r2 = 0 }
92 if r2 == 1 { ce_puts(" PASS KAT2 tags in document order: html,body,h1,p,a,img\n" as *u8); pass=pass+1 } else { ce_puts(" FAIL KAT2 tag order\n" as *u8) }
93 tot = tot + 1
94
95 // ---- KAT3: id + class extracted (h1 id='t' class='title big'); p has neither ----
96 let h1: *CssElement = el_at(elements, 2)
97 var r3: i64 = ce_val_is(html, h1.id_off, h1.id_len, "t\x00" as *u8)
98 if ce_val_is(html, h1.class_off, h1.class_len, "title big\x00" as *u8) == 0 { r3 = 0 }
99 let img: *CssElement = el_at(elements, 5)
100 if ce_val_is(html, img.id_off, img.id_len, "im\x00" as *u8) == 0 { r3 = 0 } // void elem id too
101 let p: *CssElement = el_at(elements, 3)
102 if p.id_len != 0 { r3 = 0 } // p has no id
103 if p.class_len != 0 { r3 = 0 } // p has no class
104 if r3 == 1 { ce_puts(" PASS KAT3 id+class extracted (h1 id=t class='title big', img id=im, p none)\n" as *u8); pass=pass+1 } else { ce_puts(" FAIL KAT3 id/class\n" as *u8) }
105 tot = tot + 1
106
107 ce_puts("---- nx_css_extract gate: passed " as *u8); ce_pn(pass); ce_puts(" / " as *u8); ce_pn(tot); ce_puts("\n" as *u8)
108 if pass == tot { sys_exit(0); return 0 }
109 sys_exit(1)
110 return 1
111}