@bendyline/squisq-formats 2.8.8 → 2.8.9
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-4LIFEQKX.js +358 -0
- package/dist/{chunk-UXEANVBI.js → chunk-5HUHSLGA.js} +1 -84
- package/dist/{chunk-6ALSRHD7.js → chunk-6HUQFEP3.js} +61 -4
- package/dist/{chunk-BXWNU4T5.js → chunk-DTJQK7U7.js} +43 -0
- package/dist/{chunk-QU4EVC62.js → chunk-GFHUJ7L4.js} +1 -1
- package/dist/{chunk-TMOXUUTG.js → chunk-NQNIFIDP.js} +6 -4
- package/dist/{chunk-LK4KCVN6.js → chunk-SZ3OIY6G.js} +150 -28
- package/dist/{chunk-KROH7FNT.js → chunk-VKLJUHC2.js} +6 -4
- package/dist/{chunk-GDUZJ75A.js → chunk-WVDAFJFS.js} +59 -21
- package/dist/chunk-YRFBWYAD.js +128 -0
- package/dist/{chunk-SVYTUYZM.js → chunk-ZJERBWTB.js} +6 -4
- package/dist/data/index.d.ts +27 -5
- package/dist/data/index.js +6 -2
- package/dist/diagrams/index.d.ts +19 -8
- package/dist/diagrams/index.js +7 -242
- package/dist/docx/index.d.ts +1 -1
- package/dist/docx/index.js +3 -3
- package/dist/epub/index.d.ts +1 -1
- package/dist/epub/index.js +3 -3
- package/dist/fontAwesome-C6FRDYTY.js +14 -0
- package/dist/html/index.d.ts +85 -1
- package/dist/html/index.js +9 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.js +10 -9
- package/dist/{materialize-G4WC5UG3.js → materialize-ICXNO4S4.js} +4 -1
- package/dist/outside-in/index.d.ts +12 -0
- package/dist/outside-in/index.js +2 -2
- package/dist/pdf/index.d.ts +1 -1
- package/dist/pdf/index.js +3 -3
- package/dist/plainHtmlIcons-KBSIJ5EN.js +62 -0
- package/dist/pptx/index.js +2 -2
- package/dist/readers-3P5A6A2A.js +17 -0
- package/dist/registry/index.js +1 -1
- package/package.json +2 -2
- /package/dist/{chunk-LBXBRFBZ.js → chunk-DDMPZZJF.js} +0 -0
|
@@ -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,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
convert,
|
|
3
3
|
defaultRegistry
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WVDAFJFS.js";
|
|
5
5
|
import {
|
|
6
6
|
ConversionError
|
|
7
7
|
} from "./chunk-KXOZMWBS.js";
|
|
@@ -188,7 +188,9 @@ async function renderOutsideInDocument(source, options = {}) {
|
|
|
188
188
|
{ format: "html" }
|
|
189
189
|
);
|
|
190
190
|
}
|
|
191
|
-
const formatOptions = {
|
|
191
|
+
const formatOptions = {
|
|
192
|
+
...options.formatOptions ?? {}
|
|
193
|
+
};
|
|
192
194
|
if (layout.format === "html" && options.html) {
|
|
193
195
|
formatOptions.html = {
|
|
194
196
|
...formatOptions.html ?? {},
|
|
@@ -196,10 +198,19 @@ async function renderOutsideInDocument(source, options = {}) {
|
|
|
196
198
|
basePath: options.html.basePath ?? layout.companionName
|
|
197
199
|
};
|
|
198
200
|
}
|
|
199
|
-
|
|
201
|
+
const warnings = [];
|
|
202
|
+
const markdown = await prepareOutsideInMarkdown(
|
|
203
|
+
source.markdown,
|
|
204
|
+
layout.format,
|
|
205
|
+
source.container,
|
|
206
|
+
options,
|
|
207
|
+
formatOptions,
|
|
208
|
+
warnings
|
|
209
|
+
);
|
|
210
|
+
const result = await convert(
|
|
200
211
|
{
|
|
201
212
|
kind: "markdown",
|
|
202
|
-
markdown
|
|
213
|
+
markdown,
|
|
203
214
|
container: source.container,
|
|
204
215
|
baseName: layout.stem
|
|
205
216
|
},
|
|
@@ -210,6 +221,52 @@ async function renderOutsideInDocument(source, options = {}) {
|
|
|
210
221
|
formatOptions
|
|
211
222
|
}
|
|
212
223
|
);
|
|
224
|
+
return warnings.length > 0 ? { ...result, warnings: [...warnings, ...result.warnings] } : result;
|
|
225
|
+
}
|
|
226
|
+
async function prepareOutsideInMarkdown(markdown, format, container, options, formatOptions, warnings) {
|
|
227
|
+
const render = options.renderDiagram;
|
|
228
|
+
if (!render || format !== "docx" && format !== "pdf" && format !== "pptx") return markdown;
|
|
229
|
+
const onWarning = (message) => {
|
|
230
|
+
warnings.push(message);
|
|
231
|
+
};
|
|
232
|
+
let doc = typeof markdown === "string" ? parseMarkdown(markdown) : markdown;
|
|
233
|
+
const { rasterizeDiagrams, EXPORT_DIAGRAM_KINDS } = await import("./diagrams/index.js");
|
|
234
|
+
const signal = options.signal;
|
|
235
|
+
if (format === "pptx") {
|
|
236
|
+
const { mermaid, svg } = await rasterizeDiagrams(doc, render, {
|
|
237
|
+
kinds: ["mermaid", "svg"],
|
|
238
|
+
signal,
|
|
239
|
+
onWarning
|
|
240
|
+
});
|
|
241
|
+
formatOptions.pptx = {
|
|
242
|
+
...formatOptions.pptx,
|
|
243
|
+
diagramImages: new Map([...mermaid, ...svg, ...formatOptions.pptx?.diagramImages ?? []])
|
|
244
|
+
};
|
|
245
|
+
return doc;
|
|
246
|
+
}
|
|
247
|
+
const { materializeDataReferences, DATA_PREVIEW_ROWS } = await import("./materialize-ICXNO4S4.js");
|
|
248
|
+
doc = await materializeDataReferences(doc, container, onWarning, {
|
|
249
|
+
maxRows: DATA_PREVIEW_ROWS
|
|
250
|
+
});
|
|
251
|
+
const pictured = await rasterizeDiagrams(doc, render, {
|
|
252
|
+
kinds: format === "pdf" ? EXPORT_DIAGRAM_KINDS : void 0,
|
|
253
|
+
signal,
|
|
254
|
+
onWarning
|
|
255
|
+
});
|
|
256
|
+
if (format === "docx") {
|
|
257
|
+
const { svg } = await rasterizeDiagrams(doc, render, { kinds: ["svg"], signal, onWarning });
|
|
258
|
+
formatOptions.docx = {
|
|
259
|
+
...formatOptions.docx,
|
|
260
|
+
images: new Map([...formatOptions.docx?.images ?? [], ...pictured.images]),
|
|
261
|
+
svgIslandFallbacks: new Map([...svg, ...formatOptions.docx?.svgIslandFallbacks ?? []])
|
|
262
|
+
};
|
|
263
|
+
} else {
|
|
264
|
+
formatOptions.pdf = {
|
|
265
|
+
...formatOptions.pdf,
|
|
266
|
+
images: new Map([...formatOptions.pdf?.images ?? [], ...pictured.images])
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
return pictured.markdownDoc;
|
|
213
270
|
}
|
|
214
271
|
|
|
215
272
|
export {
|
|
@@ -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
|
|
@@ -2,8 +2,9 @@ import {
|
|
|
2
2
|
upngEncoder
|
|
3
3
|
} from "./chunk-34KECNZO.js";
|
|
4
4
|
import {
|
|
5
|
-
FootnoteIndex
|
|
6
|
-
|
|
5
|
+
FootnoteIndex,
|
|
6
|
+
withoutBlockTags
|
|
7
|
+
} from "./chunk-DTJQK7U7.js";
|
|
7
8
|
import {
|
|
8
9
|
buildContainer
|
|
9
10
|
} from "./chunk-IIQYS2YH.js";
|
|
@@ -11,7 +12,7 @@ import {
|
|
|
11
12
|
collectInlineIconFamilies,
|
|
12
13
|
fontAwesomeFaces,
|
|
13
14
|
fontAwesomeGlyph
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-DDMPZZJF.js";
|
|
15
16
|
import {
|
|
16
17
|
authoredImageSize,
|
|
17
18
|
fitWithin,
|
|
@@ -499,8 +500,9 @@ var IMPORT_TABLE_MIN_ROWS = 2;
|
|
|
499
500
|
var IMPORT_URL_PATTERN = /https?:\/\/[^\s)>\]]+/g;
|
|
500
501
|
|
|
501
502
|
// src/pdf/export.ts
|
|
502
|
-
async function markdownDocToPdf(
|
|
503
|
+
async function markdownDocToPdf(source, options = {}) {
|
|
503
504
|
options.signal?.throwIfAborted();
|
|
505
|
+
const doc = withoutBlockTags(source);
|
|
504
506
|
const pdfDoc = await PDFDocument.create();
|
|
505
507
|
if (options.title) pdfDoc.setTitle(options.title);
|
|
506
508
|
if (options.author) pdfDoc.setAuthor(options.author);
|