@bendyline/squisq-formats 2.8.8 → 2.8.10

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 (40) hide show
  1. package/README.md +15 -13
  2. package/dist/chunk-4LIFEQKX.js +358 -0
  3. package/dist/{chunk-UXEANVBI.js → chunk-5HUHSLGA.js} +1 -84
  4. package/dist/{chunk-BXWNU4T5.js → chunk-DTJQK7U7.js} +43 -0
  5. package/dist/{chunk-GDUZJ75A.js → chunk-MJTPWLVV.js} +59 -21
  6. package/dist/{chunk-6ALSRHD7.js → chunk-NCDY3EOL.js} +66 -9
  7. package/dist/{chunk-TMOXUUTG.js → chunk-NQNIFIDP.js} +6 -4
  8. package/dist/{chunk-LK4KCVN6.js → chunk-QPJHAMOW.js} +70 -28
  9. package/dist/{chunk-QU4EVC62.js → chunk-S5VXWSRR.js} +1 -1
  10. package/dist/{chunk-KROH7FNT.js → chunk-VKLJUHC2.js} +6 -4
  11. package/dist/chunk-YRFBWYAD.js +128 -0
  12. package/dist/{chunk-SVYTUYZM.js → chunk-ZJERBWTB.js} +6 -4
  13. package/dist/data/index.d.ts +27 -5
  14. package/dist/data/index.js +6 -2
  15. package/dist/diagrams/index.d.ts +19 -8
  16. package/dist/diagrams/index.js +7 -242
  17. package/dist/docx/index.d.ts +1 -1
  18. package/dist/docx/index.js +3 -3
  19. package/dist/epub/index.d.ts +1 -1
  20. package/dist/epub/index.js +3 -3
  21. package/dist/fontAwesome-C6FRDYTY.js +14 -0
  22. package/dist/html/icons.d.ts +29 -0
  23. package/dist/html/icons.js +62 -0
  24. package/dist/html/index.d.ts +3 -130
  25. package/dist/html/index.js +2 -2
  26. package/dist/html/prepare.d.ts +97 -0
  27. package/dist/html/prepare.js +85 -0
  28. package/dist/index.d.ts +2 -0
  29. package/dist/index.js +16 -16
  30. package/dist/{materialize-G4WC5UG3.js → materialize-ICXNO4S4.js} +4 -1
  31. package/dist/outside-in/index.d.ts +12 -0
  32. package/dist/outside-in/index.js +3 -3
  33. package/dist/pdf/index.d.ts +1 -1
  34. package/dist/pdf/index.js +3 -3
  35. package/dist/plainHtml-B6IXcSet.d.ts +148 -0
  36. package/dist/pptx/index.js +2 -2
  37. package/dist/readers-3P5A6A2A.js +17 -0
  38. package/dist/registry/index.js +1 -1
  39. package/package.json +12 -2
  40. /package/dist/{chunk-LBXBRFBZ.js → chunk-DDMPZZJF.js} +0 -0
