@bendyline/squisq 2.1.0 → 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-DynJleo-.d.ts → Doc-BubIpWsp.d.ts} +1 -1
- package/dist/{ImageEditDoc-Ca4Tr9uN.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-VWCJ2WXC.js → chunk-2ZWIXGAC.js} +0 -1
- package/dist/{chunk-VYFRI7R6.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-JI77MGAK.js → chunk-7ARJZYQY.js} +159 -120
- 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-JHZWYRSW.js → chunk-C33GTPUZ.js} +11 -4
- package/dist/{chunk-QUUPYOSP.js → chunk-CB45YGAM.js} +2 -3
- package/dist/{chunk-XNLB57UD.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-OTKVFVL6.js → chunk-I2O6W7DX.js} +116 -44
- 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-ILWDXLUK.js → chunk-RS5AP3J4.js} +49 -10
- 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 +27 -12
- package/dist/doc/index.js +16 -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 +11 -11
- package/dist/index.js +60 -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-DDzubQXo.d.ts → materializePageSection-wSLA2A1g.d.ts} +2 -2
- 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 +5 -5
- package/dist/schemas/index.js +5 -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-B72m0W1y.d.ts → themeLibrary-DU9mUmVl.d.ts} +1 -1
- package/dist/timing/index.js +3 -4
- package/dist/transform/index.d.ts +3 -3
- 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-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-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-FVTQSNR7.js.map +0 -1
- package/dist/chunk-GZY66SDN.js.map +0 -1
- package/dist/chunk-ILWDXLUK.js.map +0 -1
- package/dist/chunk-JHZWYRSW.js.map +0 -1
- package/dist/chunk-JI77MGAK.js.map +0 -1
- package/dist/chunk-JOQYPRDZ.js.map +0 -1
- package/dist/chunk-OTKVFVL6.js.map +0 -1
- package/dist/chunk-PGGGKYWG.js +0 -1
- package/dist/chunk-PGGGKYWG.js.map +0 -1
- package/dist/chunk-Q7LROV2H.js.map +0 -1
- package/dist/chunk-QE7TWGVT.js.map +0 -1
- package/dist/chunk-QUUPYOSP.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-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-VWCJ2WXC.js.map +0 -1
- package/dist/chunk-VYFRI7R6.js.map +0 -1
- package/dist/chunk-XNLB57UD.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 -167
- package/src/__tests__/materializePageSections.test.ts +0 -404
- 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__/pageStyle.test.ts +0 -258
- 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 -173
- 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 -161
- package/src/doc/markdownToDoc.ts +0 -1054
- package/src/doc/materializeBlockLayers.ts +0 -465
- package/src/doc/mediaAnnotations.ts +0 -120
- package/src/doc/page/PageSection.ts +0 -174
- package/src/doc/page/materializePageSection.ts +0 -616
- package/src/doc/page/resolvePageBlock.ts +0 -108
- package/src/doc/page/sectionExtractors.ts +0 -466
- package/src/doc/pageCss.ts +0 -628
- 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 -424
- 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 -1073
- 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/PageStyle.ts +0 -213
- package/src/schemas/Theme.ts +0 -413
- 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 -31
- package/src/schemas/pageStyleDefaults.ts +0 -204
- package/src/schemas/themeCompile.ts +0 -244
- package/src/schemas/themeConstants.ts +0 -2
- package/src/schemas/themeLibrary.ts +0 -60
- package/src/schemas/themeValidator.ts +0 -609
- package/src/schemas/themes/bold.json +0 -77
- package/src/schemas/themes/cinematic.json +0 -143
- package/src/schemas/themes/documentary.json +0 -125
- package/src/schemas/themes/gezellig.json +0 -123
- package/src/schemas/themes/index.ts +0 -53
- package/src/schemas/themes/magazine.json +0 -126
- package/src/schemas/themes/minimalist.json +0 -74
- package/src/schemas/themes/morning-light.json +0 -117
- package/src/schemas/themes/standard-dark.json +0 -109
- package/src/schemas/themes/standard.json +0 -98
- package/src/schemas/themes/tech-dark.json +0 -143
- package/src/schemas/themes/warm-earth.json +0 -74
- 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 -217
- package/src/transform/styles/dataDriven.ts +0 -18
- package/src/transform/styles/documentary.ts +0 -18
- package/src/transform/styles/index.ts +0 -5
- package/src/transform/styles/magazine.ts +0 -19
- package/src/transform/styles/minimal.ts +0 -18
- package/src/transform/styles/narrative.ts +0 -19
- package/src/transform/templateSelector.ts +0 -389
- package/src/transform/timingAllocator.ts +0 -257
- package/src/transform/types.ts +0 -158
- 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,149 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
escapePointerSegment,
|
|
4
|
-
appendPointer,
|
|
5
|
-
toPointer,
|
|
6
|
-
pointerSegments,
|
|
7
|
-
getByPointer,
|
|
8
|
-
setByPointer,
|
|
9
|
-
resolveRef,
|
|
10
|
-
} from '../jsonForm/index.js';
|
|
11
|
-
|
|
12
|
-
describe('pointer composition', () => {
|
|
13
|
-
it('escapes arbitrary member names and appends them safely', () => {
|
|
14
|
-
expect(escapePointerSegment('a~/b')).toBe('a~0~1b');
|
|
15
|
-
expect(appendPointer('/properties', 'a~/b')).toBe('/properties/a~0~1b');
|
|
16
|
-
expect(appendPointer('', '')).toBe('/');
|
|
17
|
-
expect(appendPointer('/', 'child')).toBe('//child');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('validates an explicit base pointer before appending', () => {
|
|
21
|
-
expect(() => appendPointer('/bad~2base', 'child')).toThrow(/Invalid JSON Pointer/);
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
describe('toPointer', () => {
|
|
26
|
-
it('keeps pointer-form paths intact', () => {
|
|
27
|
-
expect(toPointer('/a/b')).toBe('/a/b');
|
|
28
|
-
expect(toPointer('/0/1')).toBe('/0/1');
|
|
29
|
-
});
|
|
30
|
-
it('converts dotted-form to pointer-form', () => {
|
|
31
|
-
expect(toPointer('user.role')).toBe('/user/role');
|
|
32
|
-
expect(toPointer('a')).toBe('/a');
|
|
33
|
-
});
|
|
34
|
-
it('returns empty for root', () => {
|
|
35
|
-
expect(toPointer('')).toBe('');
|
|
36
|
-
expect(toPointer('/')).toBe('/');
|
|
37
|
-
});
|
|
38
|
-
it('escapes ~ and / per RFC 6901', () => {
|
|
39
|
-
// dotted form does not allow / inside a segment; we test pointer-form decoding instead.
|
|
40
|
-
expect(pointerSegments('/a~1b')).toEqual(['a/b']);
|
|
41
|
-
expect(pointerSegments('/a~0b')).toEqual(['a~b']);
|
|
42
|
-
});
|
|
43
|
-
it('rejects malformed pointer syntax and escape sequences', () => {
|
|
44
|
-
expect(() => pointerSegments('not/a/pointer')).toThrow(/Invalid JSON Pointer/);
|
|
45
|
-
expect(() => pointerSegments('/bad~2escape')).toThrow(/Invalid JSON Pointer/);
|
|
46
|
-
expect(() => pointerSegments('/dangling~')).toThrow(/Invalid JSON Pointer/);
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
describe('getByPointer', () => {
|
|
51
|
-
const data = { user: { role: 'admin', tags: ['a', 'b'] } };
|
|
52
|
-
it('resolves nested object paths', () => {
|
|
53
|
-
expect(getByPointer(data, '/user/role')).toBe('admin');
|
|
54
|
-
expect(getByPointer(data, 'user.role')).toBe('admin');
|
|
55
|
-
});
|
|
56
|
-
it('resolves array indices', () => {
|
|
57
|
-
expect(getByPointer(data, '/user/tags/1')).toBe('b');
|
|
58
|
-
});
|
|
59
|
-
it('returns undefined for missing paths', () => {
|
|
60
|
-
expect(getByPointer(data, '/user/missing')).toBeUndefined();
|
|
61
|
-
expect(getByPointer(data, '/user/tags/9')).toBeUndefined();
|
|
62
|
-
});
|
|
63
|
-
it('returns the data itself for empty pointer', () => {
|
|
64
|
-
expect(getByPointer(data, '')).toBe(data);
|
|
65
|
-
});
|
|
66
|
-
it('treats "/" as the empty-string member per RFC 6901', () => {
|
|
67
|
-
expect(getByPointer({ '': 'empty key' }, '/')).toBe('empty key');
|
|
68
|
-
});
|
|
69
|
-
it('requires canonical array indices', () => {
|
|
70
|
-
expect(getByPointer({ values: ['a'] }, '/values/00')).toBeUndefined();
|
|
71
|
-
expect(getByPointer({ values: ['a'] }, '/values/-')).toBeUndefined();
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
describe('setByPointer', () => {
|
|
76
|
-
it('writes a leaf value immutably', () => {
|
|
77
|
-
const before = { a: 1, b: 2 };
|
|
78
|
-
const after = setByPointer(before, '/a', 99);
|
|
79
|
-
expect(after).toEqual({ a: 99, b: 2 });
|
|
80
|
-
expect(before).toEqual({ a: 1, b: 2 });
|
|
81
|
-
});
|
|
82
|
-
it('clones intermediate objects, shares siblings', () => {
|
|
83
|
-
const before = { x: { y: 1 }, z: { w: 2 } };
|
|
84
|
-
const after = setByPointer(before, '/x/y', 7);
|
|
85
|
-
expect(after).toEqual({ x: { y: 7 }, z: { w: 2 } });
|
|
86
|
-
expect(after.z).toBe(before.z);
|
|
87
|
-
expect(after.x).not.toBe(before.x);
|
|
88
|
-
});
|
|
89
|
-
it('writes into array indices', () => {
|
|
90
|
-
const before = { items: ['a', 'b', 'c'] };
|
|
91
|
-
const after = setByPointer(before, '/items/1', 'B');
|
|
92
|
-
expect(after.items).toEqual(['a', 'B', 'c']);
|
|
93
|
-
expect(after.items).not.toBe(before.items);
|
|
94
|
-
});
|
|
95
|
-
it('creates intermediate containers when missing', () => {
|
|
96
|
-
const after = setByPointer({}, '/a/b/0/c', 'leaf');
|
|
97
|
-
expect(after).toEqual({ a: { b: [{ c: 'leaf' }] } });
|
|
98
|
-
});
|
|
99
|
-
it('round-trips with getByPointer', () => {
|
|
100
|
-
const before = { a: { b: [{ c: 1 }, { c: 2 }] } };
|
|
101
|
-
const after = setByPointer(before, '/a/b/1/c', 42);
|
|
102
|
-
expect(getByPointer(after, '/a/b/1/c')).toBe(42);
|
|
103
|
-
expect(getByPointer(after, '/a/b/0/c')).toBe(1);
|
|
104
|
-
});
|
|
105
|
-
it('writes the empty-string member for "/"', () => {
|
|
106
|
-
expect(setByPointer({}, '/', 'value')).toEqual({ '': 'value' });
|
|
107
|
-
});
|
|
108
|
-
it('rejects non-canonical array indices instead of creating NaN properties', () => {
|
|
109
|
-
expect(() => setByPointer({ items: [] }, '/items/nope', 'x')).toThrow(/array index/i);
|
|
110
|
-
expect(() => setByPointer({ items: [] }, '/items/01', 'x')).toThrow(/array index/i);
|
|
111
|
-
});
|
|
112
|
-
it('writes prototype-shaped keys as safe own data properties', () => {
|
|
113
|
-
const before = {};
|
|
114
|
-
const after = setByPointer(before, '/__proto__/polluted', true) as Record<string, unknown>;
|
|
115
|
-
expect(Object.getPrototypeOf(after)).toBe(Object.prototype);
|
|
116
|
-
expect(Object.prototype).not.toHaveProperty('polluted');
|
|
117
|
-
expect(Object.prototype.hasOwnProperty.call(after, '__proto__')).toBe(true);
|
|
118
|
-
expect(getByPointer(after, '/__proto__/polluted')).toBe(true);
|
|
119
|
-
|
|
120
|
-
const constructorPath = setByPointer({}, '/constructor/prototype/polluted', true);
|
|
121
|
-
expect(getByPointer(constructorPath, '/constructor/prototype/polluted')).toBe(true);
|
|
122
|
-
expect(Object.prototype).not.toHaveProperty('polluted');
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
describe('resolveRef', () => {
|
|
127
|
-
const root = {
|
|
128
|
-
type: 'object',
|
|
129
|
-
properties: {
|
|
130
|
-
pet: { $ref: '#/$defs/Pet' },
|
|
131
|
-
},
|
|
132
|
-
$defs: {
|
|
133
|
-
Pet: { type: 'object', properties: { name: { type: 'string' } } },
|
|
134
|
-
},
|
|
135
|
-
};
|
|
136
|
-
it('returns referenced subschema for a local $ref', () => {
|
|
137
|
-
const ref = { $ref: '#/$defs/Pet' };
|
|
138
|
-
const resolved = resolveRef(ref, root);
|
|
139
|
-
expect(resolved?.type).toBe('object');
|
|
140
|
-
expect(resolved?.properties?.name?.type).toBe('string');
|
|
141
|
-
});
|
|
142
|
-
it('returns the schema unchanged when no $ref present', () => {
|
|
143
|
-
const node = { type: 'string' };
|
|
144
|
-
expect(resolveRef(node, root)).toBe(node);
|
|
145
|
-
});
|
|
146
|
-
it('returns undefined for unknown refs', () => {
|
|
147
|
-
expect(resolveRef({ $ref: '#/$defs/Nope' }, root)).toBeUndefined();
|
|
148
|
-
});
|
|
149
|
-
});
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { buildJsonFormTokens, resolveJsonFormTheme } from '../jsonForm/index.js';
|
|
3
|
-
import { DARK_SURFACE, LIGHT_SURFACE, DEFAULT_THEME, applySurface } from '../schemas/index.js';
|
|
4
|
-
|
|
5
|
-
const EXPECTED_SUFFIXES = [
|
|
6
|
-
'bg',
|
|
7
|
-
'text',
|
|
8
|
-
'muted',
|
|
9
|
-
'primary',
|
|
10
|
-
'accent',
|
|
11
|
-
'warning',
|
|
12
|
-
'border',
|
|
13
|
-
'input-bg',
|
|
14
|
-
'title-font',
|
|
15
|
-
'body-font',
|
|
16
|
-
'mono-font',
|
|
17
|
-
'radius',
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
describe('buildJsonFormTokens', () => {
|
|
21
|
-
it('emits the full token set for the viewer prefix', () => {
|
|
22
|
-
const tokens = buildJsonFormTokens(DEFAULT_THEME, LIGHT_SURFACE, { prefix: '--squisq-json' });
|
|
23
|
-
for (const suffix of EXPECTED_SUFFIXES) {
|
|
24
|
-
expect(tokens).toHaveProperty(`--squisq-json-${suffix}`);
|
|
25
|
-
}
|
|
26
|
-
expect(Object.keys(tokens)).toHaveLength(EXPECTED_SUFFIXES.length);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('emits the full token set for the editor prefix', () => {
|
|
30
|
-
const tokens = buildJsonFormTokens(DEFAULT_THEME, LIGHT_SURFACE, {
|
|
31
|
-
prefix: '--squisq-jsonform',
|
|
32
|
-
});
|
|
33
|
-
for (const suffix of EXPECTED_SUFFIXES) {
|
|
34
|
-
expect(tokens).toHaveProperty(`--squisq-jsonform-${suffix}`);
|
|
35
|
-
}
|
|
36
|
-
expect(Object.keys(tokens)).toHaveLength(EXPECTED_SUFFIXES.length);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('resolves colors from the applied surface (light vs dark differ)', () => {
|
|
40
|
-
const light = buildJsonFormTokens(DEFAULT_THEME, LIGHT_SURFACE, { prefix: '--squisq-json' });
|
|
41
|
-
const dark = buildJsonFormTokens(DEFAULT_THEME, DARK_SURFACE, { prefix: '--squisq-json' });
|
|
42
|
-
const lightTheme = applySurface(DEFAULT_THEME, LIGHT_SURFACE);
|
|
43
|
-
const darkTheme = applySurface(DEFAULT_THEME, DARK_SURFACE);
|
|
44
|
-
expect(light['--squisq-json-bg']).toBe(lightTheme.colors.background);
|
|
45
|
-
expect(dark['--squisq-json-bg']).toBe(darkTheme.colors.background);
|
|
46
|
-
// The two surfaces should not produce an identical background.
|
|
47
|
-
expect(light['--squisq-json-bg']).not.toBe(dark['--squisq-json-bg']);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('falls back to DEFAULT_THEME when theme is undefined', () => {
|
|
51
|
-
const tokens = buildJsonFormTokens(undefined, undefined, { prefix: '--squisq-json' });
|
|
52
|
-
expect(tokens['--squisq-json-bg']).toBe(DEFAULT_THEME.colors.background);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('does not apply surface when surface is undefined', () => {
|
|
56
|
-
const tokens = buildJsonFormTokens(DEFAULT_THEME, undefined, { prefix: '--squisq-json' });
|
|
57
|
-
expect(tokens['--squisq-json-bg']).toBe(DEFAULT_THEME.colors.background);
|
|
58
|
-
expect(tokens['--squisq-json-radius']).toBe(`${DEFAULT_THEME.style.borderRadius ?? 8}px`);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('is pure — no window/matchMedia access required', () => {
|
|
62
|
-
// Runs fine even if window is momentarily undefined-like; the function
|
|
63
|
-
// never touches globals.
|
|
64
|
-
expect(() =>
|
|
65
|
-
buildJsonFormTokens(DEFAULT_THEME, DARK_SURFACE, { prefix: '--squisq-json' }),
|
|
66
|
-
).not.toThrow();
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe('resolveJsonFormTheme', () => {
|
|
71
|
-
it('applies the surface to the theme', () => {
|
|
72
|
-
expect(resolveJsonFormTheme(DEFAULT_THEME, DARK_SURFACE)).toEqual(
|
|
73
|
-
applySurface(DEFAULT_THEME, DARK_SURFACE),
|
|
74
|
-
);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('returns the base theme untouched when surface is undefined', () => {
|
|
78
|
-
expect(resolveJsonFormTheme(DEFAULT_THEME, undefined)).toBe(DEFAULT_THEME);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('falls back to DEFAULT_THEME when theme is undefined', () => {
|
|
82
|
-
expect(resolveJsonFormTheme(undefined, undefined)).toBe(DEFAULT_THEME);
|
|
83
|
-
});
|
|
84
|
-
});
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { layoutBlock } from '../doc/templates/layoutBlock.js';
|
|
3
|
-
import { createTemplateContext } from '../schemas/BlockTemplates.js';
|
|
4
|
-
import { DEFAULT_THEME } from '../schemas/themeLibrary.js';
|
|
5
|
-
import { VIEWPORT_PRESETS } from '../schemas/Viewport.js';
|
|
6
|
-
import { isContainerTemplate } from '../doc/templates/index.js';
|
|
7
|
-
import { parseMarkdown } from '../markdown/parse.js';
|
|
8
|
-
import type { Block, Layer, TextLayer } from '../schemas/Doc.js';
|
|
9
|
-
import type { RawLayersInput } from '../schemas/BlockTemplates.js';
|
|
10
|
-
|
|
11
|
-
function child(
|
|
12
|
-
id: string,
|
|
13
|
-
template: string,
|
|
14
|
-
overrides: Record<string, string> = {},
|
|
15
|
-
bodyMd = '',
|
|
16
|
-
): Block {
|
|
17
|
-
return {
|
|
18
|
-
id,
|
|
19
|
-
startTime: 0,
|
|
20
|
-
duration: 0,
|
|
21
|
-
audioSegment: 0,
|
|
22
|
-
template,
|
|
23
|
-
templateOverrides: overrides,
|
|
24
|
-
...(bodyMd ? { contents: parseMarkdown(bodyMd).children } : {}),
|
|
25
|
-
} as Block;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function ctxWith(children: Block[]) {
|
|
29
|
-
const ctx = createTemplateContext(DEFAULT_THEME, 0, 1, VIEWPORT_PRESETS.landscape);
|
|
30
|
-
ctx.children = children;
|
|
31
|
-
return ctx;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const INPUT: RawLayersInput = { template: 'layout', id: 'lay', duration: 0, audioSegment: 0 };
|
|
35
|
-
|
|
36
|
-
describe('layoutBlock template', () => {
|
|
37
|
-
it('returns a single hint layer for an empty layout', () => {
|
|
38
|
-
const layers = layoutBlock(INPUT, ctxWith([]));
|
|
39
|
-
expect(layers).toHaveLength(1);
|
|
40
|
-
expect(layers[0].type).toBe('text');
|
|
41
|
-
expect((layers[0] as TextLayer).content.text).toBe('Empty layout');
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('emits one layer per child, in document order, at absolute positions', () => {
|
|
45
|
-
const layers = layoutBlock(
|
|
46
|
-
INPUT,
|
|
47
|
-
ctxWith([
|
|
48
|
-
child('box-1', 'rectangle', { x: '760', y: '390', width: '400', height: '300' }),
|
|
49
|
-
child('text-1', 'text', { x: '360', y: '380', width: '1200', height: '320' }, 'Welcome'),
|
|
50
|
-
]),
|
|
51
|
-
);
|
|
52
|
-
expect(layers.map((l) => l.id)).toEqual(['box-1', 'text-1']);
|
|
53
|
-
expect(layers[0].type).toBe('shape');
|
|
54
|
-
expect(layers[1].type).toBe('text');
|
|
55
|
-
expect((layers[1] as TextLayer).content.text).toBe('Welcome');
|
|
56
|
-
expect(layers[0].position).toMatchObject({ x: 760, y: 390 });
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
describe('layout container behavior', () => {
|
|
61
|
-
it('marks layout as a children-consuming container template', () => {
|
|
62
|
-
expect(isContainerTemplate('layout')).toBe(true);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('renders a layout block through the template registry', async () => {
|
|
66
|
-
const { materializeBlockLayers } = await import('../doc/materializeBlockLayers.js');
|
|
67
|
-
const parent: Block = {
|
|
68
|
-
id: 'lay',
|
|
69
|
-
startTime: 0,
|
|
70
|
-
duration: 0,
|
|
71
|
-
audioSegment: 0,
|
|
72
|
-
template: 'layout',
|
|
73
|
-
children: [
|
|
74
|
-
child('text-1', 'text', { x: '360', y: '380', width: '1200', height: '320' }, 'Title'),
|
|
75
|
-
child('box-1', 'rectangle', { x: '760', y: '390', width: '400', height: '300' }),
|
|
76
|
-
],
|
|
77
|
-
};
|
|
78
|
-
const layers = materializeBlockLayers(parent, { persistentLayers: false }).layers;
|
|
79
|
-
const types = new Set(layers.map((l: Layer) => l.type));
|
|
80
|
-
expect(types.has('text')).toBe(true);
|
|
81
|
-
expect(types.has('shape')).toBe(true);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { computeLayoutLayers } from '../doc/templates/layoutLayout.js';
|
|
3
|
-
import { parseMarkdown } from '../markdown/parse.js';
|
|
4
|
-
import type { ShapeLayer, TextLayer, ImageLayer, PathLayer } from '../schemas/Doc.js';
|
|
5
|
-
|
|
6
|
-
const VP = { width: 1920, height: 1080 };
|
|
7
|
-
|
|
8
|
-
function child(id: string, template: string, params: Record<string, string> = {}, bodyMd = '') {
|
|
9
|
-
return {
|
|
10
|
-
id,
|
|
11
|
-
template,
|
|
12
|
-
templateOverrides: params,
|
|
13
|
-
...(bodyMd ? { contents: parseMarkdown(bodyMd).children } : {}),
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
describe('computeLayoutLayers', () => {
|
|
18
|
-
it('maps a text child to an absolutely-positioned TextLayer (body text + style)', () => {
|
|
19
|
-
const { layers } = computeLayoutLayers(
|
|
20
|
-
[
|
|
21
|
-
child(
|
|
22
|
-
'text-1',
|
|
23
|
-
'text',
|
|
24
|
-
{
|
|
25
|
-
x: '100',
|
|
26
|
-
y: '200',
|
|
27
|
-
width: '600',
|
|
28
|
-
height: '120',
|
|
29
|
-
fontSize: '48',
|
|
30
|
-
align: 'center',
|
|
31
|
-
valign: 'middle',
|
|
32
|
-
color: '#1e293b',
|
|
33
|
-
},
|
|
34
|
-
'Hello **world**',
|
|
35
|
-
),
|
|
36
|
-
],
|
|
37
|
-
VP,
|
|
38
|
-
);
|
|
39
|
-
expect(layers).toHaveLength(1);
|
|
40
|
-
const t = layers[0] as TextLayer;
|
|
41
|
-
expect(t.type).toBe('text');
|
|
42
|
-
expect(t.id).toBe('text-1');
|
|
43
|
-
expect(t.position).toMatchObject({ x: 100, y: 200, width: 600, height: 120 });
|
|
44
|
-
expect(t.content.text).toBe('Hello world'); // plain projection of the body
|
|
45
|
-
expect(t.content.style.fontSize).toBe(48);
|
|
46
|
-
expect(t.content.style.textAlign).toBe('center');
|
|
47
|
-
expect(t.content.style.verticalAlign).toBe('middle');
|
|
48
|
-
expect(t.content.style.color).toBe('#1e293b');
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('maps rectangle/circle children to ShapeLayers', () => {
|
|
52
|
-
const { layers } = computeLayoutLayers(
|
|
53
|
-
[
|
|
54
|
-
child('box-1', 'rectangle', {
|
|
55
|
-
x: '10',
|
|
56
|
-
y: '10',
|
|
57
|
-
width: '200',
|
|
58
|
-
height: '100',
|
|
59
|
-
fill: '#e0e7ff',
|
|
60
|
-
stroke: '#6366f1',
|
|
61
|
-
strokeWidth: '2',
|
|
62
|
-
borderRadius: '8',
|
|
63
|
-
}),
|
|
64
|
-
child('c-1', 'circle', { x: '300', y: '10', width: '120', height: '120' }),
|
|
65
|
-
],
|
|
66
|
-
VP,
|
|
67
|
-
);
|
|
68
|
-
const shapes = layers.filter((l): l is ShapeLayer => l.type === 'shape');
|
|
69
|
-
expect(shapes.map((s) => s.content.shape)).toEqual(['rect', 'circle']);
|
|
70
|
-
expect(shapes[0].content.fill).toBe('#e0e7ff');
|
|
71
|
-
expect(shapes[0].content.borderRadius).toBe(8);
|
|
72
|
-
expect(shapes[0].position).toMatchObject({ x: 10, y: 10, width: 200, height: 100 });
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('maps an image child to an ImageLayer and skips one missing src', () => {
|
|
76
|
-
const { layers, warnings } = computeLayoutLayers(
|
|
77
|
-
[
|
|
78
|
-
child('img-1', 'image', {
|
|
79
|
-
x: '0',
|
|
80
|
-
y: '0',
|
|
81
|
-
width: '320',
|
|
82
|
-
height: '240',
|
|
83
|
-
src: 'pic.png',
|
|
84
|
-
alt: 'A pic',
|
|
85
|
-
fit: 'cover',
|
|
86
|
-
}),
|
|
87
|
-
child('img-2', 'image', { x: '0', y: '0' }),
|
|
88
|
-
],
|
|
89
|
-
VP,
|
|
90
|
-
);
|
|
91
|
-
const imgs = layers.filter((l): l is ImageLayer => l.type === 'image');
|
|
92
|
-
expect(imgs).toHaveLength(1);
|
|
93
|
-
expect(imgs[0].content.src).toBe('pic.png');
|
|
94
|
-
expect(imgs[0].content.alt).toBe('A pic');
|
|
95
|
-
expect(imgs[0].content.fit).toBe('cover');
|
|
96
|
-
expect(warnings.some((w) => w.includes('img-2'))).toBe(true);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it('maps a named polygon to a PathLayer via shapePath', () => {
|
|
100
|
-
const { layers } = computeLayoutLayers(
|
|
101
|
-
[child('star-1', 'star', { x: '0', y: '0', width: '100', height: '100' })],
|
|
102
|
-
VP,
|
|
103
|
-
);
|
|
104
|
-
const p = layers[0] as PathLayer;
|
|
105
|
-
expect(p.type).toBe('path');
|
|
106
|
-
expect(p.content.d.startsWith('M')).toBe(true);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('uses absolute positions (no fit-scaling) regardless of viewport', () => {
|
|
110
|
-
const children = [
|
|
111
|
-
child('text-1', 'text', { x: '100', y: '100', width: '200', height: '50' }, 'x'),
|
|
112
|
-
];
|
|
113
|
-
const small = computeLayoutLayers(children, { width: 200, height: 200 }).layers[0];
|
|
114
|
-
const large = computeLayoutLayers(children, { width: 4000, height: 4000 }).layers[0];
|
|
115
|
-
expect(small.position.x).toBe(100);
|
|
116
|
-
expect(large.position.x).toBe(100);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('preserves child document order as z-order', () => {
|
|
120
|
-
const { layers } = computeLayoutLayers(
|
|
121
|
-
[child('a', 'rectangle', { x: '0', y: '0' }), child('b', 'text', {}, 'top')],
|
|
122
|
-
VP,
|
|
123
|
-
);
|
|
124
|
-
expect(layers.map((l) => l.id)).toEqual(['a', 'b']);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('warns and skips a child whose annotation is not a layer kind', () => {
|
|
128
|
-
const { layers, warnings } = computeLayoutLayers(
|
|
129
|
-
[child('weird', 'banana', { x: '0', y: '0' })],
|
|
130
|
-
VP,
|
|
131
|
-
);
|
|
132
|
-
expect(layers).toHaveLength(0);
|
|
133
|
-
expect(warnings.some((w) => w.includes('weird'))).toBe(true);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('uses the supplied ink default for un-styled text and strokes', () => {
|
|
137
|
-
const { layers } = computeLayoutLayers(
|
|
138
|
-
[
|
|
139
|
-
child('t', 'text', { x: '0', y: '0' }, 'plain'),
|
|
140
|
-
child('l', 'line', { x: '0', y: '0', width: '100', height: '0' }),
|
|
141
|
-
],
|
|
142
|
-
VP,
|
|
143
|
-
{ ink: '#e0e0e0' },
|
|
144
|
-
);
|
|
145
|
-
const t = layers[0] as TextLayer;
|
|
146
|
-
const l = layers[1] as PathLayer;
|
|
147
|
-
expect(t.content.style.color).toBe('#e0e0e0');
|
|
148
|
-
expect(l.content.stroke).toBe('#e0e0e0');
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('keeps the dark-slate ink default when no defaults are supplied (editor scene canvas)', () => {
|
|
152
|
-
const { layers } = computeLayoutLayers([child('t', 'text', { x: '0', y: '0' }, 'plain')], VP);
|
|
153
|
-
const t = layers[0] as TextLayer;
|
|
154
|
-
expect(t.content.style.color).toBe('#1e293b');
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it('never overrides author-specified color/stroke with the ink default', () => {
|
|
158
|
-
const { layers } = computeLayoutLayers(
|
|
159
|
-
[
|
|
160
|
-
child('t', 'text', { x: '0', y: '0', color: '#112233' }, 'styled'),
|
|
161
|
-
child('l', 'line', { x: '0', y: '0', width: '100', height: '0', stroke: '#445566' }),
|
|
162
|
-
],
|
|
163
|
-
VP,
|
|
164
|
-
{ ink: '#e0e0e0' },
|
|
165
|
-
);
|
|
166
|
-
expect((layers[0] as TextLayer).content.style.color).toBe('#112233');
|
|
167
|
-
expect((layers[1] as PathLayer).content.stroke).toBe('#445566');
|
|
168
|
-
});
|
|
169
|
-
});
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LocalForageAdapter tests
|
|
3
|
-
*
|
|
4
|
-
* Uses the localforage library (which falls back to an in-memory driver
|
|
5
|
-
* in jsdom/Node environments) to verify the adapter contract.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
9
|
-
import { LocalForageAdapter } from '../storage/LocalForageAdapter';
|
|
10
|
-
|
|
11
|
-
describe('LocalForageAdapter', () => {
|
|
12
|
-
let storage: LocalForageAdapter;
|
|
13
|
-
|
|
14
|
-
beforeEach(async () => {
|
|
15
|
-
storage = new LocalForageAdapter({ name: 'test-db', storeName: 'test-store' });
|
|
16
|
-
await storage.clear();
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('supports enumeration', () => {
|
|
20
|
-
expect(storage.supportsEnumeration).toBe(true);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('get returns null for missing key', async () => {
|
|
24
|
-
expect(await storage.get('nonexistent')).toBeNull();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it('set and get round-trip', async () => {
|
|
28
|
-
await storage.set('key', { hello: 'world' });
|
|
29
|
-
expect(await storage.get('key')).toEqual({ hello: 'world' });
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('stores primitives', async () => {
|
|
33
|
-
await storage.set('str', 'hello');
|
|
34
|
-
await storage.set('num', 42);
|
|
35
|
-
await storage.set('bool', true);
|
|
36
|
-
expect(await storage.get('str')).toBe('hello');
|
|
37
|
-
expect(await storage.get('num')).toBe(42);
|
|
38
|
-
expect(await storage.get('bool')).toBe(true);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('overwrites existing values', async () => {
|
|
42
|
-
await storage.set('key', 'first');
|
|
43
|
-
await storage.set('key', 'second');
|
|
44
|
-
expect(await storage.get('key')).toBe('second');
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('remove deletes a key', async () => {
|
|
48
|
-
await storage.set('key', 'value');
|
|
49
|
-
await storage.remove('key');
|
|
50
|
-
expect(await storage.get('key')).toBeNull();
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('clear removes all keys', async () => {
|
|
54
|
-
await storage.set('a', 1);
|
|
55
|
-
await storage.set('b', 2);
|
|
56
|
-
await storage.clear();
|
|
57
|
-
expect(await storage.get('a')).toBeNull();
|
|
58
|
-
expect(await storage.get('b')).toBeNull();
|
|
59
|
-
expect(await storage.keys()).toEqual([]);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('keys returns all stored keys', async () => {
|
|
63
|
-
await storage.set('alpha', 1);
|
|
64
|
-
await storage.set('beta', 2);
|
|
65
|
-
const keys = await storage.keys();
|
|
66
|
-
expect(keys.sort()).toEqual(['alpha', 'beta']);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('stores binary data (ArrayBuffer)', async () => {
|
|
70
|
-
const buffer = new Uint8Array([1, 2, 3, 4]).buffer;
|
|
71
|
-
await storage.set('binary', buffer);
|
|
72
|
-
const result = await storage.get<ArrayBuffer>('binary');
|
|
73
|
-
expect(result).toBeInstanceOf(ArrayBuffer);
|
|
74
|
-
expect(new Uint8Array(result!)).toEqual(new Uint8Array([1, 2, 3, 4]));
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('stores Uint8Array', async () => {
|
|
78
|
-
const data = new Uint8Array([10, 20, 30]);
|
|
79
|
-
await storage.set('bytes', data);
|
|
80
|
-
const result = await storage.get<Uint8Array>('bytes');
|
|
81
|
-
expect(new Uint8Array(result!)).toEqual(new Uint8Array([10, 20, 30]));
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
describe('LocalForageAdapter with prefix', () => {
|
|
86
|
-
let storage: LocalForageAdapter;
|
|
87
|
-
|
|
88
|
-
beforeEach(async () => {
|
|
89
|
-
storage = new LocalForageAdapter({
|
|
90
|
-
name: 'test-db-prefix',
|
|
91
|
-
storeName: 'test-store',
|
|
92
|
-
prefix: 'slot1:',
|
|
93
|
-
});
|
|
94
|
-
await storage.clear();
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('get/set respects prefix', async () => {
|
|
98
|
-
await storage.set('doc', { title: 'My Doc' });
|
|
99
|
-
expect(await storage.get('doc')).toEqual({ title: 'My Doc' });
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('keys strips prefix', async () => {
|
|
103
|
-
await storage.set('alpha', 1);
|
|
104
|
-
await storage.set('beta', 2);
|
|
105
|
-
const keys = await storage.keys();
|
|
106
|
-
expect(keys.sort()).toEqual(['alpha', 'beta']);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('clear only removes prefixed keys', async () => {
|
|
110
|
-
// Write directly to a separate adapter (no prefix) to verify isolation
|
|
111
|
-
const other = new LocalForageAdapter({
|
|
112
|
-
name: 'test-db-prefix',
|
|
113
|
-
storeName: 'test-store',
|
|
114
|
-
prefix: 'slot2:',
|
|
115
|
-
});
|
|
116
|
-
await other.set('other-key', 'should-survive');
|
|
117
|
-
await storage.set('my-key', 'will-be-cleared');
|
|
118
|
-
|
|
119
|
-
await storage.clear();
|
|
120
|
-
|
|
121
|
-
expect(await storage.get('my-key')).toBeNull();
|
|
122
|
-
expect(await other.get('other-key')).toBe('should-survive');
|
|
123
|
-
|
|
124
|
-
// Cleanup
|
|
125
|
-
await other.clear();
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it('different prefixes are isolated', async () => {
|
|
129
|
-
const slot1 = new LocalForageAdapter({
|
|
130
|
-
name: 'test-isolation',
|
|
131
|
-
storeName: 'test-store',
|
|
132
|
-
prefix: 'slot1:',
|
|
133
|
-
});
|
|
134
|
-
const slot2 = new LocalForageAdapter({
|
|
135
|
-
name: 'test-isolation',
|
|
136
|
-
storeName: 'test-store',
|
|
137
|
-
prefix: 'slot2:',
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
await slot1.set('doc', 'slot1-doc');
|
|
141
|
-
await slot2.set('doc', 'slot2-doc');
|
|
142
|
-
|
|
143
|
-
expect(await slot1.get('doc')).toBe('slot1-doc');
|
|
144
|
-
expect(await slot2.get('doc')).toBe('slot2-doc');
|
|
145
|
-
|
|
146
|
-
const keys1 = await slot1.keys();
|
|
147
|
-
const keys2 = await slot2.keys();
|
|
148
|
-
expect(keys1).toEqual(['doc']);
|
|
149
|
-
expect(keys2).toEqual(['doc']);
|
|
150
|
-
|
|
151
|
-
// Cleanup
|
|
152
|
-
await slot1.clear();
|
|
153
|
-
await slot2.clear();
|
|
154
|
-
});
|
|
155
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import type { PathLayer } from '../schemas/Doc';
|
|
3
|
-
|
|
4
|
-
describe('major-version core API types', () => {
|
|
5
|
-
it('requires endpoint markers instead of the removed arrow field', () => {
|
|
6
|
-
const layer: PathLayer = {
|
|
7
|
-
id: 'path',
|
|
8
|
-
type: 'path',
|
|
9
|
-
position: { x: 0, y: 0, width: 10, height: 10 },
|
|
10
|
-
content: {
|
|
11
|
-
d: 'M 0 0 L 10 10',
|
|
12
|
-
// @ts-expect-error Old documents are read tolerantly, but new code uses endMarker.
|
|
13
|
-
arrow: 'end',
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
expect(layer.content).toHaveProperty('arrow', 'end');
|
|
17
|
-
});
|
|
18
|
-
});
|