@bendyline/squisq 2.0.1 → 2.2.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/LICENSE +21 -0
- package/NOTICE.md +24 -0
- package/dist/{ContentContainer-BXUlIf18.d.ts → ContentContainer-B2w9sUoL.d.ts} +15 -0
- package/dist/{Doc-ylqWKDc_.d.ts → Doc-BubIpWsp.d.ts} +160 -3
- package/dist/{ImageEditDoc-D828IXJ1.d.ts → ImageEditDoc-CGxk5CHc.d.ts} +1 -1
- package/dist/{annotationCoercion-Dr_DY9Hx.d.ts → annotationCoercion-PtRQhk5V.d.ts} +1 -1
- package/dist/chunk-2L55443L.js +0 -0
- package/dist/chunk-2ZWIXGAC.js +214 -0
- package/dist/{chunk-2PWOO4ZE.js → chunk-32R2RZAO.js} +72 -3
- package/dist/chunk-3IGPAPQ7.js +645 -0
- package/dist/{chunk-QE7TWGVT.js → chunk-4VOD55SX.js} +0 -1
- package/dist/{chunk-3E5F2XMR.js → chunk-67L6WRJN.js} +0 -1
- package/dist/{chunk-5DKBFXPY.js → chunk-6ECMNUIP.js} +26 -18
- package/dist/{chunk-X6DUONGT.js → chunk-7ARJZYQY.js} +280 -128
- package/dist/{chunk-DBS6RIFL.js → chunk-7N4G32LG.js} +0 -1
- package/dist/{chunk-JOQYPRDZ.js → chunk-7YEZFHLS.js} +10 -8
- package/dist/{chunk-2UQOHYE2.js → chunk-7ZAAICW4.js} +0 -1
- package/dist/{chunk-66QO7XFB.js → chunk-ACZOVWX3.js} +117 -7
- package/dist/{chunk-5J4HKRJF.js → chunk-BAOV476U.js} +0 -1
- package/dist/chunk-BCCXTMN5.js +699 -0
- package/dist/{chunk-W4O2TX5I.js → chunk-C33GTPUZ.js} +579 -4
- package/dist/{chunk-MMPBOUK7.js → chunk-CB45YGAM.js} +7 -2
- package/dist/{chunk-CY2R2VPR.js → chunk-DYPMOPIW.js} +18 -2
- package/dist/{chunk-VR7UPJ7C.js → chunk-FCG3BIZN.js} +12 -1
- package/dist/{chunk-5UYI3RJB.js → chunk-FDYDYL77.js} +54 -40
- package/dist/{chunk-TFJVXUHH.js → chunk-I2O6W7DX.js} +1513 -79
- package/dist/{chunk-Q7LROV2H.js → chunk-NKNMGIIN.js} +0 -1
- package/dist/chunk-OPO5K4DZ.js +241 -0
- package/dist/{chunk-TUWMK62B.js → chunk-PUS54YU6.js} +45 -2
- package/dist/chunk-QKPXHDLR.js +0 -0
- package/dist/{chunk-GZY66SDN.js → chunk-R3KTTOMS.js} +0 -1
- package/dist/{chunk-PXLVXTLW.js → chunk-RS5AP3J4.js} +72 -15
- package/dist/chunk-WV5ARNDA.js +0 -0
- package/dist/{chunk-4X3JQXNM.js → chunk-XOFT65EX.js} +1 -2
- package/dist/{chunk-FVTQSNR7.js → chunk-XRW6P7IF.js} +13 -5
- package/dist/chunk-XWNNA3KE.js +0 -0
- package/dist/chunk-YZNGMV3G.js +0 -0
- package/dist/{chunk-R2YZTCLO.js → chunk-ZQKZSJAX.js} +1 -2
- package/dist/doc/index.d.ts +166 -12
- package/dist/doc/index.js +36 -17
- package/dist/generate/index.d.ts +2 -2
- package/dist/generate/index.js +2 -3
- package/dist/icons/index.js +3 -4
- package/dist/icons/inlineIconMarker.js +1 -2
- package/dist/imageEdit/index.d.ts +48 -17
- package/dist/imageEdit/index.js +3 -4
- package/dist/index.d.ts +13 -12
- package/dist/index.js +118 -33
- package/dist/jsonForm/index.d.ts +10 -3
- package/dist/jsonForm/index.js +8 -7
- package/dist/markdown/index.d.ts +75 -11
- package/dist/markdown/index.js +32 -7
- package/dist/materializePageSection-wSLA2A1g.d.ts +223 -0
- package/dist/narration/index.d.ts +16 -3
- package/dist/narration/index.js +13 -14
- package/dist/random/index.d.ts +11 -2
- package/dist/random/index.js +2 -3
- package/dist/recommend/index.d.ts +1 -1
- package/dist/recommend/index.js +3 -4
- package/dist/schemas/index.d.ts +31 -6
- package/dist/schemas/index.js +43 -6
- package/dist/spatial/index.d.ts +2 -1
- package/dist/spatial/index.js +1 -2
- package/dist/storage/index.d.ts +4 -2
- package/dist/storage/index.js +1 -2
- package/dist/{themeLibrary-RjVgLpUi.d.ts → themeLibrary-DU9mUmVl.d.ts} +1 -1
- package/dist/timing/index.js +3 -4
- package/dist/transform/index.d.ts +9 -10
- package/dist/transform/index.js +6 -7
- package/dist/{types-C4kiRn_k.d.ts → types-8QjefM9J.d.ts} +38 -2
- package/dist/{types-BwMPl2CB.d.ts → types-CUNc9biN.d.ts} +24 -1
- package/dist/versions/index.d.ts +14 -11
- package/dist/versions/index.js +2 -3
- package/package.json +4 -2
- package/dist/chunk-2PWOO4ZE.js.map +0 -1
- package/dist/chunk-2UQOHYE2.js.map +0 -1
- package/dist/chunk-3E5F2XMR.js.map +0 -1
- package/dist/chunk-4X3JQXNM.js.map +0 -1
- package/dist/chunk-5DKBFXPY.js.map +0 -1
- package/dist/chunk-5J4HKRJF.js.map +0 -1
- package/dist/chunk-5UYI3RJB.js.map +0 -1
- package/dist/chunk-66QO7XFB.js.map +0 -1
- package/dist/chunk-AMIR72JP.js +0 -380
- package/dist/chunk-AMIR72JP.js.map +0 -1
- package/dist/chunk-CY2R2VPR.js.map +0 -1
- package/dist/chunk-DBS6RIFL.js.map +0 -1
- package/dist/chunk-DNJKBAI7.js +0 -1
- package/dist/chunk-DNJKBAI7.js.map +0 -1
- package/dist/chunk-ET53IIEP.js +0 -1
- package/dist/chunk-ET53IIEP.js.map +0 -1
- package/dist/chunk-FVJUUTEM.js +0 -74
- package/dist/chunk-FVJUUTEM.js.map +0 -1
- package/dist/chunk-FVTQSNR7.js.map +0 -1
- package/dist/chunk-GZY66SDN.js.map +0 -1
- package/dist/chunk-JOQYPRDZ.js.map +0 -1
- package/dist/chunk-MMPBOUK7.js.map +0 -1
- package/dist/chunk-PGGGKYWG.js +0 -1
- package/dist/chunk-PGGGKYWG.js.map +0 -1
- package/dist/chunk-PXLVXTLW.js.map +0 -1
- package/dist/chunk-Q7LROV2H.js.map +0 -1
- package/dist/chunk-QE7TWGVT.js.map +0 -1
- package/dist/chunk-R2GC6RLD.js +0 -344
- package/dist/chunk-R2GC6RLD.js.map +0 -1
- package/dist/chunk-R2YZTCLO.js.map +0 -1
- package/dist/chunk-S7A5D7ZJ.js +0 -174
- package/dist/chunk-S7A5D7ZJ.js.map +0 -1
- package/dist/chunk-TFJVXUHH.js.map +0 -1
- package/dist/chunk-TUWMK62B.js.map +0 -1
- package/dist/chunk-V543AI2F.js +0 -1
- package/dist/chunk-V543AI2F.js.map +0 -1
- package/dist/chunk-VR7UPJ7C.js.map +0 -1
- package/dist/chunk-W4O2TX5I.js.map +0 -1
- package/dist/chunk-X6DUONGT.js.map +0 -1
- package/dist/chunk-ZLQKNOZQ.js +0 -1
- package/dist/chunk-ZLQKNOZQ.js.map +0 -1
- package/dist/doc/index.js.map +0 -1
- package/dist/generate/index.js.map +0 -1
- package/dist/icons/index.js.map +0 -1
- package/dist/icons/inlineIconMarker.js.map +0 -1
- package/dist/imageEdit/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/jsonForm/index.js.map +0 -1
- package/dist/markdown/index.js.map +0 -1
- package/dist/narration/index.js.map +0 -1
- package/dist/random/index.js.map +0 -1
- package/dist/recommend/index.js.map +0 -1
- package/dist/schemas/index.js.map +0 -1
- package/dist/spatial/index.js.map +0 -1
- package/dist/storage/index.js.map +0 -1
- package/dist/timing/index.js.map +0 -1
- package/dist/transform/index.js.map +0 -1
- package/dist/versions/index.js.map +0 -1
- package/src/__tests__/animationUtils.test.ts +0 -117
- package/src/__tests__/annotationCoercion.test.ts +0 -243
- package/src/__tests__/applyNarrationTiming.test.ts +0 -190
- package/src/__tests__/applyRenderStyle.test.ts +0 -146
- package/src/__tests__/asciiDiagramBattle.test.ts +0 -246
- package/src/__tests__/asciiDiagramDetect.test.ts +0 -162
- package/src/__tests__/asciiDiagramMapping.test.ts +0 -38
- package/src/__tests__/asciiDiagramParse.test.ts +0 -233
- package/src/__tests__/asciiDiagramPipeline.test.ts +0 -273
- package/src/__tests__/asciiDiagramRender.test.ts +0 -162
- package/src/__tests__/asciiDiagramRepair.test.ts +0 -84
- package/src/__tests__/asciiTimelineDetect.test.ts +0 -157
- package/src/__tests__/asciiTimelineParse.test.ts +0 -205
- package/src/__tests__/asciiTimelinePipeline.test.ts +0 -349
- package/src/__tests__/asciiTimelineRender.test.ts +0 -376
- package/src/__tests__/atmosphereLayers.test.ts +0 -108
- package/src/__tests__/attrTokens.test.ts +0 -167
- package/src/__tests__/colorUtils.test.ts +0 -112
- package/src/__tests__/contentContainer.test.ts +0 -325
- package/src/__tests__/contentExtractor.test.ts +0 -243
- package/src/__tests__/coverBlock.test.ts +0 -310
- package/src/__tests__/customTemplateSample.test.ts +0 -144
- package/src/__tests__/customTemplatesFrontmatter.test.ts +0 -221
- package/src/__tests__/customThemesFrontmatter.test.ts +0 -146
- package/src/__tests__/dataTable.test.ts +0 -145
- package/src/__tests__/diagramBlock.test.ts +0 -122
- package/src/__tests__/diagramLayout.test.ts +0 -134
- package/src/__tests__/diagramText.test.ts +0 -26
- package/src/__tests__/docToMarkdownMedia.test.ts +0 -83
- package/src/__tests__/drawing.test.ts +0 -109
- package/src/__tests__/drawingBlock.test.ts +0 -124
- package/src/__tests__/drawingLayout.test.ts +0 -171
- package/src/__tests__/fixtures/asciiDiagramBattle.ts +0 -512
- package/src/__tests__/fixtures/asciiDiagrams.ts +0 -287
- package/src/__tests__/fixtures/asciiTimelines.ts +0 -35
- package/src/__tests__/fixtures/treeviewFixtures.ts +0 -243
- package/src/__tests__/geohash.test.ts +0 -110
- package/src/__tests__/getLayers.test.ts +0 -243
- package/src/__tests__/getLayersFallback.test.ts +0 -103
- package/src/__tests__/haversine.test.ts +0 -63
- package/src/__tests__/iconResolve.test.ts +0 -122
- package/src/__tests__/imageEditExportSvg.test.ts +0 -70
- package/src/__tests__/imageEditState.test.ts +0 -74
- package/src/__tests__/imageEditVersions.test.ts +0 -243
- package/src/__tests__/inferDocumentTitle.test.ts +0 -50
- package/src/__tests__/inlineIconMarker.test.ts +0 -36
- package/src/__tests__/inputDescriptors.test.ts +0 -162
- package/src/__tests__/jsonForm.chooseControl.test.ts +0 -86
- package/src/__tests__/jsonForm.evaluateWhen.test.ts +0 -59
- package/src/__tests__/jsonForm.inferSchema.test.ts +0 -25
- package/src/__tests__/jsonForm.pointer.test.ts +0 -149
- package/src/__tests__/jsonForm.tokens.test.ts +0 -84
- package/src/__tests__/layoutBlock.test.ts +0 -83
- package/src/__tests__/layoutLayout.test.ts +0 -169
- package/src/__tests__/localForageAdapter.test.ts +0 -155
- package/src/__tests__/majorApiTypes.test.ts +0 -18
- package/src/__tests__/markdown.test.ts +0 -1009
- package/src/__tests__/markdownIcons.test.ts +0 -104
- package/src/__tests__/markdownSanitize.test.ts +0 -81
- package/src/__tests__/markdownToDoc.test.ts +0 -957
- package/src/__tests__/matchFontFamily.test.ts +0 -114
- package/src/__tests__/materializeBlockLayers.test.ts +0 -135
- package/src/__tests__/materializeTestUtils.ts +0 -17
- package/src/__tests__/mediaAnnotations.test.ts +0 -91
- package/src/__tests__/mediaSchedule.test.ts +0 -118
- package/src/__tests__/narrationAlign.test.ts +0 -150
- package/src/__tests__/narrationFeatures.test.ts +0 -71
- package/src/__tests__/narrationNuclei.test.ts +0 -45
- package/src/__tests__/narrationPacing.test.ts +0 -189
- package/src/__tests__/narrationScript.test.ts +0 -149
- package/src/__tests__/narrationSessionRepro.test.ts +0 -62
- package/src/__tests__/narrationSidecar.test.ts +0 -88
- package/src/__tests__/narrationSyllables.test.ts +0 -65
- package/src/__tests__/narrationTestSignals.ts +0 -167
- package/src/__tests__/narrationVad.test.ts +0 -66
- package/src/__tests__/pandocAttrParse.test.ts +0 -187
- package/src/__tests__/recommendTemplates.test.ts +0 -183
- package/src/__tests__/resolveDocTheme.test.ts +0 -69
- package/src/__tests__/rootExports.test.ts +0 -61
- package/src/__tests__/scopedContentContainer.test.ts +0 -109
- package/src/__tests__/seededRandom.test.ts +0 -142
- package/src/__tests__/shapeGeometry.test.ts +0 -138
- package/src/__tests__/shapeVocabulary.test.ts +0 -133
- package/src/__tests__/storage.test.ts +0 -60
- package/src/__tests__/structuredData.test.ts +0 -249
- package/src/__tests__/surface.test.ts +0 -68
- package/src/__tests__/templateAnnotationParse.test.ts +0 -160
- package/src/__tests__/templateInputs.test.ts +0 -69
- package/src/__tests__/templateMetadata.test.ts +0 -32
- package/src/__tests__/templates.test.ts +0 -710
- package/src/__tests__/themeCompile.test.ts +0 -225
- package/src/__tests__/themeValidator.test.ts +0 -131
- package/src/__tests__/timing.test.ts +0 -167
- package/src/__tests__/transformProvenance.test.ts +0 -160
- package/src/__tests__/transformV2.test.ts +0 -163
- package/src/__tests__/transitionNormalize.test.ts +0 -61
- package/src/__tests__/treeviewBattle.test.ts +0 -76
- package/src/__tests__/treeviewDetect.test.ts +0 -168
- package/src/__tests__/treeviewParse.test.ts +0 -118
- package/src/__tests__/treeviewPipeline.test.ts +0 -183
- package/src/__tests__/treeviewRender.test.ts +0 -91
- package/src/__tests__/validateDoc.test.ts +0 -260
- package/src/__tests__/versions.test.ts +0 -459
- package/src/doc/annotationBlocks.ts +0 -117
- package/src/doc/applyNarrationTiming.ts +0 -244
- package/src/doc/asciiDiagram/chars.ts +0 -210
- package/src/doc/asciiDiagram/detect.ts +0 -175
- package/src/doc/asciiDiagram/index.ts +0 -38
- package/src/doc/asciiDiagram/mapping.ts +0 -225
- package/src/doc/asciiDiagram/parse.ts +0 -1095
- package/src/doc/asciiDiagram/render.ts +0 -963
- package/src/doc/asciiDiagram/repair.ts +0 -400
- package/src/doc/asciiDiagram/types.ts +0 -65
- package/src/doc/asciiTimeline/detect.ts +0 -138
- package/src/doc/asciiTimeline/index.ts +0 -26
- package/src/doc/asciiTimeline/mapping.ts +0 -43
- package/src/doc/asciiTimeline/parse.ts +0 -870
- package/src/doc/asciiTimeline/render.ts +0 -427
- package/src/doc/asciiTimeline/types.ts +0 -73
- package/src/doc/asciiTimeline/wrappedFlow.ts +0 -427
- package/src/doc/audioMapping.ts +0 -442
- package/src/doc/customTemplatesFrontmatter.ts +0 -273
- package/src/doc/customThemesFrontmatter.ts +0 -95
- package/src/doc/docToMarkdown.ts +0 -284
- package/src/doc/index.ts +0 -127
- package/src/doc/markdownToDoc.ts +0 -1054
- package/src/doc/materializeBlockLayers.ts +0 -304
- package/src/doc/mediaAnnotations.ts +0 -120
- package/src/doc/resolveDocTheme.ts +0 -56
- package/src/doc/standaloneAnnotation.ts +0 -58
- package/src/doc/structuredData.ts +0 -301
- package/src/doc/templateInputs.ts +0 -423
- package/src/doc/templates/__tests__/customTemplate.test.ts +0 -170
- package/src/doc/templates/__tests__/customTemplateRegistry.test.ts +0 -124
- package/src/doc/templates/__tests__/listBlock.test.ts +0 -64
- package/src/doc/templates/accentImage.ts +0 -362
- package/src/doc/templates/captionUtils.ts +0 -56
- package/src/doc/templates/comparisonBar.ts +0 -173
- package/src/doc/templates/coverBlock.ts +0 -255
- package/src/doc/templates/customTemplate.ts +0 -51
- package/src/doc/templates/dataTable.ts +0 -102
- package/src/doc/templates/dateEvent.ts +0 -147
- package/src/doc/templates/definitionCard.ts +0 -140
- package/src/doc/templates/diagramBlock.ts +0 -403
- package/src/doc/templates/diagramLayout.ts +0 -159
- package/src/doc/templates/drawingBlock.ts +0 -325
- package/src/doc/templates/drawingLayout.ts +0 -539
- package/src/doc/templates/factCard.ts +0 -146
- package/src/doc/templates/fallbackBlock.ts +0 -123
- package/src/doc/templates/featureBlock.ts +0 -209
- package/src/doc/templates/fullBleedQuote.ts +0 -83
- package/src/doc/templates/imageWithCaption.ts +0 -186
- package/src/doc/templates/index.ts +0 -642
- package/src/doc/templates/inputDescriptors.ts +0 -451
- package/src/doc/templates/layoutBlock.ts +0 -43
- package/src/doc/templates/layoutLayout.ts +0 -243
- package/src/doc/templates/listBlock.ts +0 -207
- package/src/doc/templates/mapBlock.ts +0 -138
- package/src/doc/templates/metadata.ts +0 -130
- package/src/doc/templates/persistentLayers.ts +0 -526
- package/src/doc/templates/photoGrid.ts +0 -190
- package/src/doc/templates/pullQuote.ts +0 -141
- package/src/doc/templates/quoteBlock.ts +0 -141
- package/src/doc/templates/registry.ts +0 -88
- package/src/doc/templates/sectionHeader.ts +0 -120
- package/src/doc/templates/statHighlight.ts +0 -146
- package/src/doc/templates/templateNames.ts +0 -22
- package/src/doc/templates/timelineBlock.ts +0 -613
- package/src/doc/templates/titleBlock.ts +0 -150
- package/src/doc/templates/tokens/__tests__/resolveTokens.test.ts +0 -487
- package/src/doc/templates/tokens/resolveTokens.ts +0 -453
- package/src/doc/templates/treeBlock.ts +0 -131
- package/src/doc/templates/twoColumn.ts +0 -263
- package/src/doc/templates/videoPullQuote.ts +0 -142
- package/src/doc/templates/videoWithCaption.ts +0 -135
- package/src/doc/treeview/chars.ts +0 -72
- package/src/doc/treeview/detect.ts +0 -145
- package/src/doc/treeview/index.ts +0 -30
- package/src/doc/treeview/mapping.ts +0 -95
- package/src/doc/treeview/parse.ts +0 -201
- package/src/doc/treeview/render.ts +0 -41
- package/src/doc/treeview/types.ts +0 -43
- package/src/doc/utils/animationUtils.ts +0 -399
- package/src/doc/utils/applyRenderStyle.ts +0 -106
- package/src/doc/utils/diagramText.ts +0 -78
- package/src/doc/utils/imageTreatment.ts +0 -70
- package/src/doc/utils/nearest.ts +0 -59
- package/src/doc/utils/shapeGeometry.ts +0 -614
- package/src/doc/utils/themeUtils.ts +0 -243
- package/src/doc/validate.ts +0 -575
- package/src/generate/contentExtractor.ts +0 -921
- package/src/generate/index.ts +0 -18
- package/src/generate/templateMapper.ts +0 -177
- package/src/icons/iconData.ts +0 -31
- package/src/icons/index.ts +0 -26
- package/src/icons/inlineIconMarker.ts +0 -73
- package/src/icons/resolve.ts +0 -139
- package/src/imageEdit/ImageEditVersionManager.ts +0 -73
- package/src/imageEdit/export.ts +0 -410
- package/src/imageEdit/index.ts +0 -72
- package/src/imageEdit/persistence.ts +0 -113
- package/src/imageEdit/state.ts +0 -112
- package/src/imageEdit/versionPaths.ts +0 -44
- package/src/imageEdit/versions.ts +0 -152
- package/src/index.ts +0 -15
- package/src/internal/immutable.ts +0 -58
- package/src/jsonForm/chooseControl.ts +0 -88
- package/src/jsonForm/evaluateWhen.ts +0 -59
- package/src/jsonForm/index.ts +0 -32
- package/src/jsonForm/inferSchema.ts +0 -25
- package/src/jsonForm/pointer.ts +0 -154
- package/src/jsonForm/tokens.ts +0 -78
- package/src/jsonForm/types.ts +0 -167
- package/src/markdown/annotationCoercion.ts +0 -295
- package/src/markdown/attrTokens.ts +0 -243
- package/src/markdown/convert.ts +0 -1353
- package/src/markdown/htmlParse.ts +0 -212
- package/src/markdown/index.ts +0 -152
- package/src/markdown/parse.ts +0 -103
- package/src/markdown/sanitize.ts +0 -318
- package/src/markdown/stringify.ts +0 -207
- package/src/markdown/types.ts +0 -710
- package/src/markdown/utils.ts +0 -459
- package/src/narration/align.ts +0 -514
- package/src/narration/features.ts +0 -231
- package/src/narration/index.ts +0 -86
- package/src/narration/nuclei.ts +0 -118
- package/src/narration/pacing.ts +0 -211
- package/src/narration/script.ts +0 -239
- package/src/narration/session.ts +0 -100
- package/src/narration/sidecar.ts +0 -187
- package/src/narration/syllables.ts +0 -85
- package/src/narration/trace.ts +0 -50
- package/src/narration/types.ts +0 -299
- package/src/narration/vad.ts +0 -131
- package/src/ngeohash.d.ts +0 -11
- package/src/random/SeededRandom.ts +0 -127
- package/src/random/index.ts +0 -1
- package/src/recommend/index.ts +0 -16
- package/src/recommend/numberHighlight.ts +0 -25
- package/src/recommend/templates.ts +0 -393
- package/src/schemas/BlockTemplates.ts +0 -1046
- package/src/schemas/CustomTemplates.ts +0 -126
- package/src/schemas/Doc.ts +0 -1052
- package/src/schemas/ImageEditDoc.ts +0 -102
- package/src/schemas/LayoutStrategy.ts +0 -178
- package/src/schemas/Media.ts +0 -179
- package/src/schemas/MediaProvider.ts +0 -70
- package/src/schemas/Theme.ts +0 -406
- package/src/schemas/Transitions.ts +0 -224
- package/src/schemas/Types.ts +0 -15
- package/src/schemas/Viewport.ts +0 -91
- package/src/schemas/colorUtils.ts +0 -219
- package/src/schemas/fontStacks.ts +0 -339
- package/src/schemas/index.ts +0 -29
- package/src/schemas/themeCompile.ts +0 -237
- package/src/schemas/themeConstants.ts +0 -2
- package/src/schemas/themeLibrary.ts +0 -60
- package/src/schemas/themeValidator.ts +0 -426
- package/src/schemas/themes/bold.json +0 -48
- package/src/schemas/themes/cinematic.json +0 -111
- package/src/schemas/themes/documentary.json +0 -96
- package/src/schemas/themes/gezellig.json +0 -93
- package/src/schemas/themes/index.ts +0 -53
- package/src/schemas/themes/magazine.json +0 -89
- package/src/schemas/themes/minimalist.json +0 -45
- package/src/schemas/themes/morning-light.json +0 -85
- package/src/schemas/themes/standard-dark.json +0 -85
- package/src/schemas/themes/standard.json +0 -74
- package/src/schemas/themes/tech-dark.json +0 -101
- package/src/schemas/themes/warm-earth.json +0 -50
- package/src/spatial/Geohash.ts +0 -196
- package/src/spatial/Haversine.ts +0 -59
- package/src/spatial/index.ts +0 -2
- package/src/storage/ContentContainer.ts +0 -220
- package/src/storage/LocalForageAdapter.ts +0 -103
- package/src/storage/LocalStorageAdapter.ts +0 -57
- package/src/storage/MediaProviderFromContainer.ts +0 -92
- package/src/storage/MemoryStorageAdapter.ts +0 -37
- package/src/storage/ScopedContentContainer.ts +0 -143
- package/src/storage/Storage.ts +0 -28
- package/src/storage/index.ts +0 -9
- package/src/timing/index.ts +0 -17
- package/src/timing/narrationTiming.ts +0 -220
- package/src/timing/readingTime.ts +0 -94
- package/src/transform/applyTransform.ts +0 -122
- package/src/transform/blockAnalyzer.ts +0 -181
- package/src/transform/index.ts +0 -23
- package/src/transform/registry.ts +0 -198
- package/src/transform/styles/dataDriven.ts +0 -17
- package/src/transform/styles/documentary.ts +0 -17
- package/src/transform/styles/index.ts +0 -5
- package/src/transform/styles/magazine.ts +0 -18
- package/src/transform/styles/minimal.ts +0 -17
- package/src/transform/styles/narrative.ts +0 -18
- package/src/transform/templateSelector.ts +0 -389
- package/src/transform/timingAllocator.ts +0 -257
- package/src/transform/types.ts +0 -151
- package/src/versions/DocumentVersionManager.ts +0 -70
- package/src/versions/gitignore.ts +0 -34
- package/src/versions/index.ts +0 -56
- package/src/versions/operations.ts +0 -144
- package/src/versions/paths.ts +0 -51
- package/src/versions/snapshotStore.ts +0 -202
- package/src/versions/timestamp.ts +0 -48
- package/src/versions/types.ts +0 -93
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import * as root from '../index';
|
|
3
|
-
import * as icons from '../icons/index';
|
|
4
|
-
import * as schemas from '../schemas/index';
|
|
5
|
-
import * as transform from '../transform/index';
|
|
6
|
-
|
|
7
|
-
const transformRuntimeExports = [
|
|
8
|
-
'applyTransform',
|
|
9
|
-
'resolveTransformStyle',
|
|
10
|
-
'getTransformStyleIds',
|
|
11
|
-
'getTransformStyleSummaries',
|
|
12
|
-
'createTransformStyleRegistry',
|
|
13
|
-
'DEFAULT_TRANSFORM_STYLE_ID',
|
|
14
|
-
'analyzeBlocks',
|
|
15
|
-
'extractDocImages',
|
|
16
|
-
] as const;
|
|
17
|
-
|
|
18
|
-
const iconRuntimeExports = [
|
|
19
|
-
'ICONS',
|
|
20
|
-
'resolveIcon',
|
|
21
|
-
'canonicalIconToken',
|
|
22
|
-
'looksLikeIconToken',
|
|
23
|
-
'suggestIcons',
|
|
24
|
-
'iconGlyph',
|
|
25
|
-
] as const;
|
|
26
|
-
|
|
27
|
-
function expectReExported(
|
|
28
|
-
rootExports: Record<string, unknown>,
|
|
29
|
-
subpathExports: Record<string, unknown>,
|
|
30
|
-
names: readonly string[],
|
|
31
|
-
): void {
|
|
32
|
-
for (const name of names) {
|
|
33
|
-
expect(rootExports[name], `root barrel should re-export ${name}`).toBe(subpathExports[name]);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
describe('root barrel exports', () => {
|
|
38
|
-
it('re-exports transform runtime APIs', () => {
|
|
39
|
-
expectReExported(root, transform, transformRuntimeExports);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('re-exports icon runtime APIs', () => {
|
|
43
|
-
expectReExported(root, icons, iconRuntimeExports);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('does not publish process-global registry mutators', () => {
|
|
47
|
-
for (const name of [
|
|
48
|
-
'registerTheme',
|
|
49
|
-
'unregisterTheme',
|
|
50
|
-
'getRegisteredThemes',
|
|
51
|
-
'lookupRegisteredTheme',
|
|
52
|
-
]) {
|
|
53
|
-
expect(root).not.toHaveProperty(name);
|
|
54
|
-
expect(schemas).not.toHaveProperty(name);
|
|
55
|
-
}
|
|
56
|
-
for (const name of ['registerTransformStyle', 'unregisterTransformStyle']) {
|
|
57
|
-
expect(root).not.toHaveProperty(name);
|
|
58
|
-
expect(transform).not.toHaveProperty(name);
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
});
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
-
import { MemoryContentContainer } from '../storage/ContentContainer';
|
|
3
|
-
import { ScopedContentContainer, scopeContainer } from '../storage/ScopedContentContainer';
|
|
4
|
-
|
|
5
|
-
const enc = (s: string) => new TextEncoder().encode(s);
|
|
6
|
-
const dec = (b: ArrayBuffer | null) => (b ? new TextDecoder().decode(b) : null);
|
|
7
|
-
|
|
8
|
-
describe('ScopedContentContainer', () => {
|
|
9
|
-
let parent: MemoryContentContainer;
|
|
10
|
-
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
parent = new MemoryContentContainer();
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('writeFile + readFile route through the prefix', async () => {
|
|
16
|
-
const scoped = scopeContainer(parent, 'image_files');
|
|
17
|
-
await scoped.writeFile('state.json', enc('{}'), 'application/json');
|
|
18
|
-
|
|
19
|
-
expect(dec(await parent.readFile('image_files/state.json'))).toBe('{}');
|
|
20
|
-
expect(dec(await scoped.readFile('state.json'))).toBe('{}');
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('exists + removeFile honor the prefix', async () => {
|
|
24
|
-
const scoped = scopeContainer(parent, 'image_files');
|
|
25
|
-
await scoped.writeFile('a.txt', enc('a'));
|
|
26
|
-
expect(await scoped.exists('a.txt')).toBe(true);
|
|
27
|
-
expect(await parent.exists('image_files/a.txt')).toBe(true);
|
|
28
|
-
|
|
29
|
-
await scoped.removeFile('a.txt');
|
|
30
|
-
expect(await scoped.exists('a.txt')).toBe(false);
|
|
31
|
-
expect(await parent.exists('image_files/a.txt')).toBe(false);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('listFiles returns prefix-stripped paths and ignores siblings', async () => {
|
|
35
|
-
const scoped = scopeContainer(parent, 'image_files');
|
|
36
|
-
await parent.writeFile('outside.txt', enc('x'));
|
|
37
|
-
await parent.writeFile('image_files_sibling/peek.txt', enc('y')); // not in scope
|
|
38
|
-
await scoped.writeFile('a.txt', enc('1'));
|
|
39
|
-
await scoped.writeFile('sub/b.txt', enc('2'));
|
|
40
|
-
|
|
41
|
-
const list = await scoped.listFiles();
|
|
42
|
-
const paths = list.map((e) => e.path).sort();
|
|
43
|
-
expect(paths).toEqual(['a.txt', 'sub/b.txt']);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('listFiles with prefix joins the scope prefix', async () => {
|
|
47
|
-
const scoped = scopeContainer(parent, 'sidecar');
|
|
48
|
-
await scoped.writeFile('assets/a.png', enc('a'));
|
|
49
|
-
await scoped.writeFile('assets/b.png', enc('b'));
|
|
50
|
-
await scoped.writeFile('state.json', enc('{}'));
|
|
51
|
-
|
|
52
|
-
const list = await scoped.listFiles('assets/');
|
|
53
|
-
expect(list.map((e) => e.path).sort()).toEqual(['assets/a.png', 'assets/b.png']);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('nested scopes compose', async () => {
|
|
57
|
-
const a = scopeContainer(parent, 'a');
|
|
58
|
-
const ab = scopeContainer(a, 'b');
|
|
59
|
-
await ab.writeFile('c.txt', enc('hi'));
|
|
60
|
-
expect(dec(await parent.readFile('a/b/c.txt'))).toBe('hi');
|
|
61
|
-
expect(dec(await ab.readFile('c.txt'))).toBe('hi');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('normalizes leading/trailing slashes in prefix and paths', async () => {
|
|
65
|
-
const scoped = scopeContainer(parent, '/sidecar/');
|
|
66
|
-
expect(scoped.prefix).toBe('sidecar');
|
|
67
|
-
await scoped.writeFile('/x.txt', enc('x'));
|
|
68
|
-
expect(dec(await parent.readFile('sidecar/x.txt'))).toBe('x');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('rejects empty / dotted prefixes', () => {
|
|
72
|
-
expect(() => scopeContainer(parent, '')).toThrow();
|
|
73
|
-
expect(() => scopeContainer(parent, '/')).toThrow();
|
|
74
|
-
expect(() => scopeContainer(parent, 'a/../b')).toThrow();
|
|
75
|
-
expect(() => scopeContainer(parent, './a')).toThrow();
|
|
76
|
-
expect(() => scopeContainer(parent, 'a\\b')).toThrow(/forward slashes/);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('rejects traversal, dot segments, and backslashes on every file operation', async () => {
|
|
80
|
-
const scoped = scopeContainer(parent, 'sidecar');
|
|
81
|
-
for (const badPath of ['../escape.txt', 'a/../../escape.txt', './same.txt', 'a\\b.txt']) {
|
|
82
|
-
expect(() => scoped.readFile(badPath)).toThrow();
|
|
83
|
-
expect(() => scoped.writeFile(badPath, enc('x'))).toThrow();
|
|
84
|
-
expect(() => scoped.removeFile(badPath)).toThrow();
|
|
85
|
-
expect(() => scoped.exists(badPath)).toThrow();
|
|
86
|
-
await expect(scoped.listFiles(badPath)).rejects.toThrow();
|
|
87
|
-
}
|
|
88
|
-
expect(await parent.listFiles()).toEqual([]);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('normalizes repeated and leading slashes without changing scope', async () => {
|
|
92
|
-
const scoped = scopeContainer(parent, '//sidecar//nested//');
|
|
93
|
-
expect(scoped.prefix).toBe('sidecar/nested');
|
|
94
|
-
await scoped.writeFile('//assets//x.txt', enc('x'));
|
|
95
|
-
expect(dec(await parent.readFile('sidecar/nested/assets/x.txt'))).toBe('x');
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('getDocumentPath / readDocument always return null', async () => {
|
|
99
|
-
const scoped = scopeContainer(parent, 'sidecar');
|
|
100
|
-
await scoped.writeFile('index.md', enc('# hi'));
|
|
101
|
-
expect(await scoped.getDocumentPath()).toBeNull();
|
|
102
|
-
expect(await scoped.readDocument()).toBeNull();
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('writeDocument throws', async () => {
|
|
106
|
-
const scoped = new ScopedContentContainer(parent, 'sidecar');
|
|
107
|
-
await expect(scoped.writeDocument()).rejects.toThrow();
|
|
108
|
-
});
|
|
109
|
-
});
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { SeededRandom, hashString } from '../random/index.js';
|
|
3
|
-
|
|
4
|
-
describe('SeededRandom', () => {
|
|
5
|
-
it('produces deterministic output from the same seed', () => {
|
|
6
|
-
const a = new SeededRandom(42);
|
|
7
|
-
const b = new SeededRandom(42);
|
|
8
|
-
expect(a.next()).toBe(b.next());
|
|
9
|
-
expect(a.next()).toBe(b.next());
|
|
10
|
-
expect(a.next()).toBe(b.next());
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('produces different output from different seeds', () => {
|
|
14
|
-
const a = new SeededRandom(1);
|
|
15
|
-
const b = new SeededRandom(2);
|
|
16
|
-
expect(a.next()).not.toBe(b.next());
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('next() returns values in [0, 1)', () => {
|
|
20
|
-
const rng = new SeededRandom(123);
|
|
21
|
-
for (let i = 0; i < 100; i++) {
|
|
22
|
-
const v = rng.next();
|
|
23
|
-
expect(v).toBeGreaterThanOrEqual(0);
|
|
24
|
-
expect(v).toBeLessThan(1);
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('nextInt(max) returns values in [0, max)', () => {
|
|
29
|
-
const rng = new SeededRandom(99);
|
|
30
|
-
for (let i = 0; i < 100; i++) {
|
|
31
|
-
const v = rng.nextInt(10);
|
|
32
|
-
expect(v).toBeGreaterThanOrEqual(0);
|
|
33
|
-
expect(v).toBeLessThan(10);
|
|
34
|
-
expect(Number.isInteger(v)).toBe(true);
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('nextIntRange(min, max) stays in range', () => {
|
|
39
|
-
const rng = new SeededRandom(77);
|
|
40
|
-
for (let i = 0; i < 100; i++) {
|
|
41
|
-
const v = rng.nextIntRange(5, 15);
|
|
42
|
-
expect(v).toBeGreaterThanOrEqual(5);
|
|
43
|
-
expect(v).toBeLessThan(15);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('pick returns undefined for empty array', () => {
|
|
48
|
-
const rng = new SeededRandom(1);
|
|
49
|
-
expect(rng.pick([])).toBeUndefined();
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('pick returns an element from the array', () => {
|
|
53
|
-
const rng = new SeededRandom(1);
|
|
54
|
-
const items = ['a', 'b', 'c'];
|
|
55
|
-
const picked = rng.pick(items);
|
|
56
|
-
expect(items).toContain(picked);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('pickRequired throws on empty array', () => {
|
|
60
|
-
const rng = new SeededRandom(1);
|
|
61
|
-
expect(() => rng.pickRequired([])).toThrow('Cannot pick from empty array');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('pickMultiple returns correct count', () => {
|
|
65
|
-
const rng = new SeededRandom(42);
|
|
66
|
-
const result = rng.pickMultiple([1, 2, 3, 4, 5], 3);
|
|
67
|
-
expect(result).toHaveLength(3);
|
|
68
|
-
// All elements should be unique
|
|
69
|
-
expect(new Set(result).size).toBe(3);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('pickMultiple returns all if count >= length', () => {
|
|
73
|
-
const rng = new SeededRandom(42);
|
|
74
|
-
const result = rng.pickMultiple([1, 2, 3], 5);
|
|
75
|
-
expect(result).toHaveLength(3);
|
|
76
|
-
expect(new Set(result).size).toBe(3);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('shuffle is deterministic', () => {
|
|
80
|
-
const a = new SeededRandom(42);
|
|
81
|
-
const b = new SeededRandom(42);
|
|
82
|
-
expect(a.shuffle([1, 2, 3, 4, 5])).toEqual(b.shuffle([1, 2, 3, 4, 5]));
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('shuffled does not modify original', () => {
|
|
86
|
-
const rng = new SeededRandom(42);
|
|
87
|
-
const original = [1, 2, 3, 4, 5];
|
|
88
|
-
const copy = [...original];
|
|
89
|
-
rng.shuffled(original);
|
|
90
|
-
expect(original).toEqual(copy);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('pickWeighted respects weights', () => {
|
|
94
|
-
// Heavily weight 'a' — over many picks it should dominate
|
|
95
|
-
const rng = new SeededRandom(42);
|
|
96
|
-
const items = [
|
|
97
|
-
{ item: 'a', weight: 100 },
|
|
98
|
-
{ item: 'b', weight: 1 },
|
|
99
|
-
];
|
|
100
|
-
let aCount = 0;
|
|
101
|
-
for (let i = 0; i < 100; i++) {
|
|
102
|
-
if (rng.pickWeighted(items) === 'a') aCount++;
|
|
103
|
-
}
|
|
104
|
-
expect(aCount).toBeGreaterThan(80);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('pickWeighted returns undefined for empty', () => {
|
|
108
|
-
const rng = new SeededRandom(1);
|
|
109
|
-
expect(rng.pickWeighted([])).toBeUndefined();
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it('derive creates independent stream', () => {
|
|
113
|
-
const rng = new SeededRandom(42);
|
|
114
|
-
const d1 = rng.derive('stream-a');
|
|
115
|
-
const d2 = rng.derive('stream-b');
|
|
116
|
-
expect(d1.next()).not.toBe(d2.next());
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('handles seed of 0 gracefully', () => {
|
|
120
|
-
const rng = new SeededRandom(0);
|
|
121
|
-
const v = rng.next();
|
|
122
|
-
expect(v).toBeGreaterThanOrEqual(0);
|
|
123
|
-
expect(v).toBeLessThan(1);
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
describe('hashString', () => {
|
|
128
|
-
it('returns a positive 32-bit integer', () => {
|
|
129
|
-
const h = hashString('hello world');
|
|
130
|
-
expect(h).toBeGreaterThanOrEqual(0);
|
|
131
|
-
expect(h).toBeLessThanOrEqual(0xffffffff);
|
|
132
|
-
expect(Number.isInteger(h)).toBe(true);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('is deterministic', () => {
|
|
136
|
-
expect(hashString('test')).toBe(hashString('test'));
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it('differs for different strings', () => {
|
|
140
|
-
expect(hashString('abc')).not.toBe(hashString('xyz'));
|
|
141
|
-
});
|
|
142
|
-
});
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
shapePath,
|
|
4
|
-
markerPath,
|
|
5
|
-
connectorPath,
|
|
6
|
-
clipEndpoints,
|
|
7
|
-
nearestSnapPoint,
|
|
8
|
-
lineStyleDasharray,
|
|
9
|
-
PATH_SHAPE_KINDS,
|
|
10
|
-
snapEndpoints,
|
|
11
|
-
snapPoints,
|
|
12
|
-
} from '../doc/utils/shapeGeometry.js';
|
|
13
|
-
|
|
14
|
-
describe('shapePath', () => {
|
|
15
|
-
it('returns a non-empty path beginning with M for every path-shape kind', () => {
|
|
16
|
-
for (const kind of PATH_SHAPE_KINDS) {
|
|
17
|
-
const d = shapePath(kind, 0, 0, 100, 80);
|
|
18
|
-
expect(d, kind).toBeTruthy();
|
|
19
|
-
expect(d?.startsWith('M'), kind).toBe(true);
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('returns null for natively-rendered primitives', () => {
|
|
24
|
-
for (const kind of ['rect', 'circle', 'line', 'text', 'path', 'arrow']) {
|
|
25
|
-
expect(shapePath(kind, 0, 0, 10, 10), kind).toBeNull();
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('triangle is a closed 3-point polygon inscribed in the box', () => {
|
|
30
|
-
expect(shapePath('triangle', 0, 0, 100, 100)).toBe('M 50 0 L 100 100 L 0 100 Z');
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('diamond hits the four edge midpoints', () => {
|
|
34
|
-
expect(shapePath('diamond', 0, 0, 100, 100)).toBe('M 50 0 L 100 50 L 50 100 L 0 50 Z');
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('honors the bounding-box offset', () => {
|
|
38
|
-
expect(shapePath('triangle', 10, 20, 100, 100)).toBe('M 60 20 L 110 120 L 10 120 Z');
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
describe('markerPath', () => {
|
|
43
|
-
it('arrow end is a filled triangle; none is null', () => {
|
|
44
|
-
expect(markerPath('arrow', 'end')).toEqual({ d: 'M 0 0 L 10 5 L 0 10 z', filled: true });
|
|
45
|
-
expect(markerPath('none', 'end')).toBeNull();
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('open is unfilled; diamond/circle/square are filled', () => {
|
|
49
|
-
expect(markerPath('open', 'end')?.filled).toBe(false);
|
|
50
|
-
expect(markerPath('diamond', 'end')?.filled).toBe(true);
|
|
51
|
-
expect(markerPath('circle', 'end')?.filled).toBe(true);
|
|
52
|
-
expect(markerPath('square', 'end')?.filled).toBe(true);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('start mirrors the arrow horizontally', () => {
|
|
56
|
-
expect(markerPath('arrow', 'start')).toEqual({ d: 'M 10 0 L 0 5 L 10 10 z', filled: true });
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
describe('connectorPath', () => {
|
|
61
|
-
const a = { x: 0, y: 0 };
|
|
62
|
-
const b = { x: 100, y: 50 };
|
|
63
|
-
|
|
64
|
-
it('straight is a single line segment', () => {
|
|
65
|
-
expect(connectorPath('straight', a, b)).toBe('M 0 0 L 100 50');
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('orthogonal has a mid elbow', () => {
|
|
69
|
-
expect(connectorPath('orthogonal', a, b)).toBe('M 0 0 L 50 0 L 50 50 L 100 50');
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('orthogonal routing approaches top/bottom ports vertically', () => {
|
|
73
|
-
expect(
|
|
74
|
-
connectorPath('orthogonal', { port: 'bottom', x: 80, y: 60 }, { port: 'top', x: 20, y: 140 }),
|
|
75
|
-
).toBe('M 80 60 L 80 100 L 20 100 L 20 140');
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('curved is a cubic bezier', () => {
|
|
79
|
-
expect(connectorPath('curved', a, b).startsWith('M 0 0 C')).toBe(true);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('curved routing follows the endpoint port directions', () => {
|
|
83
|
-
expect(
|
|
84
|
-
connectorPath('curved', { port: 'bottom', x: 80, y: 60 }, { port: 'top', x: 20, y: 140 }),
|
|
85
|
-
).toBe('M 80 60 C 80 110, 20 90, 20 140');
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
describe('clipEndpoints', () => {
|
|
90
|
-
it('clips both endpoints to the box edges', () => {
|
|
91
|
-
const r = clipEndpoints({ cx: 0, cy: 0, rx: 10, ry: 10 }, { cx: 100, cy: 0, rx: 10, ry: 10 });
|
|
92
|
-
expect(r.start).toEqual({ x: 10, y: 0 });
|
|
93
|
-
expect(r.end).toEqual({ x: 90, y: 0 });
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
describe('snapEndpoints', () => {
|
|
98
|
-
const a = { cx: 50, cy: 50, rx: 30, ry: 20 };
|
|
99
|
-
const b = { cx: 180, cy: 50, rx: 30, ry: 20 };
|
|
100
|
-
|
|
101
|
-
it('exposes side and corner ports around a box', () => {
|
|
102
|
-
expect(snapPoints(a).map((p) => p.port)).toEqual([
|
|
103
|
-
'top',
|
|
104
|
-
'right',
|
|
105
|
-
'bottom',
|
|
106
|
-
'left',
|
|
107
|
-
'top-left',
|
|
108
|
-
'top-right',
|
|
109
|
-
'bottom-right',
|
|
110
|
-
'bottom-left',
|
|
111
|
-
]);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('snaps horizontal connections to side ports', () => {
|
|
115
|
-
const r = snapEndpoints(a, b);
|
|
116
|
-
expect(r.start).toMatchObject({ port: 'right', x: 80, y: 50 });
|
|
117
|
-
expect(r.end).toMatchObject({ port: 'left', x: 150, y: 50 });
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('snaps diagonal connections to nearest corner ports', () => {
|
|
121
|
-
const r = snapEndpoints(a, { cx: 180, cy: 140, rx: 30, ry: 20 });
|
|
122
|
-
expect(r.start).toMatchObject({ port: 'bottom-right', x: 80, y: 70 });
|
|
123
|
-
expect(r.end).toMatchObject({ port: 'top-left', x: 150, y: 120 });
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('finds the nearest port toward a free pointer', () => {
|
|
127
|
-
expect(nearestSnapPoint(a, { x: 100, y: 10 }).port).toBe('top-right');
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
describe('lineStyleDasharray', () => {
|
|
132
|
-
it('maps line styles to dash patterns', () => {
|
|
133
|
-
expect(lineStyleDasharray('dashed')).toBe('8 6');
|
|
134
|
-
expect(lineStyleDasharray('dotted')).toBe('2 6');
|
|
135
|
-
expect(lineStyleDasharray('solid')).toBeUndefined();
|
|
136
|
-
expect(lineStyleDasharray(undefined)).toBeUndefined();
|
|
137
|
-
});
|
|
138
|
-
});
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { computeDrawingLayout } from '../doc/templates/drawingLayout.js';
|
|
3
|
-
import { drawingBlock } from '../doc/templates/drawingBlock.js';
|
|
4
|
-
import { diagramBlock } from '../doc/templates/diagramBlock.js';
|
|
5
|
-
import { createTemplateContext } from '../schemas/BlockTemplates.js';
|
|
6
|
-
import { DEFAULT_THEME } from '../schemas/themeLibrary.js';
|
|
7
|
-
import { VIEWPORT_PRESETS } from '../schemas/Viewport.js';
|
|
8
|
-
import type { Block, PathLayer } from '../schemas/Doc.js';
|
|
9
|
-
import type { DiagramBlockInput } from '../schemas/BlockTemplates.js';
|
|
10
|
-
|
|
11
|
-
function shape(id: string, template: string, overrides: Record<string, string> = {}): Block {
|
|
12
|
-
return {
|
|
13
|
-
id,
|
|
14
|
-
startTime: 0,
|
|
15
|
-
duration: 0,
|
|
16
|
-
audioSegment: 0,
|
|
17
|
-
template,
|
|
18
|
-
templateOverrides: overrides,
|
|
19
|
-
} as Block;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function ctx(children: Block[]) {
|
|
23
|
-
const c = createTemplateContext(DEFAULT_THEME, 0, 1, VIEWPORT_PRESETS.landscape);
|
|
24
|
-
c.children = children;
|
|
25
|
-
return c;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
describe('drawing shape vocabulary', () => {
|
|
29
|
-
it('recognizes new polygon kinds and aliases', () => {
|
|
30
|
-
const layout = computeDrawingLayout([
|
|
31
|
-
shape('s', 'star', { x: '0', y: '0' }),
|
|
32
|
-
shape('h', 'hexagon', { x: '0', y: '0' }),
|
|
33
|
-
shape('r', 'rhombus', { x: '0', y: '0' }), // alias → diamond
|
|
34
|
-
shape('a', 'rightarrow', { x: '0', y: '0' }), // alias → arrow-right
|
|
35
|
-
]);
|
|
36
|
-
const kinds = layout.shapes.map((s) => s.kind);
|
|
37
|
-
expect(kinds).toEqual(['star', 'hexagon', 'diamond', 'arrow-right']);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('renders a polygon kind as a PathLayer in the block', () => {
|
|
41
|
-
const layers = drawingBlock(
|
|
42
|
-
{ template: 'drawing', id: 'd', duration: 0, audioSegment: 0 },
|
|
43
|
-
ctx([shape('s', 'star', { x: '10', y: '10', width: '100', height: '100' })]),
|
|
44
|
-
);
|
|
45
|
-
const star = layers.find((l) => l.id === 'shape-s');
|
|
46
|
-
expect(star?.type).toBe('path');
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
describe('drawing connector semantics', () => {
|
|
51
|
-
function conn(overrides: Record<string, string>) {
|
|
52
|
-
return computeDrawingLayout([
|
|
53
|
-
shape('a', 'rect', { x: '0', y: '0', width: '50', height: '50' }),
|
|
54
|
-
shape('b', 'rect', { x: '0', y: '200', width: '50', height: '50' }),
|
|
55
|
-
shape('c', 'arrow', { from: 'a', to: 'b', ...overrides }),
|
|
56
|
-
]).connectors[0];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
it('parses end/start markers, line style, and routing', () => {
|
|
60
|
-
expect(
|
|
61
|
-
conn({
|
|
62
|
-
endStyle: 'diamond',
|
|
63
|
-
startStyle: 'circle',
|
|
64
|
-
lineStyle: 'dashed',
|
|
65
|
-
routing: 'orthogonal',
|
|
66
|
-
}),
|
|
67
|
-
).toMatchObject({
|
|
68
|
-
endMarker: 'diamond',
|
|
69
|
-
startMarker: 'circle',
|
|
70
|
-
dasharray: '8 6',
|
|
71
|
-
routing: 'orthogonal',
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('defaults arrow → end arrow, line → no marker, straight routing', () => {
|
|
76
|
-
expect(conn({})).toMatchObject({
|
|
77
|
-
endMarker: 'arrow',
|
|
78
|
-
startMarker: 'none',
|
|
79
|
-
routing: 'straight',
|
|
80
|
-
});
|
|
81
|
-
const line = computeDrawingLayout([
|
|
82
|
-
shape('a', 'rect', { x: '0', y: '0', width: '50', height: '50' }),
|
|
83
|
-
shape('b', 'rect', { x: '0', y: '200', width: '50', height: '50' }),
|
|
84
|
-
shape('l', 'line', { from: 'a', to: 'b' }),
|
|
85
|
-
]).connectors[0];
|
|
86
|
-
expect(line.endMarker).toBe('none');
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('emits the marker + dash on the rendered connector PathLayer', () => {
|
|
90
|
-
const layers = drawingBlock(
|
|
91
|
-
{ template: 'drawing', id: 'd', duration: 0, audioSegment: 0 },
|
|
92
|
-
ctx([
|
|
93
|
-
shape('a', 'rect', { x: '0', y: '0', width: '50', height: '50' }),
|
|
94
|
-
shape('b', 'rect', { x: '0', y: '200', width: '50', height: '50' }),
|
|
95
|
-
shape('c', 'arrow', { from: 'a', to: 'b', endStyle: 'diamond', lineStyle: 'dashed' }),
|
|
96
|
-
]),
|
|
97
|
-
);
|
|
98
|
-
const connector = layers.find((l) => l.id === 'connector-c') as PathLayer | undefined;
|
|
99
|
-
expect(connector?.content.endMarker).toBe('diamond');
|
|
100
|
-
expect(connector?.content.dasharray).toBe('8 6');
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
describe('diagram edge styles', () => {
|
|
105
|
-
function node(id: string, x: number, y: number, connectsTo?: string): Block {
|
|
106
|
-
return {
|
|
107
|
-
id,
|
|
108
|
-
startTime: 0,
|
|
109
|
-
duration: 0,
|
|
110
|
-
audioSegment: 0,
|
|
111
|
-
x,
|
|
112
|
-
y,
|
|
113
|
-
...(connectsTo ? { connectsTo: [{ target: connectsTo }] } : {}),
|
|
114
|
-
} as Block;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
it('applies endStyle and lineStyle to all edges', () => {
|
|
118
|
-
const c = createTemplateContext(DEFAULT_THEME, 0, 1, VIEWPORT_PRESETS.landscape);
|
|
119
|
-
c.children = [node('a', 0, 0, 'b'), node('b', 300, 0)];
|
|
120
|
-
const input: DiagramBlockInput = {
|
|
121
|
-
template: 'diagram',
|
|
122
|
-
id: 'g',
|
|
123
|
-
duration: 0,
|
|
124
|
-
audioSegment: 0,
|
|
125
|
-
endStyle: 'circle',
|
|
126
|
-
lineStyle: 'dashed',
|
|
127
|
-
};
|
|
128
|
-
const layers = diagramBlock(input, c);
|
|
129
|
-
const edge = layers.find((l) => l.id.startsWith('edge-')) as PathLayer | undefined;
|
|
130
|
-
expect(edge?.content.endMarker).toBe('circle');
|
|
131
|
-
expect(edge?.content.dasharray).toBe('8 6');
|
|
132
|
-
});
|
|
133
|
-
});
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
-
import { MemoryStorageAdapter } from '../storage/MemoryStorageAdapter';
|
|
3
|
-
|
|
4
|
-
describe('MemoryStorageAdapter', () => {
|
|
5
|
-
let storage: MemoryStorageAdapter;
|
|
6
|
-
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
storage = new MemoryStorageAdapter();
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('supports enumeration', () => {
|
|
12
|
-
expect(storage.supportsEnumeration).toBe(true);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('get returns null for missing key', async () => {
|
|
16
|
-
expect(await storage.get('nonexistent')).toBeNull();
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('set and get round-trip', async () => {
|
|
20
|
-
await storage.set('key', { hello: 'world' });
|
|
21
|
-
expect(await storage.get('key')).toEqual({ hello: 'world' });
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('stores primitives', async () => {
|
|
25
|
-
await storage.set('str', 'hello');
|
|
26
|
-
await storage.set('num', 42);
|
|
27
|
-
await storage.set('bool', true);
|
|
28
|
-
expect(await storage.get('str')).toBe('hello');
|
|
29
|
-
expect(await storage.get('num')).toBe(42);
|
|
30
|
-
expect(await storage.get('bool')).toBe(true);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('overwrites existing values', async () => {
|
|
34
|
-
await storage.set('key', 'first');
|
|
35
|
-
await storage.set('key', 'second');
|
|
36
|
-
expect(await storage.get('key')).toBe('second');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('remove deletes a key', async () => {
|
|
40
|
-
await storage.set('key', 'value');
|
|
41
|
-
await storage.remove('key');
|
|
42
|
-
expect(await storage.get('key')).toBeNull();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('clear removes all keys', async () => {
|
|
46
|
-
await storage.set('a', 1);
|
|
47
|
-
await storage.set('b', 2);
|
|
48
|
-
await storage.clear();
|
|
49
|
-
expect(await storage.get('a')).toBeNull();
|
|
50
|
-
expect(await storage.get('b')).toBeNull();
|
|
51
|
-
expect(await storage.keys()).toEqual([]);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('keys returns all stored keys', async () => {
|
|
55
|
-
await storage.set('alpha', 1);
|
|
56
|
-
await storage.set('beta', 2);
|
|
57
|
-
const keys = await storage.keys();
|
|
58
|
-
expect(keys.sort()).toEqual(['alpha', 'beta']);
|
|
59
|
-
});
|
|
60
|
-
});
|