@bendyline/squisq 2.4.2 → 2.4.4
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/chunk-24SENDJY.js +750 -0
- package/dist/{chunk-JUAC2QWP.js → chunk-CYRIVZTR.js} +1 -1
- package/dist/{chunk-EMXYZLRH.js → chunk-GGTDYLW4.js} +1 -1
- package/dist/{chunk-AQF5ZYDI.js → chunk-GXUFHFYD.js} +3 -3
- package/dist/{chunk-2HY2ZA7U.js → chunk-OIIIHI3Y.js} +45 -9
- package/dist/{chunk-7TJJA2RI.js → chunk-YQW6AQBV.js} +1 -1
- package/dist/doc/index.d.ts +8 -2
- package/dist/doc/index.js +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +12 -8
- package/dist/jsonForm/index.js +1 -1
- package/dist/markdown/index.js +3 -3
- package/dist/narration/index.js +3 -3
- package/dist/schemas/index.d.ts +22 -3
- package/dist/schemas/index.js +6 -2
- package/package.json +1 -1
- package/dist/chunk-GODLNXO4.js +0 -360
- package/dist/{chunk-D6YTLQCL.js → chunk-O3LLD7HG.js} +176 -176
|
@@ -0,0 +1,750 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defaultPageStyle
|
|
3
|
+
} from "./chunk-GAZKTT4R.js";
|
|
4
|
+
import {
|
|
5
|
+
FONT_FALLBACKS,
|
|
6
|
+
THEME_SCHEMA_VERSION,
|
|
7
|
+
assertTheme,
|
|
8
|
+
createTheme,
|
|
9
|
+
deriveScale,
|
|
10
|
+
isHex,
|
|
11
|
+
oklchDarken,
|
|
12
|
+
oklchLighten,
|
|
13
|
+
oklchSetChroma,
|
|
14
|
+
pickContrastingText,
|
|
15
|
+
relativeLuminance,
|
|
16
|
+
resolveFontFamily,
|
|
17
|
+
withAlpha
|
|
18
|
+
} from "./chunk-SBAX4ZPO.js";
|
|
19
|
+
|
|
20
|
+
// src/schemas/Doc.ts
|
|
21
|
+
function calculateDuration(audio) {
|
|
22
|
+
return audio.segments.reduce((sum, seg) => sum + seg.duration, 0);
|
|
23
|
+
}
|
|
24
|
+
function getSegmentAtTime(audio, time) {
|
|
25
|
+
let elapsed = 0;
|
|
26
|
+
for (let i = 0; i < audio.segments.length; i++) {
|
|
27
|
+
elapsed += audio.segments[i].duration;
|
|
28
|
+
if (time < elapsed) return i;
|
|
29
|
+
}
|
|
30
|
+
return audio.segments.length - 1;
|
|
31
|
+
}
|
|
32
|
+
function getBlockAtTime(blocks, time) {
|
|
33
|
+
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
34
|
+
const block = blocks[i];
|
|
35
|
+
if (time >= block.startTime && time < block.startTime + block.duration) {
|
|
36
|
+
return block;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return blocks[0] || null;
|
|
40
|
+
}
|
|
41
|
+
function getCaptionAtTime(captions, time) {
|
|
42
|
+
if (!captions || !captions.phrases.length) return null;
|
|
43
|
+
for (const phrase of captions.phrases) {
|
|
44
|
+
if (time >= phrase.startTime && time < phrase.endTime) {
|
|
45
|
+
return phrase;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/schemas/validateDoc.ts
|
|
52
|
+
var LAYER_TYPES = /* @__PURE__ */ new Set([
|
|
53
|
+
"image",
|
|
54
|
+
"text",
|
|
55
|
+
"shape",
|
|
56
|
+
"path",
|
|
57
|
+
"map",
|
|
58
|
+
"video",
|
|
59
|
+
"table",
|
|
60
|
+
"tree",
|
|
61
|
+
"mermaid"
|
|
62
|
+
]);
|
|
63
|
+
function validateDocSchema(value) {
|
|
64
|
+
const issues = [];
|
|
65
|
+
if (!isRecord(value)) {
|
|
66
|
+
add(issues, "$", "must be an object", value);
|
|
67
|
+
return issues;
|
|
68
|
+
}
|
|
69
|
+
requiredString(value, "articleId", "articleId", issues);
|
|
70
|
+
requiredFiniteNumber(value, "duration", "duration", issues, { min: 0 });
|
|
71
|
+
const blocks = requiredArray(value, "blocks", "blocks", issues);
|
|
72
|
+
if (blocks) validateBlocks(blocks, "blocks", issues);
|
|
73
|
+
const audio = requiredRecord(value, "audio", "audio", issues);
|
|
74
|
+
if (audio) {
|
|
75
|
+
const segments = requiredArray(audio, "segments", "audio.segments", issues);
|
|
76
|
+
if (segments) validateAudioSegments(segments, issues);
|
|
77
|
+
}
|
|
78
|
+
optionalString(value, "themeId", "themeId", issues);
|
|
79
|
+
optionalRecord(value, "frontmatter", "frontmatter", issues);
|
|
80
|
+
optionalRecord(value, "persistentLayers", "persistentLayers", issues);
|
|
81
|
+
optionalRecord(value, "meta", "meta", issues);
|
|
82
|
+
optionalArray(value, "customTemplates", "customTemplates", issues);
|
|
83
|
+
optionalArray(value, "customThemes", "customThemes", issues);
|
|
84
|
+
if (value.startBlock !== void 0) validateStartBlock(value.startBlock, issues);
|
|
85
|
+
if (value.captions !== void 0) validateCaptions(value.captions, issues);
|
|
86
|
+
if (value.diagnostics !== void 0) validateDiagnostics(value.diagnostics, issues);
|
|
87
|
+
if (value.documentMedia !== void 0) {
|
|
88
|
+
validateMediaArray(value.documentMedia, "documentMedia", issues);
|
|
89
|
+
}
|
|
90
|
+
return issues;
|
|
91
|
+
}
|
|
92
|
+
function assertDocSchema(value) {
|
|
93
|
+
const issues = validateDocSchema(value);
|
|
94
|
+
if (issues.length === 0) return;
|
|
95
|
+
const detail = issues.map((issue) => `${issue.path} ${issue.message}`).join("; ");
|
|
96
|
+
throw new TypeError(`Invalid squisq Doc: ${detail}`);
|
|
97
|
+
}
|
|
98
|
+
function validateBlocks(values, path, issues) {
|
|
99
|
+
for (let index = 0; index < values.length; index += 1) {
|
|
100
|
+
const blockPath = `${path}[${index}]`;
|
|
101
|
+
const block = values[index];
|
|
102
|
+
if (!isRecord(block)) {
|
|
103
|
+
add(issues, blockPath, "must be an object", block);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
requiredString(block, "id", `${blockPath}.id`, issues);
|
|
107
|
+
requiredFiniteNumber(block, "startTime", `${blockPath}.startTime`, issues, { min: 0 });
|
|
108
|
+
requiredFiniteNumber(block, "duration", `${blockPath}.duration`, issues, { min: 0 });
|
|
109
|
+
requiredInteger(block, "audioSegment", `${blockPath}.audioSegment`, issues, 0);
|
|
110
|
+
optionalString(block, "sourceBlockId", `${blockPath}.sourceBlockId`, issues);
|
|
111
|
+
optionalStringArray(block, "sourceBlockIds", `${blockPath}.sourceBlockIds`, issues);
|
|
112
|
+
optionalFiniteNumber(block, "sourceCharOffset", `${blockPath}.sourceCharOffset`, issues, {
|
|
113
|
+
min: 0
|
|
114
|
+
});
|
|
115
|
+
optionalString(block, "template", `${blockPath}.template`, issues);
|
|
116
|
+
optionalString(block, "title", `${blockPath}.title`, issues);
|
|
117
|
+
optionalBoolean(block, "autoTemplate", `${blockPath}.autoTemplate`, issues);
|
|
118
|
+
optionalFiniteNumber(block, "x", `${blockPath}.x`, issues);
|
|
119
|
+
optionalFiniteNumber(block, "y", `${blockPath}.y`, issues);
|
|
120
|
+
optionalStringArray(block, "classes", `${blockPath}.classes`, issues);
|
|
121
|
+
optionalStringRecord(block, "metadata", `${blockPath}.metadata`, issues);
|
|
122
|
+
optionalStringRecord(block, "templateOverrides", `${blockPath}.templateOverrides`, issues);
|
|
123
|
+
optionalRecord(block, "templateData", `${blockPath}.templateData`, issues);
|
|
124
|
+
optionalArray(block, "contents", `${blockPath}.contents`, issues);
|
|
125
|
+
if (block.layers !== void 0) validateLayers(block.layers, `${blockPath}.layers`, issues);
|
|
126
|
+
if (block.children !== void 0) {
|
|
127
|
+
if (Array.isArray(block.children)) {
|
|
128
|
+
validateBlocks(block.children, `${blockPath}.children`, issues);
|
|
129
|
+
} else {
|
|
130
|
+
add(issues, `${blockPath}.children`, "must be an array", block.children);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (block.connectsTo !== void 0) {
|
|
134
|
+
validateConnections(block.connectsTo, `${blockPath}.connectsTo`, issues);
|
|
135
|
+
}
|
|
136
|
+
if (block.media !== void 0) {
|
|
137
|
+
validateMediaArray(block.media, `${blockPath}.media`, issues);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function validateLayers(value, path, issues) {
|
|
142
|
+
if (!Array.isArray(value)) {
|
|
143
|
+
add(issues, path, "must be an array", value);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
147
|
+
const layerPath = `${path}[${index}]`;
|
|
148
|
+
const layer = value[index];
|
|
149
|
+
if (!isRecord(layer)) {
|
|
150
|
+
add(issues, layerPath, "must be an object", layer);
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
requiredString(layer, "id", `${layerPath}.id`, issues);
|
|
154
|
+
const type = requiredString(layer, "type", `${layerPath}.type`, issues);
|
|
155
|
+
if (type && !LAYER_TYPES.has(type)) {
|
|
156
|
+
issues.push({
|
|
157
|
+
path: `${layerPath}.type`,
|
|
158
|
+
message: `must be a known layer type (got ${quote(type)})`
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
validatePosition(layer.position, `${layerPath}.position`, issues);
|
|
162
|
+
const content = requiredRecord(layer, "content", `${layerPath}.content`, issues);
|
|
163
|
+
if (content && type) validateLayerContent(type, content, `${layerPath}.content`, issues);
|
|
164
|
+
if (layer.animation !== void 0 && !isRecord(layer.animation)) {
|
|
165
|
+
add(issues, `${layerPath}.animation`, "must be an object", layer.animation);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function validateLayerContent(type, content, path, issues) {
|
|
170
|
+
switch (type) {
|
|
171
|
+
case "image":
|
|
172
|
+
requiredString(content, "src", `${path}.src`, issues);
|
|
173
|
+
requiredString(content, "alt", `${path}.alt`, issues);
|
|
174
|
+
break;
|
|
175
|
+
case "text":
|
|
176
|
+
requiredString(content, "text", `${path}.text`, issues);
|
|
177
|
+
requiredRecord(content, "style", `${path}.style`, issues);
|
|
178
|
+
break;
|
|
179
|
+
case "shape":
|
|
180
|
+
requiredString(content, "shape", `${path}.shape`, issues);
|
|
181
|
+
break;
|
|
182
|
+
case "path":
|
|
183
|
+
requiredString(content, "d", `${path}.d`, issues);
|
|
184
|
+
break;
|
|
185
|
+
case "map": {
|
|
186
|
+
const center = requiredRecord(content, "center", `${path}.center`, issues);
|
|
187
|
+
if (center) {
|
|
188
|
+
requiredFiniteNumber(center, "lat", `${path}.center.lat`, issues);
|
|
189
|
+
requiredFiniteNumber(center, "lng", `${path}.center.lng`, issues);
|
|
190
|
+
}
|
|
191
|
+
requiredFiniteNumber(content, "zoom", `${path}.zoom`, issues);
|
|
192
|
+
requiredString(content, "style", `${path}.style`, issues);
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
case "video":
|
|
196
|
+
requiredString(content, "src", `${path}.src`, issues);
|
|
197
|
+
requiredString(content, "alt", `${path}.alt`, issues);
|
|
198
|
+
requiredFiniteNumber(content, "clipStart", `${path}.clipStart`, issues, { min: 0 });
|
|
199
|
+
requiredFiniteNumber(content, "clipEnd", `${path}.clipEnd`, issues, { min: 0 });
|
|
200
|
+
break;
|
|
201
|
+
case "table":
|
|
202
|
+
requiredStringArray(content, "headers", `${path}.headers`, issues);
|
|
203
|
+
validateStringRows(content.rows, `${path}.rows`, issues);
|
|
204
|
+
requiredRecord(content, "style", `${path}.style`, issues);
|
|
205
|
+
break;
|
|
206
|
+
case "tree":
|
|
207
|
+
requiredArray(content, "items", `${path}.items`, issues);
|
|
208
|
+
requiredRecord(content, "style", `${path}.style`, issues);
|
|
209
|
+
break;
|
|
210
|
+
case "mermaid":
|
|
211
|
+
requiredString(content, "source", `${path}.source`, issues);
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function validatePosition(value, path, issues) {
|
|
216
|
+
if (!isRecord(value)) {
|
|
217
|
+
add(issues, path, "must be an object", value);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
requiredPositionValue(value, "x", `${path}.x`, issues);
|
|
221
|
+
requiredPositionValue(value, "y", `${path}.y`, issues);
|
|
222
|
+
optionalPositionValue(value, "width", `${path}.width`, issues);
|
|
223
|
+
optionalPositionValue(value, "height", `${path}.height`, issues);
|
|
224
|
+
}
|
|
225
|
+
function validateAudioSegments(values, issues) {
|
|
226
|
+
for (let index = 0; index < values.length; index += 1) {
|
|
227
|
+
const path = `audio.segments[${index}]`;
|
|
228
|
+
const segment = values[index];
|
|
229
|
+
if (!isRecord(segment)) {
|
|
230
|
+
add(issues, path, "must be an object", segment);
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
requiredString(segment, "src", `${path}.src`, issues);
|
|
234
|
+
requiredString(segment, "name", `${path}.name`, issues);
|
|
235
|
+
requiredFiniteNumber(segment, "duration", `${path}.duration`, issues, { min: 0 });
|
|
236
|
+
requiredFiniteNumber(segment, "startTime", `${path}.startTime`, issues, { min: 0 });
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function validateConnections(value, path, issues) {
|
|
240
|
+
if (!Array.isArray(value)) {
|
|
241
|
+
add(issues, path, "must be an array", value);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
245
|
+
const itemPath = `${path}[${index}]`;
|
|
246
|
+
const connection = value[index];
|
|
247
|
+
if (!isRecord(connection)) {
|
|
248
|
+
add(issues, itemPath, "must be an object", connection);
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
requiredString(connection, "target", `${itemPath}.target`, issues);
|
|
252
|
+
optionalString(connection, "type", `${itemPath}.type`, issues);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function validateMediaArray(value, path, issues) {
|
|
256
|
+
if (!Array.isArray(value)) {
|
|
257
|
+
add(issues, path, "must be an array", value);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
261
|
+
const clipPath = `${path}[${index}]`;
|
|
262
|
+
const clip = value[index];
|
|
263
|
+
if (!isRecord(clip)) {
|
|
264
|
+
add(issues, clipPath, "must be an object", clip);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
requiredString(clip, "id", `${clipPath}.id`, issues);
|
|
268
|
+
requiredString(clip, "src", `${clipPath}.src`, issues);
|
|
269
|
+
requiredString(clip, "kind", `${clipPath}.kind`, issues);
|
|
270
|
+
requiredFiniteNumber(clip, "startAt", `${clipPath}.startAt`, issues, { min: 0 });
|
|
271
|
+
requiredString(clip, "anchor", `${clipPath}.anchor`, issues);
|
|
272
|
+
optionalFiniteNumber(clip, "clipStart", `${clipPath}.clipStart`, issues, { min: 0 });
|
|
273
|
+
optionalFiniteNumber(clip, "clipEnd", `${clipPath}.clipEnd`, issues, { min: 0 });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
function validateStartBlock(value, issues) {
|
|
277
|
+
if (!isRecord(value)) {
|
|
278
|
+
add(issues, "startBlock", "must be an object", value);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
requiredString(value, "title", "startBlock.title", issues);
|
|
282
|
+
optionalString(value, "heroSrc", "startBlock.heroSrc", issues);
|
|
283
|
+
optionalString(value, "heroAlt", "startBlock.heroAlt", issues);
|
|
284
|
+
optionalString(value, "subtitle", "startBlock.subtitle", issues);
|
|
285
|
+
}
|
|
286
|
+
function validateCaptions(value, issues) {
|
|
287
|
+
if (!isRecord(value)) {
|
|
288
|
+
add(issues, "captions", "must be an object", value);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
requiredInteger(value, "version", "captions.version", issues, 0);
|
|
292
|
+
const phrases = requiredArray(value, "phrases", "captions.phrases", issues);
|
|
293
|
+
if (!phrases) return;
|
|
294
|
+
for (let index = 0; index < phrases.length; index += 1) {
|
|
295
|
+
const path = `captions.phrases[${index}]`;
|
|
296
|
+
const phrase = phrases[index];
|
|
297
|
+
if (!isRecord(phrase)) {
|
|
298
|
+
add(issues, path, "must be an object", phrase);
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
requiredString(phrase, "text", `${path}.text`, issues);
|
|
302
|
+
requiredFiniteNumber(phrase, "startTime", `${path}.startTime`, issues, { min: 0 });
|
|
303
|
+
requiredFiniteNumber(phrase, "endTime", `${path}.endTime`, issues, { min: 0 });
|
|
304
|
+
requiredInteger(phrase, "audioSegment", `${path}.audioSegment`, issues, 0);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function validateDiagnostics(value, issues) {
|
|
308
|
+
if (!Array.isArray(value)) {
|
|
309
|
+
add(issues, "diagnostics", "must be an array", value);
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
313
|
+
const path = `diagnostics[${index}]`;
|
|
314
|
+
const diagnostic = value[index];
|
|
315
|
+
if (!isRecord(diagnostic)) {
|
|
316
|
+
add(issues, path, "must be an object", diagnostic);
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
requiredString(diagnostic, "severity", `${path}.severity`, issues);
|
|
320
|
+
requiredString(diagnostic, "code", `${path}.code`, issues);
|
|
321
|
+
requiredString(diagnostic, "message", `${path}.message`, issues);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function validateStringRows(value, path, issues) {
|
|
325
|
+
if (!Array.isArray(value)) {
|
|
326
|
+
add(issues, path, "must be an array", value);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
330
|
+
if (!Array.isArray(value[index]) || value[index].some((cell) => typeof cell !== "string")) {
|
|
331
|
+
add(issues, `${path}[${index}]`, "must be an array of strings", value[index]);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
function isRecord(value) {
|
|
336
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
337
|
+
}
|
|
338
|
+
function requiredRecord(object, key, path, issues) {
|
|
339
|
+
const value = object[key];
|
|
340
|
+
if (!isRecord(value)) {
|
|
341
|
+
add(issues, path, "must be an object", value);
|
|
342
|
+
return void 0;
|
|
343
|
+
}
|
|
344
|
+
return value;
|
|
345
|
+
}
|
|
346
|
+
function optionalRecord(object, key, path, issues) {
|
|
347
|
+
if (object[key] !== void 0 && !isRecord(object[key])) {
|
|
348
|
+
add(issues, path, "must be an object", object[key]);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function requiredArray(object, key, path, issues) {
|
|
352
|
+
const value = object[key];
|
|
353
|
+
if (!Array.isArray(value)) {
|
|
354
|
+
add(issues, path, "must be an array", value);
|
|
355
|
+
return void 0;
|
|
356
|
+
}
|
|
357
|
+
return value;
|
|
358
|
+
}
|
|
359
|
+
function optionalArray(object, key, path, issues) {
|
|
360
|
+
if (object[key] !== void 0 && !Array.isArray(object[key])) {
|
|
361
|
+
add(issues, path, "must be an array", object[key]);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
function requiredString(object, key, path, issues) {
|
|
365
|
+
const value = object[key];
|
|
366
|
+
if (typeof value !== "string") {
|
|
367
|
+
add(issues, path, "must be a string", value);
|
|
368
|
+
return void 0;
|
|
369
|
+
}
|
|
370
|
+
return value;
|
|
371
|
+
}
|
|
372
|
+
function optionalString(object, key, path, issues) {
|
|
373
|
+
if (object[key] !== void 0 && typeof object[key] !== "string") {
|
|
374
|
+
add(issues, path, "must be a string", object[key]);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
function requiredStringArray(object, key, path, issues) {
|
|
378
|
+
const value = object[key];
|
|
379
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
380
|
+
add(issues, path, "must be an array of strings", value);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
function optionalStringArray(object, key, path, issues) {
|
|
384
|
+
if (object[key] !== void 0) requiredStringArray(object, key, path, issues);
|
|
385
|
+
}
|
|
386
|
+
function optionalStringRecord(object, key, path, issues) {
|
|
387
|
+
const value = object[key];
|
|
388
|
+
if (value === void 0) return;
|
|
389
|
+
if (!isRecord(value) || Object.values(value).some((item) => typeof item !== "string")) {
|
|
390
|
+
add(issues, path, "must be an object whose values are strings", value);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
function requiredFiniteNumber(object, key, path, issues, rule = {}) {
|
|
394
|
+
const value = object[key];
|
|
395
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
396
|
+
add(issues, path, "must be a finite number", value);
|
|
397
|
+
} else if (rule.min !== void 0 && value < rule.min) {
|
|
398
|
+
issues.push({ path, message: `must be at least ${rule.min} (got ${value})` });
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
function optionalFiniteNumber(object, key, path, issues, rule = {}) {
|
|
402
|
+
if (object[key] !== void 0) requiredFiniteNumber(object, key, path, issues, rule);
|
|
403
|
+
}
|
|
404
|
+
function requiredInteger(object, key, path, issues, min) {
|
|
405
|
+
const value = object[key];
|
|
406
|
+
if (!Number.isSafeInteger(value) || value < min) {
|
|
407
|
+
add(issues, path, `must be an integer of at least ${min}`, value);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
function optionalBoolean(object, key, path, issues) {
|
|
411
|
+
if (object[key] !== void 0 && typeof object[key] !== "boolean") {
|
|
412
|
+
add(issues, path, "must be a boolean", object[key]);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
function requiredPositionValue(object, key, path, issues) {
|
|
416
|
+
const value = object[key];
|
|
417
|
+
if ((typeof value !== "number" || !Number.isFinite(value)) && typeof value !== "string") {
|
|
418
|
+
add(issues, path, "must be a finite number or string", value);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
function optionalPositionValue(object, key, path, issues) {
|
|
422
|
+
if (object[key] !== void 0) requiredPositionValue(object, key, path, issues);
|
|
423
|
+
}
|
|
424
|
+
function add(issues, path, message, value) {
|
|
425
|
+
const missing = value === void 0 ? " (field is missing)" : ` (got ${describe(value)})`;
|
|
426
|
+
issues.push({ path, message: `${message}${missing}` });
|
|
427
|
+
}
|
|
428
|
+
function describe(value) {
|
|
429
|
+
if (value === null) return "null";
|
|
430
|
+
if (Array.isArray(value)) return "an array";
|
|
431
|
+
if (typeof value === "string") return quote(value);
|
|
432
|
+
if (typeof value === "number" && Number.isNaN(value)) return "NaN";
|
|
433
|
+
return typeof value;
|
|
434
|
+
}
|
|
435
|
+
function quote(value) {
|
|
436
|
+
return JSON.stringify(value);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// src/schemas/pipStyle.ts
|
|
440
|
+
var DEFAULT_SHADOW = "0 0.75em 2em rgba(0, 0, 0, 0.34)";
|
|
441
|
+
var DERIVED_BORDER_WIDTH = "max(1px, 0.12vw)";
|
|
442
|
+
function cssLength(value) {
|
|
443
|
+
return typeof value === "number" ? `${value}px` : value;
|
|
444
|
+
}
|
|
445
|
+
function resolveRadius(theme) {
|
|
446
|
+
const explicit = theme.style.pip?.cornerRadius;
|
|
447
|
+
if (explicit != null) {
|
|
448
|
+
if (typeof explicit === "number") return explicit <= 0 ? "0" : `${explicit}px`;
|
|
449
|
+
return explicit;
|
|
450
|
+
}
|
|
451
|
+
const br = theme.style.borderRadius ?? 0;
|
|
452
|
+
if (br <= 0) return "0";
|
|
453
|
+
return `${Math.min(28, Math.max(6, Math.round(br)))}%`;
|
|
454
|
+
}
|
|
455
|
+
function resolveBorder(theme) {
|
|
456
|
+
const border = theme.style.pip?.border;
|
|
457
|
+
if (border === "none") return "none";
|
|
458
|
+
if (border && typeof border === "object") {
|
|
459
|
+
const width = border.width == null ? DERIVED_BORDER_WIDTH : cssLength(border.width);
|
|
460
|
+
const color = border.color ?? withAlpha(theme.colors.text, 0.35);
|
|
461
|
+
return `${width} solid ${color}`;
|
|
462
|
+
}
|
|
463
|
+
return `${DERIVED_BORDER_WIDTH} solid ${withAlpha(theme.colors.text, 0.35)}`;
|
|
464
|
+
}
|
|
465
|
+
function resolveShadow(theme) {
|
|
466
|
+
const shadow = theme.style.pip?.shadow;
|
|
467
|
+
if (shadow === false || shadow === "none") return "none";
|
|
468
|
+
if (typeof shadow === "string") return shadow;
|
|
469
|
+
return DEFAULT_SHADOW;
|
|
470
|
+
}
|
|
471
|
+
function pipStyleVars(theme) {
|
|
472
|
+
return {
|
|
473
|
+
"--squisq-pip-radius": resolveRadius(theme),
|
|
474
|
+
"--squisq-pip-border": resolveBorder(theme),
|
|
475
|
+
"--squisq-pip-shadow": resolveShadow(theme)
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// src/schemas/themeCompile.ts
|
|
480
|
+
var STARTER_BODY_FONT = { stackId: "system-sans" };
|
|
481
|
+
var STARTER_TITLE_FONT = { stackId: "system-serif" };
|
|
482
|
+
var STARTER_MONO_FONT = { stackId: "system-mono" };
|
|
483
|
+
var STARTER_COLOR_SCHEMES = {
|
|
484
|
+
blue: { bg: "#1a365d", text: "#63b3ed", accent: "#90cdf4" },
|
|
485
|
+
green: { bg: "#22543d", text: "#9ae6b4", accent: "#68d391" },
|
|
486
|
+
purple: { bg: "#44337a", text: "#d6bcfa", accent: "#b794f4" },
|
|
487
|
+
red: { bg: "#742a2a", text: "#fc8181", accent: "#feb2b2" },
|
|
488
|
+
orange: { bg: "#744210", text: "#fbd38d", accent: "#f6ad55" },
|
|
489
|
+
teal: { bg: "#234e52", text: "#81e6d9", accent: "#4fd1c5" }
|
|
490
|
+
};
|
|
491
|
+
var STARTER_THEME = {
|
|
492
|
+
schemaVersion: THEME_SCHEMA_VERSION,
|
|
493
|
+
id: "custom",
|
|
494
|
+
name: "Custom Theme",
|
|
495
|
+
description: "Customizer starter \u2014 gets overridden by user choices.",
|
|
496
|
+
colors: {
|
|
497
|
+
primary: "#3182ce",
|
|
498
|
+
secondary: "#4a5568",
|
|
499
|
+
background: "#1a202c",
|
|
500
|
+
backgroundLight: "#2d3748",
|
|
501
|
+
text: "#f7fafc",
|
|
502
|
+
textMuted: "#a0aec0",
|
|
503
|
+
highlight: "#4299e1",
|
|
504
|
+
warning: "#fc8181"
|
|
505
|
+
},
|
|
506
|
+
typography: {
|
|
507
|
+
bodyFont: STARTER_BODY_FONT,
|
|
508
|
+
titleFont: STARTER_TITLE_FONT,
|
|
509
|
+
monoFont: STARTER_MONO_FONT,
|
|
510
|
+
titleWeight: "bold"
|
|
511
|
+
},
|
|
512
|
+
style: {
|
|
513
|
+
textShadow: true,
|
|
514
|
+
overlayOpacity: 0.45,
|
|
515
|
+
animationSpeed: 1,
|
|
516
|
+
borderRadius: 6
|
|
517
|
+
},
|
|
518
|
+
renderStyle: {
|
|
519
|
+
name: "standard",
|
|
520
|
+
defaultTextAnimation: "fadeIn",
|
|
521
|
+
defaultImageAnimation: "slowZoom",
|
|
522
|
+
ambientMotion: true,
|
|
523
|
+
defaultTransition: { type: "fade", duration: 0.7 }
|
|
524
|
+
},
|
|
525
|
+
colorSchemes: STARTER_COLOR_SCHEMES
|
|
526
|
+
};
|
|
527
|
+
function deriveColorPalette(seeds, partialColors = {}, opts = {}) {
|
|
528
|
+
const spread = opts.contrast === "high" ? 0.22 : opts.contrast === "subtle" ? 0.08 : 0.15;
|
|
529
|
+
const primary = seeds.primary;
|
|
530
|
+
const secondary = seeds.secondary ?? oklchSetChroma(oklchLighten(primary, 0.05), 0.5);
|
|
531
|
+
const accent = seeds.accent ?? oklchLighten(primary, spread);
|
|
532
|
+
const bgSeed = partialColors.background ?? seeds.background;
|
|
533
|
+
let background;
|
|
534
|
+
if (bgSeed) {
|
|
535
|
+
background = bgSeed;
|
|
536
|
+
} else {
|
|
537
|
+
background = relativeLuminance(primary) > 0.5 ? "#0a0a0a" : "#1a202c";
|
|
538
|
+
}
|
|
539
|
+
const isLightSurface = relativeLuminance(background) > 0.5;
|
|
540
|
+
const backgroundLight = partialColors.backgroundLight ?? (isLightSurface ? oklchDarken(background, 0.04) : oklchLighten(background, 0.04));
|
|
541
|
+
const text = partialColors.text ?? seeds.text ?? pickContrastingText(background, "#f7fafc", "#1a202c");
|
|
542
|
+
const textMuted = partialColors.textMuted ?? (isLightSurface ? oklchLighten(text, 0.25) : oklchDarken(text, 0.25));
|
|
543
|
+
const highlight = partialColors.highlight ?? accent;
|
|
544
|
+
const warning = partialColors.warning ?? "#fc8181";
|
|
545
|
+
return {
|
|
546
|
+
primary: partialColors.primary ?? primary,
|
|
547
|
+
secondary: partialColors.secondary ?? secondary,
|
|
548
|
+
background,
|
|
549
|
+
backgroundLight,
|
|
550
|
+
text,
|
|
551
|
+
textMuted,
|
|
552
|
+
highlight,
|
|
553
|
+
warning
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
function accentToColorScheme(accent) {
|
|
557
|
+
if (!isHex(accent)) return { bg: "#1a202c", text: "#e2e8f0", accent: "#63b3ed" };
|
|
558
|
+
const scale = deriveScale(accent, 0.3);
|
|
559
|
+
return { bg: scale.darker2, text: scale.lighter2, accent: scale.base };
|
|
560
|
+
}
|
|
561
|
+
function compileTheme(partial, opts = {}) {
|
|
562
|
+
const base = opts.base ?? STARTER_THEME;
|
|
563
|
+
const merged = createTheme(base, partial);
|
|
564
|
+
merged.schemaVersion = THEME_SCHEMA_VERSION;
|
|
565
|
+
if (opts.base && !merged.basedOn) merged.basedOn = opts.base.id;
|
|
566
|
+
const partialTypography = partial.typography;
|
|
567
|
+
if (partialTypography) {
|
|
568
|
+
if (partialTypography.titleFont !== void 0) {
|
|
569
|
+
merged.typography.titleFont = partialTypography.titleFont;
|
|
570
|
+
}
|
|
571
|
+
if (partialTypography.bodyFont !== void 0) {
|
|
572
|
+
merged.typography.bodyFont = partialTypography.bodyFont;
|
|
573
|
+
}
|
|
574
|
+
if (partialTypography.monoFont !== void 0) {
|
|
575
|
+
merged.typography.monoFont = partialTypography.monoFont;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
if (partial.colorSchemes !== void 0) {
|
|
579
|
+
merged.colorSchemes = partial.colorSchemes;
|
|
580
|
+
}
|
|
581
|
+
if (merged.seedColors) {
|
|
582
|
+
const partialColors = partial.colors ?? {};
|
|
583
|
+
merged.colors = deriveColorPalette(merged.seedColors, partialColors, {
|
|
584
|
+
contrast: opts.contrast
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
if (!merged.pageStyle) {
|
|
588
|
+
merged.pageStyle = defaultPageStyle(merged);
|
|
589
|
+
}
|
|
590
|
+
return assertTheme(merged, `compiled theme "${merged.id}"`);
|
|
591
|
+
}
|
|
592
|
+
function parseTheme(json) {
|
|
593
|
+
let parsed;
|
|
594
|
+
try {
|
|
595
|
+
parsed = JSON.parse(json);
|
|
596
|
+
} catch (err) {
|
|
597
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
598
|
+
throw new Error(`Invalid theme JSON: ${msg}`);
|
|
599
|
+
}
|
|
600
|
+
return assertTheme(parsed, "parsed theme");
|
|
601
|
+
}
|
|
602
|
+
function serializeTheme(theme) {
|
|
603
|
+
return JSON.stringify(theme, null, 2);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// src/schemas/mermaidTheme.ts
|
|
607
|
+
var MERMAID_CHART_COLOR_COUNT = 12;
|
|
608
|
+
function uniqueColors(colors) {
|
|
609
|
+
return colors.filter((color, index) => color && colors.indexOf(color) === index);
|
|
610
|
+
}
|
|
611
|
+
function chartPalette(theme) {
|
|
612
|
+
const schemes = Object.values(theme.colorSchemes);
|
|
613
|
+
const seeds = uniqueColors([
|
|
614
|
+
theme.colors.primary,
|
|
615
|
+
theme.colors.secondary,
|
|
616
|
+
theme.colors.highlight,
|
|
617
|
+
...schemes.map((scheme) => scheme.accent),
|
|
618
|
+
theme.colors.warning,
|
|
619
|
+
...schemes.map((scheme) => scheme.bg),
|
|
620
|
+
theme.colors.textMuted,
|
|
621
|
+
theme.colors.backgroundLight
|
|
622
|
+
]);
|
|
623
|
+
const fallback = theme.colors.primary;
|
|
624
|
+
return Array.from(
|
|
625
|
+
{ length: MERMAID_CHART_COLOR_COUNT },
|
|
626
|
+
(_, index) => seeds[index % Math.max(1, seeds.length)] ?? fallback
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
function textOn(theme, background) {
|
|
630
|
+
return pickContrastingText(background, theme.colors.text, theme.colors.background);
|
|
631
|
+
}
|
|
632
|
+
function buildMermaidThemeVariables(theme) {
|
|
633
|
+
const { colors } = theme;
|
|
634
|
+
const primaryText = textOn(theme, colors.primary);
|
|
635
|
+
const secondaryText = textOn(theme, colors.secondary);
|
|
636
|
+
const highlightText = textOn(theme, colors.highlight);
|
|
637
|
+
const palette = chartPalette(theme);
|
|
638
|
+
const variables = {
|
|
639
|
+
darkMode: relativeLuminance(colors.background) < 0.5,
|
|
640
|
+
background: colors.background,
|
|
641
|
+
fontFamily: resolveFontFamily(theme.typography.bodyFont, FONT_FALLBACKS.sans),
|
|
642
|
+
primaryColor: colors.primary,
|
|
643
|
+
primaryTextColor: primaryText,
|
|
644
|
+
primaryBorderColor: colors.highlight,
|
|
645
|
+
secondaryColor: colors.secondary,
|
|
646
|
+
secondaryTextColor: secondaryText,
|
|
647
|
+
secondaryBorderColor: colors.primary,
|
|
648
|
+
tertiaryColor: colors.backgroundLight,
|
|
649
|
+
tertiaryTextColor: colors.text,
|
|
650
|
+
tertiaryBorderColor: colors.textMuted,
|
|
651
|
+
textColor: colors.text,
|
|
652
|
+
titleColor: colors.text,
|
|
653
|
+
lineColor: colors.textMuted,
|
|
654
|
+
arrowheadColor: colors.textMuted,
|
|
655
|
+
defaultLinkColor: colors.textMuted,
|
|
656
|
+
mainBkg: colors.primary,
|
|
657
|
+
nodeBkg: colors.primary,
|
|
658
|
+
nodeTextColor: primaryText,
|
|
659
|
+
nodeBorder: colors.highlight,
|
|
660
|
+
clusterBkg: colors.backgroundLight,
|
|
661
|
+
clusterBorder: colors.secondary,
|
|
662
|
+
edgeLabelBackground: colors.background,
|
|
663
|
+
actorBkg: colors.backgroundLight,
|
|
664
|
+
actorBorder: colors.primary,
|
|
665
|
+
actorTextColor: colors.text,
|
|
666
|
+
actorLineColor: colors.textMuted,
|
|
667
|
+
signalColor: colors.textMuted,
|
|
668
|
+
signalTextColor: colors.text,
|
|
669
|
+
labelBoxBkgColor: colors.backgroundLight,
|
|
670
|
+
labelBoxBorderColor: colors.secondary,
|
|
671
|
+
labelTextColor: colors.text,
|
|
672
|
+
loopTextColor: colors.text,
|
|
673
|
+
activationBkgColor: colors.secondary,
|
|
674
|
+
activationBorderColor: colors.primary,
|
|
675
|
+
sequenceNumberColor: primaryText,
|
|
676
|
+
noteBkgColor: colors.highlight,
|
|
677
|
+
noteBorderColor: colors.primary,
|
|
678
|
+
noteTextColor: highlightText,
|
|
679
|
+
sectionBkgColor: colors.backgroundLight,
|
|
680
|
+
altSectionBkgColor: colors.background,
|
|
681
|
+
sectionBkgColor2: colors.primary,
|
|
682
|
+
taskBkgColor: colors.primary,
|
|
683
|
+
taskBorderColor: colors.highlight,
|
|
684
|
+
taskTextColor: primaryText,
|
|
685
|
+
taskTextLightColor: colors.text,
|
|
686
|
+
taskTextDarkColor: colors.text,
|
|
687
|
+
taskTextOutsideColor: colors.text,
|
|
688
|
+
taskTextClickableColor: colors.highlight,
|
|
689
|
+
activeTaskBkgColor: colors.secondary,
|
|
690
|
+
activeTaskBorderColor: colors.highlight,
|
|
691
|
+
doneTaskBkgColor: colors.backgroundLight,
|
|
692
|
+
doneTaskBorderColor: colors.textMuted,
|
|
693
|
+
critBkgColor: colors.warning,
|
|
694
|
+
critBorderColor: colors.highlight,
|
|
695
|
+
todayLineColor: colors.warning,
|
|
696
|
+
gridColor: colors.textMuted,
|
|
697
|
+
pieTitleTextColor: colors.text,
|
|
698
|
+
pieSectionTextColor: colors.text,
|
|
699
|
+
pieLegendTextColor: colors.text,
|
|
700
|
+
pieStrokeColor: colors.background,
|
|
701
|
+
pieOuterStrokeColor: colors.textMuted,
|
|
702
|
+
quadrantPointFill: colors.highlight,
|
|
703
|
+
quadrantPointTextFill: highlightText,
|
|
704
|
+
quadrantXAxisTextFill: colors.text,
|
|
705
|
+
quadrantYAxisTextFill: colors.text,
|
|
706
|
+
quadrantTitleFill: colors.text,
|
|
707
|
+
requirementBackground: colors.backgroundLight,
|
|
708
|
+
requirementBorderColor: colors.primary,
|
|
709
|
+
requirementTextColor: colors.text,
|
|
710
|
+
relationColor: colors.textMuted,
|
|
711
|
+
relationLabelBackground: colors.background,
|
|
712
|
+
relationLabelColor: colors.text,
|
|
713
|
+
commitLabelColor: colors.text,
|
|
714
|
+
commitLabelBackground: colors.backgroundLight,
|
|
715
|
+
tagLabelColor: primaryText,
|
|
716
|
+
tagLabelBackground: colors.primary,
|
|
717
|
+
tagLabelBorder: colors.highlight
|
|
718
|
+
};
|
|
719
|
+
palette.forEach((color, index) => {
|
|
720
|
+
const label = textOn(theme, color);
|
|
721
|
+
variables[`cScale${index}`] = color;
|
|
722
|
+
variables[`cScaleInv${index}`] = label;
|
|
723
|
+
variables[`cScaleLabel${index}`] = label;
|
|
724
|
+
variables[`cScalePeer${index}`] = label;
|
|
725
|
+
variables[`pie${index + 1}`] = color;
|
|
726
|
+
if (index < 8) {
|
|
727
|
+
variables[`git${index}`] = color;
|
|
728
|
+
variables[`gitInv${index}`] = label;
|
|
729
|
+
variables[`gitBranchLabel${index}`] = label;
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
return variables;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
export {
|
|
736
|
+
calculateDuration,
|
|
737
|
+
getSegmentAtTime,
|
|
738
|
+
getBlockAtTime,
|
|
739
|
+
getCaptionAtTime,
|
|
740
|
+
validateDocSchema,
|
|
741
|
+
assertDocSchema,
|
|
742
|
+
pipStyleVars,
|
|
743
|
+
STARTER_THEME,
|
|
744
|
+
deriveColorPalette,
|
|
745
|
+
accentToColorScheme,
|
|
746
|
+
compileTheme,
|
|
747
|
+
parseTheme,
|
|
748
|
+
serializeTheme,
|
|
749
|
+
buildMermaidThemeVariables
|
|
750
|
+
};
|