code wiki / _hdl_build / nx_site_wholesale.nx

nx_site_wholesale.nx source

↩ module page · 237 lines · 10236 B

1// nx_site_wholesale.nx -- R-SITESHAPE of the SITE FACTORY: EMIT a complete multi-page site from a `site:` 2// graph record ("lego up a site / pass it along wholesale" -- the OUTPUT half of R-WHOLESITE). Reads the 3// content-addressed site graph (pages + per-page archetype + section-seq + nav edges) from the corpus and 4// re-emits the WHOLE site: same relative page paths (subdirs preserved), each page composed SEQ-FAITHFULLY 5// by the R5 composer, a shared nav built from the graph's own index edges (not the factory default), plus 6// self-emitted sitemap.xml + robots.txt. Content = archetype defaults or an optional .req brief. 7// usage: nx_site_wholesale <corpus-prefix> <site-key> <docroot> <domain> [reqfile] 8// license_tier: ORIGINAL 9import "nx_site_archetype.nx" 10const SW_MAGIC_1024: i64 = 1024 11const SW_MAGIC_262144: i64 = 262144 12 13const SW_MAXPG: i64 = 64 14const SW_NAMEW: i64 = 96 15const SW_SEQW: i64 = 200 16const SW_MAXNAV: i64 = 8 17 18// archname -> code (reverse of ti_arch_name); 0 unknown 19func sw_arch_code(nm: *u8, nl: i64) -> i64 { 20 let buf: *u8 = sys_mmap(32) 21 var c: i64 = 1 22 while c <= 10 { 23 let bl: i64 = ti_arch_name(c, buf) 24 if bl == nl { 25 var i: i64 = 0 26 var eq: i64 = 1 27 while i < nl { if (buf[i] as i64) != (nm[i] as i64) { eq = 0; i = nl } else { i = i + 1 } } 28 if eq == 1 { return c } 29 } 30 c = c + 1 31 } 32 return 0 33} 34// copy src[a..b) into dst, NUL-terminate; returns len 35func sw_cp(src: *u8, a: i64, b: i64, dst: *u8, cap: i64) -> i64 { 36 var o: i64 = 0 37 var i: i64 = a 38 while i < b { if o < cap - 1 { dst[o] = src[i]; o = o + 1 } i = i + 1 } 39 dst[o] = 0 as u8 40 return o 41} 42// next '|' at-or-after p, else e 43func sw_bar(s: *u8, p: i64, e: i64) -> i64 { 44 var i: i64 = p 45 while i < e { if (s[i] as i64) == 124 { return i } i = i + 1 } 46 return e 47} 48func sw_starts(s: *u8, p: i64, e: i64, lit: *u8) -> i64 { 49 var i: i64 = 0 50 while lit[i] != (0 as u8) { 51 if p + i >= e { return 0 } 52 if (s[p + i] as i64) != (lit[i] as i64) { return 0 } 53 i = i + 1 54 } 55 return 1 56} 57func sw_eqz(a: *u8, b: *u8) -> i64 { var i: i64=0; while 1==1 { if (a[i] as i64)!=(b[i] as i64) { return 0 } if a[i]==(0 as u8) { return 1 } i=i+1 } return 1 } 58 59func main(argc: i64, argv: *i64) -> i64 { 60 if argc < 5 { sa_w("usage: nx_site_wholesale <corpus-prefix> <site-key> <docroot> <domain> [reqfile]\n" as *u8); return 2 } 61 let prefix: *u8 = argv[1] as *u8 62 let key: *u8 = argv[2] as *u8 63 let docroot: *u8 = argv[3] as *u8 64 let domain: *u8 = argv[4] as *u8 65 // optional [urlbase] (starts with '/') so nav + sitemap work when served under a subpath 66 // (e.g. /wholesale/remix1); optional [reqfile] fills content. Order-flexible for back-compat. 67 let ub: *u8 = sys_mmap(160) 68 ub[0] = 0 as u8 69 if argc >= 6 { 70 let a5: *u8 = argv[5] as *u8 71 if a5[0] == (47 as u8) { 72 var u0: i64 = 0 73 while a5[u0] != (0 as u8) { if u0 < 156 { ub[u0] = a5[u0] } u0 = u0 + 1 } 74 if u0 > 156 { u0 = 156 } 75 ub[u0] = 0 as u8 76 } else { sa_req_load(a5) } 77 } 78 if argc >= 7 { sa_req_load(argv[6] as *u8) } 79 // fetch the site-graph record 80 let pbox: *i64 = sys_mmap(16) as *i64 81 let lbox: *i64 = sys_mmap(16) as *i64 82 if ss_get(prefix, key, pbox, lbox) != 1 { sa_w("site-wholesale: key not in corpus: " as *u8); sa_w(key); sa_w("\n" as *u8); return 3 } 83 let rec: *u8 = pbox[0] as *u8 84 let rn: i64 = lbox[0] 85 // parse pages + index-nav targets 86 let names: *u8 = sys_mmap(SW_MAXPG * SW_NAMEW) 87 let seqs: *u8 = sys_mmap(SW_MAXPG * SW_SEQW) 88 let archs: *i64 = sys_mmap(SW_MAXPG * 8) as *i64 89 var npg: i64 = 0 90 let navt: *u8 = sys_mmap(SW_MAXNAV * SW_NAMEW) 91 var nnav: i64 = 0 92 let anb: *u8 = sys_mmap(32) 93 var ls: i64 = 0 94 while ls < rn { 95 var le: i64 = ls 96 var sc: i64 = 1 97 while sc == 1 { if le >= rn { sc = 0 } else { if (rec[le] as i64) == 10 { sc = 0 } else { le = le + 1 } } } 98 if sw_starts(rec, ls, le, "page|" as *u8) == 1 { if npg < SW_MAXPG { 99 let f1: i64 = ls + 5 100 let b1: i64 = sw_bar(rec, f1, le) 101 let b2: i64 = sw_bar(rec, b1 + 1, le) 102 sw_cp(rec, f1, b1, (names as i64 + npg * SW_NAMEW) as *u8, SW_NAMEW) 103 let al: i64 = sw_cp(rec, b1 + 1, b2, anb, 32) 104 archs[npg] = sw_arch_code(anb, al) 105 if archs[npg] == 0 { archs[npg] = 7 } 106 sw_cp(rec, b2 + 1, le, (seqs as i64 + npg * SW_SEQW) as *u8, SW_SEQW) 107 npg = npg + 1 108 } } 109 if sw_starts(rec, ls, le, "nav|index.html|" as *u8) == 1 { if nnav < SW_MAXNAV { 110 let t1: i64 = ls + 15 111 let td: *u8 = (navt as i64 + nnav * SW_NAMEW) as *u8 112 sw_cp(rec, t1, le, td, SW_NAMEW) 113 // dedup 114 var dup: i64 = 0 115 var d: i64 = 0 116 while d < nnav { if sw_eqz(td, (navt as i64 + d * SW_NAMEW) as *u8) == 1 { dup = 1; d = nnav } else { d = d + 1 } } 117 if dup == 0 { nnav = nnav + 1 } 118 } } 119 ls = le + 1 120 } 121 if npg == 0 { sa_w("site-wholesale: record has no pages\n" as *u8); return 4 } 122 // shared nav from the graph: Home + index's targets (label = basename sans .html; href = /<name>) 123 let nlbl: *i64 = sys_mmap((SW_MAXNAV + 2) * 8) as *i64 124 let nhrf: *i64 = sys_mmap((SW_MAXNAV + 2) * 8) as *i64 125 let lblarena: *u8 = sys_mmap((SW_MAXNAV + 2) * 64) 126 let hrfarena: *u8 = sys_mmap((SW_MAXNAV + 2) * 112) 127 var nn: i64 = 0 128 nlbl[nn] = ("Home" as *u8) as i64 129 let homehref: *u8 = (hrfarena as i64) as *u8 130 var hh0: i64 = sa_cat(homehref, 0, ub) 131 homehref[hh0] = 47 as u8 132 homehref[hh0 + 1] = 0 as u8 133 nhrf[nn] = homehref as i64 134 nn = nn + 1 135 var v: i64 = 0 136 while v < nnav { 137 let t: *u8 = (navt as i64 + v * SW_NAMEW) as *u8 138 if sw_eqz(t, "index.html" as *u8) == 0 { 139 // label = basename without .html 140 var b0: i64 = 0 141 var i2: i64 = 0 142 while t[i2] != (0 as u8) { if (t[i2] as i64) == 47 { b0 = i2 + 1 } i2 = i2 + 1 } 143 let ld: *u8 = (lblarena as i64 + nn * 64) as *u8 144 var lo: i64 = 0 145 var j2: i64 = b0 146 while t[j2] != (0 as u8) { if (t[j2] as i64) == 46 { j2 = i2 } else { if lo < 60 { ld[lo] = t[j2]; lo = lo + 1 } j2 = j2 + 1 } } 147 ld[lo] = 0 as u8 148 let hd: *u8 = (hrfarena as i64 + nn * 112) as *u8 149 var ho: i64 = sa_cat(hd, 0, ub) 150 hd[ho] = 47 as u8; ho = ho + 1 151 var k2: i64 = 0 152 while t[k2] != (0 as u8) { if ho < 108 { hd[ho] = t[k2]; ho = ho + 1 } k2 = k2 + 1 } 153 hd[ho] = 0 as u8 154 nlbl[nn] = ld as i64 155 nhrf[nn] = hd as i64 156 nn = nn + 1 157 } 158 v = v + 1 159 } 160 SA_WNAV = nlbl as i64 161 SA_WHREF = nhrf as i64 162 SA_WNAVN = nn 163 // R-BRICKS: open the corpus for part: queries so grid richness follows the consumed bricks 164 let bh: *i64 = ss_open(prefix) 165 if (bh as i64) != 0 { SA_STOREH = bh as i64 } 166 // mkdir docroot + one-level subdirs from page names 167 sys_mkdir(docroot, 0x1ed) 168 let pathb: *u8 = sys_mmap(SW_MAGIC_1024) 169 var p: i64 = 0 170 while p < npg { 171 let nm: *u8 = (names as i64 + p * SW_NAMEW) as *u8 172 var sl: i64 = 0 - 1 173 var i3: i64 = 0 174 while nm[i3] != (0 as u8) { if (nm[i3] as i64) == 47 { sl = i3 } i3 = i3 + 1 } 175 if sl > 0 { 176 var po: i64 = sa_cat(pathb, 0, docroot) 177 po = sa_cat(pathb, po, "/" as *u8) 178 var c3: i64 = 0 179 while c3 < sl { pathb[po] = nm[c3]; po = po + 1; c3 = c3 + 1 } 180 pathb[po] = 0 as u8 181 sys_mkdir(pathb, 0x1ed) 182 } 183 p = p + 1 184 } 185 // emit every page seq-faithfully with the site's own nav 186 let buf: *u8 = sys_mmap(SW_MAGIC_262144) 187 let titleb: *u8 = sys_mmap(192) 188 var emitted: i64 = 0 189 p = 0 190 while p < npg { 191 let nm2: *u8 = (names as i64 + p * SW_NAMEW) as *u8 192 var t4: i64 = sa_cat(titleb, 0, sa_disp(archs[p])) 193 t4 = sa_cat(titleb, t4, " -- " as *u8) 194 t4 = sa_cat(titleb, t4, domain) 195 titleb[t4] = 0 as u8 196 let o: i64 = sa_recipe_seq(archs[p], (seqs as i64 + p * SW_SEQW) as *u8, p % 2, domain, titleb, buf) 197 var pp: i64 = sa_cat(pathb, 0, docroot) 198 pp = sa_cat(pathb, pp, "/" as *u8) 199 pp = sa_cat(pathb, pp, nm2) 200 pathb[pp] = 0 as u8 201 let fd: i64 = sys_openat_wr(pathb, 0x1a4) 202 if fd >= 0 { sys_write(fd, buf, o); sys_close(fd); emitted = emitted + 1 } 203 p = p + 1 204 } 205 // sitemap + robots over the emitted page set 206 var so: i64 = sa_cat(buf, 0, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n" as *u8) 207 p = 0 208 while p < npg { 209 let nm3: *u8 = (names as i64 + p * SW_NAMEW) as *u8 210 so = sa_cat(buf, so, "<url><loc>https://" as *u8) 211 so = sa_cat(buf, so, domain) 212 so = sa_cat(buf, so, ub) 213 so = sa_cat(buf, so, "/" as *u8) 214 if sw_eqz(nm3, "index.html" as *u8) == 0 { so = sa_cat(buf, so, nm3) } 215 so = sa_cat(buf, so, "</loc></url>\n" as *u8) 216 p = p + 1 217 } 218 so = sa_cat(buf, so, "</urlset>\n" as *u8) 219 var mp: i64 = sa_cat(pathb, 0, docroot); mp = sa_cat(pathb, mp, "/sitemap.xml" as *u8); pathb[mp] = 0 as u8 220 let mfd: i64 = sys_openat_wr(pathb, 0x1a4) 221 if mfd >= 0 { sys_write(mfd, buf, so); sys_close(mfd) } 222 var ro2: i64 = sa_cat(buf, 0, "User-agent: *\nAllow: /\nSitemap: https://" as *u8) 223 ro2 = sa_cat(buf, ro2, domain) 224 ro2 = sa_cat(buf, ro2, "/sitemap.xml\n" as *u8) 225 var rp2: i64 = sa_cat(pathb, 0, docroot); rp2 = sa_cat(pathb, rp2, "/robots.txt" as *u8); pathb[rp2] = 0 as u8 226 let rfd: i64 = sys_openat_wr(pathb, 0x1a4) 227 if rfd >= 0 { sys_write(rfd, buf, ro2); sys_close(rfd) } 228 sa_w("SITE-WHOLESALE OK: " as *u8) 229 let nb2: *u8 = sys_mmap(28) 230 let ne2: i64 = sa_catn(nb2, 0, emitted) 231 sys_write(1, nb2, ne2) 232 sa_w(" pages (structure + nav from the site graph) -> " as *u8) 233 sa_w(docroot) 234 sa_w("\n" as *u8) 235 if emitted == npg { return 0 } 236 return 1 237}