package/README.md CHANGED
@@ -337,19 +337,21 @@ Also exported: `createRegistry` / `defaultRegistry` / `defaultFormats`, `BUILTIN
337
337
 
338
338
  ## Subpath Exports
339
339
 
340
- | Subpath | Contents |
341
- | ------------------------------------- | ------------------------------------------------------------------------------- |
342
- | `@bendyline/squisq-formats/docx` | DOCX import/export (+ `docxToContainer`) |
343
- | `@bendyline/squisq-formats/pdf` | PDF import/export (+ `pdfToContainer`, `configurePdfWorker`) |
344
- | `@bendyline/squisq-formats/html` | Player HTML export, static plain-HTML export + bundles, HTML import |
345
- | `@bendyline/squisq-formats/epub` | EPUB 3 e-book export (with optional Media Overlays) |
346
- | `@bendyline/squisq-formats/pptx` | PPTX export + import (text/lists/tables + slide images) |
347
- | `@bendyline/squisq-formats/xlsx` | XLSX import + tables-only export |
348
- | `@bendyline/squisq-formats/csv` | CSV import/export (RFC 4180) |
349
- | `@bendyline/squisq-formats/ooxml` | Shared OOXML infrastructure (package reader/writer, XML utilities, namespaces) |
350
- | `@bendyline/squisq-formats/diagrams` | `rasterizeDiagrams` / `findDiagrams`: diagrams as pictures for document exports |
351
- | `@bendyline/squisq-formats/container` | `ContentContainer` ↔ ZIP serialization |
352
- | `@bendyline/squisq-formats/registry` | Format registry + programmatic `convert()` (also re-exported from the root) |
340
+ | Subpath | Contents |
341
+ | ---------------------------------------- | ------------------------------------------------------------------------------- |
342
+ | `@bendyline/squisq-formats/docx` | DOCX import/export (+ `docxToContainer`) |
343
+ | `@bendyline/squisq-formats/pdf` | PDF import/export (+ `pdfToContainer`, `configurePdfWorker`) |
344
+ | `@bendyline/squisq-formats/html` | Player HTML export, static plain-HTML export + bundles, HTML import |
345
+ | `@bendyline/squisq-formats/html-prepare` | `prepareMarkdownDocForPlainHtml`: data tables and pictures for plain-HTML pages |
346
+ | `@bendyline/squisq-formats/html-icons` | `plainHtmlIcons`: inline icons as SVG outlines for plain-HTML pages |
347
+ | `@bendyline/squisq-formats/epub` | EPUB 3 e-book export (with optional Media Overlays) |
348
+ | `@bendyline/squisq-formats/pptx` | PPTX export + import (text/lists/tables + slide images) |
349
+ | `@bendyline/squisq-formats/xlsx` | XLSX import + tables-only export |
350
+ | `@bendyline/squisq-formats/csv` | CSV import/export (RFC 4180) |
351
+ | `@bendyline/squisq-formats/ooxml` | Shared OOXML infrastructure (package reader/writer, XML utilities, namespaces) |
352
+ | `@bendyline/squisq-formats/diagrams` | `rasterizeDiagrams` / `findDiagrams`: diagrams as pictures for document exports |
353
+ | `@bendyline/squisq-formats/container` | `ContentContainer` ↔ ZIP serialization |
354
+ | `@bendyline/squisq-formats/registry` | Format registry + programmatic `convert()` (also re-exported from the root) |
353
355
 
354
356
  The package root re-exports the common converters; `./container`, the plain-HTML/bundle functions, `docxToContainer`, `pdfToContainer`, `PdfPageSize`, and the image utilities are subpath-only.
355
357
 
@@ -0,0 +1,358 @@
1
+ // src/diagrams/index.ts
2
+ import {
3
+ extractPlainText,
4
+ isSvgIslandLang,
5
+ parseSvgIsland,
6
+ stringifyMarkdown
7
+ } from "@bendyline/squisq/markdown";
8
+ import {
9
+ TABLE_FED_TEMPLATES,
10
+ buildChartData,
11
+ detectAsciiDiagram,
12
+ detectAsciiTimeline,
13
+ detectTree,
14
+ isContainerTemplate,
15
+ isEligibleAsciiFenceLang,
16
+ isEligibleAsciiTimelineFenceLang,
17
+ isEligibleTreeFenceLang,
18
+ isExplicitDiagramLang,
19
+ isExplicitTimelineLang,
20
+ isExplicitTreeLang,
21
+ resolveTemplateName
22
+ } from "@bendyline/squisq/doc";
23
+ var DEFAULT_KINDS = [
24
+ "mermaid",
25
+ "diagram",
26
+ "timeline",
27
+ "tree",
28
+ "container",
29
+ "chart"
30
+ ];
31
+ var EXPORT_DIAGRAM_KINDS = [...DEFAULT_KINDS, "svg"];
32
+ var KIND_NAMES = {
33
+ mermaid: "Diagram",
34
+ diagram: "Diagram",
35
+ timeline: "Timeline",
36
+ tree: "Tree",
37
+ container: "Diagram",
38
+ svg: "Illustration",
39
+ chart: "Chart"
40
+ };
41
+ function fenceDiagramKind(node) {
42
+ const lang = node.lang ?? null;
43
+ if ((lang ?? "").trim().toLowerCase() === "mermaid") return "mermaid";
44
+ if (isSvgIslandLang(lang)) return parseSvgIsland(node.value).ok ? "svg" : null;
45
+ if (isEligibleAsciiFenceLang(lang)) {
46
+ const detection = detectAsciiDiagram(node.value, { explicit: isExplicitDiagramLang(lang) });
47
+ if (detection.isDiagram) return "diagram";
48
+ }
49
+ if (isEligibleTreeFenceLang(lang)) {
50
+ if (detectTree(node.value, { explicit: isExplicitTreeLang(lang) }).isTree) return "tree";
51
+ }
52
+ if (isEligibleAsciiTimelineFenceLang(lang)) {
53
+ const detection = detectAsciiTimeline(node.value, { explicit: isExplicitTimelineLang(lang) });
54
+ if (detection.isTimeline) return "timeline";
55
+ }
56
+ return null;
57
+ }
58
+ function containerTemplateOf(node) {
59
+ if (node.type !== "heading") return null;
60
+ const requested = node.templateAnnotation?.template;
61
+ if (!requested || !isContainerTemplate(requested)) return null;
62
+ return resolveTemplateName(requested);
63
+ }
64
+ function mermaidAlt(source) {
65
+ const title = /^\s*accTitle\s*:\s*(.+?)\s*$/mu.exec(source)?.[1] ?? "";
66
+ const description = /^\s*accDescr\s*:\s*(.+?)\s*$/mu.exec(source)?.[1] ?? "";
67
+ return [title, description].filter(Boolean).join(". ");
68
+ }
69
+ function fenceAlt(kind, source) {
70
+ if (kind === "mermaid") return mermaidAlt(source);
71
+ if (kind === "svg") {
72
+ const result = parseSvgIsland(source);
73
+ return result.ok && result.island.title || "";
74
+ }
75
+ return "";
76
+ }
77
+ function fenceMarkdown(node) {
78
+ return stringifyMarkdown({ type: "document", children: [node] }).trim();
79
+ }
80
+ function tableText(table) {
81
+ const [header, ...body] = table.children.map(
82
+ (row) => row.children.map((cell) => extractPlainText(cell).trim())
83
+ );
84
+ return { headers: header ?? [], rows: body };
85
+ }
86
+ function listParam(value) {
87
+ const entries = value?.split(",").map((entry) => entry.trim()).filter(Boolean);
88
+ return entries && entries.length > 0 ? entries : void 0;
89
+ }
90
+ var NON_CHART_PARAMS = /* @__PURE__ */ new Set([
91
+ "showTable",
92
+ "src",
93
+ "sheet",
94
+ "anchor",
95
+ "headerRow",
96
+ "titleAnchor",
97
+ "previewRows",
98
+ "sort",
99
+ "filter"
100
+ ]);
101
+ function isTruthyParam(value) {
102
+ return value !== void 0 && value !== "false" && value !== "0";
103
+ }
104
+ function findChart(children, index) {
105
+ const heading = children[index];
106
+ const requested = heading.templateAnnotation?.template;
107
+ const template = requested ? resolveTemplateName(requested) : "";
108
+ if (!TABLE_FED_TEMPLATES.has(template) || template === "dataTable") return null;
109
+ let tableIndex = -1;
110
+ for (let at = index + 1; at < children.length; at++) {
111
+ const node = children[at];
112
+ if (node.type === "heading") break;
113
+ if (node.type === "table") {
114
+ tableIndex = at;
115
+ break;
116
+ }
117
+ }
118
+ if (tableIndex < 0) return null;
119
+ const table = children[tableIndex];
120
+ const params = heading.templateAnnotation?.params ?? {};
121
+ const data = buildChartData(tableText(table), {
122
+ labelColumn: params.labelColumn,
123
+ valueColumns: listParam(params.valueColumns)
124
+ });
125
+ if (!data) return null;
126
+ const { showTable } = params;
127
+ const chartParams = Object.fromEntries(
128
+ Object.entries(params).filter(([key]) => !NON_CHART_PARAMS.has(key))
129
+ );
130
+ const chartHeading = {
131
+ ...heading,
132
+ templateAnnotation: { template, params: chartParams }
133
+ };
134
+ const title = extractPlainText(heading).trim();
135
+ const plotted = data.series.map((series) => series.name).join(", ");
136
+ const what = `${template.replace(/Chart$/, "")} chart of ${plotted}${data.labelHeader ? ` by ${data.labelHeader}` : ""}`;
137
+ return {
138
+ chart: { headingIndex: index, tableIndex, keepTable: isTruthyParam(showTable) },
139
+ diagram: {
140
+ kind: "chart",
141
+ markdown: stringifyMarkdown({ type: "document", children: [chartHeading, table] }).trim(),
142
+ source: "",
143
+ template,
144
+ alt: title ? `${title}: ${what}` : what.charAt(0).toUpperCase() + what.slice(1)
145
+ }
146
+ };
147
+ }
148
+ function findInDocument(doc) {
149
+ const found = [];
150
+ const children = doc.children;
151
+ const walk = (nodes) => {
152
+ for (const node of nodes) {
153
+ if (node.type === "code") {
154
+ const fence = node;
155
+ const kind = fenceDiagramKind(fence);
156
+ if (kind) {
157
+ found.push({
158
+ fence,
159
+ diagram: {
160
+ kind,
161
+ markdown: fenceMarkdown(fence),
162
+ source: fence.value,
163
+ template: "",
164
+ alt: fenceAlt(kind, fence.value) || KIND_NAMES[kind]
165
+ }
166
+ });
167
+ }
168
+ continue;
169
+ }
170
+ const nested = node.children;
171
+ if (Array.isArray(nested) && node.type !== "heading" && node.type !== "paragraph") {
172
+ walk(nested);
173
+ }
174
+ }
175
+ };
176
+ for (let index = 0; index < children.length; index++) {
177
+ const node = children[index];
178
+ const template = containerTemplateOf(node);
179
+ if (!template) {
180
+ const chart = node.type === "heading" ? findChart(children, index) : null;
181
+ if (chart) found.push(chart);
182
+ walk([node]);
183
+ continue;
184
+ }
185
+ const depth = node.depth;
186
+ let end = index + 1;
187
+ while (end < children.length) {
188
+ const next = children[end];
189
+ if (next.type === "heading" && next.depth <= depth) break;
190
+ end++;
191
+ }
192
+ const heading = extractPlainText(node).trim();
193
+ found.push({
194
+ containerIndex: index,
195
+ containerEnd: end,
196
+ diagram: {
197
+ kind: "container",
198
+ markdown: stringifyMarkdown({
199
+ type: "document",
200
+ children: children.slice(index, end)
201
+ }).trim(),
202
+ source: "",
203
+ template,
204
+ alt: heading || KIND_NAMES.container
205
+ }
206
+ });
207
+ index = end - 1;
208
+ }
209
+ return found;
210
+ }
211
+ function imageUrls(nodes, into) {
212
+ for (const node of nodes) {
213
+ if (node.type === "image") into.add(node.url);
214
+ const nested = node.children;
215
+ if (Array.isArray(nested)) imageUrls(nested, into);
216
+ }
217
+ return into;
218
+ }
219
+ function findDiagrams(doc) {
220
+ return findInDocument(doc).map((entry) => entry.diagram);
221
+ }
222
+ function withoutTemplate(heading) {
223
+ const { templateAnnotation: _template, ...plain } = heading;
224
+ return plain;
225
+ }
226
+ function imageParagraph(url, alt) {
227
+ const image = { type: "image", url, alt, title: null };
228
+ return { type: "paragraph", children: [image] };
229
+ }
230
+ function replaceFences(nodes, replacements) {
231
+ let changed = false;
232
+ const next = nodes.map((node) => {
233
+ const replacement = replacements.get(node);
234
+ if (replacement) {
235
+ changed = true;
236
+ return replacement;
237
+ }
238
+ const nested = node.children;
239
+ if (Array.isArray(nested)) {
240
+ const replaced = replaceFences(nested, replacements);
241
+ if (replaced !== nested) {
242
+ changed = true;
243
+ return { ...node, children: replaced };
244
+ }
245
+ }
246
+ return node;
247
+ });
248
+ return changed ? next : nodes;
249
+ }
250
+ function cachingDiagramRasterizer(render, limit = 64) {
251
+ const drawn = /* @__PURE__ */ new Map();
252
+ return (diagram) => {
253
+ const key = `${diagram.kind}\0${diagram.markdown}\0${diagram.source}`;
254
+ let picture = drawn.get(key);
255
+ if (picture) {
256
+ drawn.delete(key);
257
+ } else {
258
+ picture = render(diagram);
259
+ picture.catch(() => drawn.delete(key));
260
+ }
261
+ drawn.set(key, picture);
262
+ if (drawn.size > limit) drawn.delete(drawn.keys().next().value);
263
+ return picture;
264
+ };
265
+ }
266
+ async function rasterizeDiagrams(doc, render, options = {}) {
267
+ const kinds = new Set(options.kinds ?? DEFAULT_KINDS);
268
+ const prefix = options.urlPrefix ?? "diagram";
269
+ const taken = imageUrls(doc.children, /* @__PURE__ */ new Set());
270
+ let counter = 0;
271
+ const nextUrl = () => {
272
+ let url;
273
+ do
274
+ url = `${prefix}-${String(++counter)}.png`;
275
+ while (taken.has(url));
276
+ taken.add(url);
277
+ return url;
278
+ };
279
+ const images = /* @__PURE__ */ new Map();
280
+ const mermaid = /* @__PURE__ */ new Map();
281
+ const svg = /* @__PURE__ */ new Map();
282
+ const fenceReplacements = /* @__PURE__ */ new Map();
283
+ const blockReplacements = [];
284
+ for (const entry of findInDocument(doc)) {
285
+ options.signal?.throwIfAborted();
286
+ if (!kinds.has(entry.diagram.kind)) continue;
287
+ let picture = null;
288
+ try {
289
+ picture = await render(entry.diagram);
290
+ } catch (error) {
291
+ options.onWarning?.(
292
+ `A ${KIND_NAMES[entry.diagram.kind].toLowerCase()} could not be drawn and was kept as text: ${error instanceof Error ? error.message : String(error)}`
293
+ );
294
+ }
295
+ if (!picture || picture.width <= 0 || picture.height <= 0) continue;
296
+ const data = picture.data instanceof Uint8Array ? picture.data : new Uint8Array(picture.data);
297
+ const url = nextUrl();
298
+ images.set(url, {
299
+ data,
300
+ contentType: "image/png",
301
+ width: picture.width,
302
+ height: picture.height
303
+ });
304
+ if (entry.diagram.kind === "mermaid") mermaid.set(entry.diagram.source.trim(), picture);
305
+ if (entry.diagram.kind === "svg") svg.set(entry.diagram.source.trim(), picture);
306
+ const paragraph = imageParagraph(url, entry.diagram.alt);
307
+ if (entry.fence) {
308
+ fenceReplacements.set(entry.fence, paragraph);
309
+ } else if (entry.containerIndex !== void 0 && entry.containerEnd !== void 0) {
310
+ blockReplacements.push({
311
+ start: entry.containerIndex,
312
+ end: entry.containerEnd,
313
+ nodes: [withoutTemplate(doc.children[entry.containerIndex]), paragraph]
314
+ });
315
+ } else if (entry.chart) {
316
+ const { headingIndex, tableIndex, keepTable } = entry.chart;
317
+ const table = doc.children[tableIndex];
318
+ blockReplacements.push(
319
+ {
320
+ start: headingIndex,
321
+ end: headingIndex + 1,
322
+ nodes: [withoutTemplate(doc.children[headingIndex])]
323
+ },
324
+ {
325
+ start: tableIndex,
326
+ end: tableIndex + 1,
327
+ nodes: keepTable ? [paragraph, table] : [paragraph]
328
+ }
329
+ );
330
+ }
331
+ }
332
+ let children = doc.children;
333
+ if (blockReplacements.length > 0) {
334
+ const rebuilt = [];
335
+ let cursor = 0;
336
+ for (const replacement of blockReplacements) {
337
+ rebuilt.push(...children.slice(cursor, replacement.start), ...replacement.nodes);
338
+ cursor = replacement.end;
339
+ }
340
+ rebuilt.push(...children.slice(cursor));
341
+ children = rebuilt;
342
+ }
343
+ if (fenceReplacements.size > 0) children = replaceFences(children, fenceReplacements);
344
+ return {
345
+ markdownDoc: children === doc.children ? doc : { ...doc, children },
346
+ images,
347
+ mermaid,
348
+ svg
349
+ };
350
+ }
351
+
352
+ export {
353
+ EXPORT_DIAGRAM_KINDS,
354
+ fenceDiagramKind,
355
+ findDiagrams,
356
+ cachingDiagramRasterizer,
357
+ rasterizeDiagrams
358
+ };
@@ -8,9 +8,6 @@ import {
8
8
  parseCsv
9
9
  } from "./chunk-Q77KNJIN.js";
10
10
 
11
- // src/data/materialize.ts
12
- import { isDataFilePath } from "@bendyline/squisq/doc";
13
-
14
11
  // src/data/readers.ts
15
12
  import { applyTableViewState, parseTableViewState } from "@bendyline/squisq/table";
16
13
  function applyViewParams(headers, body, opts) {
@@ -152,89 +149,9 @@ function defaultDataReaders() {
152
149
  return [csvDataReader, xlsxDataReader, parquetDataReader];
153
150
  }
154
151
 
155
- // src/data/materialize.ts
156
- function tableRow(cells) {
157
- return {
158
- type: "tableRow",
159
- children: cells.map((value) => ({
160
- type: "tableCell",
161
- children: value ? [{ type: "text", value }] : []
162
- }))
163
- };
164
- }
165
- function extensionOf(path) {
166
- const base = path.split("/").pop() ?? path;
167
- const dot = base.lastIndexOf(".");
168
- return dot > 0 ? base.slice(dot + 1).toLowerCase() : "";
169
- }
170
- async function materializeDataReferences(markdownDoc, container, onWarning) {
171
- const readers = defaultDataReaders();
172
- const children = [];
173
- let changed = false;
174
- for (const node of markdownDoc.children) {
175
- children.push(node);
176
- if (node.type !== "heading") continue;
177
- const params = node.templateAnnotation?.params;
178
- const src = params?.src;
179
- if (!src || !isDataFilePath(src)) continue;
180
- const label = params?.sheet && params?.anchor ? `${params.sheet}!${params.anchor}` : src;
181
- if (!container) {
182
- onWarning?.(
183
- `Data reference "${src}" could not be embedded: the export has no source container to read it from.`
184
- );
185
- continue;
186
- }
187
- const ext = extensionOf(src);
188
- const reader = readers.find((r) => r.extensions.includes(ext));
189
- if (!reader) {
190
- onWarning?.(`Data reference "${src}" could not be embedded: no reader for ".${ext}".`);
191
- continue;
192
- }
193
- let bytes = null;
194
- try {
195
- bytes = await container.readFile(src);
196
- } catch {
197
- bytes = null;
198
- }
199
- if (!bytes) {
200
- onWarning?.(`Data reference "${src}" could not be embedded: file not found in container.`);
201
- continue;
202
- }
203
- try {
204
- const table = await reader.read(bytes, {
205
- maxRows: Number.POSITIVE_INFINITY,
206
- ...params?.sheet ? { sheet: params.sheet } : {},
207
- ...params?.anchor ? { anchor: params.anchor } : {},
208
- ...params?.headerRow !== void 0 ? { headerRow: params.headerRow !== "false" } : {},
209
- // Exports honor the author's curated view: the sort/filter params
210
- // shape the embedded full table exactly as they shape previews.
211
- ...params?.sort ? { sort: params.sort } : {},
212
- ...params?.filter ? { filter: params.filter } : {}
213
- });
214
- const mdTable = {
215
- type: "table",
216
- children: [tableRow(table.headers), ...table.rows.map(tableRow)]
217
- };
218
- children.push(mdTable);
219
- changed = true;
220
- if (ext === "xlsx") {
221
- onWarning?.(
222
- `Region ${label} exported as values; formulas in the sidecar workbook were not carried over.`
223
- );
224
- }
225
- } catch (err) {
226
- onWarning?.(
227
- `Data reference "${src}" could not be embedded: ${err instanceof Error ? err.message : String(err)}`
228
- );
229
- }
230
- }
231
- return changed ? { ...markdownDoc, children } : markdownDoc;
232
- }
233
-
234
152
  export {
235
153
  csvDataReader,
236
154
  xlsxDataReader,
237
155
  parquetDataReader,
238
- defaultDataReaders,
239
- materializeDataReferences
156
+ defaultDataReaders
240
157
  };
@@ -1,3 +1,45 @@
1
+ // src/shared/blockTags.ts
2
+ import {
3
+ detectPromotableBodyAnnotation,
4
+ hasTemplate,
5
+ isMediaAnnotationName,
6
+ parseStandaloneAnnotation
7
+ } from "@bendyline/squisq/doc";
8
+ function withoutBlockTags(doc, options = {}) {
9
+ const children = withoutPromotedTags(doc.children);
10
+ const kept = children.filter((node) => !isRemovedTag(node, options));
11
+ return kept.length === doc.children.length && children === doc.children ? doc : { ...doc, children: kept };
12
+ }
13
+ function isRemovedTag(node, options) {
14
+ const tag = parseStandaloneAnnotation(node)?.template;
15
+ if (!tag) return false;
16
+ if (isMediaAnnotationName(tag)) return !options.keepMedia;
17
+ return hasTemplate(tag);
18
+ }
19
+ function withoutPromotedTags(children) {
20
+ const out = [];
21
+ let changed = false;
22
+ let index = 0;
23
+ while (index < children.length) {
24
+ const node = children[index++];
25
+ out.push(node);
26
+ if (node.type !== "heading" || node.templateAnnotation?.template) continue;
27
+ let end = index;
28
+ while (end < children.length && children[end].type !== "heading") end++;
29
+ const body = children.slice(index, end);
30
+ const found = detectPromotableBodyAnnotation(body);
31
+ const tag = found?.data.template;
32
+ if (found && tag && !isMediaAnnotationName(tag) && hasTemplate(tag)) {
33
+ out.push(...found.strippedContents);
34
+ changed = true;
35
+ } else {
36
+ out.push(...body);
37
+ }
38
+ index = end;
39
+ }
40
+ return changed ? out : children;
41
+ }
42
+
1
43
  // src/shared/footnotes.ts
2
44
  var FootnoteIndex = class {
3
45
  constructor(doc) {
@@ -102,6 +144,7 @@ function renumberFootnotes(doc) {
102
144
  }
103
145
 
104
146
  export {
147
+ withoutBlockTags,
105
148
  FootnoteIndex,
106
149
  footnoteIds,
107
150
  renumberFootnotes