Add yaml compositino
This commit is contained in:
@@ -36,11 +36,61 @@ export default function RenderingNode({ id }: Props) {
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = yaml.load(yamlText)
|
||||
// resolve !include directives by inlining YAML from reachable config nodes
|
||||
const resolveIncludes = (text: string, visited = new Set<string>()): string => {
|
||||
const includeRegex = /^(\s*)!include\s+([^\s]+)\s*$/gm
|
||||
return text.replace(includeRegex, (match, indent, ref) => {
|
||||
const refName = ref.endsWith('.yaml') ? ref.slice(0, -5) : ref
|
||||
// try to find a node by id or by title
|
||||
const refNode = nodes.find((n: any) => n.id === refName || (n.data?.title === refName))
|
||||
if (!refNode) {
|
||||
throw new Error(`Included node not found: ${ref}`)
|
||||
}
|
||||
if (visited.has(refNode.id)) {
|
||||
throw new Error(`Circular include detected: ${ref}`)
|
||||
}
|
||||
|
||||
// ensure refNode can reach this rendering node
|
||||
const isReachable = (startId: string, targetId: string) => {
|
||||
const q: string[] = [startId]
|
||||
const seen = new Set<string>([startId])
|
||||
while (q.length) {
|
||||
const cur = q.shift()!
|
||||
if (cur === targetId) return true
|
||||
for (const e of edges) {
|
||||
if (e.source === cur && !seen.has(e.target)) {
|
||||
seen.add(e.target)
|
||||
q.push(e.target)
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if (!isReachable(refNode.id, id)) {
|
||||
throw new Error(`Included node not connected to renderer: ${ref}`)
|
||||
}
|
||||
|
||||
visited.add(refNode.id)
|
||||
const includedRaw = String(refNode.data?.yaml ?? '')
|
||||
const resolved = resolveIncludes(includedRaw, visited)
|
||||
visited.delete(refNode.id)
|
||||
|
||||
// indent included content to match include position
|
||||
const indented = resolved
|
||||
.split('\n')
|
||||
.map((line: string, idx: number) => (line === '' ? '' : indent + line))
|
||||
.join('\n')
|
||||
return indented
|
||||
})
|
||||
}
|
||||
|
||||
const resolvedYaml = resolveIncludes(yamlText)
|
||||
const parsed = yaml.load(resolvedYaml)
|
||||
const newOutput = JSON.stringify(parsed, null, 2)
|
||||
setOutput((prev) => (prev === newOutput ? prev : newOutput))
|
||||
} catch (err: any) {
|
||||
const msg = 'YAML parse error: ' + err.message
|
||||
const msg = 'YAML parse/include error: ' + err.message
|
||||
setOutput((prev) => (prev === msg ? prev : msg))
|
||||
}
|
||||
}, [id, incomingIds.join(','), yamlText, nodes.length, edges.length])
|
||||
|
||||
Reference in New Issue
Block a user