code wiki / _hdl_build / nx_web_render.nx

nx_web_render.nx source

↩ module page · 82 lines · 5474 B

1// nx_web_render.nx -- LIB: the WEB domain CONSUMER for the Nishi builder. Resolves web components from the 2// universal catalog by id and substitutes {KEY} bindings into live, sovereign HTML (no JS, no external fetch), 3// and composes a full page from several components. Closes the web loop: build -> teach -> grow -> CONSUME. 4// Boundary defense (rule 12): binding VALUES are HTML-escaped, so page data can't inject markup. license_tier: ORIGINAL 5import "nx_nishi_builder.nx" 6import "nx_ad_serve.nx" 7import "nx_syscalls.nx" 8 9// 1 if hay[i..] == key followed by '='. 10func nw_keyeq(hay: *u8, i: i64, key: *u8) -> i64 { 11 var j: i64 = 0 12 while key[j] != (0 as u8) { if hay[i+j] != key[j] { return 0 } j = j + 1 } 13 if hay[i+j] != (61 as u8) { return 0 } 14 return 1 15} 16// look up KEY in a "k1=v1|k2=v2|..." bindings string -> out (value until '|' or end). 1 found, 0 not. 17func nw_bind_get(bindings: *u8, key: *u8, out: *u8, cap: i64) -> i64 { 18 let kl: i64 = as_len(key) 19 var i: i64 = 0; var run: i64 = 1; var found: i64 = 0 20 while run == 1 { 21 if bindings[i] == (0 as u8) { run = 0 } else { 22 var boundary: i64 = 0 23 if i == 0 { boundary = 1 } else { if bindings[i-1] == (124 as u8) { boundary = 1 } } 24 if boundary == 1 { if nw_keyeq(bindings, i, key) == 1 { 25 var j: i64 = i + kl + 1; var o: i64 = 0; var vr: i64 = 1 26 while vr == 1 { if bindings[j] == (0 as u8) { vr = 0 } else { if bindings[j] == (124 as u8) { vr = 0 } else { if o < cap - 1 { out[o] = bindings[j]; o = o + 1 } j = j + 1 } } } 27 out[o] = 0 as u8; found = 1; run = 0 28 } } 29 i = i + 1 30 } 31 } 32 return found 33} 34// append a template to out, substituting {KEY} -> binding value (unknown keys drop). returns new off. 35func nw_render(out: *u8, off: i64, tpl: *u8, bindings: *u8) -> i64 { 36 var o: i64 = off; var i: i64 = 0 37 while tpl[i] != (0 as u8) { 38 var handled: i64 = 0 39 if tpl[i] == (123 as u8) { 40 var k: i64 = i + 1; var close: i64 = 0 - 1; var sc: i64 = 1 41 while sc == 1 { if tpl[k] == (0 as u8) { sc = 0 } else { if tpl[k] == (125 as u8) { close = k; sc = 0 } else { k = k + 1 } } } 42 if close >= 0 { 43 let key: *u8 = sys_mmap(64); var ko: i64 = 0; var p: i64 = i + 1 44 while p < close { if ko < 63 { key[ko] = tpl[p]; ko = ko + 1 } p = p + 1 } key[ko] = 0 as u8 45 let val: *u8 = sys_mmap(1024) 46 if nw_bind_get(bindings, key, val, 1024) == 1 { o = as_append(out, o, val) } 47 i = close + 1; handled = 1 48 } 49 } 50 if handled == 0 { out[o] = tpl[i]; o = o + 1; i = i + 1 } 51 } 52 return o 53} 54// resolve a web component (kind,id) from the catalog at `path` and render with `bindings` into out at off. 55func nw_emit_component(path: *u8, kind: *u8, id: *u8, bindings: *u8, out: *u8, off: i64) -> i64 { 56 let tpl: *u8 = sys_mmap(4096) 57 if nb_lookup(path, "web" as *u8, kind, id, tpl) == 0 { return off } 58 return nw_render(out, off, tpl, bindings) 59} 60// add "KEY=<escaped val>|" to a bindings buffer. (Boundary defense: value is HTML-escaped.) 61func nw_bind_add(buf: *u8, off: i64, key: *u8, val: *u8) -> i64 { 62 var o: i64 = as_append(buf, off, key); buf[o] = 61 as u8; o = o + 1 63 o = as_append_escaped(buf, o, val, as_len(val)); buf[o] = 124 as u8; o = o + 1 64 return o 65} 66 67// compose a full page from catalog components (nav + hero + footer). NUL-terminated into out; returns length. 68func nw_emit_page(path: *u8, brand: *u8, title: *u8, sub: *u8, cta: *u8, link: *u8, copyr: *u8, out: *u8) -> i64 { 69 var o: i64 = 0 70 o = as_append(out, o, "<!doctype html><html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>" as *u8) 71 o = as_append_escaped(out, o, title, as_len(title)) 72 o = as_append(out, o, "</title><style>body{margin:0;font-family:system-ui,sans-serif;color:#16202e}.topbar{display:flex;justify-content:space-between;align-items:center;padding:14px 24px;background:#0b2545;color:#fff}.topbar .brand{color:#fff;text-decoration:none;font-weight:700}.topbar .links a{color:#cfe;margin-left:16px;text-decoration:none}.hero{padding:64px 24px;text-align:center;background:#eef2f7}.hero h1{font-size:2rem;margin:0 0 8px}.btn{display:inline-block;margin-top:16px;padding:12px 22px;background:#0b2545;color:#fff;border-radius:8px;text-decoration:none}.ftr{padding:28px 24px;background:#0b2545;color:#cfe;text-align:center}.ftr nav a{color:#fff;margin:0 8px}</style></head><body>" as *u8) 73 let nb1: *u8 = sys_mmap(512); var b: i64 = nw_bind_add(nb1, 0, "BRAND" as *u8, brand); b = nw_bind_add(nb1, b, "LINKS" as *u8, "Home" as *u8); nb1[b] = 0 as u8 74 o = nw_emit_component(path, "nav" as *u8, "topbar" as *u8, nb1, out, o) 75 let nb2: *u8 = sys_mmap(1024); b = nw_bind_add(nb2, 0, "TITLE" as *u8, title); b = nw_bind_add(nb2, b, "SUB" as *u8, sub); b = nw_bind_add(nb2, b, "LINK" as *u8, link); b = nw_bind_add(nb2, b, "CTA" as *u8, cta); nb2[b] = 0 as u8 76 o = nw_emit_component(path, "section" as *u8, "hero" as *u8, nb2, out, o) 77 let nb3: *u8 = sys_mmap(512); b = nw_bind_add(nb3, 0, "COPY" as *u8, copyr); b = nw_bind_add(nb3, b, "LINKS" as *u8, "Privacy" as *u8); nb3[b] = 0 as u8 78 o = nw_emit_component(path, "section" as *u8, "footer" as *u8, nb3, out, o) 79 o = as_append(out, o, "</body></html>" as *u8) 80 out[o] = 0 as u8 81 return o 82}