@bendyline/squisq 2.10.0 → 2.11.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.
Files changed (37) hide show
  1. package/dist/{Doc-DTyeaFuW.d.ts → Doc-CRPQCkHn.d.ts} +34 -2
  2. package/dist/{ImageEditDoc-dFEclQ9l.d.ts → ImageEditDoc-MbvJM1HE.d.ts} +1 -1
  3. package/dist/{chunk-IO5XO6XH.js → chunk-64I44JAP.js} +1 -1
  4. package/dist/{chunk-CUYHFOFL.js → chunk-6ATZOUCQ.js} +223 -14
  5. package/dist/{chunk-DRFJU4MK.js → chunk-B26DU2RH.js} +353 -3
  6. package/dist/{chunk-T3B4WJBR.js → chunk-B3AK7SLZ.js} +87 -5
  7. package/dist/{chunk-7YEZFHLS.js → chunk-O7HLQ22N.js} +11 -0
  8. package/dist/{chunk-XSW4QTMB.js → chunk-QQ4I5HWV.js} +228 -6
  9. package/dist/{chunk-NBKAXPSX.js → chunk-TMOHAFYE.js} +1 -0
  10. package/dist/{chunk-MIKKUKOD.js → chunk-UBFT2CDQ.js} +30 -15
  11. package/dist/{chunk-FCG3BIZN.js → chunk-UNVHAK3A.js} +5 -1
  12. package/dist/{chunk-NFHMHYUV.js → chunk-UXKFSYTQ.js} +1 -1
  13. package/dist/doc/index.d.ts +123 -6
  14. package/dist/doc/index.js +13 -5
  15. package/dist/fence/index.d.ts +1 -1
  16. package/dist/generate/index.d.ts +1 -1
  17. package/dist/imageEdit/index.d.ts +3 -3
  18. package/dist/index.d.ts +8 -7
  19. package/dist/index.js +22 -10
  20. package/dist/jsonForm/index.d.ts +1 -1
  21. package/dist/markdown/index.js +3 -3
  22. package/dist/{materializePageSection-BRNIINlU.d.ts → materializePageSection-BeUPHeCl.d.ts} +1 -1
  23. package/dist/narration/index.d.ts +1 -1
  24. package/dist/narration/index.js +4 -4
  25. package/dist/proof/index.d.ts +22 -3
  26. package/dist/proof/index.js +1 -1
  27. package/dist/recommend/index.js +1 -1
  28. package/dist/schemas/index.d.ts +4 -4
  29. package/dist/storage/index.js +1 -1
  30. package/dist/table/index.d.ts +123 -0
  31. package/dist/table/index.js +298 -0
  32. package/dist/{themeLibrary-xaxN5UYu.d.ts → themeLibrary-BG3jr6mT.d.ts} +1 -1
  33. package/dist/transform/index.d.ts +2 -2
  34. package/dist/versions/index.d.ts +15 -1
  35. package/dist/versions/index.js +5 -1
  36. package/dist/viewState-lTZS-hP_.d.ts +91 -0
  37. package/package.json +6 -1
