@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.
- package/README.md +15 -13
- package/dist/chunk-4LIFEQKX.js +358 -0
- package/dist/{chunk-UXEANVBI.js → chunk-5HUHSLGA.js} +1 -84
- package/dist/{chunk-BXWNU4T5.js → chunk-DTJQK7U7.js} +43 -0
- package/dist/{chunk-GDUZJ75A.js → chunk-MJTPWLVV.js} +59 -21
- package/dist/{chunk-6ALSRHD7.js → chunk-NCDY3EOL.js} +66 -9
- package/dist/{chunk-TMOXUUTG.js → chunk-NQNIFIDP.js} +6 -4
- package/dist/{chunk-LK4KCVN6.js → chunk-QPJHAMOW.js} +70 -28
- package/dist/{chunk-QU4EVC62.js → chunk-S5VXWSRR.js} +1 -1
- package/dist/{chunk-KROH7FNT.js → chunk-VKLJUHC2.js} +6 -4
- 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/icons.d.ts +29 -0
- package/dist/html/icons.js +62 -0
- package/dist/html/index.d.ts +3 -130
- package/dist/html/index.js +2 -2
- package/dist/html/prepare.d.ts +97 -0
- package/dist/html/prepare.js +85 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +16 -16
- 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 +3 -3
- package/dist/pdf/index.d.ts +1 -1
- package/dist/pdf/index.js +3 -3
- package/dist/plainHtml-B6IXcSet.d.ts +148 -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 +12 -2
- /package/dist/{chunk-LBXBRFBZ.js → chunk-DDMPZZJF.js} +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defaultDataReaders
|
|
3
|
+
} from "./chunk-5HUHSLGA.js";
|
|
4
|
+
|
|
5
|
+
// src/data/materialize.ts
|
|
6
|
+
import {
|
|
7
|
+
isDataFilePath
|
|
8
|
+
} from "@bendyline/squisq/doc";
|
|
9
|
+
function tableRow(cells) {
|
|
10
|
+
return {
|
|
11
|
+
type: "tableRow",
|
|
12
|
+
children: cells.map((value) => ({
|
|
13
|
+
type: "tableCell",
|
|
14
|
+
children: value ? [{ type: "text", value }] : []
|
|
15
|
+
}))
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function count(n) {
|
|
19
|
+
return n.toLocaleString("en-US");
|
|
20
|
+
}
|
|
21
|
+
function extensionOf(path) {
|
|
22
|
+
const base = path.split("/").pop() ?? path;
|
|
23
|
+
const dot = base.lastIndexOf(".");
|
|
24
|
+
return dot > 0 ? base.slice(dot + 1).toLowerCase() : "";
|
|
25
|
+
}
|
|
26
|
+
var DATA_PREVIEW_ROWS = 100;
|
|
27
|
+
async function materializeDataReferences(markdownDoc, container, onWarning, options = {}) {
|
|
28
|
+
const readers = defaultDataReaders();
|
|
29
|
+
const children = [];
|
|
30
|
+
let changed = false;
|
|
31
|
+
for (const [index, node] of markdownDoc.children.entries()) {
|
|
32
|
+
children.push(node);
|
|
33
|
+
if (node.type !== "heading") continue;
|
|
34
|
+
const params = node.templateAnnotation?.params;
|
|
35
|
+
const src = params?.src;
|
|
36
|
+
if (!src || !isDataFilePath(src)) continue;
|
|
37
|
+
if (markdownDoc.children[index + 1]?.type === "table") continue;
|
|
38
|
+
const label = params?.sheet && params?.anchor ? `${params.sheet}!${params.anchor}` : src;
|
|
39
|
+
if (!container) {
|
|
40
|
+
onWarning?.(
|
|
41
|
+
`Data reference "${src}" could not be embedded: the export has no source container to read it from.`
|
|
42
|
+
);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const ext = extensionOf(src);
|
|
46
|
+
const reader = readers.find((r) => r.extensions.includes(ext));
|
|
47
|
+
if (!reader) {
|
|
48
|
+
onWarning?.(`Data reference "${src}" could not be embedded: no reader for ".${ext}".`);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const previewRows = Number.parseInt(params?.previewRows ?? "", 10);
|
|
52
|
+
const maxRows = options.maxRows === void 0 ? Number.POSITIVE_INFINITY : previewRows > 0 ? previewRows : options.maxRows;
|
|
53
|
+
const readOptions = {
|
|
54
|
+
maxRows,
|
|
55
|
+
...params?.sheet ? { sheet: params.sheet } : {},
|
|
56
|
+
...params?.anchor ? { anchor: params.anchor } : {},
|
|
57
|
+
...params?.headerRow !== void 0 ? { headerRow: params.headerRow !== "false" } : {},
|
|
58
|
+
// Exports honor the author's curated view: the sort/filter params
|
|
59
|
+
// shape the embedded full table exactly as they shape previews.
|
|
60
|
+
...params?.sort ? { sort: params.sort } : {},
|
|
61
|
+
...params?.filter ? { filter: params.filter } : {}
|
|
62
|
+
};
|
|
63
|
+
const cacheKey = [
|
|
64
|
+
src,
|
|
65
|
+
readOptions.sheet ?? "",
|
|
66
|
+
readOptions.anchor ?? "",
|
|
67
|
+
String(readOptions.headerRow ?? ""),
|
|
68
|
+
readOptions.sort ?? "",
|
|
69
|
+
readOptions.filter ?? "",
|
|
70
|
+
String(maxRows)
|
|
71
|
+
].join("\0");
|
|
72
|
+
let pending = options.tableCache?.get(cacheKey);
|
|
73
|
+
if (!pending) {
|
|
74
|
+
let bytes = null;
|
|
75
|
+
try {
|
|
76
|
+
bytes = await container.readFile(src);
|
|
77
|
+
} catch {
|
|
78
|
+
bytes = null;
|
|
79
|
+
}
|
|
80
|
+
if (!bytes) {
|
|
81
|
+
onWarning?.(`Data reference "${src}" could not be embedded: file not found in container.`);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
pending = reader.read(bytes, readOptions);
|
|
85
|
+
options.tableCache?.set(cacheKey, pending);
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const table = await pending;
|
|
89
|
+
const mdTable = {
|
|
90
|
+
type: "table",
|
|
91
|
+
children: [tableRow(table.headers), ...table.rows.map(tableRow)]
|
|
92
|
+
};
|
|
93
|
+
children.push(mdTable);
|
|
94
|
+
if (table.totalRows > table.rows.length) {
|
|
95
|
+
children.push({
|
|
96
|
+
type: "paragraph",
|
|
97
|
+
children: [
|
|
98
|
+
{
|
|
99
|
+
type: "emphasis",
|
|
100
|
+
children: [
|
|
101
|
+
{
|
|
102
|
+
type: "text",
|
|
103
|
+
value: `Showing ${count(table.rows.length)} of ${count(table.totalRows)} rows.`
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
changed = true;
|
|
111
|
+
if (ext === "xlsx") {
|
|
112
|
+
onWarning?.(
|
|
113
|
+
`Region ${label} exported as values; formulas in the sidecar workbook were not carried over.`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
} catch (err) {
|
|
117
|
+
onWarning?.(
|
|
118
|
+
`Data reference "${src}" could not be embedded: ${err instanceof Error ? err.message : String(err)}`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return changed ? { ...markdownDoc, children } : markdownDoc;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export {
|
|
126
|
+
DATA_PREVIEW_ROWS,
|
|
127
|
+
materializeDataReferences
|
|
128
|
+
};
|
|
@@ -14,13 +14,14 @@ import {
|
|
|
14
14
|
} from "./chunk-JU2RHXUB.js";
|
|
15
15
|
import {
|
|
16
16
|
FootnoteIndex,
|
|
17
|
-
footnoteIds
|
|
18
|
-
|
|
17
|
+
footnoteIds,
|
|
18
|
+
withoutBlockTags
|
|
19
|
+
} from "./chunk-DTJQK7U7.js";
|
|
19
20
|
import {
|
|
20
21
|
collectInlineIconFamilies,
|
|
21
22
|
fontAwesomeFaces,
|
|
22
23
|
fontAwesomeGlyph
|
|
23
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-DDMPZZJF.js";
|
|
24
25
|
import {
|
|
25
26
|
imageSizeAttributes
|
|
26
27
|
} from "./chunk-JZR32FON.js";
|
|
@@ -30,8 +31,9 @@ import JSZip from "jszip";
|
|
|
30
31
|
import { resolveFontFamily } from "@bendyline/squisq/schemas";
|
|
31
32
|
import { resolveThemeForDoc } from "@bendyline/squisq/doc";
|
|
32
33
|
import { isHtmlLineBreak, readFrontmatterThemeId, sanitizeUrl } from "@bendyline/squisq/markdown";
|
|
33
|
-
async function markdownDocToEpub(
|
|
34
|
+
async function markdownDocToEpub(authoredDoc, options = {}) {
|
|
34
35
|
options.signal?.throwIfAborted();
|
|
36
|
+
const sourceDoc = withoutBlockTags(authoredDoc);
|
|
35
37
|
const themeId = options.themeId ?? readFrontmatterThemeId(sourceDoc.frontmatter);
|
|
36
38
|
const islandColor = themeId ? resolveThemeForDoc(sourceDoc, themeId, options.themeRegistry).colors.text : void 0;
|
|
37
39
|
const { doc, images: islandImages } = svgIslandsAsImages(sourceDoc, { color: islandColor });
|
package/dist/data/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DataSourceReader } from '@bendyline/squisq/doc';
|
|
1
|
+
import { DataSourceReader, DataSourceTable } from '@bendyline/squisq/doc';
|
|
2
2
|
import { ContentContainer } from '@bendyline/squisq/storage';
|
|
3
3
|
import { MarkdownDocument } from '@bendyline/squisq/markdown';
|
|
4
4
|
|
|
@@ -31,12 +31,34 @@ declare function defaultDataReaders(): DataSourceReader[];
|
|
|
31
31
|
* (its body link simply doesn't survive a tables-only export).
|
|
32
32
|
*/
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Rows a data reference shows in a document or page, which cannot carry the
|
|
36
|
+
* file it points at; the reader follows the author's link for the rest.
|
|
37
|
+
*/
|
|
38
|
+
declare const DATA_PREVIEW_ROWS = 100;
|
|
39
|
+
interface MaterializeDataReferencesOptions {
|
|
40
|
+
/**
|
|
41
|
+
* Embed at most this many data rows per reference — a block's own
|
|
42
|
+
* `previewRows` param wins — followed by a "Showing N of M rows" note when
|
|
43
|
+
* rows were left out. Default: every row.
|
|
44
|
+
*/
|
|
45
|
+
maxRows?: number;
|
|
46
|
+
/**
|
|
47
|
+
* A caller-owned memo of reader results, keyed by file and read options,
|
|
48
|
+
* for a caller that materializes the same document repeatedly (a live
|
|
49
|
+
* preview). The caller clears it when the files may have changed.
|
|
50
|
+
*/
|
|
51
|
+
tableCache?: Map<string, Promise<DataSourceTable>>;
|
|
52
|
+
}
|
|
34
53
|
/**
|
|
35
54
|
* Returns a copy of `markdownDoc` where every heading annotated with a
|
|
36
|
-
* resolvable data `src` is followed by the
|
|
37
|
-
*
|
|
55
|
+
* resolvable data `src` is followed by the source table (in full unless
|
|
56
|
+
* `options.maxRows` bounds it). A reference whose heading is already followed
|
|
57
|
+
* by a table keeps it — author data wins, as in `resolveDataReferences` — so
|
|
58
|
+
* materializing twice adds nothing. The input document is returned unchanged
|
|
59
|
+
* (same object) when nothing materialized.
|
|
38
60
|
*/
|
|
39
|
-
declare function materializeDataReferences(markdownDoc: MarkdownDocument, container: ContentContainer | null | undefined, onWarning?: (message: string) => void): Promise<MarkdownDocument>;
|
|
61
|
+
declare function materializeDataReferences(markdownDoc: MarkdownDocument, container: ContentContainer | null | undefined, onWarning?: (message: string) => void, options?: MaterializeDataReferencesOptions): Promise<MarkdownDocument>;
|
|
40
62
|
|
|
41
63
|
/**
|
|
42
64
|
* Sidecar naming shared by the spill-capable importers (`xlsxToContainer`,
|
|
@@ -75,4 +97,4 @@ declare function sidecarReferenceDoc(plan: DataSidecarPlan): MarkdownDocument;
|
|
|
75
97
|
/** {@link sidecarReferenceDoc} as serialized markdown source. */
|
|
76
98
|
declare function sidecarReferenceMarkdown(plan: DataSidecarPlan): string;
|
|
77
99
|
|
|
78
|
-
export { type DataSidecarPlan, csvDataReader, defaultDataReaders, docSlugForFileName, materializeDataReferences, parquetDataReader, planDataSidecar, sanitizeSourceFileName, sidecarReferenceDoc, sidecarReferenceMarkdown, xlsxDataReader };
|
|
100
|
+
export { DATA_PREVIEW_ROWS, type DataSidecarPlan, type MaterializeDataReferencesOptions, csvDataReader, defaultDataReaders, docSlugForFileName, materializeDataReferences, parquetDataReader, planDataSidecar, sanitizeSourceFileName, sidecarReferenceDoc, sidecarReferenceMarkdown, xlsxDataReader };
|
package/dist/data/index.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DATA_PREVIEW_ROWS,
|
|
3
|
+
materializeDataReferences
|
|
4
|
+
} from "../chunk-YRFBWYAD.js";
|
|
1
5
|
import {
|
|
2
6
|
csvDataReader,
|
|
3
7
|
defaultDataReaders,
|
|
4
|
-
materializeDataReferences,
|
|
5
8
|
parquetDataReader,
|
|
6
9
|
xlsxDataReader
|
|
7
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-5HUHSLGA.js";
|
|
8
11
|
import "../chunk-ATWVNF7D.js";
|
|
9
12
|
import "../chunk-Q77KNJIN.js";
|
|
10
13
|
import {
|
|
@@ -17,6 +20,7 @@ import {
|
|
|
17
20
|
import "../chunk-S5PCVMKU.js";
|
|
18
21
|
import "../chunk-7AWFHP5U.js";
|
|
19
22
|
export {
|
|
23
|
+
DATA_PREVIEW_ROWS,
|
|
20
24
|
csvDataReader,
|
|
21
25
|
defaultDataReaders,
|
|
22
26
|
docSlugForFileName,
|
package/dist/diagrams/index.d.ts
CHANGED
|
@@ -21,25 +21,28 @@ import { MarkdownDocument, MarkdownCodeBlock } from '@bendyline/squisq/markdown'
|
|
|
21
21
|
* and PPTX embed an island natively as vector art, so by default it is
|
|
22
22
|
* left in place. Ask for it to picture islands for PDF, or to get the
|
|
23
23
|
* `svg` map of PNG fallbacks the Office exporters place beside the vector.
|
|
24
|
+
* - chart heading blocks (`{[barChart]}`, `{[pieChart]}`, …) whose first
|
|
25
|
+
* table is chartable: the picture replaces the table, as the player shows
|
|
26
|
+
* the chart alone (the table stays beneath it with `showTable`).
|
|
24
27
|
*
|
|
25
|
-
* `docToPptx` keeps drawings, timelines
|
|
26
|
-
* for it, use the returned `mermaid` map as its `diagramImages` option.
|
|
28
|
+
* `docToPptx` keeps drawings, timelines, ASCII diagrams and charts as native
|
|
29
|
+
* shapes; for it, use the returned `mermaid` map as its `diagramImages` option.
|
|
27
30
|
*/
|
|
28
31
|
|
|
29
32
|
/** What kind of diagram a picture is wanted for. */
|
|
30
|
-
type ExportDiagramKind = 'mermaid' | 'diagram' | 'timeline' | 'tree' | 'container' | 'svg';
|
|
33
|
+
type ExportDiagramKind = 'mermaid' | 'diagram' | 'timeline' | 'tree' | 'container' | 'svg' | 'chart';
|
|
31
34
|
/** Every kind, `svg` included — for exporters with no vector picture of their own (PDF). */
|
|
32
35
|
declare const EXPORT_DIAGRAM_KINDS: readonly ExportDiagramKind[];
|
|
33
36
|
interface ExportDiagram {
|
|
34
37
|
readonly kind: ExportDiagramKind;
|
|
35
38
|
/**
|
|
36
|
-
* The diagram's own markdown: its fence,
|
|
37
|
-
*
|
|
39
|
+
* The diagram's own markdown: its fence, for a container its heading and
|
|
40
|
+
* every child heading and body it owns, for a chart its heading and table.
|
|
38
41
|
*/
|
|
39
42
|
readonly markdown: string;
|
|
40
|
-
/** The fence content for fence kinds; '' for containers. */
|
|
43
|
+
/** The fence content for fence kinds; '' for containers and charts. */
|
|
41
44
|
readonly source: string;
|
|
42
|
-
/** The container's template (`drawing`, `
|
|
45
|
+
/** The container's or chart's template (`drawing`, `barChart`, …); '' for fences. */
|
|
43
46
|
readonly template: string;
|
|
44
47
|
/** A text alternative for the picture. */
|
|
45
48
|
readonly alt: string;
|
|
@@ -87,6 +90,14 @@ interface RasterizedDiagrams {
|
|
|
87
90
|
declare function fenceDiagramKind(node: MarkdownCodeBlock): ExportDiagramKind | null;
|
|
88
91
|
/** Every diagram in `doc`, in document order. */
|
|
89
92
|
declare function findDiagrams(doc: MarkdownDocument): ExportDiagram[];
|
|
93
|
+
/**
|
|
94
|
+
* A renderer that remembers what it drew, for a host that renders the same
|
|
95
|
+
* document again and again — a live preview, or a file regenerated on every
|
|
96
|
+
* save — so each pass redraws only the diagrams that changed. A picture is
|
|
97
|
+
* keyed by the diagram itself; the least recently used beyond `limit` are
|
|
98
|
+
* forgotten, and a failure is never remembered.
|
|
99
|
+
*/
|
|
100
|
+
declare function cachingDiagramRasterizer(render: DiagramRasterizer, limit?: number): DiagramRasterizer;
|
|
90
101
|
/**
|
|
91
102
|
* Picture every diagram in `doc` with `render`, one at a time, and return
|
|
92
103
|
* the document with each pictured diagram replaced by an image of it. A
|
|
@@ -94,4 +105,4 @@ declare function findDiagrams(doc: MarkdownDocument): ExportDiagram[];
|
|
|
94
105
|
*/
|
|
95
106
|
declare function rasterizeDiagrams(doc: MarkdownDocument, render: DiagramRasterizer, options?: RasterizeDiagramsOptions): Promise<RasterizedDiagrams>;
|
|
96
107
|
|
|
97
|
-
export { type DiagramPicture, type DiagramRasterizer, EXPORT_DIAGRAM_KINDS, type ExportDiagram, type ExportDiagramKind, type RasterizeDiagramsOptions, type RasterizedDiagrams, fenceDiagramKind, findDiagrams, rasterizeDiagrams };
|
|
108
|
+
export { type DiagramPicture, type DiagramRasterizer, EXPORT_DIAGRAM_KINDS, type ExportDiagram, type ExportDiagramKind, type RasterizeDiagramsOptions, type RasterizedDiagrams, cachingDiagramRasterizer, fenceDiagramKind, findDiagrams, rasterizeDiagrams };
|
package/dist/diagrams/index.js
CHANGED
|
@@ -1,248 +1,13 @@
|
|
|
1
|
-
// src/diagrams/index.ts
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
detectAsciiDiagram,
|
|
10
|
-
detectAsciiTimeline,
|
|
11
|
-
detectTree,
|
|
12
|
-
isContainerTemplate,
|
|
13
|
-
isEligibleAsciiFenceLang,
|
|
14
|
-
isEligibleAsciiTimelineFenceLang,
|
|
15
|
-
isEligibleTreeFenceLang,
|
|
16
|
-
isExplicitDiagramLang,
|
|
17
|
-
isExplicitTimelineLang,
|
|
18
|
-
isExplicitTreeLang,
|
|
19
|
-
resolveTemplateName
|
|
20
|
-
} from "@bendyline/squisq/doc";
|
|
21
|
-
var DEFAULT_KINDS = [
|
|
22
|
-
"mermaid",
|
|
23
|
-
"diagram",
|
|
24
|
-
"timeline",
|
|
25
|
-
"tree",
|
|
26
|
-
"container"
|
|
27
|
-
];
|
|
28
|
-
var EXPORT_DIAGRAM_KINDS = [...DEFAULT_KINDS, "svg"];
|
|
29
|
-
var KIND_NAMES = {
|
|
30
|
-
mermaid: "Diagram",
|
|
31
|
-
diagram: "Diagram",
|
|
32
|
-
timeline: "Timeline",
|
|
33
|
-
tree: "Tree",
|
|
34
|
-
container: "Diagram",
|
|
35
|
-
svg: "Illustration"
|
|
36
|
-
};
|
|
37
|
-
function fenceDiagramKind(node) {
|
|
38
|
-
const lang = node.lang ?? null;
|
|
39
|
-
if ((lang ?? "").trim().toLowerCase() === "mermaid") return "mermaid";
|
|
40
|
-
if (isSvgIslandLang(lang)) return parseSvgIsland(node.value).ok ? "svg" : null;
|
|
41
|
-
if (isEligibleAsciiFenceLang(lang)) {
|
|
42
|
-
const detection = detectAsciiDiagram(node.value, { explicit: isExplicitDiagramLang(lang) });
|
|
43
|
-
if (detection.isDiagram) return "diagram";
|
|
44
|
-
}
|
|
45
|
-
if (isEligibleTreeFenceLang(lang)) {
|
|
46
|
-
if (detectTree(node.value, { explicit: isExplicitTreeLang(lang) }).isTree) return "tree";
|
|
47
|
-
}
|
|
48
|
-
if (isEligibleAsciiTimelineFenceLang(lang)) {
|
|
49
|
-
const detection = detectAsciiTimeline(node.value, { explicit: isExplicitTimelineLang(lang) });
|
|
50
|
-
if (detection.isTimeline) return "timeline";
|
|
51
|
-
}
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
function containerTemplateOf(node) {
|
|
55
|
-
if (node.type !== "heading") return null;
|
|
56
|
-
const requested = node.templateAnnotation?.template;
|
|
57
|
-
if (!requested || !isContainerTemplate(requested)) return null;
|
|
58
|
-
return resolveTemplateName(requested);
|
|
59
|
-
}
|
|
60
|
-
function mermaidAlt(source) {
|
|
61
|
-
const title = /^\s*accTitle\s*:\s*(.+?)\s*$/mu.exec(source)?.[1] ?? "";
|
|
62
|
-
const description = /^\s*accDescr\s*:\s*(.+?)\s*$/mu.exec(source)?.[1] ?? "";
|
|
63
|
-
return [title, description].filter(Boolean).join(". ");
|
|
64
|
-
}
|
|
65
|
-
function fenceAlt(kind, source) {
|
|
66
|
-
if (kind === "mermaid") return mermaidAlt(source);
|
|
67
|
-
if (kind === "svg") {
|
|
68
|
-
const result = parseSvgIsland(source);
|
|
69
|
-
return result.ok && result.island.title || "";
|
|
70
|
-
}
|
|
71
|
-
return "";
|
|
72
|
-
}
|
|
73
|
-
function fenceMarkdown(node) {
|
|
74
|
-
return stringifyMarkdown({ type: "document", children: [node] }).trim();
|
|
75
|
-
}
|
|
76
|
-
function findInDocument(doc) {
|
|
77
|
-
const found = [];
|
|
78
|
-
const children = doc.children;
|
|
79
|
-
const walk = (nodes) => {
|
|
80
|
-
for (const node of nodes) {
|
|
81
|
-
if (node.type === "code") {
|
|
82
|
-
const fence = node;
|
|
83
|
-
const kind = fenceDiagramKind(fence);
|
|
84
|
-
if (kind) {
|
|
85
|
-
found.push({
|
|
86
|
-
fence,
|
|
87
|
-
diagram: {
|
|
88
|
-
kind,
|
|
89
|
-
markdown: fenceMarkdown(fence),
|
|
90
|
-
source: fence.value,
|
|
91
|
-
template: "",
|
|
92
|
-
alt: fenceAlt(kind, fence.value) || KIND_NAMES[kind]
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
const nested = node.children;
|
|
99
|
-
if (Array.isArray(nested) && node.type !== "heading" && node.type !== "paragraph") {
|
|
100
|
-
walk(nested);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
for (let index = 0; index < children.length; index++) {
|
|
105
|
-
const node = children[index];
|
|
106
|
-
const template = containerTemplateOf(node);
|
|
107
|
-
if (!template) {
|
|
108
|
-
walk([node]);
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
const depth = node.depth;
|
|
112
|
-
let end = index + 1;
|
|
113
|
-
while (end < children.length) {
|
|
114
|
-
const next = children[end];
|
|
115
|
-
if (next.type === "heading" && next.depth <= depth) break;
|
|
116
|
-
end++;
|
|
117
|
-
}
|
|
118
|
-
const heading = extractPlainText(node).trim();
|
|
119
|
-
found.push({
|
|
120
|
-
containerIndex: index,
|
|
121
|
-
containerEnd: end,
|
|
122
|
-
diagram: {
|
|
123
|
-
kind: "container",
|
|
124
|
-
markdown: stringifyMarkdown({
|
|
125
|
-
type: "document",
|
|
126
|
-
children: children.slice(index, end)
|
|
127
|
-
}).trim(),
|
|
128
|
-
source: "",
|
|
129
|
-
template,
|
|
130
|
-
alt: heading || KIND_NAMES.container
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
index = end - 1;
|
|
134
|
-
}
|
|
135
|
-
return found;
|
|
136
|
-
}
|
|
137
|
-
function imageUrls(nodes, into) {
|
|
138
|
-
for (const node of nodes) {
|
|
139
|
-
if (node.type === "image") into.add(node.url);
|
|
140
|
-
const nested = node.children;
|
|
141
|
-
if (Array.isArray(nested)) imageUrls(nested, into);
|
|
142
|
-
}
|
|
143
|
-
return into;
|
|
144
|
-
}
|
|
145
|
-
function findDiagrams(doc) {
|
|
146
|
-
return findInDocument(doc).map((entry) => entry.diagram);
|
|
147
|
-
}
|
|
148
|
-
function imageParagraph(url, alt) {
|
|
149
|
-
const image = { type: "image", url, alt, title: null };
|
|
150
|
-
return { type: "paragraph", children: [image] };
|
|
151
|
-
}
|
|
152
|
-
function replaceFences(nodes, replacements) {
|
|
153
|
-
let changed = false;
|
|
154
|
-
const next = nodes.map((node) => {
|
|
155
|
-
const replacement = replacements.get(node);
|
|
156
|
-
if (replacement) {
|
|
157
|
-
changed = true;
|
|
158
|
-
return replacement;
|
|
159
|
-
}
|
|
160
|
-
const nested = node.children;
|
|
161
|
-
if (Array.isArray(nested)) {
|
|
162
|
-
const replaced = replaceFences(nested, replacements);
|
|
163
|
-
if (replaced !== nested) {
|
|
164
|
-
changed = true;
|
|
165
|
-
return { ...node, children: replaced };
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return node;
|
|
169
|
-
});
|
|
170
|
-
return changed ? next : nodes;
|
|
171
|
-
}
|
|
172
|
-
async function rasterizeDiagrams(doc, render, options = {}) {
|
|
173
|
-
const kinds = new Set(options.kinds ?? DEFAULT_KINDS);
|
|
174
|
-
const prefix = options.urlPrefix ?? "diagram";
|
|
175
|
-
const taken = imageUrls(doc.children, /* @__PURE__ */ new Set());
|
|
176
|
-
let counter = 0;
|
|
177
|
-
const nextUrl = () => {
|
|
178
|
-
let url;
|
|
179
|
-
do
|
|
180
|
-
url = `${prefix}-${String(++counter)}.png`;
|
|
181
|
-
while (taken.has(url));
|
|
182
|
-
taken.add(url);
|
|
183
|
-
return url;
|
|
184
|
-
};
|
|
185
|
-
const images = /* @__PURE__ */ new Map();
|
|
186
|
-
const mermaid = /* @__PURE__ */ new Map();
|
|
187
|
-
const svg = /* @__PURE__ */ new Map();
|
|
188
|
-
const fenceReplacements = /* @__PURE__ */ new Map();
|
|
189
|
-
const containerReplacements = [];
|
|
190
|
-
for (const entry of findInDocument(doc)) {
|
|
191
|
-
options.signal?.throwIfAborted();
|
|
192
|
-
if (!kinds.has(entry.diagram.kind)) continue;
|
|
193
|
-
let picture = null;
|
|
194
|
-
try {
|
|
195
|
-
picture = await render(entry.diagram);
|
|
196
|
-
} catch (error) {
|
|
197
|
-
options.onWarning?.(
|
|
198
|
-
`A ${KIND_NAMES[entry.diagram.kind].toLowerCase()} could not be drawn and was kept as text: ${error instanceof Error ? error.message : String(error)}`
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
if (!picture || picture.width <= 0 || picture.height <= 0) continue;
|
|
202
|
-
const data = picture.data instanceof Uint8Array ? picture.data : new Uint8Array(picture.data);
|
|
203
|
-
const url = nextUrl();
|
|
204
|
-
images.set(url, {
|
|
205
|
-
data,
|
|
206
|
-
contentType: "image/png",
|
|
207
|
-
width: picture.width,
|
|
208
|
-
height: picture.height
|
|
209
|
-
});
|
|
210
|
-
if (entry.diagram.kind === "mermaid") mermaid.set(entry.diagram.source.trim(), picture);
|
|
211
|
-
if (entry.diagram.kind === "svg") svg.set(entry.diagram.source.trim(), picture);
|
|
212
|
-
const paragraph = imageParagraph(url, entry.diagram.alt);
|
|
213
|
-
if (entry.fence) {
|
|
214
|
-
fenceReplacements.set(entry.fence, paragraph);
|
|
215
|
-
} else if (entry.containerIndex !== void 0 && entry.containerEnd !== void 0) {
|
|
216
|
-
const heading = doc.children[entry.containerIndex];
|
|
217
|
-
const { templateAnnotation: _template, ...plainHeading } = heading;
|
|
218
|
-
containerReplacements.push({
|
|
219
|
-
start: entry.containerIndex,
|
|
220
|
-
end: entry.containerEnd,
|
|
221
|
-
nodes: [plainHeading, paragraph]
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
let children = doc.children;
|
|
226
|
-
if (containerReplacements.length > 0) {
|
|
227
|
-
const rebuilt = [];
|
|
228
|
-
let cursor = 0;
|
|
229
|
-
for (const replacement of containerReplacements) {
|
|
230
|
-
rebuilt.push(...children.slice(cursor, replacement.start), ...replacement.nodes);
|
|
231
|
-
cursor = replacement.end;
|
|
232
|
-
}
|
|
233
|
-
rebuilt.push(...children.slice(cursor));
|
|
234
|
-
children = rebuilt;
|
|
235
|
-
}
|
|
236
|
-
if (fenceReplacements.size > 0) children = replaceFences(children, fenceReplacements);
|
|
237
|
-
return {
|
|
238
|
-
markdownDoc: children === doc.children ? doc : { ...doc, children },
|
|
239
|
-
images,
|
|
240
|
-
mermaid,
|
|
241
|
-
svg
|
|
242
|
-
};
|
|
243
|
-
}
|
|
2
|
+
EXPORT_DIAGRAM_KINDS,
|
|
3
|
+
cachingDiagramRasterizer,
|
|
4
|
+
fenceDiagramKind,
|
|
5
|
+
findDiagrams,
|
|
6
|
+
rasterizeDiagrams
|
|
7
|
+
} from "../chunk-4LIFEQKX.js";
|
|
244
8
|
export {
|
|
245
9
|
EXPORT_DIAGRAM_KINDS,
|
|
10
|
+
cachingDiagramRasterizer,
|
|
246
11
|
fenceDiagramKind,
|
|
247
12
|
findDiagrams,
|
|
248
13
|
rasterizeDiagrams
|
package/dist/docx/index.d.ts
CHANGED
|
@@ -84,7 +84,7 @@ interface DocxExportOptions {
|
|
|
84
84
|
* @param options - Export options
|
|
85
85
|
* @returns An ArrayBuffer containing the .docx file
|
|
86
86
|
*/
|
|
87
|
-
declare function markdownDocToDocx(
|
|
87
|
+
declare function markdownDocToDocx(source: MarkdownDocument, options?: DocxExportOptions): Promise<ArrayBuffer>;
|
|
88
88
|
/**
|
|
89
89
|
* Convert a squisq Doc to a .docx Blob.
|
|
90
90
|
*
|
package/dist/docx/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
docxToDoc,
|
|
5
5
|
docxToMarkdownDoc,
|
|
6
6
|
markdownDocToDocx
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-VKLJUHC2.js";
|
|
8
8
|
import "../chunk-DHAK4PII.js";
|
|
9
9
|
import "../chunk-VCZUXQUL.js";
|
|
10
10
|
import "../chunk-BZ5SHMOY.js";
|
|
@@ -12,9 +12,9 @@ import "../chunk-ILCJ3WFD.js";
|
|
|
12
12
|
import "../chunk-JU2RHXUB.js";
|
|
13
13
|
import "../chunk-S5PCVMKU.js";
|
|
14
14
|
import "../chunk-7AWFHP5U.js";
|
|
15
|
-
import "../chunk-
|
|
15
|
+
import "../chunk-DTJQK7U7.js";
|
|
16
16
|
import "../chunk-IIQYS2YH.js";
|
|
17
|
-
import "../chunk-
|
|
17
|
+
import "../chunk-DDMPZZJF.js";
|
|
18
18
|
import "../chunk-JZR32FON.js";
|
|
19
19
|
export {
|
|
20
20
|
docToDocx,
|
package/dist/epub/index.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ interface EpubExportOptions {
|
|
|
66
66
|
* Chapters are split at H1/H2 heading boundaries. All referenced images
|
|
67
67
|
* (provided via `options.images`) are embedded in the archive.
|
|
68
68
|
*/
|
|
69
|
-
declare function markdownDocToEpub(
|
|
69
|
+
declare function markdownDocToEpub(authoredDoc: MarkdownDocument, options?: EpubExportOptions): Promise<ArrayBuffer>;
|
|
70
70
|
/**
|
|
71
71
|
* Convert a squisq Doc to an EPUB 3 file.
|
|
72
72
|
*
|
package/dist/epub/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
docToEpub,
|
|
3
3
|
markdownDocToEpub
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-ZJERBWTB.js";
|
|
5
5
|
import "../chunk-WMIDXNGR.js";
|
|
6
6
|
import "../chunk-VCZUXQUL.js";
|
|
7
7
|
import "../chunk-BZ5SHMOY.js";
|
|
8
8
|
import "../chunk-JU2RHXUB.js";
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
9
|
+
import "../chunk-DTJQK7U7.js";
|
|
10
|
+
import "../chunk-DDMPZZJF.js";
|
|
11
11
|
import "../chunk-JZR32FON.js";
|
|
12
12
|
export {
|
|
13
13
|
docToEpub,
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
collectInlineIconFamilies,
|
|
3
|
+
fontAwesomeFace,
|
|
4
|
+
fontAwesomeFaces,
|
|
5
|
+
fontAwesomeGlyph,
|
|
6
|
+
obfuscateDocxFont
|
|
7
|
+
} from "./chunk-DDMPZZJF.js";
|
|
8
|
+
export {
|
|
9
|
+
collectInlineIconFamilies,
|
|
10
|
+
fontAwesomeFace,
|
|
11
|
+
fontAwesomeFaces,
|
|
12
|
+
fontAwesomeGlyph,
|
|
13
|
+
obfuscateDocxFont
|
|
14
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MarkdownDocument } from '@bendyline/squisq/markdown';
|
|
2
|
+
import { P as PlainHtmlIcon } from '../plainHtml-B6IXcSet.js';
|
|
3
|
+
import '@bendyline/squisq/schemas';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Inline icons as SVG, for pages that should not depend on a font.
|
|
7
|
+
*
|
|
8
|
+
* A Font Awesome icon in the plain renderer is `<i class="fa-solid fa-star">`,
|
|
9
|
+
* which draws only where Font Awesome's stylesheet and fonts load — a CDN the
|
|
10
|
+
* page may not be allowed to reach, or a bundle it doesn't ship. Each icon's
|
|
11
|
+
* outline is read here from the same Font Awesome faces the DOCX, PDF and
|
|
12
|
+
* EPUB exporters embed, and drawn as a small inline `<svg>` instead: no font,
|
|
13
|
+
* no network, and it takes the text color like the glyph would.
|
|
14
|
+
*
|
|
15
|
+
* This module is its own entry, `@bendyline/squisq-formats/html-icons`, and
|
|
16
|
+
* nothing under `/html` may import it: the faces and their parser are ~2.5 MB,
|
|
17
|
+
* and a one-file bundle of `/html` would carry them even if it never drew an
|
|
18
|
+
* icon. Hosts pass `plainHtmlIcons` to `prepareMarkdownDocForPlainHtml`
|
|
19
|
+
* (`@bendyline/squisq-formats/html-prepare`) as `outlineIcons`.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The outline of every icon `doc` uses, keyed `family:name` — the `icons`
|
|
24
|
+
* option of `markdownDocToPlainHtml`. An icon the catalog doesn't know is left
|
|
25
|
+
* out and keeps its Font Awesome markup.
|
|
26
|
+
*/
|
|
27
|
+
declare function plainHtmlIcons(doc: MarkdownDocument): Promise<Map<string, PlainHtmlIcon>>;
|
|
28
|
+
|
|
29
|
+
export { plainHtmlIcons };
|