import { extractFrontmatterBlock, findFieldLineRange, findFieldRange, type TextRange, } from "./frontmatterBlock"; export { findFieldLineRange, findFieldRange }; export type { TextRange }; export type ReplaceFrontmatterFieldResult = | { ok: true; content: string; range: TextRange } | { ok: false; reason: "no-frontmatter" | "no-field" }; /** * Replace a scalar frontmatter field value on its line. * Does not re-serialize YAML; only rewrites the value after `:`. */ export function replaceFrontmatterField( content: string, key: string, value: string, ): ReplaceFrontmatterFieldResult { const block = extractFrontmatterBlock(content); if (!block || block.closeLine < 0) { return { ok: false, reason: "no-frontmatter" }; } const lineRange = findFieldLineRange(content, key); if (!lineRange) { return { ok: false, reason: "no-field" }; } const lines = content.split(/\r?\n/); const line = lines[lineRange.startLine] ?? ""; const colonIndex = line.indexOf(":"); if (colonIndex < 0) { return { ok: false, reason: "no-field" }; } const prefix = line.slice(0, colonIndex + 1); const spacing = line.slice(colonIndex + 1).match(/^\s*/)?.[0] ?? " "; const newLine = `${prefix}${spacing || " "}${value}`; lines[lineRange.startLine] = newLine; const eol = content.includes("\r\n") ? "\r\n" : "\n"; const next = lines.join(eol); const valueRange = findFieldRange(next, key); return { ok: true, content: next, range: valueRange ?? { startLine: lineRange.startLine, startCol: 0, endLine: lineRange.startLine, endCol: newLine.length, }, }; }