@bendyline/squisq 1.5.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -10
- package/dist/{Doc-BBVGq1_9.d.ts → Doc-ylqWKDc_.d.ts} +248 -37
- package/dist/{ImageEditDoc-FuyGtt6o.d.ts → ImageEditDoc-D828IXJ1.d.ts} +1 -1
- package/dist/annotationCoercion-Dr_DY9Hx.d.ts +86 -0
- package/dist/{chunk-VWUFZ6ZG.js → chunk-3E5F2XMR.js} +2 -29
- package/dist/chunk-3E5F2XMR.js.map +1 -0
- package/dist/chunk-4X3JQXNM.js +35 -0
- package/dist/chunk-4X3JQXNM.js.map +1 -0
- package/dist/{chunk-P3K7NLHF.js → chunk-5DKBFXPY.js} +31 -121
- package/dist/chunk-5DKBFXPY.js.map +1 -0
- package/dist/{chunk-DLXZMS5K.js → chunk-5J4HKRJF.js} +51 -3
- package/dist/chunk-5J4HKRJF.js.map +1 -0
- package/dist/chunk-5UYI3RJB.js +2503 -0
- package/dist/chunk-5UYI3RJB.js.map +1 -0
- package/dist/{chunk-BEQODJWV.js → chunk-66QO7XFB.js} +11 -291
- package/dist/chunk-66QO7XFB.js.map +1 -0
- package/dist/{chunk-KKNUBQ6Y.js → chunk-6PJRB2CF.js} +156 -91
- package/dist/chunk-6PJRB2CF.js.map +1 -0
- package/dist/{chunk-HWVFJAAH.js → chunk-AMIR72JP.js} +28 -10
- package/dist/chunk-AMIR72JP.js.map +1 -0
- package/dist/chunk-FVJUUTEM.js +74 -0
- package/dist/chunk-FVJUUTEM.js.map +1 -0
- package/dist/{chunk-5TYS5V3G.js → chunk-GF3BVNLU.js} +4127 -3538
- package/dist/chunk-GF3BVNLU.js.map +1 -0
- package/dist/{chunk-Q3ROPT5H.js → chunk-GZY66SDN.js} +1 -1
- package/dist/{chunk-Q3ROPT5H.js.map → chunk-GZY66SDN.js.map} +1 -1
- package/dist/chunk-JOQYPRDZ.js +127 -0
- package/dist/chunk-JOQYPRDZ.js.map +1 -0
- package/dist/{chunk-A4O7GIWE.js → chunk-LYNJEOAC.js} +10 -73
- package/dist/chunk-LYNJEOAC.js.map +1 -0
- package/dist/{chunk-LDQ2HJIX.js → chunk-PXLVXTLW.js} +252 -54
- package/dist/chunk-PXLVXTLW.js.map +1 -0
- package/dist/{chunk-TQWLI6S2.js → chunk-Q7LROV2H.js} +4 -2
- package/dist/{chunk-TQWLI6S2.js.map → chunk-Q7LROV2H.js.map} +1 -1
- package/dist/{chunk-T5UK6YOB.js → chunk-QTSJOY54.js} +60 -17
- package/dist/chunk-QTSJOY54.js.map +1 -0
- package/dist/chunk-QVANWDPH.js +2358 -0
- package/dist/chunk-QVANWDPH.js.map +1 -0
- package/dist/{chunk-GPLTCSXO.js → chunk-R2GC6RLD.js} +7 -7
- package/dist/chunk-R2GC6RLD.js.map +1 -0
- package/dist/chunk-R2YZTCLO.js +292 -0
- package/dist/chunk-R2YZTCLO.js.map +1 -0
- package/dist/chunk-S7A5D7ZJ.js +174 -0
- package/dist/chunk-S7A5D7ZJ.js.map +1 -0
- package/dist/chunk-T3TI7GSZ.js +884 -0
- package/dist/chunk-T3TI7GSZ.js.map +1 -0
- package/dist/{chunk-LTN6I7QW.js → chunk-TUWMK62B.js} +55 -4
- package/dist/chunk-TUWMK62B.js.map +1 -0
- package/dist/{chunk-IMSCRLLV.js → chunk-VR7UPJ7C.js} +35 -25
- package/dist/chunk-VR7UPJ7C.js.map +1 -0
- package/dist/doc/index.d.ts +2334 -5
- package/dist/doc/index.js +127 -33
- package/dist/generate/index.d.ts +7 -2
- package/dist/generate/index.js +1 -1
- package/dist/imageEdit/index.d.ts +9 -6
- package/dist/imageEdit/index.js +3 -3
- package/dist/index.d.ts +12 -10
- package/dist/index.js +246 -80
- package/dist/jsonForm/index.d.ts +7 -3
- package/dist/jsonForm/index.js +9 -4
- package/dist/markdown/index.d.ts +6 -70
- package/dist/markdown/index.js +13 -9
- package/dist/narration/index.d.ts +618 -0
- package/dist/narration/index.js +82 -0
- package/dist/recommend/index.d.ts +15 -1
- package/dist/recommend/index.js +2 -2
- package/dist/schemas/index.d.ts +28 -6
- package/dist/schemas/index.js +15 -13
- package/dist/spatial/index.d.ts +0 -1
- package/dist/spatial/index.js +1 -1
- package/dist/storage/index.js +1 -1
- package/dist/{themeLibrary-CehcJhzz.d.ts → themeLibrary-RjVgLpUi.d.ts} +10 -11
- package/dist/timing/index.js +5 -3
- package/dist/transform/index.d.ts +35 -24
- package/dist/transform/index.js +9 -10
- package/dist/{types-DlAZ7MW4.d.ts → types-BwMPl2CB.d.ts} +1 -1
- package/dist/{types-D98li1gV.d.ts → types-C4kiRn_k.d.ts} +3 -1
- package/dist/versions/index.d.ts +2 -1
- package/dist/versions/index.js +2 -2
- package/package.json +6 -6
- package/src/__tests__/applyNarrationTiming.test.ts +190 -0
- package/src/__tests__/applyRenderStyle.test.ts +3 -3
- package/src/__tests__/asciiDiagramBattle.test.ts +246 -0
- package/src/__tests__/asciiDiagramDetect.test.ts +162 -0
- package/src/__tests__/asciiDiagramMapping.test.ts +38 -0
- package/src/__tests__/asciiDiagramParse.test.ts +233 -0
- package/src/__tests__/asciiDiagramPipeline.test.ts +273 -0
- package/src/__tests__/asciiDiagramRender.test.ts +162 -0
- package/src/__tests__/asciiDiagramRepair.test.ts +84 -0
- package/src/__tests__/asciiTimelineDetect.test.ts +157 -0
- package/src/__tests__/asciiTimelineParse.test.ts +205 -0
- package/src/__tests__/asciiTimelinePipeline.test.ts +349 -0
- package/src/__tests__/asciiTimelineRender.test.ts +376 -0
- package/src/__tests__/attrTokens.test.ts +5 -0
- package/src/__tests__/contentContainer.test.ts +43 -0
- package/src/__tests__/customTemplatesFrontmatter.test.ts +0 -15
- package/src/__tests__/dataTable.test.ts +25 -15
- package/src/__tests__/diagramBlock.test.ts +3 -3
- package/src/__tests__/diagramText.test.ts +26 -0
- package/src/__tests__/docToMarkdownMedia.test.ts +83 -0
- package/src/__tests__/drawingBlock.test.ts +3 -3
- package/src/__tests__/fixtures/asciiDiagramBattle.ts +512 -0
- package/src/__tests__/fixtures/asciiDiagrams.ts +287 -0
- package/src/__tests__/fixtures/asciiTimelines.ts +35 -0
- package/src/__tests__/fixtures/treeviewFixtures.ts +243 -0
- package/src/__tests__/getLayers.test.ts +32 -18
- package/src/__tests__/getLayersFallback.test.ts +8 -8
- package/src/__tests__/imageEditVersions.test.ts +2 -0
- package/src/__tests__/jsonForm.pointer.test.ts +47 -1
- package/src/__tests__/layoutBlock.test.ts +3 -3
- package/src/__tests__/majorApiTypes.test.ts +18 -0
- package/src/__tests__/markdown.test.ts +41 -0
- package/src/__tests__/matchFontFamily.test.ts +114 -0
- package/src/__tests__/materializeBlockLayers.test.ts +135 -0
- package/src/__tests__/materializeTestUtils.ts +17 -0
- package/src/__tests__/narrationAlign.test.ts +150 -0
- package/src/__tests__/narrationFeatures.test.ts +71 -0
- package/src/__tests__/narrationNuclei.test.ts +45 -0
- package/src/__tests__/narrationPacing.test.ts +189 -0
- package/src/__tests__/narrationScript.test.ts +149 -0
- package/src/__tests__/narrationSessionRepro.test.ts +62 -0
- package/src/__tests__/narrationSidecar.test.ts +88 -0
- package/src/__tests__/narrationSyllables.test.ts +65 -0
- package/src/__tests__/narrationTestSignals.ts +167 -0
- package/src/__tests__/narrationVad.test.ts +66 -0
- package/src/__tests__/resolveDocTheme.test.ts +16 -2
- package/src/__tests__/rootExports.test.ts +18 -0
- package/src/__tests__/scopedContentContainer.test.ts +20 -0
- package/src/__tests__/shapeGeometry.test.ts +12 -0
- package/src/__tests__/templateAnnotationParse.test.ts +10 -0
- package/src/__tests__/templateInputs.test.ts +69 -0
- package/src/__tests__/templateMetadata.test.ts +2 -1
- package/src/__tests__/templates.test.ts +143 -17
- package/src/__tests__/themeCompile.test.ts +49 -22
- package/src/__tests__/transformProvenance.test.ts +160 -0
- package/src/__tests__/transformV2.test.ts +40 -14
- package/src/__tests__/treeviewBattle.test.ts +76 -0
- package/src/__tests__/treeviewDetect.test.ts +168 -0
- package/src/__tests__/treeviewParse.test.ts +118 -0
- package/src/__tests__/treeviewPipeline.test.ts +183 -0
- package/src/__tests__/treeviewRender.test.ts +91 -0
- package/src/__tests__/versions.test.ts +44 -0
- package/src/doc/applyNarrationTiming.ts +244 -0
- package/src/doc/asciiDiagram/chars.ts +210 -0
- package/src/doc/asciiDiagram/detect.ts +175 -0
- package/src/doc/asciiDiagram/index.ts +38 -0
- package/src/doc/asciiDiagram/mapping.ts +225 -0
- package/src/doc/asciiDiagram/parse.ts +1095 -0
- package/src/doc/asciiDiagram/render.ts +963 -0
- package/src/doc/asciiDiagram/repair.ts +400 -0
- package/src/doc/asciiDiagram/types.ts +65 -0
- package/src/doc/asciiTimeline/detect.ts +138 -0
- package/src/doc/asciiTimeline/index.ts +26 -0
- package/src/doc/asciiTimeline/mapping.ts +43 -0
- package/src/doc/asciiTimeline/parse.ts +870 -0
- package/src/doc/asciiTimeline/render.ts +427 -0
- package/src/doc/asciiTimeline/types.ts +73 -0
- package/src/doc/asciiTimeline/wrappedFlow.ts +427 -0
- package/src/doc/audioMapping.ts +60 -46
- package/src/doc/customTemplatesFrontmatter.ts +0 -41
- package/src/doc/docToMarkdown.ts +70 -2
- package/src/doc/index.ts +76 -4
- package/src/doc/markdownToDoc.ts +135 -1
- package/src/doc/materializeBlockLayers.ts +304 -0
- package/src/doc/mediaAnnotations.ts +20 -0
- package/src/doc/resolveDocTheme.ts +8 -7
- package/src/doc/templateInputs.ts +185 -2
- package/src/doc/templates/__tests__/customTemplateRegistry.test.ts +22 -8
- package/src/doc/templates/diagramBlock.ts +237 -38
- package/src/doc/templates/fallbackBlock.ts +1 -1
- package/src/doc/templates/index.ts +134 -279
- package/src/doc/templates/inputDescriptors.ts +20 -1
- package/src/doc/templates/metadata.ts +10 -0
- package/src/doc/templates/persistentLayers.ts +12 -126
- package/src/doc/templates/registry.ts +88 -0
- package/src/doc/templates/templateNames.ts +22 -0
- package/src/doc/templates/timelineBlock.ts +613 -0
- package/src/doc/templates/treeBlock.ts +131 -0
- package/src/doc/treeview/chars.ts +72 -0
- package/src/doc/treeview/detect.ts +145 -0
- package/src/doc/treeview/index.ts +30 -0
- package/src/doc/treeview/mapping.ts +95 -0
- package/src/doc/treeview/parse.ts +201 -0
- package/src/doc/treeview/render.ts +41 -0
- package/src/doc/treeview/types.ts +43 -0
- package/src/doc/utils/applyRenderStyle.ts +2 -9
- package/src/doc/utils/diagramText.ts +78 -0
- package/src/doc/utils/shapeGeometry.ts +67 -5
- package/src/doc/validate.ts +1 -1
- package/src/generate/templateMapper.ts +7 -0
- package/src/imageEdit/export.ts +6 -5
- package/src/imageEdit/versionPaths.ts +13 -26
- package/src/imageEdit/versions.ts +21 -100
- package/src/index.ts +1 -0
- package/src/internal/immutable.ts +58 -0
- package/src/jsonForm/index.ts +9 -1
- package/src/jsonForm/pointer.ts +68 -23
- package/src/markdown/attrTokens.ts +7 -5
- package/src/markdown/index.ts +1 -0
- package/src/markdown/stringify.ts +4 -9
- package/src/markdown/utils.ts +36 -14
- package/src/narration/align.ts +514 -0
- package/src/narration/features.ts +231 -0
- package/src/narration/index.ts +86 -0
- package/src/narration/nuclei.ts +118 -0
- package/src/narration/pacing.ts +211 -0
- package/src/narration/script.ts +239 -0
- package/src/narration/session.ts +100 -0
- package/src/narration/sidecar.ts +187 -0
- package/src/narration/syllables.ts +85 -0
- package/src/narration/trace.ts +50 -0
- package/src/narration/types.ts +299 -0
- package/src/narration/vad.ts +131 -0
- package/src/recommend/numberHighlight.ts +25 -0
- package/src/recommend/templates.ts +108 -12
- package/src/schemas/BlockTemplates.ts +156 -7
- package/src/schemas/Doc.ts +72 -9
- package/src/schemas/Media.ts +12 -2
- package/src/schemas/Theme.ts +45 -25
- package/src/schemas/Viewport.ts +2 -2
- package/src/schemas/fontStacks.ts +79 -0
- package/src/schemas/themeCompile.ts +15 -0
- package/src/schemas/themeConstants.ts +2 -0
- package/src/schemas/themeLibrary.ts +25 -19
- package/src/schemas/themeValidator.ts +1 -1
- package/src/spatial/Geohash.ts +0 -3
- package/src/storage/ContentContainer.ts +17 -9
- package/src/storage/ScopedContentContainer.ts +45 -15
- package/src/transform/applyTransform.ts +5 -5
- package/src/transform/index.ts +3 -1
- package/src/transform/registry.ts +169 -49
- package/src/transform/templateSelector.ts +21 -2
- package/src/transform/timingAllocator.ts +152 -21
- package/src/transform/types.ts +14 -1
- package/src/versions/gitignore.ts +34 -0
- package/src/versions/index.ts +2 -0
- package/src/versions/operations.ts +18 -104
- package/src/versions/paths.ts +13 -28
- package/src/versions/snapshotStore.ts +202 -0
- package/src/versions/types.ts +3 -1
- package/dist/chunk-5TYS5V3G.js.map +0 -1
- package/dist/chunk-A4O7GIWE.js.map +0 -1
- package/dist/chunk-BEQODJWV.js.map +0 -1
- package/dist/chunk-DLXZMS5K.js.map +0 -1
- package/dist/chunk-GPLTCSXO.js.map +0 -1
- package/dist/chunk-HWVFJAAH.js.map +0 -1
- package/dist/chunk-IMSCRLLV.js.map +0 -1
- package/dist/chunk-JELIRVDP.js +0 -24
- package/dist/chunk-JELIRVDP.js.map +0 -1
- package/dist/chunk-KKNUBQ6Y.js.map +0 -1
- package/dist/chunk-LDQ2HJIX.js.map +0 -1
- package/dist/chunk-LTN6I7QW.js.map +0 -1
- package/dist/chunk-P3K7NLHF.js.map +0 -1
- package/dist/chunk-T5UK6YOB.js.map +0 -1
- package/dist/chunk-UY7KGQ5R.js +0 -192
- package/dist/chunk-UY7KGQ5R.js.map +0 -1
- package/dist/chunk-VLJJHDAC.js +0 -218
- package/dist/chunk-VLJJHDAC.js.map +0 -1
- package/dist/chunk-VWUFZ6ZG.js.map +0 -1
- package/dist/story/index.d.ts +0 -1801
- package/dist/story/index.js +0 -279
- package/src/doc/getLayers.ts +0 -195
- /package/dist/{story → narration}/index.js.map +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/doc/utils/animationUtils.ts","../src/doc/utils/imageTreatment.ts","../src/doc/docToMarkdown.ts","../src/doc/resolveDocTheme.ts","../src/doc/applyNarrationTiming.ts","../src/doc/audioMapping.ts","../src/doc/validate.ts","../src/doc/asciiDiagram/render.ts","../src/doc/asciiDiagram/repair.ts","../src/doc/asciiTimeline/render.ts","../src/doc/treeview/render.ts"],"sourcesContent":["/**\n * Animation Utilities\n *\n * Helper functions for mapping Doc animations to CSS classes and styles.\n * Generates the appropriate animation class names and CSS custom properties\n * for duration, delay, and easing.\n *\n * This is shared code used by both site and efb-app doc renderers.\n */\n\nimport type {\n Animation,\n AnimationType,\n TransitionDirection,\n TransitionType,\n} from '../../schemas/Doc.js';\n\ninterface AnimationResult {\n /** CSS class name to apply */\n className: string;\n /** Inline styles for CSS custom properties */\n style: Record<string, string>;\n}\n\n/**\n * Get CSS class and styles for an animation.\n */\nexport function getAnimationStyle(\n animation: Animation | undefined,\n _currentTime: number = 0,\n): AnimationResult {\n if (!animation || animation.type === 'none') {\n return { className: '', style: {} };\n }\n\n const className = getAnimationClassName(animation);\n const style = getAnimationCSSVars(animation);\n\n return { className, style };\n}\n\n/**\n * Map animation type to CSS class name.\n */\nfunction getAnimationClassName(animation: Animation): string {\n const { type, direction, panDirection } = animation;\n\n switch (type) {\n case 'fadeIn':\n return 'anim-fadeIn';\n case 'fadeOut':\n return 'anim-fadeOut';\n case 'slowZoom':\n // Slow zoom (Ken Burns style) has variants based on direction and pan\n if (panDirection === 'left') return 'anim-slowZoom-panLeft';\n if (panDirection === 'right') return 'anim-slowZoom-panRight';\n if (direction === 'out') return 'anim-slowZoom-out';\n return 'anim-slowZoom-in';\n case 'zoomIn':\n return 'anim-zoomIn';\n case 'zoomOut':\n return 'anim-zoomOut';\n case 'panLeft':\n return 'anim-panLeft';\n case 'panRight':\n return 'anim-panRight';\n case 'typewriter':\n return 'anim-typewriter';\n default:\n return '';\n }\n}\n\n/**\n * Generate CSS custom properties for animation timing.\n */\nfunction getAnimationCSSVars(animation: Animation): Record<string, string> {\n const vars: Record<string, string> = {};\n\n if (animation.duration !== undefined) {\n vars['--anim-duration'] = `${animation.duration}s`;\n }\n\n if (animation.delay !== undefined) {\n vars['--anim-delay'] = `${animation.delay}s`;\n }\n\n if (animation.easing) {\n vars['--anim-easing'] = animation.easing;\n }\n\n return vars;\n}\n\n/**\n * Get default duration for an animation type.\n */\nexport function getDefaultAnimationDuration(type: AnimationType): number {\n switch (type) {\n case 'slowZoom':\n case 'panLeft':\n case 'panRight':\n return 8; // Long, slow animations\n case 'typewriter':\n return 3;\n case 'fadeIn':\n case 'fadeOut':\n return 1;\n case 'zoomIn':\n case 'zoomOut':\n return 0.5;\n default:\n return 1;\n }\n}\n\n/**\n * Get transition class for slide entry/exit.\n */\nexport function getTransitionClass(\n type: TransitionType,\n entering: boolean,\n direction?: TransitionDirection,\n): string {\n if (type === 'cut') return '';\n const mode = entering ? 'enter' : 'exit';\n return `transition-${getTransitionVisualClass(type, direction)}-${mode}`;\n}\n\ntype TransitionVisualClass =\n | 'cut'\n | 'fade'\n | 'dissolve'\n | 'pushLeft'\n | 'pushRight'\n | 'pushUp'\n | 'pushDown'\n | 'wipeLeft'\n | 'wipeRight'\n | 'wipeUp'\n | 'wipeDown'\n | 'splitHorizontal'\n | 'splitVertical'\n | 'revealLeft'\n | 'revealRight'\n | 'revealUp'\n | 'revealDown'\n | 'random'\n | 'randomBarsHorizontal'\n | 'randomBarsVertical'\n | 'shapeCircle'\n | 'shapeDiamond'\n | 'shapePlus'\n | 'uncoverLeft'\n | 'uncoverRight'\n | 'uncoverUp'\n | 'uncoverDown'\n | 'coverLeft'\n | 'coverRight'\n | 'coverUp'\n | 'coverDown'\n | 'zoom'\n | 'panLeft'\n | 'panRight'\n | 'panUp'\n | 'panDown'\n | 'flash'\n | 'newsflash'\n | 'fallOver'\n | 'drape'\n | 'curtains'\n | 'wind'\n | 'prestige'\n | 'fracture'\n | 'crush'\n | 'peelOff'\n | 'pageCurl'\n | 'pageCurlDouble'\n | 'pageCurlSingle'\n | 'airplane'\n | 'origami'\n | 'checkerboard'\n | 'blindsHorizontal'\n | 'blindsVertical'\n | 'clock'\n | 'ripple'\n | 'honeycomb'\n | 'glitter'\n | 'vortex'\n | 'shred'\n | 'switch'\n | 'flip'\n | 'gallery'\n | 'cube'\n | 'doors'\n | 'box'\n | 'ferrisWheel'\n | 'conveyor'\n | 'rotate'\n | 'window'\n | 'orbit'\n | 'flyThrough'\n | 'morph'\n | 'combHorizontal'\n | 'combVertical'\n | 'pullLeft'\n | 'pullRight'\n | 'pullUp'\n | 'pullDown'\n | 'stripsLeft'\n | 'stripsRight'\n | 'stripsUp'\n | 'stripsDown'\n | 'wedge'\n | 'wheel'\n | 'wheelReverse'\n | 'prism'\n | 'warp'\n | 'slideLeft'\n | 'slideRight'\n | 'slideUp'\n | 'slideDown';\n\nconst TRANSITION_VISUAL_CLASS_BY_TYPE: Record<TransitionType, TransitionVisualClass> = {\n airplane: 'airplane',\n blinds: 'blindsHorizontal',\n box: 'box',\n checker: 'checkerboard',\n checkerboard: 'checkerboard',\n circle: 'shapeCircle',\n clock: 'clock',\n comb: 'combHorizontal',\n conveyor: 'conveyor',\n cover: 'coverLeft',\n crush: 'crush',\n cube: 'cube',\n curtains: 'curtains',\n cut: 'cut',\n diamond: 'shapeDiamond',\n dissolve: 'dissolve',\n doors: 'doors',\n drape: 'drape',\n fade: 'fade',\n fallOver: 'fallOver',\n ferris: 'ferrisWheel',\n ferrisWheel: 'ferrisWheel',\n flash: 'flash',\n flip: 'flip',\n flyThrough: 'flyThrough',\n flythrough: 'flyThrough',\n fracture: 'fracture',\n gallery: 'gallery',\n glitter: 'glitter',\n honeycomb: 'honeycomb',\n morph: 'morph',\n newsflash: 'newsflash',\n orbit: 'orbit',\n origami: 'origami',\n pageCurl: 'pageCurl',\n pageCurlDouble: 'pageCurlDouble',\n pageCurlSingle: 'pageCurlSingle',\n pan: 'panLeft',\n peelOff: 'peelOff',\n plus: 'shapePlus',\n prestige: 'prestige',\n prism: 'prism',\n pull: 'pullLeft',\n push: 'pushLeft',\n random: 'random',\n randomBar: 'randomBarsHorizontal',\n randomBars: 'randomBarsVertical',\n reveal: 'revealLeft',\n ripple: 'ripple',\n rotate: 'rotate',\n shape: 'shapeCircle',\n shred: 'shred',\n slideDown: 'slideDown',\n slideLeft: 'slideLeft',\n slideRight: 'slideRight',\n slideUp: 'slideUp',\n split: 'splitHorizontal',\n strips: 'stripsLeft',\n switch: 'switch',\n uncover: 'uncoverLeft',\n vortex: 'vortex',\n warp: 'warp',\n wedge: 'wedge',\n wheel: 'wheel',\n wheelReverse: 'wheelReverse',\n wind: 'wind',\n window: 'window',\n wipe: 'wipeLeft',\n zoom: 'zoom',\n};\n\nfunction getTransitionVisualClass(\n type: TransitionType,\n direction?: TransitionDirection,\n): TransitionVisualClass {\n switch (type) {\n case 'randomBars':\n case 'randomBar':\n return axisClass('randomBars', direction, type === 'randomBar' ? 'Horizontal' : 'Vertical');\n case 'comb':\n return axisClass('comb', direction, 'Horizontal');\n case 'blinds':\n return axisClass('blinds', direction, 'Horizontal');\n case 'split':\n return axisClass('split', direction, 'Horizontal');\n case 'push':\n return directionalClass('push', direction, 'Left');\n case 'wipe':\n return directionalClass('wipe', direction, 'Left');\n case 'cover':\n return directionalClass('cover', direction, 'Left');\n case 'uncover':\n return directionalClass('uncover', direction, 'Left');\n case 'pull':\n return directionalClass('pull', direction, 'Left');\n case 'reveal':\n return directionalClass('reveal', direction, 'Left');\n case 'strips':\n return directionalClass('strips', direction, 'Left');\n case 'pan':\n return directionalClass('pan', direction, 'Left');\n default:\n return TRANSITION_VISUAL_CLASS_BY_TYPE[type];\n }\n}\n\nfunction directionalClass(\n prefix: 'cover' | 'pan' | 'pull' | 'push' | 'reveal' | 'strips' | 'uncover' | 'wipe',\n direction: TransitionDirection | undefined,\n fallback: 'Left' | 'Right' | 'Up' | 'Down',\n): TransitionVisualClass {\n const suffix = directionSuffix(direction, fallback);\n return `${prefix}${suffix}` as TransitionVisualClass;\n}\n\nfunction axisClass(\n prefix: 'blinds' | 'comb' | 'randomBars' | 'split',\n direction: TransitionDirection | undefined,\n fallback: 'Horizontal' | 'Vertical',\n): TransitionVisualClass {\n const suffix = axisSuffix(direction, fallback);\n return `${prefix}${suffix}` as TransitionVisualClass;\n}\n\nfunction directionSuffix(\n direction: TransitionDirection | undefined,\n fallback: 'Left' | 'Right' | 'Up' | 'Down',\n): 'Left' | 'Right' | 'Up' | 'Down' {\n switch (direction) {\n case 'right':\n return 'Right';\n case 'up':\n return 'Up';\n case 'down':\n return 'Down';\n case 'left':\n default:\n return fallback;\n }\n}\n\nfunction axisSuffix(\n direction: TransitionDirection | undefined,\n fallback: 'Horizontal' | 'Vertical',\n): 'Horizontal' | 'Vertical' {\n switch (direction) {\n case 'vertical':\n case 'up':\n case 'down':\n return 'Vertical';\n case 'horizontal':\n case 'left':\n case 'right':\n return 'Horizontal';\n default:\n return fallback;\n }\n}\n\n/**\n * Calculate animation progress (0-1) based on current time.\n */\nexport function getAnimationProgress(\n animation: Animation,\n currentTime: number,\n slideDuration: number,\n): number {\n const delay = animation.delay || 0;\n const duration = animation.duration || slideDuration;\n\n if (currentTime < delay) return 0;\n if (currentTime >= delay + duration) return 1;\n\n return (currentTime - delay) / duration;\n}\n","/**\n * Image treatment → CSS filter derivation.\n *\n * Treatments are theme-level photographic grades (see `ImageTreatment` in\n * [Doc.ts](../../schemas/Doc.ts)). They compile to plain CSS `filter`\n * functions so the same string works on a foreignObject `<img>`, an SVG\n * `<image>` element, and in headless frame capture — no SVG filter defs to\n * coordinate, no renderer-specific code paths.\n */\n\nimport type { ImageTreatment } from '../../schemas/Doc.js';\nimport { hexHueDegrees } from '../../schemas/colorUtils.js';\n\n/** Sepia's intrinsic tint hue (deg) — duotone rotates from here to the target. */\nconst SEPIA_HUE_DEGREES = 40;\n\nconst clamp01 = (v: number) => Math.max(0, Math.min(1, v));\nconst r2 = (v: number) => Math.round(v * 100) / 100;\n\n/**\n * Build the CSS `filter` value for a treatment and/or blur.\n * Returns `undefined` when there is nothing to apply.\n */\nexport function cssFilterForTreatment(\n treatment?: ImageTreatment,\n blur?: number,\n): string | undefined {\n const parts: string[] = [];\n\n if (blur != null && blur > 0) {\n parts.push(`blur(${Math.round(blur)}px)`);\n }\n\n if (treatment && treatment.type !== 'none') {\n const s = clamp01(treatment.strength ?? 0.6);\n switch (treatment.type) {\n case 'mono':\n // Archival black & white with a whisper of contrast to keep depth.\n parts.push(`grayscale(${r2(s)})`, `contrast(${r2(1 + 0.05 * s)})`);\n break;\n case 'duotone': {\n // Classic CSS duotone approximation: flatten to gray, tint through\n // sepia (intrinsic hue ~40°), rotate to the target hue, re-saturate.\n const hue = hexHueDegrees(treatment.color ?? '#3d5a80');\n parts.push(\n 'grayscale(1)',\n `sepia(${r2(Math.max(0.35, s))})`,\n `hue-rotate(${Math.round(hue - SEPIA_HUE_DEGREES)}deg)`,\n `saturate(${r2(1 + s)})`,\n );\n break;\n }\n case 'warm':\n // Partial sepia is a well-behaved warmer; slight saturation lift.\n parts.push(`sepia(${r2(0.4 * s)})`, `saturate(${r2(1 + 0.15 * s)})`);\n break;\n case 'cool':\n // Desaturate a touch and nudge warm tones toward magenta/blue —\n // small rotations read as a grade, large ones wreck hues.\n parts.push(\n `saturate(${r2(1 - 0.25 * s)})`,\n `hue-rotate(${Math.round(-12 * s)}deg)`,\n `contrast(${r2(1 + 0.06 * s)})`,\n );\n break;\n }\n }\n\n return parts.length > 0 ? parts.join(' ') : undefined;\n}\n","/**\n * Doc → Markdown Conversion\n *\n * Converts a Doc with a heading-driven Block hierarchy back into a\n * MarkdownDocument. This is the reverse of markdownToDoc() and enables\n * round-tripping: edit a Doc's block tree, then serialize back to markdown.\n *\n * **Algorithm:**\n * Walk the block tree depth-first. For each block:\n * 1. If it has a `sourceHeading`, emit that heading node\n * 2. Emit all nodes in `contents`\n * 3. Recurse into `children`\n *\n * @example\n * ```ts\n * import { markdownToDoc, docToMarkdown } from '@bendyline/squisq/doc';\n * import { parseMarkdown, stringifyMarkdown } from '@bendyline/squisq/markdown';\n *\n * const md = '# Hello\\n\\nWorld\\n';\n * const doc = markdownToDoc(parseMarkdown(md));\n * const roundTripped = stringifyMarkdown(docToMarkdown(doc));\n * ```\n */\n\nimport type { Doc, Block } from '../schemas/Doc.js';\nimport type { MediaClip } from '../schemas/Media.js';\nimport type {\n MarkdownDocument,\n MarkdownBlockNode,\n MarkdownHeading,\n MarkdownParagraph,\n} from '../markdown/types.js';\nimport { serializeAnnotation } from '../markdown/attrTokens.js';\nimport { flattenBlocks } from './markdownToDoc.js';\nimport {\n FRONTMATTER_CUSTOM_TEMPLATES_KEY,\n writeCustomTemplatesToFrontmatter,\n} from './customTemplatesFrontmatter.js';\nimport {\n FRONTMATTER_CUSTOM_THEMES_KEY,\n writeCustomThemesToFrontmatter,\n} from './customThemesFrontmatter.js';\n\nconst TRANSITION_PARAM_KEYS = ['transition', 'transitionDuration', 'transitionDirection'] as const;\n\n/**\n * Convert a Doc with heading-driven blocks back to a MarkdownDocument.\n *\n * Walks the block tree depth-first, emitting heading nodes and contents\n * in document order. Blocks without a `sourceHeading` (preamble blocks)\n * emit only their contents.\n *\n * If a block has a `template` or `templateOverrides` that aren't already\n * reflected in the heading's `templateAnnotation`, the annotation is\n * injected so the round-trip preserves template assignments.\n *\n * @param doc - A Doc whose blocks may have `sourceHeading`, `contents`, and `children`\n * @returns A MarkdownDocument that can be stringified back to markdown\n */\nexport function docToMarkdown(doc: Doc): MarkdownDocument {\n const children: MarkdownBlockNode[] = [];\n\n // Media clips were LIFTED out of block contents at parse time\n // (`extractMediaFromContents`); re-insert their authoring annotations so\n // the round-trip doesn't silently drop narration/clip references.\n // Doc-anchored clips whose home block still exists ride back into that\n // block's body; homeless ones (programmatic clips, or a preamble block\n // that was dropped once emptied) emit at the document top — the\n // canonical authored position.\n const blockIds = new Set(flattenBlocks(doc.blocks).map((b) => b.id));\n const docMediaByBlock = new Map<string, MediaClip[]>();\n const homelessDocMedia: MediaClip[] = [];\n for (const clip of doc.documentMedia ?? []) {\n if (clip.origin && blockIds.has(clip.origin.blockId)) {\n const list = docMediaByBlock.get(clip.origin.blockId) ?? [];\n list.push(clip);\n docMediaByBlock.set(clip.origin.blockId, list);\n } else {\n homelessDocMedia.push(clip);\n }\n }\n for (const clip of homelessDocMedia) {\n children.push(synthesizeMediaParagraph(clip));\n }\n\n function emitBlock(block: Block): void {\n // Emit the heading node if present\n if (block.sourceHeading) {\n const heading = ensureAnnotation(block, block.sourceHeading);\n children.push(heading);\n } else if (block.standaloneAnnotation) {\n // Heading-less standalone block: re-emit its `{[…]}` annotation as a\n // paragraph before its contents. The serializer's quoting is paired\n // with the tokenizer, and stringifyMarkdown un-escapes `{[…]}` spans,\n // so the annotation round-trips.\n children.push(synthesizeAnnotationParagraph(block));\n }\n\n // Emit body content, with this block's media annotations re-inserted\n // at their original positions. `origin.index` refers to the ORIGINAL\n // contents array (which included every annotation), so ascending\n // insertion into the stripped contents reproduces the source order.\n const clips = [...(block.media ?? []), ...(docMediaByBlock.get(block.id) ?? [])];\n if (clips.length > 0) {\n const contents = [...(block.contents ?? [])];\n const anchored = clips\n .filter((clip) => clip.origin)\n .sort((a, b) => a.origin!.index - b.origin!.index);\n for (const clip of anchored) {\n contents.splice(\n Math.min(clip.origin!.index, contents.length),\n 0,\n synthesizeMediaParagraph(clip),\n );\n }\n // Origin-less block clips (programmatic) sit right under the heading.\n for (const clip of clips.filter((c) => !c.origin).reverse()) {\n contents.unshift(synthesizeMediaParagraph(clip));\n }\n children.push(...contents);\n } else if (block.contents) {\n children.push(...block.contents);\n }\n\n // Recurse into children (sub-headings)\n if (block.children) {\n for (const child of block.children) {\n emitBlock(child);\n }\n }\n }\n\n for (const block of doc.blocks) {\n emitBlock(block);\n }\n\n // Merge `Doc.customTemplates` into the outgoing frontmatter so the\n // markdown remains the source-of-truth: edits made via the editor's\n // TemplateDesigner round-trip through `docToMarkdown` →\n // `stringifyMarkdown` and are visible to anyone reading the file.\n const customPayload = writeCustomTemplatesToFrontmatter(doc.customTemplates);\n let frontmatter = doc.frontmatter;\n if (customPayload) {\n frontmatter = { ...(frontmatter ?? {}), [FRONTMATTER_CUSTOM_TEMPLATES_KEY]: customPayload };\n } else if (frontmatter && FRONTMATTER_CUSTOM_TEMPLATES_KEY in frontmatter) {\n // The doc has no custom templates anymore — drop the stale\n // frontmatter key so the markdown reflects the current state.\n const { [FRONTMATTER_CUSTOM_TEMPLATES_KEY]: _drop, ...rest } = frontmatter;\n void _drop;\n frontmatter = rest;\n }\n\n // Mirror the same round-trip for `Doc.customThemes` (the theme analog).\n const customThemesPayload = writeCustomThemesToFrontmatter(doc.customThemes);\n if (customThemesPayload) {\n frontmatter = { ...(frontmatter ?? {}), [FRONTMATTER_CUSTOM_THEMES_KEY]: customThemesPayload };\n } else if (frontmatter && FRONTMATTER_CUSTOM_THEMES_KEY in frontmatter) {\n const { [FRONTMATTER_CUSTOM_THEMES_KEY]: _dropTheme, ...rest } = frontmatter;\n void _dropTheme;\n frontmatter = rest;\n }\n\n return {\n type: 'document',\n children,\n ...(frontmatter && Object.keys(frontmatter).length > 0 ? { frontmatter } : {}),\n };\n}\n\n/**\n * Build the synthesized annotation paragraph for a heading-less standalone\n * block: `{[templateName key=value …]}` from its `sourceAnnotation.template`\n * and current `templateOverrides` (edits round-trip through the latter).\n */\nfunction synthesizeAnnotationParagraph(block: Block): MarkdownParagraph {\n const text = serializeAnnotation(block.sourceAnnotation?.template, block.templateOverrides);\n return { type: 'paragraph', children: [{ type: 'text', value: text }] };\n}\n\n/**\n * Re-synthesize the authoring paragraph for a media clip. The extraction\n * kept the exact source text (`origin.raw`) — emit it verbatim so quoting,\n * param order, and `mm:ss` time forms stay byte-stable. Programmatic clips\n * (no raw) serialize canonically: src, anchor, then timing params.\n */\nfunction synthesizeMediaParagraph(clip: MediaClip): MarkdownParagraph {\n if (clip.origin?.raw) {\n return { type: 'paragraph', children: [{ type: 'text', value: clip.origin.raw }] };\n }\n const params: Record<string, string> = { src: clip.src };\n if (clip.anchor === 'document') params.anchor = 'document';\n if (clip.startAt) params.startAt = String(clip.startAt);\n if (clip.clipStart != null) params.clipStart = String(clip.clipStart);\n if (clip.clipEnd != null) params.clipEnd = String(clip.clipEnd);\n if (clip.spillover) params.spillover = 'true';\n return {\n type: 'paragraph',\n children: [{ type: 'text', value: serializeAnnotation(clip.kind, params) }],\n };\n}\n\n/**\n * Ensure the heading's `templateAnnotation` reflects the block's\n * template and templateOverrides. Returns a (possibly cloned) heading.\n */\nfunction ensureAnnotation(block: Block, heading: MarkdownHeading): MarkdownHeading {\n const { attributes, transitionParams } = ensureTransitionMetadata(block, heading);\n\n // If the block has a non-default template or overrides, inject an annotation\n const hasExplicitTemplate =\n block.template && block.template !== 'sectionHeader' && block.autoTemplate !== true;\n const hasOverrides = block.templateOverrides && Object.keys(block.templateOverrides).length > 0;\n\n let templateAnnotation = heading.templateAnnotation;\n if (!templateAnnotation && (hasExplicitTemplate || hasOverrides || transitionParams)) {\n templateAnnotation = {\n ...(hasExplicitTemplate ? { template: block.template ?? 'sectionHeader' } : {}),\n ...(hasOverrides ? { params: block.templateOverrides } : {}),\n };\n }\n\n if (transitionParams) {\n templateAnnotation = {\n ...(templateAnnotation ?? {}),\n params: {\n ...(templateAnnotation?.params ?? {}),\n ...transitionParams,\n },\n };\n }\n\n if (attributes === heading.attributes && templateAnnotation === heading.templateAnnotation) {\n return heading;\n }\n\n return { ...heading, children: [...heading.children], attributes, templateAnnotation };\n}\n\nfunction ensureTransitionMetadata(\n block: Block,\n heading: MarkdownHeading,\n): {\n attributes: MarkdownHeading['attributes'];\n transitionParams: Record<string, string> | undefined;\n} {\n const transition = block.transition;\n if (!transition) {\n return { attributes: heading.attributes, transitionParams: undefined };\n }\n\n // The transition is written to the squisq-native `{[…]}` params for\n // author-facing markdown, and to `attributes.blockMeta` for the in-memory\n // Doc → MarkdownDocument → Doc path (which does not re-parse string params).\n const attrs = removeTransitionParams(heading.attributes) ?? {};\n const attributes = {\n ...attrs,\n blockMeta: {\n ...(attrs.blockMeta ?? {}),\n transition,\n },\n };\n return {\n attributes,\n transitionParams: {\n transition: transition.type,\n ...(transition.duration !== undefined\n ? { transitionDuration: String(transition.duration) }\n : {}),\n ...(transition.direction ? { transitionDirection: transition.direction } : {}),\n },\n };\n}\n\nfunction removeTransitionParams(\n attrs: MarkdownHeading['attributes'],\n): MarkdownHeading['attributes'] {\n if (!attrs?.params) return attrs;\n const params = { ...attrs.params };\n for (const key of TRANSITION_PARAM_KEYS) delete params[key];\n return {\n ...attrs,\n ...(Object.keys(params).length > 0 ? { params } : { params: undefined }),\n };\n}\n","/**\n * Doc-scoped theme resolution.\n *\n * The theme analog of how `buildRegistry` resolves custom templates: pure and\n * doc-scoped, with no global state. `resolveThemeForDoc` looks up the active\n * theme id in the doc's own custom themes first, then falls back to an\n * optional caller-owned registry, then built-ins via `resolveTheme`.\n *\n * It accepts either a squisq `Doc` (which carries a typed `customThemes`\n * array) or anything with raw `frontmatter` — notably a `MarkdownDocument`,\n * which is the shape every export pipeline pivots through. In the latter case\n * the inline themes are decoded from the `squisq-custom-themes` frontmatter\n * payload. Inline custom themes ship with the doc, exactly like custom\n * templates; host-level themes can be supplied through an explicit registry.\n */\n\nimport type { Theme, ThemeRegistry } from '../schemas/Theme.js';\nimport { resolveTheme } from '../schemas/themeLibrary.js';\nimport { readFrontmatterThemeId } from '../markdown/utils.js';\nimport { readCustomThemesFromFrontmatter } from './customThemesFrontmatter.js';\n\n/**\n * The minimal shape `resolveThemeForDoc` needs. Satisfied by both the squisq\n * `Doc` (typed `customThemes` + `themeId`) and a `MarkdownDocument` (raw\n * `frontmatter` carrying the encoded payload).\n */\nexport interface ThemeResolvable {\n themeId?: string;\n customThemes?: Theme[];\n frontmatter?: Record<string, unknown>;\n}\n\n/**\n * Resolve the Theme a document should render with.\n *\n * @param doc - the document (may carry inline custom themes plus a `themeId`\n * / `squisq-theme` frontmatter selector).\n * @param explicitId - an id that overrides the doc's own selection (e.g. the\n * editor's theme dropdown, or an export `--theme` option). When omitted, the\n * doc's `themeId` / frontmatter theme id is used.\n * @returns the matching inline custom theme (doc-scoped) when present, else\n * the caller-registry or built-in theme for that id, else the default theme.\n */\nexport function resolveThemeForDoc(\n doc: ThemeResolvable | null | undefined,\n explicitId?: string,\n registry?: ThemeRegistry,\n): Theme {\n const id = explicitId ?? doc?.themeId ?? readFrontmatterThemeId(doc?.frontmatter);\n // Prefer the already-parsed list on a squisq Doc; otherwise decode the\n // frontmatter payload (the shape exports see on a MarkdownDocument).\n const inline = doc?.customThemes ?? readCustomThemesFromFrontmatter(doc?.frontmatter);\n const custom = id ? inline?.find((t) => t.id === id) : undefined;\n if (custom) return custom;\n return resolveTheme(id, registry);\n}\n","/**\n * Apply narration timing from a document-anchored take to a Doc's block\n * timeline.\n *\n * When a doc carries a document-spanning narration clip (a preamble\n * `{[audio src=… anchor=document]}` → `doc.documentMedia`) whose\n * `.timing.json` sidecar has per-block ranges (v3, written by the\n * teleprompter's aligner), the blocks are re-timed so playback and\n * exports advance in sync with the recorded voice. Runs as step 0 of\n * `resolveAudioMapping`, so every surface that resolves audio gets it.\n *\n * Precedence: author-pinned `duration=`/`startTime=` heading attrs win\n * over narration ranges (a conflicting pin gets an `info` diagnostic);\n * narration ranges win over per-block audio-segment mapping and\n * reading-time estimates.\n */\n\nimport type { Block, Doc, DocDiagnostic } from '../schemas/Doc.js';\nimport type { MediaClip } from '../schemas/Media.js';\nimport type { ContentContainer } from '../storage/ContentContainer.js';\nimport { estimateTimeFromText } from '../timing/narrationTiming.js';\nimport { buildNarrationScript } from '../narration/script.js';\nimport {\n parseNarrationTimingJson,\n type NarrationTimingBlock,\n type NarrationTimingJsonV3,\n} from '../narration/sidecar.js';\nimport { flattenRenderableBlocks, getBlockBodyText, getPinnedBlockMeta } from './markdownToDoc.js';\nimport { scoreTextSimilarity } from './audioMapping.js';\n\nexport interface NarrationResolution {\n doc: Doc;\n /** False → the doc is returned unchanged (no clip / no sidecar / no match). */\n applied: boolean;\n /** The narration media path, for callers that bundle assets. */\n clipSrc?: string;\n}\n\n/** Minimum similarity for the fuzzy block-matching rung. */\nconst MIN_BLOCK_SIMILARITY = 0.5;\n/** Minimum whole-script similarity for the v1 proportional fallback. */\nconst MIN_V1_SCRIPT_SIMILARITY = 0.8;\n/** Pins that disagree with the narration range by more than this get a diagnostic. */\nconst PIN_CONFLICT_TOLERANCE_SEC = 1;\n\ninterface BlockRangeSec {\n startSec: number;\n endSec: number;\n}\n\n/** Spoken text of a block, mirroring the narration script builder. */\nfunction blockSpokenText(block: Block): string {\n const title = block.title ? block.title.trim() : '';\n const body = getBlockBodyText(block);\n if (title && body) return `${title}\\n${body}`;\n return title || body;\n}\n\n/**\n * Match sidecar block ranges to doc blocks with a deterministic ladder:\n * exact blockId → text similarity (greedy best-first, ≥ 0.5) →\n * in-order zip when the leftover counts agree. Unmatchable sidecar\n * blocks are dropped.\n */\nfunction matchSidecarBlocks(\n flat: Block[],\n timing: NarrationTimingJsonV3,\n): Map<string, BlockRangeSec> {\n const ranges = new Map<string, BlockRangeSec>();\n const remainingBlocks = new Set(flat.map((b) => b.id));\n const remainingSidecar: NarrationTimingBlock[] = [];\n\n const byId = new Map(flat.map((b) => [b.id, b]));\n for (const entry of timing.blocks) {\n if (entry.blockId && byId.has(entry.blockId) && remainingBlocks.has(entry.blockId)) {\n ranges.set(entry.blockId, { startSec: entry.startSec, endSec: entry.endSec });\n remainingBlocks.delete(entry.blockId);\n } else {\n remainingSidecar.push(entry);\n }\n }\n\n // Fuzzy rung: greedy best pair first, each side used once.\n if (remainingSidecar.length > 0 && remainingBlocks.size > 0) {\n const candidates: Array<{ score: number; entry: NarrationTimingBlock; blockId: string }> = [];\n for (const entry of remainingSidecar) {\n const slice = timing.sourceText.slice(entry.charStart, entry.charEnd);\n for (const block of flat) {\n if (!remainingBlocks.has(block.id)) continue;\n const score = scoreTextSimilarity(slice, blockSpokenText(block));\n if (score >= MIN_BLOCK_SIMILARITY) candidates.push({ score, entry, blockId: block.id });\n }\n }\n candidates.sort((a, b) => b.score - a.score || a.entry.blockIndex - b.entry.blockIndex);\n const usedEntries = new Set<NarrationTimingBlock>();\n for (const candidate of candidates) {\n if (usedEntries.has(candidate.entry) || !remainingBlocks.has(candidate.blockId)) continue;\n ranges.set(candidate.blockId, {\n startSec: candidate.entry.startSec,\n endSec: candidate.entry.endSec,\n });\n usedEntries.add(candidate.entry);\n remainingBlocks.delete(candidate.blockId);\n }\n // Order rung: leftover counts equal → zip in document/sidecar order.\n const leftoverEntries = remainingSidecar.filter((e) => !usedEntries.has(e));\n if (leftoverEntries.length > 0 && leftoverEntries.length === remainingBlocks.size) {\n const leftoverBlocks = flat.filter((b) => remainingBlocks.has(b.id));\n leftoverEntries.sort((a, b) => a.blockIndex - b.blockIndex);\n leftoverBlocks.forEach((block, i) => {\n const entry = leftoverEntries[i];\n ranges.set(block.id, { startSec: entry.startSec, endSec: entry.endSec });\n });\n }\n }\n\n return ranges;\n}\n\n/**\n * v1 fallback: no block ranges in the sidecar. If the take's source\n * text still narrates this doc (whole-script similarity ≥ 0.8), derive\n * per-block ranges by spoken-word proportion.\n */\nfunction proportionalRanges(\n doc: Doc,\n timing: NarrationTimingJsonV3,\n): Map<string, BlockRangeSec> | null {\n const script = buildNarrationScript(doc);\n if (script.blocks.length === 0) return null;\n if (scoreTextSimilarity(script.sourceText, timing.sourceText) < MIN_V1_SCRIPT_SIMILARITY) {\n return null;\n }\n const ranges = new Map<string, BlockRangeSec>();\n const starts = script.blocks.map((range) =>\n estimateTimeFromText(script.sourceText, range.charStart, timing.duration),\n );\n script.blocks.forEach((range, i) => {\n ranges.set(range.blockId, {\n startSec: starts[i],\n endSec: i + 1 < starts.length ? starts[i + 1] : timing.duration,\n });\n });\n return ranges;\n}\n\ninterface RetimeContext {\n clipStart: number;\n ranges: Map<string, BlockRangeSec>;\n diagnostics: DocDiagnostic[];\n /** Timeline cursor (doc seconds) for unmatched blocks. */\n cursor: number;\n}\n\n/** Recursively clone blocks, applying narration ranges to matched, unpinned blocks. */\nfunction retimeBlocks(blocks: Block[], ctx: RetimeContext): Block[] {\n return blocks.map((block) => {\n const range = ctx.ranges.get(block.id);\n const pinned = getPinnedBlockMeta(block);\n const next: Block = { ...block };\n\n if (range && pinned.duration == null && pinned.startTime == null) {\n next.startTime = ctx.clipStart + range.startSec;\n next.duration = Math.max(0, range.endSec - range.startSec);\n ctx.cursor = Math.max(ctx.cursor, next.startTime + next.duration);\n } else if (range) {\n // Author pins win; surface real disagreement as an info diagnostic.\n const pinnedStart = pinned.startTime ?? block.startTime;\n const pinnedDuration = pinned.duration ?? block.duration;\n const narrStart = ctx.clipStart + range.startSec;\n const narrDuration = Math.max(0, range.endSec - range.startSec);\n if (\n Math.abs(pinnedStart - narrStart) > PIN_CONFLICT_TOLERANCE_SEC ||\n Math.abs(pinnedDuration - narrDuration) > PIN_CONFLICT_TOLERANCE_SEC\n ) {\n ctx.diagnostics.push({\n severity: 'info',\n code: 'narration-pin-conflict',\n message:\n `Block timing is pinned (duration=/startTime=) but the recorded narration says ` +\n `~${narrDuration.toFixed(1)}s starting at ~${narrStart.toFixed(1)}s. The pin wins; ` +\n `remove it to follow the narration.`,\n blockId: block.id,\n });\n }\n ctx.cursor = Math.max(ctx.cursor, pinnedStart + pinnedDuration);\n } else {\n // No narration range (block added after the take, or unmatched):\n // keep its duration but place it at the running cursor so the\n // timeline stays monotonic.\n next.startTime = ctx.cursor;\n ctx.cursor += next.duration;\n }\n\n if (block.children && block.children.length > 0) {\n next.children = retimeBlocks(block.children, ctx);\n }\n return next;\n });\n}\n\n/**\n * Find the doc's document-anchored narration clip, load its timing\n * sidecar, and re-time the blocks from its ranges. Pure with respect to\n * the input doc — returns a new Doc (or the original when nothing\n * applies).\n */\nexport async function applyNarrationTiming(\n doc: Doc,\n container: ContentContainer,\n): Promise<NarrationResolution> {\n const clips: MediaClip[] = (doc.documentMedia ?? []).filter((c) => c.anchor === 'document');\n for (const clip of clips) {\n if (!clip.src) continue;\n const sidecarData = await container.readFile(`${clip.src}.timing.json`);\n if (!sidecarData) continue;\n const timing = parseNarrationTimingJson(sidecarData);\n if (!timing) continue;\n\n const flat = flattenRenderableBlocks(doc.blocks);\n const ranges =\n timing.blocks.length > 0 ? matchSidecarBlocks(flat, timing) : proportionalRanges(doc, timing);\n if (!ranges || ranges.size === 0) continue;\n\n const ctx: RetimeContext = {\n clipStart: clip.startAt,\n ranges,\n diagnostics: [],\n cursor: 0,\n };\n const blocks = retimeBlocks(doc.blocks, ctx);\n const duration = Math.max(clip.startAt + timing.duration, ctx.cursor);\n const retimed: Doc = {\n ...doc,\n blocks,\n duration,\n ...(ctx.diagnostics.length > 0\n ? { diagnostics: [...(doc.diagnostics ?? []), ...ctx.diagnostics] }\n : {}),\n };\n return { doc: retimed, applied: true, clipSrc: clip.src };\n }\n return { doc, applied: false };\n}\n","/**\n * Audio Mapping\n *\n * Associates audio segments (MP3 files) with document blocks.\n * Supports two modes:\n *\n * 1. **Explicit annotation**: Blocks with `{[audio=filename.mp3]}` in their\n * heading annotation are directly mapped to that audio file.\n *\n * 2. **Auto-matching**: When no annotations exist but the container has MP3s\n * with `.timing.json` files, matches MP3s to blocks by comparing the\n * timing.json `sourceText` against block text content (word overlap).\n * Falls back to filename-based matching (slugified title comparison).\n */\n\nimport type { Doc, Block, AudioSegment, AudioTimingData } from '../schemas/Doc.js';\nimport { resolveMediaSchedule } from '../schemas/Media.js';\nimport type { ContentContainer } from '../storage/ContentContainer.js';\nimport { extractPlainText } from '../markdown/utils.js';\nimport { applyNarrationTiming } from './applyNarrationTiming.js';\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\n/**\n * Parse a timing.json file from raw data.\n */\nfunction parseTimingJson(data: ArrayBuffer): AudioTimingData | null {\n try {\n const text = new TextDecoder().decode(data);\n const parsed = JSON.parse(text);\n if (parsed && typeof parsed.sourceText === 'string' && typeof parsed.duration === 'number') {\n return {\n sourceText: parsed.sourceText,\n bookmarks: Array.isArray(parsed.bookmarks) ? parsed.bookmarks : [],\n duration: parsed.duration,\n };\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Normalize text for comparison: lowercase, strip punctuation, split into word set.\n */\nfunction normalizeToWords(text: string): Set<string> {\n const words = text\n .toLowerCase()\n .replace(/[^\\w\\s]/g, ' ')\n .split(/\\s+/)\n .filter((w) => w.length > 2);\n return new Set(words);\n}\n\n/**\n * Calculate Jaccard similarity between two texts (word overlap).\n * Returns 0–1 where 1 = identical word sets.\n */\nexport function scoreTextSimilarity(a: string, b: string): number {\n const wordsA = normalizeToWords(a);\n const wordsB = normalizeToWords(b);\n if (wordsA.size === 0 || wordsB.size === 0) return 0;\n\n let intersection = 0;\n for (const w of wordsA) {\n if (wordsB.has(w)) intersection++;\n }\n\n const union = new Set([...wordsA, ...wordsB]).size;\n return union > 0 ? intersection / union : 0;\n}\n\n/**\n * Slugify a title for filename comparison.\n * \"The Behring Gambit\" → \"the-behring-gambit\"\n */\nfunction slugify(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\n/**\n * Extract plain text from a block's contents and title.\n */\nfunction blockToPlainText(block: Block): string {\n const parts: string[] = [];\n if (block.title) parts.push(block.title);\n if (block.contents) {\n for (const node of block.contents) {\n parts.push(extractPlainText(node));\n }\n }\n return parts.join('\\n');\n}\n\n/**\n * Flatten a block tree into a linear array of leaf blocks\n * (blocks that represent actual content sections).\n */\nfunction flattenForAudio(blocks: Block[]): Block[] {\n const result: Block[] = [];\n for (const block of blocks) {\n if (block.children && block.children.length > 0) {\n result.push(...flattenForAudio(block.children));\n } else {\n result.push(block);\n }\n }\n return result;\n}\n\n/**\n * Info about a narration audio file found in the container.\n *\n * Covers MP3/WebM/MP4/Ogg/M4A audio files, including browser-recorder output.\n */\ninterface NarrationAudioInfo {\n /** Path in the container (e.g., \"audio/narration-2026.webm\"). */\n path: string;\n /** Filename without path (e.g., \"narration-2026.webm\"). */\n filename: string;\n /** Parsed timing data (if .timing.json exists). */\n timing: AudioTimingData | null;\n}\n\n/**\n * File extensions that unambiguously denote audio anywhere in the\n * container. These predate the recorder feature.\n */\nconst AUDIO_ONLY_EXTENSIONS = ['.mp3', '.wav', '.ogg', '.m4a'];\n\n/**\n * Extensions that could be audio or video — `.webm` and `.mp4` are the\n * containers `MediaRecorder` produces for browser-side narration, but\n * they're also used for video clips. Only treat them as narration when\n * they live under the `audio/` directory the recorder writes to.\n */\nconst AMBIGUOUS_EXTENSIONS = ['.webm', '.mp4'];\n\nfunction isNarrationAudioPath(path: string): boolean {\n const lower = path.toLowerCase();\n if (AUDIO_ONLY_EXTENSIONS.some((ext) => lower.endsWith(ext))) return true;\n if (AMBIGUOUS_EXTENSIONS.some((ext) => lower.endsWith(ext))) {\n return lower.startsWith('audio/');\n }\n return false;\n}\n\n/** Strip a known narration audio extension from a filename. */\nfunction stripAudioExtension(filename: string): string {\n const lower = filename.toLowerCase();\n for (const ext of [...AUDIO_ONLY_EXTENSIONS, ...AMBIGUOUS_EXTENSIONS]) {\n if (lower.endsWith(ext)) return filename.slice(0, -ext.length);\n }\n return filename;\n}\n\n// ── Core Functions ───────────────────────────────────────────────────\n\n/**\n * Parse a consolidated timing.json (version 2) which contains all section\n * timing data in a single file.\n */\nfunction parseConsolidatedTiming(data: ArrayBuffer): Record<string, AudioTimingData> | null {\n try {\n const text = new TextDecoder().decode(data);\n const parsed = JSON.parse(text);\n if (parsed && parsed.version === 2 && parsed.sections) {\n return parsed.sections as Record<string, AudioTimingData>;\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Discover all narration audio files in a container and load their\n * timing data. Covers historical `.mp3`/`.wav`/`.ogg`/`.m4a` files\n * anywhere in the container plus `.webm`/`.mp4` files under `audio/`\n * (the destination the browser recorder writes to).\n *\n * Checks for a consolidated timing.json first, then falls back to\n * per-file `.timing.json` sidecars.\n */\nasync function discoverNarrationAudio(container: ContentContainer): Promise<NarrationAudioInfo[]> {\n const files = await container.listFiles();\n const audioFiles = files.filter((f) => isNarrationAudioPath(f.path));\n const results: NarrationAudioInfo[] = [];\n\n // Try to load consolidated timing.json\n let consolidatedSections: Record<string, AudioTimingData> | null = null;\n const consolidatedData = await container.readFile('timing.json');\n if (consolidatedData) {\n consolidatedSections = parseConsolidatedTiming(consolidatedData);\n }\n\n for (const file of audioFiles) {\n const filename = file.path.split('/').pop() ?? file.path;\n let timing: AudioTimingData | null = null;\n\n // Try consolidated timing first: match section name from filename\n if (consolidatedSections) {\n const audioBase = stripAudioExtension(filename);\n for (const [sectionName, sectionTiming] of Object.entries(consolidatedSections)) {\n if (audioBase.endsWith(`-${sectionName}`)) {\n timing = sectionTiming;\n break;\n }\n }\n }\n\n // Fall back to per-file .timing.json\n if (!timing) {\n const timingPath = `${file.path}.timing.json`;\n const timingData = await container.readFile(timingPath);\n if (timingData) {\n timing = parseTimingJson(timingData);\n }\n }\n\n results.push({ path: file.path, filename, timing });\n }\n\n return results;\n}\n\n/**\n * Resolve audio from explicit `{[audio=filename.mp3]}` annotations on blocks.\n * Returns the matched pairs or an empty array if no annotations found.\n */\nfunction resolveFromAnnotations(\n blocks: Block[],\n audioFiles: NarrationAudioInfo[],\n): Array<{ block: Block; audio: NarrationAudioInfo }> {\n const matches: Array<{ block: Block; audio: NarrationAudioInfo }> = [];\n const flat = flattenForAudio(blocks);\n\n for (const block of flat) {\n const audioRef = block.templateOverrides?.audio;\n if (!audioRef) continue;\n\n // Find the narration file by filename (exact or suffix match).\n const audio = audioFiles.find(\n (m) => m.filename === audioRef || m.path === audioRef || m.path.endsWith(`/${audioRef}`),\n );\n\n if (audio) {\n matches.push({ block, audio });\n }\n }\n\n return matches;\n}\n\n/** Minimum similarity score to consider a content match. */\nconst MIN_CONTENT_SIMILARITY = 0.35;\n\n/** Minimum similarity score for filename-based matching. */\nconst MIN_FILENAME_SIMILARITY = 0.5;\n\n/**\n * Auto-match narration files to blocks by content similarity.\n * Uses timing.json sourceText when available, falls back to filename matching.\n */\nfunction autoMatchBlocks(\n blocks: Block[],\n audioFiles: NarrationAudioInfo[],\n): Array<{ block: Block; audio: NarrationAudioInfo; score: number }> {\n const flat = flattenForAudio(blocks);\n if (flat.length === 0 || audioFiles.length === 0) return [];\n\n // Score all (audio, block) pairs.\n const scoredPairs: Array<{\n block: Block;\n blockIndex: number;\n audio: NarrationAudioInfo;\n audioIndex: number;\n score: number;\n }> = [];\n\n for (let audioIndex = 0; audioIndex < audioFiles.length; audioIndex++) {\n const audio = audioFiles[audioIndex];\n\n for (let bi = 0; bi < flat.length; bi++) {\n const block = flat[bi];\n const blockText = blockToPlainText(block);\n if (!blockText.trim()) continue;\n\n let score = 0;\n\n // Primary: content similarity via timing.json sourceText\n if (audio.timing?.sourceText) {\n score = scoreTextSimilarity(audio.timing.sourceText, blockText);\n }\n\n // Fallback: filename-based matching\n if (score < MIN_CONTENT_SIMILARITY && block.title) {\n const titleSlug = slugify(block.title);\n const fileSlug = slugify(stripAudioExtension(audio.filename));\n // Check if the title slug appears in the filename slug\n if (fileSlug.includes(titleSlug) && titleSlug.length >= 3) {\n score = Math.max(score, MIN_FILENAME_SIMILARITY + 0.1);\n }\n }\n\n if (score >= MIN_CONTENT_SIMILARITY) {\n scoredPairs.push({ block, blockIndex: bi, audio, audioIndex, score });\n }\n }\n }\n\n // Greedy assignment: highest score first, each audio file and block at most once.\n scoredPairs.sort((a, b) => b.score - a.score);\n const usedBlocks = new Set<number>();\n const usedAudio = new Set<number>();\n const matches: Array<{ block: Block; audio: NarrationAudioInfo; score: number }> = [];\n\n for (const pair of scoredPairs) {\n if (usedBlocks.has(pair.blockIndex) || usedAudio.has(pair.audioIndex)) continue;\n usedBlocks.add(pair.blockIndex);\n usedAudio.add(pair.audioIndex);\n matches.push({ block: pair.block, audio: pair.audio, score: pair.score });\n }\n\n return matches;\n}\n\n// ── Public API ───────────────────────────────────────────────────────\n\n/**\n * Resolve audio mapping for a Doc using a ContentContainer.\n *\n * Tries explicit `{[audio=filename.mp3]}` annotations first,\n * then falls back to auto-matching by content similarity.\n *\n * Returns a new Doc with `audio.segments` populated and blocks\n * assigned to the correct `audioSegment` indices.\n *\n * @param doc - The source Doc (not mutated).\n * @param container - ContentContainer with narration and timing files.\n * @returns New Doc with audio segments resolved, or original doc if no matches.\n */\nexport async function resolveAudioMapping(doc: Doc, container: ContentContainer): Promise<Doc> {\n // Step 0: a document-anchored narration take (preamble `{[audio src=…\n // anchor=document]}` + v3 timing sidecar) re-times the block timeline\n // to the recorded voice. See applyNarrationTiming for precedence.\n const narration = await applyNarrationTiming(doc, container);\n doc = narration.doc;\n\n const audioFiles = await discoverNarrationAudio(container);\n\n // Files already playing through the media schedule (documentMedia /\n // block clips) must not ALSO be auto-mapped into audio.segments —\n // that would play the narration twice.\n const scheduledSrcs = new Set(resolveMediaSchedule(doc).map((clip) => clip.src));\n const available = audioFiles.filter((f) => !scheduledSrcs.has(f.path));\n if (available.length === 0) return doc;\n\n // Try annotations first\n let matches = resolveFromAnnotations(doc.blocks, available);\n\n // Fall back to auto-matching if no annotations found. When narration\n // timing was applied, content auto-matching is skipped — the take owns\n // the timeline, and fuzzy matches against other files would fight it.\n if (matches.length === 0 && !narration.applied) {\n matches = autoMatchBlocks(doc.blocks, available).map((m) => ({\n block: m.block,\n audio: m.audio,\n }));\n }\n\n if (matches.length === 0) return doc;\n\n // Build audio segments in document order\n // Sort matches by the block's position in the flattened tree\n const flat = flattenForAudio(doc.blocks);\n const blockOrder = new Map(flat.map((b, i) => [b.id, i]));\n matches.sort((a, b) => (blockOrder.get(a.block.id) ?? 0) - (blockOrder.get(b.block.id) ?? 0));\n\n // Build segment list and assign indices\n const segments: AudioSegment[] = [];\n const blockToSegment = new Map<string, number>();\n let startTime = 0;\n\n for (let i = 0; i < matches.length; i++) {\n const { block, audio } = matches[i];\n const duration = audio.timing?.duration ?? 30; // Fallback duration if no timing\n\n segments.push({\n src: audio.path,\n name: block.title ?? block.id,\n duration,\n startTime,\n });\n\n blockToSegment.set(block.id, i);\n startTime += duration;\n }\n\n // Deep clone blocks and assign audioSegment indices\n const newBlocks = assignSegmentIndices(doc.blocks, blockToSegment);\n\n return {\n ...doc,\n blocks: newBlocks,\n // A narration take owns the overall duration; explicit per-block\n // segments only ever extend it.\n duration: narration.applied ? Math.max(doc.duration, startTime) : startTime,\n audio: { segments },\n };\n}\n\n/**\n * Recursively clone blocks and assign audioSegment indices.\n * Blocks not in the map keep their original audioSegment.\n * Children of a matched block inherit the parent's segment.\n */\nfunction assignSegmentIndices(\n blocks: Block[],\n blockToSegment: Map<string, number>,\n inheritedSegment?: number,\n): Block[] {\n return blocks.map((block) => {\n const segment = blockToSegment.get(block.id) ?? inheritedSegment ?? block.audioSegment;\n const newBlock: Block = {\n ...block,\n audioSegment: segment,\n };\n\n if (block.children) {\n newBlock.children = assignSegmentIndices(block.children, blockToSegment, segment);\n }\n\n return newBlock;\n });\n}\n","/**\n * Markdown document validation.\n *\n * `validateMarkdownSource()` gives authors and agents fast, structural\n * feedback on a squisq markdown document — the same checks the renderer\n * applies, surfaced as diagnostics instead of degraded slides:\n *\n * - unknown template names (with a did-you-mean suggestion)\n * - unknown drawing shapes, and shape annotations used outside a `{[drawing]}`\n * - `{[…]}` text that was not recognized as an annotation (bad quoting,\n * non-heading placement, unknown inline icon)\n * - malformed heading-attribute values (`x=abc`, bad `startTime`) and\n * non-numeric drawing-shape geometry\n * - `connectsTo` / drawing `from`/`to` targets that don't resolve,\n * duplicate block ids, unparseable data fences (reported by `markdownToDoc`)\n * - image references missing from the provided asset set (.dbk contents)\n *\n * The CLI exposes this as `squisq validate <input>`; agents can also call\n * it directly and iterate until the diagnostics list is empty.\n */\n\nimport type { Doc, Block, DocDiagnostic } from '../schemas/Doc.js';\nimport type {\n MarkdownDocument,\n MarkdownHeading,\n MarkdownNode,\n HtmlNode,\n} from '../markdown/types.js';\nimport { parseMarkdown } from '../markdown/parse.js';\nimport { getChildren, extractPlainText } from '../markdown/utils.js';\nimport { coerceAnnotationValues, KNOWN_BLOCK_META_KEYS } from '../markdown/annotationCoercion.js';\nimport { markdownToDoc, flattenBlocks } from './markdownToDoc.js';\nimport { parseStandaloneAnnotation } from './standaloneAnnotation.js';\nimport { isDataFence, parseDataFence } from './structuredData.js';\nimport { deriveTemplateInputs } from './templateInputs.js';\nimport { lintTemplateParams } from './templates/inputDescriptors.js';\nimport {\n templateRegistry,\n resolveTemplateName,\n isShapeName,\n normalizeShapeKind,\n SHAPE_NAMES,\n} from './templates/index.js';\nimport { TEMPLATE_ALIASES } from './templates/templateNames.js';\nimport { nearestName } from './utils/nearest.js';\n\n// ============================================\n// Options & result\n// ============================================\n\nexport interface ValidateOptions {\n /**\n * Known asset paths for image/video reference checks — typically the\n * file list of a .dbk container or the document's folder. Relative\n * references not present here produce a `missing-asset` warning.\n * When omitted, asset checks are skipped.\n */\n assets?: ReadonlySet<string> | ((path: string) => boolean);\n\n /**\n * Additional template names to accept beyond the built-in registry and\n * the document's own `customTemplates` (e.g. app-registered templates).\n */\n extraTemplates?: readonly string[];\n}\n\nexport interface MarkdownValidationResult {\n /** All findings, in source order where line information exists. */\n diagnostics: DocDiagnostic[];\n errorCount: number;\n warningCount: number;\n infoCount: number;\n /** The converted Doc (conversion diagnostics are included above). */\n doc: Doc;\n}\n\n// ============================================\n// Entry points\n// ============================================\n\n/**\n * Validate a squisq markdown source string. Parses, converts (collecting\n * the conversion's own diagnostics), and runs the structural checks above.\n */\nexport function validateMarkdownSource(\n source: string,\n options?: ValidateOptions,\n): MarkdownValidationResult {\n return validateMarkdownDoc(parseMarkdown(source), options);\n}\n\n/**\n * Validate an already-parsed MarkdownDocument. See {@link validateMarkdownSource}.\n */\nexport function validateMarkdownDoc(\n markdownDoc: MarkdownDocument,\n options?: ValidateOptions,\n): MarkdownValidationResult {\n const doc = markdownToDoc(markdownDoc);\n const diagnostics: DocDiagnostic[] = [...(doc.diagnostics ?? [])];\n const blocks = flattenBlocks(doc.blocks);\n\n const knownTemplates = collectKnownTemplates(doc, options);\n // Custom template names are skipped by the input linter — they carry\n // arbitrary author-defined inputs the built-in descriptors can't know about.\n const customNames = new Set<string>(doc.customTemplates?.map((t) => t.name) ?? []);\n\n // Parent-aware walk: a `{[shape]}` annotation is only meaningful on the\n // direct child of a `{[drawing]}` block, so the template check needs each\n // block's parent. Drawing connectors are validated against their siblings.\n const visit = (block: Block, parent: Block | undefined): void => {\n checkTemplate(block, parent, knownTemplates, diagnostics);\n checkAttributeCoercion(block, parent, diagnostics);\n checkConflictingAnnotationKeys(block, diagnostics);\n checkTemplateInputs(block, parent, customNames, diagnostics);\n checkPossibleDataFences(block, diagnostics);\n if (isDrawingBlock(block)) checkDrawingConnectors(block, diagnostics);\n for (const child of block.children ?? []) visit(child, block);\n };\n for (const block of doc.blocks) visit(block, undefined);\n\n checkUnrecognizedAnnotations(markdownDoc, diagnostics);\n\n if (options?.assets) {\n const hasAsset = normalizeAssetCheck(options.assets);\n checkAssets(markdownDoc, blocks, hasAsset, diagnostics);\n }\n\n diagnostics.sort(\n (a, b) => (a.line ?? Number.MAX_SAFE_INTEGER) - (b.line ?? Number.MAX_SAFE_INTEGER),\n );\n\n return {\n diagnostics,\n errorCount: diagnostics.filter((d) => d.severity === 'error').length,\n warningCount: diagnostics.filter((d) => d.severity === 'warning').length,\n infoCount: diagnostics.filter((d) => d.severity === 'info').length,\n doc,\n };\n}\n\n// ============================================\n// Template checks\n// ============================================\n\nfunction collectKnownTemplates(doc: Doc, options?: ValidateOptions): Set<string> {\n return new Set<string>([\n ...Object.keys(templateRegistry),\n ...Object.keys(TEMPLATE_ALIASES),\n ...(doc.customTemplates?.map((t) => t.name) ?? []),\n ...(options?.extraTemplates ?? []),\n ]);\n}\n\n/** True when `block` is a `{[drawing]}` container (after alias resolution). */\nfunction isDrawingBlock(block: Block): boolean {\n return resolveTemplateName(block.template ?? '') === 'drawing';\n}\n\nfunction checkTemplate(\n block: Block,\n parent: Block | undefined,\n known: Set<string>,\n diagnostics: DocDiagnostic[],\n): void {\n // Heading blocks carry the requested name on the heading annotation;\n // heading-less standalone blocks carry it on `sourceAnnotation` (raw,\n // un-resolved) — read whichever is present.\n const requested =\n block.sourceHeading?.templateAnnotation?.template ?? block.sourceAnnotation?.template;\n if (!requested) return;\n\n // Inside a drawing, the annotation names a shape primitive, not a template.\n if (parent && isDrawingBlock(parent)) {\n if (isShapeName(requested)) return;\n const suggestion = nearestName(requested, new Set(SHAPE_NAMES), {\n map: resolveTemplateName,\n });\n diagnostics.push({\n severity: 'warning',\n code: 'unknown-shape',\n message:\n `Unknown shape \"${requested}\" in drawing — the child will be skipped` +\n (suggestion ? `. Did you mean \"${suggestion}\"?` : ''),\n blockId: block.id,\n ...lineOf(block),\n });\n return;\n }\n\n // A shape annotation outside a drawing has no parent to interpret it.\n if (isShapeName(requested)) {\n diagnostics.push({\n severity: 'warning',\n code: 'shape-outside-drawing',\n message: `Shape \"${requested}\" is only recognized on a child heading of a {[drawing]} block`,\n blockId: block.id,\n ...lineOf(block),\n });\n return;\n }\n\n if (known.has(requested) || known.has(resolveTemplateName(requested))) return;\n\n const suggestion = nearestName(requested, known, { map: resolveTemplateName });\n diagnostics.push({\n severity: 'warning',\n code: 'unknown-template',\n message:\n `Unknown template \"${requested}\" — the block will render as a plain fallback card` +\n (suggestion ? `. Did you mean \"${suggestion}\"?` : ''),\n blockId: block.id,\n ...lineOf(block),\n });\n}\n\n/**\n * Lint a template block's `{[…]}` inputs against the built-in input\n * descriptors: unknown keys (with a did-you-mean), values outside a closed\n * enum / that fail coercion, and missing required inputs. All are warnings.\n *\n * Only built-in templates with descriptors are checked — shapes, drawing\n * children, custom templates, and not-yet-described built-ins are skipped\n * (`lintTemplateParams` returns `[]` for the latter). A `missing-input`\n * finding is suppressed when the value is actually satisfiable from the\n * block's own fields, structured data, or body derivation.\n */\nfunction checkTemplateInputs(\n block: Block,\n parent: Block | undefined,\n customNames: ReadonlySet<string>,\n diagnostics: DocDiagnostic[],\n): void {\n const requested = block.sourceHeading?.templateAnnotation?.template;\n if (!requested) return;\n // Inside a drawing, the annotation names a shape primitive, not a template.\n if (parent && isDrawingBlock(parent)) return;\n if (isShapeName(requested)) return;\n\n const canonical = resolveTemplateName(requested);\n if (customNames.has(requested) || customNames.has(canonical)) return;\n\n const params = block.sourceHeading?.templateAnnotation?.params ?? {};\n for (const finding of lintTemplateParams(canonical, params)) {\n if (finding.kind === 'missing-input' && isInputSatisfiable(canonical, block, finding.key)) {\n continue;\n }\n diagnostics.push({\n severity: 'warning',\n code: finding.kind,\n message: `Block \"${block.id}\": ${finding.message}`,\n blockId: block.id,\n ...lineOf(block),\n });\n }\n}\n\n/**\n * Whether a required template input is satisfiable even though it's absent\n * from the `{[…]}` params: present in a structured-data fence, carried as a\n * block-level field (e.g. `title` from the heading), or derivable from the\n * heading + body (`deriveTemplateInputs` in strict mode).\n */\nfunction isInputSatisfiable(canonical: string, block: Block, key: string): boolean {\n if (block.templateData && key in block.templateData) return true;\n if ((block as unknown as Record<string, unknown>)[key] != null) return true;\n const derived = deriveTemplateInputs(canonical, block.title ?? '', block.contents);\n return derived != null && key in derived;\n}\n\n/** Numeric geometry keys carried in a shape's `{[…]}` params. */\nconst NUMERIC_SHAPE_KEYS = ['x', 'y', 'width', 'height', 'w', 'h', 'strokeWidth', 'borderRadius'];\n\n/** Re-run heading-attribute coercion to surface its warnings with context. */\nfunction checkAttributeCoercion(\n block: Block,\n parent: Block | undefined,\n diagnostics: DocDiagnostic[],\n): void {\n // Pandoc `{#id key=value}` params (x/y/connectsTo/startTime/duration).\n const params = block.sourceHeading?.attributes?.params;\n if (params) {\n const { warnings } = coerceAnnotationValues(params);\n for (const warning of warnings) {\n diagnostics.push({\n severity: 'warning',\n code: 'invalid-attribute',\n message: `Block \"${block.id}\": ${warning}`,\n blockId: block.id,\n ...lineOf(block),\n });\n }\n }\n\n // A drawing shape's geometry lives in its `{[shape …]}` params\n // (templateOverrides), not the Pandoc block — validate those numerics too.\n if (parent && isDrawingBlock(parent) && isShapeName(block.template)) {\n const overrides = block.templateOverrides ?? {};\n for (const key of NUMERIC_SHAPE_KEYS) {\n const raw = overrides[key];\n if (raw == null) continue;\n const value = raw.replace(/,\\s*$/, '').trim();\n if (value !== '' && !Number.isFinite(Number(value))) {\n diagnostics.push({\n severity: 'warning',\n code: 'invalid-attribute',\n message: `Drawing shape \"${block.id}\": \"${key}\" is not a number (${JSON.stringify(raw)})`,\n blockId: block.id,\n ...lineOf(block),\n });\n }\n }\n }\n}\n\n/**\n * A heading can carry the same block-meta key in both the Pandoc `{k=v}`\n * block and the squiggly `{[tpl k=v]}` annotation. The Pandoc value wins\n * (same precedence as `makeBlock` in markdownToDoc), which is easy to miss\n * when the two disagree — surface an info diagnostic so the author knows\n * which value is in effect.\n */\nfunction checkConflictingAnnotationKeys(block: Block, diagnostics: DocDiagnostic[]): void {\n const annotationParams = block.sourceHeading?.templateAnnotation?.params;\n const pandocParams = block.sourceHeading?.attributes?.params;\n if (!annotationParams || !pandocParams) return;\n\n for (const key of Object.keys(KNOWN_BLOCK_META_KEYS)) {\n const fromAnnotation = annotationParams[key];\n const fromPandoc = pandocParams[key];\n if (fromAnnotation == null || fromPandoc == null || fromAnnotation === fromPandoc) continue;\n diagnostics.push({\n severity: 'info',\n code: 'conflicting-annotation-key',\n message:\n `\"${key}\" is set in both {[…]} (${fromAnnotation}) and {…} (${fromPandoc}) — ` +\n `the {…} value wins.`,\n blockId: block.id,\n ...lineOf(block),\n });\n }\n}\n\n/**\n * A drawing's `line`/`arrow` connectors reference sibling shapes by id via\n * `from`/`to`; flag any that don't resolve (mirrors the `connectsTo`\n * unresolved-connection check, but for the `{[…]}` param form).\n */\nfunction checkDrawingConnectors(block: Block, diagnostics: DocDiagnostic[]): void {\n const children = block.children ?? [];\n const ids = new Set(children.map((c) => c.id));\n for (const child of children) {\n const kind = normalizeShapeKind(child.sourceHeading?.templateAnnotation?.template);\n if (kind !== 'line' && kind !== 'arrow') continue;\n const overrides = child.templateOverrides ?? {};\n for (const key of ['from', 'to'] as const) {\n const raw = overrides[key];\n if (raw == null) continue;\n const ref = raw.replace(/,\\s*$/, '').trim();\n if (ref && !ids.has(ref)) {\n diagnostics.push({\n severity: 'warning',\n code: 'unresolved-connection',\n message: `Drawing connector \"${child.id}\" references unknown ${key} \"${ref}\"`,\n blockId: child.id,\n ...lineOf(child),\n });\n }\n }\n }\n}\n\n/**\n * A plain ```json / ```yaml fence (no `data` marker) inside a template-\n * annotated block, whose content parses as a top-level object, is almost\n * certainly meant as template input — surface an info nudge to add the\n * `data` marker. Deliberately scoped to *annotated* blocks so ordinary code\n * samples in prose sections never trigger it.\n */\nfunction checkPossibleDataFences(block: Block, diagnostics: DocDiagnostic[]): void {\n const annotated = !!(\n block.sourceHeading?.templateAnnotation?.template || block.sourceAnnotation?.template\n );\n if (!annotated) return;\n\n for (const node of block.contents ?? []) {\n if (node.type !== 'code') continue;\n const lang = node.lang?.toLowerCase();\n if (lang !== 'json' && lang !== 'yaml' && lang !== 'yml') continue;\n if (isDataFence(node)) continue; // already a data fence — nothing to nudge\n\n const result = parseDataFence(node);\n if (!result.data || Object.keys(result.data).length === 0) continue;\n\n diagnostics.push({\n severity: 'info',\n code: 'possible-data-fence',\n message:\n `This ${lang} block renders as code — add \"data\" to the fence ` +\n `(\\`\\`\\`${lang} data) if it's meant as template input.`,\n blockId: block.id,\n ...(node.position ? { line: node.position.start.line } : lineOf(block)),\n });\n }\n}\n\n// ============================================\n// Unrecognized `{[…]}` text\n// ============================================\n\nconst ANNOTATION_LIKE_RE = /\\{\\[/;\n\n/**\n * Flag literal `{[` text that survived parsing. On a heading this usually\n * means broken quoting; in body content it usually means the author\n * expected list-item/paragraph annotations, which only headings support\n * (or referenced an unknown inline icon).\n */\nfunction checkUnrecognizedAnnotations(\n markdownDoc: MarkdownDocument,\n diagnostics: DocDiagnostic[],\n): void {\n const walk = (node: MarkdownNode, headingLine: number | undefined, topLevel: boolean): void => {\n if (node.type === 'heading') {\n const heading = node as MarkdownHeading;\n const text = extractPlainText(heading);\n if (ANNOTATION_LIKE_RE.test(text)) {\n diagnostics.push({\n severity: 'warning',\n code: 'unparsed-annotation',\n message:\n `Heading \"${truncate(text)}\" contains \"{[…]}\" text that was not recognized — ` +\n `check the quoting, or whether the token is a known inline icon`,\n ...(heading.position ? { line: heading.position.start.line } : {}),\n });\n }\n return; // heading inline children already covered by extractPlainText\n }\n // A *top-level* paragraph that is exactly a `{[templateName …]}` /\n // `{[audio …]}` annotation is recognized (it becomes a standalone template\n // block or a media clip) — don't flag it, and don't descend into its text.\n // Nested paragraphs (inside a list / blockquote) are NOT extracted, so\n // they still warn.\n if (node.type === 'paragraph' && topLevel) {\n const parsed = parseStandaloneAnnotation(node);\n if (parsed && parsed.template != null) return;\n }\n if (node.type === 'text' && ANNOTATION_LIKE_RE.test(node.value)) {\n diagnostics.push({\n severity: 'warning',\n code: 'unparsed-annotation',\n message:\n `Body text contains \"{[…]}\" — template annotations are recognized on headings ` +\n `and as standalone paragraphs (or the token is not a known inline icon)`,\n ...(node.position\n ? { line: node.position.start.line }\n : headingLine != null\n ? { line: headingLine }\n : {}),\n });\n return;\n }\n if (node.type === 'code') return; // code blocks legitimately contain {[\n for (const child of getChildren(node)) {\n walk(child, headingLine, false);\n }\n };\n\n for (const child of markdownDoc.children) {\n walk(child, child.position?.start.line, true);\n }\n}\n\n// ============================================\n// Asset checks\n// ============================================\n\nfunction normalizeAssetCheck(\n assets: ReadonlySet<string> | ((path: string) => boolean),\n): (path: string) => boolean {\n if (typeof assets === 'function') return assets;\n return (path: string) => assets.has(path) || assets.has(path.replace(/^\\.\\//, ''));\n}\n\nconst URL_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;\n\n/** A reference that should resolve inside the bundle: relative, no scheme. */\nfunction isBundleRelative(url: string): boolean {\n return (\n url.length > 0 && !URL_SCHEME_RE.test(url) && !url.startsWith('//') && !url.startsWith('#')\n );\n}\n\n/** Template param keys whose values reference media assets. */\nconst ASSET_PARAM_KEYS = ['src', 'imageSrc', 'videoSrc', 'poster', 'backgroundImage'];\n\nfunction checkAssets(\n markdownDoc: MarkdownDocument,\n blocks: Block[],\n hasAsset: (path: string) => boolean,\n diagnostics: DocDiagnostic[],\n): void {\n const report = (url: string, line?: number, blockId?: string) => {\n if (!isBundleRelative(url) || hasAsset(url)) return;\n diagnostics.push({\n severity: 'warning',\n code: 'missing-asset',\n message: `Referenced asset \"${url}\" was not found in the bundle`,\n ...(blockId ? { blockId } : {}),\n ...(line != null ? { line } : {}),\n });\n };\n\n // Markdown image nodes + raw-HTML <img src>.\n const walk = (node: MarkdownNode): void => {\n if (node.type === 'image') {\n report(node.url, node.position?.start.line);\n }\n if (node.type === 'htmlBlock' || node.type === 'htmlInline') {\n walkHtmlImages(node.htmlChildren, (src) => report(src, node.position?.start.line));\n }\n for (const child of getChildren(node)) walk(child);\n };\n for (const child of markdownDoc.children) walk(child);\n\n // Media references in template params / structured data.\n for (const block of blocks) {\n const sources: Array<Record<string, unknown> | undefined> = [\n block.templateOverrides,\n block.templateData,\n ];\n for (const source of sources) {\n if (!source) continue;\n for (const key of ASSET_PARAM_KEYS) {\n const value = source[key];\n if (typeof value === 'string') {\n report(value, block.sourceHeading?.position?.start.line, block.id);\n }\n }\n const images = source['images'];\n const list =\n typeof images === 'string'\n ? images.split(',').map((s) => s.trim())\n : Array.isArray(images)\n ? images.filter((i): i is string => typeof i === 'string')\n : [];\n for (const img of list) {\n report(img, block.sourceHeading?.position?.start.line, block.id);\n }\n }\n }\n}\n\nfunction walkHtmlImages(nodes: HtmlNode[], report: (src: string) => void): void {\n for (const node of nodes) {\n if (node.type !== 'htmlElement') continue;\n if (node.tagName === 'img' && node.attributes.src) {\n report(node.attributes.src);\n }\n walkHtmlImages(node.children, report);\n }\n}\n\n// ============================================\n// Helpers\n// ============================================\n\nfunction lineOf(block: Block): { line: number } | Record<string, never> {\n const line = block.sourceHeading?.position?.start.line;\n return line != null ? { line } : {};\n}\n\nfunction truncate(text: string, max = 40): string {\n return text.length <= max ? text : `${text.slice(0, max)}…`;\n}\n","/**\n * ASCII diagram renderer: semantic nodes/edges → box-and-line art.\n *\n * Deterministic (no clock, no randomness; every iteration order is an\n * explicit sort) and designed as a fixpoint partner for `parse.ts`:\n *\n * - `parseAsciiDiagram(renderAsciiDiagram(d))` preserves node ids, labels,\n * containment, and the edge tuple set of `d`.\n * - After one normalization cycle the output is byte-stable:\n * `renderAsciiDiagram(parseAsciiDiagram(renderAsciiDiagram(d))) ===\n * renderAsciiDiagram(d)`.\n *\n * Grid positions come from the nodes; container rects are DERIVED from\n * their children each render (a container's own col/row are ignored), so\n * moving children can never orphan them outside their box.\n */\n\nimport { ASCII_VOCAB, UNICODE_VOCAB, type StyleVocab } from './chars.js';\nimport type { AsciiDiagram, AsciiDiagramEdge, AsciiDiagramNode } from './types.js';\n\nexport interface RenderAsciiDiagramOptions {\n /** Character vocabulary; defaults to the diagram's own detected style. */\n style?: 'unicode' | 'ascii';\n}\n\ninterface Rect {\n r0: number;\n c0: number;\n r1: number;\n c1: number;\n}\n\ninterface PlacedNode {\n node: AsciiDiagramNode;\n rect: Rect;\n labelLines: string[];\n isContainer: boolean;\n depth: number;\n}\n\nconst SIDE_MARGIN = 1; // blank cells kept between distinct sibling rects\n\nexport function renderAsciiDiagram(\n diagram: AsciiDiagram,\n options: RenderAsciiDiagramOptions = {},\n): string {\n const vocab = (options.style ?? diagram.style) === 'ascii' ? ASCII_VOCAB : UNICODE_VOCAB;\n if (diagram.nodes.length === 0) return '';\n\n const placed = layoutNodes(diagram.nodes, diagram.edges);\n const canvas = new Canvas();\n\n // Boxes: outermost containers first so children draw over their interior.\n const drawOrder = [...placed.values()].sort(\n (a, b) => a.depth - b.depth || a.rect.r0 - b.rect.r0 || a.rect.c0 - b.rect.c0,\n );\n for (const p of drawOrder) drawBox(canvas, p, vocab);\n\n drawEdges(canvas, diagram.edges, placed, vocab);\n\n return canvas.emit();\n}\n\n// ---------------------------------------------------------------------------\n// Layout\n// ---------------------------------------------------------------------------\n\n/**\n * Approximate per-side edge degree from the nodes' authored grid\n * positions (same side logic as `pickSides`, run before final layout).\n * Used to widen/heighten boxes so sibling attachments always land on\n * distinct, gapped cells — adjacent attachments (`┬┬`) route into each\n * other and collapse to one component on re-parse.\n */\nfunction computeSideDegrees(\n nodes: readonly AsciiDiagramNode[],\n edges: readonly AsciiDiagramEdge[],\n): Map<string, { top: number; bottom: number; left: number; right: number }> {\n const byId = new Map(nodes.map((n) => [n.id, n]));\n const deg = new Map<string, { top: number; bottom: number; left: number; right: number }>();\n for (const n of nodes) deg.set(n.id, { top: 0, bottom: 0, left: 0, right: 0 });\n const rectOf = (n: AsciiDiagramNode): Rect => ({\n r0: n.row,\n c0: n.col,\n r1: n.row + n.hRows - 1,\n c1: n.col + n.wCols - 1,\n });\n for (const e of edges) {\n const s = byId.get(e.source);\n const t = byId.get(e.target);\n if (!s || !t || s === t) continue;\n const { exit, enter } = pickSides(rectOf(s), rectOf(t));\n deg.get(e.source)![exit]++;\n deg.get(e.target)![enter]++;\n }\n return deg;\n}\n\nfunction layoutNodes(\n nodes: readonly AsciiDiagramNode[],\n edges: readonly AsciiDiagramEdge[],\n): Map<string, PlacedNode> {\n const byId = new Map<string, AsciiDiagramNode>();\n for (const node of nodes) byId.set(node.id, node);\n const sideDeg = computeSideDegrees(nodes, edges);\n\n const childIds = new Map<string, string[]>();\n const roots: string[] = [];\n for (const node of nodes) {\n if (node.containerId && byId.has(node.containerId) && node.containerId !== node.id) {\n const list = childIds.get(node.containerId) ?? [];\n list.push(node.id);\n childIds.set(node.containerId, list);\n } else {\n roots.push(node.id);\n }\n }\n\n const placed = new Map<string, PlacedNode>();\n\n const translateSubtree = (id: string, dRows: number, dCols: number): void => {\n const p = placed.get(id);\n if (p) p.rect = shiftRect(p.rect, dRows, dCols);\n for (const childId of childIds.get(id) ?? []) translateSubtree(childId, dRows, dCols);\n };\n\n // Place a set of sibling units (each may be a whole subtree) without overlap.\n const placeSiblings = (ids: string[], layoutUnit: (id: string) => Rect): Rect[] => {\n const order = [...ids].sort((a, b) => {\n const na = byId.get(a) as AsciiDiagramNode;\n const nb = byId.get(b) as AsciiDiagramNode;\n return na.row - nb.row || na.col - nb.col || na.id.localeCompare(nb.id);\n });\n const placedRects: Rect[] = [];\n for (const id of order) {\n let rect = layoutUnit(id);\n // Greedy deterministic collision resolution: shift along the axis\n // needing the smaller displacement (ties → down).\n let guard = 0;\n for (;;) {\n const hit = placedRects.find((p) => overlapsWithMargin(rect, p, SIDE_MARGIN));\n if (!hit || guard++ > 64) break;\n const dxRight = hit.c1 + SIDE_MARGIN + 1 - rect.c0;\n const dyDown = hit.r1 + SIDE_MARGIN + 1 - rect.r0;\n if (dxRight < dyDown) {\n translateSubtree(id, 0, dxRight);\n rect = shiftRect(rect, 0, dxRight);\n } else {\n translateSubtree(id, dyDown, 0);\n rect = shiftRect(rect, dyDown, 0);\n }\n }\n placedRects.push(rect);\n }\n return placedRects;\n };\n\n // Recursively size + place a subtree; returns its bounding rect.\n const layoutSubtree = (id: string, depth: number): Rect => {\n const node = byId.get(id) as AsciiDiagramNode;\n const labelLines = node.label.length > 0 ? node.label.split('\\n') : [];\n const children = childIds.get(id) ?? [];\n\n if (children.length === 0) {\n const innerW = labelLines.reduce((w, l) => Math.max(w, l.length), 0);\n // Attachment gap: a side with K edges needs ≥ 2K+1 inner cells so the\n // spread (`from + round((i+1)*inner/(K+1))`) leaves a blank column\n // between consecutive attachments and off the corners.\n const deg = sideDeg.get(id) ?? { top: 0, bottom: 0, left: 0, right: 0 };\n const horizDeg = Math.max(deg.top, deg.bottom);\n const vertDeg = Math.max(deg.left, deg.right);\n const wCols = Math.max(node.wCols, innerW + 4, 3, horizDeg > 0 ? 2 * horizDeg + 1 : 0);\n const hRows = Math.max(\n node.hRows,\n labelLines.length + 2,\n 3,\n vertDeg > 0 ? 2 * vertDeg + 1 : 0,\n );\n const rect: Rect = {\n r0: node.row,\n c0: node.col,\n r1: node.row + hRows - 1,\n c1: node.col + wCols - 1,\n };\n placed.set(id, { node, rect, labelLines, isContainer: false, depth });\n return rect;\n }\n\n // Container: children first, then derive our rect around them.\n const childRects = placeSiblings(children, (childId) => layoutSubtree(childId, depth + 1));\n const bbox = unionRects(childRects);\n const extraRows = Math.max(0, labelLines.length - 1);\n const titleLen = (labelLines[0] ?? '').length;\n const rect: Rect = {\n r0: bbox.r0 - 2 - extraRows,\n c0: bbox.c0 - 2,\n r1: bbox.r1 + 2,\n c1: bbox.c1 + 2,\n };\n // Top border must host `── Title ──` with ≥1 line char each side.\n const minW = titleLen > 0 ? titleLen + 6 : 3;\n if (rect.c1 - rect.c0 + 1 < minW) rect.c1 = rect.c0 + minW - 1;\n // Never shrink below the parsed size (visual stability for wide containers).\n if (rect.c1 - rect.c0 + 1 < node.wCols) rect.c1 = rect.c0 + node.wCols - 1;\n placed.set(id, { node, rect, labelLines, isContainer: true, depth });\n return rect;\n };\n\n placeSiblings(roots, (id) => layoutSubtree(id, 0));\n\n // Normalize into the positive quadrant (container margins can push past 0).\n let minR = Infinity;\n let minC = Infinity;\n for (const p of placed.values()) {\n minR = Math.min(minR, p.rect.r0);\n minC = Math.min(minC, p.rect.c0);\n }\n const dR = minR < 0 ? -minR : 0;\n const dC = minC < 0 ? -minC : 0;\n if (dR > 0 || dC > 0) {\n for (const p of placed.values()) p.rect = shiftRect(p.rect, dR, dC);\n }\n return placed;\n}\n\nfunction overlapsWithMargin(a: Rect, b: Rect, margin: number): boolean {\n return (\n a.r0 - margin <= b.r1 && b.r0 - margin <= a.r1 && a.c0 - margin <= b.c1 && b.c0 - margin <= a.c1\n );\n}\n\nfunction shiftRect(rect: Rect, dRows: number, dCols: number): Rect {\n return { r0: rect.r0 + dRows, c0: rect.c0 + dCols, r1: rect.r1 + dRows, c1: rect.c1 + dCols };\n}\n\nfunction unionRects(rects: Rect[]): Rect {\n return rects.reduce((acc, r) => ({\n r0: Math.min(acc.r0, r.r0),\n c0: Math.min(acc.c0, r.c0),\n r1: Math.max(acc.r1, r.r1),\n c1: Math.max(acc.c1, r.c1),\n }));\n}\n\n// ---------------------------------------------------------------------------\n// Canvas\n// ---------------------------------------------------------------------------\n\ntype CellKind = 'empty' | 'border' | 'label' | 'line-h' | 'line-v' | 'turn' | 'arrow' | 'junction';\n\nclass Canvas {\n private rows: string[][] = [];\n private kinds: CellKind[][] = [];\n\n private ensure(r: number, c: number): void {\n while (this.rows.length <= r) {\n this.rows.push([]);\n this.kinds.push([]);\n }\n const row = this.rows[r];\n const kindRow = this.kinds[r];\n while (row.length <= c) {\n row.push(' ');\n kindRow.push('empty');\n }\n }\n\n kindAt(r: number, c: number): CellKind {\n return this.kinds[r]?.[c] ?? 'empty';\n }\n\n /** Unconditional write (boxes, labels, junction upgrades). */\n set(r: number, c: number, ch: string, kind: CellKind): void {\n if (r < 0 || c < 0) return;\n this.ensure(r, c);\n this.rows[r][c] = ch;\n this.kinds[r][c] = kind;\n }\n\n /** Edge-aware write: respects borders, upgrades crossings, lets arrows win. */\n drawEdgeCell(r: number, c: number, ch: string, kind: CellKind, vocab: StyleVocab): void {\n if (r < 0 || c < 0) return;\n this.ensure(r, c);\n const existing = this.kinds[r][c];\n if (existing === 'border' || existing === 'label' || existing === 'junction') return;\n if (kind === 'arrow') {\n this.rows[r][c] = ch;\n this.kinds[r][c] = kind;\n return;\n }\n if (existing === 'arrow') return;\n if (\n (existing === 'line-h' && kind === 'line-v') ||\n (existing === 'line-v' && kind === 'line-h')\n ) {\n this.rows[r][c] = vocab.cross;\n this.kinds[r][c] = 'turn';\n return;\n }\n if (existing === 'empty') {\n this.rows[r][c] = ch;\n this.kinds[r][c] = kind;\n }\n }\n\n emit(): string {\n const lines = this.rows.map((row) => row.join('').replace(/\\s+$/u, ''));\n while (lines.length > 0 && lines[lines.length - 1] === '') lines.pop();\n return lines.join('\\n');\n }\n}\n\n// ---------------------------------------------------------------------------\n// Boxes\n// ---------------------------------------------------------------------------\n\nfunction drawBox(canvas: Canvas, p: PlacedNode, vocab: StyleVocab): void {\n const { rect, labelLines, isContainer } = p;\n const innerW = rect.c1 - rect.c0 - 1;\n\n // Top border (containers embed their first label line as a title).\n canvas.set(rect.r0, rect.c0, vocab.tl, 'border');\n canvas.set(rect.r0, rect.c1, vocab.tr, 'border');\n const title = isContainer && labelLines.length > 0 ? ` ${labelLines[0]} ` : null;\n if (title && title.length <= innerW - 2) {\n const left = Math.floor((innerW - title.length) / 2);\n for (let i = 0; i < innerW; i++) {\n const inTitle = i >= left && i < left + title.length;\n const ch = inTitle ? title[i - left] : vocab.h;\n canvas.set(rect.r0, rect.c0 + 1 + i, ch, inTitle ? 'label' : 'border');\n }\n } else {\n for (let c = rect.c0 + 1; c <= rect.c1 - 1; c++) canvas.set(rect.r0, c, vocab.h, 'border');\n }\n\n // Bottom border + sides.\n canvas.set(rect.r1, rect.c0, vocab.bl, 'border');\n canvas.set(rect.r1, rect.c1, vocab.br, 'border');\n for (let c = rect.c0 + 1; c <= rect.c1 - 1; c++) canvas.set(rect.r1, c, vocab.h, 'border');\n for (let r = rect.r0 + 1; r <= rect.r1 - 1; r++) {\n canvas.set(r, rect.c0, vocab.v, 'border');\n canvas.set(r, rect.c1, vocab.v, 'border');\n }\n\n // Interior label lines: leaves get all lines (vertically centered),\n // containers the lines after the embedded title, directly below the top.\n const interiorLines = isContainer ? labelLines.slice(1) : labelLines;\n if (interiorLines.length > 0) {\n const innerH = rect.r1 - rect.r0 - 1;\n const startRow = isContainer\n ? rect.r0 + 1\n : rect.r0 + 1 + Math.max(0, Math.floor((innerH - interiorLines.length) / 2));\n interiorLines.forEach((line, i) => {\n const pad = Math.max(0, Math.floor((innerW - line.length) / 2));\n for (let j = 0; j < line.length && pad + j < innerW; j++) {\n canvas.set(startRow + i, rect.c0 + 1 + pad + j, line[j], 'label');\n }\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Edges\n// ---------------------------------------------------------------------------\n\ntype Side = 'top' | 'bottom' | 'left' | 'right';\n\ninterface RoutePlan {\n edge: AsciiDiagramEdge;\n sourceId: string;\n targetId: string;\n exitSide: Side;\n enterSide: Side;\n biDir: boolean;\n}\n\nfunction drawEdges(\n canvas: Canvas,\n edges: readonly AsciiDiagramEdge[],\n placed: Map<string, PlacedNode>,\n vocab: StyleVocab,\n): void {\n // Merge reciprocal directed pairs into single double-arrow lines.\n const sorted = [...edges].sort(\n (a, b) =>\n a.source.localeCompare(b.source) ||\n a.target.localeCompare(b.target) ||\n (a.label ?? '').localeCompare(b.label ?? ''),\n );\n const skip = new Set<number>();\n const plans: RoutePlan[] = [];\n for (let i = 0; i < sorted.length; i++) {\n if (skip.has(i)) continue;\n const e = sorted[i];\n if (!placed.has(e.source) || !placed.has(e.target)) continue;\n let biDir = false;\n if (e.directed) {\n const j = sorted.findIndex(\n (o, k) =>\n k > i &&\n !skip.has(k) &&\n o.directed &&\n o.source === e.target &&\n o.target === e.source &&\n (o.label ?? '') === (e.label ?? ''),\n );\n if (j >= 0) {\n skip.add(j);\n biDir = true;\n }\n }\n const sides = pickSides(\n (placed.get(e.source) as PlacedNode).rect,\n (placed.get(e.target) as PlacedNode).rect,\n );\n plans.push({\n edge: e,\n sourceId: e.source,\n targetId: e.target,\n exitSide: sides.exit,\n enterSide: sides.enter,\n biDir,\n });\n }\n\n const attachment = assignAttachments(plans, placed);\n const sideLabelRequests: SideLabelRequest[] = [];\n plans.forEach((plan, i) =>\n routeEdge(canvas, plan, i, placed, attachment, vocab, (candidates, label) =>\n sideLabelRequests.push({ candidates, label }),\n ),\n );\n\n // Side labels last, so they can never break another edge's line: each\n // label lands beside the first candidate whose anchor is still a plain\n // vertical and whose neighboring cells are all free — right side\n // (`│ label`) preferred, left side (`label │`) as fallback.\n for (const req of sideLabelRequests) {\n let done = false;\n for (const side of ['right', 'left'] as const) {\n if (done) break;\n for (const { row, col } of req.candidates) {\n if (canvas.kindAt(row, col) !== 'line-v') continue;\n const startCol = side === 'right' ? col + 2 : col - 1 - req.label.length;\n if (startCol < 0) continue;\n const gapCol = side === 'right' ? col + 1 : col - 1;\n let free = canvas.kindAt(row, gapCol) === 'empty';\n for (let i = 0; free && i < req.label.length; i++) {\n if (canvas.kindAt(row, startCol + i) !== 'empty') free = false;\n }\n // Left-side runs must not merge into earlier art on their left.\n if (free && side === 'left' && startCol > 0) {\n free = canvas.kindAt(row, startCol - 1) === 'empty';\n }\n if (!free) continue;\n for (let i = 0; i < req.label.length; i++) {\n canvas.set(row, startCol + i, req.label[i], 'label');\n }\n done = true;\n break;\n }\n }\n }\n}\n\ninterface SideLabelRequest {\n /** Candidate anchor cells in preference order (middle-out per leg). */\n candidates: Array<{ row: number; col: number }>;\n label: string;\n}\n\nfunction pickSides(s: Rect, t: Rect): { exit: Side; enter: Side } {\n if (t.r0 > s.r1) return { exit: 'bottom', enter: 'top' };\n if (t.r1 < s.r0) return { exit: 'top', enter: 'bottom' };\n if (t.c0 > s.c1) return { exit: 'right', enter: 'left' };\n if (t.c1 < s.c0) return { exit: 'left', enter: 'right' };\n // Overlapping / containment: connect the closest pair of parallel borders.\n const gaps: Array<{ side: Side; gap: number }> = [\n { side: 'top', gap: Math.abs(s.r0 - t.r0) },\n { side: 'bottom', gap: Math.abs(t.r1 - s.r1) },\n { side: 'left', gap: Math.abs(s.c0 - t.c0) },\n { side: 'right', gap: Math.abs(t.c1 - s.c1) },\n ];\n gaps.sort((a, b) => a.gap - b.gap);\n return { exit: gaps[0].side, enter: gaps[0].side };\n}\n\ninterface AttachmentSlot {\n pos: number;\n /** 0-based order within the (node, side) group + group size — used to\n * stagger Z-route jog rows so parallel routes never touch (touching\n * turns would merge into one component on re-parse). */\n index: number;\n count: number;\n}\n\n/** Deterministic per-(node, side) attachment positions, spread across the side. */\nfunction assignAttachments(\n plans: RoutePlan[],\n placed: Map<string, PlacedNode>,\n): Map<string, AttachmentSlot> {\n interface Request {\n key: string; // `${planIndex}:exit` | `${planIndex}:enter`\n otherId: string;\n }\n const bySide = new Map<string, Request[]>();\n plans.forEach((plan, i) => {\n const exitKey = `${plan.sourceId}|${plan.exitSide}`;\n const enterKey = `${plan.targetId}|${plan.enterSide}`;\n bySide.set(exitKey, [\n ...(bySide.get(exitKey) ?? []),\n { key: `${i}:exit`, otherId: plan.targetId },\n ]);\n bySide.set(enterKey, [\n ...(bySide.get(enterKey) ?? []),\n { key: `${i}:enter`, otherId: plan.sourceId },\n ]);\n });\n const result = new Map<string, AttachmentSlot>();\n for (const [sideKey, list] of [...bySide.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {\n const [nodeId, side] = sideKey.split('|') as [string, Side];\n const node = placed.get(nodeId) as PlacedNode;\n list.sort((a, b) => {\n const ra = (placed.get(a.otherId) as PlacedNode).rect;\n const rb = (placed.get(b.otherId) as PlacedNode).rect;\n return ra.r0 - rb.r0 || ra.c0 - rb.c0 || a.otherId.localeCompare(b.otherId);\n });\n const horizontal = side === 'top' || side === 'bottom';\n const from = horizontal ? node.rect.c0 + 1 : node.rect.r0 + 1;\n const to = horizontal ? node.rect.c1 - 1 : node.rect.r1 - 1;\n const inner = Math.max(1, to - from + 1);\n const k = list.length;\n if (k === 1) {\n // Single attachment lands on the side's center cell.\n result.set(list[0].key, { pos: from + Math.floor((inner - 1) / 2), index: 0, count: 1 });\n } else {\n // Stride-2 centered placement guarantees a blank cell between\n // consecutive attachments (min box sizing reserves the room), so\n // sibling routes never share adjacent columns and collapse on\n // re-parse. Span = 2k-1; clamp into the side if a tiny box can't fit.\n const span = 2 * k - 1;\n const start = from + Math.max(0, Math.floor((inner - span) / 2));\n list.forEach((req, i) => {\n result.set(req.key, { pos: Math.min(to, start + 2 * i), index: i, count: k });\n });\n }\n }\n return result;\n}\n\nfunction routeEdge(\n canvas: Canvas,\n plan: RoutePlan,\n planIdx: number,\n placed: Map<string, PlacedNode>,\n attachment: Map<string, AttachmentSlot>,\n vocab: StyleVocab,\n deferSideLabel: (candidates: Array<{ row: number; col: number }>, label: string) => void,\n): void {\n const s = (placed.get(plan.sourceId) as PlacedNode).rect;\n const t = (placed.get(plan.targetId) as PlacedNode).rect;\n const exitSlot = attachment.get(`${planIdx}:exit`) as AttachmentSlot;\n const enterSlot = attachment.get(`${planIdx}:enter`) as AttachmentSlot;\n const exitPos = exitSlot.pos;\n const enterPos = enterSlot.pos;\n // Deterministic jog stagger: routes sharing a side (either end — fan-outs\n // AND fan-ins) each get a distinct mid-line so their turns/segments can\n // never touch or overlap on the same row/column.\n const basis = enterSlot.count > exitSlot.count ? enterSlot : exitSlot;\n const stagger = basis.index - Math.floor((basis.count - 1) / 2);\n\n const junction = (r: number, c: number, side: Side): void => {\n const ch =\n side === 'top'\n ? vocab.stemUp\n : side === 'bottom'\n ? vocab.stemDown\n : side === 'left'\n ? vocab.stemLeft\n : vocab.stemRight;\n canvas.set(r, c, ch, 'junction');\n };\n\n const args: EdgeDrawArgs = {\n canvas,\n directed: plan.edge.directed,\n biDir: plan.biDir,\n label: plan.edge.label,\n vocab,\n junction,\n stagger,\n deferSideLabel,\n };\n\n if (plan.exitSide === 'bottom' && plan.enterSide === 'top') {\n drawVertical(args, s, t, exitPos, enterPos, 1);\n } else if (plan.exitSide === 'top' && plan.enterSide === 'bottom') {\n drawVertical(args, s, t, exitPos, enterPos, -1);\n } else if (plan.exitSide === 'right' && plan.enterSide === 'left') {\n drawHorizontal(args, s, t, exitPos, enterPos, 1);\n } else if (plan.exitSide === 'left' && plan.enterSide === 'right') {\n drawHorizontal(args, s, t, exitPos, enterPos, -1);\n } else {\n drawNested(args, s, t, plan.exitSide);\n }\n}\n\ninterface EdgeDrawArgs {\n canvas: Canvas;\n directed: boolean;\n biDir: boolean;\n label: string | undefined;\n vocab: StyleVocab;\n junction: (r: number, c: number, side: Side) => void;\n /** Jog offset for Z-routes so sibling routes never share a mid-line. */\n stagger: number;\n /** Queue a `│ label` placement for the deferred final pass. */\n deferSideLabel: (candidates: Array<{ row: number; col: number }>, label: string) => void;\n}\n\n/** Order candidate rows middle-out so labels prefer a run's midpoint. */\nfunction middleOut(from: number, to: number): number[] {\n const lo = Math.min(from, to);\n const hi = Math.max(from, to);\n const rows: number[] = [];\n for (let r = lo; r <= hi; r++) rows.push(r);\n const mid = Math.floor((lo + hi) / 2);\n return rows.sort((a, b) => Math.abs(a - mid) - Math.abs(b - mid) || a - b);\n}\n\nfunction clamp(value: number, lo: number, hi: number): number {\n return Math.max(lo, Math.min(hi, value));\n}\n\nfunction drawVertical(\n args: EdgeDrawArgs,\n s: Rect,\n t: Rect,\n exitCol: number,\n enterCol: number,\n dir: 1 | -1,\n): void {\n const { canvas, directed, biDir, label, vocab, junction, stagger } = args;\n // dir 1: exit bottom of s, enter top of t (t below); dir -1 mirrored.\n const exitRow = dir === 1 ? s.r1 : s.r0;\n const enterRow = dir === 1 ? t.r0 : t.r1;\n const firstFree = exitRow + dir;\n const lastFree = enterRow - dir;\n const gap = (lastFree - firstFree) * dir + 1;\n\n const drawV = (col: number, rA: number, rB: number): void => {\n const lo = Math.min(rA, rB);\n const hi = Math.max(rA, rB);\n for (let r = lo; r <= hi; r++) canvas.drawEdgeCell(r, col, vocab.v, 'line-v', vocab);\n };\n\n const straightOk =\n exitCol >= t.c0 + 1 && exitCol <= t.c1 - 1 && exitCol >= s.c0 + 1 && exitCol <= s.c1 - 1;\n\n if (straightOk || gap < 2) {\n // Straight (or no room to jog): one column, clamped onto both borders.\n const sCol = clamp(exitCol, s.c0 + 1, s.c1 - 1);\n const tCol = clamp(exitCol, t.c0 + 1, t.c1 - 1);\n junction(exitRow, sCol, dir === 1 ? 'bottom' : 'top');\n junction(enterRow, tCol, dir === 1 ? 'top' : 'bottom');\n if (sCol === tCol && gap >= 1) {\n drawV(sCol, firstFree, lastFree);\n if (directed) {\n canvas.drawEdgeCell(\n lastFree,\n sCol,\n dir === 1 ? vocab.arrowDown : vocab.arrowUp,\n 'arrow',\n vocab,\n );\n }\n if (biDir && gap >= 2) {\n canvas.drawEdgeCell(\n firstFree,\n sCol,\n dir === 1 ? vocab.arrowUp : vocab.arrowDown,\n 'arrow',\n vocab,\n );\n }\n // `│ label` beside the run (deferred pass finds a free plain row).\n if (label) {\n args.deferSideLabel(\n middleOut(firstFree, lastFree).map((row) => ({ row, col: sCol })),\n label,\n );\n }\n }\n return;\n }\n\n // Z-route with a horizontal jog (also hosts the label when present).\n // Sibling routes stagger their jog rows so turns never touch (touching\n // turns would merge into one polyline on re-parse).\n const midRow = clamp(\n Math.floor((exitRow + enterRow) / 2) + stagger,\n Math.min(firstFree, lastFree),\n Math.max(firstFree, lastFree),\n );\n junction(exitRow, exitCol, dir === 1 ? 'bottom' : 'top');\n junction(enterRow, enterCol, dir === 1 ? 'top' : 'bottom');\n if (Math.abs(midRow - exitRow) >= 2) drawV(exitCol, firstFree, midRow - dir);\n if (Math.abs(enterRow - midRow) >= 2) drawV(enterCol, midRow + dir, lastFree);\n let labelEmbedded = false;\n if (exitCol === enterCol) {\n canvas.drawEdgeCell(midRow, exitCol, vocab.v, 'line-v', vocab);\n } else {\n const goingRight = enterCol > exitCol;\n // Turn glyph names describe the corner's two open sides.\n const exitTurn =\n dir === 1\n ? goingRight\n ? vocab.turnUpRight\n : vocab.turnUpLeft\n : goingRight\n ? vocab.turnDownRight\n : vocab.turnDownLeft;\n const enterTurn =\n dir === 1\n ? goingRight\n ? vocab.turnDownLeft\n : vocab.turnDownRight\n : goingRight\n ? vocab.turnUpLeft\n : vocab.turnUpRight;\n canvas.drawEdgeCell(midRow, exitCol, exitTurn, 'turn', vocab);\n canvas.drawEdgeCell(midRow, enterCol, enterTurn, 'turn', vocab);\n const lo = Math.min(exitCol, enterCol);\n const hi = Math.max(exitCol, enterCol);\n let segment: string[] = [];\n for (let c = lo + 1; c <= hi - 1; c++) segment.push(vocab.h);\n // `+ 4` (not `+ 2`): at least one line char must survive on each side\n // of ` label `, or the re-parse bridge can't glue the run back together.\n if (label && segment.length >= label.length + 4) {\n const text = ` ${label} `;\n const left = Math.floor((segment.length - text.length) / 2);\n segment = segment.map((ch, i) => (i >= left && i < left + text.length ? text[i - left] : ch));\n labelEmbedded = true;\n }\n segment.forEach((ch, i) => {\n canvas.drawEdgeCell(midRow, lo + 1 + i, ch, ch === vocab.h ? 'line-h' : 'label', vocab);\n });\n }\n if (directed) {\n canvas.drawEdgeCell(\n lastFree,\n enterCol,\n dir === 1 ? vocab.arrowDown : vocab.arrowUp,\n 'arrow',\n vocab,\n );\n }\n if (biDir) {\n canvas.drawEdgeCell(\n firstFree,\n exitCol,\n dir === 1 ? vocab.arrowUp : vocab.arrowDown,\n 'arrow',\n vocab,\n );\n }\n // Label that couldn't embed in the jog: queue a `│ label` placement\n // beside a vertical leg (exit leg preferred — its cells are all plain;\n // the deferred pass skips arrowhead/cross rows automatically).\n if (label && !labelEmbedded) {\n const candidates: Array<{ row: number; col: number }> = [];\n if (exitCol === enterCol) {\n for (const row of middleOut(firstFree, lastFree)) candidates.push({ row, col: exitCol });\n } else {\n const exitLegLen = (midRow - dir - firstFree) * dir + 1;\n const enterLegLen = (lastFree - (midRow + dir)) * dir + 1;\n if (exitLegLen >= 1) {\n for (const row of middleOut(firstFree, midRow - dir)) {\n candidates.push({ row, col: exitCol });\n }\n }\n if (enterLegLen >= 1) {\n for (const row of middleOut(midRow + dir, lastFree)) {\n candidates.push({ row, col: enterCol });\n }\n }\n }\n if (candidates.length > 0) args.deferSideLabel(candidates, label);\n }\n}\n\nfunction drawHorizontal(\n args: EdgeDrawArgs,\n s: Rect,\n t: Rect,\n exitRow: number,\n enterRow: number,\n dir: 1 | -1,\n): void {\n const { canvas, directed, biDir, label, vocab, junction } = args;\n // dir 1: exit right of s, enter left of t (t to the right); dir -1 mirrored.\n const exitCol = dir === 1 ? s.c1 : s.c0;\n const enterCol = dir === 1 ? t.c0 : t.c1;\n const firstFree = exitCol + dir;\n const lastFree = enterCol - dir;\n const gap = (lastFree - firstFree) * dir + 1;\n\n const drawH = (row: number, cA: number, cB: number, hostLabel: boolean): void => {\n const lo = Math.min(cA, cB);\n const hi = Math.max(cA, cB);\n let segment: string[] = [];\n for (let c = lo; c <= hi; c++) segment.push(vocab.h);\n if (hostLabel && label && segment.length >= label.length + 4) {\n const text = ` ${label} `;\n const left = Math.floor((segment.length - text.length) / 2);\n segment = segment.map((ch, i) => (i >= left && i < left + text.length ? text[i - left] : ch));\n }\n segment.forEach((ch, i) => {\n canvas.drawEdgeCell(row, lo + i, ch, ch === vocab.h ? 'line-h' : 'label', vocab);\n });\n };\n\n const straightOk =\n exitRow >= t.r0 + 1 && exitRow <= t.r1 - 1 && exitRow >= s.r0 + 1 && exitRow <= s.r1 - 1;\n\n if (straightOk || gap < 2) {\n const sRow = clamp(exitRow, s.r0 + 1, s.r1 - 1);\n const tRow = clamp(exitRow, t.r0 + 1, t.r1 - 1);\n junction(sRow, exitCol, dir === 1 ? 'right' : 'left');\n junction(tRow, enterCol, dir === 1 ? 'left' : 'right');\n if (sRow === tRow && gap >= 1) {\n drawH(sRow, firstFree, lastFree, true);\n if (directed) {\n canvas.drawEdgeCell(\n sRow,\n lastFree,\n dir === 1 ? vocab.arrowRight : vocab.arrowLeft,\n 'arrow',\n vocab,\n );\n }\n if (biDir && gap >= 2) {\n canvas.drawEdgeCell(\n sRow,\n firstFree,\n dir === 1 ? vocab.arrowLeft : vocab.arrowRight,\n 'arrow',\n vocab,\n );\n }\n }\n return;\n }\n\n // Horizontal Z-route (staggered like the vertical case).\n const midCol = clamp(\n Math.floor((exitCol + enterCol) / 2) + args.stagger,\n Math.min(firstFree, lastFree),\n Math.max(firstFree, lastFree),\n );\n junction(exitRow, exitCol, dir === 1 ? 'right' : 'left');\n junction(enterRow, enterCol, dir === 1 ? 'left' : 'right');\n if (Math.abs(midCol - exitCol) >= 2) drawH(exitRow, firstFree, midCol - dir, true);\n if (Math.abs(enterCol - midCol) >= 2) drawH(enterRow, midCol + dir, lastFree, false);\n if (exitRow === enterRow) {\n canvas.drawEdgeCell(exitRow, midCol, vocab.h, 'line-h', vocab);\n } else {\n const goingDown = enterRow > exitRow;\n const exitTurn =\n dir === 1\n ? goingDown\n ? vocab.turnDownLeft\n : vocab.turnUpLeft\n : goingDown\n ? vocab.turnDownRight\n : vocab.turnUpRight;\n const enterTurn =\n dir === 1\n ? goingDown\n ? vocab.turnUpRight\n : vocab.turnDownRight\n : goingDown\n ? vocab.turnUpLeft\n : vocab.turnDownLeft;\n canvas.drawEdgeCell(exitRow, midCol, exitTurn, 'turn', vocab);\n canvas.drawEdgeCell(enterRow, midCol, enterTurn, 'turn', vocab);\n const lo = Math.min(exitRow, enterRow);\n const hi = Math.max(exitRow, enterRow);\n for (let r = lo + 1; r <= hi - 1; r++) {\n canvas.drawEdgeCell(r, midCol, vocab.v, 'line-v', vocab);\n }\n }\n if (directed) {\n canvas.drawEdgeCell(\n enterRow,\n lastFree,\n dir === 1 ? vocab.arrowRight : vocab.arrowLeft,\n 'arrow',\n vocab,\n );\n }\n if (biDir) {\n canvas.drawEdgeCell(\n exitRow,\n firstFree,\n dir === 1 ? vocab.arrowLeft : vocab.arrowRight,\n 'arrow',\n vocab,\n );\n }\n}\n\n/** Containment / overlap: a short straight run between the closest parallel borders. */\nfunction drawNested(args: EdgeDrawArgs, s: Rect, t: Rect, side: Side): void {\n const { canvas, directed, vocab, junction } = args;\n if (side === 'top' || side === 'bottom') {\n const overlapLo = Math.max(s.c0 + 1, t.c0 + 1);\n const overlapHi = Math.min(s.c1 - 1, t.c1 - 1);\n if (overlapLo > overlapHi) return;\n const col = Math.floor((overlapLo + overlapHi) / 2);\n const sRow = side === 'top' ? s.r0 : s.r1;\n const tRow = side === 'top' ? t.r0 : t.r1;\n if (sRow === tRow) return;\n junction(sRow, col, side);\n junction(tRow, col, side);\n const lo = Math.min(sRow, tRow);\n const hi = Math.max(sRow, tRow);\n for (let r = lo + 1; r <= hi - 1; r++) canvas.drawEdgeCell(r, col, vocab.v, 'line-v', vocab);\n if (directed && hi - lo >= 2) {\n const arrowRow = tRow > sRow ? tRow - 1 : tRow + 1;\n canvas.drawEdgeCell(\n arrowRow,\n col,\n tRow > sRow ? vocab.arrowDown : vocab.arrowUp,\n 'arrow',\n vocab,\n );\n }\n } else {\n const overlapLo = Math.max(s.r0 + 1, t.r0 + 1);\n const overlapHi = Math.min(s.r1 - 1, t.r1 - 1);\n if (overlapLo > overlapHi) return;\n const row = Math.floor((overlapLo + overlapHi) / 2);\n const sCol = side === 'left' ? s.c0 : s.c1;\n const tCol = side === 'left' ? t.c0 : t.c1;\n if (sCol === tCol) return;\n junction(row, sCol, side);\n junction(row, tCol, side);\n const lo = Math.min(sCol, tCol);\n const hi = Math.max(sCol, tCol);\n for (let c = lo + 1; c <= hi - 1; c++) canvas.drawEdgeCell(row, c, vocab.h, 'line-h', vocab);\n if (directed && hi - lo >= 2) {\n const arrowCol = tCol > sCol ? tCol - 1 : tCol + 1;\n canvas.drawEdgeCell(\n row,\n arrowCol,\n tCol > sCol ? vocab.arrowRight : vocab.arrowLeft,\n 'arrow',\n vocab,\n );\n }\n }\n}\n","/**\n * ASCII diagram REPAIR — an opt-in, best-effort pass that reconstructs a\n * clean, well-formed diagram from broken box-and-line art.\n *\n * The motivating case: hand-drawn architecture art whose labels overflow\n * their boxes and shove every following column out of alignment row-to-row\n * (e.g. a rename widened the labels). Conservative detection correctly\n * declines such art (`garbled-labels`) so it renders as a faithful code\n * block — but a user can then ask to \"repair\" it. This is that repair.\n *\n * It is deliberately AGGRESSIVE and lossy — never on the auto-detection path\n * (a mistake there would hide real code). It is only invoked when the user\n * explicitly opts in, and the result is a fully editable diagram, so an\n * imperfect edge or two is fine (the canvas lets the user fix them).\n *\n * Pipeline:\n * 1. Aggressive box tracing (walls may cross edge routing).\n * 2. Row-band label recovery — the key trick: even when a box's columns are\n * desynced from its borders, each label ROW is internally consistent, so\n * its `│…│` segments map to the band's boxes by reading order.\n * 3. Best-effort edge recovery (facing-border adjacency + arrowhead\n * direction).\n * 4. Re-render clean via `renderAsciiDiagram` — the output re-parses cleanly.\n */\n\nimport { isHoriz, isVert, isJunction, arrowDirection } from './chars.js';\nimport { toGrid, traceBoxes, type TracedRect } from './parse.js';\nimport { renderAsciiDiagram } from './render.js';\nimport { detectAsciiDiagram } from './detect.js';\nimport type { AsciiDiagram, AsciiDiagramEdge, AsciiDiagramNode } from './types.js';\n\nexport interface RepairResult {\n /** The reconstructed diagram model (grid-native coordinates). */\n diagram: AsciiDiagram;\n /** Clean, re-rendered box-and-line art — re-parses to `diagram`. */\n art: string;\n}\n\n/** Minimum boxes for a repair to be worthwhile. */\nconst MIN_REPAIR_BOXES = 2;\n/** Max vertical gap (rows) between two boxes to infer a connecting edge. */\nconst MAX_EDGE_ROW_GAP = 8;\n/** Max horizontal gap (cols) between two boxes to infer a connecting edge. */\nconst MAX_EDGE_COL_GAP = 12;\n/** Blank rows inserted between stacked bands so edges route without overlap. */\nconst BAND_ROW_GAP = 4;\n/** Blank cols inserted between boxes in a band so edges route without overlap. */\nconst BAND_COL_GAP = 4;\n\n/**\n * True when a fence is a box diagram too broken for clean detection but worth\n * offering to repair: it has box corners and aggressively traces ≥2 boxes,\n * yet conservative detection declines it. Clean diagrams (already detected)\n * and non-box art both return false, so the three states partition cleanly.\n */\nexport function isRepairableDiagram(text: string): boolean {\n // Already a clean diagram → not a repair candidate (the canvas handles it).\n if (detectAsciiDiagram(text).isDiagram) return false;\n const grid = toGrid(text);\n const rects = traceBoxes(grid, true);\n return dedupeRects(rects).length >= MIN_REPAIR_BOXES;\n}\n\n/**\n * Reconstruct a clean diagram from broken art. Returns `null` when fewer than\n * two boxes can be recovered (nothing worth repairing).\n */\nexport function repairAsciiDiagram(text: string): RepairResult | null {\n const grid = toGrid(text);\n const rects = dedupeRects(traceBoxes(grid, true));\n if (rects.length < MIN_REPAIR_BOXES) return null;\n\n const nodes = buildNodes(grid, rects);\n const edges = recoverEdges(grid, rects, nodes);\n const style = detectGridStyle(grid);\n const diagram: AsciiDiagram = { nodes, edges, style, warnings: ['repaired'] };\n return { diagram, art: renderAsciiDiagram(diagram) };\n}\n\n// ---------------------------------------------------------------------------\n// Box de-duplication (aggressive tracing can emit the same rect twice, and\n// nested duplicates where a container and a decomposed cell coincide).\n// ---------------------------------------------------------------------------\n\nfunction dedupeRects(rects: TracedRect[]): TracedRect[] {\n const seen = new Set<string>();\n const out: TracedRect[] = [];\n for (const r of rects) {\n const key = `${r.r0},${r.c0},${r.r1},${r.c1}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(r);\n }\n // Reading order (row, then col).\n return out.sort((a, b) => a.r0 - b.r0 || a.c0 - b.c0);\n}\n\n// ---------------------------------------------------------------------------\n// Label recovery (row-band segment matching)\n// ---------------------------------------------------------------------------\n\nfunction buildNodes(grid: string[][], rects: TracedRect[]): AsciiDiagramNode[] {\n const W = grid[0]?.length ?? 0;\n const labels = rects.map(() => [] as string[]);\n const index = new Map(rects.map((r, i) => [r, i] as const));\n\n // Group boxes into horizontal bands (row ranges overlap).\n const bands: TracedRect[][] = [];\n for (const r of rects) {\n let band = bands.find((bd) => bd.some((x) => x.r0 <= r.r1 && r.r0 <= x.r1));\n if (!band) {\n band = [];\n bands.push(band);\n }\n band.push(r);\n }\n\n for (const band of bands) {\n band.sort((a, b) => a.c0 - b.c0);\n const minR = Math.min(...band.map((b) => b.r0 + 1));\n const maxR = Math.max(...band.map((b) => b.r1 - 1));\n for (let r = minR; r <= maxR; r++) {\n const inRow = band.filter((b) => r > b.r0 && r < b.r1);\n if (inRow.length === 0) continue;\n const rowText = grid[r].join('');\n // Split the row into `│`-delimited segments; a clean band row yields one\n // non-empty segment per box, matched by reading order.\n const segs = rowText\n .split(/[│┃║]/)\n .map(cleanLabelText)\n .filter((s) => s.length > 0);\n if (segs.length === inRow.length) {\n inRow.forEach((b, i) => {\n const idx = index.get(b);\n if (idx !== undefined && segs[i]) labels[idx].push(segs[i]);\n });\n } else {\n // Fallback: slice each box's own columns (works when its border cols\n // still line up — isolated boxes, or when the band-split is ambiguous).\n for (const b of inRow) {\n const idx = index.get(b);\n if (idx === undefined) continue;\n const t = cleanLabelText(grid[r].slice(b.c0 + 1, Math.min(b.c1, W)).join(''));\n if (t) labels[idx].push(t);\n }\n }\n }\n }\n\n // Normalize rows onto well-spaced band offsets. Preserving the original\n // (tight, broken) row positions makes the renderer route edges THROUGH\n // boxes; stacking bands with a routing gap gives every band-to-band edge\n // clean vertical space so the rendered art re-parses losslessly. Columns\n // keep their original relative order (the horizontal layout was fine).\n const bandRow = new Map<TracedRect[], number>();\n const orderedBands = [...bands].sort(\n (a, b) => Math.min(...a.map((x) => x.r0)) - Math.min(...b.map((x) => x.r0)),\n );\n let rowCursor = 0;\n for (const band of orderedBands) {\n bandRow.set(band, rowCursor);\n const bandHeight = Math.max(...band.map((b) => b.r1 - b.r0 + 1));\n rowCursor += bandHeight + BAND_ROW_GAP;\n }\n const rectBand = new Map<TracedRect, TracedRect[]>();\n for (const band of bands) for (const r of band) rectBand.set(r, band);\n\n // Normalize columns within each band by the boxes' FITTED widths. Recovered\n // labels are usually wider than the broken art's boxes, so the original\n // column spacing would make fitted boxes overlap — the renderer would then\n // shove a box into the wrong band and route edges through it. Laying each\n // band out left-to-right by fitted width + a routing gap keeps bands intact.\n const fittedW = rects.map((rect, i) =>\n Math.max(rect.c1 - rect.c0 + 1, ...labels[i].map((l) => l.length + 4), 3),\n );\n const rectIndex = new Map(rects.map((r, i) => [r, i] as const));\n const bandCol = new Map<TracedRect, number>();\n for (const band of bands) {\n const ordered = [...band].sort((a, b) => a.c0 - b.c0);\n let colCursor = Math.min(...band.map((b) => b.c0));\n for (const r of ordered) {\n bandCol.set(r, colCursor);\n colCursor += (fittedW[rectIndex.get(r) ?? 0] ?? 3) + BAND_COL_GAP;\n }\n }\n\n // Assign ids (slug of the first label line, deduped), then resolve\n // containment (a box strictly inside another becomes its child).\n const parentIdx = rects.map((_, i) => smallestContainer(rects, i));\n const usedIds = new Map<string, number>();\n const nodes: AsciiDiagramNode[] = rects.map((rect, i) => {\n let id = slugify(labels[i][0] ?? '');\n const n = usedIds.get(id) ?? 0;\n usedIds.set(id, n + 1);\n if (n > 0) id = `${id}-${n + 1}`;\n const band = rectBand.get(rect);\n const nested = parentIdx[i] >= 0;\n const row = band && !nested ? (bandRow.get(band) ?? rect.r0) : rect.r0;\n const col = !nested ? (bandCol.get(rect) ?? rect.c0) : rect.c0;\n return {\n id,\n label: labels[i].join('\\n'),\n col,\n row,\n wCols: rect.c1 - rect.c0 + 1,\n hRows: rect.r1 - rect.r0 + 1,\n };\n });\n nodes.forEach((node, i) => {\n if (parentIdx[i] >= 0) node.containerId = nodes[parentIdx[i]].id;\n });\n return nodes;\n}\n\n/**\n * Strip UNICODE box-drawing chars and arrowheads (edge routing that bled into\n * a label). ASCII `-`/`|`/`+` are kept — they're common in real label text\n * (`molen-tooling`, `read-only`, `stdin | stdout`), and a unicode diagram\n * (the common case) never uses them as borders anyway.\n */\nfunction cleanLabelText(seg: string): string {\n let out = '';\n for (const ch of seg) {\n const code = ch.codePointAt(0) ?? 0;\n const box = code >= 0x2500 && code <= 0x257f; // Box Drawing block\n if (box || arrowDirection(ch) !== null) out += ' ';\n else out += ch;\n }\n return out.replace(/\\s+/g, ' ').trim();\n}\n\nfunction smallestContainer(rects: TracedRect[], i: number): number {\n const child = rects[i];\n let best = -1;\n let bestArea = Infinity;\n for (let j = 0; j < rects.length; j++) {\n if (j === i) continue;\n const p = rects[j];\n if (p.r0 < child.r0 && p.c0 < child.c0 && p.r1 > child.r1 && p.c1 > child.c1) {\n const a = (p.r1 - p.r0) * (p.c1 - p.c0);\n if (a < bestArea) {\n bestArea = a;\n best = j;\n }\n }\n }\n return best;\n}\n\nfunction slugify(s: string): string {\n const slug = s\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n return slug || 'node';\n}\n\n// ---------------------------------------------------------------------------\n// Edge recovery (facing-border adjacency + arrowhead direction)\n// ---------------------------------------------------------------------------\n\nfunction recoverEdges(\n grid: string[][],\n rects: TracedRect[],\n nodes: AsciiDiagramNode[],\n): AsciiDiagramEdge[] {\n const H = grid.length;\n const W = grid[0]?.length ?? 0;\n const at = (r: number, c: number): string =>\n r >= 0 && r < H && c >= 0 && c < W ? grid[r][c] : ' ';\n const isConnector = (ch: string): boolean =>\n isVert(ch) || isHoriz(ch) || isJunction(ch) || arrowDirection(ch) !== null;\n\n const colOverlap = (a: TracedRect, b: TracedRect): boolean =>\n Math.max(a.c0, b.c0) <= Math.min(a.c1, b.c1);\n const rowOverlap = (a: TracedRect, b: TracedRect): boolean =>\n Math.max(a.r0, b.r0) <= Math.min(a.r1, b.r1);\n\n const edges: AsciiDiagramEdge[] = [];\n const seen = new Set<string>();\n const push = (s: number, t: number, directed: boolean) => {\n if (s === t) return;\n const key = `${nodes[s].id}|${nodes[t].id}`;\n if (seen.has(key)) return;\n seen.add(key);\n edges.push({ source: nodes[s].id, target: nodes[t].id, directed });\n };\n\n for (let i = 0; i < rects.length; i++) {\n for (let j = 0; j < rects.length; j++) {\n if (i === j) continue;\n const A = rects[i];\n const B = rects[j];\n\n // Vertical: A above B, columns overlap, a connector spans the gap, and\n // no third box sits directly between them in that column band.\n if (A.r1 < B.r0 && B.r0 - A.r1 <= MAX_EDGE_ROW_GAP && colOverlap(A, B)) {\n const lo = Math.max(A.c0, B.c0);\n const hi = Math.min(A.c1, B.c1);\n if (\n gapHasConnector(at, A.r1 + 1, B.r0 - 1, lo - 1, hi + 1, isConnector) &&\n !boxBetweenVert(rects, i, j, lo, hi)\n ) {\n const directed = gapHasArrow(at, A.r1 + 1, B.r0, lo - 1, hi + 1, 'down');\n push(i, j, directed);\n }\n }\n\n // Horizontal: A left of B, rows overlap. Require an actual arrowhead in\n // the gap — a label that overflowed its box leaks `│`/text into the gap\n // between horizontally-adjacent boxes, which a plain-connector test\n // would read as a phantom edge. A real horizontal edge carries `►`/`◄`.\n if (A.c1 < B.c0 && B.c0 - A.c1 <= MAX_EDGE_COL_GAP && rowOverlap(A, B) && i < j) {\n const lo = Math.max(A.r0, B.r0);\n const hi = Math.min(A.r1, B.r1);\n const rightArrow = gapHasArrow(at, lo - 1, hi + 1, A.c1 + 1, B.c0, 'right');\n const leftArrow = gapHasArrow(at, lo - 1, hi + 1, A.c1 + 1, B.c0, 'left');\n if ((rightArrow || leftArrow) && !boxBetweenHoriz(rects, i, j, lo, hi)) {\n if (leftArrow && !rightArrow) push(j, i, true);\n else push(i, j, true);\n }\n }\n }\n }\n return edges;\n}\n\nfunction gapHasConnector(\n at: (r: number, c: number) => string,\n r0: number,\n r1: number,\n c0: number,\n c1: number,\n isConnector: (ch: string) => boolean,\n): boolean {\n for (let r = r0; r <= r1; r++)\n for (let c = c0; c <= c1; c++) if (isConnector(at(r, c))) return true;\n return false;\n}\n\nfunction gapHasArrow(\n at: (r: number, c: number) => string,\n r0: number,\n r1: number,\n c0: number,\n c1: number,\n dir: 'down' | 'up' | 'left' | 'right',\n): boolean {\n for (let r = r0; r <= r1; r++) {\n for (let c = c0; c <= c1; c++) {\n if (arrowDirection(at(r, c)) === dir) return true;\n }\n }\n return false;\n}\n\nfunction boxBetweenVert(\n rects: TracedRect[],\n i: number,\n j: number,\n lo: number,\n hi: number,\n): boolean {\n const A = rects[i];\n const B = rects[j];\n return rects.some((k, ki) => {\n if (ki === i || ki === j) return false;\n return k.r0 > A.r1 && k.r1 < B.r0 && Math.max(k.c0, lo) <= Math.min(k.c1, hi);\n });\n}\n\nfunction boxBetweenHoriz(\n rects: TracedRect[],\n i: number,\n j: number,\n lo: number,\n hi: number,\n): boolean {\n const A = rects[i];\n const B = rects[j];\n return rects.some((k, ki) => {\n if (ki === i || ki === j) return false;\n return k.c0 > A.c1 && k.c1 < B.c0 && Math.max(k.r0, lo) <= Math.min(k.r1, hi);\n });\n}\n\n// ---------------------------------------------------------------------------\n\nfunction detectGridStyle(grid: string[][]): 'unicode' | 'ascii' {\n let unicode = 0;\n let ascii = 0;\n for (const row of grid) {\n for (const ch of row) {\n const code = ch.codePointAt(0) ?? 0;\n if (code >= 0x2500 && code <= 0x257f) unicode++;\n else if (ch === '+' || ch === '|' || ch === '-') ascii++;\n }\n }\n return ascii > unicode ? 'ascii' : 'unicode';\n}\n","/**\n * ASCII timeline renderer: semantic tracks/events -> canonical timeline art.\n *\n * The canonical authored form keeps the rail visually continuous and moves\n * event payloads onto pointer callouts:\n *\n * ▲ T28 :: delta 28 {#t28 column=12}\n * Kernel {#kernel start=8 end=72}: ───●────────────────○────►\n * ▼ T29 {#t29 column=36}\n *\n * Links follow the tracks as declarations. This form is compact, readable in\n * raw Markdown, and is the exact grammar consumed by `parse.ts`. Rendering is\n * deterministic and normalizes parser-sensitive text/ids up front, so it is a\n * byte fixpoint after one render:\n *\n * renderAsciiTimeline(parseAsciiTimeline(renderAsciiTimeline(t))) ===\n * renderAsciiTimeline(t)\n */\n\nimport type {\n AsciiTimeline,\n AsciiTimelineMarker,\n AsciiTimelineSide,\n AsciiTimelineStyle,\n} from './types.js';\n\nexport interface RenderAsciiTimelineOptions {\n /** Character vocabulary; defaults to the timeline's detected style. */\n style?: AsciiTimelineStyle;\n}\n\ninterface TimelineVocab {\n rail: string;\n arrow: string;\n marker: Record<AsciiTimelineMarker, string>;\n}\n\ninterface PreparedEvent {\n id: string;\n label: string;\n description?: string;\n descriptionSide?: AsciiTimelineSide;\n column: number;\n side: AsciiTimelineSide;\n callout?: boolean;\n marker: AsciiTimelineMarker;\n}\n\ninterface PreparedTrack {\n id: string;\n label?: string;\n endLabel?: string;\n startColumn: number;\n endColumn: number;\n events: PreparedEvent[];\n}\n\ninterface PreparedLink {\n source: string;\n target: string;\n label?: string;\n}\n\nconst UNICODE_VOCAB: TimelineVocab = {\n rail: '\\u2500',\n arrow: '\\u25ba',\n marker: {\n filled: '\\u25cf',\n hollow: '\\u25cb',\n diamond: '\\u25c6',\n },\n};\n\nconst ASCII_VOCAB: TimelineVocab = {\n rail: '-',\n arrow: '>',\n marker: {\n filled: '*',\n hollow: 'o',\n // The parser's ASCII vocabulary has no distinct diamond point. Folding\n // it to `*` is the canonical ASCII representation and is byte-stable.\n diamond: '*',\n },\n};\n\nconst MIN_AXIS_WIDTH = 48;\nconst MAX_COORDINATE_AXIS_WIDTH = 64;\nconst EVENT_SPACING = 3;\nconst TERMINAL_RAIL_LENGTH = 3;\n\n/** Render a timeline into deterministic, parser-canonical ASCII/Unicode art. */\nexport function renderAsciiTimeline(\n timeline: AsciiTimeline,\n options: RenderAsciiTimelineOptions = {},\n): string {\n const style = options.style ?? timeline.style;\n const vocab = style === 'ascii' ? ASCII_VOCAB : UNICODE_VOCAB;\n const { tracks, links } = prepareTimeline(timeline, style);\n if (tracks.length === 0) return '';\n\n const globalStart = Math.min(...tracks.map((track) => track.startColumn));\n const globalEnd = Math.max(...tracks.map((track) => track.endColumn));\n const globalSpan = Math.max(1, globalEnd - globalStart);\n const axisWidth = Math.max(\n MIN_AXIS_WIDTH,\n Math.min(MAX_COORDINATE_AXIS_WIDTH, Math.ceil(globalSpan)),\n ...tracks.map((track) => track.events.length * EVENT_SPACING),\n );\n const prefixes = tracks.map((track) => renderTrackPrefix(track));\n const prefixWidth = Math.max(...prefixes.map(displayWidth));\n const lines: string[] = [];\n\n tracks.forEach((track, index) => {\n if (index > 0) lines.push('');\n lines.push(\n ...renderTrack(\n track,\n style,\n vocab,\n prefixes[index],\n prefixWidth,\n axisWidth,\n globalStart,\n globalSpan,\n ),\n );\n });\n\n if (links.length > 0) {\n lines.push('');\n for (const link of links) lines.push(renderLink(link, style));\n }\n\n return lines.join('\\n');\n}\n\nfunction renderTrack(\n track: PreparedTrack,\n style: AsciiTimelineStyle,\n vocab: TimelineVocab,\n prefix: string,\n prefixWidth: number,\n axisWidth: number,\n globalStart: number,\n globalSpan: number,\n): string[] {\n const paddedPrefix = `${prefix}${' '.repeat(Math.max(0, prefixWidth - displayWidth(prefix)))}`;\n const positioned = positionEvents(track.events, axisWidth, globalStart, globalSpan);\n const rail = Array.from({ length: axisWidth + 1 }, () => vocab.rail);\n for (const { event, offset } of positioned) rail[offset] = vocab.marker[event.marker];\n\n const callouts = positioned.map(({ event, offset }) => ({\n event,\n column: prefixWidth + offset,\n text: renderEventPayload(event),\n }));\n const pointer = style === 'ascii' ? { above: '^', below: 'v' } : { above: '▲', below: '▼' };\n const above = renderCalloutLanes(\n callouts.filter(({ event }) => event.side === 'above'),\n pointer.above,\n );\n const below = renderCalloutLanes(\n callouts.filter(({ event }) => event.side === 'below'),\n pointer.below,\n );\n const axis = `${paddedPrefix}${rail.join('')}${vocab.rail.repeat(TERMINAL_RAIL_LENGTH)}${vocab.arrow}${track.endLabel ? ` ${track.endLabel}` : ''}`;\n return [...above, axis, ...below];\n}\n\nfunction renderEventPayload(event: PreparedEvent): string {\n const body = event.description ? `${event.label} :: ${event.description}` : event.label;\n const descriptionSide = event.descriptionSide ? ` descriptionSide=${event.descriptionSide}` : '';\n const callout = event.callout === false ? ' callout=false' : '';\n return `${body} {#${event.id} column=${formatCoordinate(event.column)}${descriptionSide}${callout}}`;\n}\n\nfunction renderTrackPrefix(track: PreparedTrack): string {\n const metadata = `{#${track.id} start=${formatCoordinate(track.startColumn)} end=${formatCoordinate(track.endColumn)}}`;\n return track.label ? `${track.label} ${metadata}: ` : `${metadata}: `;\n}\n\nfunction positionEvents(\n events: readonly PreparedEvent[],\n axisWidth: number,\n globalStart: number,\n globalSpan: number,\n): Array<{ event: PreparedEvent; offset: number }> {\n let previous = -1;\n return events.map((event, index) => {\n const ideal = Math.round(((event.column - globalStart) / globalSpan) * axisWidth);\n const remaining = events.length - index - 1;\n const latest = Math.max(0, axisWidth - remaining);\n const offset = Math.max(previous + 1, Math.min(latest, Math.max(0, ideal)));\n previous = offset;\n return { event, offset };\n });\n}\n\nfunction renderCalloutLanes(\n callouts: ReadonlyArray<{ column: number; text: string }>,\n pointer: string,\n): string[] {\n const lanes: Array<Array<{ column: number; text: string }>> = [];\n const laneEnds: number[] = [];\n for (const callout of callouts) {\n const end = callout.column + 2 + displayWidth(callout.text);\n let lane = laneEnds.findIndex((laneEnd) => callout.column > laneEnd + 1);\n if (lane < 0) {\n lane = lanes.length;\n lanes.push([]);\n laneEnds.push(-1);\n }\n lanes[lane].push(callout);\n laneEnds[lane] = end;\n }\n return lanes.map((lane) => {\n const chars: string[] = [];\n for (const callout of lane) {\n while (chars.length < callout.column) chars.push(' ');\n chars.push(pointer, ' ', ...Array.from(callout.text));\n }\n return chars.join('').trimEnd();\n });\n}\n\nfunction displayWidth(value: string): number {\n return Array.from(value).length;\n}\n\nfunction renderLink(link: PreparedLink, style: AsciiTimelineStyle): string {\n const arrow = style === 'ascii' ? '->' : '\\u2192';\n return `branch: ${link.source} ${arrow} ${link.target}${link.label ? ` : ${link.label}` : ''}`;\n}\n\nfunction prepareTimeline(\n timeline: AsciiTimeline,\n style: AsciiTimelineStyle,\n): { tracks: PreparedTrack[]; links: PreparedLink[] } {\n const sourceTracks = timeline.tracks\n .map((track, index) => ({ track, index }))\n .filter(({ track }) => Array.isArray(track.events) && track.events.length > 0)\n .sort(\n (a, b) =>\n finiteOr(a.track.row, a.index) - finiteOr(b.track.row, b.index) ||\n a.index - b.index ||\n a.track.id.localeCompare(b.track.id),\n );\n\n const usedTrackIds = new Set<string>();\n const usedEventIds = new Set<string>();\n const endpointIds = new Map<string, string>();\n const labelIds = new Map<string, string>();\n const tracks: PreparedTrack[] = [];\n let fallbackIndex = 0;\n\n for (const { track } of sourceTracks) {\n const trackLabel = canonicalInlineText(track.label);\n const endLabel = canonicalInlineText(track.endLabel);\n const trackId = uniqueId(\n canonicalId(track.id, canonicalId(trackLabel, `track_${tracks.length + 1}`)),\n usedTrackIds,\n );\n const sortedEvents = track.events\n .map((event, index) => ({ event, index }))\n .sort(\n (a, b) =>\n finiteOr(a.event.column, a.index) - finiteOr(b.event.column, b.index) ||\n a.index - b.index ||\n a.event.id.localeCompare(b.event.id),\n );\n const events: PreparedEvent[] = [];\n\n for (let index = 0; index < sortedEvents.length; index++) {\n const event = sortedEvents[index].event;\n const fallbackLabel = `Event ${index + 1}`;\n const label = canonicalInlineText(event.label) || fallbackLabel;\n const idBase = canonicalId(event.id, canonicalId(label, `event_${++fallbackIndex}`));\n const id = uniqueId(idBase, usedEventIds);\n const description = canonicalInlineText(event.description);\n const descriptionSide =\n description && (event.descriptionSide === 'above' || event.descriptionSide === 'below')\n ? event.descriptionSide\n : undefined;\n const column = canonicalCoordinate(event.column, index);\n const side: AsciiTimelineSide =\n event.side === 'below'\n ? 'below'\n : event.side === 'above'\n ? 'above'\n : index % 2 === 0\n ? 'above'\n : 'below';\n const marker = canonicalMarker(event.marker, style);\n\n events.push({\n id,\n label,\n ...(description ? { description } : {}),\n ...(descriptionSide ? { descriptionSide } : {}),\n column,\n side,\n ...(event.callout === false ? { callout: false } : {}),\n marker,\n });\n\n // Source ids are normally unique. Preserve the first target when a\n // malformed runtime value duplicates one; the rendered ids themselves\n // are always unique and are also valid branch endpoints.\n if (event.id && !endpointIds.has(event.id)) endpointIds.set(event.id, id);\n endpointIds.set(id, id);\n labelIds.set(slug(label), id);\n }\n\n const eventColumns = events.map((event) => event.column);\n const fallbackStart = eventColumns.length > 0 ? Math.min(...eventColumns) : 0;\n const fallbackEnd = eventColumns.length > 0 ? Math.max(...eventColumns) : fallbackStart + 1;\n tracks.push({\n id: trackId,\n ...(trackLabel ? { label: trackLabel } : {}),\n ...(endLabel ? { endLabel } : {}),\n startColumn: canonicalCoordinate(track.startColumn, fallbackStart),\n endColumn: canonicalCoordinate(track.endColumn, fallbackEnd),\n events,\n });\n }\n\n const resolveEndpoint = (value: string): string | undefined =>\n endpointIds.get(value) ?? labelIds.get(slug(value));\n const links: PreparedLink[] = [];\n for (const link of Array.isArray(timeline.links) ? timeline.links : []) {\n const source = resolveEndpoint(link.source);\n const target = resolveEndpoint(link.target);\n // Unresolved declarations would be dropped by the parser anyway. Drop\n // them before the first render so the emitted form is already a fixpoint.\n if (!source || !target) continue;\n const label = canonicalBranchText(link.label);\n links.push({ source, target, ...(label ? { label } : {}) });\n }\n links.sort(\n (a, b) =>\n a.source.localeCompare(b.source) ||\n a.target.localeCompare(b.target) ||\n (a.label ?? '').localeCompare(b.label ?? ''),\n );\n\n return { tracks, links };\n}\n\nfunction canonicalMarker(\n marker: AsciiTimelineMarker | undefined,\n style: AsciiTimelineStyle,\n): AsciiTimelineMarker {\n if (marker === 'hollow') return 'hollow';\n if (marker === 'diamond' && style !== 'ascii') return 'diamond';\n return 'filled';\n}\n\n/**\n * Normalize point glyphs that would accidentally create another event. Rails,\n * prose arrows, and hyphens are preserved: `parse.ts` only strips separator\n * rails at the payload edges, so `A > B` and `release--candidate` round-trip.\n */\nfunction canonicalInlineText(value: string | undefined): string {\n if (!value) return '';\n const normalized = value\n .normalize('NFC')\n .replace(/[\\r\\n\\t]+/g, ' ')\n .replace(/[\\u25cf\\u25cb\\u25c9\\u25c6\\u25c7\\u2022]+/gu, '\\u00b7')\n .replace(/\\*/g, '\\u2217')\n .replace(/::/g, '\\u2236')\n .replace(/\\s+/g, ' ')\n .trim();\n // A leading authored rail is otherwise indistinguishable from the\n // renderer's separator prefix to `stripEdgeRails`. Keep the punctuation\n // visible with non-structural lookalikes so `--watch`, `-1.5`, and\n // `─phase` survive the very first render/parse normalization cycle.\n return normalized.replace(/^[\\u2500\\u2501\\u2550\\u254c\\u254d\\u2504\\u2505\\u2508\\u2509-]+/u, (run) =>\n Array.from(run, (character) => (character === '-' ? '\\u2212' : '\\u2013')).join(''),\n );\n}\n\nfunction canonicalBranchText(value: string | undefined): string {\n return canonicalInlineText(value).replace(/\\s+/g, ' ').trim();\n}\n\nfunction canonicalId(value: string | undefined, fallback: string): string {\n const normalized = (value ?? '')\n .normalize('NFC')\n .replace(/[\\r\\n\\t\\s]+/g, '_')\n .replace(/[^A-Za-z0-9_.~-]+/g, '_')\n .replace(/^_+|_+$/g, '');\n return normalized || fallback;\n}\n\nfunction uniqueId(base: string, used: Set<string>): string {\n if (!used.has(base)) {\n used.add(base);\n return base;\n }\n let suffix = 2;\n let candidate = `${base}_${suffix}`;\n while (used.has(candidate)) candidate = `${base}_${++suffix}`;\n used.add(candidate);\n return candidate;\n}\n\nfunction slug(value: string): string {\n return (\n value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '') || 'event'\n );\n}\n\nfunction finiteOr(value: number, fallback: number): number {\n return Number.isFinite(value) ? value : fallback;\n}\n\nfunction canonicalCoordinate(value: number, fallback: number): number {\n const finite = finiteOr(value, fallback);\n return Math.max(0, Object.is(finite, -0) ? 0 : finite);\n}\n\nfunction formatCoordinate(value: number): string {\n return String(Object.is(value, -0) ? 0 : value);\n}\n","/**\n * ASCII tree renderer: nested nodes → clean tree art.\n *\n * A deterministic depth-first walk emitting rail/branch prefixes. The\n * fixpoint is structural: `parseTree(renderTree(t))` preserves the node\n * hierarchy + labels + comments, and `renderTree(parseTree(renderTree(t)))`\n * is byte-identical (idempotent after one normalization cycle). Unlike the\n * diagram renderer there is no spatial layout, so jitter is impossible.\n */\n\nimport { ASCII_TREE_VOCAB, UNICODE_TREE_VOCAB } from './chars.js';\nimport type { Tree, TreeNode } from './types.js';\n\nexport interface RenderTreeOptions {\n /** Character vocabulary; defaults to the tree's own detected style. */\n style?: 'unicode' | 'ascii';\n}\n\nexport function renderTree(tree: Tree, options: RenderTreeOptions = {}): string {\n const vocab = (options.style ?? tree.style) === 'ascii' ? ASCII_TREE_VOCAB : UNICODE_TREE_VOCAB;\n const lines: string[] = [];\n\n const label = (node: TreeNode): string =>\n node.comment ? `${node.label} # ${node.comment}` : node.label;\n\n const walk = (nodes: readonly TreeNode[], prefix: string): void => {\n nodes.forEach((node, i) => {\n const last = i === nodes.length - 1;\n lines.push(prefix + (last ? vocab.elbow : vocab.tee) + label(node));\n walk(node.children, prefix + (last ? vocab.gap : vocab.rail));\n });\n };\n\n // Roots sit at column 0 with no connector; their children get branches.\n for (const root of tree.roots) {\n lines.push(label(root));\n walk(root.children, '');\n }\n\n return lines.join('\\n');\n}\n"],"mappings":"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","names":["suggestion","rect","slugify","slug","UNICODE_VOCAB","ASCII_VOCAB"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
toMdast
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-66QO7XFB.js";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
} from "./chunk-
|
|
5
|
+
formatFrontmatterValue
|
|
6
|
+
} from "./chunk-AMIR72JP.js";
|
|
7
7
|
|
|
8
8
|
// src/markdown/stringify.ts
|
|
9
9
|
import { unified } from "unified";
|
|
@@ -15,7 +15,7 @@ var defaultProcessor;
|
|
|
15
15
|
var DQ_RUN = `"(?:[^"\\\\]|\\\\.)*"`;
|
|
16
16
|
var SQ_RUN = `'(?:[^'\\\\]|\\\\.)*'`;
|
|
17
17
|
var ESCAPED_TEMPLATE_SPAN_RE = new RegExp(
|
|
18
|
-
`\\{\\\\\\[((?:${DQ_RUN}|${SQ_RUN}|\\\\.|[^\\]\\\\])
|
|
18
|
+
`\\{\\\\\\[((?:${DQ_RUN}|${SQ_RUN}|\\\\.|[^\\]\\\\])*)\\]\\}`,
|
|
19
19
|
"g"
|
|
20
20
|
);
|
|
21
21
|
var HEADING_LINE_RE = /^#{1,6} .*$/gm;
|
|
@@ -79,8 +79,8 @@ function stringifyMarkdown(doc, options) {
|
|
|
79
79
|
cleaned = cleaned.replace(/\{(?!\\?\[)[^}]*\}/g, (match) => match.replace(/\\:/g, ":"));
|
|
80
80
|
if (doc.frontmatter && Object.keys(doc.frontmatter).length > 0) {
|
|
81
81
|
const yamlLines = Object.entries(doc.frontmatter).map(([k, v]) => {
|
|
82
|
-
if (typeof v === "string") {
|
|
83
|
-
return
|
|
82
|
+
if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
|
|
83
|
+
return `${k}: ${formatFrontmatterValue(v)}`;
|
|
84
84
|
}
|
|
85
85
|
return `${k}: ${JSON.stringify(v)}`;
|
|
86
86
|
});
|
|
@@ -341,4 +341,4 @@ export {
|
|
|
341
341
|
sanitizeUrl,
|
|
342
342
|
sanitizeHtmlNodes
|
|
343
343
|
};
|
|
344
|
-
//# sourceMappingURL=chunk-
|
|
344
|
+
//# sourceMappingURL=chunk-R2GC6RLD.js.map
|