code wiki / (root) / nx_hub_emit.nx

nx_hub_emit.nx source

↩ module page · 189 lines · 6976 B

1// nx_hub_emit.nx -- sovereign emitter: content/hub.cards -> dist/hub/index.html 2// 3// Built per operator directive 2026-06-30 ("build the apis that will do 4// what you'd do in shell"). Data-driven: the card set lives in the 5// pipe-delimited manifest content/hub.cards (the SSOT); editing it + re- 6// running this organ regenerates the s-class hub page. Reuses the site's 7// .app-grid / .app-card CSS (so it matches the homepage) + a no-dependency 8// client-side search filter. "soon" cards render disabled (no dead link). 9// 10// File-I/O only -> imports the leaf x86_64 syscall layer ONLY (builds 11// clean; see [[nishi-serving-syscall-dup-gotcha]]). Run from the 12// nishi-pages checkout (so content/ + dist/ resolve); dist/hub must exist. 13// 14// Build: ./nxc2.exe --target x86_64 runtime/nx_hub_emit.nx > /tmp/he.s 15// wsl bash -c "gcc -no-pie /tmp/he.s -o /tmp/nx_hub_emit" 16// Run: cd nishi-pages && mkdir -p dist/hub && /tmp/nx_hub_emit 17// 18// nx_capability_claims: 19// needs: [x86_64_syscalls, pipe_delimited_parse] 20// provides: [hub_page_emit, data_driven_cards, client_side_card_search] 21// safety: [html_escape_text_fields, no_floating_point, fixed_output_path] 22// verdict: [exit_0_ok] 23// license: ORIGINAL 24// kind: nishi_pages_specialist 25// layer: L3 (transform over L1 syscalls) 26// raci: [R=nishi_pages_builder, A=elder_west, C=hub_cards_owner, I=conductor] 27 28import "nx_syscalls_x86_64.nx" 29const K_MAGIC_262144: i64 = 262144 30 31// Append NUL-terminated s to buf at off; return new off. 32func he_puts(buf: *u8, off: i64, s: *u8) -> i64 { 33 var o: i64 = off 34 var i: i64 = 0 35 while s[i] != 0 { 36 buf[o] = s[i] 37 o = o + 1 38 i = i + 1 39 } 40 return o 41} 42 43// Append n raw bytes from src to buf at off; return new off. 44func he_putb(buf: *u8, off: i64, src: *u8, n: i64) -> i64 { 45 var o: i64 = off 46 var i: i64 = 0 47 while i < n { 48 buf[o] = src[i] 49 o = o + 1 50 i = i + 1 51 } 52 return o 53} 54 55// Append src[0..n), HTML-escaping & < > (UTF-8 multibyte passes through). 56func he_put_esc(buf: *u8, off: i64, src: *u8, n: i64) -> i64 { 57 var o: i64 = off 58 var i: i64 = 0 59 while i < n { 60 let c: i64 = src[i] as i64 61 if c == 0x26 { 62 o = he_puts(buf, o, "&amp;" as *u8) 63 } else { 64 if c == 0x3c { 65 o = he_puts(buf, o, "&lt;" as *u8) 66 } else { 67 if c == 0x3e { 68 o = he_puts(buf, o, "&gt;" as *u8) 69 } else { 70 buf[o] = src[i] 71 o = o + 1 72 } 73 } 74 } 75 i = i + 1 76 } 77 return o 78} 79 80// True if buf[off..off+n) equals the NUL-terminated literal lit. 81func he_eq(buf: *u8, off: i64, n: i64, lit: *u8) -> i64 { 82 var i: i64 = 0 83 while lit[i] != 0 { 84 if i >= n { return 0 } 85 if (buf[off + i] as i64) != (lit[i] as i64) { return 0 } 86 i = i + 1 87 } 88 if i != n { return 0 } 89 return 1 90} 91 92// Split buf[ls..le) on '|' into foff[]/flen[] (up to 6 fields). Returns 93// the field count. 94func he_split(buf: *u8, ls: i64, le: i64, foff: *i64, flen: *i64) -> i64 { 95 var fi: i64 = 0 96 var s: i64 = ls 97 var i: i64 = ls 98 while i < le { 99 if (buf[i] as i64) == 0x7c { 100 if fi < 6 { 101 foff[fi] = s 102 flen[fi] = i - s 103 fi = fi + 1 104 } 105 s = i + 1 106 } 107 i = i + 1 108 } 109 if fi < 6 { 110 foff[fi] = s 111 flen[fi] = le - s 112 fi = fi + 1 113 } 114 return fi 115} 116 117func main() -> i64 { 118 let len_p: *i64 = sys_mmap(8) as *i64 119 let data: *u8 = sys_read_file_x86_64("content/hub.cards" as *u8, len_p) 120 if data == (0 as *u8) { return 5 } 121 let dn: i64 = len_p[0] 122 123 let out: *u8 = sys_mmap(K_MAGIC_262144) 124 var o: i64 = 0 125 126 o = he_puts(out, o, "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Hub &middot; Nishi Family</title><link rel=\"stylesheet\" href=\"/assets/style.css\"><style>.app-soon{opacity:.55}.app-soon h3::after{content:\" \\2022 soon\";font-size:.7em;color:#8a8d98}</style></head><body><header class=\"site-header\"><a class=\"site-title\" href=\"/\">Nishi Family</a><nav><a href=\"/hub\">Hub</a><a href=\"/games\">Games</a><a href=\"/video/\">Video</a><a href=\"/pages/about\">About</a></nav></header><main><section class=\"hero\"><h1>Nishi Family Hub</h1><p class=\"tagline\">Everything the family runs, in one place.</p></section><section class=\"apps\"><div class=\"app-grid\" id=\"hubgrid\">" as *u8) 127 128 let foff: *i64 = sys_mmap(64) as *i64 129 let flen: *i64 = sys_mmap(64) as *i64 130 131 var ls: i64 = 0 132 while ls < dn { 133 // Find end of this line (first \n at/after ls, else dn). 134 var le: i64 = 0 - 1 135 var k: i64 = ls 136 while k < dn { 137 if le < 0 { 138 if (data[k] as i64) == 0x0a { le = k } 139 } 140 k = k + 1 141 } 142 if le < 0 { le = dn } 143 144 // Skip blank lines and comments (#...). 145 var skip: i64 = 0 146 if le <= ls { skip = 1 } 147 if skip == 0 { 148 if (data[ls] as i64) == 0x23 { skip = 1 } 149 } 150 151 if skip == 0 { 152 let nf: i64 = he_split(data, ls, le, foff, flen) 153 if nf >= 5 { 154 let is_soon: i64 = he_eq(data, foff[0], flen[0], "soon" as *u8) 155 // <a class="app-card[ app-soon]" href="..." data-kw="title blurb keywords"> 156 o = he_puts(out, o, "<a class=\"app-card" as *u8) 157 if is_soon == 1 { o = he_puts(out, o, " app-soon" as *u8) } 158 o = he_puts(out, o, "\" href=\"" as *u8) 159 if is_soon == 1 { 160 o = he_puts(out, o, "#" as *u8) 161 } else { 162 o = he_putb(out, o, ((data as i64) + foff[3]) as *u8, flen[3]) 163 } 164 o = he_puts(out, o, "\"><span class=\"app-emoji\">" as *u8) 165 o = he_putb(out, o, ((data as i64) + foff[1]) as *u8, flen[1]) 166 o = he_puts(out, o, "</span><h3>" as *u8) 167 o = he_put_esc(out, o, ((data as i64) + foff[2]) as *u8, flen[2]) 168 o = he_puts(out, o, "</h3><p>" as *u8) 169 o = he_put_esc(out, o, ((data as i64) + foff[4]) as *u8, flen[4]) 170 o = he_puts(out, o, "</p></a>" as *u8) 171 } 172 } 173 174 ls = le + 1 175 } 176 177 o = he_puts(out, o, "</div></section></main><footer><p>&copy; 2026 Elder West. Served by NishiVM &mdash; sovereign substrate.</p></footer></body></html>" as *u8) 178 179 let fd: i64 = sys_openat_wr("dist/hub/index.html" as *u8, 420) 180 if fd < 0 { return 6 } 181 sys_write(fd, out, o) 182 sys_close(fd) 183 184 let banner: *u8 = "nx_hub_emit: wrote dist/hub/index.html\n" as *u8 185 var bn: i64 = 0 186 while banner[bn] != 0 { bn = bn + 1 } 187 sys_write(1, banner, bn) 188 return 0 189}