feat(okr): delt frontmatter-parse/skrive-modul + #-strip-fix (SC2) [skip-docs]
This commit is contained in:
parent
274d833e64
commit
d9f2848d90
2 changed files with 164 additions and 0 deletions
55
lib/frontmatter.mjs
Normal file
55
lib/frontmatter.mjs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// frontmatter.mjs
|
||||
// Delt frontmatter-parse/skrive for okr-pluginen. Zero npm dependencies.
|
||||
//
|
||||
// Konsoliderer den dupliserte flate `get()`-parseren fra inject-okr-context.mjs
|
||||
// (:59-66) og coaching-hook.mjs (:20-27) til EN modul, med to korreksjoner mot
|
||||
// den gamle atferden:
|
||||
// 1. Linjeanker (`^\s*key:`, multiline) — key matcher kun ved linjestart
|
||||
// (modulo innrykk), aldri som substring midt i en annen key/verdi. Bevarer
|
||||
// first-match og nestet (innrykket) oppslag (load-bearing: inject:69).
|
||||
// 2. Trailing " #kommentar" strippes KUN fra USITERTE verdier. Siterte verdier
|
||||
// beholder en intern '#' ("A #B" -> A #B). Retter comment-leak-bugen der
|
||||
// `okr_frikoblet_fra_loenn: true # ...` lakk kommentaren inn i verdien.
|
||||
//
|
||||
// Tolererer fler-linje OKF-list-verdier (f.eks. `tags:`) uten krasj: get() paa
|
||||
// en list-key returnerer null (rest-av-linja er tom); list-elementer paa
|
||||
// foelgende linjer konsumeres aldri (ingen konsument leser tre-filenes `tags`).
|
||||
|
||||
const FM_RE = /^---\n([\s\S]*?)\n---/;
|
||||
|
||||
export function parseFrontmatter(content) {
|
||||
const match = String(content).match(FM_RE);
|
||||
const raw = match ? match[1] : null;
|
||||
|
||||
const get = (key) => {
|
||||
if (raw === null) return null;
|
||||
const m = raw.match(new RegExp(`^\\s*${key}:\\s*(.*)$`, 'm'));
|
||||
if (!m) return null;
|
||||
let v = m[1].trim();
|
||||
if (v === '') return null;
|
||||
const q = v[0];
|
||||
if (q === '"' || q === "'") {
|
||||
const end = v.indexOf(q, 1);
|
||||
if (end !== -1) return v.slice(1, end); // intern '#' bevart
|
||||
v = v.slice(1); // uavsluttet quote: fall tilbake til resten
|
||||
} else {
|
||||
v = v.replace(/\s+#.*$/, '').trim(); // usitert: strip trailing kommentar
|
||||
}
|
||||
return v === '' ? null : v;
|
||||
};
|
||||
|
||||
return { raw, get };
|
||||
}
|
||||
|
||||
export function writeFrontmatter(fields) {
|
||||
const lines = ['---'];
|
||||
for (const [key, value] of Object.entries(fields)) {
|
||||
const s = String(value);
|
||||
// Siter naar verdien inneholder '#'/':' eller har kant-whitespace, slik at
|
||||
// round-trip via parseFrontmatter bevarer den eksakt (jf. siter-#-regelen).
|
||||
const needsQuote = /[#:]/.test(s) || /^\s|\s$/.test(s) || /^["']/.test(s);
|
||||
lines.push(`${key}: ${needsQuote ? JSON.stringify(s) : s}`);
|
||||
}
|
||||
lines.push('---');
|
||||
return lines.join('\n') + '\n';
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue