@bendyline/squisq 1.3.0 → 1.4.1
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/dist/{Doc-Ch4tc3vv.d.ts → Doc-BeSeH2iX.d.ts} +118 -41
- package/dist/ImageEditDoc-BTIvw0oq.d.ts +84 -0
- package/dist/{chunk-CYQHG27J.js → chunk-2TMAWB4Y.js} +74 -1
- package/dist/chunk-2TMAWB4Y.js.map +1 -0
- package/dist/{chunk-OASJKWO5.js → chunk-3K5OG6KI.js} +92 -7
- package/dist/chunk-3K5OG6KI.js.map +1 -0
- package/dist/chunk-57CVQCFX.js +193 -0
- package/dist/chunk-57CVQCFX.js.map +1 -0
- package/dist/{chunk-QM5PKNPW.js → chunk-5WFRKURX.js} +1 -1
- package/dist/chunk-5WFRKURX.js.map +1 -0
- package/dist/chunk-B4EEON3N.js +1317 -0
- package/dist/chunk-B4EEON3N.js.map +1 -0
- package/dist/chunk-DBS6RIFL.js +81 -0
- package/dist/chunk-DBS6RIFL.js.map +1 -0
- package/dist/{chunk-MIBRIRGJ.js → chunk-FR2RBTKO.js} +3 -3
- package/dist/{chunk-MIBRIRGJ.js.map → chunk-FR2RBTKO.js.map} +1 -1
- package/dist/chunk-H3AXU4MJ.js +179 -0
- package/dist/chunk-H3AXU4MJ.js.map +1 -0
- package/dist/chunk-JELIRVDP.js +24 -0
- package/dist/chunk-JELIRVDP.js.map +1 -0
- package/dist/chunk-K32VJONL.js +193 -0
- package/dist/chunk-K32VJONL.js.map +1 -0
- package/dist/{chunk-6BAVXFYC.js → chunk-KSWJR66U.js} +218 -42
- package/dist/chunk-KSWJR66U.js.map +1 -0
- package/dist/{chunk-TSG2OSE6.js → chunk-MYIH7FWD.js} +3 -3
- package/dist/chunk-MYIH7FWD.js.map +1 -0
- package/dist/chunk-VLJJHDAC.js +218 -0
- package/dist/chunk-VLJJHDAC.js.map +1 -0
- package/dist/chunk-WMOI7FN3.js +182 -0
- package/dist/chunk-WMOI7FN3.js.map +1 -0
- package/dist/chunk-ZTX4PFFT.js +520 -0
- package/dist/chunk-ZTX4PFFT.js.map +1 -0
- package/dist/doc/index.d.ts +5 -10
- package/dist/doc/index.js +145 -7
- package/dist/doc/index.js.map +1 -1
- package/dist/generate/index.d.ts +99 -7
- package/dist/generate/index.js +16 -3
- package/dist/generate/index.js.map +1 -1
- package/dist/icons/index.d.ts +87 -0
- package/dist/icons/index.js +17 -0
- package/dist/icons/index.js.map +1 -0
- package/dist/imageEdit/index.d.ts +216 -0
- package/dist/imageEdit/index.js +54 -0
- package/dist/imageEdit/index.js.map +1 -0
- package/dist/index.d.ts +21 -9
- package/dist/index.js +461 -8
- package/dist/index.js.map +1 -1
- package/dist/jsonForm/index.d.ts +191 -0
- package/dist/jsonForm/index.js +27 -0
- package/dist/jsonForm/index.js.map +1 -0
- package/dist/markdown/index.d.ts +265 -19
- package/dist/markdown/index.js +39 -33
- package/dist/markdown/index.js.map +1 -1
- package/dist/random/index.d.ts +51 -2
- package/dist/random/index.js +9 -1
- package/dist/random/index.js.map +1 -1
- package/dist/recommend/index.d.ts +42 -0
- package/dist/recommend/index.js +10 -0
- package/dist/recommend/index.js.map +1 -0
- package/dist/schemas/index.d.ts +188 -10
- package/dist/schemas/index.js +120 -7
- package/dist/schemas/index.js.map +1 -1
- package/dist/spatial/index.d.ts +111 -3
- package/dist/spatial/index.js +24 -2
- package/dist/spatial/index.js.map +1 -1
- package/dist/storage/index.d.ts +159 -9
- package/dist/storage/index.js +20 -5
- package/dist/storage/index.js.map +1 -1
- package/dist/story/index.d.ts +53 -13
- package/dist/story/index.js +12 -4
- package/dist/themeLibrary-BHjJ0Qx6.d.ts +40 -0
- package/dist/timing/index.d.ts +109 -4
- package/dist/timing/index.js +23 -2
- package/dist/timing/index.js.map +1 -1
- package/dist/transform/index.d.ts +175 -6
- package/dist/transform/index.js +490 -3
- package/dist/transform/index.js.map +1 -1
- package/dist/{types-CkNttVSF.d.ts → types-BdZkdJ3z.d.ts} +17 -2
- package/dist/types-D98li1gV.d.ts +93 -0
- package/dist/versions/index.d.ts +128 -0
- package/dist/versions/index.js +35 -0
- package/dist/versions/index.js.map +1 -0
- package/package.json +28 -1
- package/src/__tests__/colorUtils.test.ts +112 -0
- package/src/__tests__/getLayers.test.ts +32 -7
- package/src/__tests__/iconResolve.test.ts +122 -0
- package/src/__tests__/imageEditState.test.ts +74 -0
- package/src/__tests__/imageEditVersions.test.ts +169 -0
- package/src/__tests__/inferDocumentTitle.test.ts +50 -0
- package/src/__tests__/jsonForm.chooseControl.test.ts +86 -0
- package/src/__tests__/jsonForm.evaluateWhen.test.ts +59 -0
- package/src/__tests__/jsonForm.inferSchema.test.ts +25 -0
- package/src/__tests__/jsonForm.pointer.test.ts +103 -0
- package/src/__tests__/markdownIcons.test.ts +104 -0
- package/src/__tests__/markdownToDoc.test.ts +19 -4
- package/src/__tests__/recommendTemplates.test.ts +183 -0
- package/src/__tests__/scopedContentContainer.test.ts +89 -0
- package/src/__tests__/slideshowGenerator.test.ts +1 -1
- package/src/__tests__/templateAnnotationParse.test.ts +42 -0
- package/src/__tests__/templates.test.ts +93 -9
- package/src/__tests__/themeCompile.test.ts +156 -0
- package/src/__tests__/themeValidator.test.ts +125 -0
- package/src/__tests__/versions.test.ts +415 -0
- package/src/doc/audioMapping.ts +55 -11
- package/src/doc/getLayers.ts +32 -21
- package/src/doc/markdownToDoc.ts +45 -7
- package/src/doc/templates/featureBlock.ts +202 -0
- package/src/doc/templates/fullBleedQuote.ts +13 -0
- package/src/doc/templates/index.ts +50 -16
- package/src/doc/templates/listBlock.ts +24 -5
- package/src/doc/templates/statHighlight.ts +13 -0
- package/src/doc/templates/titleBlock.ts +9 -0
- package/src/doc/utils/themeUtils.ts +8 -7
- package/src/generate/slideshowGenerator.ts +1 -1
- package/src/generate/templateMapper.ts +2 -2
- package/src/icons/iconData.ts +31 -0
- package/src/icons/index.ts +18 -0
- package/src/icons/resolve.ts +139 -0
- package/src/imageEdit/ImageEditVersionManager.ts +73 -0
- package/src/imageEdit/export.ts +326 -0
- package/src/imageEdit/index.ts +71 -0
- package/src/imageEdit/persistence.ts +62 -0
- package/src/imageEdit/state.ts +112 -0
- package/src/imageEdit/versionPaths.ts +57 -0
- package/src/imageEdit/versions.ts +231 -0
- package/src/index.ts +4 -0
- package/src/jsonForm/chooseControl.ts +88 -0
- package/src/jsonForm/evaluateWhen.ts +59 -0
- package/src/jsonForm/index.ts +22 -0
- package/src/jsonForm/inferSchema.ts +25 -0
- package/src/jsonForm/pointer.ts +109 -0
- package/src/jsonForm/types.ts +167 -0
- package/src/markdown/convert.ts +145 -5
- package/src/markdown/index.ts +3 -0
- package/src/markdown/types.ts +19 -2
- package/src/markdown/utils.ts +159 -0
- package/src/recommend/index.ts +16 -0
- package/src/recommend/templates.ts +273 -0
- package/src/schemas/BlockTemplates.ts +50 -7
- package/src/schemas/ImageEditDoc.ts +95 -0
- package/src/schemas/Theme.ts +98 -31
- package/src/schemas/colorUtils.ts +186 -0
- package/src/schemas/fontStacks.ts +257 -0
- package/src/schemas/index.ts +12 -0
- package/src/schemas/themeCompile.ts +203 -0
- package/src/schemas/themeLibrary.ts +18 -597
- package/src/schemas/themeValidator.ts +388 -0
- package/src/schemas/themes/bold.json +48 -0
- package/src/schemas/themes/cinematic.json +54 -0
- package/src/schemas/themes/documentary.json +49 -0
- package/src/schemas/themes/gezellig.json +44 -0
- package/src/schemas/themes/index.ts +53 -0
- package/src/schemas/themes/magazine.json +44 -0
- package/src/schemas/themes/minimalist.json +45 -0
- package/src/schemas/themes/morning-light.json +42 -0
- package/src/schemas/themes/standard-dark.json +50 -0
- package/src/schemas/themes/standard.json +42 -0
- package/src/schemas/themes/tech-dark.json +48 -0
- package/src/schemas/themes/warm-earth.json +50 -0
- package/src/storage/ScopedContentContainer.ts +113 -0
- package/src/storage/index.ts +1 -0
- package/src/versions/DocumentVersionManager.ts +70 -0
- package/src/versions/index.ts +54 -0
- package/src/versions/operations.ts +230 -0
- package/src/versions/paths.ts +66 -0
- package/src/versions/timestamp.ts +48 -0
- package/src/versions/types.ts +91 -0
- package/dist/__tests__/animationUtils.test.d.ts +0 -2
- package/dist/__tests__/animationUtils.test.d.ts.map +0 -1
- package/dist/__tests__/animationUtils.test.js +0 -60
- package/dist/__tests__/animationUtils.test.js.map +0 -1
- package/dist/__tests__/contentContainer.test.d.ts +0 -2
- package/dist/__tests__/contentContainer.test.d.ts.map +0 -1
- package/dist/__tests__/contentContainer.test.js +0 -234
- package/dist/__tests__/contentContainer.test.js.map +0 -1
- package/dist/__tests__/contentExtractor.test.d.ts +0 -2
- package/dist/__tests__/contentExtractor.test.d.ts.map +0 -1
- package/dist/__tests__/contentExtractor.test.js +0 -151
- package/dist/__tests__/contentExtractor.test.js.map +0 -1
- package/dist/__tests__/coverBlock.test.d.ts +0 -2
- package/dist/__tests__/coverBlock.test.d.ts.map +0 -1
- package/dist/__tests__/coverBlock.test.js +0 -197
- package/dist/__tests__/coverBlock.test.js.map +0 -1
- package/dist/__tests__/dataTable.test.d.ts +0 -2
- package/dist/__tests__/dataTable.test.d.ts.map +0 -1
- package/dist/__tests__/dataTable.test.js +0 -110
- package/dist/__tests__/dataTable.test.js.map +0 -1
- package/dist/__tests__/geohash.test.d.ts +0 -2
- package/dist/__tests__/geohash.test.d.ts.map +0 -1
- package/dist/__tests__/geohash.test.js +0 -87
- package/dist/__tests__/geohash.test.js.map +0 -1
- package/dist/__tests__/getLayers.test.d.ts +0 -2
- package/dist/__tests__/getLayers.test.d.ts.map +0 -1
- package/dist/__tests__/getLayers.test.js +0 -167
- package/dist/__tests__/getLayers.test.js.map +0 -1
- package/dist/__tests__/haversine.test.d.ts +0 -2
- package/dist/__tests__/haversine.test.d.ts.map +0 -1
- package/dist/__tests__/haversine.test.js +0 -56
- package/dist/__tests__/haversine.test.js.map +0 -1
- package/dist/__tests__/localForageAdapter.test.d.ts +0 -8
- package/dist/__tests__/localForageAdapter.test.d.ts.map +0 -1
- package/dist/__tests__/localForageAdapter.test.js +0 -130
- package/dist/__tests__/localForageAdapter.test.js.map +0 -1
- package/dist/__tests__/markdown.test.d.ts +0 -2
- package/dist/__tests__/markdown.test.d.ts.map +0 -1
- package/dist/__tests__/markdown.test.js +0 -715
- package/dist/__tests__/markdown.test.js.map +0 -1
- package/dist/__tests__/markdownToDoc.test.d.ts +0 -2
- package/dist/__tests__/markdownToDoc.test.d.ts.map +0 -1
- package/dist/__tests__/markdownToDoc.test.js +0 -447
- package/dist/__tests__/markdownToDoc.test.js.map +0 -1
- package/dist/__tests__/seededRandom.test.d.ts +0 -2
- package/dist/__tests__/seededRandom.test.d.ts.map +0 -1
- package/dist/__tests__/seededRandom.test.js +0 -125
- package/dist/__tests__/seededRandom.test.js.map +0 -1
- package/dist/__tests__/slideshowGenerator.test.d.ts +0 -2
- package/dist/__tests__/slideshowGenerator.test.d.ts.map +0 -1
- package/dist/__tests__/slideshowGenerator.test.js +0 -114
- package/dist/__tests__/slideshowGenerator.test.js.map +0 -1
- package/dist/__tests__/storage.test.d.ts +0 -2
- package/dist/__tests__/storage.test.d.ts.map +0 -1
- package/dist/__tests__/storage.test.js +0 -51
- package/dist/__tests__/storage.test.js.map +0 -1
- package/dist/__tests__/surface.test.d.ts +0 -2
- package/dist/__tests__/surface.test.d.ts.map +0 -1
- package/dist/__tests__/surface.test.js +0 -57
- package/dist/__tests__/surface.test.js.map +0 -1
- package/dist/__tests__/templates.test.d.ts +0 -2
- package/dist/__tests__/templates.test.d.ts.map +0 -1
- package/dist/__tests__/templates.test.js +0 -217
- package/dist/__tests__/templates.test.js.map +0 -1
- package/dist/__tests__/timing.test.d.ts +0 -2
- package/dist/__tests__/timing.test.d.ts.map +0 -1
- package/dist/__tests__/timing.test.js +0 -131
- package/dist/__tests__/timing.test.js.map +0 -1
- package/dist/chunk-6BAVXFYC.js.map +0 -1
- package/dist/chunk-7GF6RDED.js +0 -82
- package/dist/chunk-7GF6RDED.js.map +0 -1
- package/dist/chunk-CYQHG27J.js.map +0 -1
- package/dist/chunk-F22AE6BY.js +0 -121
- package/dist/chunk-F22AE6BY.js.map +0 -1
- package/dist/chunk-FIQR4AJG.js +0 -517
- package/dist/chunk-FIQR4AJG.js.map +0 -1
- package/dist/chunk-OASJKWO5.js.map +0 -1
- package/dist/chunk-QM5PKNPW.js.map +0 -1
- package/dist/chunk-TSG2OSE6.js.map +0 -1
- package/dist/doc/audioMapping.d.ts +0 -36
- package/dist/doc/audioMapping.d.ts.map +0 -1
- package/dist/doc/audioMapping.js +0 -315
- package/dist/doc/audioMapping.js.map +0 -1
- package/dist/doc/docToMarkdown.d.ts +0 -41
- package/dist/doc/docToMarkdown.d.ts.map +0 -1
- package/dist/doc/docToMarkdown.js +0 -88
- package/dist/doc/docToMarkdown.js.map +0 -1
- package/dist/doc/getLayers.d.ts +0 -65
- package/dist/doc/getLayers.d.ts.map +0 -1
- package/dist/doc/getLayers.js +0 -103
- package/dist/doc/getLayers.js.map +0 -1
- package/dist/doc/index.d.ts.map +0 -1
- package/dist/doc/markdownToDoc.d.ts +0 -75
- package/dist/doc/markdownToDoc.d.ts.map +0 -1
- package/dist/doc/markdownToDoc.js +0 -398
- package/dist/doc/markdownToDoc.js.map +0 -1
- package/dist/doc/templates/accentImage.d.ts +0 -59
- package/dist/doc/templates/accentImage.d.ts.map +0 -1
- package/dist/doc/templates/accentImage.js +0 -275
- package/dist/doc/templates/accentImage.js.map +0 -1
- package/dist/doc/templates/captionUtils.d.ts +0 -20
- package/dist/doc/templates/captionUtils.d.ts.map +0 -1
- package/dist/doc/templates/captionUtils.js +0 -29
- package/dist/doc/templates/captionUtils.js.map +0 -1
- package/dist/doc/templates/comparisonBar.d.ts +0 -13
- package/dist/doc/templates/comparisonBar.d.ts.map +0 -1
- package/dist/doc/templates/comparisonBar.js +0 -145
- package/dist/doc/templates/comparisonBar.js.map +0 -1
- package/dist/doc/templates/coverBlock.d.ts +0 -51
- package/dist/doc/templates/coverBlock.d.ts.map +0 -1
- package/dist/doc/templates/coverBlock.js +0 -153
- package/dist/doc/templates/coverBlock.js.map +0 -1
- package/dist/doc/templates/dataTable.d.ts +0 -14
- package/dist/doc/templates/dataTable.d.ts.map +0 -1
- package/dist/doc/templates/dataTable.js +0 -73
- package/dist/doc/templates/dataTable.js.map +0 -1
- package/dist/doc/templates/dateEvent.d.ts +0 -15
- package/dist/doc/templates/dateEvent.d.ts.map +0 -1
- package/dist/doc/templates/dateEvent.js +0 -114
- package/dist/doc/templates/dateEvent.js.map +0 -1
- package/dist/doc/templates/definitionCard.d.ts +0 -13
- package/dist/doc/templates/definitionCard.d.ts.map +0 -1
- package/dist/doc/templates/definitionCard.js +0 -117
- package/dist/doc/templates/definitionCard.js.map +0 -1
- package/dist/doc/templates/factCard.d.ts +0 -15
- package/dist/doc/templates/factCard.d.ts.map +0 -1
- package/dist/doc/templates/factCard.js +0 -104
- package/dist/doc/templates/factCard.js.map +0 -1
- package/dist/doc/templates/fullBleedQuote.d.ts +0 -13
- package/dist/doc/templates/fullBleedQuote.d.ts.map +0 -1
- package/dist/doc/templates/fullBleedQuote.js +0 -55
- package/dist/doc/templates/fullBleedQuote.js.map +0 -1
- package/dist/doc/templates/imageWithCaption.d.ts +0 -13
- package/dist/doc/templates/imageWithCaption.d.ts.map +0 -1
- package/dist/doc/templates/imageWithCaption.js +0 -146
- package/dist/doc/templates/imageWithCaption.js.map +0 -1
- package/dist/doc/templates/index.d.ts +0 -105
- package/dist/doc/templates/index.d.ts.map +0 -1
- package/dist/doc/templates/index.js +0 -445
- package/dist/doc/templates/index.js.map +0 -1
- package/dist/doc/templates/listBlock.d.ts +0 -13
- package/dist/doc/templates/listBlock.d.ts.map +0 -1
- package/dist/doc/templates/listBlock.js +0 -92
- package/dist/doc/templates/listBlock.js.map +0 -1
- package/dist/doc/templates/mapBlock.d.ts +0 -17
- package/dist/doc/templates/mapBlock.d.ts.map +0 -1
- package/dist/doc/templates/mapBlock.js +0 -115
- package/dist/doc/templates/mapBlock.js.map +0 -1
- package/dist/doc/templates/persistentLayers.d.ts +0 -39
- package/dist/doc/templates/persistentLayers.d.ts.map +0 -1
- package/dist/doc/templates/persistentLayers.js +0 -447
- package/dist/doc/templates/persistentLayers.js.map +0 -1
- package/dist/doc/templates/photoGrid.d.ts +0 -20
- package/dist/doc/templates/photoGrid.d.ts.map +0 -1
- package/dist/doc/templates/photoGrid.js +0 -175
- package/dist/doc/templates/photoGrid.js.map +0 -1
- package/dist/doc/templates/pullQuote.d.ts +0 -13
- package/dist/doc/templates/pullQuote.d.ts.map +0 -1
- package/dist/doc/templates/pullQuote.js +0 -113
- package/dist/doc/templates/pullQuote.js.map +0 -1
- package/dist/doc/templates/quoteBlock.d.ts +0 -15
- package/dist/doc/templates/quoteBlock.d.ts.map +0 -1
- package/dist/doc/templates/quoteBlock.js +0 -101
- package/dist/doc/templates/quoteBlock.js.map +0 -1
- package/dist/doc/templates/sectionHeader.d.ts +0 -14
- package/dist/doc/templates/sectionHeader.d.ts.map +0 -1
- package/dist/doc/templates/sectionHeader.js +0 -97
- package/dist/doc/templates/sectionHeader.js.map +0 -1
- package/dist/doc/templates/statHighlight.d.ts +0 -15
- package/dist/doc/templates/statHighlight.d.ts.map +0 -1
- package/dist/doc/templates/statHighlight.js +0 -102
- package/dist/doc/templates/statHighlight.js.map +0 -1
- package/dist/doc/templates/titleBlock.d.ts +0 -13
- package/dist/doc/templates/titleBlock.d.ts.map +0 -1
- package/dist/doc/templates/titleBlock.js +0 -95
- package/dist/doc/templates/titleBlock.js.map +0 -1
- package/dist/doc/templates/twoColumn.d.ts +0 -15
- package/dist/doc/templates/twoColumn.d.ts.map +0 -1
- package/dist/doc/templates/twoColumn.js +0 -225
- package/dist/doc/templates/twoColumn.js.map +0 -1
- package/dist/doc/templates/videoPullQuote.d.ts +0 -20
- package/dist/doc/templates/videoPullQuote.d.ts.map +0 -1
- package/dist/doc/templates/videoPullQuote.js +0 -122
- package/dist/doc/templates/videoPullQuote.js.map +0 -1
- package/dist/doc/templates/videoWithCaption.d.ts +0 -20
- package/dist/doc/templates/videoWithCaption.d.ts.map +0 -1
- package/dist/doc/templates/videoWithCaption.js +0 -107
- package/dist/doc/templates/videoWithCaption.js.map +0 -1
- package/dist/doc/utils/animationUtils.d.ts +0 -34
- package/dist/doc/utils/animationUtils.d.ts.map +0 -1
- package/dist/doc/utils/animationUtils.js +0 -110
- package/dist/doc/utils/animationUtils.js.map +0 -1
- package/dist/doc/utils/themeUtils.d.ts +0 -64
- package/dist/doc/utils/themeUtils.d.ts.map +0 -1
- package/dist/doc/utils/themeUtils.js +0 -135
- package/dist/doc/utils/themeUtils.js.map +0 -1
- package/dist/generate/contentExtractor.d.ts +0 -112
- package/dist/generate/contentExtractor.d.ts.map +0 -1
- package/dist/generate/contentExtractor.js +0 -638
- package/dist/generate/contentExtractor.js.map +0 -1
- package/dist/generate/index.d.ts.map +0 -1
- package/dist/generate/slideshowGenerator.d.ts +0 -72
- package/dist/generate/slideshowGenerator.d.ts.map +0 -1
- package/dist/generate/slideshowGenerator.js +0 -159
- package/dist/generate/slideshowGenerator.js.map +0 -1
- package/dist/generate/templateMapper.d.ts +0 -23
- package/dist/generate/templateMapper.d.ts.map +0 -1
- package/dist/generate/templateMapper.js +0 -114
- package/dist/generate/templateMapper.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/markdown/convert.d.ts +0 -71
- package/dist/markdown/convert.d.ts.map +0 -1
- package/dist/markdown/convert.js +0 -845
- package/dist/markdown/convert.js.map +0 -1
- package/dist/markdown/htmlParse.d.ts +0 -26
- package/dist/markdown/htmlParse.d.ts.map +0 -1
- package/dist/markdown/htmlParse.js +0 -195
- package/dist/markdown/htmlParse.js.map +0 -1
- package/dist/markdown/index.d.ts.map +0 -1
- package/dist/markdown/parse.d.ts +0 -27
- package/dist/markdown/parse.d.ts.map +0 -1
- package/dist/markdown/parse.js +0 -90
- package/dist/markdown/parse.js.map +0 -1
- package/dist/markdown/stringify.d.ts +0 -32
- package/dist/markdown/stringify.d.ts.map +0 -1
- package/dist/markdown/stringify.js +0 -108
- package/dist/markdown/stringify.js.map +0 -1
- package/dist/markdown/types.d.ts +0 -516
- package/dist/markdown/types.d.ts.map +0 -1
- package/dist/markdown/types.js +0 -17
- package/dist/markdown/types.js.map +0 -1
- package/dist/markdown/utils.d.ts +0 -78
- package/dist/markdown/utils.d.ts.map +0 -1
- package/dist/markdown/utils.js +0 -153
- package/dist/markdown/utils.js.map +0 -1
- package/dist/random/SeededRandom.d.ts +0 -50
- package/dist/random/SeededRandom.d.ts.map +0 -1
- package/dist/random/SeededRandom.js +0 -115
- package/dist/random/SeededRandom.js.map +0 -1
- package/dist/random/index.d.ts.map +0 -1
- package/dist/schemas/BlockTemplates.d.ts +0 -600
- package/dist/schemas/BlockTemplates.d.ts.map +0 -1
- package/dist/schemas/BlockTemplates.js +0 -72
- package/dist/schemas/BlockTemplates.js.map +0 -1
- package/dist/schemas/Doc.d.ts +0 -503
- package/dist/schemas/Doc.d.ts.map +0 -1
- package/dist/schemas/Doc.js +0 -90
- package/dist/schemas/Doc.js.map +0 -1
- package/dist/schemas/LayoutStrategy.d.ts +0 -84
- package/dist/schemas/LayoutStrategy.d.ts.map +0 -1
- package/dist/schemas/LayoutStrategy.js +0 -123
- package/dist/schemas/LayoutStrategy.js.map +0 -1
- package/dist/schemas/MediaProvider.d.ts +0 -65
- package/dist/schemas/MediaProvider.d.ts.map +0 -1
- package/dist/schemas/MediaProvider.js +0 -13
- package/dist/schemas/MediaProvider.js.map +0 -1
- package/dist/schemas/Theme.d.ts +0 -194
- package/dist/schemas/Theme.d.ts.map +0 -1
- package/dist/schemas/Theme.js +0 -97
- package/dist/schemas/Theme.js.map +0 -1
- package/dist/schemas/Types.d.ts +0 -14
- package/dist/schemas/Types.d.ts.map +0 -1
- package/dist/schemas/Types.js +0 -5
- package/dist/schemas/Types.js.map +0 -1
- package/dist/schemas/Viewport.d.ts +0 -74
- package/dist/schemas/Viewport.d.ts.map +0 -1
- package/dist/schemas/Viewport.js +0 -63
- package/dist/schemas/Viewport.js.map +0 -1
- package/dist/schemas/index.d.ts.map +0 -1
- package/dist/schemas/themeLibrary.d.ts +0 -41
- package/dist/schemas/themeLibrary.d.ts.map +0 -1
- package/dist/schemas/themeLibrary.js +0 -597
- package/dist/schemas/themeLibrary.js.map +0 -1
- package/dist/spatial/Geohash.d.ts +0 -85
- package/dist/spatial/Geohash.d.ts.map +0 -1
- package/dist/spatial/Geohash.js +0 -142
- package/dist/spatial/Geohash.js.map +0 -1
- package/dist/spatial/Haversine.d.ts +0 -24
- package/dist/spatial/Haversine.d.ts.map +0 -1
- package/dist/spatial/Haversine.js +0 -48
- package/dist/spatial/Haversine.js.map +0 -1
- package/dist/spatial/index.d.ts.map +0 -1
- package/dist/storage/ContentContainer.d.ts +0 -87
- package/dist/storage/ContentContainer.d.ts.map +0 -1
- package/dist/storage/ContentContainer.js +0 -131
- package/dist/storage/ContentContainer.js.map +0 -1
- package/dist/storage/LocalForageAdapter.d.ts +0 -36
- package/dist/storage/LocalForageAdapter.d.ts.map +0 -1
- package/dist/storage/LocalForageAdapter.js +0 -82
- package/dist/storage/LocalForageAdapter.js.map +0 -1
- package/dist/storage/LocalStorageAdapter.d.ts +0 -16
- package/dist/storage/LocalStorageAdapter.d.ts.map +0 -1
- package/dist/storage/LocalStorageAdapter.js +0 -50
- package/dist/storage/LocalStorageAdapter.js.map +0 -1
- package/dist/storage/MediaProviderFromContainer.d.ts +0 -21
- package/dist/storage/MediaProviderFromContainer.d.ts.map +0 -1
- package/dist/storage/MediaProviderFromContainer.js +0 -79
- package/dist/storage/MediaProviderFromContainer.js.map +0 -1
- package/dist/storage/MemoryStorageAdapter.d.ts +0 -15
- package/dist/storage/MemoryStorageAdapter.d.ts.map +0 -1
- package/dist/storage/MemoryStorageAdapter.js +0 -34
- package/dist/storage/MemoryStorageAdapter.js.map +0 -1
- package/dist/storage/Storage.d.ts +0 -23
- package/dist/storage/Storage.d.ts.map +0 -1
- package/dist/storage/Storage.js +0 -9
- package/dist/storage/Storage.js.map +0 -1
- package/dist/storage/index.d.ts.map +0 -1
- package/dist/themeLibrary-CEo2D4b6.d.ts +0 -44
- package/dist/timing/index.d.ts.map +0 -1
- package/dist/timing/narrationTiming.d.ts +0 -54
- package/dist/timing/narrationTiming.d.ts.map +0 -1
- package/dist/timing/narrationTiming.js +0 -190
- package/dist/timing/narrationTiming.js.map +0 -1
- package/dist/timing/readingTime.d.ts +0 -54
- package/dist/timing/readingTime.d.ts.map +0 -1
- package/dist/timing/readingTime.js +0 -49
- package/dist/timing/readingTime.js.map +0 -1
- package/dist/transform/applyTransform.d.ts +0 -22
- package/dist/transform/applyTransform.d.ts.map +0 -1
- package/dist/transform/applyTransform.js +0 -68
- package/dist/transform/applyTransform.js.map +0 -1
- package/dist/transform/blockAnalyzer.d.ts +0 -48
- package/dist/transform/blockAnalyzer.d.ts.map +0 -1
- package/dist/transform/blockAnalyzer.js +0 -135
- package/dist/transform/blockAnalyzer.js.map +0 -1
- package/dist/transform/index.d.ts.map +0 -1
- package/dist/transform/registry.d.ts +0 -19
- package/dist/transform/registry.d.ts.map +0 -1
- package/dist/transform/registry.js +0 -41
- package/dist/transform/registry.js.map +0 -1
- package/dist/transform/styles/dataDriven.d.ts +0 -4
- package/dist/transform/styles/dataDriven.d.ts.map +0 -1
- package/dist/transform/styles/dataDriven.js +0 -15
- package/dist/transform/styles/dataDriven.js.map +0 -1
- package/dist/transform/styles/documentary.d.ts +0 -4
- package/dist/transform/styles/documentary.d.ts.map +0 -1
- package/dist/transform/styles/documentary.js +0 -15
- package/dist/transform/styles/documentary.js.map +0 -1
- package/dist/transform/styles/index.d.ts +0 -6
- package/dist/transform/styles/index.d.ts.map +0 -1
- package/dist/transform/styles/index.js +0 -6
- package/dist/transform/styles/index.js.map +0 -1
- package/dist/transform/styles/magazine.d.ts +0 -4
- package/dist/transform/styles/magazine.d.ts.map +0 -1
- package/dist/transform/styles/magazine.js +0 -15
- package/dist/transform/styles/magazine.js.map +0 -1
- package/dist/transform/styles/minimal.d.ts +0 -4
- package/dist/transform/styles/minimal.d.ts.map +0 -1
- package/dist/transform/styles/minimal.js +0 -15
- package/dist/transform/styles/minimal.js.map +0 -1
- package/dist/transform/styles/narrative.d.ts +0 -4
- package/dist/transform/styles/narrative.d.ts.map +0 -1
- package/dist/transform/styles/narrative.js +0 -15
- package/dist/transform/styles/narrative.js.map +0 -1
- package/dist/transform/templateSelector.d.ts +0 -30
- package/dist/transform/templateSelector.d.ts.map +0 -1
- package/dist/transform/templateSelector.js +0 -218
- package/dist/transform/templateSelector.js.map +0 -1
- package/dist/transform/timingAllocator.d.ts +0 -21
- package/dist/transform/timingAllocator.d.ts.map +0 -1
- package/dist/transform/timingAllocator.js +0 -111
- package/dist/transform/timingAllocator.js.map +0 -1
- package/dist/transform/types.d.ts +0 -86
- package/dist/transform/types.d.ts.map +0 -1
- package/dist/transform/types.js +0 -9
- package/dist/transform/types.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transform/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,eAAe,CAAC;AAYvB,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"sources":["../../src/transform/styles/documentary.ts","../../src/transform/styles/magazine.ts","../../src/transform/styles/dataDriven.ts","../../src/transform/styles/narrative.ts","../../src/transform/styles/minimal.ts","../../src/transform/registry.ts","../../src/transform/blockAnalyzer.ts","../../src/transform/templateSelector.ts","../../src/transform/timingAllocator.ts","../../src/transform/applyTransform.ts"],"sourcesContent":["import type { TransformStyleConfig } from '../types.js';\n\n/** Conservative style — sparse highlights, preserves most text as-is. */\nexport const documentaryStyle: TransformStyleConfig = {\n id: 'documentary',\n name: 'Documentary',\n description: 'Conservative — highlights only the strongest stats, dates, and quotes',\n minConfidence: 0.5,\n transformRatio: 0.3,\n preferredTypes: ['stat', 'date', 'quote', 'fact'],\n colorSchemes: ['blue', 'green', 'purple'],\n insertSectionHeaders: false,\n interleaveImages: true,\n blocksPerSection: { min: 1, max: 3 },\n transitionStyle: 'fade',\n};\n","import type { TransformStyleConfig } from '../types.js';\n\n/** Visual variety — pull quotes, definitions, image-heavy layout. */\nexport const magazineStyle: TransformStyleConfig = {\n id: 'magazine',\n name: 'Magazine',\n description: 'Visual variety with pull quotes, facts, and rich image layouts',\n minConfidence: 0.4,\n transformRatio: 0.6,\n preferredTypes: ['quote', 'fact', 'list', 'definition', 'stat', 'impactLine'],\n colorSchemes: ['blue', 'green', 'purple', 'orange', 'red'],\n insertSectionHeaders: true,\n interleaveImages: true,\n blocksPerSection: { min: 2, max: 5 },\n transitionStyle: 'dissolve',\n};\n","import type { TransformStyleConfig } from '../types.js';\n\n/** Numbers-forward — aggressively extracts stats, comparisons, and dates. */\nexport const dataDrivenStyle: TransformStyleConfig = {\n id: 'data-driven',\n name: 'Data-Driven',\n description: 'Aggressively highlights statistics, comparisons, and timelines',\n minConfidence: 0.3,\n transformRatio: 0.8,\n preferredTypes: ['stat', 'comparison', 'date', 'list', 'fact'],\n colorSchemes: ['blue', 'orange', 'green', 'purple', 'red'],\n insertSectionHeaders: true,\n interleaveImages: false,\n blocksPerSection: { min: 2, max: 6 },\n transitionStyle: 'cut',\n};\n","import type { TransformStyleConfig } from '../types.js';\n\n/** Timeline-focused — emphasizes dates, quotes, and story arc. */\nexport const narrativeStyle: TransformStyleConfig = {\n id: 'narrative',\n name: 'Narrative',\n description: 'Story-driven with timeline events, quotes, and impact moments',\n minConfidence: 0.4,\n transformRatio: 0.5,\n preferredTypes: ['date', 'quote', 'impactLine', 'fact', 'stat'],\n colorSchemes: ['blue', 'purple', 'green'],\n insertSectionHeaders: true,\n interleaveImages: true,\n blocksPerSection: { min: 1, max: 4 },\n transitionStyle: 'fade',\n};\n","import type { TransformStyleConfig } from '../types.js';\n\n/** Light touch — only the highest-confidence items get transformed. */\nexport const minimalStyle: TransformStyleConfig = {\n id: 'minimal',\n name: 'Minimal',\n description: 'Light touch — only the strongest highlights, mostly text',\n minConfidence: 0.6,\n transformRatio: 0.2,\n preferredTypes: ['stat', 'quote'],\n colorSchemes: ['blue', 'green'],\n insertSectionHeaders: false,\n interleaveImages: false,\n blocksPerSection: { min: 1, max: 2 },\n transitionStyle: 'fade',\n};\n","/**\n * Transform Style Registry\n *\n * Central registry of built-in transform styles. Follows the same pattern\n * as themeLibrary.ts — a record of configs with lookup/summary helpers.\n */\n\nimport type { TransformStyleConfig, TransformStyleSummary } from './types.js';\nimport { documentaryStyle } from './styles/documentary.js';\nimport { magazineStyle } from './styles/magazine.js';\nimport { dataDrivenStyle } from './styles/dataDriven.js';\nimport { narrativeStyle } from './styles/narrative.js';\nimport { minimalStyle } from './styles/minimal.js';\n\n/** All registered transform styles, keyed by id. */\nconst TRANSFORM_STYLES: Record<string, TransformStyleConfig> = {\n [documentaryStyle.id]: documentaryStyle,\n [magazineStyle.id]: magazineStyle,\n [dataDrivenStyle.id]: dataDrivenStyle,\n [narrativeStyle.id]: narrativeStyle,\n [minimalStyle.id]: minimalStyle,\n};\n\n/** Default style used when no id is provided. */\nexport const DEFAULT_TRANSFORM_STYLE_ID = 'documentary';\n\n/**\n * Resolve a transform style by id.\n * Returns the default style if the id is not found.\n */\nexport function resolveTransformStyle(id: string): TransformStyleConfig {\n return TRANSFORM_STYLES[id] ?? TRANSFORM_STYLES[DEFAULT_TRANSFORM_STYLE_ID];\n}\n\n/** Get all registered style ids. */\nexport function getTransformStyleIds(): string[] {\n return Object.keys(TRANSFORM_STYLES);\n}\n\n/** Get summary info for all styles (for UI dropdowns). */\nexport function getTransformStyleSummaries(): TransformStyleSummary[] {\n return Object.values(TRANSFORM_STYLES).map(({ id, name, description }) => ({\n id,\n name,\n description,\n }));\n}\n","/**\n * Block Analyzer\n *\n * Walks Doc blocks, extracts plain text from their markdown contents,\n * and runs the content extractor on each block to identify stats, dates,\n * quotes, etc. that can be promoted to visual template blocks.\n */\n\nimport type { Block } from '../schemas/Doc.js';\nimport type { MarkdownBlockNode, MarkdownNode } from '../markdown/types.js';\nimport type { ExtractedElement, ExtractionOptions } from '../generate/contentExtractor.js';\nimport type { TransformImage } from './types.js';\nimport { extractContent, stripMarkdown } from '../generate/contentExtractor.js';\nimport { extractPlainText, getChildren } from '../markdown/utils.js';\n\n/** An image found in a block's markdown contents. */\nexport interface BlockImage {\n /** Image URL (relative or absolute). */\n src: string;\n /** Alt text. */\n alt: string;\n /** Index of the source block in the analyzed array. */\n sourceBlockIndex: number;\n}\n\n/** A block enriched with extraction analysis. */\nexport interface AnalyzedBlock {\n /** The original block. */\n block: Block;\n /** Plain text extracted from the block's contents. */\n plainText: string;\n /** Content extractions found in the block's text. */\n extractions: ExtractedElement[];\n /** Whether this block has child blocks. */\n hasChildren: boolean;\n /** Word count of the block's body text. */\n bodyWordCount: number;\n /** Images found in this block's markdown contents. */\n images: BlockImage[];\n}\n\n/**\n * Extract plain text from an array of MarkdownBlockNodes.\n */\nfunction contentsToPlainText(contents: MarkdownBlockNode[]): string {\n return contents.map((node) => extractPlainText(node)).join('\\n');\n}\n\n/**\n * Recursively walk a markdown node tree and collect all images.\n */\nfunction collectImages(node: MarkdownNode): Array<{ src: string; alt: string }> {\n const results: Array<{ src: string; alt: string }> = [];\n\n if ('type' in node && node.type === 'image' && 'url' in node) {\n const img = node as { url: string; alt?: string };\n if (img.url) {\n results.push({ src: img.url, alt: img.alt ?? '' });\n }\n }\n\n for (const child of getChildren(node)) {\n results.push(...collectImages(child));\n }\n\n return results;\n}\n\n/**\n * Extract images from a block's markdown contents.\n */\nfunction extractBlockImages(block: Block, blockIndex: number): BlockImage[] {\n if (!block.contents || block.contents.length === 0) return [];\n\n const images: BlockImage[] = [];\n for (const node of block.contents) {\n for (const img of collectImages(node)) {\n images.push({ ...img, sourceBlockIndex: blockIndex });\n }\n }\n return images;\n}\n\n/**\n * Collect all unique images from all blocks in a Doc.\n * Returns them as TransformImages for use in the transform pipeline.\n */\nexport function extractDocImages(blocks: Block[]): TransformImage[] {\n const seen = new Set<string>();\n const images: TransformImage[] = [];\n\n function walk(blockList: Block[]): void {\n for (const block of blockList) {\n if (block.contents) {\n for (const node of block.contents) {\n for (const img of collectImages(node)) {\n if (!seen.has(img.src)) {\n seen.add(img.src);\n images.push({ src: img.src, alt: img.alt });\n }\n }\n }\n }\n if (block.children) {\n walk(block.children);\n }\n }\n }\n\n walk(blocks);\n return images;\n}\n\n/**\n * Collect leaf blocks from a nested block tree.\n * Only returns blocks that have their own `contents` but no children,\n * preventing parent blocks from duplicating text that also appears\n * in their children. Parent-only blocks (with a title but no body\n * content) are included as structural placeholders.\n */\nfunction collectLeafBlocks(blocks: Block[]): Block[] {\n const result: Block[] = [];\n for (const block of blocks) {\n if (block.children && block.children.length > 0) {\n // Parent block — only include it as a structural marker\n // (title only, no body extraction) if it has no contents of its own.\n // Then recurse into children for the actual content.\n if (!block.contents || block.contents.length === 0) {\n result.push(block);\n }\n result.push(...collectLeafBlocks(block.children));\n } else {\n // Leaf block — include for content analysis\n result.push(block);\n }\n }\n return result;\n}\n\n/**\n * Analyze all blocks in a Doc, extracting text and running content extraction.\n *\n * @param blocks - The Doc's block array (may be nested via children).\n * @param options - Extraction options (minConfidence, types filter).\n * @returns Analyzed blocks with extractions, in flattened order.\n */\nexport function analyzeBlocks(blocks: Block[], options?: ExtractionOptions): AnalyzedBlock[] {\n const flat = collectLeafBlocks(blocks);\n const results: AnalyzedBlock[] = [];\n\n for (const block of flat) {\n let plainText = '';\n\n if (block.contents && block.contents.length > 0) {\n plainText = contentsToPlainText(block.contents);\n } else if (block.title) {\n plainText = block.title;\n }\n\n // Strip any remaining markdown syntax\n const stripped = stripMarkdown(plainText);\n const bodyWordCount = stripped.split(/\\s+/).filter((w) => w.length > 0).length;\n\n // Run content extraction\n const extraction = extractContent(stripped, options);\n\n // Extract images from markdown contents\n const images = extractBlockImages(block, results.length);\n\n results.push({\n block,\n plainText: stripped,\n extractions: extraction.elements,\n hasChildren: !!(block.children && block.children.length > 0),\n bodyWordCount,\n images,\n });\n }\n\n return results;\n}\n","/**\n * Template Selector\n *\n * Selects which extracted elements to promote to visual template blocks\n * and handles color scheme rotation, image interleaving, and template\n * variety. Ported and generalized from qualla-internal's TemplateSelector.\n */\n\nimport type { Block } from '../schemas/Doc.js';\nimport type {\n TemplateBlock,\n AccentImage,\n AccentPosition,\n ImageWithCaptionInput,\n SectionHeaderInput,\n} from '../schemas/BlockTemplates.js';\nimport type { ExtractedElement } from '../generate/contentExtractor.js';\nimport type { TransformStyleConfig, TransformImage } from './types.js';\nimport type { AnalyzedBlock } from './blockAnalyzer.js';\nimport { mapElementToBlock } from '../generate/templateMapper.js';\nimport { SeededRandom } from '../random/SeededRandom.js';\n\n/** Accent positions to rotate through. */\nconst ACCENT_POSITIONS: AccentPosition[] = [\n 'left-strip',\n 'right-strip',\n 'bottom-strip',\n 'corner-inset',\n];\n\n/** Ambient motions to rotate on image blocks. */\nconst AMBIENT_MOTIONS: Array<'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight'> = [\n 'zoomIn',\n 'zoomOut',\n 'panLeft',\n 'panRight',\n];\n\n/** A selected element paired with its source block. */\ninterface SelectedExtraction {\n element: ExtractedElement;\n sourceBlock: Block;\n /** Index in the original analyzed blocks array. */\n sourceIndex: number;\n}\n\n/** Result of template selection. */\nexport interface SelectionResult {\n /** Replacement blocks: a mix of original blocks and new template blocks. */\n blocks: Array<Block | TemplateBlock>;\n /** How many blocks were transformed. */\n transformedCount: number;\n /** How many blocks were inserted (images, section headers). */\n insertedCount: number;\n}\n\n/**\n * Select extractions and build a transformed block sequence.\n *\n * @param analyzed - Analyzed blocks from blockAnalyzer.\n * @param config - The transform style configuration.\n * @param images - Available images for interleaving.\n * @param seed - Random seed for deterministic output.\n */\nexport function selectAndBuild(\n analyzed: AnalyzedBlock[],\n config: TransformStyleConfig,\n images: TransformImage[],\n seed: number,\n): SelectionResult {\n const rng = new SeededRandom(seed);\n\n // 1. Collect all extractions across all blocks, filtered by config\n const candidates = collectCandidates(analyzed, config);\n\n // 2. Determine how many blocks to transform\n const maxTransforms = Math.max(1, Math.floor(analyzed.length * config.transformRatio));\n const selected = candidates.slice(0, maxTransforms);\n\n // 3. Build the output block sequence\n const result = buildBlockSequence(analyzed, selected, config, images, rng);\n\n return result;\n}\n\n/**\n * Collect candidate extractions from all analyzed blocks, sorted by\n * a combined score of confidence and type preference.\n */\nfunction collectCandidates(\n analyzed: AnalyzedBlock[],\n config: TransformStyleConfig,\n): SelectedExtraction[] {\n const candidates: SelectedExtraction[] = [];\n\n for (let i = 0; i < analyzed.length; i++) {\n const ab = analyzed[i];\n // Skip blocks with no meaningful text\n if (ab.bodyWordCount < 5) continue;\n\n for (const element of ab.extractions) {\n if (element.confidence < config.minConfidence) continue;\n\n candidates.push({\n element,\n sourceBlock: ab.block,\n sourceIndex: i,\n });\n }\n }\n\n // Sort by: preferred type rank (lower = better), then confidence (higher = better)\n const typeRank = new Map(config.preferredTypes.map((t, i) => [t, i]));\n const maxRank = config.preferredTypes.length;\n\n candidates.sort((a, b) => {\n const rankA = typeRank.get(a.element.type) ?? maxRank;\n const rankB = typeRank.get(b.element.type) ?? maxRank;\n if (rankA !== rankB) return rankA - rankB;\n return b.element.confidence - a.element.confidence;\n });\n\n // Deduplicate: if the same extracted text appears multiple times\n // (e.g., from overlapping parent/child blocks), keep only the\n // highest-ranked occurrence.\n const seenTexts = new Set<string>();\n const deduplicated: SelectedExtraction[] = [];\n for (const candidate of candidates) {\n const key = candidate.element.text.trim().toLowerCase();\n if (seenTexts.has(key)) continue;\n seenTexts.add(key);\n deduplicated.push(candidate);\n }\n\n return deduplicated;\n}\n\n/**\n * Build the output block sequence, replacing source blocks with template\n * blocks where extractions were selected, and interleaving images.\n */\nfunction buildBlockSequence(\n analyzed: AnalyzedBlock[],\n selected: SelectedExtraction[],\n config: TransformStyleConfig,\n images: TransformImage[],\n rng: SeededRandom,\n): SelectionResult {\n // Map: sourceIndex → list of selected extractions for that block\n const blockExtractions = new Map<number, SelectedExtraction[]>();\n for (const sel of selected) {\n const list = blockExtractions.get(sel.sourceIndex) ?? [];\n list.push(sel);\n blockExtractions.set(sel.sourceIndex, list);\n }\n\n // Limit extractions per block: cap at blocksPerSection.max and ensure\n // template type variety within each block (no two same-type extractions).\n for (const [idx, list] of blockExtractions) {\n const diverse: SelectedExtraction[] = [];\n const usedTypes = new Set<string>();\n for (const sel of list) {\n if (usedTypes.has(sel.element.type)) continue;\n usedTypes.add(sel.element.type);\n diverse.push(sel);\n if (diverse.length >= config.blocksPerSection.max) break;\n }\n blockExtractions.set(idx, diverse);\n }\n\n const blocks: Array<Block | TemplateBlock> = [];\n let transformedCount = 0;\n let insertedCount = 0;\n let colorIndex = 0;\n let blockIdCounter = 0;\n let imageIndex = 0;\n let accentPositionIndex = 0;\n let elementsSinceImage = 0;\n let prevTemplateType = '';\n\n // Calculate image interleaving interval\n const totalTransformed = Array.from(blockExtractions.values()).reduce(\n (sum, list) => sum + list.length,\n 0,\n );\n const imageInterval =\n config.interleaveImages && images.length > 0 && totalTransformed > 0\n ? Math.max(2, Math.floor(totalTransformed / (images.length + 1)))\n : Infinity;\n\n for (let i = 0; i < analyzed.length; i++) {\n const ab = analyzed[i];\n const extractions = blockExtractions.get(i);\n\n if (!extractions || extractions.length === 0) {\n // Keep the original block unchanged\n blocks.push(ab.block);\n continue;\n }\n\n // Insert section header before a group of transformed blocks (if enabled)\n if (config.insertSectionHeaders && ab.block.title) {\n const headerBlock: SectionHeaderInput = {\n template: 'sectionHeader',\n id: `transform-header-${blockIdCounter++}`,\n duration: ab.block.duration > 0 ? Math.min(3, ab.block.duration * 0.2) : 3,\n audioSegment: ab.block.audioSegment,\n title: ab.block.title,\n colorScheme: config.colorSchemes[colorIndex % config.colorSchemes.length],\n };\n blocks.push(headerBlock);\n insertedCount++;\n }\n\n // Convert each selected extraction to a template block.\n // Track the last template used globally (not just within this block)\n // to avoid consecutive same-template slides across the entire output.\n for (const sel of extractions) {\n const colorScheme = config.colorSchemes[colorIndex % config.colorSchemes.length];\n\n // Build accent image if we have images in the pool\n let accentImage: AccentImage | undefined;\n if (images.length > 0 && config.interleaveImages) {\n const img = images[imageIndex % images.length];\n accentImage = {\n src: img.src,\n alt: img.alt ?? '',\n position: ACCENT_POSITIONS[accentPositionIndex % ACCENT_POSITIONS.length],\n ambientMotion: rng.pick(AMBIENT_MOTIONS) ?? 'zoomIn',\n credit: img.credit,\n license: img.license,\n };\n accentPositionIndex++;\n }\n\n const templateBlock = mapElementToBlock(sel.element, {\n id: `transform-${blockIdCounter++}`,\n duration: ab.block.duration > 0 ? ab.block.duration / extractions.length : 6,\n audioSegment: ab.block.audioSegment,\n colorScheme,\n accentImage,\n sourceStartTime: sel.element.sourcePosition,\n });\n\n // Apply transition based on style\n if (config.transitionStyle !== 'cut') {\n (\n templateBlock as TemplateBlock & { transition?: { type: string; duration: number } }\n ).transition = {\n type:\n config.transitionStyle === 'mixed'\n ? (rng.pick(['fade', 'dissolve']) ?? 'fade')\n : config.transitionStyle,\n duration: 0.5,\n };\n }\n\n // Avoid consecutive same-template blocks by bumping color for variety\n if (templateBlock.template === prevTemplateType) {\n colorIndex++;\n }\n prevTemplateType = templateBlock.template;\n\n blocks.push(templateBlock);\n transformedCount++;\n colorIndex++;\n elementsSinceImage++;\n\n // Interleave standalone image at intervals\n if (\n config.interleaveImages &&\n imageIndex < images.length &&\n elementsSinceImage >= imageInterval\n ) {\n const img = images[imageIndex];\n const imageBlock: ImageWithCaptionInput = {\n template: 'imageWithCaption',\n id: `transform-img-${blockIdCounter++}`,\n duration: 4,\n audioSegment: ab.block.audioSegment,\n imageSrc: img.src,\n imageAlt: img.alt ?? '',\n ambientMotion: rng.pick(AMBIENT_MOTIONS) ?? 'zoomIn',\n };\n blocks.push(imageBlock);\n imageIndex++;\n insertedCount++;\n elementsSinceImage = 0;\n }\n }\n }\n\n return { blocks, transformedCount, insertedCount };\n}\n","/**\n * Timing Allocator\n *\n * Distributes timing (startTime, duration) across transformed blocks.\n * When the source Doc has audio, blocks are fitted to the overall duration.\n * When no audio is present, uses reading-time estimation.\n */\n\nimport type { Block } from '../schemas/Doc.js';\nimport type { TemplateBlock } from '../schemas/BlockTemplates.js';\nimport { isTemplateBlock } from '../schemas/BlockTemplates.js';\n\n/** Minimum block duration in seconds. */\nconst MIN_BLOCK_DURATION = 3;\n/** Maximum block duration in seconds. */\nconst MAX_BLOCK_DURATION = 20;\n/** Default duration when no timing info is available. */\nconst DEFAULT_BLOCK_DURATION = 6;\n\n/**\n * Allocate startTime and duration across a mixed array of blocks and\n * template blocks. Template blocks get timing assigned; existing blocks\n * retain their original timing when possible.\n *\n * @param blocks - The output from templateSelector (mixed Block | TemplateBlock).\n * @param totalDuration - The Doc's total duration (from audio or estimation).\n * @returns A new array of Blocks with consistent timing. Template blocks\n * are returned as Blocks (with startTime/duration set, layers empty).\n */\nexport function allocateTiming(\n blocks: Array<Block | TemplateBlock>,\n totalDuration: number,\n): Block[] {\n if (blocks.length === 0) return [];\n\n const effectiveDuration = totalDuration > 0 ? totalDuration : estimateDefaultDuration(blocks);\n\n // First pass: assign raw durations\n const durations = blocks.map((block) => {\n if (!isTemplateBlock(block) && block.duration > 0) {\n // Existing block with known duration — keep it\n return block.duration;\n }\n if (isTemplateBlock(block) && block.duration > 0) {\n return block.duration;\n }\n return DEFAULT_BLOCK_DURATION;\n });\n\n // Scale durations to fit the total\n const rawTotal = durations.reduce((sum, d) => sum + d, 0);\n if (rawTotal > 0 && effectiveDuration > 0) {\n const scale = effectiveDuration / rawTotal;\n for (let i = 0; i < durations.length; i++) {\n durations[i] = clampDuration(durations[i] * scale);\n }\n }\n\n // Second pass: assign startTimes and build output Blocks\n let currentTime = 0;\n const result: Block[] = [];\n\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n const duration = durations[i];\n\n if (isTemplateBlock(block)) {\n // Convert TemplateBlock to Block shell, preserving all template-specific\n // fields (stat, quote, description, etc.) so they survive through to\n // the player's template expansion step.\n const outputBlock = {\n ...block,\n startTime: currentTime,\n duration,\n title: getTemplateTitle(block),\n } as unknown as Block;\n result.push(outputBlock);\n } else {\n // Existing block — update timing\n result.push({\n ...block,\n startTime: currentTime,\n duration,\n });\n }\n\n currentTime += duration;\n }\n\n return result;\n}\n\n/** Clamp a duration to the min/max range. */\nfunction clampDuration(d: number): number {\n return Math.max(MIN_BLOCK_DURATION, Math.min(MAX_BLOCK_DURATION, d));\n}\n\n/** Estimate a total duration from block contents when no audio is available. */\nfunction estimateDefaultDuration(blocks: Array<Block | TemplateBlock>): number {\n let totalSeconds = 0;\n for (const block of blocks) {\n if (!isTemplateBlock(block) && block.duration > 0) {\n totalSeconds += block.duration;\n } else {\n totalSeconds += DEFAULT_BLOCK_DURATION;\n }\n }\n return Math.max(totalSeconds, blocks.length * MIN_BLOCK_DURATION);\n}\n\n/** Extract a display title from a template block if available. */\nfunction getTemplateTitle(block: TemplateBlock): string | undefined {\n if ('title' in block && typeof block.title === 'string') {\n return block.title;\n }\n if ('stat' in block && typeof block.stat === 'string') {\n return block.stat;\n }\n if ('fact' in block && typeof block.fact === 'string') {\n return block.fact;\n }\n if ('quote' in block && typeof block.quote === 'string') {\n return block.quote.slice(0, 60);\n }\n return undefined;\n}\n","/**\n * Apply Transform\n *\n * Main entry point for the transform module. Takes a Doc and a style,\n * analyzes block content, selects extractions to promote, and returns\n * a new Doc with blocks optimized for visual presentation.\n *\n * The input Doc is never mutated — a fresh Doc is always returned.\n */\n\nimport type { Doc } from '../schemas/Doc.js';\nimport type { TransformStyleId, TransformOptions, TransformResult } from './types.js';\nimport { resolveTransformStyle } from './registry.js';\nimport { analyzeBlocks, extractDocImages } from './blockAnalyzer.js';\nimport { selectAndBuild } from './templateSelector.js';\nimport { allocateTiming } from './timingAllocator.js';\nimport { hashString } from '../random/SeededRandom.js';\n\n/**\n * Apply a transform style to a Doc, producing a new Doc with blocks\n * optimized for visual presentation.\n *\n * @param doc - The source Doc (not mutated).\n * @param styleId - Registered transform style id (e.g. 'documentary', 'magazine').\n * @param options - Optional seed, images, theme override.\n * @returns TransformResult with the new Doc and stats.\n */\nexport function applyTransform(\n doc: Doc,\n styleId: TransformStyleId,\n options?: TransformOptions,\n): TransformResult {\n const baseConfig = resolveTransformStyle(styleId);\n const config = options?.overrides\n ? { ...baseConfig, ...options.overrides, id: baseConfig.id }\n : baseConfig;\n\n const seed = options?.seed ?? hashString(doc.articleId || 'transform');\n\n // Use provided images or auto-extract from the doc's markdown content\n const images = options?.images ?? extractDocImages(doc.blocks);\n\n // 1. Analyze blocks\n const analyzed = analyzeBlocks(doc.blocks, {\n minConfidence: config.minConfidence,\n types: config.preferredTypes,\n });\n\n // If no blocks have meaningful content, return the doc unchanged\n const hasContent = analyzed.some((ab) => ab.bodyWordCount >= 5);\n if (!hasContent) {\n return {\n doc: { ...doc },\n stats: {\n totalInputBlocks: doc.blocks.length,\n transformedBlocks: 0,\n insertedBlocks: 0,\n },\n };\n }\n\n // 2. Select extractions and build template blocks\n const selection = selectAndBuild(analyzed, config, images, seed);\n\n // 3. Allocate timing across the new block sequence\n const timedBlocks = allocateTiming(selection.blocks, doc.duration);\n\n // 4. Assemble the output Doc\n const transformedDoc: Doc = {\n ...doc,\n blocks: timedBlocks,\n themeId: options?.themeId ?? doc.themeId,\n };\n\n return {\n doc: transformedDoc,\n stats: {\n totalInputBlocks: doc.blocks.length,\n transformedBlocks: selection.transformedCount,\n insertedBlocks: selection.insertedCount,\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -394,6 +394,21 @@ interface MarkdownInlineMath extends MarkdownNodeBase {
|
|
|
394
394
|
/** Math content (without $ delimiters) */
|
|
395
395
|
value: string;
|
|
396
396
|
}
|
|
397
|
+
/**
|
|
398
|
+
* Inline FontAwesome icon. Authored as `{[name]}` (bare) or
|
|
399
|
+
* `{[fa-<family>:name]}` (qualified) in markdown source. The parser
|
|
400
|
+
* resolves the token against the FA Free catalog and emits this node;
|
|
401
|
+
* unknown / ambiguous tokens stay as literal text.
|
|
402
|
+
*/
|
|
403
|
+
interface MarkdownInlineIcon extends MarkdownNodeBase {
|
|
404
|
+
type: 'inlineIcon';
|
|
405
|
+
/** Token exactly as authored — e.g. `github` or `fa-solid:user`. */
|
|
406
|
+
token: string;
|
|
407
|
+
/** Resolved icon family. */
|
|
408
|
+
family: 'brands' | 'solid' | 'regular';
|
|
409
|
+
/** Resolved icon name (without the `fa-` prefix). */
|
|
410
|
+
name: string;
|
|
411
|
+
}
|
|
397
412
|
/**
|
|
398
413
|
* A footnote reference [^id]. GFM extension.
|
|
399
414
|
*/
|
|
@@ -455,7 +470,7 @@ interface MarkdownTextDirective extends MarkdownNodeBase {
|
|
|
455
470
|
*/
|
|
456
471
|
interface MarkdownMention extends MarkdownNodeBase {
|
|
457
472
|
type: 'mention';
|
|
458
|
-
/** Namespace for the mentioned entity (e.g. `"
|
|
473
|
+
/** Namespace for the mentioned entity (e.g. `"user"`). */
|
|
459
474
|
targetKind: string;
|
|
460
475
|
/** Stable identifier within the namespace. */
|
|
461
476
|
targetId: string;
|
|
@@ -465,7 +480,7 @@ interface MarkdownMention extends MarkdownNodeBase {
|
|
|
465
480
|
/** Block-level content that can appear as direct children of the document root, blockquotes, list items, etc. */
|
|
466
481
|
type MarkdownBlockNode = MarkdownHeading | MarkdownParagraph | MarkdownBlockquote | MarkdownList | MarkdownCodeBlock | MarkdownThematicBreak | MarkdownTable | MarkdownHtmlBlock | MarkdownMathBlock | MarkdownLinkDefinition | MarkdownFootnoteDefinition | MarkdownContainerDirective | MarkdownLeafDirective | MarkdownDefinitionList;
|
|
467
482
|
/** Inline/phrasing content that appears inside paragraphs, headings, links, etc. */
|
|
468
|
-
type MarkdownInlineNode = MarkdownText | MarkdownEmphasis | MarkdownStrong | MarkdownStrikethrough | MarkdownInlineCode | MarkdownLink | MarkdownImage | MarkdownBreak | MarkdownInlineHtml | MarkdownInlineMath | MarkdownFootnoteReference | MarkdownLinkReference | MarkdownImageReference | MarkdownTextDirective | MarkdownMention;
|
|
483
|
+
type MarkdownInlineNode = MarkdownText | MarkdownEmphasis | MarkdownStrong | MarkdownStrikethrough | MarkdownInlineCode | MarkdownLink | MarkdownImage | MarkdownBreak | MarkdownInlineHtml | MarkdownInlineMath | MarkdownFootnoteReference | MarkdownLinkReference | MarkdownImageReference | MarkdownTextDirective | MarkdownMention | MarkdownInlineIcon;
|
|
469
484
|
/**
|
|
470
485
|
* Any node in the markdown tree. Includes structural nodes (listItem,
|
|
471
486
|
* tableRow, tableCell, etc.) that only appear as children of specific parents.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public types for the document version-history feature.
|
|
3
|
+
*
|
|
4
|
+
* Versions are snapshots of the primary markdown document stored alongside
|
|
5
|
+
* the document inside the same {@link ContentContainer}. They live under
|
|
6
|
+
* `.versions/<docBasename>.<sortableTimestamp>.md`. The container is the
|
|
7
|
+
* unit of persistence — when the host serializes the container to a ZIP,
|
|
8
|
+
* a real folder, or anywhere else, the version snapshots ride along.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* A single version snapshot record.
|
|
12
|
+
*/
|
|
13
|
+
interface Version {
|
|
14
|
+
/** Container-relative path, e.g. `.versions/index.20260430T152030Z.md`. */
|
|
15
|
+
path: string;
|
|
16
|
+
/** Document basename without extension, e.g. `index`. */
|
|
17
|
+
basename: string;
|
|
18
|
+
/** Parsed timestamp from the filename, in UTC. */
|
|
19
|
+
timestamp: Date;
|
|
20
|
+
/** Snapshot size in bytes. */
|
|
21
|
+
size: number;
|
|
22
|
+
/**
|
|
23
|
+
* Collision suffix index. `0` for a path with no `-N` suffix, `1` for `-2`,
|
|
24
|
+
* `2` for `-3`, and so on. Used as the tie-break for ordering snapshots
|
|
25
|
+
* that share the same UTC second.
|
|
26
|
+
*/
|
|
27
|
+
collision: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Result of a {@link saveVersion} call.
|
|
31
|
+
*/
|
|
32
|
+
interface SaveVersionResult {
|
|
33
|
+
/** True when a new snapshot file was actually written. */
|
|
34
|
+
saved: boolean;
|
|
35
|
+
/** The newly stamped version (only when `saved` is true). */
|
|
36
|
+
version: Version | null;
|
|
37
|
+
/**
|
|
38
|
+
* Why the save behaved the way it did:
|
|
39
|
+
* - `'saved'` — a new snapshot was written.
|
|
40
|
+
* - `'unchanged'` — current content matches the latest snapshot byte-for-byte.
|
|
41
|
+
* - `'no-document'` — the container has no primary markdown document.
|
|
42
|
+
* - `'empty'` — the resolved content was empty.
|
|
43
|
+
*/
|
|
44
|
+
reason: 'saved' | 'unchanged' | 'no-document' | 'empty';
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Options for {@link saveVersion}.
|
|
48
|
+
*/
|
|
49
|
+
interface SaveVersionOptions {
|
|
50
|
+
/** Override the document content; otherwise the container's primary doc is read. */
|
|
51
|
+
content?: string;
|
|
52
|
+
/** Override the timestamp; defaults to `new Date()`. Useful for tests. */
|
|
53
|
+
now?: Date;
|
|
54
|
+
/** Skip the diff-vs-latest check and force a write. */
|
|
55
|
+
force?: boolean;
|
|
56
|
+
/** Override the document basename used to build the version filename. */
|
|
57
|
+
basename?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Pruning policy passed to {@link pruneVersions}.
|
|
61
|
+
*/
|
|
62
|
+
type PrunePolicy = {
|
|
63
|
+
type: 'keep-last-n';
|
|
64
|
+
n: number;
|
|
65
|
+
} | {
|
|
66
|
+
type: 'older-than';
|
|
67
|
+
date: Date;
|
|
68
|
+
} | {
|
|
69
|
+
type: 'predicate';
|
|
70
|
+
keep: (v: Version, all: Version[]) => boolean;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Options for {@link revertToVersion}.
|
|
74
|
+
*/
|
|
75
|
+
interface RevertOptions {
|
|
76
|
+
/**
|
|
77
|
+
* Whether to snapshot the current document content before replacing it.
|
|
78
|
+
* Defaults to `true` so a revert is always recoverable.
|
|
79
|
+
*/
|
|
80
|
+
snapshotCurrent?: boolean;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Options for {@link coalesceVersions}.
|
|
84
|
+
*/
|
|
85
|
+
interface CoalesceOptions {
|
|
86
|
+
/**
|
|
87
|
+
* Two adjacent snapshots whose timestamps are within `windowMs` collapse
|
|
88
|
+
* to the newer one. Defaults to 60_000 (one minute).
|
|
89
|
+
*/
|
|
90
|
+
windowMs?: number;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type { CoalesceOptions as C, PrunePolicy as P, RevertOptions as R, SaveVersionOptions as S, Version as V, SaveVersionResult as a };
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { C as CoalesceOptions, V as Version, P as PrunePolicy, R as RevertOptions, S as SaveVersionOptions, a as SaveVersionResult } from '../types-D98li1gV.js';
|
|
2
|
+
import { C as ContentContainer } from '../ContentContainer-DNx460y8.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Pure-ish version operations against a {@link ContentContainer}.
|
|
6
|
+
*
|
|
7
|
+
* These functions are the canonical implementation. {@link DocumentVersionManager}
|
|
8
|
+
* is a thin wrapper that captures a container reference for ergonomics.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* List all snapshots in the container, newest-first.
|
|
13
|
+
*
|
|
14
|
+
* @param basename Optional filter: when set, only versions whose basename
|
|
15
|
+
* matches are returned.
|
|
16
|
+
*/
|
|
17
|
+
declare function listVersions(container: ContentContainer, basename?: string): Promise<Version[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Read the markdown content of a snapshot. Returns null if the snapshot
|
|
20
|
+
* doesn't exist.
|
|
21
|
+
*/
|
|
22
|
+
declare function readVersion(container: ContentContainer, version: Version | string): Promise<string | null>;
|
|
23
|
+
/**
|
|
24
|
+
* Save a new snapshot of the document if its content differs from the
|
|
25
|
+
* latest existing snapshot.
|
|
26
|
+
*/
|
|
27
|
+
declare function saveVersion(container: ContentContainer, options?: SaveVersionOptions): Promise<SaveVersionResult>;
|
|
28
|
+
/**
|
|
29
|
+
* Revert the document to a prior snapshot. By default, the *current*
|
|
30
|
+
* document is snapshotted first so the revert is itself recoverable.
|
|
31
|
+
*/
|
|
32
|
+
declare function revertToVersion(container: ContentContainer, version: Version | string, options?: RevertOptions): Promise<{
|
|
33
|
+
reverted: boolean;
|
|
34
|
+
snapshotted: Version | null;
|
|
35
|
+
}>;
|
|
36
|
+
/**
|
|
37
|
+
* Delete snapshots that don't satisfy the policy. Returns the deleted
|
|
38
|
+
* versions in their original (newest-first) order.
|
|
39
|
+
*/
|
|
40
|
+
declare function pruneVersions(container: ContentContainer, policy: PrunePolicy, basename?: string): Promise<Version[]>;
|
|
41
|
+
/**
|
|
42
|
+
* Collapse adjacent snapshots that occurred close together — keeping the
|
|
43
|
+
* newer one — to keep history readable across rapid edits.
|
|
44
|
+
*/
|
|
45
|
+
declare function coalesceVersions(container: ContentContainer, options?: CoalesceOptions, basename?: string): Promise<Version[]>;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Convenience wrapper around the version operations that captures a
|
|
49
|
+
* {@link ContentContainer} reference and an optional basename override.
|
|
50
|
+
*
|
|
51
|
+
* Hosts that prefer a stable handle (e.g. to pass into a UI component)
|
|
52
|
+
* use this; everything it does is also reachable as a free function.
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
interface DocumentVersionManagerOptions {
|
|
56
|
+
/**
|
|
57
|
+
* Override the document basename used in version filenames. Defaults to
|
|
58
|
+
* the basename of `container.getDocumentPath()` resolved at call time.
|
|
59
|
+
*/
|
|
60
|
+
basename?: string;
|
|
61
|
+
}
|
|
62
|
+
declare class DocumentVersionManager {
|
|
63
|
+
private readonly container;
|
|
64
|
+
private readonly basename;
|
|
65
|
+
constructor(container: ContentContainer, options?: DocumentVersionManagerOptions);
|
|
66
|
+
saveVersion(options?: SaveVersionOptions): Promise<SaveVersionResult>;
|
|
67
|
+
listVersions(): Promise<Version[]>;
|
|
68
|
+
readVersion(version: Version | string): Promise<string | null>;
|
|
69
|
+
revertToVersion(version: Version | string, options?: RevertOptions): Promise<{
|
|
70
|
+
reverted: boolean;
|
|
71
|
+
snapshotted: Version | null;
|
|
72
|
+
}>;
|
|
73
|
+
pruneVersions(policy: PrunePolicy): Promise<Version[]>;
|
|
74
|
+
coalesceVersions(options?: CoalesceOptions): Promise<Version[]>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Sortable, human-readable timestamps for version filenames.
|
|
79
|
+
*
|
|
80
|
+
* Format: ISO 8601 basic, UTC, second precision, `Z` suffix —
|
|
81
|
+
* e.g. `20260430T152030Z`. Lexicographic order matches chronological order,
|
|
82
|
+
* so `listFiles` returns versions in time order without parsing.
|
|
83
|
+
*/
|
|
84
|
+
/**
|
|
85
|
+
* Format a Date as a sortable, filename-safe UTC timestamp string.
|
|
86
|
+
*/
|
|
87
|
+
declare function formatVersionTimestamp(date: Date): string;
|
|
88
|
+
/**
|
|
89
|
+
* Parse a version timestamp string back to a Date. Returns null if the input
|
|
90
|
+
* doesn't match the expected format.
|
|
91
|
+
*/
|
|
92
|
+
declare function parseVersionTimestamp(stamp: string): Date | null;
|
|
93
|
+
/**
|
|
94
|
+
* The pattern a valid version timestamp matches. Exported so other modules
|
|
95
|
+
* can validate filenames without re-deriving the regex.
|
|
96
|
+
*/
|
|
97
|
+
declare const VERSION_TIMESTAMP_PATTERN: RegExp;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Path conventions for version snapshots.
|
|
101
|
+
*
|
|
102
|
+
* Snapshots live at `<VERSIONS_PREFIX><basename>.<timestamp>[<-suffix>].md`.
|
|
103
|
+
* The optional numeric suffix (`-2`, `-3`, ...) is appended only when two
|
|
104
|
+
* snapshots collide on the same UTC second.
|
|
105
|
+
*/
|
|
106
|
+
/** Subfolder (inside the ContentContainer) that holds version snapshots. */
|
|
107
|
+
declare const VERSIONS_PREFIX = ".versions/";
|
|
108
|
+
/**
|
|
109
|
+
* Strip the directory and extension from a document path to produce the
|
|
110
|
+
* basename used in version filenames. `subdir/index.md` -> `index`.
|
|
111
|
+
*/
|
|
112
|
+
declare function getDocBasename(documentPath: string): string;
|
|
113
|
+
/**
|
|
114
|
+
* Build a version snapshot path. Optionally append a collision suffix
|
|
115
|
+
* (e.g. `2`, `3`) when two saves land on the same UTC second.
|
|
116
|
+
*/
|
|
117
|
+
declare function buildVersionPath(basename: string, date: Date, collision?: number): string;
|
|
118
|
+
/**
|
|
119
|
+
* Parse a version snapshot path. Returns null if it doesn't match the
|
|
120
|
+
* convention (so unrelated files stored under `.versions/` are ignored).
|
|
121
|
+
*/
|
|
122
|
+
declare function parseVersionPath(path: string): {
|
|
123
|
+
basename: string;
|
|
124
|
+
timestamp: Date;
|
|
125
|
+
collision: number;
|
|
126
|
+
} | null;
|
|
127
|
+
|
|
128
|
+
export { CoalesceOptions, DocumentVersionManager, type DocumentVersionManagerOptions, PrunePolicy, RevertOptions, SaveVersionOptions, SaveVersionResult, VERSIONS_PREFIX, VERSION_TIMESTAMP_PATTERN, Version, buildVersionPath, coalesceVersions, formatVersionTimestamp, getDocBasename, listVersions, parseVersionPath, parseVersionTimestamp, pruneVersions, readVersion, revertToVersion, saveVersion };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DocumentVersionManager,
|
|
3
|
+
VERSIONS_PREFIX,
|
|
4
|
+
buildVersionPath,
|
|
5
|
+
coalesceVersions,
|
|
6
|
+
getDocBasename,
|
|
7
|
+
listVersions,
|
|
8
|
+
parseVersionPath,
|
|
9
|
+
pruneVersions,
|
|
10
|
+
readVersion,
|
|
11
|
+
revertToVersion,
|
|
12
|
+
saveVersion
|
|
13
|
+
} from "../chunk-VLJJHDAC.js";
|
|
14
|
+
import {
|
|
15
|
+
VERSION_TIMESTAMP_PATTERN,
|
|
16
|
+
formatVersionTimestamp,
|
|
17
|
+
parseVersionTimestamp
|
|
18
|
+
} from "../chunk-JELIRVDP.js";
|
|
19
|
+
export {
|
|
20
|
+
DocumentVersionManager,
|
|
21
|
+
VERSIONS_PREFIX,
|
|
22
|
+
VERSION_TIMESTAMP_PATTERN,
|
|
23
|
+
buildVersionPath,
|
|
24
|
+
coalesceVersions,
|
|
25
|
+
formatVersionTimestamp,
|
|
26
|
+
getDocBasename,
|
|
27
|
+
listVersions,
|
|
28
|
+
parseVersionPath,
|
|
29
|
+
parseVersionTimestamp,
|
|
30
|
+
pruneVersions,
|
|
31
|
+
readVersion,
|
|
32
|
+
revertToVersion,
|
|
33
|
+
saveVersion
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bendyline/squisq",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "Headless utilities for doc/block rendering, spatial math, Markdown, and storage",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bendyline",
|
|
@@ -85,13 +85,40 @@
|
|
|
85
85
|
"types": "./dist/transform/index.d.ts",
|
|
86
86
|
"import": "./dist/transform/index.js",
|
|
87
87
|
"default": "./dist/transform/index.js"
|
|
88
|
+
},
|
|
89
|
+
"./versions": {
|
|
90
|
+
"types": "./dist/versions/index.d.ts",
|
|
91
|
+
"import": "./dist/versions/index.js",
|
|
92
|
+
"default": "./dist/versions/index.js"
|
|
93
|
+
},
|
|
94
|
+
"./jsonForm": {
|
|
95
|
+
"types": "./dist/jsonForm/index.d.ts",
|
|
96
|
+
"import": "./dist/jsonForm/index.js",
|
|
97
|
+
"default": "./dist/jsonForm/index.js"
|
|
98
|
+
},
|
|
99
|
+
"./imageEdit": {
|
|
100
|
+
"types": "./dist/imageEdit/index.d.ts",
|
|
101
|
+
"import": "./dist/imageEdit/index.js",
|
|
102
|
+
"default": "./dist/imageEdit/index.js"
|
|
103
|
+
},
|
|
104
|
+
"./icons": {
|
|
105
|
+
"types": "./dist/icons/index.d.ts",
|
|
106
|
+
"import": "./dist/icons/index.js",
|
|
107
|
+
"default": "./dist/icons/index.js"
|
|
108
|
+
},
|
|
109
|
+
"./recommend": {
|
|
110
|
+
"types": "./dist/recommend/index.d.ts",
|
|
111
|
+
"import": "./dist/recommend/index.js",
|
|
112
|
+
"default": "./dist/recommend/index.js"
|
|
88
113
|
}
|
|
89
114
|
},
|
|
90
115
|
"scripts": {
|
|
91
116
|
"build": "tsup",
|
|
117
|
+
"dev": "concurrently -n js,dts -c blue,gray -r \"tsup --watch --no-dts --no-clean\" \"tsup --watch --dts-only --no-clean\"",
|
|
92
118
|
"typecheck": "tsc --noEmit"
|
|
93
119
|
},
|
|
94
120
|
"dependencies": {
|
|
121
|
+
"genson-js": "0.0.8",
|
|
95
122
|
"hast-util-from-html": "2.0.3",
|
|
96
123
|
"localforage": "1.10.0",
|
|
97
124
|
"ngeohash": "0.6.3",
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
isHex,
|
|
4
|
+
oklchLighten,
|
|
5
|
+
oklchDarken,
|
|
6
|
+
oklchSetChroma,
|
|
7
|
+
contrastRatio,
|
|
8
|
+
pickContrastingText,
|
|
9
|
+
deriveScale,
|
|
10
|
+
relativeLuminance,
|
|
11
|
+
} from '../schemas/colorUtils.js';
|
|
12
|
+
|
|
13
|
+
describe('isHex', () => {
|
|
14
|
+
it('accepts #rgb and #rrggbb', () => {
|
|
15
|
+
expect(isHex('#fff')).toBe(true);
|
|
16
|
+
expect(isHex('#123abc')).toBe(true);
|
|
17
|
+
expect(isHex('#FF0080')).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
it('rejects malformed strings', () => {
|
|
20
|
+
expect(isHex('fff')).toBe(false);
|
|
21
|
+
expect(isHex('#1234')).toBe(false);
|
|
22
|
+
expect(isHex('#xyz')).toBe(false);
|
|
23
|
+
expect(isHex('rgb(0,0,0)')).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('oklchLighten / oklchDarken', () => {
|
|
28
|
+
it('lighten produces a lighter color (higher luminance)', () => {
|
|
29
|
+
const dark = '#101010';
|
|
30
|
+
const lighter = oklchLighten(dark, 0.2);
|
|
31
|
+
expect(relativeLuminance(lighter)).toBeGreaterThan(relativeLuminance(dark));
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('darken produces a darker color (lower luminance)', () => {
|
|
35
|
+
const light = '#e0e0e0';
|
|
36
|
+
const darker = oklchDarken(light, 0.2);
|
|
37
|
+
expect(relativeLuminance(darker)).toBeLessThan(relativeLuminance(light));
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('round-trips approximately stable for moderate adjustments', () => {
|
|
41
|
+
const seed = '#3182ce';
|
|
42
|
+
const round = oklchDarken(oklchLighten(seed, 0.1), 0.1);
|
|
43
|
+
// sRGB gamut clamping prevents perfect round-trip; expect within a small epsilon.
|
|
44
|
+
expect(round).toMatch(/^#[0-9a-f]{6}$/);
|
|
45
|
+
const lumDiff = Math.abs(relativeLuminance(seed) - relativeLuminance(round));
|
|
46
|
+
expect(lumDiff).toBeLessThan(0.05);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('returns a hex string', () => {
|
|
50
|
+
expect(oklchLighten('#3182ce', 0.1)).toMatch(/^#[0-9a-f]{6}$/);
|
|
51
|
+
expect(oklchDarken('#3182ce', 0.1)).toMatch(/^#[0-9a-f]{6}$/);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('falls back to input on parse failure', () => {
|
|
55
|
+
expect(oklchLighten('not-a-color', 0.1)).toBe('not-a-color');
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('oklchSetChroma', () => {
|
|
60
|
+
it('reducing chroma toward 0 desaturates a color', () => {
|
|
61
|
+
const vivid = '#ff3366';
|
|
62
|
+
const muted = oklchSetChroma(vivid, 0.1);
|
|
63
|
+
// Muted version's R/G/B channels should be much closer to each other than vivid.
|
|
64
|
+
const parse = (h: string) => [
|
|
65
|
+
parseInt(h.slice(1, 3), 16),
|
|
66
|
+
parseInt(h.slice(3, 5), 16),
|
|
67
|
+
parseInt(h.slice(5, 7), 16),
|
|
68
|
+
];
|
|
69
|
+
const [vr, vg, vb] = parse(vivid);
|
|
70
|
+
const [mr, mg, mb] = parse(muted);
|
|
71
|
+
const vSpread = Math.max(vr, vg, vb) - Math.min(vr, vg, vb);
|
|
72
|
+
const mSpread = Math.max(mr, mg, mb) - Math.min(mr, mg, mb);
|
|
73
|
+
expect(mSpread).toBeLessThan(vSpread);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('contrastRatio', () => {
|
|
78
|
+
it('white-on-black is the maximum (≈21)', () => {
|
|
79
|
+
expect(contrastRatio('#ffffff', '#000000')).toBeCloseTo(21, 0);
|
|
80
|
+
});
|
|
81
|
+
it('same-color is 1', () => {
|
|
82
|
+
expect(contrastRatio('#aabbcc', '#aabbcc')).toBeCloseTo(1, 5);
|
|
83
|
+
});
|
|
84
|
+
it('is symmetric', () => {
|
|
85
|
+
expect(contrastRatio('#222', '#ddd')).toBeCloseTo(contrastRatio('#ddd', '#222'), 5);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe('pickContrastingText', () => {
|
|
90
|
+
it('returns dark text for light backgrounds', () => {
|
|
91
|
+
expect(pickContrastingText('#ffffff')).toBe('#1a202c');
|
|
92
|
+
expect(pickContrastingText('#f7fafc')).toBe('#1a202c');
|
|
93
|
+
});
|
|
94
|
+
it('returns light text for dark backgrounds', () => {
|
|
95
|
+
expect(pickContrastingText('#000000')).toBe('#f7fafc');
|
|
96
|
+
expect(pickContrastingText('#1a202c')).toBe('#f7fafc');
|
|
97
|
+
});
|
|
98
|
+
it('respects custom light/dark options', () => {
|
|
99
|
+
expect(pickContrastingText('#000000', '#fefefe', '#020202')).toBe('#fefefe');
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
describe('deriveScale', () => {
|
|
104
|
+
it('produces 5 stops with base in the middle', () => {
|
|
105
|
+
const scale = deriveScale('#3182ce', 0.15);
|
|
106
|
+
expect(scale.base).toBe('#3182ce');
|
|
107
|
+
expect(relativeLuminance(scale.lighter2)).toBeGreaterThan(relativeLuminance(scale.lighter1));
|
|
108
|
+
expect(relativeLuminance(scale.lighter1)).toBeGreaterThan(relativeLuminance(scale.base));
|
|
109
|
+
expect(relativeLuminance(scale.base)).toBeGreaterThan(relativeLuminance(scale.darker1));
|
|
110
|
+
expect(relativeLuminance(scale.darker1)).toBeGreaterThan(relativeLuminance(scale.darker2));
|
|
111
|
+
});
|
|
112
|
+
});
|
|
@@ -11,7 +11,7 @@ import type { Block, Layer, TextLayer, ShapeLayer } from '../schemas/Doc.js';
|
|
|
11
11
|
|
|
12
12
|
function makeTemplateBlock(overrides: Partial<TemplateBlock> = {}): TemplateBlock {
|
|
13
13
|
return {
|
|
14
|
-
template: '
|
|
14
|
+
template: 'title',
|
|
15
15
|
id: 'test-title-1',
|
|
16
16
|
duration: 5,
|
|
17
17
|
audioSegment: 0,
|
|
@@ -43,7 +43,7 @@ const defaultContext: RenderContext = {
|
|
|
43
43
|
|
|
44
44
|
describe('getLayers', () => {
|
|
45
45
|
it('generates layers for a known template block', () => {
|
|
46
|
-
const block = makeTemplateBlock({ template: '
|
|
46
|
+
const block = makeTemplateBlock({ template: 'title', title: 'Test Title' });
|
|
47
47
|
const layers = getLayers(block, defaultContext);
|
|
48
48
|
|
|
49
49
|
expect(Array.isArray(layers)).toBe(true);
|
|
@@ -83,6 +83,31 @@ describe('getLayers', () => {
|
|
|
83
83
|
expect(layers).toEqual(existingLayers);
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
+
it('resolves legacy template aliases through TEMPLATE_ALIASES', () => {
|
|
87
|
+
// Regression: `getLayers` previously did `block.template in templateRegistry`
|
|
88
|
+
// without alias resolution, so docs authored with the legacy long ids
|
|
89
|
+
// (`titleBlock`, `quoteBlock`, `mapBlock`, `listBlock`) rendered as
|
|
90
|
+
// empty SVG cards in the linear/document view — `hasTemplate()` accepts
|
|
91
|
+
// the alias, so `isAnnotatedBlock` returns true and the card wrapper
|
|
92
|
+
// renders, but the registry lookup below would miss the alias and the
|
|
93
|
+
// layer array came back empty.
|
|
94
|
+
const aliasedToCanonical: Array<[string, string]> = [
|
|
95
|
+
['titleBlock', 'title'],
|
|
96
|
+
['quoteBlock', 'quote'],
|
|
97
|
+
['listBlock', 'list'],
|
|
98
|
+
];
|
|
99
|
+
for (const [alias] of aliasedToCanonical) {
|
|
100
|
+
const block = makeTemplateBlock({
|
|
101
|
+
template: alias as TemplateBlock['template'],
|
|
102
|
+
title: 'Aliased',
|
|
103
|
+
items: ['a', 'b', 'c'],
|
|
104
|
+
quote: 'q',
|
|
105
|
+
} as Partial<TemplateBlock>);
|
|
106
|
+
const layers = getLayers(block, defaultContext);
|
|
107
|
+
expect(layers.length).toBeGreaterThan(0);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
86
111
|
it('returns empty array for unknown template', () => {
|
|
87
112
|
const block = {
|
|
88
113
|
template: 'totally_nonexistent',
|
|
@@ -103,7 +128,7 @@ describe('getLayers', () => {
|
|
|
103
128
|
});
|
|
104
129
|
|
|
105
130
|
it('uses default context values when context is omitted', () => {
|
|
106
|
-
const block = makeTemplateBlock({ template: '
|
|
131
|
+
const block = makeTemplateBlock({ template: 'title', title: 'Defaults' });
|
|
107
132
|
const layers = getLayers(block);
|
|
108
133
|
|
|
109
134
|
expect(Array.isArray(layers)).toBe(true);
|
|
@@ -147,7 +172,7 @@ describe('getLayers', () => {
|
|
|
147
172
|
};
|
|
148
173
|
|
|
149
174
|
it('injects persistent bottom and top layers around block layers', () => {
|
|
150
|
-
const block = makeTemplateBlock({ template: '
|
|
175
|
+
const block = makeTemplateBlock({ template: 'title', title: 'With Persistent' });
|
|
151
176
|
const layers = getLayers(block, { ...defaultContext, persistentLayers: persistentConfig });
|
|
152
177
|
|
|
153
178
|
// First layer should be the bottom persistent layer
|
|
@@ -160,7 +185,7 @@ describe('getLayers', () => {
|
|
|
160
185
|
|
|
161
186
|
it('respects useBottomLayer: false opt-out', () => {
|
|
162
187
|
const block = makeTemplateBlock({
|
|
163
|
-
template: '
|
|
188
|
+
template: 'title',
|
|
164
189
|
title: 'No Bottom',
|
|
165
190
|
useBottomLayer: false,
|
|
166
191
|
});
|
|
@@ -174,7 +199,7 @@ describe('getLayers', () => {
|
|
|
174
199
|
|
|
175
200
|
it('respects useTopLayer: false opt-out', () => {
|
|
176
201
|
const block = makeTemplateBlock({
|
|
177
|
-
template: '
|
|
202
|
+
template: 'title',
|
|
178
203
|
title: 'No Top',
|
|
179
204
|
useTopLayer: false,
|
|
180
205
|
});
|
|
@@ -187,7 +212,7 @@ describe('getLayers', () => {
|
|
|
187
212
|
});
|
|
188
213
|
|
|
189
214
|
it('skips injection when no persistent layers are configured', () => {
|
|
190
|
-
const block = makeTemplateBlock({ template: '
|
|
215
|
+
const block = makeTemplateBlock({ template: 'title', title: 'No Persistent' });
|
|
191
216
|
const withoutPersistent = getLayers(block, defaultContext);
|
|
192
217
|
const withEmptyPersistent = getLayers(block, {
|
|
193
218
|
...defaultContext,
|