code wiki / _hdl_build / nx_sitegen_video.nx

nx_sitegen_video.nx source

↩ module page · 51 lines · 3848 B

1// nx_sitegen_video.nx -- AUTO-BUILDER, VIDEO-GALLERY page type (operator's "sites like YouTube showing pets to 2// others"). Builds a complete responsive video-gallery page FROM DATA: page title + heading + a list of videos 3// (title / thumbnail / source per video) -> a grid of inline players + an onsite search. Like the game page 4// type, it is its OWN page profile (not the marketing block-walk), emitted bits-up + responsive by construction; 5// every data field is injection-ESCAPED (hs_escape). Data-driven => the same builder ships any video site by 6// swapping the list. license_tier: ORIGINAL 7import "nx_html_sanitize.nx" 8import "nx_syscalls.nx" 9 10func vid_w(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd, s, n); return 0 } 11// escape an untrusted data field (hs_escape) and write it to fd. 12func vid_esc(fd: i64, src: *u8) -> i64 { 13 if (src as i64) == 0 { return 0 } 14 var sl: i64 = 0 15 while src[sl] != (0 as u8) { sl = sl + 1 } 16 let dst: *u8 = sys_mmap(sl*8 + 16) 17 let n: i64 = hs_escape(src, sl, dst, sl*8 + 15) 18 sys_write(fd, dst, n) 19 return 0 20} 21 22// build a video-gallery page to fd. titles/thumbs/urls = parallel arrays of *u8 (cast to i64); n videos. 23func vid_build(fd: i64, title: *u8, heading: *u8, titles: *i64, thumbs: *i64, urls: *i64, n: i64) -> i64 { 24 vid_w(fd, "<!doctype html>\n<html lang=\"en\"><head><meta charset=\"utf-8\">\n" as *u8) 25 vid_w(fd, "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n" as *u8) 26 vid_w(fd, "<title>" as *u8); vid_esc(fd, title); vid_w(fd, "</title>\n<style>\n" as *u8) 27 vid_w(fd, "*{box-sizing:border-box}body{margin:0;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif;color:#e8eef6;background:#0f1115}\n" as *u8) 28 vid_w(fd, ".wrap{max-width:1100px;margin:0 auto;padding:0 18px}\n" as *u8) 29 vid_w(fd, "header{background:#11151c;padding:14px 0;position:sticky;top:0;z-index:9}.brand{font-weight:700;font-size:1.15rem;color:#fff}\n" as *u8) 30 vid_w(fd, ".search{margin:14px 0;display:flex;gap:8px}.search input{flex:1;padding:11px;border-radius:8px;border:1px solid #2a2f3a;background:#0b0e14;color:#e8eef6}\n" as *u8) 31 vid_w(fd, ".grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:18px;margin:18px 0}\n" as *u8) 32 vid_w(fd, "figure{margin:0;background:#171b22;border:1px solid #232833;border-radius:10px;overflow:hidden}video{width:100%;display:block;background:#000;aspect-ratio:16/9}\n" as *u8) 33 vid_w(fd, "figcaption{padding:10px 12px;font-size:.96rem}h2{color:#fff}footer{color:#8a93a3;padding:18px 0;text-align:center}\n" as *u8) 34 vid_w(fd, "@media(max-width:600px){.grid{grid-template-columns:1fr}}\n" as *u8) 35 vid_w(fd, "</style></head><body>\n" as *u8) 36 vid_w(fd, "<header><div class=\"wrap\"><span class=\"brand\">" as *u8); vid_esc(fd, title); vid_w(fd, "</span></div></header>\n" as *u8) 37 vid_w(fd, "<div class=\"wrap\"><form class=\"search\" role=\"search\" action=\"/search\" method=\"get\"><input type=\"search\" name=\"q\" placeholder=\"Search videos...\" aria-label=\"Search videos\"></form>\n" as *u8) 38 vid_w(fd, "<section><h2>" as *u8); vid_esc(fd, heading); vid_w(fd, "</h2><div class=\"grid\">\n" as *u8) 39 var i: i64 = 0 40 while i < n { 41 vid_w(fd, "<figure><video controls preload=\"none\" poster=\"" as *u8); vid_esc(fd, thumbs[i] as *u8) 42 vid_w(fd, "\" src=\"" as *u8); vid_esc(fd, urls[i] as *u8) 43 vid_w(fd, "\"></video><figcaption>" as *u8); vid_esc(fd, titles[i] as *u8) 44 vid_w(fd, "</figcaption></figure>\n" as *u8) 45 i = i + 1 46 } 47 vid_w(fd, "</div></section></div>\n" as *u8) 48 vid_w(fd, "<footer><div class=\"wrap\">Built by the Nishi auto-builder &mdash; sovereign video gallery</div></footer>\n" as *u8) 49 vid_w(fd, "</body></html>\n" as *u8) 50 return n 51}