@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
package/src/spatial/Geohash.ts
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Geohash Utilities
|
|
3
|
-
*
|
|
4
|
-
* Provides geohash encoding/decoding and spatial utilities using the standard
|
|
5
|
-
* ngeohash library for core operations, plus custom utilities for overlap checking
|
|
6
|
-
* and distance calculation.
|
|
7
|
-
*
|
|
8
|
-
* Geohashes are a hierarchical spatial indexing system that divides the world
|
|
9
|
-
* into a grid of cells. Each additional character narrows the area by ~1/32.
|
|
10
|
-
*
|
|
11
|
-
* Precision guide:
|
|
12
|
-
* - 4 chars: ~39km x 19km (used for tile indexing)
|
|
13
|
-
* - 5 chars: ~5km x 5km
|
|
14
|
-
* - 6 chars: ~1.2km x 0.6km
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import ngeohash from 'ngeohash';
|
|
18
|
-
import { haversineDistance } from './Haversine.js';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Encode latitude/longitude to a geohash string.
|
|
22
|
-
* Uses the standard ngeohash library.
|
|
23
|
-
*/
|
|
24
|
-
export function encodeGeohash(lat: number, lng: number, precision = 9): string {
|
|
25
|
-
return ngeohash.encode(lat, lng, precision);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Decode a geohash to latitude/longitude center with error bounds.
|
|
30
|
-
* Uses the standard ngeohash library.
|
|
31
|
-
*/
|
|
32
|
-
export function decodeGeohash(hash: string): {
|
|
33
|
-
lat: number;
|
|
34
|
-
lng: number;
|
|
35
|
-
latErr: number;
|
|
36
|
-
lngErr: number;
|
|
37
|
-
} {
|
|
38
|
-
const result = ngeohash.decode(hash);
|
|
39
|
-
return {
|
|
40
|
-
lat: result.latitude,
|
|
41
|
-
lng: result.longitude,
|
|
42
|
-
latErr: result.error.latitude,
|
|
43
|
-
lngErr: result.error.longitude,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Get the 8 neighboring geohash cells.
|
|
49
|
-
* Returns up to 8 neighbors (fewer at poles or antimeridian).
|
|
50
|
-
* Uses the standard ngeohash library.
|
|
51
|
-
*/
|
|
52
|
-
export function getNeighbors(hash: string): string[] {
|
|
53
|
-
return ngeohash.neighbors(hash);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Get a 3x3 grid of geohash4 cells (center + 8 neighbors).
|
|
58
|
-
* Used for landing bonus expansions in Fly mode.
|
|
59
|
-
*
|
|
60
|
-
* @param geohash4 - Center geohash4 cell
|
|
61
|
-
* @returns Array of 9 geohash4 cells (center first, then neighbors)
|
|
62
|
-
*
|
|
63
|
-
* @example
|
|
64
|
-
* getGeohash4Neighbors('c23n')
|
|
65
|
-
* // => ['c23n', 'c23p', 'c23q', 'c23j', 'c23m', 'c23k', 'c23h', 'c23e', 'c23s']
|
|
66
|
-
*/
|
|
67
|
-
export function getGeohash4Neighbors(geohash4: string): string[] {
|
|
68
|
-
if (geohash4.length !== 4) return [];
|
|
69
|
-
const neighbors = getNeighbors(geohash4);
|
|
70
|
-
return [geohash4, ...neighbors];
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Get the prefix of a geohash at a given precision.
|
|
75
|
-
* Simple helper for extracting geohash prefixes for directory organization.
|
|
76
|
-
*/
|
|
77
|
-
export function getGeohashPrefix(geohash: string, precision: number): string {
|
|
78
|
-
return geohash.slice(0, precision);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Convert a geohash prefix to a hierarchical path.
|
|
83
|
-
*
|
|
84
|
-
* Examples:
|
|
85
|
-
* "9mud" -> "9/m/u/d"
|
|
86
|
-
* "9q8y" -> "9/q/8/y"
|
|
87
|
-
* "c24k" -> "c/2/4/k"
|
|
88
|
-
*
|
|
89
|
-
* This is used for organizing files in hierarchical directories to avoid
|
|
90
|
-
* thousands of folders in a single directory, which causes filesystem
|
|
91
|
-
* performance issues.
|
|
92
|
-
*/
|
|
93
|
-
export function geohashToHierarchicalPath(geohash4: string): string {
|
|
94
|
-
if (geohash4.length !== 4) return '';
|
|
95
|
-
const [c1, c2, c3, c4] = geohash4.split('');
|
|
96
|
-
return `${c1}/${c2}/${c3}/${c4}`;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Compute all geohash cells along the great-circle path between two geohash cells.
|
|
101
|
-
* Samples points along the spherical arc from `from` to `to`, encoding each to a
|
|
102
|
-
* geohash at the given precision, and returns the deduplicated list of intermediate
|
|
103
|
-
* cells (excluding `from` and `to`).
|
|
104
|
-
*
|
|
105
|
-
* Uses spherical linear interpolation (SLERP) via 3D unit vectors, which correctly
|
|
106
|
-
* handles antimeridian crossings and polar paths — both of which flat lat/lng
|
|
107
|
-
* interpolation gets wrong.
|
|
108
|
-
*/
|
|
109
|
-
export function getGeohashPath(from: string, to: string, precision = 4): string[] {
|
|
110
|
-
if (from === to) return [];
|
|
111
|
-
|
|
112
|
-
const fromCenter = decodeGeohash(from);
|
|
113
|
-
const toCenter = decodeGeohash(to);
|
|
114
|
-
|
|
115
|
-
// Use haversine for accurate great-circle distance (step sizing)
|
|
116
|
-
const distKm = haversineDistance(
|
|
117
|
-
{ lat: fromCenter.lat, lng: fromCenter.lng },
|
|
118
|
-
{ lat: toCenter.lat, lng: toCenter.lng },
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
// Step every ~15km to avoid skipping any geohash4 cell (~39x19km)
|
|
122
|
-
const steps = Math.max(2, Math.ceil(distKm / 15));
|
|
123
|
-
|
|
124
|
-
// Convert endpoints to unit Cartesian vectors for SLERP
|
|
125
|
-
const φ1 = (fromCenter.lat * Math.PI) / 180;
|
|
126
|
-
const λ1 = (fromCenter.lng * Math.PI) / 180;
|
|
127
|
-
const φ2 = (toCenter.lat * Math.PI) / 180;
|
|
128
|
-
const λ2 = (toCenter.lng * Math.PI) / 180;
|
|
129
|
-
|
|
130
|
-
const x1 = Math.cos(φ1) * Math.cos(λ1);
|
|
131
|
-
const y1 = Math.cos(φ1) * Math.sin(λ1);
|
|
132
|
-
const z1 = Math.sin(φ1);
|
|
133
|
-
const x2 = Math.cos(φ2) * Math.cos(λ2);
|
|
134
|
-
const y2 = Math.cos(φ2) * Math.sin(λ2);
|
|
135
|
-
const z2 = Math.sin(φ2);
|
|
136
|
-
|
|
137
|
-
// Central angle between the two points
|
|
138
|
-
const dot = Math.max(-1, Math.min(1, x1 * x2 + y1 * y2 + z1 * z2));
|
|
139
|
-
const d = Math.acos(dot);
|
|
140
|
-
// Near-antipodal fallback: sin(d)≈0 means the great circle is undefined.
|
|
141
|
-
// Extremely unlikely for geohash path use; fall back to linear lat/lng.
|
|
142
|
-
const useLinear = Math.abs(Math.sin(d)) < 1e-10;
|
|
143
|
-
|
|
144
|
-
const seen = new Set<string>();
|
|
145
|
-
seen.add(from);
|
|
146
|
-
seen.add(to);
|
|
147
|
-
|
|
148
|
-
const path: string[] = [];
|
|
149
|
-
for (let i = 1; i < steps; i++) {
|
|
150
|
-
const t = i / steps;
|
|
151
|
-
let lat: number;
|
|
152
|
-
let lng: number;
|
|
153
|
-
if (useLinear) {
|
|
154
|
-
lat = fromCenter.lat + t * (toCenter.lat - fromCenter.lat);
|
|
155
|
-
lng = fromCenter.lng + t * (toCenter.lng - fromCenter.lng);
|
|
156
|
-
} else {
|
|
157
|
-
const A = Math.sin((1 - t) * d) / Math.sin(d);
|
|
158
|
-
const B = Math.sin(t * d) / Math.sin(d);
|
|
159
|
-
const x = A * x1 + B * x2;
|
|
160
|
-
const y = A * y1 + B * y2;
|
|
161
|
-
const z = A * z1 + B * z2;
|
|
162
|
-
lat = (Math.atan2(z, Math.sqrt(x * x + y * y)) * 180) / Math.PI;
|
|
163
|
-
lng = (Math.atan2(y, x) * 180) / Math.PI;
|
|
164
|
-
}
|
|
165
|
-
const hash = encodeGeohash(lat, lng, precision);
|
|
166
|
-
if (!seen.has(hash)) {
|
|
167
|
-
seen.add(hash);
|
|
168
|
-
path.push(hash);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return path;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Check if a geohash cell overlaps with a bounding box.
|
|
177
|
-
* Custom implementation (not available in ngeohash).
|
|
178
|
-
*/
|
|
179
|
-
export function geohashOverlapsBounds(
|
|
180
|
-
hash: string,
|
|
181
|
-
bounds: { north: number; south: number; east: number; west: number },
|
|
182
|
-
): boolean {
|
|
183
|
-
const { lat, lng, latErr, lngErr } = decodeGeohash(hash);
|
|
184
|
-
|
|
185
|
-
const hashNorth = lat + latErr;
|
|
186
|
-
const hashSouth = lat - latErr;
|
|
187
|
-
const hashEast = lng + lngErr;
|
|
188
|
-
const hashWest = lng - lngErr;
|
|
189
|
-
|
|
190
|
-
return !(
|
|
191
|
-
hashNorth < bounds.south ||
|
|
192
|
-
hashSouth > bounds.north ||
|
|
193
|
-
hashEast < bounds.west ||
|
|
194
|
-
hashWest > bounds.east
|
|
195
|
-
);
|
|
196
|
-
}
|
package/src/spatial/Haversine.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Haversine Distance Calculation
|
|
3
|
-
*
|
|
4
|
-
* Provides accurate distance calculation between two geographic coordinates
|
|
5
|
-
* using the Haversine formula, which accounts for Earth's curvature.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { Coordinates } from '../schemas/Types.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Calculate distance between two coordinates using Haversine formula.
|
|
12
|
-
*
|
|
13
|
-
* @param from Start coordinates
|
|
14
|
-
* @param to End coordinates
|
|
15
|
-
* @returns Distance in kilometers
|
|
16
|
-
*/
|
|
17
|
-
export function haversineDistance(from: Coordinates, to: Coordinates): number {
|
|
18
|
-
const R = 6371; // Earth's radius in kilometers
|
|
19
|
-
|
|
20
|
-
const dLat = toRadians(to.lat - from.lat);
|
|
21
|
-
const dLng = toRadians(to.lng - from.lng);
|
|
22
|
-
|
|
23
|
-
const a =
|
|
24
|
-
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
25
|
-
Math.cos(toRadians(from.lat)) *
|
|
26
|
-
Math.cos(toRadians(to.lat)) *
|
|
27
|
-
Math.sin(dLng / 2) *
|
|
28
|
-
Math.sin(dLng / 2);
|
|
29
|
-
|
|
30
|
-
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
31
|
-
|
|
32
|
-
return R * c;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Calculate bearing from one coordinate to another.
|
|
37
|
-
*
|
|
38
|
-
* @param from Start coordinates
|
|
39
|
-
* @param to End coordinates
|
|
40
|
-
* @returns Bearing in degrees (0-360, where 0 = north, 90 = east)
|
|
41
|
-
*/
|
|
42
|
-
export function calculateBearing(from: Coordinates, to: Coordinates): number {
|
|
43
|
-
const dLng = toRadians(to.lng - from.lng);
|
|
44
|
-
const lat1 = toRadians(from.lat);
|
|
45
|
-
const lat2 = toRadians(to.lat);
|
|
46
|
-
|
|
47
|
-
const x = Math.sin(dLng) * Math.cos(lat2);
|
|
48
|
-
const y = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLng);
|
|
49
|
-
|
|
50
|
-
const bearing = Math.atan2(x, y);
|
|
51
|
-
return ((bearing * 180) / Math.PI + 360) % 360;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Convert degrees to radians.
|
|
56
|
-
*/
|
|
57
|
-
function toRadians(degrees: number): number {
|
|
58
|
-
return (degrees * Math.PI) / 180;
|
|
59
|
-
}
|
package/src/spatial/index.ts
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ContentContainer — virtual file system for document containers.
|
|
3
|
-
*
|
|
4
|
-
* A Squisq document is more than just markdown: it's a container of files
|
|
5
|
-
* including the primary markdown document, images, audio, timing data, and
|
|
6
|
-
* other media. ContentContainer provides an abstract async file system
|
|
7
|
-
* interface for reading, writing, and listing these files.
|
|
8
|
-
*
|
|
9
|
-
* Paths are forward-slash separated strings relative to the container root
|
|
10
|
-
* (e.g., 'images/hero.jpg', 'index.md'). No leading slash.
|
|
11
|
-
*
|
|
12
|
-
* Implementations (in core):
|
|
13
|
-
* - MemoryContentContainer — in-memory Map (for zip import, tests, transient use)
|
|
14
|
-
* - ScopedContentContainer — a prefix-scoped view onto a parent container
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Metadata about a file in a ContentContainer.
|
|
19
|
-
*/
|
|
20
|
-
export interface ContentEntry {
|
|
21
|
-
/** Relative path within the container (e.g., 'images/hero.jpg') */
|
|
22
|
-
path: string;
|
|
23
|
-
/** MIME type (e.g., 'image/jpeg') */
|
|
24
|
-
mimeType: string;
|
|
25
|
-
/** File size in bytes */
|
|
26
|
-
size: number;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Abstract async file system for document containers.
|
|
31
|
-
*
|
|
32
|
-
* All paths are forward-slash separated, relative to the container root,
|
|
33
|
-
* with no leading slash. Example: 'images/hero.jpg', 'index.md'.
|
|
34
|
-
*/
|
|
35
|
-
export interface ContentContainer {
|
|
36
|
-
/** Read a file's binary content. Returns null if the file does not exist. */
|
|
37
|
-
readFile(path: string): Promise<ArrayBuffer | null>;
|
|
38
|
-
|
|
39
|
-
/** Write a file. Creates or overwrites. */
|
|
40
|
-
writeFile(path: string, data: ArrayBuffer | Uint8Array, mimeType?: string): Promise<void>;
|
|
41
|
-
|
|
42
|
-
/** Remove a file. No-op if the file does not exist. */
|
|
43
|
-
removeFile(path: string): Promise<void>;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* List files in the container.
|
|
47
|
-
*
|
|
48
|
-
* Returns file **entries** (`ContentEntry[]` with `.path`/`.mimeType`/`.size`),
|
|
49
|
-
* NOT bare path strings — despite the name. Read `entry.path` for the path;
|
|
50
|
-
* calling string methods (e.g. `.startsWith`) directly on an entry will throw.
|
|
51
|
-
* @param prefix — Optional path prefix to filter by (e.g., 'images/')
|
|
52
|
-
*/
|
|
53
|
-
listFiles(prefix?: string): Promise<ContentEntry[]>;
|
|
54
|
-
|
|
55
|
-
/** Check whether a file exists. */
|
|
56
|
-
exists(path: string): Promise<boolean>;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Find the primary markdown document path.
|
|
60
|
-
*
|
|
61
|
-
* Discovery order: index.md → doc.md → document.md → first *.md at root.
|
|
62
|
-
* Returns null if no markdown file is found at the root level.
|
|
63
|
-
*/
|
|
64
|
-
getDocumentPath(): Promise<string | null>;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Convenience: read the primary markdown document as a UTF-8 string.
|
|
68
|
-
* Returns null if no markdown file is found.
|
|
69
|
-
*/
|
|
70
|
-
readDocument(): Promise<string | null>;
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Convenience: write a markdown document.
|
|
74
|
-
* @param markdown — The markdown content
|
|
75
|
-
* @param filename — Filename to use (defaults to 'index.md')
|
|
76
|
-
*/
|
|
77
|
-
writeDocument(markdown: string, filename?: string): Promise<void>;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// ============================================
|
|
81
|
-
// Well-known markdown filenames in priority order
|
|
82
|
-
// ============================================
|
|
83
|
-
|
|
84
|
-
const MARKDOWN_PRIORITY = ['index.md', 'doc.md', 'document.md'];
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Find the primary markdown path from a list of file entries.
|
|
88
|
-
* Exported for reuse by other ContentContainer implementations.
|
|
89
|
-
*/
|
|
90
|
-
export function findDocumentPath(entries: ContentEntry[]): string | null {
|
|
91
|
-
// Only consider root-level files (no '/' in path)
|
|
92
|
-
const rootFiles = entries.filter((e) => !e.path.includes('/'));
|
|
93
|
-
|
|
94
|
-
for (const name of MARKDOWN_PRIORITY) {
|
|
95
|
-
const match = rootFiles.find((e) => e.path.toLowerCase() === name);
|
|
96
|
-
if (match) return match.path;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Fallback: first .md file at root
|
|
100
|
-
const firstMd = rootFiles.find((e) => e.path.toLowerCase().endsWith('.md'));
|
|
101
|
-
return firstMd?.path ?? null;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// ============================================
|
|
105
|
-
// MemoryContentContainer
|
|
106
|
-
// ============================================
|
|
107
|
-
|
|
108
|
-
interface MemoryFile {
|
|
109
|
-
data: ArrayBuffer;
|
|
110
|
-
mimeType: string;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* In-memory ContentContainer backed by a Map.
|
|
115
|
-
*
|
|
116
|
-
* Used for zip import (deserialize into memory), tests, and transient operations.
|
|
117
|
-
*/
|
|
118
|
-
export class MemoryContentContainer implements ContentContainer {
|
|
119
|
-
private files = new Map<string, MemoryFile>();
|
|
120
|
-
|
|
121
|
-
async readFile(path: string): Promise<ArrayBuffer | null> {
|
|
122
|
-
const stored = this.files.get(path)?.data;
|
|
123
|
-
// A container owns its bytes. Returning the backing buffer would let a
|
|
124
|
-
// caller mutate stored state without going through writeFile().
|
|
125
|
-
return stored ? stored.slice(0) : null;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async writeFile(path: string, data: ArrayBuffer | Uint8Array, mimeType?: string): Promise<void> {
|
|
129
|
-
// Copy to a standalone ArrayBuffer. Uint8Array/Buffer may share a larger
|
|
130
|
-
// backing buffer (e.g., Node's buffer pool), so we must slice to the
|
|
131
|
-
// exact byte range to avoid storing stale pool data.
|
|
132
|
-
// ArrayBuffer.isView is cross-realm-safe (unlike `instanceof
|
|
133
|
-
// ArrayBuffer`, which fails for values created in jsdom/iframes).
|
|
134
|
-
let source: Uint8Array;
|
|
135
|
-
if (ArrayBuffer.isView(data)) {
|
|
136
|
-
source = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
137
|
-
} else {
|
|
138
|
-
source = new Uint8Array(data);
|
|
139
|
-
}
|
|
140
|
-
// Always materialize in this realm, including for iframe ArrayBuffers and
|
|
141
|
-
// views backed by SharedArrayBuffer.
|
|
142
|
-
const owned = new Uint8Array(source.byteLength);
|
|
143
|
-
owned.set(source);
|
|
144
|
-
this.files.set(path, {
|
|
145
|
-
data: owned.buffer,
|
|
146
|
-
mimeType: mimeType ?? guessMimeType(path),
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
async removeFile(path: string): Promise<void> {
|
|
151
|
-
this.files.delete(path);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
async listFiles(prefix?: string): Promise<ContentEntry[]> {
|
|
155
|
-
const entries: ContentEntry[] = [];
|
|
156
|
-
for (const [path, file] of this.files) {
|
|
157
|
-
if (prefix && !path.startsWith(prefix)) continue;
|
|
158
|
-
entries.push({
|
|
159
|
-
path,
|
|
160
|
-
mimeType: file.mimeType,
|
|
161
|
-
size: file.data.byteLength,
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
return entries;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async exists(path: string): Promise<boolean> {
|
|
168
|
-
return this.files.has(path);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async getDocumentPath(): Promise<string | null> {
|
|
172
|
-
return findDocumentPath(await this.listFiles());
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
async readDocument(): Promise<string | null> {
|
|
176
|
-
const docPath = await this.getDocumentPath();
|
|
177
|
-
if (!docPath) return null;
|
|
178
|
-
const data = await this.readFile(docPath);
|
|
179
|
-
if (!data) return null;
|
|
180
|
-
return new TextDecoder().decode(data);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async writeDocument(markdown: string, filename?: string): Promise<void> {
|
|
184
|
-
const name = filename ?? 'index.md';
|
|
185
|
-
const data = new TextEncoder().encode(markdown);
|
|
186
|
-
await this.writeFile(name, data, 'text/markdown');
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// ============================================
|
|
191
|
-
// MIME type guessing
|
|
192
|
-
// ============================================
|
|
193
|
-
|
|
194
|
-
const EXTENSION_MIME_MAP: Record<string, string> = {
|
|
195
|
-
'.md': 'text/markdown',
|
|
196
|
-
'.txt': 'text/plain',
|
|
197
|
-
'.json': 'application/json',
|
|
198
|
-
'.jpg': 'image/jpeg',
|
|
199
|
-
'.jpeg': 'image/jpeg',
|
|
200
|
-
'.png': 'image/png',
|
|
201
|
-
'.gif': 'image/gif',
|
|
202
|
-
'.svg': 'image/svg+xml',
|
|
203
|
-
'.webp': 'image/webp',
|
|
204
|
-
'.avif': 'image/avif',
|
|
205
|
-
'.mp4': 'video/mp4',
|
|
206
|
-
'.webm': 'video/webm',
|
|
207
|
-
'.mp3': 'audio/mpeg',
|
|
208
|
-
'.wav': 'audio/wav',
|
|
209
|
-
'.ogg': 'audio/ogg',
|
|
210
|
-
'.css': 'text/css',
|
|
211
|
-
'.html': 'text/html',
|
|
212
|
-
'.js': 'application/javascript',
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
function guessMimeType(path: string): string {
|
|
216
|
-
const dot = path.lastIndexOf('.');
|
|
217
|
-
if (dot === -1) return 'application/octet-stream';
|
|
218
|
-
const ext = path.slice(dot).toLowerCase();
|
|
219
|
-
return EXTENSION_MIME_MAP[ext] ?? 'application/octet-stream';
|
|
220
|
-
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LocalForage adapter - IndexedDB storage with automatic fallbacks.
|
|
3
|
-
*
|
|
4
|
-
* Uses localforage which provides IndexedDB storage with automatic
|
|
5
|
-
* fallbacks to WebSQL and localStorage. This allows storing much more
|
|
6
|
-
* data than raw localStorage (which is limited to ~5MB).
|
|
7
|
-
*
|
|
8
|
-
* Unlike LocalStorageAdapter, this adapter can store binary data
|
|
9
|
-
* (ArrayBuffer, Blob, Uint8Array) natively without JSON serialization.
|
|
10
|
-
*
|
|
11
|
-
* Ported from qualla-internal/shared/services/StorageAdapters.ts with
|
|
12
|
-
* configurable store name and key prefix.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import localforage from 'localforage';
|
|
16
|
-
import type { StorageAdapter } from './Storage.js';
|
|
17
|
-
|
|
18
|
-
export interface LocalForageAdapterOptions {
|
|
19
|
-
/** IndexedDB database name (default: 'squisq') */
|
|
20
|
-
name?: string;
|
|
21
|
-
/** IndexedDB object store name (default: 'data') */
|
|
22
|
-
storeName?: string;
|
|
23
|
-
/** Key prefix for namespacing (default: '') */
|
|
24
|
-
prefix?: string;
|
|
25
|
-
/** Human-readable description (default: 'Squisq storage') */
|
|
26
|
-
description?: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export class LocalForageAdapter implements StorageAdapter {
|
|
30
|
-
readonly supportsEnumeration = true;
|
|
31
|
-
private store: LocalForage;
|
|
32
|
-
private prefix: string;
|
|
33
|
-
|
|
34
|
-
constructor(options: LocalForageAdapterOptions = {}) {
|
|
35
|
-
const {
|
|
36
|
-
name = 'squisq',
|
|
37
|
-
storeName = 'data',
|
|
38
|
-
prefix = '',
|
|
39
|
-
description = 'Squisq storage',
|
|
40
|
-
} = options;
|
|
41
|
-
|
|
42
|
-
this.prefix = prefix;
|
|
43
|
-
this.store = localforage.createInstance({ name, storeName, description });
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async get<T>(key: string): Promise<T | null> {
|
|
47
|
-
try {
|
|
48
|
-
const value = await this.store.getItem<T>(this.prefix + key);
|
|
49
|
-
return value;
|
|
50
|
-
} catch (e: unknown) {
|
|
51
|
-
console.warn('[Storage] get (IndexedDB) failed:', key, e);
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async set<T>(key: string, value: T): Promise<void> {
|
|
57
|
-
try {
|
|
58
|
-
await this.store.setItem(this.prefix + key, value);
|
|
59
|
-
} catch (e: unknown) {
|
|
60
|
-
console.error('[Storage] set (IndexedDB) failed:', key, e);
|
|
61
|
-
throw e;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async remove(key: string): Promise<void> {
|
|
66
|
-
try {
|
|
67
|
-
await this.store.removeItem(this.prefix + key);
|
|
68
|
-
} catch (e: unknown) {
|
|
69
|
-
console.warn('[Storage] remove (IndexedDB) failed:', key, e);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async clear(): Promise<void> {
|
|
74
|
-
try {
|
|
75
|
-
if (this.prefix) {
|
|
76
|
-
// Only remove keys with our prefix
|
|
77
|
-
const keys = await this.store.keys();
|
|
78
|
-
const keysToRemove = keys.filter((k) => k.startsWith(this.prefix));
|
|
79
|
-
await Promise.all(keysToRemove.map((k) => this.store.removeItem(k)));
|
|
80
|
-
} else {
|
|
81
|
-
// No prefix — clear the entire store
|
|
82
|
-
await this.store.clear();
|
|
83
|
-
}
|
|
84
|
-
} catch (e: unknown) {
|
|
85
|
-
console.error('[Storage] clear (IndexedDB) failed:', e);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async keys(): Promise<string[]> {
|
|
90
|
-
try {
|
|
91
|
-
const allKeys = await this.store.keys();
|
|
92
|
-
if (this.prefix) {
|
|
93
|
-
return allKeys
|
|
94
|
-
.filter((k) => k.startsWith(this.prefix))
|
|
95
|
-
.map((k) => k.slice(this.prefix.length));
|
|
96
|
-
}
|
|
97
|
-
return allKeys;
|
|
98
|
-
} catch (e: unknown) {
|
|
99
|
-
console.warn('[Storage] keys (IndexedDB) failed:', e);
|
|
100
|
-
return [];
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* localStorage adapter for web browsers.
|
|
3
|
-
* Supports a configurable key prefix to namespace stored data.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { StorageAdapter } from './Storage.js';
|
|
7
|
-
|
|
8
|
-
export class LocalStorageAdapter implements StorageAdapter {
|
|
9
|
-
readonly supportsEnumeration = true;
|
|
10
|
-
private prefix: string;
|
|
11
|
-
|
|
12
|
-
constructor(prefix = '') {
|
|
13
|
-
this.prefix = prefix;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async get<T>(key: string): Promise<T | null> {
|
|
17
|
-
try {
|
|
18
|
-
const raw = localStorage.getItem(this.prefix + key);
|
|
19
|
-
if (raw === null) return null;
|
|
20
|
-
return JSON.parse(raw) as T;
|
|
21
|
-
} catch {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async set<T>(key: string, value: T): Promise<void> {
|
|
27
|
-
localStorage.setItem(this.prefix + key, JSON.stringify(value));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async remove(key: string): Promise<void> {
|
|
31
|
-
localStorage.removeItem(this.prefix + key);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async clear(): Promise<void> {
|
|
35
|
-
const keysToRemove: string[] = [];
|
|
36
|
-
for (let i = 0; i < localStorage.length; i++) {
|
|
37
|
-
const k = localStorage.key(i);
|
|
38
|
-
if (k && k.startsWith(this.prefix)) {
|
|
39
|
-
keysToRemove.push(k);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
for (const k of keysToRemove) {
|
|
43
|
-
localStorage.removeItem(k);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async keys(): Promise<string[]> {
|
|
48
|
-
const result: string[] = [];
|
|
49
|
-
for (let i = 0; i < localStorage.length; i++) {
|
|
50
|
-
const k = localStorage.key(i);
|
|
51
|
-
if (k && k.startsWith(this.prefix)) {
|
|
52
|
-
result.push(k.slice(this.prefix.length));
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return result;
|
|
56
|
-
}
|
|
57
|
-
}
|