@bendyline/squisq 2.13.0 → 2.13.2

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.
Files changed (37) hide show
  1. package/dist/{Doc-czvrR7Oy.d.ts → Doc-CYTLtFEu.d.ts} +32 -0
  2. package/dist/{ImageEditDoc-BDkpwCMN.d.ts → ImageEditDoc-DZ4k_O10.d.ts} +1 -1
  3. package/dist/{chunk-Y3HL26X3.js → chunk-2GN67Q2T.js} +1 -1
  4. package/dist/{chunk-PVFDR3XT.js → chunk-3A6YM375.js} +1 -1
  5. package/dist/{chunk-ECPR5JKY.js → chunk-56TW6HE6.js} +7 -7
  6. package/dist/{chunk-4OQFLZ6G.js → chunk-5HWYSUXS.js} +20 -4
  7. package/dist/{chunk-ILLLGZCE.js → chunk-7ZXCS3UU.js} +2 -2
  8. package/dist/{chunk-2DXLKKTS.js → chunk-FUQYQWQR.js} +5 -5
  9. package/dist/{chunk-GX3VSKYS.js → chunk-GLWQTZ4C.js} +1 -1
  10. package/dist/{chunk-MWSGNEH6.js → chunk-HE3HQZWU.js} +1 -0
  11. package/dist/{chunk-JDYWKGG7.js → chunk-HGCIIXHP.js} +1 -1
  12. package/dist/{chunk-E2NFHYCB.js → chunk-ISVJ42I3.js} +7 -1
  13. package/dist/{chunk-HYJ63N6V.js → chunk-WNEH3BZP.js} +14 -0
  14. package/dist/{chunk-FVFTJ64H.js → chunk-YY3OQ3MI.js} +296 -53
  15. package/dist/doc/index.d.ts +11 -6
  16. package/dist/doc/index.js +8 -8
  17. package/dist/fence/index.d.ts +1 -1
  18. package/dist/generate/index.d.ts +1 -1
  19. package/dist/imageEdit/index.d.ts +3 -3
  20. package/dist/index.d.ts +4 -4
  21. package/dist/index.js +12 -12
  22. package/dist/jsonForm/index.d.ts +1 -1
  23. package/dist/jsonForm/index.js +3 -3
  24. package/dist/markdown/index.js +3 -3
  25. package/dist/{materializePageSection-mTAAHNlA.d.ts → materializePageSection-CDps_xUd.d.ts} +1 -1
  26. package/dist/mediaEdit/index.d.ts +2 -2
  27. package/dist/narration/index.d.ts +1 -1
  28. package/dist/narration/index.js +5 -5
  29. package/dist/recommend/index.js +2 -2
  30. package/dist/schemas/index.d.ts +4 -4
  31. package/dist/schemas/index.js +2 -2
  32. package/dist/{themeLibrary-Bsn4YNuq.d.ts → themeLibrary-CMm_jh3a.d.ts} +1 -1
  33. package/dist/timing/index.d.ts +7 -1
  34. package/dist/timing/index.js +1 -1
  35. package/dist/transform/index.d.ts +2 -2
  36. package/dist/transform/index.js +6 -6
  37. package/package.json +1 -1
@@ -1936,6 +1936,13 @@ interface ThemeTypography {
1936
1936
  titleLineHeight?: number;
1937
1937
  /** Default title font weight */
1938
1938
  titleWeight?: 'normal' | 'bold';
1939
+ /** Font family for social (burned-in, word-by-word) captions (default: titleFont) */
1940
+ captionFont?: FontFamily;
1941
+ /**
1942
+ * Letter case of social captions: `'upper'` (default) sets them in capitals;
1943
+ * `'as-written'` keeps the narration's own casing, so names keep their capitals.
1944
+ */
1945
+ captionCase?: 'upper' | 'as-written';
1939
1946
  }
1940
1947
  /**
1941
1948
  * Global visual-style knobs that templates consult.
@@ -2295,6 +2302,14 @@ interface StartBlockConfig {
2295
2302
  heroCredit?: string;
2296
2303
  /** License identifier for the hero image */
2297
2304
  heroLicense?: string;