@@ -21,7 +21,7 @@ import {
21
21
  parseAsciiTimeline,
22
22
  pickAutoTemplate,
23
23
  profileBlockContents
24
- } from "./chunk-CUYHFOFL.js";
24
+ } from "./chunk-6ATZOUCQ.js";
25
25
  import {
26
26
  DEFAULT_THEME,
27
27
  FRONTMATTER_CUSTOM_TEMPLATES_KEY,
@@ -56,7 +56,7 @@ import {
56
56
  sanitizeUrl,
57
57
  splitKeyValueToken,
58
58
  tokenizeAttrTokens
59
- } from "./chunk-NBKAXPSX.js";
59
+ } from "./chunk-TMOHAFYE.js";
60
60
  import {
61
61
  extractPlainText,
62
62
  readFrontmatterThemeId,
@@ -6850,11 +6850,283 @@ function scatterChart(input, context) {
6850
6850
  return renderChart("scatter", input, context);
6851
6851
  }
6852
6852
 
6853
+ // src/doc/templates/transcriptBlock.ts
6854
+ function transcriptBlock(rawInput, context) {
6855
+ const input = {
6856
+ ...rawInput,
6857
+ speaker: rawInput.speaker ?? rawInput.title ?? "Speaker",
6858
+ text: rawInput.text ?? ""
6859
+ };
6860
+ const { theme } = context;
6861
+ const scheme = resolveColorScheme(context, input.colorScheme);
6862
+ const variant = input.variant ?? "speech";
6863
+ const side = input.side ?? "left";
6864
+ const handoff = typeof input.counterpartName === "string" && input.counterpartName.length > 0;
6865
+ const bodyFont = getThemeFont(context, "body");
6866
+ const monoFont = getThemeFont(context, "mono");
6867
+ const nameFontSize = themedFontSize(26, context, false);
6868
+ const textFontSize = themedFontSize(32, context, true);
6869
+ const metaFontSize = themedFontSize(22, context, false);
6870
+ const bubbleFill = variant === "thought" ? withAlpha(theme.colors.text, 0.05) : variant === "tool" ? withAlpha(scheme.accent, 0.12) : withAlpha(theme.colors.text, 0.08);
6871
+ const textColor = variant === "thought" ? theme.colors.textMuted : theme.colors.text;
6872
+ const layers = [createBackgroundLayer("bg", themedSurfaceGradient(context, 160))];
6873
+ if (handoff) {
6874
+ return [...layers, ...handoffLayers(input, context, scheme.accent, textColor, bubbleFill)];
6875
+ }
6876
+ const avatarX = side === "left" ? "12%" : "88%";
6877
+ const columnX = side === "left" ? "20%" : "18%";
6878
+ const bubbleWidthPct = 62;
6879
+ layers.push(
6880
+ ...avatarLayers("speaker", input.speaker, input.speakerImage, avatarX, "34%", context)
6881
+ );
6882
+ layers.push({
6883
+ type: "text",
6884
+ id: "speaker-name",
6885
+ content: {
6886
+ text: input.speaker + (variant === "thought" ? " \xB7 thinking" : ""),
6887
+ style: {
6888
+ fontSize: nameFontSize,
6889
+ fontFamily: bodyFont,
6890
+ fontWeight: "bold",
6891
+ color: theme.colors.textMuted,
6892
+ textAlign: side === "left" ? "left" : "right",
6893
+ shadow: shouldUseShadow(context)
6894
+ }
6895
+ },
6896
+ position: { x: columnX, y: "24%", width: `${bubbleWidthPct}%`, anchor: "top-left" },
6897
+ animation: { type: "fadeIn", duration: 0.4 }
6898
+ });
6899
+ const bubbleWidthPx = (bubbleWidthPct - 5) / 100 * context.viewport.width;
6900
+ const textHeightPct = Math.min(
6901
+ 46,
6902
+ estimateTextHeight(input.text, textFontSize, bubbleWidthPx, 1.35) / context.viewport.height * 100 + 8
6903
+ );
6904
+ layers.push({
6905
+ type: "shape",
6906
+ id: "bubble",
6907
+ content: {
6908
+ shape: "rect",
6909
+ fill: bubbleFill,
6910
+ borderRadius: 18,
6911
+ ...variant === "tool" ? { stroke: scheme.accent, strokeWidth: 2 } : {}
6912
+ },
6913
+ position: {
6914
+ x: columnX,
6915
+ y: "29%",
6916
+ width: `${bubbleWidthPct}%`,
6917
+ height: `${Math.max(16, textHeightPct)}%`,
6918
+ anchor: "top-left"
6919
+ },
6920
+ animation: { type: "fadeIn", duration: 0.4, delay: 0.1 }
6921
+ });
6922
+ if (variant === "tool" && input.toolName) {
6923
+ layers.push({
6924
+ type: "text",
6925
+ id: "tool-name",
6926
+ content: {
6927
+ text: input.toolName,
6928
+ style: {
6929
+ fontSize: themedFontSize(28, context, false),
6930
+ fontFamily: monoFont,
6931
+ fontWeight: "bold",
6932
+ color: scheme.accent
6933
+ }
6934
+ },
6935
+ position: { x: `${parseFloat(columnX) + 2}%`, y: "32%", anchor: "top-left" },
6936
+ animation: { type: "fadeIn", duration: 0.4, delay: 0.15 }
6937
+ });
6938
+ }
6939
+ layers.push({
6940
+ type: "text",
6941
+ id: "message",
6942
+ content: {
6943
+ text: input.text,
6944
+ style: {
6945
+ fontSize: textFontSize,
6946
+ fontFamily: variant === "tool" ? monoFont : bodyFont,
6947
+ fontStyle: variant === "thought" ? "italic" : "normal",
6948
+ color: textColor,
6949
+ lineHeight: 1.35,
6950
+ maxLines: 7
6951
+ }
6952
+ },
6953
+ position: {
6954
+ x: `${parseFloat(columnX) + 2}%`,
6955
+ y: variant === "tool" && input.toolName ? "38%" : "32.5%",
6956
+ width: `${bubbleWidthPct - 4}%`,
6957
+ anchor: "top-left"
6958
+ },
6959
+ animation: { type: "typewriter", duration: Math.min(2.5, 0.4 + input.text.length / 120) }
6960
+ });
6961
+ if (variant === "tool" && input.resultText) {
6962
+ layers.push({
6963
+ type: "text",
6964
+ id: "tool-result",
6965
+ content: {
6966
+ text: input.resultText,
6967
+ style: {
6968
+ fontSize: themedFontSize(26, context, false),
6969
+ fontFamily: monoFont,
6970
+ color: theme.colors.textMuted,
6971
+ lineHeight: 1.3,
6972
+ maxLines: 3
6973
+ }
6974
+ },
6975
+ position: { x: columnX, y: "78%", width: `${bubbleWidthPct}%`, anchor: "top-left" },
6976
+ animation: { type: "fadeIn", duration: 0.4, delay: 0.3 }
6977
+ });
6978
+ }
6979
+ if (input.meta) {
6980
+ layers.push({
6981
+ type: "text",
6982
+ id: "meta",
6983
+ content: {
6984
+ text: input.meta,
6985
+ style: { fontSize: metaFontSize, fontFamily: bodyFont, color: theme.colors.textMuted }
6986
+ },
6987
+ position: { x: "96%", y: "94%", anchor: "bottom-right" }
6988
+ });
6989
+ }
6990
+ return layers;
6991
+ }
6992
+ function handoffLayers(input, context, accent, textColor, bubbleFill) {
6993
+ const { theme } = context;
6994
+ const bodyFont = getThemeFont(context, "body");
6995
+ const nameFontSize = themedFontSize(28, context, false);
6996
+ const textFontSize = themedFontSize(32, context, true);
6997
+ const layers = [
6998
+ ...avatarLayers("speaker", input.speaker, input.speakerImage, "26%", "28%", context),
6999
+ ...avatarLayers(
7000
+ "counterpart",
7001
+ input.counterpartName ?? "",
7002
+ input.counterpartImage,
7003
+ "74%",
7004
+ "28%",
7005
+ context
7006
+ ),
7007
+ nameLayer("speaker-name", input.speaker, "26%", nameFontSize, bodyFont, theme.colors.textMuted),
7008
+ nameLayer(
7009
+ "counterpart-name",
7010
+ input.counterpartName ?? "",
7011
+ "74%",
7012
+ nameFontSize,
7013
+ bodyFont,
7014
+ theme.colors.textMuted
7015
+ ),
7016
+ {
7017
+ type: "path",
7018
+ id: "handoff-arrow",
7019
+ content: { d: "M 0 0 L 100 0", stroke: accent, strokeWidth: 4, endMarker: "arrow" },
7020
+ position: { x: "50%", y: "28%", width: "28%", height: "1%", anchor: "center" },
7021
+ animation: { type: "fadeIn", duration: 0.4, delay: 0.2 }
7022
+ }
7023
+ ];
7024
+ if (input.text.length > 0) {
7025
+ layers.push(
7026
+ {
7027
+ type: "shape",
7028
+ id: "bubble",
7029
+ content: { shape: "rect", fill: bubbleFill, borderRadius: 18 },
7030
+ position: { x: "50%", y: "66%", width: "66%", height: "32%", anchor: "center" },
7031
+ animation: { type: "fadeIn", duration: 0.4, delay: 0.3 }
7032
+ },
7033
+ {
7034
+ type: "text",
7035
+ id: "message",
7036
+ content: {
7037
+ text: input.text,
7038
+ style: {
7039
+ fontSize: textFontSize,
7040
+ fontFamily: bodyFont,
7041
+ color: textColor,
7042
+ textAlign: "center",
7043
+ lineHeight: 1.35,
7044
+ maxLines: 5
7045
+ }
7046
+ },
7047
+ position: { x: "50%", y: "66%", width: "60%", height: "26%", anchor: "center" },
7048
+ animation: { type: "typewriter", duration: 2, delay: 0.4 }
7049
+ }
7050
+ );
7051
+ }
7052
+ if (input.meta) {
7053
+ layers.push({
7054
+ type: "text",
7055
+ id: "meta",
7056
+ content: {
7057
+ text: input.meta,
7058
+ style: {
7059
+ fontSize: themedFontSize(22, context, false),
7060
+ fontFamily: bodyFont,
7061
+ color: theme.colors.textMuted
7062
+ }
7063
+ },
7064
+ position: { x: "96%", y: "94%", anchor: "bottom-right" }
7065
+ });
7066
+ }
7067
+ return layers;
7068
+ }
7069
+ function nameLayer(id, text, x, fontSize, fontFamily, color) {
7070
+ return {
7071
+ type: "text",
7072
+ id,
7073
+ content: {
7074
+ text,
7075
+ style: { fontSize, fontFamily, fontWeight: "bold", color, textAlign: "center" }
7076
+ },
7077
+ position: { x, y: "42%", anchor: "center" }
7078
+ };
7079
+ }
7080
+ function avatarLayers(idPrefix, name, imageSrc, x, y, context) {
7081
+ const { theme } = context;
7082
+ if (imageSrc) {
7083
+ return [
7084
+ {
7085
+ type: "image",
7086
+ id: `${idPrefix}-avatar`,
7087
+ content: { src: imageSrc, alt: name, fit: "contain" },
7088
+ position: { x, y, width: "9%", height: "16%", anchor: "center" }
7089
+ }
7090
+ ];
7091
+ }
7092
+ const initials = name.split(/\s+/).map((part) => part[0] ?? "").join("").slice(0, 2).toUpperCase();
7093
+ return [
7094
+ {
7095
+ type: "shape",
7096
+ id: `${idPrefix}-avatar-bg`,
7097
+ content: {
7098
+ shape: "circle",
7099
+ fill: withAlpha(theme.colors.text, 0.1),
7100
+ stroke: theme.colors.textMuted,
7101
+ strokeWidth: 2
7102
+ },
7103
+ position: { x, y, width: "9%", height: "16%", anchor: "center" }
7104
+ },
7105
+ {
7106
+ type: "text",
7107
+ id: `${idPrefix}-avatar-initials`,
7108
+ content: {
7109
+ text: initials || "?",
7110
+ style: {
7111
+ fontSize: themedFontSize(44, context, true),
7112
+ fontFamily: getThemeFont(context, "body"),
7113
+ fontWeight: "bold",
7114
+ color: theme.colors.text,
7115
+ textAlign: "center",
7116
+ verticalAlign: "middle"
7117
+ }
7118
+ },
7119
+ position: { x, y, width: "9%", height: "16%", anchor: "center" }
7120
+ }
7121
+ ];
7122
+ }
7123
+
6853
7124
  // src/doc/templates/registry.ts
6854
7125
  var templateRegistry = {
6855
7126
  title: titleBlock,
6856
7127
  sectionHeader,
6857
7128
  bigText,
7129
+ transcript: transcriptBlock,
6858
7130
  content: contentBlock,
6859
7131
  statHighlight,
6860
7132
  quote: quoteBlock,
@@ -7031,9 +7303,47 @@ function CHART_DESCRIPTORS(extra = []) {
7031
7303
  coerce: "stringList"
7032
7304
  },
7033
7305
  { key: "rows", description: "Table rows (supply via a data fence)" },
7306
+ ...DATA_SRC_DESCRIPTORS(),
7307
+ { key: "sheet", description: "Worksheet inside the src workbook (XLSX src only)" },
7308
+ {
7309
+ key: "anchor",
7310
+ description: "Top-left cell of the region inside the src workbook, e.g. 'B7'"
7311
+ },
7312
+ {
7313
+ key: "headerRow",
7314
+ description: "Whether row 1 of the source region is a header row",
7315
+ coerce: "boolean"
7316
+ },
7034
7317
  ...extra
7035
7318
  ];
7036
7319
  }
