@bendyline/squisq 1.1.0 → 1.1.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/ContentContainer-DNx460y8.d.ts +88 -0
- package/dist/{Doc-1hmT1LZl.d.ts → Doc-Cvt2lyzn.d.ts} +56 -4
- package/dist/__tests__/markdownToDoc.test.js +75 -0
- package/dist/__tests__/markdownToDoc.test.js.map +1 -1
- package/dist/{chunk-PJ7AODIM.js → chunk-3WBJAZZ5.js} +394 -52
- package/dist/chunk-3WBJAZZ5.js.map +1 -0
- package/dist/{chunk-6YJPI6VI.js → chunk-4X3JQXNM.js} +1 -1
- package/dist/{chunk-S4F2RY37.js → chunk-CORGFIFU.js} +1 -1
- package/dist/chunk-CORGFIFU.js.map +1 -0
- package/dist/chunk-DNJKBAI7.js +1 -0
- package/dist/chunk-DNJKBAI7.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-OFU53HI7.js +165 -0
- package/dist/chunk-OFU53HI7.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/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/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 +2 -2
- 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 +52 -0
- 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 +50 -5
- package/dist/story/index.js +15 -5
- package/dist/{themeLibrary-DR1VRo-8.d.ts → themeLibrary-VOHfPzRB.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__/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/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/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 +2 -2
- package/src/schemas/Doc.ts +60 -0
- 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
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import type { Layer } from '../../schemas/Doc.js';
|
|
14
14
|
import type { FactCardInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
15
15
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
16
|
+
import { getThemeFont } from '../utils/themeUtils.js';
|
|
16
17
|
import { createAccentLayers, getAccentLayout, adjustY, DEFAULT_LAYOUT } from './accentImage.js';
|
|
17
18
|
import { createBackgroundLayer } from './captionUtils.js';
|
|
18
19
|
|
|
@@ -48,6 +49,7 @@ export function factCard(input: FactCardInput, context: TemplateContext): Layer[
|
|
|
48
49
|
text: fact,
|
|
49
50
|
style: {
|
|
50
51
|
fontSize: factFontSize,
|
|
52
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
51
53
|
fontWeight: 'bold',
|
|
52
54
|
color: theme.colors.text,
|
|
53
55
|
textAlign: 'center',
|
|
@@ -72,6 +74,7 @@ export function factCard(input: FactCardInput, context: TemplateContext): Layer[
|
|
|
72
74
|
text: explanation,
|
|
73
75
|
style: {
|
|
74
76
|
fontSize: explainFontSize,
|
|
77
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
75
78
|
color: theme.colors.textMuted,
|
|
76
79
|
textAlign: 'center',
|
|
77
80
|
lineHeight: 1.5,
|
|
@@ -96,6 +99,7 @@ export function factCard(input: FactCardInput, context: TemplateContext): Layer[
|
|
|
96
99
|
text: source,
|
|
97
100
|
style: {
|
|
98
101
|
fontSize: sourceFontSize,
|
|
102
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
99
103
|
color: theme.colors.textMuted,
|
|
100
104
|
textAlign: 'center',
|
|
101
105
|
shadow: !!accentImage,
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import type { Layer } from '../../schemas/Doc.js';
|
|
12
12
|
import type { FullBleedQuoteInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
13
13
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
14
|
-
import { resolveColorScheme } from '../utils/themeUtils.js';
|
|
14
|
+
import { resolveColorScheme, getThemeFont } from '../utils/themeUtils.js';
|
|
15
15
|
|
|
16
16
|
export function fullBleedQuote(input: FullBleedQuoteInput, context: TemplateContext): Layer[] {
|
|
17
17
|
const { text, colorScheme = 'blue' } = input;
|
|
@@ -40,6 +40,7 @@ export function fullBleedQuote(input: FullBleedQuoteInput, context: TemplateCont
|
|
|
40
40
|
text,
|
|
41
41
|
style: {
|
|
42
42
|
fontSize: textFontSize,
|
|
43
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
43
44
|
fontWeight: 'bold',
|
|
44
45
|
color: colors.text,
|
|
45
46
|
textAlign: 'center',
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import type { Layer } from '../../schemas/Doc.js';
|
|
12
12
|
import type { ImageWithCaptionInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
13
13
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
14
|
+
import { getThemeFont } from '../utils/themeUtils.js';
|
|
14
15
|
import { cleanCaption } from './captionUtils.js';
|
|
15
16
|
import { mapAmbientMotion } from './accentImage.js';
|
|
16
17
|
|
|
@@ -80,6 +81,7 @@ export function imageWithCaption(input: ImageWithCaptionInput, context: Template
|
|
|
80
81
|
text: caption,
|
|
81
82
|
style: {
|
|
82
83
|
fontSize: titleFontSize,
|
|
84
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
83
85
|
fontWeight: 'bold',
|
|
84
86
|
color: theme.colors.text,
|
|
85
87
|
textAlign: 'center',
|
|
@@ -104,6 +106,7 @@ export function imageWithCaption(input: ImageWithCaptionInput, context: Template
|
|
|
104
106
|
text: subtitle,
|
|
105
107
|
style: {
|
|
106
108
|
fontSize: subtitleFontSize,
|
|
109
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
107
110
|
color: theme.colors.textMuted,
|
|
108
111
|
textAlign: 'center',
|
|
109
112
|
lineHeight: 1.5,
|
|
@@ -148,6 +151,7 @@ export function imageWithCaption(input: ImageWithCaptionInput, context: Template
|
|
|
148
151
|
text: caption,
|
|
149
152
|
style: {
|
|
150
153
|
fontSize: captionFontSize,
|
|
154
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
151
155
|
color: theme.colors.text,
|
|
152
156
|
textAlign: 'center',
|
|
153
157
|
shadow: true,
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import type { Layer } from '../../schemas/Doc.js';
|
|
12
12
|
import type { ListBlockInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
13
13
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
14
|
+
import { getThemeFont } from '../utils/themeUtils.js';
|
|
14
15
|
import { createAccentLayers, getAccentLayout, adjustY, DEFAULT_LAYOUT } from './accentImage.js';
|
|
15
16
|
|
|
16
17
|
export function listBlock(input: ListBlockInput, context: TemplateContext): Layer[] {
|
|
@@ -51,6 +52,7 @@ export function listBlock(input: ListBlockInput, context: TemplateContext): Laye
|
|
|
51
52
|
text: title,
|
|
52
53
|
style: {
|
|
53
54
|
fontSize: titleFontSize,
|
|
55
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
54
56
|
fontWeight: 'bold',
|
|
55
57
|
color: theme.colors.text,
|
|
56
58
|
textAlign: 'center',
|
|
@@ -82,6 +84,7 @@ export function listBlock(input: ListBlockInput, context: TemplateContext): Laye
|
|
|
82
84
|
text: itemText,
|
|
83
85
|
style: {
|
|
84
86
|
fontSize: itemFontSize,
|
|
87
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
85
88
|
color: theme.colors.text,
|
|
86
89
|
lineHeight: 1.4,
|
|
87
90
|
shadow: !!accentImage,
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import type { Layer } from '../../schemas/Doc.js';
|
|
16
16
|
import type { MapBlockInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
17
17
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
18
|
+
import { getThemeFont } from '../utils/themeUtils.js';
|
|
18
19
|
import { mapAmbientMotion } from './accentImage.js';
|
|
19
20
|
|
|
20
21
|
export function mapBlock(input: MapBlockInput, context: TemplateContext): Layer[] {
|
|
@@ -76,6 +77,7 @@ export function mapBlock(input: MapBlockInput, context: TemplateContext): Layer[
|
|
|
76
77
|
text: title,
|
|
77
78
|
style: {
|
|
78
79
|
fontSize: titleFontSize,
|
|
80
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
79
81
|
fontWeight: 'bold',
|
|
80
82
|
color: theme.colors.text,
|
|
81
83
|
textAlign: 'center',
|
|
@@ -113,6 +115,7 @@ export function mapBlock(input: MapBlockInput, context: TemplateContext): Layer[
|
|
|
113
115
|
text: caption,
|
|
114
116
|
style: {
|
|
115
117
|
fontSize: captionFontSize,
|
|
118
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
116
119
|
color: theme.colors.text,
|
|
117
120
|
textAlign: 'center',
|
|
118
121
|
shadow: true,
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import type { Layer } from '../../schemas/Doc.js';
|
|
19
19
|
import type { PhotoGridInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
20
20
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
21
|
+
import { getThemeFont } from '../utils/themeUtils.js';
|
|
21
22
|
import { cleanCaption } from './captionUtils.js';
|
|
22
23
|
|
|
23
24
|
/** Gap between images as percentage */
|
|
@@ -72,6 +73,7 @@ export function photoGrid(input: PhotoGridInput, context: TemplateContext): Laye
|
|
|
72
73
|
text: img.alt,
|
|
73
74
|
style: {
|
|
74
75
|
fontSize: altFontSize,
|
|
76
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
75
77
|
color: theme.colors.textMuted,
|
|
76
78
|
textAlign: 'center' as const,
|
|
77
79
|
},
|
|
@@ -126,6 +128,7 @@ export function photoGrid(input: PhotoGridInput, context: TemplateContext): Laye
|
|
|
126
128
|
text: caption,
|
|
127
129
|
style: {
|
|
128
130
|
fontSize: captionFontSize,
|
|
131
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
129
132
|
color: theme.colors.text,
|
|
130
133
|
textAlign: 'center',
|
|
131
134
|
shadow: true,
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import type { Layer } from '../../schemas/Doc.js';
|
|
12
12
|
import type { PullQuoteInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
13
13
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
14
|
+
import { getThemeFont } from '../utils/themeUtils.js';
|
|
14
15
|
|
|
15
16
|
export function pullQuote(input: PullQuoteInput, context: TemplateContext): Layer[] {
|
|
16
17
|
const { text, attribution, backgroundImage, ambientMotion } = input;
|
|
@@ -57,6 +58,7 @@ export function pullQuote(input: PullQuoteInput, context: TemplateContext): Laye
|
|
|
57
58
|
text: '\u201C',
|
|
58
59
|
style: {
|
|
59
60
|
fontSize: decoFontSize,
|
|
61
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
60
62
|
color: 'rgba(255, 255, 255, 0.08)',
|
|
61
63
|
textAlign: 'center',
|
|
62
64
|
},
|
|
@@ -76,6 +78,7 @@ export function pullQuote(input: PullQuoteInput, context: TemplateContext): Laye
|
|
|
76
78
|
text,
|
|
77
79
|
style: {
|
|
78
80
|
fontSize: quoteFontSize,
|
|
81
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
79
82
|
color: '#ffffff',
|
|
80
83
|
textAlign: 'center',
|
|
81
84
|
lineHeight: 1.5,
|
|
@@ -101,6 +104,7 @@ export function pullQuote(input: PullQuoteInput, context: TemplateContext): Laye
|
|
|
101
104
|
text: `\u2014 ${attribution}`,
|
|
102
105
|
style: {
|
|
103
106
|
fontSize: attrFontSize,
|
|
107
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
104
108
|
color: 'rgba(255, 255, 255, 0.7)',
|
|
105
109
|
textAlign: 'center',
|
|
106
110
|
shadow: true,
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import type { Layer } from '../../schemas/Doc.js';
|
|
14
14
|
import type { QuoteBlockInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
15
15
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
16
|
+
import { getThemeFont } from '../utils/themeUtils.js';
|
|
16
17
|
import { createAccentLayers, getAccentLayout, adjustY, DEFAULT_LAYOUT } from './accentImage.js';
|
|
17
18
|
import { createBackgroundLayer } from './captionUtils.js';
|
|
18
19
|
|
|
@@ -50,6 +51,7 @@ export function quoteBlock(input: QuoteBlockInput, context: TemplateContext): La
|
|
|
50
51
|
text: '\u201C',
|
|
51
52
|
style: {
|
|
52
53
|
fontSize: decorativeQuoteFontSize,
|
|
54
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
53
55
|
color: 'rgba(255, 255, 255, 0.06)',
|
|
54
56
|
textAlign: 'center',
|
|
55
57
|
},
|
|
@@ -70,6 +72,7 @@ export function quoteBlock(input: QuoteBlockInput, context: TemplateContext): La
|
|
|
70
72
|
text: quote,
|
|
71
73
|
style: {
|
|
72
74
|
fontSize: quoteFontSize,
|
|
75
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
73
76
|
color: theme.colors.text,
|
|
74
77
|
textAlign: 'center',
|
|
75
78
|
lineHeight: 1.6,
|
|
@@ -94,6 +97,7 @@ export function quoteBlock(input: QuoteBlockInput, context: TemplateContext): La
|
|
|
94
97
|
text: `— ${attribution}`,
|
|
95
98
|
style: {
|
|
96
99
|
fontSize: attrFontSize,
|
|
100
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
97
101
|
color: theme.colors.textMuted,
|
|
98
102
|
textAlign: 'center',
|
|
99
103
|
shadow: !!accentImage,
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
import type { Layer, AnimationType } from '../../schemas/Doc.js';
|
|
13
13
|
import type { SectionHeaderInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
14
14
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
15
|
-
import { resolveColorScheme } from '../utils/themeUtils.js';
|
|
15
|
+
import { resolveColorScheme, getThemeFont } from '../utils/themeUtils.js';
|
|
16
16
|
|
|
17
17
|
export function sectionHeader(input: SectionHeaderInput, context: TemplateContext): Layer[] {
|
|
18
|
-
const { title, colorScheme = 'blue', imageSrc, imageAlt, ambientMotion } = input;
|
|
18
|
+
const { title = '', colorScheme = 'blue', imageSrc, imageAlt, ambientMotion } = input;
|
|
19
19
|
const { layout } = context;
|
|
20
20
|
const colors = resolveColorScheme(context, colorScheme);
|
|
21
21
|
|
|
@@ -86,6 +86,7 @@ export function sectionHeader(input: SectionHeaderInput, context: TemplateContex
|
|
|
86
86
|
text: title,
|
|
87
87
|
style: {
|
|
88
88
|
fontSize: titleFontSize,
|
|
89
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
89
90
|
fontWeight: 'bold',
|
|
90
91
|
color: imageSrc ? '#ffffff' : colors.text,
|
|
91
92
|
textAlign: 'center',
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import type { Layer } from '../../schemas/Doc.js';
|
|
14
14
|
import type { StatHighlightInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
15
15
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
16
|
-
import { resolveColorScheme } from '../utils/themeUtils.js';
|
|
16
|
+
import { resolveColorScheme, getThemeFont } from '../utils/themeUtils.js';
|
|
17
17
|
import { createAccentLayers, getAccentLayout, adjustY, DEFAULT_LAYOUT } from './accentImage.js';
|
|
18
18
|
import { createBackgroundLayer } from './captionUtils.js';
|
|
19
19
|
|
|
@@ -50,6 +50,7 @@ export function statHighlight(input: StatHighlightInput, context: TemplateContex
|
|
|
50
50
|
text: stat,
|
|
51
51
|
style: {
|
|
52
52
|
fontSize: statFontSize,
|
|
53
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
53
54
|
fontWeight: 'bold',
|
|
54
55
|
color: colors.text,
|
|
55
56
|
shadow: !!accentImage,
|
|
@@ -71,6 +72,7 @@ export function statHighlight(input: StatHighlightInput, context: TemplateContex
|
|
|
71
72
|
text: description,
|
|
72
73
|
style: {
|
|
73
74
|
fontSize: descFontSize,
|
|
75
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
74
76
|
color: theme.colors.textMuted,
|
|
75
77
|
textAlign: 'center',
|
|
76
78
|
lineHeight: 1.6,
|
|
@@ -95,6 +97,7 @@ export function statHighlight(input: StatHighlightInput, context: TemplateContex
|
|
|
95
97
|
text: detail,
|
|
96
98
|
style: {
|
|
97
99
|
fontSize: detailFontSize,
|
|
100
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
98
101
|
color: colors.accent,
|
|
99
102
|
textAlign: 'center',
|
|
100
103
|
shadow: !!accentImage,
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import type { Layer } from '../../schemas/Doc.js';
|
|
12
12
|
import type { TitleBlockInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
13
13
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
14
|
+
import { getThemeFont } from '../utils/themeUtils.js';
|
|
14
15
|
|
|
15
16
|
export function titleBlock(input: TitleBlockInput, context: TemplateContext): Layer[] {
|
|
16
17
|
const { title, subtitle, backgroundColor } = input;
|
|
@@ -56,6 +57,7 @@ export function titleBlock(input: TitleBlockInput, context: TemplateContext): La
|
|
|
56
57
|
text: title,
|
|
57
58
|
style: {
|
|
58
59
|
fontSize: titleFontSize,
|
|
60
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
59
61
|
fontWeight: 'bold',
|
|
60
62
|
color: theme.colors.text,
|
|
61
63
|
textAlign: 'center',
|
|
@@ -81,6 +83,7 @@ export function titleBlock(input: TitleBlockInput, context: TemplateContext): La
|
|
|
81
83
|
text: subtitle,
|
|
82
84
|
style: {
|
|
83
85
|
fontSize: subtitleFontSize,
|
|
86
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
84
87
|
color: theme.colors.textMuted,
|
|
85
88
|
textAlign: 'center',
|
|
86
89
|
lineHeight: 1.5,
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import type { Layer } from '../../schemas/Doc.js';
|
|
14
14
|
import type { TwoColumnInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
15
15
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
16
|
-
import { resolveColorScheme } from '../utils/themeUtils.js';
|
|
16
|
+
import { resolveColorScheme, getThemeFont } from '../utils/themeUtils.js';
|
|
17
17
|
import { getTwoColumnPositions } from '../../schemas/LayoutStrategy.js';
|
|
18
18
|
|
|
19
19
|
export function twoColumn(input: TwoColumnInput, context: TemplateContext): Layer[] {
|
|
@@ -87,6 +87,7 @@ export function twoColumn(input: TwoColumnInput, context: TemplateContext): Laye
|
|
|
87
87
|
text: header,
|
|
88
88
|
style: {
|
|
89
89
|
fontSize: headerFontSize,
|
|
90
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
90
91
|
color: theme.colors.textMuted,
|
|
91
92
|
textAlign: 'center',
|
|
92
93
|
},
|
|
@@ -126,6 +127,7 @@ export function twoColumn(input: TwoColumnInput, context: TemplateContext): Laye
|
|
|
126
127
|
text: left.label,
|
|
127
128
|
style: {
|
|
128
129
|
fontSize: labelFontSize,
|
|
130
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
129
131
|
fontWeight: 'bold',
|
|
130
132
|
color: leftColors.text,
|
|
131
133
|
textAlign: 'center',
|
|
@@ -149,6 +151,7 @@ export function twoColumn(input: TwoColumnInput, context: TemplateContext): Laye
|
|
|
149
151
|
text: left.sublabel,
|
|
150
152
|
style: {
|
|
151
153
|
fontSize: sublabelFontSize,
|
|
154
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
152
155
|
color: theme.colors.textMuted,
|
|
153
156
|
textAlign: 'center',
|
|
154
157
|
lineHeight: 1.4,
|
|
@@ -176,6 +179,7 @@ export function twoColumn(input: TwoColumnInput, context: TemplateContext): Laye
|
|
|
176
179
|
text: connectorSymbol,
|
|
177
180
|
style: {
|
|
178
181
|
fontSize: connectorFontSize,
|
|
182
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
179
183
|
fontWeight: 'bold',
|
|
180
184
|
color: 'rgba(255, 255, 255, 0.6)',
|
|
181
185
|
textAlign: 'center',
|
|
@@ -197,6 +201,7 @@ export function twoColumn(input: TwoColumnInput, context: TemplateContext): Laye
|
|
|
197
201
|
text: right.label,
|
|
198
202
|
style: {
|
|
199
203
|
fontSize: labelFontSize,
|
|
204
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
200
205
|
fontWeight: 'bold',
|
|
201
206
|
color: rightColors.text,
|
|
202
207
|
textAlign: 'center',
|
|
@@ -220,6 +225,7 @@ export function twoColumn(input: TwoColumnInput, context: TemplateContext): Laye
|
|
|
220
225
|
text: right.sublabel,
|
|
221
226
|
style: {
|
|
222
227
|
fontSize: sublabelFontSize,
|
|
228
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
223
229
|
color: theme.colors.textMuted,
|
|
224
230
|
textAlign: 'center',
|
|
225
231
|
lineHeight: 1.4,
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import type { Layer } from '../../schemas/Doc.js';
|
|
19
19
|
import type { VideoPullQuoteInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
20
20
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
21
|
+
import { getThemeFont } from '../utils/themeUtils.js';
|
|
21
22
|
|
|
22
23
|
export function videoPullQuote(input: VideoPullQuoteInput, context: TemplateContext): Layer[] {
|
|
23
24
|
const { text, attribution, backgroundVideo } = input;
|
|
@@ -66,6 +67,7 @@ export function videoPullQuote(input: VideoPullQuoteInput, context: TemplateCont
|
|
|
66
67
|
text: '\u201C',
|
|
67
68
|
style: {
|
|
68
69
|
fontSize: decoFontSize,
|
|
70
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
69
71
|
color: 'rgba(255, 255, 255, 0.08)',
|
|
70
72
|
textAlign: 'center',
|
|
71
73
|
},
|
|
@@ -85,6 +87,7 @@ export function videoPullQuote(input: VideoPullQuoteInput, context: TemplateCont
|
|
|
85
87
|
text,
|
|
86
88
|
style: {
|
|
87
89
|
fontSize: quoteFontSize,
|
|
90
|
+
fontFamily: getThemeFont(context, 'title'),
|
|
88
91
|
color: '#ffffff',
|
|
89
92
|
textAlign: 'center',
|
|
90
93
|
lineHeight: 1.5,
|
|
@@ -110,6 +113,7 @@ export function videoPullQuote(input: VideoPullQuoteInput, context: TemplateCont
|
|
|
110
113
|
text: `\u2014 ${attribution}`,
|
|
111
114
|
style: {
|
|
112
115
|
fontSize: attrFontSize,
|
|
116
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
113
117
|
color: 'rgba(255, 255, 255, 0.7)',
|
|
114
118
|
textAlign: 'center',
|
|
115
119
|
shadow: true,
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import type { Layer } from '../../schemas/Doc.js';
|
|
19
19
|
import type { VideoWithCaptionInput, TemplateContext } from '../../schemas/BlockTemplates.js';
|
|
20
20
|
import { scaledFontSize } from '../../schemas/BlockTemplates.js';
|
|
21
|
+
import { getThemeFont } from '../utils/themeUtils.js';
|
|
21
22
|
import { cleanCaption } from './captionUtils.js';
|
|
22
23
|
|
|
23
24
|
export function videoWithCaption(input: VideoWithCaptionInput, context: TemplateContext): Layer[] {
|
|
@@ -86,6 +87,7 @@ export function videoWithCaption(input: VideoWithCaptionInput, context: Template
|
|
|
86
87
|
text: caption,
|
|
87
88
|
style: {
|
|
88
89
|
fontSize: captionFontSize,
|
|
90
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
89
91
|
color: theme.colors.text,
|
|
90
92
|
textAlign: 'center',
|
|
91
93
|
shadow: true,
|
|
@@ -110,6 +112,7 @@ export function videoWithCaption(input: VideoWithCaptionInput, context: Template
|
|
|
110
112
|
text: videoCredit,
|
|
111
113
|
style: {
|
|
112
114
|
fontSize: creditFontSize,
|
|
115
|
+
fontFamily: getThemeFont(context, 'body'),
|
|
113
116
|
color: 'rgba(255, 255, 255, 0.5)',
|
|
114
117
|
textAlign: 'right',
|
|
115
118
|
},
|
|
@@ -37,6 +37,35 @@ export function resolveColorScheme(
|
|
|
37
37
|
return FALLBACK_COLOR_SCHEME;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
// ============================================
|
|
41
|
+
// Font Family Resolution
|
|
42
|
+
// ============================================
|
|
43
|
+
|
|
44
|
+
/** Safe system font fallbacks. */
|
|
45
|
+
const FALLBACK_BODY = 'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';
|
|
46
|
+
const FALLBACK_TITLE = 'Georgia, "Times New Roman", serif';
|
|
47
|
+
const FALLBACK_MONO = 'Consolas, "Courier New", monospace';
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get the theme font family for a given role.
|
|
51
|
+
* Templates call this to set `fontFamily` on text layers.
|
|
52
|
+
*
|
|
53
|
+
* @param context Template context (includes theme with typography settings)
|
|
54
|
+
* @param role 'title' for headings, 'body' for descriptions, 'mono' for code
|
|
55
|
+
* @returns A CSS font-family string with the theme's font and safe fallbacks
|
|
56
|
+
*/
|
|
57
|
+
export function getThemeFont(context: TemplateContext, role: 'title' | 'body' | 'mono'): string {
|
|
58
|
+
const { typography } = context.theme;
|
|
59
|
+
switch (role) {
|
|
60
|
+
case 'title':
|
|
61
|
+
return typography.titleFontFamily || FALLBACK_TITLE;
|
|
62
|
+
case 'body':
|
|
63
|
+
return typography.bodyFontFamily || FALLBACK_BODY;
|
|
64
|
+
case 'mono':
|
|
65
|
+
return typography.monoFontFamily || FALLBACK_MONO;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
40
69
|
// ============================================
|
|
41
70
|
// Font Sizing
|
|
42
71
|
// ============================================
|
package/src/markdown/convert.ts
CHANGED
|
@@ -181,17 +181,25 @@ function extractTemplateAnnotation(
|
|
|
181
181
|
*/
|
|
182
182
|
function parseAnnotationTokens(inner: string): HeadingTemplateAnnotation {
|
|
183
183
|
const tokens = inner.split(/\s+/);
|
|
184
|
-
const template = tokens[0];
|
|
185
184
|
const params: Record<string, string> = {};
|
|
186
185
|
|
|
187
|
-
|
|
186
|
+
// If the first token contains '=', there's no template name —
|
|
187
|
+
// the annotation is purely key-value (e.g., `{[audio=intro.mp3]}`).
|
|
188
|
+
const firstIsParam = tokens[0].indexOf('=') > 0;
|
|
189
|
+
const template = firstIsParam ? undefined : tokens[0];
|
|
190
|
+
const startIdx = firstIsParam ? 0 : 1;
|
|
191
|
+
|
|
192
|
+
for (let i = startIdx; i < tokens.length; i++) {
|
|
188
193
|
const eqIdx = tokens[i].indexOf('=');
|
|
189
194
|
if (eqIdx > 0) {
|
|
190
195
|
params[tokens[i].slice(0, eqIdx)] = tokens[i].slice(eqIdx + 1);
|
|
191
196
|
}
|
|
192
197
|
}
|
|
193
198
|
|
|
194
|
-
const result: HeadingTemplateAnnotation = {
|
|
199
|
+
const result: HeadingTemplateAnnotation = {};
|
|
200
|
+
if (template) {
|
|
201
|
+
result.template = template;
|
|
202
|
+
}
|
|
195
203
|
if (Object.keys(params).length > 0) {
|
|
196
204
|
result.params = params;
|
|
197
205
|
}
|
|
@@ -202,14 +210,16 @@ function parseAnnotationTokens(inner: string): HeadingTemplateAnnotation {
|
|
|
202
210
|
* Serialize a HeadingTemplateAnnotation back to `{[templateName key=value …]}` text.
|
|
203
211
|
*/
|
|
204
212
|
function serializeTemplateAnnotation(annotation: HeadingTemplateAnnotation): string {
|
|
205
|
-
|
|
213
|
+
const parts: string[] = [];
|
|
214
|
+
if (annotation.template) {
|
|
215
|
+
parts.push(annotation.template);
|
|
216
|
+
}
|
|
206
217
|
if (annotation.params) {
|
|
207
218
|
for (const [key, value] of Object.entries(annotation.params)) {
|
|
208
|
-
|
|
219
|
+
parts.push(`${key}=${value}`);
|
|
209
220
|
}
|
|
210
221
|
}
|
|
211
|
-
|
|
212
|
-
return result;
|
|
222
|
+
return `{[${parts.join(' ')}]}`;
|
|
213
223
|
}
|
|
214
224
|
|
|
215
225
|
/**
|
package/src/markdown/types.ts
CHANGED
|
@@ -118,8 +118,10 @@ interface MarkdownNodeBase {
|
|
|
118
118
|
* → `{ template: 'chart', params: { colorScheme: 'blue' } }`
|
|
119
119
|
*/
|
|
120
120
|
export interface HeadingTemplateAnnotation {
|
|
121
|
-
/** Template name (first token inside `{[…]}`)
|
|
122
|
-
|
|
121
|
+
/** Template name (first token inside `{[…]}`).
|
|
122
|
+
* Optional when the annotation contains only key=value pairs
|
|
123
|
+
* (e.g., `{[audio=intro.mp3]}`). */
|
|
124
|
+
template?: string;
|
|
123
125
|
/** Optional key-value parameters (remaining `key=value` tokens) */
|
|
124
126
|
params?: Record<string, string>;
|
|
125
127
|
}
|
|
@@ -39,12 +39,12 @@ export type ColorScheme = string;
|
|
|
39
39
|
* PT Serif provides a classic, readable appearance for documentary-style content.
|
|
40
40
|
* Used as a fallback in TextLayer when no font is specified.
|
|
41
41
|
*/
|
|
42
|
-
export const DEFAULT_DOC_FONT = '
|
|
42
|
+
export const DEFAULT_DOC_FONT = 'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Default font family for titles.
|
|
46
46
|
*/
|
|
47
|
-
export const DEFAULT_TITLE_FONT = '
|
|
47
|
+
export const DEFAULT_TITLE_FONT = 'Georgia, "Times New Roman", serif';
|
|
48
48
|
|
|
49
49
|
// ============================================
|
|
50
50
|
// Accent Image System
|
package/src/schemas/Doc.ts
CHANGED
|
@@ -127,6 +127,13 @@ export interface Block {
|
|
|
127
127
|
/** Template name that generated this block (for debugging) */
|
|
128
128
|
template?: string;
|
|
129
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Display title for template rendering.
|
|
132
|
+
* Extracted from the sourceHeading when the block is created by markdownToDoc().
|
|
133
|
+
* Templates like sectionHeader and titleBlock read this for their title layer.
|
|
134
|
+
*/
|
|
135
|
+
title?: string;
|
|
136
|
+
|
|
130
137
|
// ── Markdown-driven hierarchy (optional) ──
|
|
131
138
|
|
|
132
139
|
/**
|
|
@@ -436,6 +443,19 @@ export interface AudioTrack {
|
|
|
436
443
|
// Captions
|
|
437
444
|
// ============================================
|
|
438
445
|
|
|
446
|
+
/**
|
|
447
|
+
* A single word with precise timing, used for word-level highlighting
|
|
448
|
+
* in social-style captions. Populated from TTS timing data when available.
|
|
449
|
+
*/
|
|
450
|
+
export interface CaptionWord {
|
|
451
|
+
/** The word text */
|
|
452
|
+
text: string;
|
|
453
|
+
/** Start time in seconds (relative to doc start) */
|
|
454
|
+
startTime: number;
|
|
455
|
+
/** End time in seconds */
|
|
456
|
+
endTime: number;
|
|
457
|
+
}
|
|
458
|
+
|
|
439
459
|
/**
|
|
440
460
|
* A single caption phrase to display during playback.
|
|
441
461
|
*/
|
|
@@ -448,6 +468,13 @@ export interface CaptionPhrase {
|
|
|
448
468
|
endTime: number;
|
|
449
469
|
/** Which audio segment this caption belongs to (0-indexed) */
|
|
450
470
|
audioSegment: number;
|
|
471
|
+
/**
|
|
472
|
+
* Optional per-word timing from TTS timing data.
|
|
473
|
+
* When present, enables precise word-level highlighting in social
|
|
474
|
+
* caption style. When absent, word timing is interpolated evenly
|
|
475
|
+
* across the phrase duration.
|
|
476
|
+
*/
|
|
477
|
+
words?: CaptionWord[];
|
|
451
478
|
}
|
|
452
479
|
|
|
453
480
|
/**
|
|
@@ -476,6 +503,39 @@ export interface AudioSegment {
|
|
|
476
503
|
startTime: number;
|
|
477
504
|
}
|
|
478
505
|
|
|
506
|
+
// ============================================
|
|
507
|
+
// Audio Timing Data (from TTS)
|
|
508
|
+
// ============================================
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* A single word-level timing bookmark from TTS synthesis.
|
|
512
|
+
* Used for precise audio-to-content mapping and word-level caption sync.
|
|
513
|
+
*/
|
|
514
|
+
export interface AudioBookmark {
|
|
515
|
+
/** Unique identifier (e.g., "word-0", "word-1") */
|
|
516
|
+
id: string;
|
|
517
|
+
/** Timestamp in seconds from audio start */
|
|
518
|
+
time: number;
|
|
519
|
+
/** Character offset in the source text */
|
|
520
|
+
charOffset: number;
|
|
521
|
+
/** The word text at this position */
|
|
522
|
+
textFragment?: string;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Timing data for an audio segment, typically from a `.timing.json` file
|
|
527
|
+
* generated alongside TTS audio. Contains the source text and per-word
|
|
528
|
+
* timing bookmarks for precise content matching and caption sync.
|
|
529
|
+
*/
|
|
530
|
+
export interface AudioTimingData {
|
|
531
|
+
/** The normalized plain text that was synthesized */
|
|
532
|
+
sourceText: string;
|
|
533
|
+
/** Word-level timing bookmarks */
|
|
534
|
+
bookmarks: AudioBookmark[];
|
|
535
|
+
/** Total audio duration in seconds */
|
|
536
|
+
duration: number;
|
|
537
|
+
}
|
|
538
|
+
|
|
479
539
|
// ============================================
|
|
480
540
|
// Helper Functions
|
|
481
541
|
// ============================================
|