code wiki / _hdl_build / nx_html_book.nx

nx_html_book.nx source

↩ module page · 84 lines · 4869 B

1// nx_html_book.nx -- SOVEREIGN HTML (single-file web ebook) -> Nishi reader format. The library holds ~79 .html 2// books that previously dead-ended at /file. Reads the .html and runs it through the SAME chapter_split pipeline 3// as the EPUB/MOBI readers (nx_html_to_text -> book.json + chapN.txt) so the zero-JS reader renders it unchanged. 4// <title> -> book title (else the slug). Usage: nx_html_book <html-path> <slug>. expect_exit: 0 license_tier: ORIGINAL 5import "nx_syscalls.nx" 6import "nx_chapter_split.nx" 7const K_MAGIC_1024: i64 = 1024 8 9func hb_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 10func hb_w(fd: i64, s: *u8) -> i64 { sys_write(fd, s, hb_slen(s)); return 0 } 11func hb_p(s: *u8) -> i64 { hb_w(1, s); return 0 } 12func hb_pn(v: i64) -> i64 { let b: *u8=sys_mmap(24); var m: i64=v; if m<0{m=0-m} let t: *u8=sys_mmap(24); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 } 13func ensure_dir(path: *u8) -> i64 { __syscall(258, 0-100, path, 0x1ed, 0, 0, 0); return 0 } 14func er_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){dst[off+i]=s[i];i=i+1} return off+i } 15func er_wjson(fd: i64, s: *u8) -> i64 { 16 var i: i64 = 0 17 while s[i] != (0 as u8) { 18 let c: i64 = s[i] as i64 19 if c == 0x22 { sys_write(fd, "\\\"" as *u8, 2) } 20 else { if c == 0x5c { sys_write(fd, "\\\\" as *u8, 2) } 21 else { if c < 0x20 { sys_write(fd, " " as *u8, 1) } 22 else { sys_write(fd, (s as i64 + i) as *u8, 1) } } } 23 i = i + 1 24 } 25 return 0 26} 27func find_sub(hay: *u8, hl: i64, needle: *u8) -> i64 { 28 let nl: i64 = hb_slen(needle); if nl == 0 { return 0-1 } 29 var i: i64 = 0 30 while i + nl <= hl { var k: i64=0; var hit: i64=1; while k<nl { if hay[i+k]!=needle[k]{hit=0;k=nl}else{k=k+1} } if hit==1 {return i} i=i+1 } 31 return 0-1 32} 33// extract <title> inner text (tags stripped) into out; ret len (0 if none). 34func extract_title(html: *u8, hl: i64, out: *u8, cap: i64) -> i64 { 35 out[0] = 0 as u8 36 let t: i64 = find_sub(html, hl, "<title" as *u8) 37 if t < 0 { return 0 } 38 var gt: i64 = 0-1; var p: i64 = t 39 while p < hl { if html[p] == (0x3e as u8) { gt = p; p = hl } else { p = p + 1 } } 40 if gt < 0 { return 0 } 41 let cs: i64 = gt + 1 42 let he: i64 = find_sub((html as i64 + cs) as *u8, hl - cs, "</title" as *u8) 43 var ce: i64 = hl 44 if he >= 0 { ce = cs + he } 45 var o: i64 = 0; var i: i64 = cs 46 while i < ce { let c: i64 = html[i] as i64; if c != 0x3c { if c != 0x3e { if c >= 0x20 { if o < cap-1 { out[o]=html[i] as u8; o=o+1 } } } } i = i + 1 } 47 out[o] = 0 as u8 48 return o 49} 50 51func do_html(path: *u8, slug: *u8) -> i64 { 52 let lb: *i64 = sys_mmap(16) as *i64 53 let z: *u8 = sys_read_file(path, lb) 54 if (z as i64) == 0 { hb_p("HTML-FAIL read " as *u8); hb_p(path); hb_p("\n" as *u8); return 0-1 } 55 let zl: i64 = lb[0] 56 if zl < 20 { hb_p("HTML-FAIL too-small\n" as *u8); return 0-1 } 57 let title: *u8 = sys_mmap(K_MAGIC_1024); title[0]=0 as u8 58 extract_title(z, zl, title, K_MAGIC_1024) 59 if title[0] == (0 as u8) { var k: i64=0; while slug[k]!=(0 as u8){ title[k]=slug[k]; k=k+1 } title[k]=0 as u8 } 60 ensure_dir("knowledge/staging/media/reader" as *u8) 61 let dir: *u8 = sys_mmap(512); var dl: i64 = er_cat(dir, 0, "knowledge/staging/media/reader/" as *u8); dl = er_cat(dir, dl, slug); dir[dl]=0 as u8 62 ensure_dir(dir) 63 let jp: *u8 = sys_mmap(K_MAGIC_1024); var jl: i64 = er_cat(jp, 0, dir as *u8); jl = er_cat(jp, jl, "/book.json" as *u8); jp[jl]=0 as u8 64 let jfd: i64 = sys_openat_wr(jp, 0x1a4) 65 if jfd < 0 { hb_p("HTML-FAIL open-json\n" as *u8); return 0-1 } 66 hb_w(jfd, "{\"title\":\"" as *u8); er_wjson(jfd, title) 67 hb_w(jfd, "\",\"author\":\"\",\"publisher\":\"\",\"pubdate\":\"\",\"isbn\":\"\",\"description\":\"\",\"format\":\"html\",\"slug\":\"" as *u8); er_wjson(jfd, slug) 68 hb_w(jfd, "\"," as *u8) 69 let totalp: *i64 = sys_mmap(8) as *i64; totalp[0]=0 70 let nseg: i64 = chapter_split(z, zl, dir, title, jfd, totalp, "html\x00" as *u8) 71 hb_w(jfd, ",\"assets\":[],\"nassets\":0,\"cover\":\"\"}" as *u8) 72 sys_close(jfd) 73 hb_p("HTML-BOOK title=\"" as *u8); hb_w(1, title); hb_p("\" chapters=" as *u8); hb_pn(nseg); hb_p(" chars=" as *u8); hb_pn(totalp[0]); hb_p(" -> " as *u8); hb_p(dir); hb_p("\n" as *u8) 74 if totalp[0] < 20 { return 0-1 } 75 return 0 76} 77func main(argc: i64, argv: *i64) -> i64 { 78 var path: *u8 = "knowledge/fixtures/nishi_html_fixture.html" as *u8 79 var slug: *u8 = "nishi_html_fixture" as *u8 80 if argc >= 3 { path = argv[1] as *u8; slug = argv[2] as *u8 } 81 let r: i64 = do_html(path, slug) 82 if r == 0 { hb_p("HTML-BOOK-OK\n" as *u8); sys_exit(0); return 0 } 83 hb_p("HTML-BOOK-FAIL\n" as *u8); sys_exit(1); return 1 84}