// Config — read-only YAML viewer with redaction + collapsible sections. const { Card } = window.UI; const REDACT_KEYS = /^(api_key|api_secret|token|webhook|password|secret)$/i; function highlightYaml(line) { // crude but works: comment, key:value, list, redacted strings if (/^\s*#/.test(line)) return {line}; const m = line.match(/^(\s*)([-]?\s*)([\w._-]+)(\s*:\s*)(.*)$/); if (m) { const [, indent, dash, key, sep, val] = m; const isSecret = REDACT_KEYS.test(key); return ( <> {indent} {dash && {dash}} {key} {sep} {val === '***REDACTED***' || isSecret && /REDACTED/.test(val) ? {val} : /^\[.*\]$/.test(val) ? {val} : /^-?\d+\.?\d*$/.test(val) ? {val} : {val}} ); } const li = line.match(/^(\s*)(-\s+)(.*)$/); if (li) return <>{li[1]}{li[2]}{li[3]}; return {line}; } function parseSections(yaml) { const lines = yaml.split('\n'); const sections = []; let cur = null; lines.forEach((l, i) => { if (/^\w/.test(l)) { if (cur) sections.push(cur); cur = { name: l.replace(':', ''), lines: [{ n: i+1, text: l }] }; } else if (cur) { cur.lines.push({ n: i+1, text: l }); } }); if (cur) sections.push(cur); return sections; } function PageConfig() { const { data, error, loading, refresh } = window.API.useAPI( () => window.API.get('/api/v1/config'), [], ); const yaml = (data && data.yaml) || ''; const path = (data && data.path) || 'configs/bot.yaml'; const redacted = !!(data && data.redacted); const note = data && (data.note || data.error); const sections = React.useMemo(() => parseSections(yaml || ''), [yaml]); const [openSet, setOpenSet] = React.useState(() => new Set(['app'])); const toggle = (n) => setOpenSet(s => { const c = new Set(s); c.has(n) ? c.delete(n) : c.add(n); return c; }); const expandAll = () => setOpenSet(new Set(sections.map(s => s.name))); const collapseAll = () => setOpenSet(new Set()); return (

config

read-only view of {path}

secrets are env-only; this view is read-only — to change, edit {path} on disk and restart. {redacted ? 'server-side redaction active' : 'no redaction applied'}
{loading &&
loading…
} {error &&
{error.message}
} {note &&
{note}
} {!loading && !error && yaml && (
{sections.map(sec => { const open = openSet.has(sec.name); return (
{open && (
                      {sec.lines.map((l, i) => (
                        
{l.n} {highlightYaml(l.text) || ' '}
))}
)}
); })}
)}
); } window.PageConfig = PageConfig;