fix: nunjuclk rendering
This commit is contained in:
@@ -480,12 +480,14 @@ function RenderingNodeComponent({ id, data, width, height, selected }: Props) {
|
||||
return
|
||||
}
|
||||
|
||||
setResolvedContent(afterNunjucks)
|
||||
// Collapse runs of newlines so {% for %} / {{ }} on their own lines don't leave blank lines
|
||||
const resolved = afterNunjucks.replace(/(\r?\n)(\s*\r?\n)+/g, '$1').trim()
|
||||
setResolvedContent(resolved)
|
||||
const typeRenderer = getConfigType(configTypeId)
|
||||
|
||||
try {
|
||||
const renderOptions = configTypeId === 'wireframe' ? { width: viewportWidth, height: viewportHeight } : undefined
|
||||
const htmlOrSvg = await typeRenderer.render(afterNunjucks, renderOptions)
|
||||
const htmlOrSvg = await typeRenderer.render(resolved, renderOptions)
|
||||
if (cancelled || thisRunId !== runIdRef.current) return
|
||||
setRenderedContent(htmlOrSvg)
|
||||
setError(null)
|
||||
@@ -539,6 +541,18 @@ function RenderingNodeComponent({ id, data, width, height, selected }: Props) {
|
||||
// Kroki and other SVG sources may prepend <?xml ... ?> so we detect by presence of <svg> tag
|
||||
const isSvgOutput = Boolean(renderedContent?.trim() && /<svg[\s>]/i.test(renderedContent.trim()))
|
||||
|
||||
/** Strip remaining Nunjucks tags from resolved content for display in raw view (so tags don't show as literal lines). */
|
||||
const rawDisplayContent = useMemo(() => {
|
||||
if (resolvedContent == null) return ''
|
||||
return resolvedContent
|
||||
.replace(/\{%[\s\S]*?%\}/g, '')
|
||||
.replace(/\{\{[\s\S]*?\}\}/g, '')
|
||||
.replace(/\{#[\s\S]*?#\}/g, '')
|
||||
.replace(/(\r?\n)\s*(\r?\n)/g, '$1$2')
|
||||
.replace(/^\s*\n|\n\s*$/g, (m) => (m === '\n' ? '\n' : ''))
|
||||
.trim()
|
||||
}, [resolvedContent])
|
||||
|
||||
/** Process SVG HTML so it keeps aspect ratio and fills the viewport (used only for display, not download). */
|
||||
const displayContent = useMemo(() => {
|
||||
if (!renderedContent || !isSvgOutput) return renderedContent
|
||||
@@ -650,16 +664,34 @@ function RenderingNodeComponent({ id, data, width, height, selected }: Props) {
|
||||
<ToggleGroup
|
||||
type="single"
|
||||
value={viewMode}
|
||||
onValueChange={(v) => v && (v === 'preview' || v === 'raw') && setViewMode(v)}
|
||||
onValueChange={(v) => {
|
||||
if (v === 'preview' || v === 'raw') setViewMode(v)
|
||||
}}
|
||||
aria-label="View mode"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="gap-0 rounded-md p-0.5 [&>button]:rounded-none [&>button:first-child]:rounded-l-md [&>button:last-child]:rounded-r-md [&>button:not(:first-child)]:border-l-0"
|
||||
>
|
||||
<ToggleGroupItem value="preview" aria-label="Preview" className="gap-1.5 px-2.5 h-7">
|
||||
<ToggleGroupItem
|
||||
value="preview"
|
||||
aria-label="Preview"
|
||||
className="gap-1.5 px-2.5 h-7"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setViewMode('preview')
|
||||
}}
|
||||
>
|
||||
Preview
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem value="raw" aria-label="Raw config" className="gap-1.5 px-2.5 h-7">
|
||||
<ToggleGroupItem
|
||||
value="raw"
|
||||
aria-label="Raw config"
|
||||
className="gap-1.5 px-2.5 h-7"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setViewMode('raw')
|
||||
}}
|
||||
>
|
||||
Raw
|
||||
</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
@@ -800,18 +832,18 @@ function RenderingNodeComponent({ id, data, width, height, selected }: Props) {
|
||||
size="icon"
|
||||
className="absolute top-2 right-2 z-10 h-7 w-7 shrink-0 rounded-md shadow-sm"
|
||||
onClick={() => {
|
||||
const text = resolvedContent ?? ''
|
||||
const text = rawDisplayContent
|
||||
if (text) {
|
||||
navigator.clipboard?.writeText(text).then(() => toast.success('Copied to clipboard')).catch(() => {})
|
||||
}
|
||||
}}
|
||||
disabled={!resolvedContent}
|
||||
disabled={!rawDisplayContent}
|
||||
title="Copy raw output"
|
||||
>
|
||||
<Copy className="size-3.5" />
|
||||
</Button>
|
||||
<CodeMirror
|
||||
value={resolvedContent ?? ''}
|
||||
value={rawDisplayContent}
|
||||
height={`${rawEditorHeight}px`}
|
||||
theme={theme}
|
||||
extensions={rawExtensions}
|
||||
@@ -917,7 +949,7 @@ function RenderingNodeComponent({ id, data, width, height, selected }: Props) {
|
||||
<BaseNodeFooter>
|
||||
<NodeFooterEdgeIndicators nodeId={id} nodeType="render">
|
||||
{viewMode === 'raw'
|
||||
? (resolvedContent != null ? `Raw · ${resolvedContent.length} chars` : '—')
|
||||
? (rawDisplayContent ? `Raw · ${rawDisplayContent.length} chars` : '—')
|
||||
: renderedContent
|
||||
? `${configType.label} · ${renderedContent.length} chars`
|
||||
: error
|
||||
|
||||
Reference in New Issue
Block a user