2305
+ /**
2306
+ * How a hero cover keeps its title legible. `'scrim'` (default): a gradient tinted from
2307
+ * the theme background darkens the lower frame, with the title low and wide.
2308
+ * `'frosted'`: the photo stays clear; the title sits on a frosted-glass plate near the
2309
+ * bottom that grows upward for longer titles, kept within the frame's centre square
2310
+ * (so a square crop, such as a social link card, shows all of it).
2311
+ */
2312
+ coverStyle?: 'scrim' | 'frosted';
2298
2313
  }
2299
2314
  /**
2300
2315
  * A structural problem detected while converting or validating a document.
@@ -2826,6 +2841,18 @@ interface ShapeLayer extends BaseLayer {
2826
2841
  borderStyle?: BorderStyle;
2827
2842
  /** Corner radius for rect */
2828
2843
  borderRadius?: number;
2844
+ /**
2845
+ * Frosted glass: blur what lies behind a rect by this radius in px (CSS
2846
+ * `backdrop-filter`), under its fill. Use a translucent fill for the tint.
2847
+ */
2848
+ backdropBlur?: number;
2849
+ /**
2850
+ * Frosted glass: scale the contrast of what lies behind a rect toward mid-grey (CSS
2851
+ * `backdrop-filter: contrast()`), with `backdropBlur`. Below 1 it pulls bright snow
2852
+ * or sky down (and deep shadow up) while mid-tones barely move, so light text stays
2853
+ * legible on glass over any photo without darkening the glass overall.
2854
+ */
2855
+ backdropContrast?: number;
2829
2856
  };
2830
2857
  }
2831
2858
  /**
@@ -3303,6 +3330,11 @@ interface CaptionWord {
3303
3330
  startTime: number;
3304
3331
  /** End time in seconds */
3305
3332
  endTime: number;
3333
+ /**
3334
+ * The narration text starts a new paragraph after this word, with no punctuation to
3335
+ * show it (a spoken title or heading): captions break here as at a sentence end.
3336
+ */
3337
+ paragraphEnd?: boolean;
3306
3338
  }
