@bendyline/squisq 1.4.1 → 1.5.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/README.md +14 -1
- package/dist/{ContentContainer-DNx460y8.d.ts → ContentContainer-BXUlIf18.d.ts} +6 -2
- package/dist/{Doc-BeSeH2iX.d.ts → Doc-BBVGq1_9.d.ts} +922 -273
- package/dist/{ImageEditDoc-BTIvw0oq.d.ts → ImageEditDoc-FuyGtt6o.d.ts} +11 -4
- package/dist/{chunk-ZTX4PFFT.js → chunk-2OIBZYKP.js} +75 -2
- package/dist/chunk-2OIBZYKP.js.map +1 -0
- package/dist/chunk-2UQOHYE2.js +45 -0
- package/dist/chunk-2UQOHYE2.js.map +1 -0
- package/dist/chunk-6ATE2PSM.js +344 -0
- package/dist/chunk-6ATE2PSM.js.map +1 -0
- package/dist/{chunk-57CVQCFX.js → chunk-A4O7GIWE.js} +74 -23
- package/dist/chunk-A4O7GIWE.js.map +1 -0
- package/dist/{chunk-5WFRKURX.js → chunk-DLXZMS5K.js} +4 -2
- package/dist/chunk-DLXZMS5K.js.map +1 -0
- package/dist/chunk-ET53IIEP.js +1 -0
- package/dist/chunk-ET53IIEP.js.map +1 -0
- package/dist/chunk-HWVFJAAH.js +362 -0
- package/dist/chunk-HWVFJAAH.js.map +1 -0
- package/dist/{chunk-2TMAWB4Y.js → chunk-IMSCRLLV.js} +1 -1
- package/dist/chunk-IMSCRLLV.js.map +1 -0
- package/dist/{chunk-B4EEON3N.js → chunk-KKNUBQ6Y.js} +536 -103
- package/dist/chunk-KKNUBQ6Y.js.map +1 -0
- package/dist/chunk-LDQ2HJIX.js +596 -0
- package/dist/chunk-LDQ2HJIX.js.map +1 -0
- package/dist/chunk-LH7I6SH7.js +7208 -0
- package/dist/chunk-LH7I6SH7.js.map +1 -0
- package/dist/chunk-PGGGKYWG.js +1 -0
- package/dist/chunk-PGGGKYWG.js.map +1 -0
- package/dist/{chunk-7UDSRZKG.js → chunk-Q3ROPT5H.js} +35 -14
- package/dist/chunk-Q3ROPT5H.js.map +1 -0
- package/dist/chunk-QE7TWGVT.js +178 -0
- package/dist/chunk-QE7TWGVT.js.map +1 -0
- package/dist/chunk-RUDYOTA6.js +345 -0
- package/dist/chunk-RUDYOTA6.js.map +1 -0
- package/dist/{chunk-K32VJONL.js → chunk-T5UK6YOB.js} +41 -2
- package/dist/chunk-T5UK6YOB.js.map +1 -0
- package/dist/{chunk-3K5OG6KI.js → chunk-TEEEILMP.js} +412 -186
- package/dist/chunk-TEEEILMP.js.map +1 -0
- package/dist/{chunk-FR2RBTKO.js → chunk-TQWLI6S2.js} +93 -27
- package/dist/chunk-TQWLI6S2.js.map +1 -0
- package/dist/{chunk-WMOI7FN3.js → chunk-UY7KGQ5R.js} +12 -2
- package/dist/{chunk-WMOI7FN3.js.map → chunk-UY7KGQ5R.js.map} +1 -1
- package/dist/{chunk-3E5F2XMR.js → chunk-VWUFZ6ZG.js} +29 -2
- package/dist/chunk-VWUFZ6ZG.js.map +1 -0
- package/dist/chunk-ZLQKNOZQ.js +1 -0
- package/dist/chunk-ZLQKNOZQ.js.map +1 -0
- package/dist/doc/index.d.ts +5 -5
- package/dist/doc/index.js +135 -8
- package/dist/generate/index.d.ts +3 -74
- package/dist/generate/index.js +2 -7
- package/dist/icons/index.d.ts +3 -26
- package/dist/icons/index.js +13 -0
- package/dist/icons/inlineIconMarker.d.ts +1 -0
- package/dist/icons/inlineIconMarker.js +15 -0
- package/dist/icons/inlineIconMarker.js.map +1 -0
- package/dist/imageEdit/index.d.ts +12 -6
- package/dist/imageEdit/index.js +4 -1
- package/dist/index.d.ts +14 -11
- package/dist/index.js +265 -37
- package/dist/inlineIconMarker-CiE8Hlvz.d.ts +59 -0
- package/dist/jsonForm/index.d.ts +42 -1
- package/dist/jsonForm/index.js +9 -1
- package/dist/markdown/index.d.ts +228 -3
- package/dist/markdown/index.js +42 -7
- package/dist/recommend/index.d.ts +1 -1
- package/dist/recommend/index.js +3 -2
- package/dist/schemas/index.d.ts +28 -8
- package/dist/schemas/index.js +36 -8
- package/dist/spatial/index.d.ts +9 -4
- package/dist/spatial/index.js +1 -1
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/index.js +1 -1
- package/dist/story/index.d.ts +1021 -41
- package/dist/story/index.js +135 -8
- package/dist/{themeLibrary-BHjJ0Qx6.d.ts → themeLibrary-CehcJhzz.d.ts} +1 -1
- package/dist/timing/index.js +3 -5
- package/dist/transform/index.d.ts +48 -10
- package/dist/transform/index.js +17 -481
- package/dist/transform/index.js.map +1 -1
- package/dist/{types-BdZkdJ3z.d.ts → types-DlAZ7MW4.d.ts} +115 -1
- package/dist/versions/index.d.ts +1 -1
- package/package.json +6 -1
- package/src/__tests__/animationUtils.test.ts +40 -0
- package/src/__tests__/annotationCoercion.test.ts +243 -0
- package/src/__tests__/applyRenderStyle.test.ts +146 -0
- package/src/__tests__/atmosphereLayers.test.ts +108 -0
- package/src/__tests__/attrTokens.test.ts +162 -0
- package/src/__tests__/contentExtractor.test.ts +60 -0
- package/src/__tests__/coverBlock.test.ts +46 -1
- package/src/__tests__/customTemplateSample.test.ts +144 -0
- package/src/__tests__/customTemplatesFrontmatter.test.ts +236 -0
- package/src/__tests__/customThemesFrontmatter.test.ts +145 -0
- package/src/__tests__/diagramBlock.test.ts +122 -0
- package/src/__tests__/diagramLayout.test.ts +134 -0
- package/src/__tests__/drawing.test.ts +109 -0
- package/src/__tests__/drawingBlock.test.ts +124 -0
- package/src/__tests__/drawingLayout.test.ts +171 -0
- package/src/__tests__/geohash.test.ts +6 -5
- package/src/__tests__/getLayers.test.ts +6 -2
- package/src/__tests__/getLayersFallback.test.ts +103 -0
- package/src/__tests__/imageEditExportSvg.test.ts +70 -0
- package/src/__tests__/imageEditVersions.test.ts +72 -0
- package/src/__tests__/inlineIconMarker.test.ts +36 -0
- package/src/__tests__/inputDescriptors.test.ts +162 -0
- package/src/__tests__/jsonForm.tokens.test.ts +84 -0
- package/src/__tests__/layoutBlock.test.ts +83 -0
- package/src/__tests__/layoutLayout.test.ts +169 -0
- package/src/__tests__/markdown.test.ts +87 -0
- package/src/__tests__/markdownSanitize.test.ts +79 -0
- package/src/__tests__/markdownToDoc.test.ts +391 -2
- package/src/__tests__/mediaAnnotations.test.ts +91 -0
- package/src/__tests__/mediaSchedule.test.ts +118 -0
- package/src/__tests__/pandocAttrParse.test.ts +187 -0
- package/src/__tests__/resolveDocTheme.test.ts +55 -0
- package/src/__tests__/rootExports.test.ts +43 -0
- package/src/__tests__/shapeGeometry.test.ts +89 -0
- package/src/__tests__/shapeVocabulary.test.ts +133 -0
- package/src/__tests__/structuredData.test.ts +249 -0
- package/src/__tests__/templateAnnotationParse.test.ts +108 -0
- package/src/__tests__/templateMetadata.test.ts +31 -0
- package/src/__tests__/templates.test.ts +257 -4
- package/src/__tests__/themeCompile.test.ts +42 -0
- package/src/__tests__/themeValidator.test.ts +6 -0
- package/src/__tests__/transformV2.test.ts +137 -0
- package/src/__tests__/transitionNormalize.test.ts +61 -0
- package/src/__tests__/validateDoc.test.ts +260 -0
- package/src/doc/annotationBlocks.ts +117 -0
- package/src/doc/customTemplatesFrontmatter.ts +314 -0
- package/src/doc/customThemesFrontmatter.ts +95 -0
- package/src/doc/docToMarkdown.ts +104 -5
- package/src/doc/getLayers.ts +49 -17
- package/src/doc/index.ts +47 -1
- package/src/doc/markdownToDoc.ts +411 -13
- package/src/doc/mediaAnnotations.ts +100 -0
- package/src/doc/resolveDocTheme.ts +55 -0
- package/src/doc/standaloneAnnotation.ts +58 -0
- package/src/doc/structuredData.ts +301 -0
- package/src/doc/templateInputs.ts +240 -0
- package/src/doc/templates/__tests__/customTemplate.test.ts +170 -0
- package/src/doc/templates/__tests__/customTemplateRegistry.test.ts +110 -0
- package/src/doc/templates/accentImage.ts +30 -6
- package/src/doc/templates/captionUtils.ts +23 -0
- package/src/doc/templates/comparisonBar.ts +33 -18
- package/src/doc/templates/coverBlock.ts +35 -5
- package/src/doc/templates/customTemplate.ts +51 -0
- package/src/doc/templates/dataTable.ts +37 -19
- package/src/doc/templates/dateEvent.ts +41 -20
- package/src/doc/templates/definitionCard.ts +26 -18
- package/src/doc/templates/diagramBlock.ts +204 -0
- package/src/doc/templates/diagramLayout.ts +159 -0
- package/src/doc/templates/drawingBlock.ts +325 -0
- package/src/doc/templates/drawingLayout.ts +539 -0
- package/src/doc/templates/factCard.ts +54 -26
- package/src/doc/templates/fallbackBlock.ts +123 -0
- package/src/doc/templates/featureBlock.ts +20 -13
- package/src/doc/templates/fullBleedQuote.ts +18 -8
- package/src/doc/templates/imageWithCaption.ts +30 -15
- package/src/doc/templates/index.ts +225 -46
- package/src/doc/templates/inputDescriptors.ts +432 -0
- package/src/doc/templates/layoutBlock.ts +43 -0
- package/src/doc/templates/layoutLayout.ts +243 -0
- package/src/doc/templates/listBlock.ts +56 -30
- package/src/doc/templates/mapBlock.ts +15 -12
- package/src/doc/templates/metadata.ts +120 -0
- package/src/doc/templates/persistentLayers.ts +129 -11
- package/src/doc/templates/photoGrid.ts +22 -34
- package/src/doc/templates/pullQuote.ts +30 -12
- package/src/doc/templates/quoteBlock.ts +54 -29
- package/src/doc/templates/sectionHeader.ts +25 -11
- package/src/doc/templates/statHighlight.ts +39 -22
- package/src/doc/templates/titleBlock.ts +59 -21
- package/src/doc/templates/tokens/__tests__/resolveTokens.test.ts +487 -0
- package/src/doc/templates/tokens/resolveTokens.ts +453 -0
- package/src/doc/templates/twoColumn.ts +48 -30
- package/src/doc/templates/videoPullQuote.ts +22 -12
- package/src/doc/templates/videoWithCaption.ts +21 -15
- package/src/doc/utils/animationUtils.ts +267 -3
- package/src/doc/utils/applyRenderStyle.ts +113 -0
- package/src/doc/utils/imageTreatment.ts +70 -0
- package/src/doc/utils/nearest.ts +59 -0
- package/src/doc/utils/shapeGeometry.ts +464 -0
- package/src/doc/utils/themeUtils.ts +75 -1
- package/src/doc/validate.ts +575 -0
- package/src/generate/contentExtractor.ts +148 -35
- package/src/generate/index.ts +0 -3
- package/src/icons/index.ts +8 -0
- package/src/icons/inlineIconMarker.ts +73 -0
- package/src/imageEdit/export.ts +85 -2
- package/src/imageEdit/index.ts +1 -0
- package/src/imageEdit/persistence.ts +51 -0
- package/src/index.ts +2 -0
- package/src/jsonForm/index.ts +2 -0
- package/src/jsonForm/tokens.ts +78 -0
- package/src/markdown/annotationCoercion.ts +295 -0
- package/src/markdown/attrTokens.ts +241 -0
- package/src/markdown/convert.ts +229 -26
- package/src/markdown/index.ts +37 -0
- package/src/markdown/sanitize.ts +318 -0
- package/src/markdown/stringify.ts +96 -6
- package/src/markdown/types.ts +66 -0
- package/src/markdown/utils.ts +111 -2
- package/src/recommend/templates.ts +24 -0
- package/src/schemas/BlockTemplates.ts +133 -4
- package/src/schemas/CustomTemplates.ts +126 -0
- package/src/schemas/Doc.ts +387 -65
- package/src/schemas/ImageEditDoc.ts +11 -4
- package/src/schemas/Media.ts +169 -0
- package/src/schemas/Theme.ts +23 -1
- package/src/schemas/Transitions.ts +224 -0
- package/src/schemas/colorUtils.ts +33 -0
- package/src/schemas/fontStacks.ts +5 -2
- package/src/schemas/index.ts +3 -0
- package/src/schemas/themeCompile.ts +24 -5
- package/src/schemas/themeValidator.ts +49 -11
- package/src/schemas/themes/cinematic.json +69 -12
- package/src/schemas/themes/documentary.json +58 -11
- package/src/schemas/themes/gezellig.json +60 -11
- package/src/schemas/themes/magazine.json +54 -9
- package/src/schemas/themes/morning-light.json +52 -9
- package/src/schemas/themes/standard-dark.json +48 -13
- package/src/schemas/themes/standard.json +44 -12
- package/src/schemas/themes/tech-dark.json +65 -12
- package/src/spatial/Geohash.ts +52 -21
- package/src/storage/ContentContainer.ts +6 -2
- package/src/transform/applyTransform.ts +43 -4
- package/src/transform/index.ts +1 -0
- package/src/transform/registry.ts +44 -13
- package/src/transform/styles/dataDriven.ts +2 -1
- package/src/transform/styles/documentary.ts +2 -1
- package/src/transform/styles/magazine.ts +3 -1
- package/src/transform/styles/minimal.ts +2 -1
- package/src/transform/styles/narrative.ts +3 -1
- package/src/transform/templateSelector.ts +87 -11
- package/src/transform/types.ts +35 -2
- package/dist/chunk-2TMAWB4Y.js.map +0 -1
- package/dist/chunk-3E5F2XMR.js.map +0 -1
- package/dist/chunk-3K5OG6KI.js.map +0 -1
- package/dist/chunk-4X3JQXNM.js +0 -35
- package/dist/chunk-4X3JQXNM.js.map +0 -1
- package/dist/chunk-57CVQCFX.js.map +0 -1
- package/dist/chunk-5WFRKURX.js.map +0 -1
- package/dist/chunk-7UDSRZKG.js.map +0 -1
- package/dist/chunk-B4EEON3N.js.map +0 -1
- package/dist/chunk-FR2RBTKO.js.map +0 -1
- package/dist/chunk-H3AXU4MJ.js +0 -179
- package/dist/chunk-H3AXU4MJ.js.map +0 -1
- package/dist/chunk-K32VJONL.js.map +0 -1
- package/dist/chunk-KSWJR66U.js +0 -3706
- package/dist/chunk-KSWJR66U.js.map +0 -1
- package/dist/chunk-MYIH7FWD.js +0 -145
- package/dist/chunk-MYIH7FWD.js.map +0 -1
- package/dist/chunk-ZTX4PFFT.js.map +0 -1
- package/src/__tests__/slideshowGenerator.test.ts +0 -128
- package/src/generate/slideshowGenerator.ts +0 -273
|
@@ -20,12 +20,23 @@ import type {
|
|
|
20
20
|
PersistentLayerConfig,
|
|
21
21
|
} from '../../schemas/BlockTemplates.js';
|
|
22
22
|
import type { Theme } from '../../schemas/Theme.js';
|
|
23
|
+
import type { CustomTemplateDefinition } from '../../schemas/CustomTemplates.js';
|
|
23
24
|
import { isTemplateBlock, createTemplateContext } from '../../schemas/BlockTemplates.js';
|
|
24
25
|
import { DEFAULT_THEME as defaultTheme } from '../../schemas/themeLibrary.js';
|
|
25
|
-
import { expandPersistentLayers } from './persistentLayers.js';
|
|
26
|
+
import { expandPersistentLayers, wrapWithPersistentLayers } from './persistentLayers.js';
|
|
27
|
+
import { applyRenderStyleToLayers } from '../utils/applyRenderStyle.js';
|
|
28
|
+
import { resolveBlockTransition } from '../../schemas/Transitions.js';
|
|
29
|
+
import { makeCustomTemplateFn } from './customTemplate.js';
|
|
30
|
+
// Coerces inline `{[…]}` string params into typed template input. inputDescriptors
|
|
31
|
+
// imports `resolveTemplateName` from this module in return; the cycle is benign
|
|
32
|
+
// because every cross-reference lives inside a function body, not module init.
|
|
33
|
+
import { coerceTemplateParams } from './inputDescriptors.js';
|
|
26
34
|
import type { ViewportConfig } from '../../schemas/Viewport.js';
|
|
27
35
|
import { VIEWPORT_PRESETS } from '../../schemas/Viewport.js';
|
|
28
36
|
|
|
37
|
+
export { TEMPLATE_METADATA } from './metadata.js';
|
|
38
|
+
export type { TemplateMetadata } from './metadata.js';
|
|
39
|
+
|
|
29
40
|
// Import all template functions
|
|
30
41
|
import { titleBlock } from './titleBlock.js';
|
|
31
42
|
import { sectionHeader } from './sectionHeader.js';
|
|
@@ -46,6 +57,9 @@ import { pullQuote } from './pullQuote.js';
|
|
|
46
57
|
import { videoWithCaption } from './videoWithCaption.js';
|
|
47
58
|
import { videoPullQuote } from './videoPullQuote.js';
|
|
48
59
|
import { dataTable } from './dataTable.js';
|
|
60
|
+
import { diagramBlock } from './diagramBlock.js';
|
|
61
|
+
import { drawingBlock } from './drawingBlock.js';
|
|
62
|
+
import { layoutBlock } from './layoutBlock.js';
|
|
49
63
|
|
|
50
64
|
/**
|
|
51
65
|
* Registry mapping template ids (the strings that appear in
|
|
@@ -82,6 +96,9 @@ export const templateRegistry: TemplateRegistry = {
|
|
|
82
96
|
videoWithCaption,
|
|
83
97
|
videoPullQuote,
|
|
84
98
|
dataTable,
|
|
99
|
+
diagram: diagramBlock,
|
|
100
|
+
layout: layoutBlock,
|
|
101
|
+
drawing: drawingBlock,
|
|
85
102
|
};
|
|
86
103
|
|
|
87
104
|
/**
|
|
@@ -95,6 +112,8 @@ export const TEMPLATE_ALIASES: Readonly<Record<string, string>> = {
|
|
|
95
112
|
quoteBlock: 'quote',
|
|
96
113
|
mapBlock: 'map',
|
|
97
114
|
listBlock: 'list',
|
|
115
|
+
diagramBlock: 'diagram',
|
|
116
|
+
diagramNode: 'diagram',
|
|
98
117
|
};
|
|
99
118
|
|
|
100
119
|
/**
|
|
@@ -105,14 +124,67 @@ export function resolveTemplateName(name: string): string {
|
|
|
105
124
|
return TEMPLATE_ALIASES[name] ?? name;
|
|
106
125
|
}
|
|
107
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Container templates render their parent block by consuming the block's
|
|
129
|
+
* child headings (via `context.children`) — `diagram` draws them as nodes,
|
|
130
|
+
* `drawing` as shapes, `layout` as absolutely-positioned layers. Those
|
|
131
|
+
* children are therefore NOT independently renderable slides/sections;
|
|
132
|
+
* render paths use {@link isContainerTemplate} to skip descending into
|
|
133
|
+
* them (see `flattenRenderableBlocks`).
|
|
134
|
+
*/
|
|
135
|
+
export const CONTAINER_TEMPLATES: ReadonlySet<string> = new Set(['diagram', 'drawing', 'layout']);
|
|
136
|
+
|
|
137
|
+
/** True when `name` (or its alias) is a children-consuming container template. */
|
|
138
|
+
export function isContainerTemplate(name: string | undefined): boolean {
|
|
139
|
+
if (!name) return false;
|
|
140
|
+
return CONTAINER_TEMPLATES.has(resolveTemplateName(name));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Merge user-defined custom templates onto the built-in registry.
|
|
145
|
+
* Built-in names take precedence on collision — a user can't shadow
|
|
146
|
+
* `title` or `diagram` from a custom definition. Returns a frozen view
|
|
147
|
+
* so callers don't accidentally mutate the global registry.
|
|
148
|
+
*/
|
|
149
|
+
export type RuntimeTemplateRegistry = Record<
|
|
150
|
+
string,
|
|
151
|
+
(input: TemplateBlock, ctx: TemplateContext) => Layer[]
|
|
152
|
+
>;
|
|
153
|
+
|
|
154
|
+
export function buildRegistry(
|
|
155
|
+
custom?: readonly CustomTemplateDefinition[],
|
|
156
|
+
): RuntimeTemplateRegistry {
|
|
157
|
+
// The exported `templateRegistry` is a discriminated-union mapped type;
|
|
158
|
+
// we cast through `unknown` because each entry's `input` type is the
|
|
159
|
+
// template-specific variant, not the broad `TemplateBlock` union.
|
|
160
|
+
// The runtime contract — "given any TemplateBlock that resolves to a
|
|
161
|
+
// registered name, the function returns Layer[]" — holds because the
|
|
162
|
+
// expansion path looks up by `template` string before calling.
|
|
163
|
+
const merged: RuntimeTemplateRegistry = {
|
|
164
|
+
...(templateRegistry as unknown as RuntimeTemplateRegistry),
|
|
165
|
+
};
|
|
166
|
+
if (custom) {
|
|
167
|
+
for (const def of custom) {
|
|
168
|
+
if (merged[def.name]) continue; // built-in wins
|
|
169
|
+
merged[def.name] = makeCustomTemplateFn(def) as unknown as RuntimeTemplateRegistry[string];
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return merged;
|
|
173
|
+
}
|
|
174
|
+
|
|
108
175
|
/**
|
|
109
176
|
* Expand a template block into a full Block with layers.
|
|
177
|
+
*
|
|
178
|
+
* `registry` lets callers swap in a registry that includes user-defined
|
|
179
|
+
* custom templates. Defaults to the built-in registry when omitted.
|
|
110
180
|
*/
|
|
111
|
-
export function expandTemplateBlock(
|
|
181
|
+
export function expandTemplateBlock(
|
|
182
|
+
templateBlock: TemplateBlock,
|
|
183
|
+
context: TemplateContext,
|
|
184
|
+
registry: RuntimeTemplateRegistry = templateRegistry as unknown as RuntimeTemplateRegistry,
|
|
185
|
+
): Block {
|
|
112
186
|
const resolved = resolveTemplateName(templateBlock.template);
|
|
113
|
-
const templateFn =
|
|
114
|
-
| ((input: TemplateBlock, ctx: TemplateContext) => Layer[])
|
|
115
|
-
| undefined;
|
|
187
|
+
const templateFn = registry[resolved];
|
|
116
188
|
|
|
117
189
|
if (!templateFn) {
|
|
118
190
|
console.warn(`Unknown template: ${templateBlock.template}`);
|
|
@@ -127,10 +199,25 @@ export function expandTemplateBlock(templateBlock: TemplateBlock, context: Templ
|
|
|
127
199
|
};
|
|
128
200
|
}
|
|
129
201
|
|
|
202
|
+
// Effective template input: the block's own fields, then structured
|
|
203
|
+
// body data (```json data fences / derived auto-template inputs), then
|
|
204
|
+
// `{[…]}` string overrides — the same merge order getLayers uses. Inline
|
|
205
|
+
// overrides are coerced to their typed shape (e.g. `center="47.6,-122.3"` →
|
|
206
|
+
// `{lat,lng}`); `templateOverrides` itself stays raw for round-tripping.
|
|
207
|
+
const { templateData, templateOverrides } = templateBlock as Block;
|
|
208
|
+
const input =
|
|
209
|
+
templateData || templateOverrides
|
|
210
|
+
? ({
|
|
211
|
+
...templateBlock,
|
|
212
|
+
...templateData,
|
|
213
|
+
...coerceTemplateParams(templateBlock.template, templateOverrides ?? {}).input,
|
|
214
|
+
} as TemplateBlock)
|
|
215
|
+
: templateBlock;
|
|
216
|
+
|
|
130
217
|
// Generate layers from template with error handling
|
|
131
218
|
let layers: Layer[];
|
|
132
219
|
try {
|
|
133
|
-
layers = templateFn(
|
|
220
|
+
layers = templateFn(input, context);
|
|
134
221
|
if (!Array.isArray(layers)) {
|
|
135
222
|
console.error(
|
|
136
223
|
`Template ${templateBlock.template} did not return an array, got:`,
|
|
@@ -180,6 +267,12 @@ export interface ExpandDocBlocksOptions {
|
|
|
180
267
|
* ensuring proper synchronization with audio playback.
|
|
181
268
|
*/
|
|
182
269
|
audioSegments?: AudioSegmentTiming[];
|
|
270
|
+
/**
|
|
271
|
+
* User-defined custom templates to merge onto the built-in registry
|
|
272
|
+
* before expanding blocks. Typically passed straight from
|
|
273
|
+
* `Doc.customTemplates`. Built-in names take precedence on collision.
|
|
274
|
+
*/
|
|
275
|
+
customTemplates?: readonly CustomTemplateDefinition[];
|
|
183
276
|
}
|
|
184
277
|
|
|
185
278
|
/**
|
|
@@ -193,38 +286,88 @@ export interface ExpandDocBlocksOptions {
|
|
|
193
286
|
* @param blocks - Array of template or raw blocks
|
|
194
287
|
* @param options - Expansion options including theme, viewport, and persistent layers
|
|
195
288
|
*/
|
|
289
|
+
/**
|
|
290
|
+
* Finalize an expanded block in place: apply the theme's motion post-pass
|
|
291
|
+
* to template-generated layers, wrap with persistent bottom/top layers,
|
|
292
|
+
* and fill the theme's default transition (never on block 0, never over an
|
|
293
|
+
* authored transition). Shared by every expansion path in this module.
|
|
294
|
+
*/
|
|
295
|
+
function finalizeExpandedBlock(
|
|
296
|
+
expandedBlock: Block,
|
|
297
|
+
sourceBlock: DocBlock,
|
|
298
|
+
blockIndex: number,
|
|
299
|
+
theme: Theme,
|
|
300
|
+
bottomLayers: Layer[],
|
|
301
|
+
topLayers: Layer[],
|
|
302
|
+
): void {
|
|
303
|
+
// Theme motion defaults apply only to template-generated layers —
|
|
304
|
+
// raw authored block.layers are never restyled.
|
|
305
|
+
if (isTemplateBlock(sourceBlock) && expandedBlock.layers && expandedBlock.layers.length > 0) {
|
|
306
|
+
expandedBlock.layers = applyRenderStyleToLayers(expandedBlock.layers, expandedBlock, theme);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (bottomLayers.length > 0 || topLayers.length > 0) {
|
|
310
|
+
expandedBlock.layers = wrapWithPersistentLayers(
|
|
311
|
+
expandedBlock.layers ?? [],
|
|
312
|
+
sourceBlock as TemplateBlock,
|
|
313
|
+
bottomLayers,
|
|
314
|
+
topLayers,
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const transition = resolveBlockTransition(expandedBlock, theme, blockIndex);
|
|
319
|
+
if (transition !== expandedBlock.transition) {
|
|
320
|
+
expandedBlock.transition = transition;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
196
324
|
export function expandDocBlocks(blocks: DocBlock[], options: ExpandDocBlocksOptions = {}): Block[] {
|
|
197
325
|
const opts: ExpandDocBlocksOptions = options;
|
|
198
326
|
|
|
199
327
|
const theme = opts.theme ?? defaultTheme;
|
|
200
328
|
const viewport = opts.viewport ?? VIEWPORT_PRESETS.landscape;
|
|
201
|
-
const { persistentLayers, audioSegments } = opts;
|
|
329
|
+
const { persistentLayers, audioSegments, customTemplates } = opts;
|
|
202
330
|
const totalBlocks = blocks.length;
|
|
203
|
-
|
|
204
|
-
//
|
|
205
|
-
const
|
|
206
|
-
|
|
331
|
+
// Merge user-defined templates onto the built-in registry once per
|
|
332
|
+
// call; passed into every `expandTemplateBlock` invocation below.
|
|
333
|
+
const registry: RuntimeTemplateRegistry =
|
|
334
|
+
customTemplates && customTemplates.length > 0
|
|
335
|
+
? buildRegistry(customTemplates)
|
|
336
|
+
: (templateRegistry as unknown as RuntimeTemplateRegistry);
|
|
337
|
+
|
|
338
|
+
// Pre-expand persistent layers once. Callers that pass no config inherit
|
|
339
|
+
// the theme's atmosphere (docs with their own layers pass them in and win
|
|
340
|
+
// wholesale — see resolvePersistentLayers).
|
|
341
|
+
const effectivePersistentLayers = persistentLayers ?? theme.persistentLayers;
|
|
342
|
+
const bottomLayers = expandPersistentLayers(effectivePersistentLayers?.bottomLayers, theme);
|
|
343
|
+
const topLayers = expandPersistentLayers(effectivePersistentLayers?.topLayers, theme);
|
|
207
344
|
|
|
208
345
|
// If no audio segments provided, use simple cumulative timing
|
|
209
346
|
if (!audioSegments || audioSegments.length === 0) {
|
|
210
347
|
let currentTime = 0;
|
|
211
348
|
return blocks.map((block, index) => {
|
|
212
349
|
const context = createTemplateContext(theme, index, totalBlocks, viewport);
|
|
350
|
+
const maybeChildren = (block as Block).children;
|
|
351
|
+
if (maybeChildren && maybeChildren.length > 0) {
|
|
352
|
+
context.children = maybeChildren;
|
|
353
|
+
}
|
|
354
|
+
// Expose the source block so custom templates' token resolver can
|
|
355
|
+
// see the block's title / contents / children. Only set for
|
|
356
|
+
// custom-templated blocks — built-ins ignore context.block but
|
|
357
|
+
// exposing it changes object identity which we want to avoid for
|
|
358
|
+
// the perf-sensitive built-in path.
|
|
359
|
+
if (
|
|
360
|
+
isTemplateBlock(block) &&
|
|
361
|
+
customTemplates &&
|
|
362
|
+
customTemplates.some((c) => c.name === block.template)
|
|
363
|
+
) {
|
|
364
|
+
context.block = block as Block;
|
|
365
|
+
}
|
|
213
366
|
const expandedBlock = isTemplateBlock(block)
|
|
214
|
-
? expandTemplateBlock(block, context)
|
|
367
|
+
? expandTemplateBlock(block, context, registry)
|
|
215
368
|
: (block as Block);
|
|
216
369
|
|
|
217
|
-
|
|
218
|
-
const templateBlock = block as TemplateBlock;
|
|
219
|
-
const useBottom = templateBlock.useBottomLayer !== false;
|
|
220
|
-
const useTop = templateBlock.useTopLayer !== false;
|
|
221
|
-
if (bottomLayers.length > 0 || topLayers.length > 0) {
|
|
222
|
-
expandedBlock.layers = [
|
|
223
|
-
...(useBottom ? bottomLayers : []),
|
|
224
|
-
...(expandedBlock.layers ?? []),
|
|
225
|
-
...(useTop ? topLayers : []),
|
|
226
|
-
];
|
|
227
|
-
}
|
|
370
|
+
finalizeExpandedBlock(expandedBlock, block, index, theme, bottomLayers, topLayers);
|
|
228
371
|
|
|
229
372
|
expandedBlock.startTime = currentTime;
|
|
230
373
|
currentTime += expandedBlock.duration;
|
|
@@ -252,20 +395,22 @@ export function expandDocBlocks(blocks: DocBlock[], options: ExpandDocBlocksOpti
|
|
|
252
395
|
let offsetTime = 0;
|
|
253
396
|
for (const { block, originalIndex } of segmentBlocks) {
|
|
254
397
|
const context = createTemplateContext(theme, originalIndex, totalBlocks, viewport);
|
|
398
|
+
const maybeChildren = (block as Block).children;
|
|
399
|
+
if (maybeChildren && maybeChildren.length > 0) {
|
|
400
|
+
context.children = maybeChildren;
|
|
401
|
+
}
|
|
402
|
+
if (
|
|
403
|
+
isTemplateBlock(block) &&
|
|
404
|
+
customTemplates &&
|
|
405
|
+
customTemplates.some((c) => c.name === block.template)
|
|
406
|
+
) {
|
|
407
|
+
context.block = block as Block;
|
|
408
|
+
}
|
|
255
409
|
const expandedBlock = isTemplateBlock(block)
|
|
256
|
-
? expandTemplateBlock(block, context)
|
|
410
|
+
? expandTemplateBlock(block, context, registry)
|
|
257
411
|
: (block as Block);
|
|
258
412
|
|
|
259
|
-
|
|
260
|
-
const useBottom = templateBlock.useBottomLayer !== false;
|
|
261
|
-
const useTop = templateBlock.useTopLayer !== false;
|
|
262
|
-
if (bottomLayers.length > 0 || topLayers.length > 0) {
|
|
263
|
-
expandedBlock.layers = [
|
|
264
|
-
...(useBottom ? bottomLayers : []),
|
|
265
|
-
...(expandedBlock.layers ?? []),
|
|
266
|
-
...(useTop ? topLayers : []),
|
|
267
|
-
];
|
|
268
|
-
}
|
|
413
|
+
finalizeExpandedBlock(expandedBlock, block, originalIndex, theme, bottomLayers, topLayers);
|
|
269
414
|
|
|
270
415
|
expandedBlock.startTime = offsetTime;
|
|
271
416
|
offsetTime += expandedBlock.duration;
|
|
@@ -318,21 +463,24 @@ export function expandDocBlocks(blocks: DocBlock[], options: ExpandDocBlocksOpti
|
|
|
318
463
|
|
|
319
464
|
for (const { block, originalIndex } of segmentBlocks) {
|
|
320
465
|
const context = createTemplateContext(theme, originalIndex, totalBlocks, viewport);
|
|
466
|
+
const maybeChildren = (block as Block).children;
|
|
467
|
+
if (maybeChildren && maybeChildren.length > 0) {
|
|
468
|
+
context.children = maybeChildren;
|
|
469
|
+
}
|
|
470
|
+
if (
|
|
471
|
+
isTemplateBlock(block) &&
|
|
472
|
+
customTemplates &&
|
|
473
|
+
customTemplates.some((c) => c.name === block.template)
|
|
474
|
+
) {
|
|
475
|
+
context.block = block as Block;
|
|
476
|
+
}
|
|
321
477
|
const expandedBlock = isTemplateBlock(block)
|
|
322
|
-
? expandTemplateBlock(block, context)
|
|
478
|
+
? expandTemplateBlock(block, context, registry)
|
|
323
479
|
: (block as Block);
|
|
324
480
|
|
|
325
|
-
|
|
326
|
-
const useBottom = templateBlock.useBottomLayer !== false;
|
|
327
|
-
const useTop = templateBlock.useTopLayer !== false;
|
|
328
|
-
if (bottomLayers.length > 0 || topLayers.length > 0) {
|
|
329
|
-
expandedBlock.layers = [
|
|
330
|
-
...(useBottom ? bottomLayers : []),
|
|
331
|
-
...(expandedBlock.layers ?? []),
|
|
332
|
-
...(useTop ? topLayers : []),
|
|
333
|
-
];
|
|
334
|
-
}
|
|
481
|
+
finalizeExpandedBlock(expandedBlock, block, originalIndex, theme, bottomLayers, topLayers);
|
|
335
482
|
|
|
483
|
+
const templateBlock = block as TemplateBlock;
|
|
336
484
|
expandedInfos.push({
|
|
337
485
|
block: expandedBlock,
|
|
338
486
|
originalIndex,
|
|
@@ -578,7 +726,13 @@ export type {
|
|
|
578
726
|
} from '../../schemas/Viewport.js';
|
|
579
727
|
export { getLayoutHints, getTwoColumnPositions } from '../../schemas/LayoutStrategy.js';
|
|
580
728
|
export type { LayoutHints } from '../../schemas/LayoutStrategy.js';
|
|
581
|
-
export {
|
|
729
|
+
export {
|
|
730
|
+
expandPersistentLayers,
|
|
731
|
+
getDocStyleConfig,
|
|
732
|
+
getPersistentLayersFromTheme,
|
|
733
|
+
resolvePersistentLayers,
|
|
734
|
+
wrapWithPersistentLayers,
|
|
735
|
+
} from './persistentLayers.js';
|
|
582
736
|
|
|
583
737
|
// Re-export individual templates for direct access
|
|
584
738
|
export { titleBlock } from './titleBlock.js';
|
|
@@ -602,6 +756,31 @@ export { pullQuote } from './pullQuote.js';
|
|
|
602
756
|
export { videoWithCaption } from './videoWithCaption.js';
|
|
603
757
|
export { videoPullQuote } from './videoPullQuote.js';
|
|
604
758
|
export { dataTable } from './dataTable.js';
|
|
759
|
+
export { diagramBlock } from './diagramBlock.js';
|
|
760
|
+
export { computeDiagramLayout } from './diagramLayout.js';
|
|
761
|
+
export type {
|
|
762
|
+
DiagramLayout,
|
|
763
|
+
DiagramNodePosition,
|
|
764
|
+
DiagramEdge,
|
|
765
|
+
DiagramLayoutOptions,
|
|
766
|
+
} from './diagramLayout.js';
|
|
767
|
+
export { drawingBlock } from './drawingBlock.js';
|
|
768
|
+
export {
|
|
769
|
+
computeDrawingLayout,
|
|
770
|
+
normalizeShapeKind,
|
|
771
|
+
isShapeName,
|
|
772
|
+
SHAPE_NAMES,
|
|
773
|
+
} from './drawingLayout.js';
|
|
774
|
+
export type {
|
|
775
|
+
DrawingLayout,
|
|
776
|
+
DrawingShape,
|
|
777
|
+
DrawingShapeKind,
|
|
778
|
+
DrawingConnector,
|
|
779
|
+
DrawingLayoutOptions,
|
|
780
|
+
} from './drawingLayout.js';
|
|
781
|
+
export { layoutBlock } from './layoutBlock.js';
|
|
782
|
+
export { computeLayoutLayers } from './layoutLayout.js';
|
|
783
|
+
export type { LayoutLayersResult, LayoutLayerDefaults } from './layoutLayout.js';
|
|
605
784
|
|
|
606
785
|
// Re-export accent image utilities
|
|
607
786
|
export { getAccentLayout, createAccentLayers, adjustY, DEFAULT_LAYOUT } from './accentImage.js';
|