code wiki / _hdl_build / nx_wiki_page_lib.nx

nx_wiki_page_lib.nx source

↩ module page · 165 lines · 9359 B

1// nx_wiki_page_lib.nx -- the reusable page emitter for the autonomous wiki. wp_emit_page() turns ONE 2// workstream record (a memory project-*.md = our real work) into an S-class anatomy page (Lead -> 3// Infobox -> Body[md render w/ [[wikilinks]]] -> See also -> Category) on the shared skin, per the 4// Wikipedia MoS/Layout the Nishi researcher fetched. Used by nx_wiki_workstream_page (one page) AND 5// nx_wiki_build (all of them). Sovereign: nx_syscalls + nx_wiki_skin_lib. license_tier: ORIGINAL 6import "nx_syscalls.nx" 7import "nx_wiki_skin_lib.nx" 8const K_MAGIC_2048: i64 = 2048 9 10func wp_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 11func wp_slurp(path: *u8, buf: *u8, cap: i64) -> i64 { 12 let fd: i64 = sys_openat_rd(path) 13 if fd < 0 { return 0 } 14 var total: i64 = 0 15 var nrd: i64 = sys_read(fd, buf, cap) 16 while nrd > 0 { total = total + nrd; if total >= cap { nrd = 0 } else { nrd = sys_read(fd, ((buf as i64) + total) as *u8, cap - total) } } 17 sys_close(fd) 18 return total 19} 20func wp_find_from(buf: *u8, len: i64, from: i64, pat: *u8) -> i64 { 21 var pl: i64 = 0; while pat[pl] != (0 as u8) { pl = pl + 1 } 22 if pl == 0 { return 0 - 1 } 23 var i: i64 = from 24 while i + pl <= len { var j: i64 = 0; var ok: i64 = 1; while j < pl { if buf[i + j] != pat[j] { ok = 0; j = pl } else { j = j + 1 } } if ok == 1 { return i } i = i + 1 } 25 return 0 - 1 26} 27func wp_line_end(buf: *u8, len: i64, s: i64) -> i64 { var e: i64 = s; while e < len { if buf[e] == (10 as u8) { return e } e = e + 1 } return len } 28func wp_fm_field(buf: *u8, len: i64, key: *u8, out: *u8, cap: i64) -> i64 { 29 let p: i64 = wp_find_from(buf, len, 0, key) 30 if p < 0 { out[0] = 0 as u8; return 0 } 31 var s: i64 = p 32 while s < len { 33 if buf[s] == (58 as u8) { 34 s = s + 1 35 if s < len { if buf[s] == (32 as u8) { s = s + 1 } } 36 var o: i64 = 0 37 while s < len { if buf[s] == (10 as u8) { s = len } else { if buf[s] == (13 as u8) { s = len } else { if o < cap - 1 { out[o] = buf[s]; o = o + 1 } s = s + 1 } } } 38 out[o] = 0 as u8 39 return o 40 } 41 s = s + 1 42 } 43 out[0] = 0 as u8 44 return 0 45} 46func wp_esc1(dst: *u8, o: i64, c: i64) -> i64 { 47 if c == 60 { return sk_cat(dst, o, "&lt;" as *u8) } 48 if c == 62 { return sk_cat(dst, o, "&gt;" as *u8) } 49 if c == 38 { return sk_cat(dst, o, "&amp;" as *u8) } 50 dst[o] = c as u8; return o + 1 51} 52func wp_esc(dst: *u8, o: i64, buf: *u8, a: i64, b: i64) -> i64 { var oo: i64 = o; var i: i64 = a; while i < b { oo = wp_esc1(dst, oo, buf[i] as i64); i = i + 1 } return oo } 53func wp_find2(buf: *u8, i: i64, end: i64, a: u8, b: u8) -> i64 { var k: i64 = i; while k + 1 < end { if buf[k] == a { if buf[k + 1] == b { return k } } k = k + 1 } return end } 54func wp_find1(buf: *u8, i: i64, end: i64, a: u8) -> i64 { var k: i64 = i; while k < end { if buf[k] == a { return k } k = k + 1 } return end } 55func wp_inline(dst: *u8, off: i64, buf: *u8, a: i64, b: i64) -> i64 { 56 var o: i64 = off; var i: i64 = a 57 while i < b { 58 let c: i64 = buf[i] as i64 59 if c == 91 { if i + 1 < b { if buf[i + 1] == (91 as u8) { 60 let k: i64 = wp_find2(buf, i + 2, b, 93 as u8, 93 as u8) 61 o = sk_cat(dst, o, "<a href=\"" as *u8) 62 var t: i64 = i + 2; while t < k { dst[o] = buf[t]; o = o + 1; t = t + 1 } 63 o = sk_cat(dst, o, ".html\">" as *u8) 64 o = wp_esc(dst, o, buf, i + 2, k) 65 o = sk_cat(dst, o, "</a>" as *u8) 66 i = k + 2 67 } else { o = wp_esc1(dst, o, 91); i = i + 1 } } else { o = wp_esc1(dst, o, 91); i = i + 1 } } 68 else { if c == 42 { if i + 1 < b { if buf[i + 1] == (42 as u8) { 69 let k: i64 = wp_find2(buf, i + 2, b, 42 as u8, 42 as u8) 70 o = sk_cat(dst, o, "<strong>" as *u8); o = wp_esc(dst, o, buf, i + 2, k); o = sk_cat(dst, o, "</strong>" as *u8) 71 i = k + 2 72 } else { o = wp_esc1(dst, o, 42); i = i + 1 } } else { o = wp_esc1(dst, o, 42); i = i + 1 } } 73 else { if c == 96 { 74 let k: i64 = wp_find1(buf, i + 1, b, 96 as u8) 75 o = sk_cat(dst, o, "<code>" as *u8); o = wp_esc(dst, o, buf, i + 1, k); o = sk_cat(dst, o, "</code>" as *u8) 76 i = k + 1 77 } 78 else { o = wp_esc1(dst, o, c); i = i + 1 } } } 79 } 80 return o 81} 82func wp_body(dst: *u8, off: i64, buf: *u8, start: i64, len: i64) -> i64 { 83 var o: i64 = off; var in_list: i64 = 0; var ls: i64 = start 84 while ls < len { 85 let le: i64 = wp_line_end(buf, len, ls) 86 var blank: i64 = 1; var j: i64 = ls 87 while j < le { if buf[j] != (32 as u8) { blank = 0; j = le } else { j = j + 1 } } 88 if blank == 1 { if in_list == 1 { o = sk_cat(dst, o, "</ul>\n" as *u8); in_list = 0 } } 89 else { 90 if buf[ls] == (35 as u8) { 91 if in_list == 1 { o = sk_cat(dst, o, "</ul>\n" as *u8); in_list = 0 } 92 var h: i64 = 0; var p: i64 = ls 93 while p < le { if buf[p] == (35 as u8) { h = h + 1; p = p + 1 } else { p = le } } 94 var cs: i64 = ls + h 95 if cs < le { if buf[cs] == (32 as u8) { cs = cs + 1 } } 96 var tag: *u8 = "h2" as *u8 97 if h == 3 { tag = "h3" as *u8 } 98 if h >= 4 { tag = "h4" as *u8 } 99 o = sk_cat(dst, o, "<" as *u8); o = sk_cat(dst, o, tag); o = sk_cat(dst, o, ">" as *u8) 100 o = wp_inline(dst, o, buf, cs, le) 101 o = sk_cat(dst, o, "</" as *u8); o = sk_cat(dst, o, tag); o = sk_cat(dst, o, ">\n" as *u8) 102 } 103 else { var islist: i64 = 0 104 if buf[ls] == (45 as u8) { if ls + 1 < le { if buf[ls + 1] == (32 as u8) { islist = 1 } } } 105 if islist == 1 { 106 if in_list == 0 { o = sk_cat(dst, o, "<ul>\n" as *u8); in_list = 1 } 107 o = sk_cat(dst, o, "<li>" as *u8); o = wp_inline(dst, o, buf, ls + 2, le); o = sk_cat(dst, o, "</li>\n" as *u8) 108 } else { 109 if in_list == 1 { o = sk_cat(dst, o, "</ul>\n" as *u8); in_list = 0 } 110 o = sk_cat(dst, o, "<p>" as *u8); o = wp_inline(dst, o, buf, ls, le); o = sk_cat(dst, o, "</p>\n" as *u8) 111 } 112 } 113 } 114 ls = le + 1 115 } 116 if in_list == 1 { o = sk_cat(dst, o, "</ul>\n" as *u8) } 117 return o 118} 119func wp_seealso(dst: *u8, off: i64, buf: *u8, start: i64, len: i64) -> i64 { 120 var o: i64 = off; var count: i64 = 0 121 o = sk_cat(dst, o, "<ul>\n" as *u8) 122 var i: i64 = start 123 while i + 1 < len { 124 if buf[i] == (91 as u8) { if buf[i + 1] == (91 as u8) { 125 let k: i64 = wp_find2(buf, i + 2, len, 93 as u8, 93 as u8) 126 o = sk_cat(dst, o, "<li><a href=\"" as *u8) 127 var t: i64 = i + 2; while t < k { dst[o] = buf[t]; o = o + 1; t = t + 1 } 128 o = sk_cat(dst, o, ".html\">" as *u8); o = wp_esc(dst, o, buf, i + 2, k); o = sk_cat(dst, o, "</a></li>\n" as *u8) 129 count = count + 1 130 i = k + 2 131 } else { i = i + 1 } } else { i = i + 1 } 132 } 133 if count == 0 { o = sk_cat(dst, o, "<li class=\"sub\">no linked workstreams</li>\n" as *u8) } 134 o = sk_cat(dst, o, "</ul>\n" as *u8) 135 return o 136} 137 138// THE PAGE: render record `rec[0..slen)` into `out`, return HTML length. Skips records with no name. 139func wp_emit_page(out: *u8, rec: *u8, slen: i64) -> i64 { 140 let name: *u8 = sys_mmap(256); wp_fm_field(rec, slen, "name:" as *u8, name, 256) 141 if name[0] == (0 as u8) { return 0 } 142 let desc: *u8 = sys_mmap(K_MAGIC_2048); wp_fm_field(rec, slen, "description:" as *u8, desc, K_MAGIC_2048) 143 let typ: *u8 = sys_mmap(64); wp_fm_field(rec, slen, "\n type:" as *u8, typ, 64) 144 if typ[0] == (0 as u8) { wp_fm_field(rec, slen, "type:" as *u8, typ, 64) } 145 146 var body_start: i64 = 0 147 let close: i64 = wp_find_from(rec, slen, 3, "\n---" as *u8) 148 if close >= 0 { var bs: i64 = close + 4; while bs < slen { if rec[bs] == (10 as u8) { bs = bs + 1; body_start = bs; bs = slen } else { bs = bs + 1 } } } 149 150 var w: i64 = 0 151 w = skin_open(out, w, name, "ws" as *u8) 152 w = sk_cat(out, w, "<h1>" as *u8); w = wp_esc(out, w, name, 0, wp_slen(name)); w = sk_cat(out, w, "</h1>\n" as *u8) 153 w = sk_cat(out, w, "<p class=\"sub\">" as *u8); w = wp_inline(out, w, desc, 0, wp_slen(desc)); w = sk_cat(out, w, "</p>\n" as *u8) 154 w = sk_cat(out, w, "<table><thead><tr><th colspan=2>Workstream</th></tr></thead><tbody>" as *u8) 155 w = sk_cat(out, w, "<tr><td>Name</td><td><code>" as *u8); w = wp_esc(out, w, name, 0, wp_slen(name)); w = sk_cat(out, w, "</code></td></tr>" as *u8) 156 w = sk_cat(out, w, "<tr><td>Type</td><td>" as *u8); w = wp_esc(out, w, typ, 0, wp_slen(typ)); w = sk_cat(out, w, "</td></tr>" as *u8) 157 w = sk_cat(out, w, "<tr><td>Source</td><td class=\"sub\">live work record (not a TSV)</td></tr></tbody></table>\n" as *u8) 158 w = sk_cat(out, w, "<h2>Detail</h2>\n" as *u8) 159 w = wp_body(out, w, rec, body_start, slen) 160 w = sk_cat(out, w, "<h2>See also</h2>\n" as *u8) 161 w = wp_seealso(out, w, rec, body_start, slen) 162 w = sk_cat(out, w, "<h2>Category</h2>\n<p><a href=\"index.html\">" as *u8); w = wp_esc(out, w, typ, 0, wp_slen(typ)); w = sk_cat(out, w, "</a></p>\n" as *u8) 163 w = skin_close(out, w, sys_now_realtime_sec()) 164 return w 165}