@blundergoat/goat-flow
Version:
AI coding agent harness and local dashboard for Claude Code, OpenAI Codex, Google Antigravity, and GitHub Copilot - setup audits, guardrails, structured skills, deny hooks, and persistent learning loops.
51 lines (50 loc) • 1.64 kB
JavaScript
;
const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
/** Parse frontmatter only when js-yaml is loaded and the YAML root is an object. */
function parseFrontmatter(block) {
const yaml = window.jsyaml;
if (!yaml)
return null;
const parsed = yaml.load(block);
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
return null;
}
return parsed;
}
/** Build the global markdown renderer with reusable line-break and no-line-break instances. */
function buildRenderer() {
const md = window.markdownit;
if (!md) {
return () => ({
html: '<pre class="gf-md-error">markdown-it not loaded</pre>',
frontmatter: null,
});
}
const defaultInstance = md({
html: false,
linkify: true,
breaks: true,
typographer: false,
});
const noBreaksInstance = md({
html: false,
linkify: true,
breaks: false,
typographer: false,
});
return (text, opts = {}) => {
let body = text;
let frontmatter = null;
const match = body.match(FRONTMATTER_RE);
if (match) {
const parsedFrontmatter = parseFrontmatter(match[1] ?? "");
if (parsedFrontmatter && opts.frontmatter !== "passthrough") {
body = body.slice(match[0].length);
}
frontmatter = parsedFrontmatter;
}
const instance = opts.breaks === false ? noBreaksInstance : defaultInstance;
return { html: instance.render(body), frontmatter };
};
}
window.renderMarkdown = buildRenderer();