@bendyline/squisq 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ContentContainer-DNx460y8.d.ts +88 -0
- package/dist/{Doc-1hmT1LZl.d.ts → Doc-Dwn5aHFC.d.ts} +115 -6
- package/dist/__tests__/dataTable.test.d.ts +2 -0
- package/dist/__tests__/dataTable.test.d.ts.map +1 -0
- package/dist/__tests__/dataTable.test.js +110 -0
- package/dist/__tests__/dataTable.test.js.map +1 -0
- package/dist/__tests__/markdownToDoc.test.js +75 -0
- package/dist/__tests__/markdownToDoc.test.js.map +1 -1
- package/dist/{chunk-6YJPI6VI.js → chunk-4X3JQXNM.js} +1 -1
- package/dist/chunk-DNJKBAI7.js +1 -0
- package/dist/chunk-DNJKBAI7.js.map +1 -0
- package/dist/{chunk-S4F2RY37.js → chunk-KEFWM2VC.js} +1 -1
- package/dist/chunk-KEFWM2VC.js.map +1 -0
- package/dist/{chunk-VP5SZTZ2.js → chunk-MIBRIRGJ.js} +2 -139
- package/dist/chunk-MIBRIRGJ.js.map +1 -0
- package/dist/{chunk-URU6QMLY.js → chunk-NJLL5XYC.js} +15 -8
- package/dist/chunk-NJLL5XYC.js.map +1 -0
- package/dist/chunk-QM5PKNPW.js +165 -0
- package/dist/chunk-QM5PKNPW.js.map +1 -0
- package/dist/{chunk-PJ7AODIM.js → chunk-T6WBC3ND.js} +459 -53
- package/dist/chunk-T6WBC3ND.js.map +1 -0
- package/dist/chunk-TSG2OSE6.js +145 -0
- package/dist/chunk-TSG2OSE6.js.map +1 -0
- package/dist/{chunk-O5HCIUAD.js → chunk-TVPKD76V.js} +81 -187
- package/dist/chunk-TVPKD76V.js.map +1 -0
- package/dist/contentExtractor-BNfVJV2U.d.ts +113 -0
- package/dist/doc/audioMapping.d.ts +36 -0
- package/dist/doc/audioMapping.d.ts.map +1 -0
- package/dist/doc/audioMapping.js +279 -0
- package/dist/doc/audioMapping.js.map +1 -0
- package/dist/doc/index.d.ts +1 -0
- package/dist/doc/index.d.ts.map +1 -1
- package/dist/doc/index.js +1 -0
- package/dist/doc/index.js.map +1 -1
- package/dist/doc/markdownToDoc.d.ts.map +1 -1
- package/dist/doc/markdownToDoc.js +126 -1
- package/dist/doc/markdownToDoc.js.map +1 -1
- package/dist/doc/templates/comparisonBar.d.ts.map +1 -1
- package/dist/doc/templates/comparisonBar.js +23 -5
- package/dist/doc/templates/comparisonBar.js.map +1 -1
- package/dist/doc/templates/coverBlock.d.ts.map +1 -1
- package/dist/doc/templates/coverBlock.js +3 -0
- package/dist/doc/templates/coverBlock.js.map +1 -1
- package/dist/doc/templates/dataTable.d.ts +14 -0
- package/dist/doc/templates/dataTable.d.ts.map +1 -0
- package/dist/doc/templates/dataTable.js +73 -0
- package/dist/doc/templates/dataTable.js.map +1 -0
- package/dist/doc/templates/dateEvent.d.ts.map +1 -1
- package/dist/doc/templates/dateEvent.js +4 -0
- package/dist/doc/templates/dateEvent.js.map +1 -1
- package/dist/doc/templates/definitionCard.d.ts.map +1 -1
- package/dist/doc/templates/definitionCard.js +4 -1
- package/dist/doc/templates/definitionCard.js.map +1 -1
- package/dist/doc/templates/factCard.d.ts.map +1 -1
- package/dist/doc/templates/factCard.js +4 -0
- package/dist/doc/templates/factCard.js.map +1 -1
- package/dist/doc/templates/fullBleedQuote.d.ts.map +1 -1
- package/dist/doc/templates/fullBleedQuote.js +2 -1
- package/dist/doc/templates/fullBleedQuote.js.map +1 -1
- package/dist/doc/templates/imageWithCaption.d.ts.map +1 -1
- package/dist/doc/templates/imageWithCaption.js +4 -0
- package/dist/doc/templates/imageWithCaption.js.map +1 -1
- package/dist/doc/templates/index.d.ts +1 -0
- package/dist/doc/templates/index.d.ts.map +1 -1
- package/dist/doc/templates/index.js +3 -0
- package/dist/doc/templates/index.js.map +1 -1
- package/dist/doc/templates/listBlock.d.ts.map +1 -1
- package/dist/doc/templates/listBlock.js +3 -0
- package/dist/doc/templates/listBlock.js.map +1 -1
- package/dist/doc/templates/mapBlock.d.ts.map +1 -1
- package/dist/doc/templates/mapBlock.js +3 -0
- package/dist/doc/templates/mapBlock.js.map +1 -1
- package/dist/doc/templates/photoGrid.d.ts.map +1 -1
- package/dist/doc/templates/photoGrid.js +3 -0
- package/dist/doc/templates/photoGrid.js.map +1 -1
- package/dist/doc/templates/pullQuote.d.ts.map +1 -1
- package/dist/doc/templates/pullQuote.js +4 -0
- package/dist/doc/templates/pullQuote.js.map +1 -1
- package/dist/doc/templates/quoteBlock.d.ts.map +1 -1
- package/dist/doc/templates/quoteBlock.js +4 -0
- package/dist/doc/templates/quoteBlock.js.map +1 -1
- package/dist/doc/templates/sectionHeader.d.ts.map +1 -1
- package/dist/doc/templates/sectionHeader.js +3 -2
- package/dist/doc/templates/sectionHeader.js.map +1 -1
- package/dist/doc/templates/statHighlight.d.ts.map +1 -1
- package/dist/doc/templates/statHighlight.js +4 -1
- package/dist/doc/templates/statHighlight.js.map +1 -1
- package/dist/doc/templates/titleBlock.d.ts.map +1 -1
- package/dist/doc/templates/titleBlock.js +3 -0
- package/dist/doc/templates/titleBlock.js.map +1 -1
- package/dist/doc/templates/twoColumn.d.ts.map +1 -1
- package/dist/doc/templates/twoColumn.js +7 -1
- package/dist/doc/templates/twoColumn.js.map +1 -1
- package/dist/doc/templates/videoPullQuote.d.ts.map +1 -1
- package/dist/doc/templates/videoPullQuote.js +4 -0
- package/dist/doc/templates/videoPullQuote.js.map +1 -1
- package/dist/doc/templates/videoWithCaption.d.ts.map +1 -1
- package/dist/doc/templates/videoWithCaption.js +3 -0
- package/dist/doc/templates/videoWithCaption.js.map +1 -1
- package/dist/doc/utils/themeUtils.d.ts +9 -0
- package/dist/doc/utils/themeUtils.d.ts.map +1 -1
- package/dist/doc/utils/themeUtils.js +26 -0
- package/dist/doc/utils/themeUtils.js.map +1 -1
- package/dist/markdown/convert.d.ts.map +1 -1
- package/dist/markdown/convert.js +16 -7
- package/dist/markdown/convert.js.map +1 -1
- package/dist/markdown/types.d.ts +4 -2
- package/dist/markdown/types.d.ts.map +1 -1
- package/dist/schemas/BlockTemplates.d.ts +20 -3
- package/dist/schemas/BlockTemplates.d.ts.map +1 -1
- package/dist/schemas/BlockTemplates.js +2 -2
- package/dist/schemas/BlockTemplates.js.map +1 -1
- package/dist/schemas/Doc.d.ts +93 -1
- package/dist/schemas/Doc.d.ts.map +1 -1
- package/dist/schemas/Doc.js.map +1 -1
- package/dist/schemas/themeLibrary.d.ts +2 -2
- package/dist/schemas/themeLibrary.d.ts.map +1 -1
- package/dist/schemas/themeLibrary.js +91 -26
- package/dist/schemas/themeLibrary.js.map +1 -1
- package/dist/story/index.d.ts +63 -5
- package/dist/story/index.js +17 -5
- package/dist/{themeLibrary-DR1VRo-8.d.ts → themeLibrary-DLJtGh8-.d.ts} +3 -3
- package/dist/transform/applyTransform.d.ts +22 -0
- package/dist/transform/applyTransform.d.ts.map +1 -0
- package/dist/transform/applyTransform.js +68 -0
- package/dist/transform/applyTransform.js.map +1 -0
- package/dist/transform/blockAnalyzer.d.ts +48 -0
- package/dist/transform/blockAnalyzer.d.ts.map +1 -0
- package/dist/transform/blockAnalyzer.js +135 -0
- package/dist/transform/blockAnalyzer.js.map +1 -0
- package/dist/transform/index.d.ts +6 -0
- package/dist/transform/index.d.ts.map +1 -0
- package/dist/transform/index.js +4 -0
- package/dist/transform/index.js.map +1 -0
- package/dist/transform/registry.d.ts +19 -0
- package/dist/transform/registry.d.ts.map +1 -0
- package/dist/transform/registry.js +41 -0
- package/dist/transform/registry.js.map +1 -0
- package/dist/transform/styles/dataDriven.d.ts +4 -0
- package/dist/transform/styles/dataDriven.d.ts.map +1 -0
- package/dist/transform/styles/dataDriven.js +15 -0
- package/dist/transform/styles/dataDriven.js.map +1 -0
- package/dist/transform/styles/documentary.d.ts +4 -0
- package/dist/transform/styles/documentary.d.ts.map +1 -0
- package/dist/transform/styles/documentary.js +15 -0
- package/dist/transform/styles/documentary.js.map +1 -0
- package/dist/transform/styles/index.d.ts +6 -0
- package/dist/transform/styles/index.d.ts.map +1 -0
- package/dist/transform/styles/index.js +6 -0
- package/dist/transform/styles/index.js.map +1 -0
- package/dist/transform/styles/magazine.d.ts +4 -0
- package/dist/transform/styles/magazine.d.ts.map +1 -0
- package/dist/transform/styles/magazine.js +15 -0
- package/dist/transform/styles/magazine.js.map +1 -0
- package/dist/transform/styles/minimal.d.ts +4 -0
- package/dist/transform/styles/minimal.d.ts.map +1 -0
- package/dist/transform/styles/minimal.js +15 -0
- package/dist/transform/styles/minimal.js.map +1 -0
- package/dist/transform/styles/narrative.d.ts +4 -0
- package/dist/transform/styles/narrative.d.ts.map +1 -0
- package/dist/transform/styles/narrative.js +15 -0
- package/dist/transform/styles/narrative.js.map +1 -0
- package/dist/transform/templateSelector.d.ts +30 -0
- package/dist/transform/templateSelector.d.ts.map +1 -0
- package/dist/transform/templateSelector.js +218 -0
- package/dist/transform/templateSelector.js.map +1 -0
- package/dist/transform/timingAllocator.d.ts +21 -0
- package/dist/transform/timingAllocator.d.ts.map +1 -0
- package/dist/transform/timingAllocator.js +111 -0
- package/dist/transform/timingAllocator.js.map +1 -0
- package/dist/transform/types.d.ts +86 -0
- package/dist/transform/types.d.ts.map +1 -0
- package/dist/transform/types.js +9 -0
- package/dist/transform/types.js.map +1 -0
- package/dist/{types-DHiv_Pnm.d.ts → types-DYAzisMG.d.ts} +4 -2
- package/package.json +6 -1
- package/src/__tests__/dataTable.test.ts +135 -0
- package/src/__tests__/markdownToDoc.test.ts +96 -0
- package/src/doc/audioMapping.ts +346 -0
- package/src/doc/index.ts +1 -0
- package/src/doc/markdownToDoc.ts +136 -2
- package/src/doc/templates/comparisonBar.ts +23 -5
- package/src/doc/templates/coverBlock.ts +3 -0
- package/src/doc/templates/dataTable.ts +84 -0
- package/src/doc/templates/dateEvent.ts +4 -0
- package/src/doc/templates/definitionCard.ts +4 -1
- package/src/doc/templates/factCard.ts +4 -0
- package/src/doc/templates/fullBleedQuote.ts +2 -1
- package/src/doc/templates/imageWithCaption.ts +4 -0
- package/src/doc/templates/index.ts +3 -0
- package/src/doc/templates/listBlock.ts +3 -0
- package/src/doc/templates/mapBlock.ts +3 -0
- package/src/doc/templates/photoGrid.ts +3 -0
- package/src/doc/templates/pullQuote.ts +4 -0
- package/src/doc/templates/quoteBlock.ts +4 -0
- package/src/doc/templates/sectionHeader.ts +3 -2
- package/src/doc/templates/statHighlight.ts +4 -1
- package/src/doc/templates/titleBlock.ts +3 -0
- package/src/doc/templates/twoColumn.ts +7 -1
- package/src/doc/templates/videoPullQuote.ts +4 -0
- package/src/doc/templates/videoWithCaption.ts +3 -0
- package/src/doc/utils/themeUtils.ts +29 -0
- package/src/markdown/convert.ts +17 -7
- package/src/markdown/types.ts +4 -2
- package/src/schemas/BlockTemplates.ts +22 -3
- package/src/schemas/Doc.ts +103 -1
- package/src/schemas/themeLibrary.ts +95 -26
- package/src/transform/applyTransform.ts +83 -0
- package/src/transform/blockAnalyzer.ts +181 -0
- package/src/transform/index.ts +20 -0
- package/src/transform/registry.ts +47 -0
- package/src/transform/styles/dataDriven.ts +16 -0
- package/src/transform/styles/documentary.ts +16 -0
- package/src/transform/styles/index.ts +5 -0
- package/src/transform/styles/magazine.ts +16 -0
- package/src/transform/styles/minimal.ts +16 -0
- package/src/transform/styles/narrative.ts +16 -0
- package/src/transform/templateSelector.ts +294 -0
- package/src/transform/timingAllocator.ts +126 -0
- package/src/transform/types.ts +105 -0
- package/dist/chunk-O5HCIUAD.js.map +0 -1
- package/dist/chunk-PJ7AODIM.js.map +0 -1
- package/dist/chunk-S4F2RY37.js.map +0 -1
- package/dist/chunk-URU6QMLY.js.map +0 -1
- package/dist/chunk-VP5SZTZ2.js.map +0 -1
- /package/dist/{chunk-6YJPI6VI.js.map → chunk-4X3JQXNM.js.map} +0 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import {
|
|
2
|
+
extractContent,
|
|
3
|
+
mapElementToBlock,
|
|
4
|
+
stripMarkdown
|
|
5
|
+
} from "./chunk-MIBRIRGJ.js";
|
|
6
|
+
import {
|
|
7
|
+
SeededRandom,
|
|
8
|
+
hashString
|
|
9
|
+
} from "./chunk-FVTQSNR7.js";
|
|
10
|
+
import {
|
|
11
|
+
estimateNarrationDuration
|
|
12
|
+
} from "./chunk-3E5F2XMR.js";
|
|
13
|
+
|
|
14
|
+
// src/generate/slideshowGenerator.ts
|
|
15
|
+
var DEFAULT_COLOR_SCHEMES = ["blue", "green", "purple", "orange", "red"];
|
|
16
|
+
var DEFAULT_AMBIENT_MOTIONS = [
|
|
17
|
+
"zoomIn",
|
|
18
|
+
"zoomOut",
|
|
19
|
+
"panLeft",
|
|
20
|
+
"panRight"
|
|
21
|
+
];
|
|
22
|
+
var DEFAULT_ACCENT_POSITIONS = ["left-strip", "right-strip", "bottom-strip"];
|
|
23
|
+
function generateSlideshow(text, images = [], options = {}) {
|
|
24
|
+
const {
|
|
25
|
+
seed,
|
|
26
|
+
title,
|
|
27
|
+
subtitle,
|
|
28
|
+
duration: explicitDuration,
|
|
29
|
+
targetSlides,
|
|
30
|
+
colorSchemes = DEFAULT_COLOR_SCHEMES,
|
|
31
|
+
ambientMotions = DEFAULT_AMBIENT_MOTIONS,
|
|
32
|
+
accentPositions = DEFAULT_ACCENT_POSITIONS,
|
|
33
|
+
minSlideDuration = 4,
|
|
34
|
+
maxSlideDuration = 15,
|
|
35
|
+
themeId,
|
|
36
|
+
isMarkdown = false,
|
|
37
|
+
minConfidence = 0.3
|
|
38
|
+
} = options;
|
|
39
|
+
const plainText = isMarkdown ? stripMarkdown(text) : text;
|
|
40
|
+
const rng = new SeededRandom(seed ?? hashString(plainText));
|
|
41
|
+
const totalDuration = explicitDuration ?? estimateNarrationDuration(plainText);
|
|
42
|
+
const extraction = extractContent(plainText, { minConfidence });
|
|
43
|
+
const allElements = extraction.elements;
|
|
44
|
+
const slideBudget = targetSlides ?? computeSlideBudget(totalDuration, allElements.length);
|
|
45
|
+
const imageSlotCount = images.length > 0 ? Math.max(1, Math.round(slideBudget * 0.4)) : 0;
|
|
46
|
+
const contentSlotCount = Math.max(0, slideBudget - imageSlotCount - (title ? 1 : 0));
|
|
47
|
+
const sorted = [...allElements].sort((a, b) => b.confidence - a.confidence);
|
|
48
|
+
const selected = sorted.slice(0, contentSlotCount);
|
|
49
|
+
selected.sort((a, b) => a.sourcePosition - b.sourcePosition);
|
|
50
|
+
const blocks = [];
|
|
51
|
+
let slideIndex = 0;
|
|
52
|
+
let colorIdx = 0;
|
|
53
|
+
let accentIdx = 0;
|
|
54
|
+
const totalSlideCount = (title ? 1 : 0) + selected.length + Math.min(imageSlotCount, images.length);
|
|
55
|
+
const perSlide = totalSlideCount > 0 ? Math.min(maxSlideDuration, Math.max(minSlideDuration, totalDuration / totalSlideCount)) : minSlideDuration;
|
|
56
|
+
if (title) {
|
|
57
|
+
const titleBlock = {
|
|
58
|
+
id: `slide-${slideIndex++}`,
|
|
59
|
+
template: "titleBlock",
|
|
60
|
+
title,
|
|
61
|
+
subtitle,
|
|
62
|
+
duration: Math.min(perSlide, 6),
|
|
63
|
+
audioSegment: 0
|
|
64
|
+
};
|
|
65
|
+
blocks.push(titleBlock);
|
|
66
|
+
}
|
|
67
|
+
const standaloneImages = images.slice(0, Math.min(imageSlotCount, images.length));
|
|
68
|
+
const accentPool = images.length > standaloneImages.length ? images.slice(standaloneImages.length) : [...images];
|
|
69
|
+
const imageInterval = standaloneImages.length > 0 ? Math.max(1, Math.floor(selected.length / (standaloneImages.length + 1))) : Infinity;
|
|
70
|
+
let imgIdx = 0;
|
|
71
|
+
let sinceImage = 0;
|
|
72
|
+
for (let i = 0; i < selected.length; i++) {
|
|
73
|
+
if (sinceImage >= imageInterval && imgIdx < standaloneImages.length) {
|
|
74
|
+
blocks.push(
|
|
75
|
+
createImageSlide(standaloneImages[imgIdx], slideIndex++, perSlide, rng, ambientMotions)
|
|
76
|
+
);
|
|
77
|
+
imgIdx++;
|
|
78
|
+
sinceImage = 0;
|
|
79
|
+
}
|
|
80
|
+
const element = selected[i];
|
|
81
|
+
let accentImage;
|
|
82
|
+
if (accentPool.length > 0) {
|
|
83
|
+
const img = accentPool[i % accentPool.length];
|
|
84
|
+
accentImage = {
|
|
85
|
+
src: img.src,
|
|
86
|
+
alt: img.alt ?? "",
|
|
87
|
+
position: accentPositions[accentIdx % accentPositions.length],
|
|
88
|
+
ambientMotion: rng.pickRequired(ambientMotions),
|
|
89
|
+
credit: img.credit,
|
|
90
|
+
license: img.license
|
|
91
|
+
};
|
|
92
|
+
accentIdx++;
|
|
93
|
+
}
|
|
94
|
+
const block = mapElementToBlock(element, {
|
|
95
|
+
id: `slide-${slideIndex++}`,
|
|
96
|
+
duration: perSlide,
|
|
97
|
+
audioSegment: 0,
|
|
98
|
+
colorScheme: colorSchemes[colorIdx % colorSchemes.length],
|
|
99
|
+
accentImage
|
|
100
|
+
});
|
|
101
|
+
blocks.push(block);
|
|
102
|
+
colorIdx++;
|
|
103
|
+
sinceImage++;
|
|
104
|
+
}
|
|
105
|
+
while (imgIdx < standaloneImages.length) {
|
|
106
|
+
blocks.push(
|
|
107
|
+
createImageSlide(standaloneImages[imgIdx], slideIndex++, perSlide, rng, ambientMotions)
|
|
108
|
+
);
|
|
109
|
+
imgIdx++;
|
|
110
|
+
}
|
|
111
|
+
const doc = {
|
|
112
|
+
articleId: title ?? "slideshow",
|
|
113
|
+
duration: totalDuration,
|
|
114
|
+
blocks,
|
|
115
|
+
audio: {
|
|
116
|
+
segments: [{ src: "", name: "main", duration: totalDuration, startTime: 0 }]
|
|
117
|
+
},
|
|
118
|
+
themeId
|
|
119
|
+
};
|
|
120
|
+
return doc;
|
|
121
|
+
}
|
|
122
|
+
function computeSlideBudget(duration, elementCount) {
|
|
123
|
+
const byDuration = Math.round(duration / 60 * 5);
|
|
124
|
+
const budget = Math.min(byDuration, elementCount + 4);
|
|
125
|
+
return Math.max(3, Math.min(12, budget));
|
|
126
|
+
}
|
|
127
|
+
function createImageSlide(img, index, duration, rng, motions) {
|
|
128
|
+
return {
|
|
129
|
+
id: `slide-${index}`,
|
|
130
|
+
template: "imageWithCaption",
|
|
131
|
+
imageSrc: img.src,
|
|
132
|
+
imageAlt: img.alt ?? "",
|
|
133
|
+
caption: img.alt,
|
|
134
|
+
duration,
|
|
135
|
+
audioSegment: 0,
|
|
136
|
+
ambientMotion: rng.pickRequired(motions),
|
|
137
|
+
imageCredit: img.credit,
|
|
138
|
+
imageLicense: img.license
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export {
|
|
143
|
+
generateSlideshow
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=chunk-TSG2OSE6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/generate/slideshowGenerator.ts"],"sourcesContent":["/**\n * Slideshow Generator\n *\n * Turns plain text + optional images into a complete squisq `Doc`.\n *\n * Pipeline:\n * 1. Strip markdown (if needed)\n * 2. Extract compelling content (stats, dates, quotes, …)\n * 3. Estimate narration timing\n * 4. Map extractions → template blocks\n * 5. Interleave image slides\n * 6. Return a ready-to-render `Doc`\n */\n\nimport type { Doc } from '../schemas/Doc.js';\nimport type {\n TemplateBlock,\n ImageWithCaptionInput,\n TitleBlockInput,\n ColorScheme,\n AccentImage,\n AccentPosition,\n} from '../schemas/BlockTemplates.js';\nimport { extractContent, stripMarkdown } from './contentExtractor.js';\nimport { mapElementToBlock } from './templateMapper.js';\nimport { estimateNarrationDuration } from '../timing/narrationTiming.js';\nimport { SeededRandom, hashString } from '../random/SeededRandom.js';\n\n// ── Public types ───────────────────────────────────────────────────\n\n/** A Doc variant whose blocks are TemplateBlocks (no startTime required). */\nexport type SlideshowDoc = Omit<Doc, 'blocks'> & {\n blocks: TemplateBlock[];\n};\n\n/** Image metadata passed to the generator. */\nexport interface SlideshowImage {\n /** Image source path or URL. */\n src: string;\n /** Alt text for accessibility. */\n alt?: string;\n /** Photo credit. */\n credit?: string;\n /** License identifier. */\n license?: string;\n}\n\n/** Options for `generateSlideshow`. */\nexport interface SlideshowOptions {\n /** Deterministic seed (default: hash of the text). */\n seed?: number;\n /** Title slide text. Omit to skip the title slide. */\n title?: string;\n /** Subtitle for the title slide. */\n subtitle?: string;\n /** Explicit total duration in seconds. When omitted, estimated from text. */\n duration?: number;\n /** Target number of content slides (default: 5–8, auto-scaled). */\n targetSlides?: number;\n /** Color schemes to rotate (default: ['blue','green','purple','orange','red']). */\n colorSchemes?: ColorScheme[];\n /** Ambient motions to rotate on images. */\n ambientMotions?: Array<'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight'>;\n /** Accent positions to rotate on text slides. */\n accentPositions?: AccentPosition[];\n /** Minimum slide duration in seconds (default: 4). */\n minSlideDuration?: number;\n /** Maximum slide duration in seconds (default: 15). */\n maxSlideDuration?: number;\n /** Theme identifier to embed in the Doc. */\n themeId?: string;\n /** Whether the input text is markdown (default: false). */\n isMarkdown?: boolean;\n /** Minimum extraction confidence (default: 0.3). */\n minConfidence?: number;\n}\n\nconst DEFAULT_COLOR_SCHEMES: ColorScheme[] = ['blue', 'green', 'purple', 'orange', 'red'];\nconst DEFAULT_AMBIENT_MOTIONS: Array<'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight'> = [\n 'zoomIn',\n 'zoomOut',\n 'panLeft',\n 'panRight',\n];\nconst DEFAULT_ACCENT_POSITIONS: AccentPosition[] = ['left-strip', 'right-strip', 'bottom-strip'];\n\n// ── Main ───────────────────────────────────────────────────────────\n\n/**\n * Generate a slideshow `Doc` from text and optional images.\n *\n * ```ts\n * const doc = generateSlideshow(articleText, myImages, {\n * title: 'Mount Rainier',\n * themeId: 'documentary',\n * });\n * // doc is a complete Doc ready for DocPlayer / LinearDocView\n * ```\n */\nexport function generateSlideshow(\n text: string,\n images: SlideshowImage[] = [],\n options: SlideshowOptions = {},\n): SlideshowDoc {\n const {\n seed,\n title,\n subtitle,\n duration: explicitDuration,\n targetSlides,\n colorSchemes = DEFAULT_COLOR_SCHEMES,\n ambientMotions = DEFAULT_AMBIENT_MOTIONS,\n accentPositions = DEFAULT_ACCENT_POSITIONS,\n minSlideDuration = 4,\n maxSlideDuration = 15,\n themeId,\n isMarkdown = false,\n minConfidence = 0.3,\n } = options;\n\n const plainText = isMarkdown ? stripMarkdown(text) : text;\n const rng = new SeededRandom(seed ?? hashString(plainText));\n\n // 1. Estimate total duration\n const totalDuration = explicitDuration ?? estimateNarrationDuration(plainText);\n\n // 2. Extract compelling content\n const extraction = extractContent(plainText, { minConfidence });\n const allElements = extraction.elements;\n\n // 3. Decide slide budget\n const slideBudget = targetSlides ?? computeSlideBudget(totalDuration, allElements.length);\n\n // Allocate slots between content and images\n const imageSlotCount = images.length > 0 ? Math.max(1, Math.round(slideBudget * 0.4)) : 0;\n const contentSlotCount = Math.max(0, slideBudget - imageSlotCount - (title ? 1 : 0));\n\n // Select top elements by confidence, then restore source order\n const sorted = [...allElements].sort((a, b) => b.confidence - a.confidence);\n const selected = sorted.slice(0, contentSlotCount);\n selected.sort((a, b) => a.sourcePosition - b.sourcePosition);\n\n // 4. Build slides\n const blocks: TemplateBlock[] = [];\n let slideIndex = 0;\n let colorIdx = 0;\n let accentIdx = 0;\n\n // Determine per-slide duration\n const totalSlideCount =\n (title ? 1 : 0) + selected.length + Math.min(imageSlotCount, images.length);\n const perSlide =\n totalSlideCount > 0\n ? Math.min(maxSlideDuration, Math.max(minSlideDuration, totalDuration / totalSlideCount))\n : minSlideDuration;\n\n // Title slide\n if (title) {\n const titleBlock: TitleBlockInput = {\n id: `slide-${slideIndex++}`,\n template: 'titleBlock',\n title,\n subtitle,\n duration: Math.min(perSlide, 6),\n audioSegment: 0,\n };\n blocks.push(titleBlock);\n }\n\n // Prepare image pool for standalone + accent images\n const standaloneImages = images.slice(0, Math.min(imageSlotCount, images.length));\n const accentPool =\n images.length > standaloneImages.length ? images.slice(standaloneImages.length) : [...images]; // reuse if not enough\n\n // Interleave pattern: insert an image slide every N content slides\n const imageInterval =\n standaloneImages.length > 0\n ? Math.max(1, Math.floor(selected.length / (standaloneImages.length + 1)))\n : Infinity;\n let imgIdx = 0;\n let sinceImage = 0;\n\n for (let i = 0; i < selected.length; i++) {\n // Maybe insert a standalone image slide before this content slide\n if (sinceImage >= imageInterval && imgIdx < standaloneImages.length) {\n blocks.push(\n createImageSlide(standaloneImages[imgIdx], slideIndex++, perSlide, rng, ambientMotions),\n );\n imgIdx++;\n sinceImage = 0;\n }\n\n const element = selected[i];\n\n // Optional accent image\n let accentImage: AccentImage | undefined;\n if (accentPool.length > 0) {\n const img = accentPool[i % accentPool.length];\n accentImage = {\n src: img.src,\n alt: img.alt ?? '',\n position: accentPositions[accentIdx % accentPositions.length],\n ambientMotion: rng.pickRequired(ambientMotions),\n credit: img.credit,\n license: img.license,\n };\n accentIdx++;\n }\n\n const block = mapElementToBlock(element, {\n id: `slide-${slideIndex++}`,\n duration: perSlide,\n audioSegment: 0,\n colorScheme: colorSchemes[colorIdx % colorSchemes.length],\n accentImage,\n });\n blocks.push(block);\n colorIdx++;\n sinceImage++;\n }\n\n // Append any remaining standalone images\n while (imgIdx < standaloneImages.length) {\n blocks.push(\n createImageSlide(standaloneImages[imgIdx], slideIndex++, perSlide, rng, ambientMotions),\n );\n imgIdx++;\n }\n\n // 5. Assemble Doc\n const doc: SlideshowDoc = {\n articleId: title ?? 'slideshow',\n duration: totalDuration,\n blocks,\n audio: {\n segments: [{ src: '', name: 'main', duration: totalDuration, startTime: 0 }],\n },\n themeId,\n };\n\n return doc;\n}\n\n// ── Helpers ────────────────────────────────────────────────────────\n\nfunction computeSlideBudget(duration: number, elementCount: number): number {\n // Aim for ~5 slides per minute of content, clamped 3–12\n const byDuration = Math.round((duration / 60) * 5);\n // But don't exceed available elements + a few image slots\n const budget = Math.min(byDuration, elementCount + 4);\n return Math.max(3, Math.min(12, budget));\n}\n\nfunction createImageSlide(\n img: SlideshowImage,\n index: number,\n duration: number,\n rng: SeededRandom,\n motions: Array<'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight'>,\n): ImageWithCaptionInput {\n return {\n id: `slide-${index}`,\n template: 'imageWithCaption',\n imageSrc: img.src,\n imageAlt: img.alt ?? '',\n caption: img.alt,\n duration,\n audioSegment: 0,\n ambientMotion: rng.pickRequired(motions),\n imageCredit: img.credit,\n imageLicense: img.license,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,156 +1,22 @@
|
|
|
1
|
-
// src/schemas/Viewport.ts
|
|
2
|
-
var VIEWPORT_PRESETS = {
|
|
3
|
-
/** 16:9 landscape (default, 1080p) */
|
|
4
|
-
landscape: { width: 1920, height: 1080, name: "16:9 Landscape" },
|
|
5
|
-
/** 9:16 portrait (vertical video, stories) */
|
|
6
|
-
portrait: { width: 1080, height: 1920, name: "9:16 Portrait" },
|
|
7
|
-
/** 1:1 square (social media) */
|
|
8
|
-
square: { width: 1080, height: 1080, name: "1:1 Square" },
|
|
9
|
-
/** 4:3 standard (legacy) */
|
|
10
|
-
standard: { width: 1440, height: 1080, name: "4:3 Standard" }
|
|
11
|
-
};
|
|
12
|
-
function getViewport(viewport) {
|
|
13
|
-
if (typeof viewport === "string") {
|
|
14
|
-
return VIEWPORT_PRESETS[viewport];
|
|
15
|
-
}
|
|
16
|
-
return viewport;
|
|
17
|
-
}
|
|
18
|
-
var REFERENCE_DIAGONAL = Math.sqrt(1920 * 1920 + 1080 * 1080);
|
|
19
|
-
function calculateFontScale(viewport) {
|
|
20
|
-
const currentDiagonal = Math.sqrt(
|
|
21
|
-
viewport.width * viewport.width + viewport.height * viewport.height
|
|
22
|
-
);
|
|
23
|
-
return currentDiagonal / REFERENCE_DIAGONAL;
|
|
24
|
-
}
|
|
25
|
-
function getViewportOrientation(viewport) {
|
|
26
|
-
const ratio = viewport.width / viewport.height;
|
|
27
|
-
if (Math.abs(ratio - 1) < 0.05) return "square";
|
|
28
|
-
return ratio > 1 ? "landscape" : "portrait";
|
|
29
|
-
}
|
|
30
|
-
function getAspectRatioString(viewport) {
|
|
31
|
-
const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
|
|
32
|
-
const divisor = gcd(viewport.width, viewport.height);
|
|
33
|
-
return `${viewport.width / divisor}:${viewport.height / divisor}`;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// src/schemas/LayoutStrategy.ts
|
|
37
|
-
var LAYOUT_CONFIGS = {
|
|
38
|
-
landscape: {
|
|
39
|
-
primaryY: "35%",
|
|
40
|
-
secondaryY: "55%",
|
|
41
|
-
tertiaryY: "75%",
|
|
42
|
-
titleScale: 1,
|
|
43
|
-
bodyScale: 1,
|
|
44
|
-
columnLeftX: "25%",
|
|
45
|
-
columnRightX: "75%",
|
|
46
|
-
columnTopY: "35%",
|
|
47
|
-
columnBottomY: "65%",
|
|
48
|
-
stackColumns: false,
|
|
49
|
-
maxTextWidth: "80%",
|
|
50
|
-
horizontalPadding: "10%",
|
|
51
|
-
captionY: "85%",
|
|
52
|
-
captionScale: 1
|
|
53
|
-
},
|
|
54
|
-
portrait: {
|
|
55
|
-
// Content positioned higher for thumb-reach zone on mobile
|
|
56
|
-
primaryY: "25%",
|
|
57
|
-
secondaryY: "42%",
|
|
58
|
-
tertiaryY: "58%",
|
|
59
|
-
// Titles scale down for narrower width; body text scales up to fill vertical space
|
|
60
|
-
titleScale: 0.7,
|
|
61
|
-
bodyScale: 1.5,
|
|
62
|
-
// Stacked columns instead of side-by-side
|
|
63
|
-
columnLeftX: "50%",
|
|
64
|
-
columnRightX: "50%",
|
|
65
|
-
columnTopY: "30%",
|
|
66
|
-
columnBottomY: "55%",
|
|
67
|
-
stackColumns: true,
|
|
68
|
-
// Wider relative to viewport to use available space
|
|
69
|
-
maxTextWidth: "90%",
|
|
70
|
-
horizontalPadding: "5%",
|
|
71
|
-
captionY: "75%",
|
|
72
|
-
captionScale: 0.85
|
|
73
|
-
},
|
|
74
|
-
square: {
|
|
75
|
-
primaryY: "30%",
|
|
76
|
-
secondaryY: "50%",
|
|
77
|
-
tertiaryY: "70%",
|
|
78
|
-
titleScale: 0.85,
|
|
79
|
-
bodyScale: 0.9,
|
|
80
|
-
columnLeftX: "25%",
|
|
81
|
-
columnRightX: "75%",
|
|
82
|
-
columnTopY: "35%",
|
|
83
|
-
columnBottomY: "65%",
|
|
84
|
-
stackColumns: false,
|
|
85
|
-
maxTextWidth: "85%",
|
|
86
|
-
horizontalPadding: "7.5%",
|
|
87
|
-
captionY: "82%",
|
|
88
|
-
captionScale: 0.9
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
function getLayoutHints(orientation) {
|
|
92
|
-
return LAYOUT_CONFIGS[orientation];
|
|
93
|
-
}
|
|
94
|
-
function scaledFontSize(basePx, viewport, orientation, isTitle = false) {
|
|
95
|
-
const fontScale = calculateFontScale(viewport);
|
|
96
|
-
const layout = getLayoutHints(orientation);
|
|
97
|
-
const typeScale = isTitle ? layout.titleScale : layout.bodyScale;
|
|
98
|
-
return Math.round(basePx * fontScale * typeScale);
|
|
99
|
-
}
|
|
100
|
-
function getTwoColumnPositions(orientation) {
|
|
101
|
-
const layout = getLayoutHints(orientation);
|
|
102
|
-
if (layout.stackColumns) {
|
|
103
|
-
return {
|
|
104
|
-
left: { x: "50%", y: layout.columnTopY },
|
|
105
|
-
right: { x: "50%", y: layout.columnBottomY }
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
return {
|
|
109
|
-
left: { x: layout.columnLeftX, y: "50%" },
|
|
110
|
-
right: { x: layout.columnRightX, y: "50%" }
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
function getSafeTextBounds(orientation) {
|
|
114
|
-
const layout = getLayoutHints(orientation);
|
|
115
|
-
return {
|
|
116
|
-
left: layout.horizontalPadding,
|
|
117
|
-
right: layout.horizontalPadding,
|
|
118
|
-
top: "10%",
|
|
119
|
-
bottom: "10%"
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// src/schemas/BlockTemplates.ts
|
|
124
|
-
var DEFAULT_DOC_FONT = '"PT Serif", Georgia, "Times New Roman", serif';
|
|
125
|
-
var DEFAULT_TITLE_FONT = '"PT Serif", Georgia, "Times New Roman", serif';
|
|
126
|
-
function isTemplateBlock(block) {
|
|
127
|
-
return "template" in block && typeof block.template === "string";
|
|
128
|
-
}
|
|
129
|
-
function createTemplateContext(theme, blockIndex, totalBlocks, viewport = VIEWPORT_PRESETS.landscape) {
|
|
130
|
-
const orientation = getViewportOrientation(viewport);
|
|
131
|
-
return {
|
|
132
|
-
theme,
|
|
133
|
-
blockIndex,
|
|
134
|
-
totalBlocks,
|
|
135
|
-
viewport,
|
|
136
|
-
fontScale: calculateFontScale(viewport),
|
|
137
|
-
orientation,
|
|
138
|
-
layout: getLayoutHints(orientation)
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
function scaledFontSize2(basePx, context, isTitle = false) {
|
|
142
|
-
return scaledFontSize(basePx, context.viewport, context.orientation, isTitle);
|
|
143
|
-
}
|
|
144
|
-
function isPersistentLayerTemplate(layer) {
|
|
145
|
-
return "template" in layer && typeof layer.template === "string";
|
|
146
|
-
}
|
|
147
|
-
|
|
148
1
|
// src/schemas/themeLibrary.ts
|
|
149
|
-
var
|
|
150
|
-
var
|
|
151
|
-
var
|
|
152
|
-
var
|
|
153
|
-
var
|
|
2
|
+
var SYSTEM_SANS = 'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';
|
|
3
|
+
var SYSTEM_SERIF = 'Georgia, "Times New Roman", serif';
|
|
4
|
+
var SYSTEM_MONO = 'Consolas, "Courier New", monospace';
|
|
5
|
+
var PLAYFAIR = '"Playfair Display", Georgia, serif';
|
|
6
|
+
var SOURCE_SERIF = '"Source Serif 4", "PT Serif", Georgia, serif';
|
|
7
|
+
var INTER = '"Inter", "Segoe UI", Roboto, sans-serif';
|
|
8
|
+
var OSWALD = '"Oswald", Impact, "Arial Black", sans-serif';
|
|
9
|
+
var ROBOTO = '"Roboto", "Segoe UI", Arial, sans-serif';
|
|
10
|
+
var MERRIWEATHER = '"Merriweather", Georgia, serif';
|
|
11
|
+
var LORA = '"Lora", "Merriweather", Georgia, serif';
|
|
12
|
+
var JETBRAINS_MONO = '"JetBrains Mono", "Fira Code", Consolas, monospace';
|
|
13
|
+
var IBM_PLEX_SANS = '"IBM Plex Sans", "Segoe UI", Roboto, sans-serif';
|
|
14
|
+
var DM_SERIF = '"DM Serif Display", Georgia, serif';
|
|
15
|
+
var DM_SANS = '"DM Sans", "Segoe UI", Roboto, sans-serif';
|
|
16
|
+
var CORMORANT = '"Cormorant Garamond", Garamond, Georgia, serif';
|
|
17
|
+
var CRIMSON = '"Crimson Text", Georgia, serif';
|
|
18
|
+
var PT_SERIF = '"PT Serif", Georgia, serif';
|
|
19
|
+
var HANKEN_GROTESK = '"Hanken Grotesk", system-ui, sans-serif';
|
|
154
20
|
var CLASSIC_COLOR_SCHEMES = {
|
|
155
21
|
blue: { bg: "#1a365d", text: "#63b3ed", accent: "#90cdf4" },
|
|
156
22
|
green: { bg: "#22543d", text: "#9ae6b4", accent: "#68d391" },
|
|
@@ -159,10 +25,52 @@ var CLASSIC_COLOR_SCHEMES = {
|
|
|
159
25
|
orange: { bg: "#744210", text: "#fbd38d", accent: "#f6ad55" },
|
|
160
26
|
teal: { bg: "#234e52", text: "#81e6d9", accent: "#4fd1c5" }
|
|
161
27
|
};
|
|
28
|
+
var standard = {
|
|
29
|
+
id: "standard",
|
|
30
|
+
name: "Standard",
|
|
31
|
+
description: "Clean and safe. System fonts only \u2014 no external font dependencies.",
|
|
32
|
+
colors: {
|
|
33
|
+
primary: "#3182ce",
|
|
34
|
+
secondary: "#4a5568",
|
|
35
|
+
background: "#1a202c",
|
|
36
|
+
backgroundLight: "#2d3748",
|
|
37
|
+
text: "#f7fafc",
|
|
38
|
+
textMuted: "#a0aec0",
|
|
39
|
+
highlight: "#4299e1",
|
|
40
|
+
warning: "#fc8181"
|
|
41
|
+
},
|
|
42
|
+
typography: {
|
|
43
|
+
bodyFontFamily: SYSTEM_SANS,
|
|
44
|
+
titleFontFamily: SYSTEM_SERIF,
|
|
45
|
+
monoFontFamily: SYSTEM_MONO,
|
|
46
|
+
titleWeight: "bold"
|
|
47
|
+
},
|
|
48
|
+
style: {
|
|
49
|
+
textShadow: true,
|
|
50
|
+
overlayOpacity: 0.45,
|
|
51
|
+
animationSpeed: 1
|
|
52
|
+
},
|
|
53
|
+
renderStyle: {
|
|
54
|
+
name: "standard",
|
|
55
|
+
defaultTextAnimation: "fadeIn",
|
|
56
|
+
defaultImageAnimation: "slowZoom",
|
|
57
|
+
ambientMotion: true,
|
|
58
|
+
defaultTransition: { type: "fade", duration: 0.7 }
|
|
59
|
+
},
|
|
60
|
+
colorSchemes: CLASSIC_COLOR_SCHEMES,
|
|
61
|
+
persistentLayers: {
|
|
62
|
+
bottomLayers: [
|
|
63
|
+
{
|
|
64
|
+
template: "gradientBackground",
|
|
65
|
+
config: { type: "gradientBackground", preset: "dark-vignette" }
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
};
|
|
162
70
|
var documentary = {
|
|
163
71
|
id: "documentary",
|
|
164
72
|
name: "Documentary",
|
|
165
|
-
description: "Classic dark cinematic look with serif typography.
|
|
73
|
+
description: "Classic dark cinematic look with elegant serif typography.",
|
|
166
74
|
colors: {
|
|
167
75
|
primary: "#3d5a80",
|
|
168
76
|
secondary: "#63b3ed",
|
|
@@ -174,8 +82,8 @@ var documentary = {
|
|
|
174
82
|
warning: "#fc8181"
|
|
175
83
|
},
|
|
176
84
|
typography: {
|
|
177
|
-
bodyFontFamily:
|
|
178
|
-
titleFontFamily:
|
|
85
|
+
bodyFontFamily: SOURCE_SERIF,
|
|
86
|
+
titleFontFamily: PLAYFAIR,
|
|
179
87
|
titleWeight: "bold"
|
|
180
88
|
},
|
|
181
89
|
style: {
|
|
@@ -215,8 +123,8 @@ var minimalist = {
|
|
|
215
123
|
warning: "#e53e3e"
|
|
216
124
|
},
|
|
217
125
|
typography: {
|
|
218
|
-
bodyFontFamily:
|
|
219
|
-
titleFontFamily:
|
|
126
|
+
bodyFontFamily: INTER,
|
|
127
|
+
titleFontFamily: INTER,
|
|
220
128
|
titleWeight: "bold",
|
|
221
129
|
lineHeight: 1.6
|
|
222
130
|
},
|
|
@@ -259,8 +167,8 @@ var bold = {
|
|
|
259
167
|
warning: "#fc8181"
|
|
260
168
|
},
|
|
261
169
|
typography: {
|
|
262
|
-
bodyFontFamily:
|
|
263
|
-
titleFontFamily:
|
|
170
|
+
bodyFontFamily: ROBOTO,
|
|
171
|
+
titleFontFamily: OSWALD,
|
|
264
172
|
titleWeight: "bold",
|
|
265
173
|
titleScale: 1.15,
|
|
266
174
|
bodyScale: 1,
|
|
@@ -306,7 +214,7 @@ var morningLight = {
|
|
|
306
214
|
warning: "#c53030"
|
|
307
215
|
},
|
|
308
216
|
typography: {
|
|
309
|
-
bodyFontFamily:
|
|
217
|
+
bodyFontFamily: LORA,
|
|
310
218
|
titleFontFamily: MERRIWEATHER,
|
|
311
219
|
titleWeight: "bold",
|
|
312
220
|
lineHeight: 1.7
|
|
@@ -347,9 +255,9 @@ var techDark = {
|
|
|
347
255
|
warning: "#ff5252"
|
|
348
256
|
},
|
|
349
257
|
typography: {
|
|
350
|
-
bodyFontFamily:
|
|
351
|
-
titleFontFamily:
|
|
352
|
-
monoFontFamily:
|
|
258
|
+
bodyFontFamily: IBM_PLEX_SANS,
|
|
259
|
+
titleFontFamily: JETBRAINS_MONO,
|
|
260
|
+
monoFontFamily: JETBRAINS_MONO,
|
|
353
261
|
titleWeight: "bold",
|
|
354
262
|
titleScale: 0.9,
|
|
355
263
|
lineHeight: 1.5
|
|
@@ -394,8 +302,8 @@ var magazine = {
|
|
|
394
302
|
warning: "#fc8181"
|
|
395
303
|
},
|
|
396
304
|
typography: {
|
|
397
|
-
bodyFontFamily:
|
|
398
|
-
titleFontFamily:
|
|
305
|
+
bodyFontFamily: DM_SANS,
|
|
306
|
+
titleFontFamily: DM_SERIF,
|
|
399
307
|
titleWeight: "bold",
|
|
400
308
|
titleScale: 1.05,
|
|
401
309
|
lineHeight: 1.5
|
|
@@ -437,8 +345,8 @@ var cinematic = {
|
|
|
437
345
|
warning: "#fc8181"
|
|
438
346
|
},
|
|
439
347
|
typography: {
|
|
440
|
-
bodyFontFamily:
|
|
441
|
-
titleFontFamily:
|
|
348
|
+
bodyFontFamily: CRIMSON,
|
|
349
|
+
titleFontFamily: CORMORANT,
|
|
442
350
|
titleWeight: "bold",
|
|
443
351
|
lineHeight: 1.5,
|
|
444
352
|
titleLineHeight: 1.2
|
|
@@ -490,8 +398,8 @@ var warmEarth = {
|
|
|
490
398
|
warning: "#e53e3e"
|
|
491
399
|
},
|
|
492
400
|
typography: {
|
|
493
|
-
bodyFontFamily:
|
|
494
|
-
titleFontFamily:
|
|
401
|
+
bodyFontFamily: HANKEN_GROTESK,
|
|
402
|
+
titleFontFamily: PT_SERIF,
|
|
495
403
|
titleWeight: "bold",
|
|
496
404
|
lineHeight: 1.6
|
|
497
405
|
},
|
|
@@ -525,6 +433,7 @@ var warmEarth = {
|
|
|
525
433
|
}
|
|
526
434
|
};
|
|
527
435
|
var THEMES = {
|
|
436
|
+
standard,
|
|
528
437
|
documentary,
|
|
529
438
|
minimalist,
|
|
530
439
|
bold,
|
|
@@ -534,8 +443,8 @@ var THEMES = {
|
|
|
534
443
|
cinematic,
|
|
535
444
|
"warm-earth": warmEarth
|
|
536
445
|
};
|
|
537
|
-
var DEFAULT_THEME_ID = "
|
|
538
|
-
var DEFAULT_THEME =
|
|
446
|
+
var DEFAULT_THEME_ID = "standard";
|
|
447
|
+
var DEFAULT_THEME = standard;
|
|
539
448
|
function resolveTheme(id) {
|
|
540
449
|
if (id && id in THEMES) return THEMES[id];
|
|
541
450
|
return DEFAULT_THEME;
|
|
@@ -552,21 +461,6 @@ function getThemeSummaries() {
|
|
|
552
461
|
}
|
|
553
462
|
|
|
554
463
|
export {
|
|
555
|
-
VIEWPORT_PRESETS,
|
|
556
|
-
getViewport,
|
|
557
|
-
calculateFontScale,
|
|
558
|
-
getViewportOrientation,
|
|
559
|
-
getAspectRatioString,
|
|
560
|
-
getLayoutHints,
|
|
561
|
-
scaledFontSize,
|
|
562
|
-
getTwoColumnPositions,
|
|
563
|
-
getSafeTextBounds,
|
|
564
|
-
DEFAULT_DOC_FONT,
|
|
565
|
-
DEFAULT_TITLE_FONT,
|
|
566
|
-
isTemplateBlock,
|
|
567
|
-
createTemplateContext,
|
|
568
|
-
scaledFontSize2,
|
|
569
|
-
isPersistentLayerTemplate,
|
|
570
464
|
THEMES,
|
|
571
465
|
DEFAULT_THEME_ID,
|
|
572
466
|
DEFAULT_THEME,
|
|
@@ -574,4 +468,4 @@ export {
|
|
|
574
468
|
getAvailableThemes,
|
|
575
469
|
getThemeSummaries
|
|
576
470
|
};
|
|
577
|
-
//# sourceMappingURL=chunk-
|
|
471
|
+
//# sourceMappingURL=chunk-TVPKD76V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schemas/themeLibrary.ts"],"sourcesContent":["/**\n * Built-in Theme Library\n *\n * Ships 8 curated themes covering documentary, editorial, minimal, and\n * cinematic styles. Each theme is fully JSON-serializable.\n *\n * Usage:\n * ```ts\n * import { THEMES, resolveTheme } from '@bendyline/squisq/schemas';\n *\n * const theme = resolveTheme('minimalist'); // look up by id\n * const theme = THEMES.documentary; // direct access\n * ```\n */\n\nimport type { Theme, ThemeColorScheme } from './Theme.js';\n\n// ============================================\n// Shared constants\n// ============================================\n\n// ── Font stacks ──────────────────────────────────────────────────\n// Each stack lists the recommended Google Font first (works when the\n// wrapping site loads it), then degrades to safe system fonts.\n// Squisq itself does NOT load Google Fonts.\n\n/** System fonts only — no external dependencies. */\nconst SYSTEM_SANS = 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif';\nconst SYSTEM_SERIF = 'Georgia, \"Times New Roman\", serif';\nconst SYSTEM_MONO = 'Consolas, \"Courier New\", monospace';\n\n/** Theme-specific stacks with Google Font leads. */\nconst PLAYFAIR = '\"Playfair Display\", Georgia, serif';\nconst SOURCE_SERIF = '\"Source Serif 4\", \"PT Serif\", Georgia, serif';\nconst INTER = '\"Inter\", \"Segoe UI\", Roboto, sans-serif';\nconst OSWALD = '\"Oswald\", Impact, \"Arial Black\", sans-serif';\nconst ROBOTO = '\"Roboto\", \"Segoe UI\", Arial, sans-serif';\nconst MERRIWEATHER = '\"Merriweather\", Georgia, serif';\nconst LORA = '\"Lora\", \"Merriweather\", Georgia, serif';\nconst JETBRAINS_MONO = '\"JetBrains Mono\", \"Fira Code\", Consolas, monospace';\nconst IBM_PLEX_SANS = '\"IBM Plex Sans\", \"Segoe UI\", Roboto, sans-serif';\nconst DM_SERIF = '\"DM Serif Display\", Georgia, serif';\nconst DM_SANS = '\"DM Sans\", \"Segoe UI\", Roboto, sans-serif';\nconst CORMORANT = '\"Cormorant Garamond\", Garamond, Georgia, serif';\nconst CRIMSON = '\"Crimson Text\", Georgia, serif';\nconst PT_SERIF = '\"PT Serif\", Georgia, serif';\nconst HANKEN_GROTESK = '\"Hanken Grotesk\", system-ui, sans-serif';\n\n/** Standard 6-scheme set used by the documentary theme (migrated from old COLOR_SCHEMES). */\nconst CLASSIC_COLOR_SCHEMES: Record<string, ThemeColorScheme> = {\n blue: { bg: '#1a365d', text: '#63b3ed', accent: '#90cdf4' },\n green: { bg: '#22543d', text: '#9ae6b4', accent: '#68d391' },\n purple: { bg: '#44337a', text: '#d6bcfa', accent: '#b794f4' },\n red: { bg: '#742a2a', text: '#fc8181', accent: '#feb2b2' },\n orange: { bg: '#744210', text: '#fbd38d', accent: '#f6ad55' },\n teal: { bg: '#234e52', text: '#81e6d9', accent: '#4fd1c5' },\n};\n\n// ============================================\n// 1. Standard (default — safe system fonts, no external dependencies)\n// ============================================\n\nconst standard: Theme = {\n id: 'standard',\n name: 'Standard',\n description: 'Clean and safe. System fonts only — no external font dependencies.',\n colors: {\n primary: '#3182ce',\n secondary: '#4a5568',\n background: '#1a202c',\n backgroundLight: '#2d3748',\n text: '#f7fafc',\n textMuted: '#a0aec0',\n highlight: '#4299e1',\n warning: '#fc8181',\n },\n typography: {\n bodyFontFamily: SYSTEM_SANS,\n titleFontFamily: SYSTEM_SERIF,\n monoFontFamily: SYSTEM_MONO,\n titleWeight: 'bold',\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.45,\n animationSpeed: 1.0,\n },\n renderStyle: {\n name: 'standard',\n defaultTextAnimation: 'fadeIn',\n defaultImageAnimation: 'slowZoom',\n ambientMotion: true,\n defaultTransition: { type: 'fade', duration: 0.7 },\n },\n colorSchemes: CLASSIC_COLOR_SCHEMES,\n persistentLayers: {\n bottomLayers: [\n {\n template: 'gradientBackground',\n config: { type: 'gradientBackground', preset: 'dark-vignette' },\n },\n ],\n },\n};\n\n// ============================================\n// 2. Documentary\n// ============================================\n\nconst documentary: Theme = {\n id: 'documentary',\n name: 'Documentary',\n description: 'Classic dark cinematic look with elegant serif typography.',\n colors: {\n primary: '#3d5a80',\n secondary: '#63b3ed',\n background: '#1a202c',\n backgroundLight: '#2d3748',\n text: '#ffffff',\n textMuted: '#a0aec0',\n highlight: '#63b3ed',\n warning: '#fc8181',\n },\n typography: {\n bodyFontFamily: SOURCE_SERIF,\n titleFontFamily: PLAYFAIR,\n titleWeight: 'bold',\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.5,\n animationSpeed: 1.0,\n },\n renderStyle: {\n name: 'documentary',\n defaultTextAnimation: 'fadeIn',\n defaultImageAnimation: 'slowZoom',\n ambientMotion: true,\n defaultTransition: { type: 'fade', duration: 0.8 },\n },\n colorSchemes: CLASSIC_COLOR_SCHEMES,\n persistentLayers: {\n bottomLayers: [\n {\n template: 'gradientBackground',\n config: { type: 'gradientBackground', preset: 'dark-vignette' },\n },\n ],\n },\n};\n\n// ============================================\n// 2. Minimalist\n// ============================================\n\nconst minimalist: Theme = {\n id: 'minimalist',\n name: 'Minimalist',\n description: 'Clean near-white background with sans-serif type and minimal animation.',\n colors: {\n primary: '#2d3748',\n secondary: '#4a5568',\n background: '#f7fafc',\n backgroundLight: '#edf2f7',\n text: '#1a202c',\n textMuted: '#718096',\n highlight: '#3182ce',\n warning: '#e53e3e',\n },\n typography: {\n bodyFontFamily: INTER,\n titleFontFamily: INTER,\n titleWeight: 'bold',\n lineHeight: 1.6,\n },\n style: {\n textShadow: false,\n overlayOpacity: 0.3,\n animationSpeed: 1.2,\n borderRadius: 8,\n },\n renderStyle: {\n name: 'minimalist',\n defaultTextAnimation: 'fadeIn',\n ambientMotion: false,\n defaultTransition: { type: 'fade', duration: 0.6 },\n templateHints: {\n titleBlock: { showAccentLine: false },\n },\n },\n colorSchemes: {\n blue: { bg: '#ebf8ff', text: '#2b6cb0', accent: '#3182ce' },\n green: { bg: '#f0fff4', text: '#276749', accent: '#38a169' },\n purple: { bg: '#faf5ff', text: '#553c9a', accent: '#805ad5' },\n red: { bg: '#fff5f5', text: '#c53030', accent: '#e53e3e' },\n orange: { bg: '#fffaf0', text: '#c05621', accent: '#dd6b20' },\n teal: { bg: '#e6fffa', text: '#285e61', accent: '#319795' },\n },\n};\n\n// ============================================\n// 3. Bold\n// ============================================\n\nconst bold: Theme = {\n id: 'bold',\n name: 'Bold',\n description: 'High-contrast black with vivid accents and dramatic animations.',\n colors: {\n primary: '#e53e3e',\n secondary: '#ed8936',\n background: '#000000',\n backgroundLight: '#1a1a1a',\n text: '#ffffff',\n textMuted: '#cbd5e0',\n highlight: '#f6e05e',\n warning: '#fc8181',\n },\n typography: {\n bodyFontFamily: ROBOTO,\n titleFontFamily: OSWALD,\n titleWeight: 'bold',\n titleScale: 1.15,\n bodyScale: 1.0,\n titleLineHeight: 1.1,\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.6,\n animationSpeed: 0.8,\n },\n renderStyle: {\n name: 'bold',\n defaultTextAnimation: 'zoomIn',\n defaultImageAnimation: 'slowZoom',\n ambientMotion: true,\n defaultTransition: { type: 'dissolve', duration: 0.5 },\n templateHints: {\n statHighlight: { entrance: 'dramatic' },\n fullBleedQuote: { entrance: 'dramatic' },\n },\n },\n colorSchemes: {\n blue: { bg: '#1a202c', text: '#63b3ed', accent: '#90cdf4' },\n green: { bg: '#1a202c', text: '#48bb78', accent: '#68d391' },\n purple: { bg: '#1a202c', text: '#b794f4', accent: '#d6bcfa' },\n red: { bg: '#1a202c', text: '#fc8181', accent: '#feb2b2' },\n orange: { bg: '#1a202c', text: '#f6ad55', accent: '#fbd38d' },\n teal: { bg: '#1a202c', text: '#4fd1c5', accent: '#81e6d9' },\n },\n};\n\n// ============================================\n// 4. Morning Light\n// ============================================\n\nconst morningLight: Theme = {\n id: 'morning-light',\n name: 'Morning Light',\n description: 'Warm light background with dark text and gentle serif typography.',\n colors: {\n primary: '#744210',\n secondary: '#975a16',\n background: '#faf8f5',\n backgroundLight: '#f5f0eb',\n text: '#2d3748',\n textMuted: '#718096',\n highlight: '#dd6b20',\n warning: '#c53030',\n },\n typography: {\n bodyFontFamily: LORA,\n titleFontFamily: MERRIWEATHER,\n titleWeight: 'bold',\n lineHeight: 1.7,\n },\n style: {\n textShadow: false,\n overlayOpacity: 0.35,\n animationSpeed: 1.1,\n borderRadius: 4,\n },\n renderStyle: {\n name: 'morning-light',\n defaultTextAnimation: 'fadeIn',\n ambientMotion: false,\n defaultTransition: { type: 'fade', duration: 1.0 },\n },\n colorSchemes: {\n blue: { bg: '#ebf8ff', text: '#2c5282', accent: '#4299e1' },\n green: { bg: '#f0fff4', text: '#22543d', accent: '#48bb78' },\n purple: { bg: '#faf5ff', text: '#44337a', accent: '#9f7aea' },\n red: { bg: '#fff5f5', text: '#9b2c2c', accent: '#fc8181' },\n orange: { bg: '#fffaf0', text: '#744210', accent: '#ed8936' },\n teal: { bg: '#e6fffa', text: '#234e52', accent: '#38b2ac' },\n },\n};\n\n// ============================================\n// 5. Tech Dark\n// ============================================\n\nconst techDark: Theme = {\n id: 'tech-dark',\n name: 'Tech Dark',\n description: 'True black with neon cyan/green accents and monospace titles.',\n colors: {\n primary: '#00e5ff',\n secondary: '#00e676',\n background: '#0a0a0a',\n backgroundLight: '#1a1a2e',\n text: '#e0e0e0',\n textMuted: '#9e9e9e',\n highlight: '#00e5ff',\n warning: '#ff5252',\n },\n typography: {\n bodyFontFamily: IBM_PLEX_SANS,\n titleFontFamily: JETBRAINS_MONO,\n monoFontFamily: JETBRAINS_MONO,\n titleWeight: 'bold',\n titleScale: 0.9,\n lineHeight: 1.5,\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.55,\n animationSpeed: 0.9,\n borderRadius: 2,\n },\n renderStyle: {\n name: 'tech-dark',\n defaultTextAnimation: 'typewriter',\n defaultImageAnimation: 'slowZoom',\n ambientMotion: true,\n defaultTransition: { type: 'dissolve', duration: 0.4 },\n templateHints: {\n statHighlight: { entrance: 'dramatic' },\n },\n },\n colorSchemes: {\n blue: { bg: '#0d1b2a', text: '#00b0ff', accent: '#40c4ff' },\n green: { bg: '#0d1b0d', text: '#00e676', accent: '#69f0ae' },\n purple: { bg: '#1a0d2e', text: '#d500f9', accent: '#ea80fc' },\n red: { bg: '#2e0d0d', text: '#ff5252', accent: '#ff8a80' },\n orange: { bg: '#2e1a0d', text: '#ff9100', accent: '#ffab40' },\n teal: { bg: '#0d2e2e', text: '#1de9b6', accent: '#64ffda' },\n },\n};\n\n// ============================================\n// 6. Magazine\n// ============================================\n\nconst magazine: Theme = {\n id: 'magazine',\n name: 'Magazine',\n description: 'Rich editorial palette with mixed serif/sans typography and slide transitions.',\n colors: {\n primary: '#c53030',\n secondary: '#2b6cb0',\n background: '#1a202c',\n backgroundLight: '#2d3748',\n text: '#f7fafc',\n textMuted: '#cbd5e0',\n highlight: '#ed8936',\n warning: '#fc8181',\n },\n typography: {\n bodyFontFamily: DM_SANS,\n titleFontFamily: DM_SERIF,\n titleWeight: 'bold',\n titleScale: 1.05,\n lineHeight: 1.5,\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.45,\n animationSpeed: 1.0,\n borderRadius: 6,\n },\n renderStyle: {\n name: 'magazine',\n defaultTextAnimation: 'fadeIn',\n defaultImageAnimation: 'slowZoom',\n ambientMotion: true,\n defaultTransition: { type: 'slideLeft', duration: 0.7 },\n },\n colorSchemes: {\n blue: { bg: '#1a365d', text: '#90cdf4', accent: '#63b3ed' },\n green: { bg: '#1c4532', text: '#9ae6b4', accent: '#68d391' },\n purple: { bg: '#322659', text: '#d6bcfa', accent: '#b794f4' },\n red: { bg: '#63171b', text: '#feb2b2', accent: '#fc8181' },\n orange: { bg: '#652b19', text: '#fbd38d', accent: '#f6ad55' },\n teal: { bg: '#1d4044', text: '#81e6d9', accent: '#4fd1c5' },\n },\n};\n\n// ============================================\n// 7. Cinematic\n// ============================================\n\nconst cinematic: Theme = {\n id: 'cinematic',\n name: 'Cinematic',\n description: 'Ultra-dark with moody gradients, gold accents, and slow dissolve transitions.',\n colors: {\n primary: '#d69e2e',\n secondary: '#b7791f',\n background: '#0a0f1a',\n backgroundLight: '#1a202c',\n text: '#f7fafc',\n textMuted: '#a0aec0',\n highlight: '#ecc94b',\n warning: '#fc8181',\n },\n typography: {\n bodyFontFamily: CRIMSON,\n titleFontFamily: CORMORANT,\n titleWeight: 'bold',\n lineHeight: 1.5,\n titleLineHeight: 1.2,\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.55,\n animationSpeed: 1.2,\n },\n renderStyle: {\n name: 'cinematic',\n defaultTextAnimation: 'fadeIn',\n defaultImageAnimation: 'slowZoom',\n ambientMotion: true,\n defaultTransition: { type: 'dissolve', duration: 1.2 },\n templateHints: {\n titleBlock: { showAccentLine: true },\n },\n },\n colorSchemes: {\n blue: { bg: '#0d1b2a', text: '#90cdf4', accent: '#63b3ed' },\n green: { bg: '#0d1b14', text: '#9ae6b4', accent: '#68d391' },\n purple: { bg: '#1a0d2e', text: '#d6bcfa', accent: '#b794f4' },\n red: { bg: '#2a0d0d', text: '#fc8181', accent: '#feb2b2' },\n orange: { bg: '#2a1a0d', text: '#fbd38d', accent: '#f6ad55' },\n teal: { bg: '#0d2a2a', text: '#81e6d9', accent: '#4fd1c5' },\n },\n persistentLayers: {\n bottomLayers: [\n {\n template: 'gradientBackground',\n config: { type: 'gradientBackground', preset: 'radial-dark' },\n },\n ],\n },\n};\n\n// ============================================\n// 8. Warm Earth\n// ============================================\n\nconst warmEarth: Theme = {\n id: 'warm-earth',\n name: 'Warm Earth',\n description: 'Natural warm tones with earthy browns and terracotta accents.',\n colors: {\n primary: '#9c4221',\n secondary: '#c05621',\n background: '#1c1410',\n backgroundLight: '#2d241e',\n text: '#faf5f0',\n textMuted: '#c4a882',\n highlight: '#dd6b20',\n warning: '#e53e3e',\n },\n typography: {\n bodyFontFamily: HANKEN_GROTESK,\n titleFontFamily: PT_SERIF,\n titleWeight: 'bold',\n lineHeight: 1.6,\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.5,\n animationSpeed: 1.1,\n },\n renderStyle: {\n name: 'warm-earth',\n defaultTextAnimation: 'fadeIn',\n defaultImageAnimation: 'panLeft',\n ambientMotion: true,\n defaultTransition: { type: 'fade', duration: 0.9 },\n },\n colorSchemes: {\n blue: { bg: '#2a1f14', text: '#90cdf4', accent: '#63b3ed' },\n green: { bg: '#1e2a14', text: '#9ae6b4', accent: '#68d391' },\n purple: { bg: '#2a142a', text: '#d6bcfa', accent: '#b794f4' },\n red: { bg: '#2a1414', text: '#fc8181', accent: '#feb2b2' },\n orange: { bg: '#2a1e0a', text: '#fbd38d', accent: '#f6ad55' },\n teal: { bg: '#142a28', text: '#81e6d9', accent: '#4fd1c5' },\n },\n persistentLayers: {\n bottomLayers: [\n {\n template: 'gradientBackground',\n config: { type: 'gradientBackground', preset: 'earth-tones' },\n },\n ],\n },\n};\n\n// ============================================\n// Theme Library\n// ============================================\n\n/**\n * All built-in themes, keyed by id.\n */\nexport const THEMES: Record<string, Theme> = {\n standard,\n documentary,\n minimalist,\n bold,\n 'morning-light': morningLight,\n 'tech-dark': techDark,\n magazine,\n cinematic,\n 'warm-earth': warmEarth,\n};\n\n/** The default theme id. */\nexport const DEFAULT_THEME_ID = 'standard';\n\n/** The default theme (standard — safe system fonts, no external dependencies). */\nexport const DEFAULT_THEME: Theme = standard;\n\n/**\n * Resolve a theme by id. Returns the default theme when `id` is\n * undefined or not found in the library.\n */\nexport function resolveTheme(id: string | undefined): Theme {\n if (id && id in THEMES) return THEMES[id];\n return DEFAULT_THEME;\n}\n\n/**\n * Get all available theme ids.\n */\nexport function getAvailableThemes(): string[] {\n return Object.keys(THEMES);\n}\n\n/**\n * Get a summary of all themes (id + name + description) for theme pickers.\n */\nexport function getThemeSummaries(): Array<{ id: string; name: string; description?: string }> {\n return Object.values(THEMES).map((t) => ({\n id: t.id,\n name: t.name,\n description: t.description,\n }));\n}\n"],"mappings":"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","names":[]}
|