3307
3339
  /**
3308
3340
  * A single caption phrase to display during playback.
@@ -1,4 +1,4 @@
1
- import { a2 as ImageLayer, bw as TextLayer, bh as ShapeLayer, aX as PathLayer } from './Doc-czvrR7Oy.js';
1
+ import { a2 as ImageLayer, bw as TextLayer, bh as ShapeLayer, aX as PathLayer } from './Doc-CYTLtFEu.js';
2
2
 
3
3
  /**
4
4
  * ImageEditDoc — JSON document describing a layered, editable image.
@@ -8,7 +8,7 @@ import {
8
8
  expectedSyllablesAt,
9
9
  flattenRenderableBlocks,
10
10
  wordPosAtExpectedSyllables
11
- } from "./chunk-FVFTJ64H.js";
11
+ } from "./chunk-YY3OQ3MI.js";
12
12
 
13
13
  // src/narration/types.ts
14
14
  var DEFAULT_FEATURE_CONFIG = Object.freeze({
@@ -11,7 +11,7 @@ import {
11
11
  parseFrontmatter,
12
12
  parseHtmlToNodes,
13
13
  sanitizeUrl
14
- } from "./chunk-MWSGNEH6.js";
14
+ } from "./chunk-HE3HQZWU.js";
15
15
  import {
16
16
  resolveIcon
17
17
  } from "./chunk-CZ7AUSLI.js";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-FTN6SGW5.js";
4
4
  import {
5
5
  applySavedPresentation
6
- } from "./chunk-2DXLKKTS.js";
6
+ } from "./chunk-FUQYQWQR.js";
7
7
  import {
8
8
  SHAPE_NAMES,
9
9
  buildChartData,
@@ -32,7 +32,7 @@ import {
32
32
  templateRegistry,
33
33
  writeCustomTemplatesToFrontmatter,
34
34
  writeCustomThemesToFrontmatter
35
- } from "./chunk-FVFTJ64H.js";
35
+ } from "./chunk-YY3OQ3MI.js";
36
36
  import {
37
37
  ASCII_TREE_VOCAB,
38
38
  ASCII_VOCAB,
@@ -54,7 +54,7 @@ import {
54
54
  toCells,
55
55
  toGrid,
56
56
  traceBoxes
57
- } from "./chunk-JDYWKGG7.js";
57
+ } from "./chunk-HGCIIXHP.js";
58
58
  import {
59
59
  iconMarker
60
60
  } from "./chunk-7ZAAICW4.js";
@@ -78,7 +78,7 @@ import {
78
78
  resolveFontFamily,
79
79
  resolveTheme,
80
80
  withAlpha
81
- } from "./chunk-HYJ63N6V.js";
81
+ } from "./chunk-WNEH3BZP.js";
82
82
  import {
83
83
  createMediaTimeMap
84
84
  } from "./chunk-JSGIWW35.js";
@@ -87,7 +87,7 @@ import {
87
87
  } from "./chunk-L7QZORLB.js";
88
88
  import {
89
89
  parseMarkdown
90
- } from "./chunk-PVFDR3XT.js";
90
+ } from "./chunk-3A6YM375.js";
91
91
  import {
92
92
  TABLE_FED_TEMPLATES,
93
93
  TEMPLATE_ALIASES,
@@ -105,14 +105,14 @@ import {
105
105
  parseHtmlToNodes,
106
106
  parseVideoEmbedUrl,
107
107
  readFrontmatterThemeId
108
- } from "./chunk-MWSGNEH6.js";
108
+ } from "./chunk-HE3HQZWU.js";
109
109
  import {
110
110
  BUILD_PARAM_KEYS,
111
111
  buildSpecParams
112
112
  } from "./chunk-P53Z4RYC.js";
113
113
  import {
114
114
  buildCaptionTrack
115
- } from "./chunk-4OQFLZ6G.js";
115
+ } from "./chunk-5HWYSUXS.js";
116
116
  import {
117
117
  estimateTimeFromText
118
118
  } from "./chunk-GHOPHGOK.js";
@@ -8,6 +8,20 @@ var DEFAULT_TARGET_WORDS = 10;
8
8
  var DEFAULT_MIN_DURATION = 1.5;
9
9
  var DEFAULT_MAX_DURATION = 6;
10
10
  var DEFAULT_WORDS_PER_SECOND = 2.5;
11
+ var CLOSING_MARKS = /^[.,;:!?…"'”’»)\]]+/;
12
+ var OPENING_MARKS = /[“"‘'«([]+$/;
13
+ function writtenWord(sourceText, bookmark, fragment) {
14
+ const at = bookmark.charOffset;
15
+ if (!sourceText || !(at >= 0)) return { text: fragment, paragraphEnd: false };
16
+ if (sourceText.slice(at, at + fragment.length).toLowerCase() !== fragment.toLowerCase()) {
17
+ return { text: fragment, paragraphEnd: false };
18
+ }
19
+ const end = at + fragment.length;
20
+ const before = OPENING_MARKS.exec(sourceText.slice(Math.max(0, at - 3), at))?.[0] ?? "";
21
+ const after = CLOSING_MARKS.exec(sourceText.slice(end, end + 4))?.[0] ?? "";
22
+ const paragraphEnd = /^[^\S\n]*\n/.test(sourceText.slice(end + after.length));
23
+ return { text: before + fragment + after, paragraphEnd };
24
+ }
11
25
  function phrasesFromTiming(source, segmentIndex, targetWords) {
12
26
  const { segment, timing } = source;
13
27
  if (!timing || timing.bookmarks.length === 0) return [];
@@ -17,8 +31,9 @@ function phrasesFromTiming(source, segmentIndex, targetWords) {
17
31
  let phraseText = "";
18
32
  for (let index = 0; index < timing.bookmarks.length; index += 1) {
19
33
  const bookmark = timing.bookmarks[index];
20
- const text = bookmark.textFragment?.trim() ?? "";
21
- if (!text) continue;
34
+ const fragment = bookmark.textFragment?.trim() ?? "";
35
+ if (!fragment) continue;
36
+ const { text, paragraphEnd } = writtenWord(timing.sourceText, bookmark, fragment);
22
37
  const next = timing.bookmarks[index + 1];
23
38
  const startTime = Math.min(
24
39
  segmentEnd,
@@ -31,11 +46,12 @@ function phrasesFromTiming(source, segmentIndex, targetWords) {
31
46
  const word = {
32
47
  text,
33
48
  startTime,
34
- endTime
49
+ endTime,
50
+ ...paragraphEnd ? { paragraphEnd: true } : {}
35
51
  };
36
52
  words.push(word);
37
53
  phraseText += `${phraseText ? " " : ""}${text}`;
38
- const flush = /[.!?]$/.test(text) && words.length >= 4 || /[,;:]$/.test(text) && words.length >= targetWords - 2 || words.length >= targetWords + 3 || index === timing.bookmarks.length - 1;
54
+ const flush = paragraphEnd || /[.!?]$/.test(text) && words.length >= 4 || /[,;:]$/.test(text) && words.length >= targetWords - 2 || words.length >= targetWords + 3 || index === timing.bookmarks.length - 1;
39
55
  if (flush) {
40
56
  phrases.push({
41
57
  text: phraseText,
@@ -3,14 +3,14 @@ import {
3
3
  parseMarkdown,
4
4
  remarkWikiLinks,
5
5
  toMdast
6
- } from "./chunk-PVFDR3XT.js";
6
+ } from "./chunk-3A6YM375.js";
7
7
  import {
8
8
  formatFrontmatterYaml,
9
9
  getChildren,
10
10
  splitFrontmatterBlock,
11
11
  stringifyHtmlNodes,
12
12
  walkMarkdownTree
13
- } from "./chunk-MWSGNEH6.js";
13
+ } from "./chunk-HE3HQZWU.js";
14
14
 
15
15
  // src/markdown/stringify.ts
16
16
  import { unified } from "unified";
@@ -4,7 +4,7 @@ import {
4
4
  flattenRenderableBlocks,
5
5
  getPinnedBlockMeta,
6
6
  markdownToDoc
7
- } from "./chunk-FVFTJ64H.js";
7
+ } from "./chunk-YY3OQ3MI.js";
8
8
  import {
9
9
  deriveTemplateInputs,
10
10
  extractImages,
@@ -12,7 +12,7 @@ import {
12
12
  isAsciiTimelineFence,
13
13
  isPictureFence,
14
14
  isTreeFence
15
- } from "./chunk-JDYWKGG7.js";
15
+ } from "./chunk-HGCIIXHP.js";
16
16
  import {
17
17
  extractContent,
18
18
  mapElementToBlock,
@@ -21,10 +21,10 @@ import {
21
21
  import {
22
22
  cloneAndFreezeData,
23
23
  isTemplateBlock
24
- } from "./chunk-HYJ63N6V.js";
24
+ } from "./chunk-WNEH3BZP.js";
25
25
  import {
26
26
  parseMarkdown
27
- } from "./chunk-PVFDR3XT.js";
27
+ } from "./chunk-3A6YM375.js";
28
28
  import {
29
29
  isContainerTemplate
30
30
  } from "./chunk-Y25EJEZN.js";
@@ -32,7 +32,7 @@ import {
32
32
  extractPlainText,
33
33
  getChildren,
34
34
  stringifyHtmlNodes
35
- } from "./chunk-MWSGNEH6.js";
35
+ } from "./chunk-HE3HQZWU.js";
36
36
  import {
37
37
  parseBuildSpec
38
38
  } from "./chunk-P53Z4RYC.js";
@@ -2,7 +2,7 @@ import {
2
2
  DEFAULT_THEME,
3
3
  applySurface,
4
4
  resolveFontFamily
5
- } from "./chunk-HYJ63N6V.js";
5
+ } from "./chunk-WNEH3BZP.js";
6
6
 
7
7
  // src/jsonForm/chooseControl.ts
8
8
  var ENUM_SEGMENTED_LIMIT = 4;
@@ -176,6 +176,7 @@ function extractPlainText(node) {
176
176
  if ("value" in node && typeof node.value === "string") {
177
177
  return node.value;
178
178
  }
179
+ if (node.type === "break") return "\n";
179
180
  const children = getChildren(node);
180
181
  const separator = node.type === "list" || node.type === "listItem" || node.type === "table" ? "\n" : node.type === "tableRow" ? " " : "";
181
182
  return children.map(extractPlainText).join(separator);
@@ -8,7 +8,7 @@ import {
8
8
  parseTimeSeconds,
9
9
  sanitizeUrl,
10
10
  walkMarkdownTree
11
- } from "./chunk-MWSGNEH6.js";
11
+ } from "./chunk-HE3HQZWU.js";
12
12
 
13
13
  // src/doc/asciiDiagram/chars.ts
14
14
  function toCells(s) {
@@ -15,7 +15,7 @@ import {
15
15
  relativeLuminance,
16
16
  resolveFontFamily,
17
17
  withAlpha
18
- } from "./chunk-HYJ63N6V.js";
18
+ } from "./chunk-WNEH3BZP.js";
19
19
  import {
20
20
  SVG_ISLAND_LIMITS,
21
21
  parseBuildSpec
@@ -306,6 +306,9 @@ function validateStartBlock(value, issues) {
306
306
  optionalString(value, "heroSrc", "startBlock.heroSrc", issues);
307
307
  optionalString(value, "heroAlt", "startBlock.heroAlt", issues);
308
308
  optionalString(value, "subtitle", "startBlock.subtitle", issues);
309
+ if (value.coverStyle !== void 0 && value.coverStyle !== "scrim" && value.coverStyle !== "frosted") {
310
+ add(issues, "startBlock.coverStyle", 'must be "scrim" or "frosted"', value.coverStyle);
311
+ }
309
312
  }
310
313
  function validateCaptions(value, issues) {
311
314
  if (!isRecord(value)) {
@@ -598,6 +601,9 @@ function compileTheme(partial, opts = {}) {
598
601
  if (partialTypography.monoFont !== void 0) {
599
602
  merged.typography.monoFont = partialTypography.monoFont;
600
603
  }
604
+ if (partialTypography.captionFont !== void 0) {
605
+ merged.typography.captionFont = partialTypography.captionFont;
606
+ }
601
607
  }
602
608
  if (partial.colorSchemes !== void 0) {
603
609
  merged.colorSchemes = partial.colorSchemes;
@@ -1042,6 +1042,10 @@ var V = class {
1042
1042
  this.fontFamily(`${path}.bodyFont`, v.bodyFont);
1043
1043
  this.fontFamily(`${path}.titleFont`, v.titleFont);
1044
1044
  if (v.monoFont !== void 0) this.fontFamily(`${path}.monoFont`, v.monoFont);
1045
+ if (v.captionFont !== void 0) this.fontFamily(`${path}.captionFont`, v.captionFont);
1046
+ if (v.captionCase !== void 0 && v.captionCase !== "upper" && v.captionCase !== "as-written") {
1047
+ this.err(`${path}.captionCase`, 'expected "upper" or "as-written"');
1048
+ }
1045
1049
  for (const k of ["titleScale", "bodyScale", "lineHeight", "titleLineHeight"]) {
1046
1050
  if (v[k] !== void 0 && !this.isNumber(v[k])) {
1047
1051
  this.err(`${path}.${k}`, `expected number, got ${typeof v[k]}`);
@@ -2636,6 +2640,8 @@ var warm_earth_default = {
2636
2640
  typography: {
2637
2641
  bodyFont: { stackId: "pt-serif" },
2638
2642
  titleFont: { stackId: "pt-serif" },
2643
+ captionFont: { stackId: "pt-sans" },
2644
+ captionCase: "as-written",
2639
2645
  titleWeight: "bold",
2640
2646
  lineHeight: 1.6
2641
2647
  },
@@ -2924,6 +2930,14 @@ var AVAILABLE_FONT_STACKS = [
2924
2930
  kind: "sans",
2925
2931
  googleFontFamily: "DM Sans"
2926
2932
  },
2933
+ {
2934
+ // PT Serif's companion sans (same designers, shared proportions); also a macOS system font.
2935
+ id: "pt-sans",
2936
+ label: "PT Sans",
2937
+ family: '"PT Sans", "Helvetica Neue", Arial, sans-serif',
2938
+ kind: "sans",
2939
+ googleFontFamily: "PT Sans"
2940
+ },
2927
2941
  {
2928
2942
  id: "oswald",
2929
2943
  label: "Oswald",