@opengeni/artifact-tool 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +104 -0
- package/dist/bounded-zip.d.ts +28 -0
- package/dist/chunk-4BSENMAE.js +39 -0
- package/dist/chunk-4BSENMAE.js.map +1 -0
- package/dist/chunk-4FRFNNBM.js +276 -0
- package/dist/chunk-4FRFNNBM.js.map +1 -0
- package/dist/chunk-5XIA6KHZ.js +49 -0
- package/dist/chunk-5XIA6KHZ.js.map +1 -0
- package/dist/chunk-66CT2ZRP.js +2229 -0
- package/dist/chunk-66CT2ZRP.js.map +1 -0
- package/dist/chunk-72SYDU4O.js +319 -0
- package/dist/chunk-72SYDU4O.js.map +1 -0
- package/dist/chunk-B2ZJRZDA.js +279 -0
- package/dist/chunk-B2ZJRZDA.js.map +1 -0
- package/dist/chunk-DCTLTNPW.js +2458 -0
- package/dist/chunk-DCTLTNPW.js.map +1 -0
- package/dist/chunk-FGZM4FQ6.js +473 -0
- package/dist/chunk-FGZM4FQ6.js.map +1 -0
- package/dist/chunk-HTJBLBDE.js +591 -0
- package/dist/chunk-HTJBLBDE.js.map +1 -0
- package/dist/chunk-IYFXZQ34.js +5306 -0
- package/dist/chunk-IYFXZQ34.js.map +1 -0
- package/dist/chunk-J6N7IR44.js +172 -0
- package/dist/chunk-J6N7IR44.js.map +1 -0
- package/dist/chunk-N2IHNWBS.js +1002 -0
- package/dist/chunk-N2IHNWBS.js.map +1 -0
- package/dist/chunk-NAG44K67.js +549 -0
- package/dist/chunk-NAG44K67.js.map +1 -0
- package/dist/chunk-O24KTEGP.js +33 -0
- package/dist/chunk-O24KTEGP.js.map +1 -0
- package/dist/chunk-PI2AZVGK.js +2074 -0
- package/dist/chunk-PI2AZVGK.js.map +1 -0
- package/dist/chunk-Q2FFHEY7.js +40 -0
- package/dist/chunk-Q2FFHEY7.js.map +1 -0
- package/dist/chunk-RBGQADXA.js +57 -0
- package/dist/chunk-RBGQADXA.js.map +1 -0
- package/dist/chunk-U5G2BKM2.js +613 -0
- package/dist/chunk-U5G2BKM2.js.map +1 -0
- package/dist/chunk-VOJHMSM3.js +39 -0
- package/dist/chunk-VOJHMSM3.js.map +1 -0
- package/dist/chunk-VUNV25KB.js +16 -0
- package/dist/chunk-VUNV25KB.js.map +1 -0
- package/dist/chunk-XIFUNVBO.js +101 -0
- package/dist/chunk-XIFUNVBO.js.map +1 -0
- package/dist/chunk-ZCJYRJGB.js +489 -0
- package/dist/chunk-ZCJYRJGB.js.map +1 -0
- package/dist/chunk-ZZXPEE4S.js +2260 -0
- package/dist/chunk-ZZXPEE4S.js.map +1 -0
- package/dist/document-docx-api.d.ts +49 -0
- package/dist/document-docx-codec.d.ts +9 -0
- package/dist/document-docx-codec.js +4765 -0
- package/dist/document-docx-codec.js.map +1 -0
- package/dist/document-docx-import.d.ts +261 -0
- package/dist/document-docx-packer.d.ts +18 -0
- package/dist/document-docx-state.d.ts +12 -0
- package/dist/document-render.d.ts +3 -0
- package/dist/document-render.js +492 -0
- package/dist/document-render.js.map +1 -0
- package/dist/document.d.ts +432 -0
- package/dist/document.js +37 -0
- package/dist/document.js.map +1 -0
- package/dist/errors.d.ts +23 -0
- package/dist/file-blob.d.ts +11 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +186 -0
- package/dist/index.js.map +1 -0
- package/dist/inspection.d.ts +12 -0
- package/dist/kernel.d.ts +101 -0
- package/dist/lib-GQLPACFK.js +9746 -0
- package/dist/lib-GQLPACFK.js.map +1 -0
- package/dist/materializer-cli-entry.d.ts +2 -0
- package/dist/materializer-cli-entry.js +29 -0
- package/dist/materializer-cli-entry.js.map +1 -0
- package/dist/materializer-cli.d.ts +24 -0
- package/dist/materializer-cli.js +24 -0
- package/dist/materializer-cli.js.map +1 -0
- package/dist/native-raster.d.ts +10 -0
- package/dist/native.d.ts +129 -0
- package/dist/native.js +31 -0
- package/dist/native.js.map +1 -0
- package/dist/office-import.d.ts +48 -0
- package/dist/office-import.js +154 -0
- package/dist/office-import.js.map +1 -0
- package/dist/presentation-pptx-api.d.ts +60 -0
- package/dist/presentation-pptx-import.d.ts +5 -0
- package/dist/presentation-pptx-state-digest-765CZZED.js +10 -0
- package/dist/presentation-pptx-state-digest-765CZZED.js.map +1 -0
- package/dist/presentation-pptx-state-digest.d.ts +3 -0
- package/dist/presentation-pptx-state.d.ts +4 -0
- package/dist/presentation-pptx-xml.d.ts +29 -0
- package/dist/presentation-pptx.d.ts +5 -0
- package/dist/presentation-pptx.js +2365 -0
- package/dist/presentation-pptx.js.map +1 -0
- package/dist/presentation-render.d.ts +29 -0
- package/dist/presentation-render.js +375 -0
- package/dist/presentation-render.js.map +1 -0
- package/dist/presentation.d.ts +565 -0
- package/dist/presentation.js +71 -0
- package/dist/presentation.js.map +1 -0
- package/dist/production-composite.d.ts +68 -0
- package/dist/production-document.d.ts +2 -0
- package/dist/production-document.js +176 -0
- package/dist/production-document.js.map +1 -0
- package/dist/production-native-codecs.d.ts +94 -0
- package/dist/production-presentation.d.ts +2 -0
- package/dist/production-presentation.js +176 -0
- package/dist/production-presentation.js.map +1 -0
- package/dist/production-sha256.d.ts +2 -0
- package/dist/production-spreadsheet-native.d.ts +12 -0
- package/dist/production-spreadsheet.d.ts +2 -0
- package/dist/production-spreadsheet.js +176 -0
- package/dist/production-spreadsheet.js.map +1 -0
- package/dist/production.d.ts +96 -0
- package/dist/raster-image.d.ts +34 -0
- package/dist/reference.d.ts +17 -0
- package/dist/reference.js +574 -0
- package/dist/reference.js.map +1 -0
- package/dist/runtime-cli-entry.d.ts +2 -0
- package/dist/runtime-cli-entry.js +21 -0
- package/dist/runtime-cli-entry.js.map +1 -0
- package/dist/runtime-cli.d.ts +76 -0
- package/dist/runtime-cli.js +26 -0
- package/dist/runtime-cli.js.map +1 -0
- package/dist/runtime-development.d.ts +73 -0
- package/dist/runtime-development.js +30 -0
- package/dist/runtime-development.js.map +1 -0
- package/dist/runtime-receipt.d.ts +19 -0
- package/dist/runtime.d.ts +355 -0
- package/dist/runtime.js +42 -0
- package/dist/runtime.js.map +1 -0
- package/dist/snapshot.d.ts +26 -0
- package/dist/snapshot.js +61 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/spreadsheet-address.d.ts +18 -0
- package/dist/spreadsheet-file.d.ts +17 -0
- package/dist/spreadsheet-formula.d.ts +67 -0
- package/dist/spreadsheet-image.d.ts +17 -0
- package/dist/spreadsheet-render.d.ts +5 -0
- package/dist/spreadsheet-render.js +752 -0
- package/dist/spreadsheet-render.js.map +1 -0
- package/dist/spreadsheet-types.d.ts +155 -0
- package/dist/spreadsheet-xlsx-api.d.ts +88 -0
- package/dist/spreadsheet-xlsx-codec.d.ts +16 -0
- package/dist/spreadsheet-xlsx-codec.js +16 -0
- package/dist/spreadsheet-xlsx-codec.js.map +1 -0
- package/dist/spreadsheet-xlsx-state.d.ts +16 -0
- package/dist/spreadsheet.d.ts +724 -0
- package/dist/spreadsheet.js +67 -0
- package/dist/spreadsheet.js.map +1 -0
- package/package.json +129 -0
- package/src/bounded-zip.ts +450 -0
- package/src/document-docx-api.ts +64 -0
- package/src/document-docx-codec.ts +2253 -0
- package/src/document-docx-import.ts +3814 -0
- package/src/document-docx-packer.ts +72 -0
- package/src/document-docx-state.ts +59 -0
- package/src/document-render.ts +615 -0
- package/src/document.ts +2800 -0
- package/src/errors.ts +45 -0
- package/src/file-blob.ts +43 -0
- package/src/index.ts +4 -0
- package/src/inspection.ts +50 -0
- package/src/kernel.ts +525 -0
- package/src/materializer-cli-entry.ts +11 -0
- package/src/materializer-cli.ts +743 -0
- package/src/native-raster.ts +141 -0
- package/src/native.ts +390 -0
- package/src/office-import.ts +243 -0
- package/src/presentation-pptx-api.ts +107 -0
- package/src/presentation-pptx-import.ts +2065 -0
- package/src/presentation-pptx-state-digest.ts +46 -0
- package/src/presentation-pptx-state.ts +18 -0
- package/src/presentation-pptx-xml.ts +473 -0
- package/src/presentation-pptx.ts +447 -0
- package/src/presentation-render.ts +532 -0
- package/src/presentation.ts +2599 -0
- package/src/production-composite.ts +805 -0
- package/src/production-document.ts +2 -0
- package/src/production-native-codecs.ts +1141 -0
- package/src/production-presentation.ts +2 -0
- package/src/production-sha256.ts +150 -0
- package/src/production-spreadsheet-native.ts +686 -0
- package/src/production-spreadsheet.ts +2 -0
- package/src/production.ts +1022 -0
- package/src/raster-image.ts +586 -0
- package/src/reference.ts +17 -0
- package/src/runtime-cli-entry.ts +13 -0
- package/src/runtime-cli.ts +670 -0
- package/src/runtime-development.ts +689 -0
- package/src/runtime-receipt.ts +169 -0
- package/src/runtime.ts +1463 -0
- package/src/snapshot.ts +88 -0
- package/src/spreadsheet-address.ts +90 -0
- package/src/spreadsheet-file.ts +71 -0
- package/src/spreadsheet-formula.ts +1212 -0
- package/src/spreadsheet-image.ts +242 -0
- package/src/spreadsheet-render.ts +985 -0
- package/src/spreadsheet-types.ts +171 -0
- package/src/spreadsheet-xlsx-api.ts +123 -0
- package/src/spreadsheet-xlsx-codec.ts +3063 -0
- package/src/spreadsheet-xlsx-state.ts +191 -0
- package/src/spreadsheet.ts +5195 -0
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
import {
|
|
2
|
+
rasterizeSvgToPng
|
|
3
|
+
} from "./chunk-XIFUNVBO.js";
|
|
4
|
+
import {
|
|
5
|
+
Document,
|
|
6
|
+
DocumentPageBreak,
|
|
7
|
+
DocumentParagraph,
|
|
8
|
+
DocumentTable
|
|
9
|
+
} from "./chunk-66CT2ZRP.js";
|
|
10
|
+
import {
|
|
11
|
+
ArtifactLimitError
|
|
12
|
+
} from "./chunk-O24KTEGP.js";
|
|
13
|
+
import {
|
|
14
|
+
FileBlob
|
|
15
|
+
} from "./chunk-4BSENMAE.js";
|
|
16
|
+
import "./chunk-Q2FFHEY7.js";
|
|
17
|
+
import "./chunk-VUNV25KB.js";
|
|
18
|
+
|
|
19
|
+
// src/document-render.ts
|
|
20
|
+
var MAX_RASTER_DIMENSION = 32768;
|
|
21
|
+
var MAX_RASTER_PIXELS = 128e6;
|
|
22
|
+
var MAX_RASTER_GLYPHS = 5e4;
|
|
23
|
+
var MAX_RASTER_TEXT_RUNS = 25e3;
|
|
24
|
+
async function renderDocument(document, options = {}) {
|
|
25
|
+
if (!(document instanceof Document)) throw new Error("Document renderer requires a Document");
|
|
26
|
+
validateRenderOptions(options);
|
|
27
|
+
const format = options.format ?? "png";
|
|
28
|
+
if (format === "html") return new FileBlob([renderHtml(document)], { type: "text/html" });
|
|
29
|
+
if (format === "png") {
|
|
30
|
+
validateRasterBudget(measureCanvas(document), options.scale ?? 1);
|
|
31
|
+
validateRasterComplexity(document);
|
|
32
|
+
}
|
|
33
|
+
const svg = renderSvg(document, options);
|
|
34
|
+
if (format === "svg") return new FileBlob([svg], { type: "image/svg+xml" });
|
|
35
|
+
return FileBlob.fromBytes(await rasterizeSvgToPng(svg), {
|
|
36
|
+
type: "image/png"
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function projectPages(document) {
|
|
40
|
+
const pages = [];
|
|
41
|
+
let pageNumber = 1;
|
|
42
|
+
for (let sectionIndex = 0; sectionIndex < document.sections.items.length; sectionIndex += 1) {
|
|
43
|
+
const section = document.sections.items[sectionIndex];
|
|
44
|
+
const end = document.sections.items[sectionIndex + 1]?.startBlockIndex ?? document.blocks.items.length;
|
|
45
|
+
const chunks = [[]];
|
|
46
|
+
for (const block of document.blocks.items.slice(section.startBlockIndex, end)) {
|
|
47
|
+
if (block instanceof DocumentPageBreak) chunks.push([]);
|
|
48
|
+
else {
|
|
49
|
+
if (block instanceof DocumentParagraph && block.style.pageBreakBefore && chunks[chunks.length - 1].length > 0)
|
|
50
|
+
chunks.push([]);
|
|
51
|
+
chunks[chunks.length - 1].push(block);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
for (let pageInSection = 0; pageInSection < chunks.length; pageInSection += 1) {
|
|
55
|
+
const variant = pageInSection === 0 && section.titlePage ? "first" : document.evenAndOddHeaders && pageNumber % 2 === 0 ? "even" : "default";
|
|
56
|
+
pages.push({
|
|
57
|
+
section,
|
|
58
|
+
pageNumber,
|
|
59
|
+
pageInSection,
|
|
60
|
+
blocks: chunks[pageInSection],
|
|
61
|
+
header: { variant, story: section.headers[variant] },
|
|
62
|
+
footer: { variant, story: section.footers[variant] }
|
|
63
|
+
});
|
|
64
|
+
pageNumber += 1;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return pages;
|
|
68
|
+
}
|
|
69
|
+
function renderHtml(document) {
|
|
70
|
+
const markers = buildListMarkers(document);
|
|
71
|
+
const reviews = indexReviews(document);
|
|
72
|
+
const pages = projectPages(document).map((page) => {
|
|
73
|
+
const body = page.blocks.map((block) => htmlBlock(block, markers, reviews)).join("\n");
|
|
74
|
+
const header = page.header.story.items.map((block) => htmlBlock(block, markers, reviews)).join("\n");
|
|
75
|
+
const footer = page.footer.story.items.map((block) => htmlBlock(block, markers, reviews)).join("\n");
|
|
76
|
+
const geometry = page.section.page;
|
|
77
|
+
return `<section data-section-id="${escapeAttribute(page.section.id)}" data-page-number="${page.pageNumber}" data-section-page="${page.pageInSection + 1}" data-header-variant="${page.header.variant}" data-footer-variant="${page.footer.variant}" style="width:${geometry.widthPt}pt;min-height:${geometry.heightPt}pt;padding:${geometry.marginTopPt}pt ${geometry.marginRightPt}pt ${geometry.marginBottomPt}pt ${geometry.marginLeftPt}pt"><header data-story-id="${escapeAttribute(page.header.story.id)}" data-story-variant="${page.header.variant}">${header}</header><main>${body}</main><footer data-story-id="${escapeAttribute(page.footer.story.id)}" data-story-variant="${page.footer.variant}">${footer}</footer></section>`;
|
|
78
|
+
}).join("\n");
|
|
79
|
+
return `<!doctype html><html><head><meta charset="utf-8"><style>html{background:#e5e7eb}body{margin:0;color:#111827;font-family:Arial,sans-serif}section{box-sizing:border-box;display:flex;flex-direction:column;margin:16px auto;background:white}main{flex:1}table{border-collapse:collapse;table-layout:fixed}th,td{box-sizing:border-box;vertical-align:middle;text-align:left}p,h1,h2,h3,h4,h5,h6,th,td{white-space:pre-wrap;tab-size:4}p{line-height:1.35}header,footer{color:#4b5563}ins{text-decoration-color:#16a34a;text-decoration-thickness:2px}del{text-decoration-color:#dc2626;text-decoration-thickness:2px}mark[data-comment-ids]{background:#fef3c7;border-bottom:1px solid #d97706}.document-list-marker{display:inline-block;min-width:1.5em;color:#4b5563}</style></head><body>${pages}</body></html>`;
|
|
80
|
+
}
|
|
81
|
+
function htmlBlock(block, markers, reviews) {
|
|
82
|
+
if (block instanceof DocumentPageBreak) return "";
|
|
83
|
+
if (block instanceof DocumentTable) {
|
|
84
|
+
const border = color(block.style.borderColor ?? "#D1D5DB");
|
|
85
|
+
const padding = block.style.cellPaddingPt ?? 6;
|
|
86
|
+
const columns = block.style.columnWidthsPt ? `<colgroup>${block.style.columnWidthsPt.map((width) => `<col style="width:${width}pt">`).join("")}</colgroup>` : "";
|
|
87
|
+
const rows = block.rows.map((row, rowIndex) => {
|
|
88
|
+
const header = rowIndex < (block.style.headerRows ?? 0);
|
|
89
|
+
const tag2 = header ? "th" : "td";
|
|
90
|
+
return `<tr>${row.map((cell) => {
|
|
91
|
+
const style = [
|
|
92
|
+
`border:1px solid ${border}`,
|
|
93
|
+
`padding:${padding}pt`,
|
|
94
|
+
header && block.style.headerFill ? `background:${color(block.style.headerFill)}` : ""
|
|
95
|
+
].filter(Boolean).join(";");
|
|
96
|
+
const content = cell.map(
|
|
97
|
+
(run) => `<span style="${escapeAttribute(runCss(run.style))}">${escapeText(run.text)}</span>`
|
|
98
|
+
).join("");
|
|
99
|
+
return `<${tag2} style="${escapeAttribute(style)}">${content}</${tag2}>`;
|
|
100
|
+
}).join("")}</tr>`;
|
|
101
|
+
}).join("");
|
|
102
|
+
return `<table style="${escapeAttribute(tableCss(block.style))}">${columns}${rows}</table>`;
|
|
103
|
+
}
|
|
104
|
+
const tag = block.style.headingLevel ? `h${block.style.headingLevel}` : "p";
|
|
105
|
+
const marker = block.style.list ? `<span class="document-list-marker" aria-hidden="true">${escapeText(markers.get(block.id) ?? "")}</span>` : "";
|
|
106
|
+
return `<${tag} data-block-id="${escapeAttribute(block.id)}" style="${escapeAttribute(paragraphCss(block.style))}">${marker}${reviewedParagraphHtml(block, reviews)}</${tag}>`;
|
|
107
|
+
}
|
|
108
|
+
function indexReviews(document) {
|
|
109
|
+
const comments = /* @__PURE__ */ new Map();
|
|
110
|
+
const changes = /* @__PURE__ */ new Map();
|
|
111
|
+
for (const item of document.comments.items) append(comments, item.blockId, item);
|
|
112
|
+
for (const item of document.changes.items) append(changes, item.blockId, item);
|
|
113
|
+
return { comments, changes };
|
|
114
|
+
}
|
|
115
|
+
function reviewedParagraphHtml(block, reviews) {
|
|
116
|
+
const comments = reviews.comments.get(block.id) ?? [];
|
|
117
|
+
const changes = reviews.changes.get(block.id) ?? [];
|
|
118
|
+
const boundaries = /* @__PURE__ */ new Set([0, block.text.length]);
|
|
119
|
+
const spans = [];
|
|
120
|
+
const points = /* @__PURE__ */ new Map();
|
|
121
|
+
const commentStarts = /* @__PURE__ */ new Map();
|
|
122
|
+
const commentEnds = /* @__PURE__ */ new Map();
|
|
123
|
+
const changeStarts = /* @__PURE__ */ new Map();
|
|
124
|
+
const changeEnds = /* @__PURE__ */ new Map();
|
|
125
|
+
let offset = 0;
|
|
126
|
+
for (const run of block.runs) {
|
|
127
|
+
const start = offset;
|
|
128
|
+
offset += run.text.length;
|
|
129
|
+
spans.push({ start, end: offset, run });
|
|
130
|
+
boundaries.add(start);
|
|
131
|
+
boundaries.add(offset);
|
|
132
|
+
}
|
|
133
|
+
for (const comment of comments) {
|
|
134
|
+
boundaries.add(comment.start);
|
|
135
|
+
boundaries.add(comment.end);
|
|
136
|
+
if (comment.start === comment.end) append(points, comment.start, comment);
|
|
137
|
+
else {
|
|
138
|
+
append(commentStarts, comment.start, comment);
|
|
139
|
+
append(commentEnds, comment.end, comment);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
for (const change of changes) {
|
|
143
|
+
boundaries.add(change.start);
|
|
144
|
+
boundaries.add(change.end);
|
|
145
|
+
append(changeStarts, change.start, change);
|
|
146
|
+
append(changeEnds, change.end, change);
|
|
147
|
+
}
|
|
148
|
+
const ordered = [...boundaries].sort((left, right) => left - right);
|
|
149
|
+
const html = [];
|
|
150
|
+
const activeComments = /* @__PURE__ */ new Set();
|
|
151
|
+
const activeChanges = /* @__PURE__ */ new Set();
|
|
152
|
+
let spanIndex = 0;
|
|
153
|
+
for (let index = 0; index < ordered.length; index += 1) {
|
|
154
|
+
const start = ordered[index];
|
|
155
|
+
for (const item of commentEnds.get(start) ?? []) activeComments.delete(item);
|
|
156
|
+
for (const item of changeEnds.get(start) ?? []) activeChanges.delete(item);
|
|
157
|
+
for (const item of commentStarts.get(start) ?? []) activeComments.add(item);
|
|
158
|
+
for (const item of changeStarts.get(start) ?? []) activeChanges.add(item);
|
|
159
|
+
for (const item of points.get(start) ?? []) {
|
|
160
|
+
html.push(
|
|
161
|
+
`<span data-comment-anchor="${escapeAttribute(item.id)}" aria-label="Comment anchor"></span>`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
if (index === ordered.length - 1) break;
|
|
165
|
+
const end = ordered[index + 1];
|
|
166
|
+
while (spans[spanIndex] && spans[spanIndex].end <= start) spanIndex += 1;
|
|
167
|
+
const span = spans[spanIndex];
|
|
168
|
+
if (!span) throw new Error(`Document paragraph ${block.id} has a discontinuous run map`);
|
|
169
|
+
if (activeChanges.size > 1)
|
|
170
|
+
throw new Error(`Document paragraph ${block.id} has overlapping tracked changes`);
|
|
171
|
+
let segment = `<span style="${escapeAttribute(runCss(span.run.style))}">${escapeText(span.run.text.slice(start - span.start, end - span.start))}</span>`;
|
|
172
|
+
const change = activeChanges.values().next().value;
|
|
173
|
+
if (change) {
|
|
174
|
+
const tag = change.kind === "insert" ? "ins" : "del";
|
|
175
|
+
segment = `<${tag} data-change-id="${escapeAttribute(change.id)}">${segment}</${tag}>`;
|
|
176
|
+
}
|
|
177
|
+
if (activeComments.size > 0) {
|
|
178
|
+
const ids = [...activeComments].map((item) => item.id).join(" ");
|
|
179
|
+
segment = `<mark data-comment-ids="${escapeAttribute(ids)}">${segment}</mark>`;
|
|
180
|
+
}
|
|
181
|
+
html.push(segment);
|
|
182
|
+
}
|
|
183
|
+
return html.join("");
|
|
184
|
+
}
|
|
185
|
+
function renderSvg(document, options) {
|
|
186
|
+
const scale = options.scale ?? 1;
|
|
187
|
+
const background = color(options.background ?? "#FFFFFF");
|
|
188
|
+
const pages = projectPages(document);
|
|
189
|
+
const width = Math.max(...pages.map((page) => page.section.page.widthPt * (4 / 3)));
|
|
190
|
+
const markers = buildListMarkers(document);
|
|
191
|
+
const gap = 24;
|
|
192
|
+
const elements = [];
|
|
193
|
+
let canvasY = 0;
|
|
194
|
+
for (const page of pages) {
|
|
195
|
+
const geometry = page.section.page;
|
|
196
|
+
const pageWidth = geometry.widthPt * (4 / 3);
|
|
197
|
+
const pageHeight = pageCanvasHeight(page);
|
|
198
|
+
const left = (width - pageWidth) / 2;
|
|
199
|
+
const contentX = left + geometry.marginLeftPt * (4 / 3);
|
|
200
|
+
const usableWidth = pageWidth - (geometry.marginLeftPt + geometry.marginRightPt) * (4 / 3);
|
|
201
|
+
elements.push(
|
|
202
|
+
`<g data-section-id="${escapeAttribute(page.section.id)}" data-page-number="${page.pageNumber}" data-section-page="${page.pageInSection + 1}"><rect x="${left}" y="${canvasY}" width="${pageWidth}" height="${pageHeight}" fill="${escapeAttribute(background)}"/>`
|
|
203
|
+
);
|
|
204
|
+
const header = svgBlocks(
|
|
205
|
+
page.header.story.items,
|
|
206
|
+
contentX,
|
|
207
|
+
canvasY + 8,
|
|
208
|
+
usableWidth,
|
|
209
|
+
markers,
|
|
210
|
+
"#4B5563"
|
|
211
|
+
);
|
|
212
|
+
elements.push(
|
|
213
|
+
`<g data-story-id="${escapeAttribute(page.header.story.id)}" data-story-variant="${page.header.variant}">${header.elements.join("")}</g>`
|
|
214
|
+
);
|
|
215
|
+
const body = svgBlocks(
|
|
216
|
+
page.blocks,
|
|
217
|
+
contentX,
|
|
218
|
+
canvasY + geometry.marginTopPt * (4 / 3),
|
|
219
|
+
usableWidth,
|
|
220
|
+
markers,
|
|
221
|
+
"#111827"
|
|
222
|
+
);
|
|
223
|
+
elements.push(`<g data-document-body="true">${body.elements.join("")}</g>`);
|
|
224
|
+
const footerHeight = estimateBlocks(page.footer.story.items);
|
|
225
|
+
const footer = svgBlocks(
|
|
226
|
+
page.footer.story.items,
|
|
227
|
+
contentX,
|
|
228
|
+
canvasY + pageHeight - geometry.marginBottomPt * (4 / 3) - footerHeight,
|
|
229
|
+
usableWidth,
|
|
230
|
+
markers,
|
|
231
|
+
"#4B5563"
|
|
232
|
+
);
|
|
233
|
+
elements.push(
|
|
234
|
+
`<g data-story-id="${escapeAttribute(page.footer.story.id)}" data-story-variant="${page.footer.variant}">${footer.elements.join("")}</g></g>`
|
|
235
|
+
);
|
|
236
|
+
canvasY += pageHeight + gap;
|
|
237
|
+
}
|
|
238
|
+
const height = Math.max(1, canvasY - gap);
|
|
239
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width * scale}" height="${height * scale}" viewBox="0 0 ${width} ${height}"><rect width="100%" height="100%" fill="${escapeAttribute(background)}"/>${elements.join("")}</svg>`;
|
|
240
|
+
}
|
|
241
|
+
function svgBlocks(blocks, x, initialY, usableWidth, markers, fallbackColor) {
|
|
242
|
+
const elements = [];
|
|
243
|
+
let y = initialY;
|
|
244
|
+
for (const block of blocks) {
|
|
245
|
+
if (block instanceof DocumentTable) {
|
|
246
|
+
const columns = block.rows[0]?.length ?? 1;
|
|
247
|
+
const totalWidth = block.style.widthPt !== void 0 ? block.style.widthPt * (4 / 3) : usableWidth;
|
|
248
|
+
const widths = block.style.columnWidthsPt?.map((value) => value * (4 / 3)) ?? Array.from({ length: columns }, () => totalWidth / columns);
|
|
249
|
+
const padding = (block.style.cellPaddingPt ?? 6) * (4 / 3);
|
|
250
|
+
block.rows.forEach((row, rowIndex) => {
|
|
251
|
+
const rowHeight = svgTableRowHeight(row, padding);
|
|
252
|
+
const maximumFontSize = row.reduce(
|
|
253
|
+
(maximum, cell) => cell.reduce(
|
|
254
|
+
(cellMaximum, run) => Math.max(cellMaximum, (run.style.fontSizePt ?? 10.5) * (4 / 3)),
|
|
255
|
+
maximum
|
|
256
|
+
),
|
|
257
|
+
14
|
|
258
|
+
);
|
|
259
|
+
let cellX = x;
|
|
260
|
+
row.forEach((cell, columnIndex) => {
|
|
261
|
+
const cellWidth = widths[columnIndex] ?? totalWidth / columns;
|
|
262
|
+
const header = rowIndex < (block.style.headerRows ?? 0);
|
|
263
|
+
const fill = header && block.style.headerFill ? color(block.style.headerFill) : "#FFFFFF";
|
|
264
|
+
const content = cell.map((run) => {
|
|
265
|
+
const decoration = [
|
|
266
|
+
run.style.underline ? "underline" : "",
|
|
267
|
+
run.style.strike ? "line-through" : ""
|
|
268
|
+
].filter(Boolean).join(" ");
|
|
269
|
+
return `<tspan font-family="${escapeAttribute(run.style.fontFamily ?? "Arial")}" font-size="${(run.style.fontSizePt ?? 10.5) * (4 / 3)}" font-weight="${run.style.bold || header ? 700 : 400}" font-style="${run.style.italic ? "italic" : "normal"}"${decoration ? ` text-decoration="${decoration}"` : ""} fill="${escapeAttribute(color(run.style.color ?? fallbackColor))}">${escapeText(run.text.replaceAll(" ", " ").replaceAll("\n", " "))}</tspan>`;
|
|
270
|
+
}).join("");
|
|
271
|
+
const baseline = y + (rowHeight - maximumFontSize) / 2 + maximumFontSize;
|
|
272
|
+
elements.push(
|
|
273
|
+
`<rect x="${cellX}" y="${y}" width="${cellWidth}" height="${rowHeight}" fill="${escapeAttribute(fill)}" stroke="${escapeAttribute(color(block.style.borderColor ?? "#D1D5DB"))}"/><text x="${cellX + padding}" y="${baseline}">${content}</text>`
|
|
274
|
+
);
|
|
275
|
+
cellX += cellWidth;
|
|
276
|
+
});
|
|
277
|
+
y += rowHeight;
|
|
278
|
+
});
|
|
279
|
+
y += 16;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
const baseSize = block.style.headingLevel ? Math.max(18, 34 - block.style.headingLevel * 3) : 14;
|
|
283
|
+
const lines = svgLines(block, markers.get(block.id));
|
|
284
|
+
const maxSize = block.runs.reduce(
|
|
285
|
+
(maximum, run) => Math.max(maximum, (run.style.fontSizePt ?? baseSize * 0.75) * (4 / 3)),
|
|
286
|
+
baseSize
|
|
287
|
+
);
|
|
288
|
+
const lineHeight = maxSize * (block.style.lineHeight ?? 1.35);
|
|
289
|
+
const textX = block.style.alignment === "center" ? x + usableWidth / 2 : block.style.alignment === "right" ? x + usableWidth : x;
|
|
290
|
+
const textAnchor = block.style.alignment === "center" ? "middle" : block.style.alignment === "right" ? "end" : "start";
|
|
291
|
+
y += block.style.spaceBeforePt ?? 4;
|
|
292
|
+
for (const line of lines) {
|
|
293
|
+
y += maxSize;
|
|
294
|
+
const content = line.map(({ text, style }) => {
|
|
295
|
+
const size = (style.fontSizePt ?? baseSize * 0.75) * (4 / 3);
|
|
296
|
+
const decoration = [
|
|
297
|
+
style.underline ? "underline" : "",
|
|
298
|
+
style.strike ? "line-through" : ""
|
|
299
|
+
].filter(Boolean).join(" ");
|
|
300
|
+
return `<tspan font-family="${escapeAttribute(style.fontFamily ?? "Arial")}" font-size="${size}" font-weight="${style.bold || block.style.headingLevel ? 700 : 400}" font-style="${style.italic ? "italic" : "normal"}"${decoration ? ` text-decoration="${decoration}"` : ""} fill="${escapeAttribute(color(style.color ?? fallbackColor))}">${escapeText(text)}</tspan>`;
|
|
301
|
+
}).join("");
|
|
302
|
+
elements.push(`<text x="${textX}" y="${y}" text-anchor="${textAnchor}">${content}</text>`);
|
|
303
|
+
y += Math.max(0, lineHeight - maxSize);
|
|
304
|
+
}
|
|
305
|
+
y += block.style.spaceAfterPt ?? 8;
|
|
306
|
+
}
|
|
307
|
+
return { elements, bottom: y };
|
|
308
|
+
}
|
|
309
|
+
function svgLines(block, marker) {
|
|
310
|
+
const lines = [[]];
|
|
311
|
+
if (marker) lines[0].push({ text: `${marker} `, style: {} });
|
|
312
|
+
for (const run of block.runs) {
|
|
313
|
+
run.text.split("\n").forEach((chunk, index) => {
|
|
314
|
+
if (index > 0) lines.push([]);
|
|
315
|
+
if (chunk.length > 0)
|
|
316
|
+
lines.at(-1).push({ text: chunk.replaceAll(" ", " "), style: run.style });
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
return lines;
|
|
320
|
+
}
|
|
321
|
+
function buildListMarkers(document) {
|
|
322
|
+
const result = /* @__PURE__ */ new Map();
|
|
323
|
+
const visit = (blocks) => {
|
|
324
|
+
let activeKind;
|
|
325
|
+
const implicit = Array.from({ length: 9 }, () => 0);
|
|
326
|
+
const explicit = /* @__PURE__ */ new Map();
|
|
327
|
+
for (const block of blocks) {
|
|
328
|
+
if (!(block instanceof DocumentParagraph) || !block.style.list) {
|
|
329
|
+
activeKind = void 0;
|
|
330
|
+
implicit.fill(0);
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
const level = block.style.list.level ?? 0;
|
|
334
|
+
const id = block.style.list.instanceId;
|
|
335
|
+
let counters;
|
|
336
|
+
if (id) {
|
|
337
|
+
const key = `${block.style.list.kind}:${id}`;
|
|
338
|
+
counters = explicit.get(key) ?? Array.from({ length: 9 }, () => 0);
|
|
339
|
+
explicit.set(key, counters);
|
|
340
|
+
activeKind = void 0;
|
|
341
|
+
} else {
|
|
342
|
+
if (activeKind !== block.style.list.kind) implicit.fill(0);
|
|
343
|
+
activeKind = block.style.list.kind;
|
|
344
|
+
counters = implicit;
|
|
345
|
+
}
|
|
346
|
+
if (block.style.list.kind === "number") {
|
|
347
|
+
counters[level] = (counters[level] ?? 0) + 1;
|
|
348
|
+
for (let deeper = level + 1; deeper < counters.length; deeper += 1) counters[deeper] = 0;
|
|
349
|
+
result.set(block.id, `${counters[level]}.`);
|
|
350
|
+
} else result.set(block.id, ["\u2022", "\u25E6", "\u25AA"][level % 3]);
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
visit(document.blocks.items);
|
|
354
|
+
for (const section of document.sections.items)
|
|
355
|
+
for (const story of section.allStories()) visit(story.items);
|
|
356
|
+
return result;
|
|
357
|
+
}
|
|
358
|
+
function estimateBlocks(blocks) {
|
|
359
|
+
let height = 0;
|
|
360
|
+
for (const block of blocks) {
|
|
361
|
+
if (block instanceof DocumentTable) {
|
|
362
|
+
const padding = (block.style.cellPaddingPt ?? 6) * (4 / 3);
|
|
363
|
+
height += block.rows.reduce((sum, row) => sum + svgTableRowHeight(row, padding), 0) + 16;
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
const base = block.style.headingLevel ? Math.max(18, 34 - block.style.headingLevel * 3) : 14;
|
|
367
|
+
const size = block.runs.reduce(
|
|
368
|
+
(maximum, run) => Math.max(maximum, (run.style.fontSizePt ?? base * 0.75) * (4 / 3)),
|
|
369
|
+
base
|
|
370
|
+
);
|
|
371
|
+
height += (block.style.spaceBeforePt ?? 4) + size * (block.style.lineHeight ?? 1.35) * Math.max(1, block.text.split("\n").length) + (block.style.spaceAfterPt ?? 8);
|
|
372
|
+
}
|
|
373
|
+
return height;
|
|
374
|
+
}
|
|
375
|
+
function svgTableRowHeight(row, padding) {
|
|
376
|
+
const maximumFontSize = row.reduce(
|
|
377
|
+
(maximum, cell) => cell.reduce(
|
|
378
|
+
(cellMaximum, run) => Math.max(cellMaximum, (run.style.fontSizePt ?? 10.5) * (4 / 3)),
|
|
379
|
+
maximum
|
|
380
|
+
),
|
|
381
|
+
14
|
|
382
|
+
);
|
|
383
|
+
return Math.max(32, maximumFontSize * 1.2 + padding * 2);
|
|
384
|
+
}
|
|
385
|
+
function pageCanvasHeight(page) {
|
|
386
|
+
const physical = page.section.page.heightPt * (4 / 3);
|
|
387
|
+
const content = (page.section.page.marginTopPt + page.section.page.marginBottomPt) * (4 / 3) + estimateBlocks(page.blocks);
|
|
388
|
+
return Math.max(physical, content);
|
|
389
|
+
}
|
|
390
|
+
function measureCanvas(document) {
|
|
391
|
+
const pages = projectPages(document);
|
|
392
|
+
return {
|
|
393
|
+
width: Math.max(...pages.map((page) => page.section.page.widthPt * (4 / 3))),
|
|
394
|
+
height: Math.max(1, pages.reduce((sum, page) => sum + pageCanvasHeight(page) + 24, 0) - 24)
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function validateRasterBudget(dimensions, scale) {
|
|
398
|
+
const width = Math.ceil(dimensions.width * scale);
|
|
399
|
+
const height = Math.ceil(dimensions.height * scale);
|
|
400
|
+
const dimension = Math.max(width, height);
|
|
401
|
+
if (dimension > MAX_RASTER_DIMENSION) {
|
|
402
|
+
throw new ArtifactLimitError("document raster dimension", dimension, MAX_RASTER_DIMENSION);
|
|
403
|
+
}
|
|
404
|
+
const pixels = width * height;
|
|
405
|
+
if (!Number.isSafeInteger(pixels) || pixels > MAX_RASTER_PIXELS) {
|
|
406
|
+
throw new ArtifactLimitError("document raster pixels", pixels, MAX_RASTER_PIXELS);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
function validateRasterComplexity(document) {
|
|
410
|
+
let glyphs = 0;
|
|
411
|
+
let runs = 0;
|
|
412
|
+
for (const block of document.allStoryBlocks()) {
|
|
413
|
+
if (block instanceof DocumentPageBreak) continue;
|
|
414
|
+
if (block instanceof DocumentParagraph) {
|
|
415
|
+
glyphs += block.text.length;
|
|
416
|
+
runs += block.runs.length;
|
|
417
|
+
} else
|
|
418
|
+
for (const row of block.rows)
|
|
419
|
+
for (const cell of row)
|
|
420
|
+
for (const run of cell) {
|
|
421
|
+
glyphs += run.text.length;
|
|
422
|
+
runs += 1;
|
|
423
|
+
}
|
|
424
|
+
if (glyphs > MAX_RASTER_GLYPHS)
|
|
425
|
+
throw new ArtifactLimitError("document raster glyphs", glyphs, MAX_RASTER_GLYPHS);
|
|
426
|
+
if (runs > MAX_RASTER_TEXT_RUNS)
|
|
427
|
+
throw new ArtifactLimitError("document raster text runs", runs, MAX_RASTER_TEXT_RUNS);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
function paragraphCss(style) {
|
|
431
|
+
return [
|
|
432
|
+
style.alignment ? `text-align:${style.alignment}` : "",
|
|
433
|
+
style.spaceBeforePt !== void 0 ? `margin-top:${style.spaceBeforePt}pt` : "",
|
|
434
|
+
style.spaceAfterPt !== void 0 ? `margin-bottom:${style.spaceAfterPt}pt` : "",
|
|
435
|
+
style.lineHeight !== void 0 ? `line-height:${style.lineHeight}` : "",
|
|
436
|
+
style.keepNext ? "break-after:avoid" : "",
|
|
437
|
+
style.pageBreakBefore ? "break-before:page" : ""
|
|
438
|
+
].filter(Boolean).join(";");
|
|
439
|
+
}
|
|
440
|
+
function tableCss(style) {
|
|
441
|
+
return [
|
|
442
|
+
style.widthPt !== void 0 ? `width:${style.widthPt}pt` : "width:100%",
|
|
443
|
+
"table-layout:fixed",
|
|
444
|
+
style.allowRowSplit !== true ? "break-inside:avoid" : ""
|
|
445
|
+
].filter(Boolean).join(";");
|
|
446
|
+
}
|
|
447
|
+
function runCss(style) {
|
|
448
|
+
const decoration = [style.underline ? "underline" : "", style.strike ? "line-through" : ""].filter(Boolean).join(" ");
|
|
449
|
+
return [
|
|
450
|
+
`font-family:${style.fontFamily ?? "Arial"}`,
|
|
451
|
+
`font-size:${style.fontSizePt ?? 11}pt`,
|
|
452
|
+
`color:${color(style.color ?? "#111827")}`,
|
|
453
|
+
style.bold ? "font-weight:700" : "",
|
|
454
|
+
style.italic ? "font-style:italic" : "",
|
|
455
|
+
decoration ? `text-decoration:${decoration}` : ""
|
|
456
|
+
].filter(Boolean).join(";");
|
|
457
|
+
}
|
|
458
|
+
function validateRenderOptions(options) {
|
|
459
|
+
if (typeof options !== "object" || options === null || Array.isArray(options))
|
|
460
|
+
throw new Error("Document render options must be an object");
|
|
461
|
+
for (const key of Object.keys(options)) {
|
|
462
|
+
if (!["format", "scale", "background"].includes(key))
|
|
463
|
+
throw new Error(`Unknown document render options property: ${key}`);
|
|
464
|
+
const descriptor = Object.getOwnPropertyDescriptor(options, key);
|
|
465
|
+
if (!descriptor || !("value" in descriptor))
|
|
466
|
+
throw new Error("Document render options must contain plain data properties");
|
|
467
|
+
}
|
|
468
|
+
if (options.format !== void 0 && !["html", "svg", "png"].includes(options.format))
|
|
469
|
+
throw new Error(`Unsupported document render format: ${String(options.format)}`);
|
|
470
|
+
if (options.scale !== void 0 && (!Number.isFinite(options.scale) || options.scale < 0.1 || options.scale > 8))
|
|
471
|
+
throw new Error("document render scale must be between 0.1 and 8");
|
|
472
|
+
if (options.background !== void 0) color(options.background);
|
|
473
|
+
}
|
|
474
|
+
function append(map, key, value) {
|
|
475
|
+
const values = map.get(key);
|
|
476
|
+
if (values) values.push(value);
|
|
477
|
+
else map.set(key, [value]);
|
|
478
|
+
}
|
|
479
|
+
function color(value) {
|
|
480
|
+
if (!/^#?[0-9A-Fa-f]{6}$/.test(value)) throw new Error(`Invalid or unsafe color: ${value}`);
|
|
481
|
+
return `#${value.replace(/^#/, "").toUpperCase()}`;
|
|
482
|
+
}
|
|
483
|
+
function escapeText(value) {
|
|
484
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
485
|
+
}
|
|
486
|
+
function escapeAttribute(value) {
|
|
487
|
+
return escapeText(value).replaceAll('"', """).replaceAll("'", "'");
|
|
488
|
+
}
|
|
489
|
+
export {
|
|
490
|
+
renderDocument
|
|
491
|
+
};
|
|
492
|
+
//# sourceMappingURL=document-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/document-render.ts"],"sourcesContent":["import { ArtifactLimitError } from \"./errors\";\nimport { FileBlob } from \"./file-blob\";\nimport { rasterizeSvgToPng } from \"./native-raster\";\nimport {\n Document,\n DocumentPageBreak,\n DocumentParagraph,\n DocumentTable,\n type DocumentBlock,\n type DocumentCommentThread,\n type DocumentRenderOptions,\n type DocumentSection,\n type DocumentStory,\n type DocumentStoryBlock,\n type DocumentTableStyle,\n type DocumentTextRun,\n type DocumentTextStyle,\n type TrackedChange,\n} from \"./document\";\n\nconst MAX_RASTER_DIMENSION = 32_768;\nconst MAX_RASTER_PIXELS = 128_000_000;\nconst MAX_RASTER_GLYPHS = 50_000;\nconst MAX_RASTER_TEXT_RUNS = 25_000;\n\nexport async function renderDocument(\n document: Document,\n options: DocumentRenderOptions = {},\n): Promise<FileBlob> {\n if (!(document instanceof Document)) throw new Error(\"Document renderer requires a Document\");\n validateRenderOptions(options);\n const format = options.format ?? \"png\";\n if (format === \"html\") return new FileBlob([renderHtml(document)], { type: \"text/html\" });\n if (format === \"png\") {\n validateRasterBudget(measureCanvas(document), options.scale ?? 1);\n validateRasterComplexity(document);\n }\n const svg = renderSvg(document, options);\n if (format === \"svg\") return new FileBlob([svg], { type: \"image/svg+xml\" });\n return FileBlob.fromBytes(await rasterizeSvgToPng(svg), {\n type: \"image/png\",\n });\n}\n\ntype StoryVariant = \"default\" | \"first\" | \"even\";\ntype ProjectedPage = {\n section: DocumentSection;\n pageNumber: number;\n pageInSection: number;\n blocks: readonly (DocumentParagraph | DocumentTable)[];\n header: { variant: StoryVariant; story: DocumentStory };\n footer: { variant: StoryVariant; story: DocumentStory };\n};\n\nfunction projectPages(document: Document): ProjectedPage[] {\n const pages: ProjectedPage[] = [];\n let pageNumber = 1;\n for (let sectionIndex = 0; sectionIndex < document.sections.items.length; sectionIndex += 1) {\n const section = document.sections.items[sectionIndex]!;\n const end =\n document.sections.items[sectionIndex + 1]?.startBlockIndex ?? document.blocks.items.length;\n const chunks: Array<Array<DocumentParagraph | DocumentTable>> = [[]];\n for (const block of document.blocks.items.slice(section.startBlockIndex, end)) {\n if (block instanceof DocumentPageBreak) chunks.push([]);\n else {\n if (\n block instanceof DocumentParagraph &&\n block.style.pageBreakBefore &&\n chunks[chunks.length - 1]!.length > 0\n )\n chunks.push([]);\n chunks[chunks.length - 1]!.push(block);\n }\n }\n for (let pageInSection = 0; pageInSection < chunks.length; pageInSection += 1) {\n const variant: StoryVariant =\n pageInSection === 0 && section.titlePage\n ? \"first\"\n : document.evenAndOddHeaders && pageNumber % 2 === 0\n ? \"even\"\n : \"default\";\n pages.push({\n section,\n pageNumber,\n pageInSection,\n blocks: chunks[pageInSection]!,\n header: { variant, story: section.headers[variant] },\n footer: { variant, story: section.footers[variant] },\n });\n pageNumber += 1;\n }\n }\n return pages;\n}\n\nfunction renderHtml(document: Document): string {\n const markers = buildListMarkers(document);\n const reviews = indexReviews(document);\n const pages = projectPages(document)\n .map((page) => {\n const body = page.blocks.map((block) => htmlBlock(block, markers, reviews)).join(\"\\n\");\n const header = page.header.story.items\n .map((block) => htmlBlock(block, markers, reviews))\n .join(\"\\n\");\n const footer = page.footer.story.items\n .map((block) => htmlBlock(block, markers, reviews))\n .join(\"\\n\");\n const geometry = page.section.page;\n return `<section data-section-id=\"${escapeAttribute(page.section.id)}\" data-page-number=\"${page.pageNumber}\" data-section-page=\"${page.pageInSection + 1}\" data-header-variant=\"${page.header.variant}\" data-footer-variant=\"${page.footer.variant}\" style=\"width:${geometry.widthPt}pt;min-height:${geometry.heightPt}pt;padding:${geometry.marginTopPt}pt ${geometry.marginRightPt}pt ${geometry.marginBottomPt}pt ${geometry.marginLeftPt}pt\"><header data-story-id=\"${escapeAttribute(page.header.story.id)}\" data-story-variant=\"${page.header.variant}\">${header}</header><main>${body}</main><footer data-story-id=\"${escapeAttribute(page.footer.story.id)}\" data-story-variant=\"${page.footer.variant}\">${footer}</footer></section>`;\n })\n .join(\"\\n\");\n return `<!doctype html><html><head><meta charset=\"utf-8\"><style>html{background:#e5e7eb}body{margin:0;color:#111827;font-family:Arial,sans-serif}section{box-sizing:border-box;display:flex;flex-direction:column;margin:16px auto;background:white}main{flex:1}table{border-collapse:collapse;table-layout:fixed}th,td{box-sizing:border-box;vertical-align:middle;text-align:left}p,h1,h2,h3,h4,h5,h6,th,td{white-space:pre-wrap;tab-size:4}p{line-height:1.35}header,footer{color:#4b5563}ins{text-decoration-color:#16a34a;text-decoration-thickness:2px}del{text-decoration-color:#dc2626;text-decoration-thickness:2px}mark[data-comment-ids]{background:#fef3c7;border-bottom:1px solid #d97706}.document-list-marker{display:inline-block;min-width:1.5em;color:#4b5563}</style></head><body>${pages}</body></html>`;\n}\n\nfunction htmlBlock(\n block: DocumentBlock | DocumentStoryBlock,\n markers: ReadonlyMap<string, string>,\n reviews: ReviewIndex,\n): string {\n if (block instanceof DocumentPageBreak) return \"\";\n if (block instanceof DocumentTable) {\n const border = color(block.style.borderColor ?? \"#D1D5DB\");\n const padding = block.style.cellPaddingPt ?? 6;\n const columns = block.style.columnWidthsPt\n ? `<colgroup>${block.style.columnWidthsPt.map((width) => `<col style=\"width:${width}pt\">`).join(\"\")}</colgroup>`\n : \"\";\n const rows = block.rows\n .map((row, rowIndex) => {\n const header = rowIndex < (block.style.headerRows ?? 0);\n const tag = header ? \"th\" : \"td\";\n return `<tr>${row\n .map((cell) => {\n const style = [\n `border:1px solid ${border}`,\n `padding:${padding}pt`,\n header && block.style.headerFill ? `background:${color(block.style.headerFill)}` : \"\",\n ]\n .filter(Boolean)\n .join(\";\");\n const content = cell\n .map(\n (run) =>\n `<span style=\"${escapeAttribute(runCss(run.style))}\">${escapeText(run.text)}</span>`,\n )\n .join(\"\");\n return `<${tag} style=\"${escapeAttribute(style)}\">${content}</${tag}>`;\n })\n .join(\"\")}</tr>`;\n })\n .join(\"\");\n return `<table style=\"${escapeAttribute(tableCss(block.style))}\">${columns}${rows}</table>`;\n }\n const tag = block.style.headingLevel ? `h${block.style.headingLevel}` : \"p\";\n const marker = block.style.list\n ? `<span class=\"document-list-marker\" aria-hidden=\"true\">${escapeText(markers.get(block.id) ?? \"\")}</span>`\n : \"\";\n return `<${tag} data-block-id=\"${escapeAttribute(block.id)}\" style=\"${escapeAttribute(paragraphCss(block.style))}\">${marker}${reviewedParagraphHtml(block, reviews)}</${tag}>`;\n}\n\ntype ReviewIndex = {\n comments: ReadonlyMap<string, readonly DocumentCommentThread[]>;\n changes: ReadonlyMap<string, readonly TrackedChange[]>;\n};\n\nfunction indexReviews(document: Document): ReviewIndex {\n const comments = new Map<string, DocumentCommentThread[]>();\n const changes = new Map<string, TrackedChange[]>();\n for (const item of document.comments.items) append(comments, item.blockId, item);\n for (const item of document.changes.items) append(changes, item.blockId, item);\n return { comments, changes };\n}\n\nfunction reviewedParagraphHtml(block: DocumentParagraph, reviews: ReviewIndex): string {\n const comments = reviews.comments.get(block.id) ?? [];\n const changes = reviews.changes.get(block.id) ?? [];\n const boundaries = new Set<number>([0, block.text.length]);\n const spans: Array<{ start: number; end: number; run: DocumentTextRun }> = [];\n const points = new Map<number, DocumentCommentThread[]>();\n const commentStarts = new Map<number, DocumentCommentThread[]>();\n const commentEnds = new Map<number, DocumentCommentThread[]>();\n const changeStarts = new Map<number, TrackedChange[]>();\n const changeEnds = new Map<number, TrackedChange[]>();\n let offset = 0;\n for (const run of block.runs) {\n const start = offset;\n offset += run.text.length;\n spans.push({ start, end: offset, run });\n boundaries.add(start);\n boundaries.add(offset);\n }\n for (const comment of comments) {\n boundaries.add(comment.start);\n boundaries.add(comment.end);\n if (comment.start === comment.end) append(points, comment.start, comment);\n else {\n append(commentStarts, comment.start, comment);\n append(commentEnds, comment.end, comment);\n }\n }\n for (const change of changes) {\n boundaries.add(change.start);\n boundaries.add(change.end);\n append(changeStarts, change.start, change);\n append(changeEnds, change.end, change);\n }\n const ordered = [...boundaries].sort((left, right) => left - right);\n const html: string[] = [];\n const activeComments = new Set<DocumentCommentThread>();\n const activeChanges = new Set<TrackedChange>();\n let spanIndex = 0;\n for (let index = 0; index < ordered.length; index += 1) {\n const start = ordered[index]!;\n for (const item of commentEnds.get(start) ?? []) activeComments.delete(item);\n for (const item of changeEnds.get(start) ?? []) activeChanges.delete(item);\n for (const item of commentStarts.get(start) ?? []) activeComments.add(item);\n for (const item of changeStarts.get(start) ?? []) activeChanges.add(item);\n for (const item of points.get(start) ?? []) {\n html.push(\n `<span data-comment-anchor=\"${escapeAttribute(item.id)}\" aria-label=\"Comment anchor\"></span>`,\n );\n }\n if (index === ordered.length - 1) break;\n const end = ordered[index + 1]!;\n while (spans[spanIndex] && spans[spanIndex]!.end <= start) spanIndex += 1;\n const span = spans[spanIndex];\n if (!span) throw new Error(`Document paragraph ${block.id} has a discontinuous run map`);\n if (activeChanges.size > 1)\n throw new Error(`Document paragraph ${block.id} has overlapping tracked changes`);\n let segment = `<span style=\"${escapeAttribute(runCss(span.run.style))}\">${escapeText(span.run.text.slice(start - span.start, end - span.start))}</span>`;\n const change = activeChanges.values().next().value as TrackedChange | undefined;\n if (change) {\n const tag = change.kind === \"insert\" ? \"ins\" : \"del\";\n segment = `<${tag} data-change-id=\"${escapeAttribute(change.id)}\">${segment}</${tag}>`;\n }\n if (activeComments.size > 0) {\n const ids = [...activeComments].map((item) => item.id).join(\" \");\n segment = `<mark data-comment-ids=\"${escapeAttribute(ids)}\">${segment}</mark>`;\n }\n html.push(segment);\n }\n return html.join(\"\");\n}\n\nfunction renderSvg(document: Document, options: DocumentRenderOptions): string {\n const scale = options.scale ?? 1;\n const background = color(options.background ?? \"#FFFFFF\");\n const pages = projectPages(document);\n const width = Math.max(...pages.map((page) => page.section.page.widthPt * (4 / 3)));\n const markers = buildListMarkers(document);\n const gap = 24;\n const elements: string[] = [];\n let canvasY = 0;\n for (const page of pages) {\n const geometry = page.section.page;\n const pageWidth = geometry.widthPt * (4 / 3);\n const pageHeight = pageCanvasHeight(page);\n const left = (width - pageWidth) / 2;\n const contentX = left + geometry.marginLeftPt * (4 / 3);\n const usableWidth = pageWidth - (geometry.marginLeftPt + geometry.marginRightPt) * (4 / 3);\n elements.push(\n `<g data-section-id=\"${escapeAttribute(page.section.id)}\" data-page-number=\"${page.pageNumber}\" data-section-page=\"${page.pageInSection + 1}\"><rect x=\"${left}\" y=\"${canvasY}\" width=\"${pageWidth}\" height=\"${pageHeight}\" fill=\"${escapeAttribute(background)}\"/>`,\n );\n const header = svgBlocks(\n page.header.story.items,\n contentX,\n canvasY + 8,\n usableWidth,\n markers,\n \"#4B5563\",\n );\n elements.push(\n `<g data-story-id=\"${escapeAttribute(page.header.story.id)}\" data-story-variant=\"${page.header.variant}\">${header.elements.join(\"\")}</g>`,\n );\n const body = svgBlocks(\n page.blocks,\n contentX,\n canvasY + geometry.marginTopPt * (4 / 3),\n usableWidth,\n markers,\n \"#111827\",\n );\n elements.push(`<g data-document-body=\"true\">${body.elements.join(\"\")}</g>`);\n const footerHeight = estimateBlocks(page.footer.story.items);\n const footer = svgBlocks(\n page.footer.story.items,\n contentX,\n canvasY + pageHeight - geometry.marginBottomPt * (4 / 3) - footerHeight,\n usableWidth,\n markers,\n \"#4B5563\",\n );\n elements.push(\n `<g data-story-id=\"${escapeAttribute(page.footer.story.id)}\" data-story-variant=\"${page.footer.variant}\">${footer.elements.join(\"\")}</g></g>`,\n );\n canvasY += pageHeight + gap;\n }\n const height = Math.max(1, canvasY - gap);\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width * scale}\" height=\"${height * scale}\" viewBox=\"0 0 ${width} ${height}\"><rect width=\"100%\" height=\"100%\" fill=\"${escapeAttribute(background)}\"/>${elements.join(\"\")}</svg>`;\n}\n\nfunction svgBlocks(\n blocks: readonly (DocumentParagraph | DocumentTable)[],\n x: number,\n initialY: number,\n usableWidth: number,\n markers: ReadonlyMap<string, string>,\n fallbackColor: string,\n): { elements: string[]; bottom: number } {\n const elements: string[] = [];\n let y = initialY;\n for (const block of blocks) {\n if (block instanceof DocumentTable) {\n const columns = block.rows[0]?.length ?? 1;\n const totalWidth =\n block.style.widthPt !== undefined ? block.style.widthPt * (4 / 3) : usableWidth;\n const widths =\n block.style.columnWidthsPt?.map((value) => value * (4 / 3)) ??\n Array.from({ length: columns }, () => totalWidth / columns);\n const padding = (block.style.cellPaddingPt ?? 6) * (4 / 3);\n block.rows.forEach((row, rowIndex) => {\n const rowHeight = svgTableRowHeight(row, padding);\n const maximumFontSize = row.reduce(\n (maximum, cell) =>\n cell.reduce(\n (cellMaximum, run) => Math.max(cellMaximum, (run.style.fontSizePt ?? 10.5) * (4 / 3)),\n maximum,\n ),\n 14,\n );\n let cellX = x;\n row.forEach((cell, columnIndex) => {\n const cellWidth = widths[columnIndex] ?? totalWidth / columns;\n const header = rowIndex < (block.style.headerRows ?? 0);\n const fill = header && block.style.headerFill ? color(block.style.headerFill) : \"#FFFFFF\";\n const content = cell\n .map((run) => {\n const decoration = [\n run.style.underline ? \"underline\" : \"\",\n run.style.strike ? \"line-through\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n return `<tspan font-family=\"${escapeAttribute(run.style.fontFamily ?? \"Arial\")}\" font-size=\"${(run.style.fontSizePt ?? 10.5) * (4 / 3)}\" font-weight=\"${run.style.bold || header ? 700 : 400}\" font-style=\"${run.style.italic ? \"italic\" : \"normal\"}\"${decoration ? ` text-decoration=\"${decoration}\"` : \"\"} fill=\"${escapeAttribute(color(run.style.color ?? fallbackColor))}\">${escapeText(run.text.replaceAll(\"\\t\", \" \").replaceAll(\"\\n\", \" \"))}</tspan>`;\n })\n .join(\"\");\n const baseline = y + (rowHeight - maximumFontSize) / 2 + maximumFontSize;\n elements.push(\n `<rect x=\"${cellX}\" y=\"${y}\" width=\"${cellWidth}\" height=\"${rowHeight}\" fill=\"${escapeAttribute(fill)}\" stroke=\"${escapeAttribute(color(block.style.borderColor ?? \"#D1D5DB\"))}\"/><text x=\"${cellX + padding}\" y=\"${baseline}\">${content}</text>`,\n );\n cellX += cellWidth;\n });\n y += rowHeight;\n });\n y += 16;\n continue;\n }\n const baseSize = block.style.headingLevel\n ? Math.max(18, 34 - block.style.headingLevel * 3)\n : 14;\n const lines = svgLines(block, markers.get(block.id));\n const maxSize = block.runs.reduce(\n (maximum, run) => Math.max(maximum, (run.style.fontSizePt ?? baseSize * 0.75) * (4 / 3)),\n baseSize,\n );\n const lineHeight = maxSize * (block.style.lineHeight ?? 1.35);\n const textX =\n block.style.alignment === \"center\"\n ? x + usableWidth / 2\n : block.style.alignment === \"right\"\n ? x + usableWidth\n : x;\n const textAnchor =\n block.style.alignment === \"center\"\n ? \"middle\"\n : block.style.alignment === \"right\"\n ? \"end\"\n : \"start\";\n y += block.style.spaceBeforePt ?? 4;\n for (const line of lines) {\n y += maxSize;\n const content = line\n .map(({ text, style }) => {\n const size = (style.fontSizePt ?? baseSize * 0.75) * (4 / 3);\n const decoration = [\n style.underline ? \"underline\" : \"\",\n style.strike ? \"line-through\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n return `<tspan font-family=\"${escapeAttribute(style.fontFamily ?? \"Arial\")}\" font-size=\"${size}\" font-weight=\"${style.bold || block.style.headingLevel ? 700 : 400}\" font-style=\"${style.italic ? \"italic\" : \"normal\"}\"${decoration ? ` text-decoration=\"${decoration}\"` : \"\"} fill=\"${escapeAttribute(color(style.color ?? fallbackColor))}\">${escapeText(text)}</tspan>`;\n })\n .join(\"\");\n elements.push(`<text x=\"${textX}\" y=\"${y}\" text-anchor=\"${textAnchor}\">${content}</text>`);\n y += Math.max(0, lineHeight - maxSize);\n }\n y += block.style.spaceAfterPt ?? 8;\n }\n return { elements, bottom: y };\n}\n\nfunction svgLines(\n block: DocumentParagraph,\n marker: string | undefined,\n): Array<Array<{ text: string; style: DocumentTextStyle }>> {\n const lines: Array<Array<{ text: string; style: DocumentTextStyle }>> = [[]];\n if (marker) lines[0]!.push({ text: `${marker} `, style: {} });\n for (const run of block.runs) {\n run.text.split(\"\\n\").forEach((chunk, index) => {\n if (index > 0) lines.push([]);\n if (chunk.length > 0)\n lines.at(-1)!.push({ text: chunk.replaceAll(\"\\t\", \" \"), style: run.style });\n });\n }\n return lines;\n}\n\nfunction buildListMarkers(document: Document): Map<string, string> {\n const result = new Map<string, string>();\n const visit = (blocks: readonly (DocumentBlock | DocumentStoryBlock)[]): void => {\n let activeKind: \"bullet\" | \"number\" | undefined;\n const implicit = Array.from({ length: 9 }, () => 0);\n const explicit = new Map<string, number[]>();\n for (const block of blocks) {\n if (!(block instanceof DocumentParagraph) || !block.style.list) {\n activeKind = undefined;\n implicit.fill(0);\n continue;\n }\n const level = block.style.list.level ?? 0;\n const id = block.style.list.instanceId;\n let counters: number[];\n if (id) {\n const key = `${block.style.list.kind}:${id}`;\n counters = explicit.get(key) ?? Array.from({ length: 9 }, () => 0);\n explicit.set(key, counters);\n activeKind = undefined;\n } else {\n if (activeKind !== block.style.list.kind) implicit.fill(0);\n activeKind = block.style.list.kind;\n counters = implicit;\n }\n if (block.style.list.kind === \"number\") {\n counters[level] = (counters[level] ?? 0) + 1;\n for (let deeper = level + 1; deeper < counters.length; deeper += 1) counters[deeper] = 0;\n result.set(block.id, `${counters[level]}.`);\n } else result.set(block.id, [\"•\", \"◦\", \"▪\"][level % 3]!);\n }\n };\n visit(document.blocks.items);\n for (const section of document.sections.items)\n for (const story of section.allStories()) visit(story.items);\n return result;\n}\n\nfunction estimateBlocks(blocks: readonly (DocumentParagraph | DocumentTable)[]): number {\n let height = 0;\n for (const block of blocks) {\n if (block instanceof DocumentTable) {\n const padding = (block.style.cellPaddingPt ?? 6) * (4 / 3);\n height += block.rows.reduce((sum, row) => sum + svgTableRowHeight(row, padding), 0) + 16;\n continue;\n }\n const base = block.style.headingLevel ? Math.max(18, 34 - block.style.headingLevel * 3) : 14;\n const size = block.runs.reduce(\n (maximum, run) => Math.max(maximum, (run.style.fontSizePt ?? base * 0.75) * (4 / 3)),\n base,\n );\n height +=\n (block.style.spaceBeforePt ?? 4) +\n size * (block.style.lineHeight ?? 1.35) * Math.max(1, block.text.split(\"\\n\").length) +\n (block.style.spaceAfterPt ?? 8);\n }\n return height;\n}\n\nfunction svgTableRowHeight(row: readonly (readonly DocumentTextRun[])[], padding: number): number {\n const maximumFontSize = row.reduce(\n (maximum, cell) =>\n cell.reduce(\n (cellMaximum, run) => Math.max(cellMaximum, (run.style.fontSizePt ?? 10.5) * (4 / 3)),\n maximum,\n ),\n 14,\n );\n return Math.max(32, maximumFontSize * 1.2 + padding * 2);\n}\n\nfunction pageCanvasHeight(page: ProjectedPage): number {\n const physical = page.section.page.heightPt * (4 / 3);\n const content =\n (page.section.page.marginTopPt + page.section.page.marginBottomPt) * (4 / 3) +\n estimateBlocks(page.blocks);\n return Math.max(physical, content);\n}\n\nfunction measureCanvas(document: Document): { width: number; height: number } {\n const pages = projectPages(document);\n return {\n width: Math.max(...pages.map((page) => page.section.page.widthPt * (4 / 3))),\n height: Math.max(1, pages.reduce((sum, page) => sum + pageCanvasHeight(page) + 24, 0) - 24),\n };\n}\n\nfunction validateRasterBudget(dimensions: { width: number; height: number }, scale: number): void {\n const width = Math.ceil(dimensions.width * scale);\n const height = Math.ceil(dimensions.height * scale);\n const dimension = Math.max(width, height);\n if (dimension > MAX_RASTER_DIMENSION) {\n throw new ArtifactLimitError(\"document raster dimension\", dimension, MAX_RASTER_DIMENSION);\n }\n const pixels = width * height;\n if (!Number.isSafeInteger(pixels) || pixels > MAX_RASTER_PIXELS) {\n throw new ArtifactLimitError(\"document raster pixels\", pixels, MAX_RASTER_PIXELS);\n }\n}\n\nfunction validateRasterComplexity(document: Document): void {\n let glyphs = 0;\n let runs = 0;\n for (const block of document.allStoryBlocks()) {\n if (block instanceof DocumentPageBreak) continue;\n if (block instanceof DocumentParagraph) {\n glyphs += block.text.length;\n runs += block.runs.length;\n } else\n for (const row of block.rows)\n for (const cell of row)\n for (const run of cell) {\n glyphs += run.text.length;\n runs += 1;\n }\n if (glyphs > MAX_RASTER_GLYPHS)\n throw new ArtifactLimitError(\"document raster glyphs\", glyphs, MAX_RASTER_GLYPHS);\n if (runs > MAX_RASTER_TEXT_RUNS)\n throw new ArtifactLimitError(\"document raster text runs\", runs, MAX_RASTER_TEXT_RUNS);\n }\n}\n\nfunction paragraphCss(style: DocumentParagraph[\"style\"]): string {\n return [\n style.alignment ? `text-align:${style.alignment}` : \"\",\n style.spaceBeforePt !== undefined ? `margin-top:${style.spaceBeforePt}pt` : \"\",\n style.spaceAfterPt !== undefined ? `margin-bottom:${style.spaceAfterPt}pt` : \"\",\n style.lineHeight !== undefined ? `line-height:${style.lineHeight}` : \"\",\n style.keepNext ? \"break-after:avoid\" : \"\",\n style.pageBreakBefore ? \"break-before:page\" : \"\",\n ]\n .filter(Boolean)\n .join(\";\");\n}\n\nfunction tableCss(style: DocumentTableStyle): string {\n return [\n style.widthPt !== undefined ? `width:${style.widthPt}pt` : \"width:100%\",\n \"table-layout:fixed\",\n style.allowRowSplit !== true ? \"break-inside:avoid\" : \"\",\n ]\n .filter(Boolean)\n .join(\";\");\n}\n\nfunction runCss(style: DocumentTextStyle): string {\n const decoration = [style.underline ? \"underline\" : \"\", style.strike ? \"line-through\" : \"\"]\n .filter(Boolean)\n .join(\" \");\n return [\n `font-family:${style.fontFamily ?? \"Arial\"}`,\n `font-size:${style.fontSizePt ?? 11}pt`,\n `color:${color(style.color ?? \"#111827\")}`,\n style.bold ? \"font-weight:700\" : \"\",\n style.italic ? \"font-style:italic\" : \"\",\n decoration ? `text-decoration:${decoration}` : \"\",\n ]\n .filter(Boolean)\n .join(\";\");\n}\n\nfunction validateRenderOptions(options: DocumentRenderOptions): void {\n if (typeof options !== \"object\" || options === null || Array.isArray(options))\n throw new Error(\"Document render options must be an object\");\n for (const key of Object.keys(options)) {\n if (![\"format\", \"scale\", \"background\"].includes(key))\n throw new Error(`Unknown document render options property: ${key}`);\n const descriptor = Object.getOwnPropertyDescriptor(options, key);\n if (!descriptor || !(\"value\" in descriptor))\n throw new Error(\"Document render options must contain plain data properties\");\n }\n if (options.format !== undefined && ![\"html\", \"svg\", \"png\"].includes(options.format))\n throw new Error(`Unsupported document render format: ${String(options.format)}`);\n if (\n options.scale !== undefined &&\n (!Number.isFinite(options.scale) || options.scale < 0.1 || options.scale > 8)\n )\n throw new Error(\"document render scale must be between 0.1 and 8\");\n if (options.background !== undefined) color(options.background);\n}\n\nfunction append<K, T>(map: Map<K, T[]>, key: K, value: T): void {\n const values = map.get(key);\n if (values) values.push(value);\n else map.set(key, [value]);\n}\n\nfunction color(value: string): string {\n if (!/^#?[0-9A-Fa-f]{6}$/.test(value)) throw new Error(`Invalid or unsafe color: ${value}`);\n return `#${value.replace(/^#/, \"\").toUpperCase()}`;\n}\n\nfunction escapeText(value: string): string {\n return value.replaceAll(\"&\", \"&\").replaceAll(\"<\", \"<\").replaceAll(\">\", \">\");\n}\n\nfunction escapeAttribute(value: string): string {\n return escapeText(value).replaceAll('\"', \""\").replaceAll(\"'\", \"'\");\n}\n"],"mappings":"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","names":["tag"]}
|