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}