code wiki / (root) / nx_frontmatter.nx

nx_frontmatter.nx source

↩ module page · 99 lines · 3682 B

1// nx_frontmatter.nx -- splits "---\n<yaml>\n---\n<body>" into YAML 2// + body slices. Mirrors what nishi-pages/build/build.py load_doc() 3// did in Python; substrate-native + bounded + auditable. 4// 5// Wire format (mandatory): 6// src[0..3] == "---\n" (3 dashes + newline) 7// src[3..yaml_end] == YAML subset bytes 8// src[yaml_end..yaml_end+4] == "\n---" (terminator) OR "\n---\n" 9// src[yaml_end+5..] == body bytes (markdown, plain text, anything) 10// 11// Returns: 12// yaml_off / yaml_len = slice of the YAML subset block 13// body_off / body_len = slice of the body bytes 14// 15// Used by: 16// nishi-pages content/posts/*.md, content/pages/*.md (YAML front- 17// matter + markdown body) 18// 19// Per cardinal feedback-defensive-at-boundaries: input must START 20// with literal "---\n" or NX_FM_NO_FRONTMATTER returns; YAML term 21// must be present or NX_FM_UNTERMINATED returns. 22 23// nx_safety_envelope: 24// intended_use: reusable YAML-frontmatter splitter for nishi-pages content 25// sil_target: SIL2 26// evidence: bench/nx_frontmatter_smoke.nx exercises 3 cases 27// verdict: NOT_YET_EVALUATED -- pending smoke 28 29import "nx_syscalls_x86_64.nx" 30 31// ---- Sealed verdicts ---- 32 33const NX_FM_OK: i64 = 0 34const NX_FM_BAD_INPUT: i64 = 1 // src null / len < 4 35const NX_FM_NO_FRONTMATTER: i64 = 2 // doesn't start with "---\n" 36const NX_FM_UNTERMINATED: i64 = 3 // no closing "\n---" found 37const NX_FM_VERDICT_N: i64 = 4 38 39func _fm_match4(src: *u8, off: i64, n: i64, 40 a: i64, b: i64, c: i64, d: i64) -> i64 { 41 if off + 4 > n { return 0 } 42 if src[off] != (a & 0xFF) as u8 { return 0 } 43 if src[off + 1] != (b & 0xFF) as u8 { return 0 } 44 if src[off + 2] != (c & 0xFF) as u8 { return 0 } 45 if src[off + 3] != (d & 0xFF) as u8 { return 0 } 46 return 1 47} 48 49// Split src into frontmatter YAML + body. 50// On NX_FM_OK, *yaml_off..*yaml_len is the YAML and *body_off..*body_len 51// is the body. All offsets are RELATIVE to src. 52// 53// Tolerant of optional trailing "\n" after the second "---". 54func nx_frontmatter_split(src: *u8, src_n: i64, 55 yaml_off: *i64, yaml_len: *i64, 56 body_off: *i64, body_len: *i64) -> i64 { 57 if src as i64 == 0 { return NX_FM_BAD_INPUT } 58 if src_n < 4 { return NX_FM_BAD_INPUT } 59 60 // Header: "---\n" (0x2D 0x2D 0x2D 0x0A) 61 if _fm_match4(src, 0, src_n, 0x2D, 0x2D, 0x2D, 0x0A) == 0 { 62 return NX_FM_NO_FRONTMATTER 63 } 64 65 // Find terminator: scan for "\n---" starting at offset 4 (just 66 // past the "---\n" header). The \n we find IS the line terminator 67 // of the last YAML line. 68 var p: i64 = 4 69 var term: i64 = -1 70 while p + 4 <= src_n { 71 // "\n---" = 0x0A 0x2D 0x2D 0x2D 72 if src[p] == 0x0A { 73 if src[p + 1] == 0x2D { 74 if src[p + 2] == 0x2D { 75 if src[p + 3] == 0x2D { term = p; p = src_n } 76 } 77 } 78 } 79 p = p + 1 80 } 81 if term < 0 { return NX_FM_UNTERMINATED } 82 83 // YAML = src[4..term+1] (include the trailing \n so each YAML line 84 // ends with \n -- the YAML parser needs that). 85 yaml_off[0] = 4 86 yaml_len[0] = (term + 1) - 4 87 88 // Body starts AFTER second "---", optional trailing \n, optional leading \n. 89 var body_start: i64 = term + 4 // skip "\n---" 90 // Optional trailing newline after the closing "---". 91 if body_start < src_n { 92 if src[body_start] == 0x0A { body_start = body_start + 1 } 93 } 94 body_off[0] = body_start 95 body_len[0] = src_n - body_start 96 if body_len[0] < 0 { body_len[0] = 0 } 97 98 return NX_FM_OK 99}