eventual rendfering

This commit is contained in:
2026-03-07 22:13:12 +01:00
parent 848305fd87
commit 5b07bd4887

View File

@@ -88,40 +88,102 @@ export const RenderingNode = memo(function RenderingNode({ id, width, height }:
const plantumlText = srcNode && srcNode.type === 'config' ? srcNode?.data?.plantuml ?? '' : ''
const srcData = srcNode?.data ?? {}
/** Set of node IDs that can affect this render node (configs in the chain + variables/functions feeding them) */
const connectedNodeIds = useMemo(() => {
const out = new Set<string>()
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
}
const resolveRef = (name: string) => {
const refName = name.replace(/\.(puml|html)$/, '').trim()
return nodes.find((n: any) => n.id === refName || n.data?.title === refName)?.id ?? refName
}
const getTemplateRefs = (content: string): string[] => {
const refs: string[] = []
const extendMatch = content.match(/\{\%\s*extends\s+["']([^"']+)["']\s*\%\}/)
if (extendMatch) refs.push(extendMatch[1].trim())
const includeRegex = /\{\%\s*include\s+["']([^"']+)["']\s*\%\}/g
let m
while ((m = includeRegex.exec(content)) !== null) refs.push(m[1].trim())
const importRegex = /\{\%\s*import\s+["']([^"']+)["']\s+as\s+\w+\s*\%\}/g
while ((m = importRegex.exec(content)) !== null) refs.push(m[1].trim())
return refs
}
const addConfigRefs = (nodeId: string, visited: Set<string>) => {
if (visited.has(nodeId)) return
const node = nodes.find((n: any) => n.id === nodeId && n.type === 'config')
if (!node) return
visited.add(nodeId)
out.add(nodeId)
const content = String(node.data?.plantuml ?? '')
for (const ref of getTemplateRefs(content)) {
const refId = resolveRef(ref)
if (refId && nodes.some((n: any) => n.id === refId && n.type === 'config') && isReachable(refId, id))
addConfigRefs(refId, visited)
}
}
const configVisited = new Set<string>()
for (const nid of incomingIds) {
const node = nodes.find((n: any) => n.id === nid)
if (node?.type === 'config') addConfigRefs(nid, configVisited)
else out.add(nid)
}
for (const e of edges) {
if (out.has(e.target)) out.add(e.source)
}
return out
}, [nodes, edges, id, incomingIds])
const configSignature = useMemo(
() =>
nodes
.filter((n: any) => n.type === 'config')
.filter((n: any) => n.type === 'config' && connectedNodeIds.has(n.id))
.map((n: any) => `${n.id}:${n.data?.title ?? ''}:${n.data?.plantuml ?? ''}`)
.sort()
.join('|'),
[nodes]
[nodes, connectedNodeIds]
)
const edgesSignature = useMemo(
() =>
edges
.filter((e: any) => connectedNodeIds.has(e.source) && (connectedNodeIds.has(e.target) || e.target === id))
.map((e: any) => `${e.source}->${e.target}`)
.sort()
.join('|'),
[edges]
[edges, connectedNodeIds, id]
)
const variablesSignature = useMemo(
() =>
nodes
.filter((n: any) => n.type === 'variable')
.filter((n: any) => n.type === 'variable' && connectedNodeIds.has(n.id))
.map((n: any) => `${n.id}:${n.data?.value}`)
.sort()
.join('|'),
[nodes]
[nodes, connectedNodeIds]
)
const functionsSignature = useMemo(
() =>
nodes
.filter((n: any) => n.type === 'function')
.filter((n: any) => n.type === 'function' && connectedNodeIds.has(n.id))
.map((n: any) => `${n.id}:${n.data?.body ?? ''}`)
.sort()
.join('|'),
[nodes]
[nodes, connectedNodeIds]
)
useEffect(() => {