feat: add OpenCode/Codex outputs and update changelog (#104)
* Add OpenCode converter coverage and specs * Add Codex target support and spec docs * Generate Codex command skills and refresh spec docs * Add global Codex install path * fix: harden plugin path loading and codex descriptions * feat: ensure codex agents block on convert/install * docs: clarify target branch usage for review * chore: prep npm package metadata and release notes * docs: mention opencode and codex in changelog * docs: update CLI usage and remove stale todos * feat: install from GitHub with global outputs
This commit is contained in:
65
src/utils/frontmatter.ts
Normal file
65
src/utils/frontmatter.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { load } from "js-yaml"
|
||||
|
||||
export type FrontmatterResult = {
|
||||
data: Record<string, unknown>
|
||||
body: string
|
||||
}
|
||||
|
||||
export function parseFrontmatter(raw: string): FrontmatterResult {
|
||||
const lines = raw.split(/\r?\n/)
|
||||
if (lines.length === 0 || lines[0].trim() !== "---") {
|
||||
return { data: {}, body: raw }
|
||||
}
|
||||
|
||||
let endIndex = -1
|
||||
for (let i = 1; i < lines.length; i += 1) {
|
||||
if (lines[i].trim() === "---") {
|
||||
endIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (endIndex === -1) {
|
||||
return { data: {}, body: raw }
|
||||
}
|
||||
|
||||
const yamlText = lines.slice(1, endIndex).join("\n")
|
||||
const body = lines.slice(endIndex + 1).join("\n")
|
||||
const parsed = load(yamlText)
|
||||
const data = (parsed && typeof parsed === "object") ? (parsed as Record<string, unknown>) : {}
|
||||
return { data, body }
|
||||
}
|
||||
|
||||
export function formatFrontmatter(data: Record<string, unknown>, body: string): string {
|
||||
const yaml = Object.entries(data)
|
||||
.filter(([, value]) => value !== undefined)
|
||||
.map(([key, value]) => formatYamlLine(key, value))
|
||||
.join("\n")
|
||||
|
||||
if (yaml.trim().length === 0) {
|
||||
return body
|
||||
}
|
||||
|
||||
return [`---`, yaml, `---`, "", body].join("\n")
|
||||
}
|
||||
|
||||
function formatYamlLine(key: string, value: unknown): string {
|
||||
if (Array.isArray(value)) {
|
||||
const items = value.map((item) => ` - ${formatYamlValue(item)}`)
|
||||
return [key + ":", ...items].join("\n")
|
||||
}
|
||||
return `${key}: ${formatYamlValue(value)}`
|
||||
}
|
||||
|
||||
function formatYamlValue(value: unknown): string {
|
||||
if (value === null || value === undefined) return ""
|
||||
if (typeof value === "number" || typeof value === "boolean") return String(value)
|
||||
const raw = String(value)
|
||||
if (raw.includes("\n")) {
|
||||
return `|\n${raw.split("\n").map((line) => ` ${line}`).join("\n")}`
|
||||
}
|
||||
if (raw.includes(":") || raw.startsWith("[") || raw.startsWith("{")) {
|
||||
return JSON.stringify(raw)
|
||||
}
|
||||
return raw
|
||||
}
|
||||
Reference in New Issue
Block a user