7320
+ function DATA_SRC_DESCRIPTORS() {
7321
+ return [
7322
+ {
7323
+ key: "src",
7324
+ description: "Container path to a sidecar data file (.csv/.tsv/.xlsx/.parquet) supplying the table"
7325
+ },
7326
+ {
7327
+ key: "previewRows",
7328
+ description: "Max data rows resolved from src for the bounded preview",
7329
+ coerce: "number"
7330
+ },
7331
+ // Written by `resolveDataReferences` onto templateData (totalRows/totalCols/
7332
+ // previewRows/truncated) — declared so resolved docs don't lint as unknown.
7333
+ { key: "srcStats", description: "Preview stats recorded by data-reference resolution" },
7334
+ // Non-destructive view state over the src data (see @bendyline/squisq/table
7335
+ // for the grammar) — applied by the readers before windowing, so previews
7336
+ // and exports show the author's curated view.
7337
+ {
7338
+ key: "sort",
7339
+ description: "Sort order over src data: 'Col:desc,Other' (quote names containing , or :)"
7340
+ },
7341
+ {
7342
+ key: "filter",
7343
+ description: "Row filter over src data: 'Col=value;Other>=10' (ops = != > < >= <= ~ !~; AND only)"
7344
+ }
7345
+ ];
7346
+ }
7037
7347
  var STACKED_DESCRIPTOR = {
7038
7348
  key: "stacked",
7039
7349
  description: "Stack series instead of grouping them side by side",
@@ -7076,6 +7386,23 @@ var TEMPLATE_INPUT_DESCRIPTORS = {
7076
7386
  { key: "ambientMotion", description: "Slow zoom/pan effect", values: AMBIENT_MOTION_VALUES }
7077
7387
  ],
7078
7388
  content: [{ key: "title", description: "Heading shown above the complete body" }],
7389
+ transcript: [
7390
+ { key: "speaker", description: "Speaker display name" },
7391
+ { key: "speakerImage", description: "Avatar image path (missing \u2192 initials medallion)" },
7392
+ { key: "side", description: "Speaker column side", values: ["left", "right"] },
7393
+ { key: "variant", description: "Beat kind", values: ["speech", "thought", "tool"] },
7394
+ { key: "text", description: "The message body" },
7395
+ { key: "toolName", description: "Tool variant: invoked tool name (mono chip)" },
7396
+ { key: "resultText", description: "Tool variant: bounded result line" },
7397
+ { key: "counterpartName", description: "Handoff form: receiving speaker name" },
7398
+ { key: "counterpartImage", description: "Handoff form: receiving speaker avatar path" },
7399
+ { key: "meta", description: "Muted corner line (timestamp, step)" },
7400
+ {
7401
+ key: "colorScheme",
7402
+ description: "Accent scheme (tool chip, handoff arrow)",
7403
+ valueHint: COLOR_SCHEME_HINT
7404
+ }
7405
+ ],
7079
7406
  statHighlight: [
7080
7407
  { key: "stat", description: 'The statistic (e.g. "89%", "2x")' },
7081
7408
  { key: "description", description: "What the stat means" },
@@ -7182,7 +7509,11 @@ var TEMPLATE_INPUT_DESCRIPTORS = {
7182
7509
  description: "Whether row 1 of the source region is a header row",
7183
7510
  coerce: "boolean"
7184
7511
  },
7185
- { key: "titleAnchor", description: "Cell this heading text was absorbed from" }
7512
+ { key: "titleAnchor", description: "Cell this heading text was absorbed from" },
7513
+ // Sidecar data source (see DATA_SRC_DESCRIPTORS): `src` points at a
7514
+ // container data file; `sheet`/`anchor`/`headerRow` above double as the
7515
+ // in-workbook address when src names an .xlsx.
7516
+ ...DATA_SRC_DESCRIPTORS()
7186
7517
  ],
7187
7518
  barChart: CHART_DESCRIPTORS([STACKED_DESCRIPTOR]),
7188
7519
  columnChart: CHART_DESCRIPTORS([STACKED_DESCRIPTOR]),
@@ -7518,6 +7849,15 @@ var BLOCK_MEDIA_LAYOUT_POLICIES = {
7518
7849
  unconsumedMedia: "reserve-when-no-native-media",
7519
7850
  variants: TITLE_VARIANTS
7520
7851
  },
7852
+ transcript: {
7853
+ summary: "Speaker avatars are native media (initials medallions when absent); other media stays supplemental.",
7854
+ noMedia: "template-without-optional-media",
7855
+ ownership: "optional-native",
7856
+ nativeLayout: "accent-strip-or-inset",
7857
+ additionalMediaLayout: "overlay-inset",
7858
+ unconsumedMedia: "reserve-when-no-native-media",
7859
+ variants: TEXT_VARIANTS
7860
+ },
7521
7861
  content: {
7522
7862
  summary: "Preserves the complete heading and body; supplemental media receives a companion field.",
7523
7863
  noMedia: "template-default",
@@ -8663,6 +9003,10 @@ var TEMPLATE_METADATA = {
8663
9003
  label: "Big Text",
8664
9004
  description: "Gigantic uppercase display text \u2014 thumbnail-style \u2014 on a theme surface or over an image with a contrast bloom."
8665
9005
  },
9006
+ transcript: {
9007
+ label: "Transcript",
9008
+ description: "A conversational beat: speaker avatar and message bubble, with thought, tool, and two-speaker handoff variants."
9009
+ },
8666
9010
  content: {
8667
9011
  label: "Content",
8668
9012
  description: "Shows a heading and the complete body in a loss-averse content-first layout."
@@ -8815,6 +9159,12 @@ var TEMPLATE_AUTHORING_METADATA = {
8815
9159
  safeForContentFirst: true,
8816
9160
  placement: "heading"
8817
9161
  },
9162
+ transcript: {
9163
+ role: "content",
9164
+ bodyPolicy: "structured",
9165
+ safeForContentFirst: false,
9166
+ placement: "heading"
9167
+ },
8818
9168
  statHighlight: {
8819
9169
  role: "highlight",
8820
9170
  bodyPolicy: "derived",
@@ -40,14 +40,96 @@ function categorizeLintKind(kind) {
40
40
 
41
41
  // src/proof/masking.ts
42
42
  var ANNOTATION_RE = /\{\[[^\n]*?\]\}/g;
43
- function blankProtectedSpans(text) {
43
+ function blankProtectedSpans(text, options = {}) {
44
+ const ranges = [];
45
+ ANNOTATION_RE.lastIndex = 0;
46
+ let match;
47
+ while ((match = ANNOTATION_RE.exec(text)) !== null) {
48
+ ranges.push({ start: match.index, end: match.index + match[0].length });
49
+ }
50
+ if (options.markdownCode) ranges.push(...markdownCodeRanges(text));
51
+ if (ranges.length === 0) return { text, blanked: [] };
52
+ ranges.sort((a, b) => a.start - b.start || a.end - b.end);
44
53
  const blanked = [];
45
- const out = text.replace(ANNOTATION_RE, (match, offset) => {
46
- blanked.push({ start: offset, end: offset + match.length });
47
- return " ".repeat(match.length);
48
- });
54
+ for (const range of ranges) {
55
+ const last = blanked[blanked.length - 1];
56
+ if (last && range.start <= last.end) last.end = Math.max(last.end, range.end);
57
+ else blanked.push({ ...range });
58
+ }
59
+ let out = "";
60
+ let cursor = 0;
61
+ for (const range of blanked) {
62
+ out += text.slice(cursor, range.start);
63
+ out += text.slice(range.start, range.end).replace(/[^\n]/g, " ");
64
+ cursor = range.end;
65
+ }
66
+ out += text.slice(cursor);
49
67
  return { text: out, blanked };
50
68
  }
69
+ function markdownCodeRanges(text) {
70
+ const fences = fencedCodeRanges(text);
71
+ const ranges = [...fences];
72
+ let cursor = 0;
73
+ for (const fence of fences) {
74
+ collectInlineCodeRanges(text, cursor, fence.start, ranges);
75
+ cursor = fence.end;
76
+ }
77
+ collectInlineCodeRanges(text, cursor, text.length, ranges);
78
+ return ranges;
79
+ }
80
+ var FENCE_RE = /^( {0,3})(`{3,}|~{3,})(.*)$/;
81
+ function fencedCodeRanges(text) {
82
+ const ranges = [];
83
+ let lineStart = 0;
84
+ let open = null;
85
+ for (; ; ) {
86
+ const newline = text.indexOf("\n", lineStart);
87
+ const lineEnd = newline === -1 ? text.length : newline;
88
+ const match = FENCE_RE.exec(text.slice(lineStart, lineEnd));
89
+ if (!open) {
90
+ if (match) open = { start: lineStart, marker: match[2] };
91
+ } else if (match && // A closing fence is the same character, at least as long, and bare.
92
+ match[2][0] === open.marker[0] && match[2].length >= open.marker.length && match[3].trim() === "") {
93
+ ranges.push({ start: open.start, end: lineEnd });
94
+ open = null;
95
+ }
96
+ if (newline === -1) break;
97
+ lineStart = newline + 1;
98
+ }
99
+ if (open) ranges.push({ start: open.start, end: text.length });
100
+ return ranges;
101
+ }
102
+ function collectInlineCodeRanges(text, from, to, out) {
103
+ let i = from;
104
+ let openStart = -1;
105
+ let openLength = 0;
106
+ while (i < to) {
107
+ if (text[i] === "`") {
108
+ let run = 1;
109
+ while (i + run < to && text[i + run] === "`") run++;
110
+ if (openStart < 0) {
111
+ openStart = i;
112
+ openLength = run;
113
+ } else if (run === openLength) {
114
+ out.push({ start: openStart, end: i + run });
115
+ openStart = -1;
116
+ openLength = 0;
117
+ }
118
+ i += run;
119
+ continue;
120
+ }
121
+ if (openStart >= 0 && text[i] === "\n" && startsBlankLine(text, i + 1, to)) {
122
+ openStart = -1;
123
+ openLength = 0;
124
+ }
125
+ i++;
126
+ }
127
+ }
128
+ function startsBlankLine(text, index, to) {
129
+ let i = index;
130
+ while (i < to && (text[i] === " " || text[i] === " ")) i++;
131
+ return i >= to || text[i] === "\n";
132
+ }
51
133
  function dropMaskedFindings(findings, blanked) {
52
134
  if (blanked.length === 0) return [...findings];
53
135
  return findings.filter(
@@ -26,6 +26,15 @@ function buildVersionPath(basename, date, collision = 0) {
26
26
  function parseVersionPath(path) {
27
27
  return parseSnapshotPath(DOCUMENT_VERSION_PATHS, path);
28
28
  }
29
+ var DATA_BACKUP_PREFIX = ".versions/data/";
30
+ function buildDataBackupPath(sidecarPath, date, collision = 0) {
31
+ const slash = sidecarPath.lastIndexOf(".");
32
+ const extension = slash > 0 ? sidecarPath.slice(slash + 1).toLowerCase() : "bin";
33
+ const withoutExt = slash > 0 ? sidecarPath.slice(0, slash) : sidecarPath;
34
+ const flattened = withoutExt.replace(/\//g, "__");
35
+ const strategy = { prefix: DATA_BACKUP_PREFIX, extension };
36
+ return buildSnapshotPath(strategy, flattened, date, collision);
37
+ }
29
38
 
30
39
  // src/versions/operations.ts
31
40
  async function resolveBasename(container, override) {
@@ -119,6 +128,8 @@ export {
119
128
  getDocBasename,
120
129
  buildVersionPath,
121
130
  parseVersionPath,
131
+ DATA_BACKUP_PREFIX,
132
+ buildDataBackupPath,
122
133
  listVersions,
123
134
  readVersion,
124
135
  saveVersion,