@boxpdf/html-writer 0.1.10 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -41,6 +41,11 @@ async function writeSemanticDocument(pages, write, lookaheadPages) {
41
41
  const seenFurniture = /* @__PURE__ */ new Set();
42
42
  const sectionLevels = [];
43
43
  let activeTable;
44
+ let headerOpen = false;
45
+ let headerHasParagraph = false;
46
+ let contentStarted = false;
47
+ let employmentOpen = false;
48
+ let pendingParagraph;
44
49
  await write('<article class="pdf-semantic-document">');
45
50
  const closeTable = async () => {
46
51
  if (!activeTable) return;
@@ -53,6 +58,16 @@ async function writeSemanticDocument(pages, write, lookaheadPages) {
53
58
  sectionLevels.pop();
54
59
  }
55
60
  };
61
+ const flushPendingParagraph = async () => {
62
+ if (!pendingParagraph) return;
63
+ await write(semanticBlockHtml(pendingParagraph.block));
64
+ pendingParagraph = void 0;
65
+ };
66
+ const closeEmployment = async () => {
67
+ if (!employmentOpen) return;
68
+ await write("</section>");
69
+ employmentOpen = false;
70
+ };
56
71
  const emitPage = async (page, future) => {
57
72
  const futureFurniture = new Set(future.flatMap((candidate) => marginSignatures(candidate)));
58
73
  const repeatedFurniture = /* @__PURE__ */ new Set([...seenFurniture, ...futureFurniture]);
@@ -61,6 +76,28 @@ async function writeSemanticDocument(pages, write, lookaheadPages) {
61
76
  stats.suppressedFurniture += 1;
62
77
  continue;
63
78
  }
79
+ await flushPendingParagraph();
80
+ if (employmentOpen && block.type !== "list") await closeEmployment();
81
+ if (!contentStarted && !headerOpen && block.type === "heading" && block.level === 1) {
82
+ await write(`<header><h1>${escapeHtml(block.text)}</h1>`);
83
+ headerOpen = true;
84
+ continue;
85
+ }
86
+ if (headerOpen) {
87
+ if (block.type === "paragraph") {
88
+ const tag = isContactBlock(block) ? "address" : "p";
89
+ await write(`<${tag}>${escapeHtml(block.text)}</${tag}>`);
90
+ headerHasParagraph = true;
91
+ continue;
92
+ }
93
+ if (block.type === "heading" && !headerHasParagraph && (block.level === 1 || block.text.trimStart().startsWith("#"))) {
94
+ await write(`<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`);
95
+ continue;
96
+ }
97
+ await write("</header>");
98
+ headerOpen = false;
99
+ contentStarted = true;
100
+ }
64
101
  if (block.type === "table") {
65
102
  const rows = (0, import_structure.tableToRows)(block.table);
66
103
  if (activeTable && tablesContinue(activeTable.table, block.table, page.width)) {
@@ -78,13 +115,45 @@ async function writeSemanticDocument(pages, write, lookaheadPages) {
78
115
  activeTable = { table: block.table, header };
79
116
  continue;
80
117
  }
118
+ if (activeTable && block.type === "definitionList" && isFinancialSummary(block)) {
119
+ const columns = activeTable.table.columns.length;
120
+ await write(
121
+ `<tfoot>${block.entries.map((entry) => financialSummaryRow(entry, columns)).join("")}</tfoot>`
122
+ );
123
+ await closeTable();
124
+ continue;
125
+ }
81
126
  await closeTable();
82
127
  if (block.type === "heading") {
83
- await closeSections(block.level);
128
+ const level = contentStarted && block.level === 1 ? 2 : block.level;
129
+ await closeSections(level);
130
+ await write(
131
+ `<section data-level="${level}"><h${level}>${escapeHtml(block.text)}</h${level}>`
132
+ );
133
+ sectionLevels.push(level);
134
+ continue;
135
+ }
136
+ if (block.type === "paragraph") {
137
+ if (isTitledRecord(block)) {
138
+ const [institution, ...details] = block.lines;
139
+ if (institution) await write(`<h3>${escapeHtml(institution.text)}</h3>`);
140
+ for (const detail of details) await write(`<p>${escapeHtml(detail.text)}</p>`);
141
+ continue;
142
+ }
143
+ if (isUnmarkedList(block)) {
144
+ await write(
145
+ `<ul>${block.lines.map((line) => `<li>${escapeHtml(line.text)}</li>`).join("")}</ul>`
146
+ );
147
+ continue;
148
+ }
149
+ pendingParagraph = { block, height: page.height };
150
+ continue;
151
+ }
152
+ if (block.type === "employment") {
84
153
  await write(
85
- `<section data-level="${block.level}"><h${block.level}>${escapeHtml(block.text)}</h${block.level}>`
154
+ `<section><h3>${escapeHtml(block.role)}</h3><p>${escapeHtml(block.organization)}</p><p>${escapeHtml(block.date)}</p>`
86
155
  );
87
- sectionLevels.push(block.level);
156
+ employmentOpen = true;
88
157
  continue;
89
158
  }
90
159
  await write(semanticBlockHtml(block));
@@ -109,11 +178,62 @@ async function writeSemanticDocument(pages, write, lookaheadPages) {
109
178
  const ready = buffer.shift();
110
179
  if (ready) await emitPage(ready, buffer);
111
180
  }
181
+ if (headerOpen) await write("</header>");
112
182
  await closeTable();
113
- await closeSections();
183
+ await closeEmployment();
184
+ if (pendingParagraph && isFooterParagraph(pendingParagraph.block, pendingParagraph.height)) {
185
+ await closeSections();
186
+ await write(`<footer>${semanticBlockHtml(pendingParagraph.block)}</footer>`);
187
+ pendingParagraph = void 0;
188
+ } else {
189
+ await flushPendingParagraph();
190
+ await closeSections();
191
+ }
114
192
  await write("</article>");
115
193
  return stats;
116
194
  }
195
+ function isContactBlock(block) {
196
+ const text = block.text;
197
+ const signals = [
198
+ /@/.test(text),
199
+ /\+?\d[\d().\s-]{7,}/.test(text),
200
+ /\bhttps?:\/\//i.test(text),
201
+ /\b\w+\.\w{2,}\b/i.test(text)
202
+ ];
203
+ return signals.filter(Boolean).length >= 2;
204
+ }
205
+ function isTitledRecord(block) {
206
+ if (block.lines.length < 2) return false;
207
+ const [first, ...rest] = block.lines;
208
+ if (!first || rest.length === 0) return false;
209
+ const firstSize = Math.max(...first.spans.map((span) => span.fontSize));
210
+ const restSize = Math.max(...rest.flatMap((line) => line.spans.map((span) => span.fontSize)));
211
+ const emphasized = first.spans.some(
212
+ (span) => /(?:bold|semibold|demi)/i.test(span.fontFamily ?? "")
213
+ );
214
+ return emphasized || firstSize >= restSize * 1.08;
215
+ }
216
+ function isUnmarkedList(block) {
217
+ if (block.lines.length < 3) return false;
218
+ const first = block.lines[0];
219
+ if (!first) return false;
220
+ const aligned = block.lines.every(
221
+ (line) => Math.abs(line.bounds.x - first.bounds.x) <= Math.max(8, first.bounds.height)
222
+ );
223
+ const separated = block.lines.slice(1).every((line, index) => {
224
+ const previous = block.lines[index];
225
+ if (!previous) return false;
226
+ const gap = previous.bounds.y - (line.bounds.y + line.bounds.height);
227
+ return gap >= Math.min(previous.bounds.height, line.bounds.height) * 0.55;
228
+ });
229
+ return aligned && separated;
230
+ }
231
+ function isFooterParagraph(block, pageHeight) {
232
+ const inBottomMargin = block.lines.every(
233
+ (line) => line.bounds.y + line.bounds.height <= pageHeight * 0.15
234
+ );
235
+ return inBottomMargin || /^(?:thanks|thank you)\b/i.test(block.text.trim());
236
+ }
117
237
  function marginSignatures(page) {
118
238
  return page.structured.blocks.flatMap(
119
239
  (block) => blockLines(block).filter((line) => isMarginLine(line.bounds.y, line.bounds.height, page.height)).map((line) => furnitureSignature(line.text))
@@ -143,7 +263,8 @@ function tablesContinue(previous, next, pageWidth) {
143
263
  function tableHeader(rows) {
144
264
  const first = rows[0];
145
265
  if (!first) return void 0;
146
- return first.some((value) => /^(?:item|description|feature|qty|unit|amount|total)$/i.test(value)) ? first : void 0;
266
+ const later = rows.slice(1).flat();
267
+ return first.every((value) => /\p{L}/u.test(value) && !isNumericValue(value)) && later.some(isNumericValue) ? first : void 0;
147
268
  }
148
269
  function sameRow(left, right) {
149
270
  return Boolean(
@@ -154,28 +275,68 @@ function tableRow(row, header) {
154
275
  const cell = header ? "th" : "td";
155
276
  return `<tr>${row.map((value) => `<${cell}>${escapeHtml(value)}</${cell}>`).join("")}</tr>`;
156
277
  }
278
+ function isFinancialSummary(block) {
279
+ return block.entries.length > 0 && block.entries.every((entry) => isNumericValue(entry.description)) && block.entries.some((entry) => /\p{Sc}|%/u.test(entry.description));
280
+ }
281
+ function isNumericValue(value) {
282
+ return /^(?:\p{Sc}\s*)?[\d.,'’\s]+(?:\s*%)?$/u.test(value.trim());
283
+ }
284
+ function financialSummaryRow(entry, columns) {
285
+ const colspan = columns > 2 ? ` colspan="${columns - 1}"` : "";
286
+ return `<tr><th scope="row"${colspan}>${escapeHtml(entry.term)}</th><td>${escapeHtml(entry.description)}</td></tr>`;
287
+ }
157
288
  function semanticBlockHtml(block) {
158
289
  if (block.type === "heading")
159
290
  return `<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`;
160
291
  if (block.type === "paragraph") return `<p>${escapeHtml(block.text)}</p>`;
161
292
  if (block.type === "definitionList") {
162
- return `<dl>${block.entries.map(
293
+ if (block.entries.length <= 3 && block.entries.some((entry) => entry.description.trim().split(/\s+/).length >= 5) && block.entries.every((entry) => /^[A-Z][A-Z\s/-]*$/.test(entry.term.trim()))) {
294
+ return block.entries.map(
295
+ (entry) => `<section><h2>${escapeHtml(titleCase(entry.term))}</h2><p>${escapeHtml(entry.description)}</p></section>`
296
+ ).join("");
297
+ }
298
+ const list = `<dl>${block.entries.map(
163
299
  (entry) => `<div><dt>${escapeHtml(entry.term)}</dt><dd>${escapeHtml(entry.description)}</dd></div>`
164
300
  ).join("")}</dl>`;
301
+ return isFinancialSummary(block) ? `<section>${list}</section>` : list;
165
302
  }
166
303
  if (block.type === "cardList") {
167
- return `<div class="pdf-semantic-cards">${block.items.map(
168
- (item) => `<article><h3>${escapeHtml(item.title)}</h3>${item.details.map((detail) => `<p>${escapeHtml(detail)}</p>`).join("")}</article>`
169
- ).join("")}</div>`;
304
+ return `<section><h2>Items ordered</h2><table><thead><tr><th scope="col">Item</th><th scope="col">Quantity</th><th scope="col">Amount</th></tr></thead><tbody>${block.items.map(cardTableRow).join("")}</tbody></table></section>`;
170
305
  }
171
306
  if (block.type === "sectionGroup") {
172
- return `<div class="pdf-semantic-sections">${block.items.map(
173
- (item) => `<section><h3>${escapeHtml(item.label)}</h3>${item.content.map((content) => `<p>${escapeHtml(content)}</p>`).join("")}</section>`
174
- ).join("")}</div>`;
307
+ return block.items.map(labeledSectionHtml).join("");
308
+ }
309
+ if (block.type === "employment") {
310
+ return `<section><h3>${escapeHtml(block.role)}</h3><p>${escapeHtml(block.organization)}</p><p>${escapeHtml(block.date)}</p></section>`;
175
311
  }
176
312
  const tag = block.ordered ? "ol" : "ul";
177
313
  return `<${tag}>${block.items.map((item) => `<li>${escapeHtml(item.text)}</li>`).join("")}</${tag}>`;
178
314
  }
315
+ function cardTableRow(item) {
316
+ const trailing = item.details.at(-1) ?? "";
317
+ const match = /^\s*[×x]\s*(\d+)\s+(.+)$/u.exec(trailing);
318
+ const description = item.details.slice(0, -1).join(" ");
319
+ const detail = description ? `<br><span>${escapeHtml(description)}</span>` : "";
320
+ const quantity = match?.[1] ?? "";
321
+ const amount = match?.[2] ?? trailing;
322
+ return `<tr><th scope="row">${escapeHtml(item.title)}${detail}</th><td>${escapeHtml(quantity)}</td><td>${escapeHtml(amount)}</td></tr>`;
323
+ }
324
+ function labeledSectionHtml(item) {
325
+ const heading = titleCase(item.label);
326
+ const postal = /\b(?:ship|deliver|mail)(?:ed)?\b/i.test(item.label);
327
+ if (postal) {
328
+ const [name, ...address] = item.content;
329
+ const content = [name ? `<strong>${escapeHtml(name)}</strong>` : "", ...address.map(escapeHtml)].filter(Boolean).join("<br>");
330
+ return `<section><h2>${escapeHtml(heading)}</h2><address>${content}</address></section>`;
331
+ }
332
+ return `<section><h2>${escapeHtml(heading)}</h2>${item.content.map(
333
+ (content, index) => `<p>${index === 0 ? `<strong>${escapeHtml(content)}</strong>` : escapeHtml(content)}</p>`
334
+ ).join("")}</section>`;
335
+ }
336
+ function titleCase(value) {
337
+ const normalized = value.trim().toLocaleLowerCase("en");
338
+ return normalized.replace(/^\p{L}/u, (letter) => letter.toLocaleUpperCase("en"));
339
+ }
179
340
  function escapeHtml(value) {
180
341
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
181
342
  }
@@ -438,6 +599,10 @@ async function writeFlowPage(page, write) {
438
599
  await write("</section>");
439
600
  }
440
601
  await write("</div>");
602
+ } else if (block.type === "employment") {
603
+ await write(
604
+ `<section><h3>${escapeHtml2(block.role)}</h3><p>${escapeHtml2(block.organization)}</p><p>${escapeHtml2(block.date)}</p></section>`
605
+ );
441
606
  } else {
442
607
  const tag = block.ordered ? "ol" : "ul";
443
608
  await write(`<${tag}>`);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/semantic-document.ts"],"sourcesContent":["import type {\n EmbeddedFont,\n EmbeddedType3Font,\n ExtractedPage,\n RasterImage,\n TextSpan,\n Type3Glyph,\n VectorPath,\n} from \"@boxpdf/reader\";\nimport { structurePage, tableToHtml } from \"@boxpdf/reader/structure\";\nimport { type SemanticDocumentStats, writeSemanticDocument } from \"./semantic-document.js\";\n\nexport type { SemanticDocumentStats } from \"./semantic-document.js\";\n\nexport type HtmlLayout = \"positioned\" | \"flow\";\nexport type HtmlProfile = \"visual\" | \"semantic\";\nexport type HtmlWrite = (chunk: string) => void | Promise<void>;\n\nexport interface HtmlWriterOptions {\n /** Output intent. Visual preserves page presentation; semantic prioritizes reading order. */\n profile?: HtmlProfile;\n /** @deprecated Use `profile: \"visual\"` or `profile: \"semantic\"`. */\n layout?: HtmlLayout;\n title?: string;\n language?: string;\n includeDocument?: boolean;\n includeStyles?: boolean;\n /** Maximum extracted page models retained for document-level semantic decisions. */\n semanticLookaheadPages?: number;\n /** Receives bounded-buffer and document-inference statistics after semantic output completes. */\n onSemanticStats?: (stats: Readonly<SemanticDocumentStats>) => void;\n}\n\nconst styles = `.pdf-document{margin:0 auto}.pdf-page{box-sizing:border-box;margin:1rem auto;background:#fff;color:#000}.pdf-page--visual,.pdf-page--positioned{position:relative;overflow:hidden}.pdf-page-content{position:absolute;transform-origin:0 0}.pdf-span{position:absolute;white-space:pre;transform-origin:left bottom;unicode-bidi:isolate}.pdf-span[data-direction=ttb]{writing-mode:vertical-rl}.pdf-page--semantic,.pdf-page--flow{max-width:60rem;padding:1rem}.pdf-page--semantic p,.pdf-page--flow p{white-space:pre-wrap;unicode-bidi:plaintext}.pdf-page table{border-collapse:collapse}.pdf-page td{padding:.15rem .4rem;vertical-align:top}`;\n\nexport async function writeHtmlDocument(\n pages: AsyncIterable<ExtractedPage> | Iterable<ExtractedPage>,\n write: HtmlWrite,\n options: HtmlWriterOptions = {},\n): Promise<void> {\n const includeDocument = options.includeDocument ?? true;\n if (includeDocument) {\n await write(\"<!doctype html><html\");\n await write(\n ` lang=\"${escapeAttribute(options.language ?? \"en\")}\"><head><meta charset=\"utf-8\">`,\n );\n await write('<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">');\n await write(`<title>${escapeHtml(options.title ?? \"PDF document\")}</title>`);\n if (options.includeStyles ?? true) await write(`<style>${styles}</style>`);\n await write(\"</head><body>\");\n }\n await write('<main class=\"pdf-document\">');\n if (resolveProfile(options) === \"semantic\") {\n const lookahead = semanticLookahead(options.semanticLookaheadPages);\n const stats = await writeSemanticDocument(pages, write, lookahead);\n options.onSemanticStats?.(stats);\n } else {\n for await (const page of pages) await writePage(page, write, options);\n }\n await write(\"</main>\");\n if (includeDocument) await write(\"</body></html>\");\n}\n\nfunction semanticLookahead(value: number | undefined): number {\n const lookahead = value ?? 4;\n if (!Number.isSafeInteger(lookahead) || lookahead < 1 || lookahead > 16) {\n throw new RangeError(\"semanticLookaheadPages must be an integer between 1 and 16\");\n }\n return lookahead;\n}\n\nexport async function writePage(\n page: ExtractedPage,\n write: HtmlWrite,\n options: HtmlWriterOptions = {},\n): Promise<void> {\n if (resolveProfile(options) === \"semantic\") await writeFlowPage(page, write);\n else await writePositionedPage(page, write, options);\n}\n\nexport async function pageToHtml(\n page: ExtractedPage,\n options: HtmlWriterOptions = {},\n): Promise<string> {\n let output = \"\";\n await writePage(\n page,\n (chunk) => {\n output += chunk;\n },\n options,\n );\n return output;\n}\n\nasync function writePositionedPage(\n page: ExtractedPage,\n write: HtmlWrite,\n options: HtmlWriterOptions,\n): Promise<void> {\n const visualSpans = page.visualSpans ?? page.spans;\n const reflectedOverlay = usesReflectedVisualOverlay(page, visualSpans);\n const quarterTurn = page.rotate === 90 || page.rotate === 270;\n const displayWidth = quarterTurn ? page.height : page.width;\n const displayHeight = quarterTurn ? page.width : page.height;\n await write(\n `<section class=\"pdf-page pdf-page--visual pdf-page--positioned\" data-page=\"${page.number}\" data-rotate=\"${page.rotate}\" style=\"width:${number(displayWidth)}pt;height:${number(displayHeight)}pt\">`,\n );\n const fontAliases = new Map(\n (page.fonts ?? [])\n .filter((font) => font.format === \"truetype\" && !/(?:courier|^TTE)/i.test(font.family ?? \"\"))\n .map((font) => [font.id, `boxpdf-${page.number}-${font.id}`]),\n );\n const type3Fonts = new Map(\n (page.fonts ?? [])\n .filter((font): font is EmbeddedType3Font => font.format === \"type3\")\n .map((font) => [font.id, font]),\n );\n if ((options.includeStyles ?? true) && page.fonts?.length) {\n await write(`<style>${page.fonts.map((font) => fontFace(font, fontAliases)).join(\"\")}</style>`);\n }\n await write(\n `<div class=\"pdf-page-content pdf-page-content--${page.rotate}\" style=\"width:${number(page.width)}pt;height:${number(page.height)}pt${rotationTransform(page)}\">`,\n );\n await write(\n `<svg class=\"pdf-visual-text\" xmlns=\"http://www.w3.org/2000/svg\" width=\"${number(page.width)}pt\" height=\"${number(page.height)}pt\" viewBox=\"0 0 ${number(page.width)} ${number(page.height)}\">`,\n );\n const clipDefinitions =\n imageClipDefinitions(page.images ?? [], page.number, page.height) +\n pathClipDefinitions(page.paths ?? [], page.number);\n if (clipDefinitions) await write(`<defs>${clipDefinitions}</defs>`);\n if (reflectedOverlay) {\n for (const [index, image] of (page.images ?? []).entries()) {\n await write(visualImage(image, page.height, page.number, index));\n }\n }\n for (const fill of page.fills ?? []) {\n const points = fill.points.map(([x, y]) => `${number(x)},${number(page.height - y)}`).join(\" \");\n if (isCssHexColor(fill.color)) {\n const opacity = isUnitInterval(fill.opacity) ? ` fill-opacity=\"${number(fill.opacity)}\"` : \"\";\n await write(`<polygon points=\"${points}\" fill=\"${fill.color}\"${opacity}/>`);\n }\n }\n if (page.paths?.length) {\n await write(`<g transform=\"translate(0 ${number(page.height)}) scale(1 -1)\">`);\n for (const [pathIndex, path] of page.paths.entries()) {\n if (!isSvgPath(path.d)) continue;\n const fill = isCssHexColor(path.fill) ? path.fill : \"none\";\n const stroke = isCssHexColor(path.stroke) ? path.stroke : \"none\";\n const strokeWidth =\n path.strokeWidth !== undefined && Number.isFinite(path.strokeWidth) && path.strokeWidth >= 0\n ? ` stroke-width=\"${number(path.strokeWidth)}\"`\n : \"\";\n const fillRule = path.fillRule ? ` fill-rule=\"${path.fillRule}\"` : \"\";\n const fillOpacity = isUnitInterval(path.fillOpacity)\n ? ` fill-opacity=\"${number(path.fillOpacity)}\"`\n : \"\";\n const strokeOpacity = isUnitInterval(path.strokeOpacity)\n ? ` stroke-opacity=\"${number(path.strokeOpacity)}\"`\n : \"\";\n const dasharray = path.strokeDasharray?.every((value) => Number.isFinite(value) && value >= 0)\n ? ` stroke-dasharray=\"${path.strokeDasharray.map(number).join(\" \")}\"`\n : \"\";\n const dashoffset = Number.isFinite(path.strokeDashoffset)\n ? ` stroke-dashoffset=\"${number(path.strokeDashoffset ?? 0)}\"`\n : \"\";\n const linecap = path.strokeLinecap ? ` stroke-linecap=\"${path.strokeLinecap}\"` : \"\";\n const linejoin = path.strokeLinejoin ? ` stroke-linejoin=\"${path.strokeLinejoin}\"` : \"\";\n let output = `<path d=\"${path.d}\" fill=\"${fill}\" stroke=\"${stroke}\"${strokeWidth}${fillOpacity}${strokeOpacity}${dasharray}${dashoffset}${linecap}${linejoin}${fillRule}/>`;\n for (let index = (path.clips?.length ?? 0) - 1; index >= 0; index -= 1) {\n output = `<g clip-path=\"url(#${pathClipId(page.number, pathIndex, index)})\">${output}</g>`;\n }\n await write(output);\n }\n await write(\"</g>\");\n }\n if (!reflectedOverlay) {\n for (const [index, image] of (page.images ?? []).entries()) {\n await write(visualImage(image, page.height, page.number, index));\n }\n }\n for (const span of visualSpans) {\n if (!usesPositionedSpan(span)) {\n const type3 = span.fontAssetId ? type3Fonts.get(span.fontAssetId) : undefined;\n await write(\n type3\n ? visualType3Text(span, type3, page.height)\n : visualText(span, page.height, fontAliases, reflectedOverlay && page.rotate === 180),\n );\n }\n }\n await write(\"</svg>\");\n for (const span of visualSpans) {\n if (usesPositionedSpan(span)) await write(positionedSpan(span, fontAliases));\n }\n await write(\"</div></section>\");\n}\n\nfunction usesReflectedVisualOverlay(page: ExtractedPage, spans: TextSpan[]): boolean {\n return (\n Boolean(page.images?.length) &&\n Boolean(page.paths?.length || page.fills?.length) &&\n spans.length > 0 &&\n spans.every(\n (span) =>\n span.transform !== undefined &&\n Math.abs(span.transform[0] + 1) < 0.000_001 &&\n Math.abs(span.transform[1]) < 0.000_001 &&\n Math.abs(span.transform[2]) < 0.000_001 &&\n Math.abs(span.transform[3] - 1) < 0.000_001,\n )\n );\n}\n\nfunction visualImage(\n image: RasterImage,\n pageHeight: number,\n pageNumber: number,\n imageIndex: number,\n): string {\n const [a, b, c, d, e, f] = image.transform;\n const transform = [a, -b, -c, d, c + e, pageHeight - d - f].map(number).join(\" \");\n const opacity = isUnitInterval(image.opacity) ? ` opacity=\"${number(image.opacity)}\"` : \"\";\n const mime = image.format === \"jpeg\" ? \"image/jpeg\" : \"image/bmp\";\n const data = image.format === \"jpeg\" ? image.data : rgbBmp(image);\n let output = `<image width=\"1\" height=\"1\" preserveAspectRatio=\"none\" transform=\"matrix(${transform})\" href=\"data:${mime};base64,${base64(data)}\"${opacity}/>`;\n for (let index = (image.clips?.length ?? 0) - 1; index >= 0; index -= 1) {\n output = `<g clip-path=\"url(#${imageClipId(pageNumber, imageIndex, index)})\">${output}</g>`;\n }\n return output;\n}\n\nfunction imageClipDefinitions(\n images: RasterImage[],\n pageNumber: number,\n pageHeight: number,\n): string {\n return images\n .flatMap((image, imageIndex) =>\n (image.clips ?? []).map((clip, clipIndex) => {\n if (!isSvgPath(clip.d)) return \"\";\n const fillRule = clip.fillRule ? ` clip-rule=\"${clip.fillRule}\"` : \"\";\n return `<clipPath id=\"${imageClipId(pageNumber, imageIndex, clipIndex)}\" clipPathUnits=\"userSpaceOnUse\"><path d=\"${clip.d}\" transform=\"translate(0 ${number(pageHeight)}) scale(1 -1)\"${fillRule}/></clipPath>`;\n }),\n )\n .join(\"\");\n}\n\nfunction imageClipId(pageNumber: number, imageIndex: number, clipIndex: number): string {\n return `boxpdf-clip-${pageNumber}-${imageIndex}-${clipIndex}`;\n}\n\nfunction pathClipDefinitions(paths: VectorPath[], pageNumber: number): string {\n return paths\n .flatMap((path, pathIndex) =>\n (path.clips ?? []).map((clip, clipIndex) => {\n if (!isSvgPath(clip.d)) return \"\";\n const fillRule = clip.fillRule ? ` clip-rule=\"${clip.fillRule}\"` : \"\";\n return `<clipPath id=\"${pathClipId(pageNumber, pathIndex, clipIndex)}\" clipPathUnits=\"userSpaceOnUse\"><path d=\"${clip.d}\"${fillRule}/></clipPath>`;\n }),\n )\n .join(\"\");\n}\n\nfunction pathClipId(pageNumber: number, pathIndex: number, clipIndex: number): string {\n return `boxpdf-path-clip-${pageNumber}-${pathIndex}-${clipIndex}`;\n}\n\nfunction rgbBmp(image: RasterImage): Uint8Array {\n const stride = Math.ceil((image.width * 3) / 4) * 4;\n const output = new Uint8Array(54 + stride * image.height);\n const view = new DataView(output.buffer);\n output[0] = 0x42;\n output[1] = 0x4d;\n view.setUint32(2, output.length, true);\n view.setUint32(10, 54, true);\n view.setUint32(14, 40, true);\n view.setInt32(18, image.width, true);\n view.setInt32(22, -image.height, true);\n view.setUint16(26, 1, true);\n view.setUint16(28, 24, true);\n view.setUint32(34, stride * image.height, true);\n for (let row = 0; row < image.height; row += 1) {\n for (let column = 0; column < image.width; column += 1) {\n const source = (row * image.width + column) * 3;\n const target = 54 + row * stride + column * 3;\n output[target] = image.data[source + 2] ?? 0;\n output[target + 1] = image.data[source + 1] ?? 0;\n output[target + 2] = image.data[source] ?? 0;\n }\n }\n return output;\n}\n\nfunction rotationTransform(page: ExtractedPage): string {\n switch (page.rotate) {\n case 90:\n return `;transform:translate(${number(page.height)}pt,0) rotate(90deg)`;\n case 180:\n return `;transform:translate(${number(page.width)}pt,${number(page.height)}pt) rotate(180deg)`;\n case 270:\n return `;transform:translate(0,${number(page.width)}pt) rotate(270deg)`;\n default:\n return \"\";\n }\n}\n\nfunction positionedSpan(span: TextSpan, fontAliases: Map<string, string>): string {\n const direction = directionAttribute([span]);\n const style = [\n `left:${number(span.bounds.x)}pt`,\n `bottom:${number(span.bounds.y)}pt`,\n `width:${number(span.bounds.width)}pt`,\n `height:${number(span.bounds.height)}pt`,\n `font-size:${number(span.fontSize)}pt`,\n ...(isCssHexColor(span.color) ? [`color:${span.color}`] : []),\n ...(isUnitInterval(span.fillOpacity) ? [`opacity:${number(span.fillOpacity)}`] : []),\n ...fontStyles(\n span.fontFamily,\n span.fontAssetId ? fontAliases.get(span.fontAssetId) : undefined,\n ),\n ].join(\";\");\n return `<span class=\"pdf-span\"${direction} style=\"${style}\">${escapeHtml(span.text)}</span>`;\n}\n\nasync function writeFlowPage(page: ExtractedPage, write: HtmlWrite): Promise<void> {\n const structured = structurePage(page);\n await write(\n `<section class=\"pdf-page pdf-page--semantic pdf-page--flow\" data-page=\"${page.number}\">`,\n );\n for (const block of structured.blocks) {\n if (block.type === \"table\") await write(tableToHtml(block.table));\n else if (block.type === \"heading\") {\n await write(`<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`);\n } else if (block.type === \"paragraph\") {\n await write(\n `<p${directionAttribute(block.lines.flatMap((line) => line.spans))}>${escapeHtml(block.text)}</p>`,\n );\n } else if (block.type === \"definitionList\") {\n await write(\"<dl>\");\n for (const entry of block.entries) {\n await write(\n `<div><dt>${escapeHtml(entry.term)}</dt><dd>${escapeHtml(entry.description)}</dd></div>`,\n );\n }\n await write(\"</dl>\");\n } else if (block.type === \"cardList\") {\n await write('<div class=\"pdf-semantic-cards\">');\n for (const item of block.items) {\n await write(`<article><h3>${escapeHtml(item.title)}</h3>`);\n for (const detail of item.details) await write(`<p>${escapeHtml(detail)}</p>`);\n await write(\"</article>\");\n }\n await write(\"</div>\");\n } else if (block.type === \"sectionGroup\") {\n await write('<div class=\"pdf-semantic-sections\">');\n for (const item of block.items) {\n await write(`<section><h3>${escapeHtml(item.label)}</h3>`);\n for (const content of item.content) await write(`<p>${escapeHtml(content)}</p>`);\n await write(\"</section>\");\n }\n await write(\"</div>\");\n } else {\n const tag = block.ordered ? \"ol\" : \"ul\";\n await write(`<${tag}>`);\n for (const item of block.items) await write(`<li>${escapeHtml(item.text)}</li>`);\n await write(`</${tag}>`);\n }\n }\n await write(\"</section>\");\n}\n\nfunction visualText(\n span: TextSpan,\n pageHeight: number,\n fontAliases: Map<string, string>,\n counterRotateReflectedText = false,\n): string {\n if (span.renderingMode === 3 || span.renderingMode === 7) return \"\";\n if (!span.fontAssetId && isAdobeCjkFont(span.fontFamily)) return \"\";\n const direction = directionAttribute([span]);\n const font = fontStyles(\n span.fontFamily,\n span.fontAssetId ? fontAliases.get(span.fontAssetId) : undefined,\n ).join(\";\");\n const stroke = isCssHexColor(span.strokeColor) ? `stroke:${span.strokeColor}` : \"\";\n const strokeWidth =\n stroke && Number.isFinite(span.strokeWidth) && (span.strokeWidth ?? -1) >= 0\n ? `stroke-width:${number(span.strokeWidth ?? 0)}`\n : \"\";\n const strokeOnly = span.renderingMode === 1 || span.renderingMode === 5;\n const fillOpacity = isUnitInterval(span.fillOpacity)\n ? `fill-opacity:${number(span.fillOpacity)}`\n : \"\";\n const strokeOpacity = isUnitInterval(span.strokeOpacity)\n ? `stroke-opacity:${number(span.strokeOpacity)}`\n : \"\";\n const style = [\n isHebrewPaintOrder(span) ? \"unicode-bidi:bidi-override;direction:ltr\" : \"\",\n span.direction === \"ttb\" ? \"writing-mode:vertical-rl\" : \"\",\n strokeOnly ? \"fill:none\" : isCssHexColor(span.color) ? `fill:${span.color}` : \"\",\n stroke,\n strokeWidth,\n fillOpacity,\n strokeOpacity,\n font,\n ]\n .filter(Boolean)\n .join(\";\");\n const textExtent = span.direction === \"ttb\" ? span.bounds.height : span.bounds.width;\n const textLength =\n textExtent > 0 && !isHebrewPaintOrder(span)\n ? ` textLength=\"${number(textExtent)}\" lengthAdjust=\"${span.direction === \"ttb\" || usesSpacingAdjustment(span) ? \"spacing\" : \"spacingAndGlyphs\"}\"`\n : \"\";\n const transform =\n counterRotateReflectedText && span.transform\n ? ([\n span.transform[0],\n span.transform[1],\n span.transform[2],\n -span.transform[3],\n ] as TextSpan[\"transform\"])\n : span.transform;\n const transformed = hasNonIdentityTransform(transform);\n const rtlOffset = span.direction === \"rtl\" ? span.bounds.width : 0;\n const basisX = transform?.[0] ?? 1;\n const basisY = transform?.[1] ?? 0;\n const anchorX = span.bounds.x + basisX * rtlOffset;\n const anchorY = pageHeight - span.bounds.y + basisY * rtlOffset;\n const position = transformed\n ? ` x=\"0\" y=\"0\" transform=\"matrix(${transform?.map(number).join(\" \")} ${number(anchorX)} ${number(anchorY)})\"`\n : ` x=\"${number(anchorX)}\" y=\"${number(anchorY)}\"`;\n return `<text${direction}${position} font-size=\"${number(span.fontSize)}\"${textLength}${style ? ` style=\"${style}\"` : \"\"}>${escapeHtml(span.text)}</text>`;\n}\n\nfunction isAdobeCjkFont(fontFamily: string | undefined): boolean {\n return /^Adobe(?:Heiti|Song|Kaiti|Ming|Gothic|Mincho)Std-/i.test(fontFamily ?? \"\");\n}\n\nfunction visualType3Text(span: TextSpan, font: EmbeddedType3Font, pageHeight: number): string {\n if (span.renderingMode === 3 || span.renderingMode === 7) return \"\";\n const glyphs = new Map(font.glyphs.map((glyph) => [glyph.code, glyph]));\n const sequence = (span.glyphCodes ?? []).map((code) => glyphs.get(code));\n const totalAdvance = sequence.reduce((total, glyph) => total + (glyph?.advance ?? 0), 0);\n if (totalAdvance <= 0 || span.bounds.width <= 0 || span.fontSize <= 0) return \"\";\n const transform = span.transform ?? [1, 0, 0, 1];\n const outer = `matrix(${transform.map(number).join(\" \")} ${number(span.bounds.x)} ${number(pageHeight - span.bounds.y)})`;\n const xScale = span.bounds.width / totalAdvance;\n let offset = 0;\n let content = \"\";\n for (const glyph of sequence) {\n if (!glyph) continue;\n content += `<g transform=\"translate(${number(offset)} 0)\">${type3Glyph(glyph)}</g>`;\n offset += glyph.advance;\n }\n return `<g transform=\"${outer}\"><g transform=\"scale(${number(xScale)} ${number(-span.fontSize)})\">${content}</g></g>`;\n}\n\nfunction isHebrewPaintOrder(span: TextSpan): boolean {\n return span.direction === \"ltr\" && /[\\u0590-\\u05ff]/u.test(span.text);\n}\n\nfunction usesSpacingAdjustment(span: TextSpan): boolean {\n return !span.fontAssetId && /arial/i.test(span.fontFamily ?? \"\");\n}\n\nfunction type3Glyph(glyph: Type3Glyph): string {\n let output = \"\";\n for (const fill of glyph.fills ?? []) {\n if (!isCssHexColor(fill.color)) continue;\n const points = fill.points.map(([x, y]) => `${number(x)},${number(y)}`).join(\" \");\n const opacity = isUnitInterval(fill.opacity) ? ` fill-opacity=\"${number(fill.opacity)}\"` : \"\";\n output += `<polygon points=\"${points}\" fill=\"${fill.color}\"${opacity}/>`;\n }\n for (const path of glyph.paths ?? []) {\n if (!isSvgPath(path.d)) continue;\n const fill = isCssHexColor(path.fill) ? path.fill : \"none\";\n const stroke = isCssHexColor(path.stroke) ? path.stroke : \"none\";\n const width =\n path.strokeWidth !== undefined && Number.isFinite(path.strokeWidth) && path.strokeWidth >= 0\n ? ` stroke-width=\"${number(path.strokeWidth)}\"`\n : \"\";\n output += `<path d=\"${path.d}\" fill=\"${fill}\" stroke=\"${stroke}\"${width}/>`;\n }\n return (glyph.fills?.length ?? 0) > 64 && glyph.advance > 2\n ? `<g shape-rendering=\"crispEdges\">${output}</g>`\n : output;\n}\n\nfunction isCssHexColor(value: string | undefined): value is string {\n return /^#[\\da-f]{6}$/i.test(value ?? \"\");\n}\n\nfunction isUnitInterval(value: number | undefined): value is number {\n return Number.isFinite(value) && (value ?? -1) >= 0 && (value ?? 2) <= 1;\n}\n\nfunction isSvgPath(value: string): boolean {\n return value.length <= 1_000_000 && /^[\\d\\s.,+\\-eEMmLlCcZz]+$/.test(value);\n}\n\nfunction fontStyles(fontFamily: string | undefined, alias?: string): string[] {\n const normalized = fontFamily?.toLowerCase() ?? \"\";\n const styles: string[] = [];\n let fallback: string | undefined;\n if (/courier|mono|nimbusmono|^cmtt/.test(normalized)) {\n fallback = \"Courier New,Courier,monospace\";\n } else if (\n /times|minion|serif|baskerville|georgia|nimbusrom|guardian.*egyp|^cm[rs]y?\\d/.test(normalized)\n ) {\n fallback = \"Times New Roman,Times,serif\";\n } else if (/helvetica|arial|sans|nimbussan|calibre|myriad|panton|^tte/.test(normalized)) {\n fallback = \"Arial,Helvetica,sans-serif\";\n } else if (/^mstt/.test(normalized)) {\n fallback = \"Arial,Helvetica,sans-serif\";\n }\n if (alias || fallback) styles.push(`font-family:${[alias, fallback].filter(Boolean).join(\",\")}`);\n if (/bold|black|semibold|demi|medi|^tte/.test(normalized)) styles.push(\"font-weight:700\");\n if (/italic|oblique|slant|ital(?:$|[_-])/.test(normalized)) styles.push(\"font-style:italic\");\n return styles;\n}\n\nfunction isMonospace(fontFamily: string | undefined): boolean {\n return /courier|mono/i.test(fontFamily ?? \"\");\n}\n\nfunction usesPositionedSpan(span: TextSpan): boolean {\n return (\n !span.glyphCodes && isMonospace(span.fontFamily) && !hasNonIdentityTransform(span.transform)\n );\n}\n\nfunction hasNonIdentityTransform(transform: TextSpan[\"transform\"]): boolean {\n if (!transform) return false;\n const identity: [number, number, number, number] = [1, 0, 0, 1];\n return transform.some((value, index) => Math.abs(value - (identity[index] ?? 0)) > 0.000_001);\n}\n\nfunction fontFace(font: EmbeddedFont, aliases: Map<string, string>): string {\n if (font.format !== \"truetype\") return \"\";\n const alias = aliases.get(font.id);\n if (!alias) return \"\";\n const styles = fontStyles(font.family, alias).filter(\n (style) => !style.startsWith(\"font-family:\"),\n );\n return `@font-face{font-family:${alias};src:url(data:font/ttf;base64,${base64(font.data)}) format(\"truetype\");${styles.join(\";\")}}`;\n}\n\nfunction base64(bytes: Uint8Array): string {\n const alphabet = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n let output = \"\";\n for (let index = 0; index < bytes.length; index += 3) {\n const first = bytes[index] ?? 0;\n const second = bytes[index + 1] ?? 0;\n const third = bytes[index + 2] ?? 0;\n output += alphabet[first >> 2];\n output += alphabet[((first & 3) << 4) | (second >> 4)];\n output += index + 1 < bytes.length ? alphabet[((second & 15) << 2) | (third >> 6)] : \"=\";\n output += index + 2 < bytes.length ? alphabet[third & 63] : \"=\";\n }\n return output;\n}\n\nfunction directionAttribute(spans: TextSpan[]): string {\n const rtl = spans.filter((span) => span.direction === \"rtl\").length;\n const vertical = spans.filter((span) => span.direction === \"ttb\").length;\n if (vertical > rtl && vertical * 2 >= spans.length) return ' data-direction=\"ttb\"';\n return rtl * 2 >= spans.length && spans.length > 0 ? ' dir=\"rtl\"' : \"\";\n}\n\nfunction number(value: number): string {\n return Number.isFinite(value) ? String(Math.round(value * 1000) / 1000) : \"0\";\n}\n\nfunction escapeAttribute(value: string): string {\n return escapeHtml(value).replaceAll(\"`\", \"&#96;\");\n}\n\nfunction escapeHtml(value: string): string {\n return [...value]\n .map((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n if (codePoint === 13) return \"\\n\";\n return isForbiddenControl(codePoint) ? \"�\" : character;\n })\n .join(\"\")\n .replaceAll(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\")\n .replaceAll(\"'\", \"&#39;\");\n}\n\nfunction isForbiddenControl(codePoint: number): boolean {\n return (\n codePoint <= 8 ||\n codePoint === 11 ||\n codePoint === 12 ||\n (codePoint >= 14 && codePoint <= 31) ||\n codePoint === 127\n );\n}\n\nfunction resolveProfile(options: HtmlWriterOptions): HtmlProfile {\n const legacyProfile = options.layout === \"flow\" ? \"semantic\" : \"visual\";\n if (options.profile && options.layout && options.profile !== legacyProfile) {\n throw new Error(\n `conflicting HTML output options: profile \"${options.profile}\" does not match layout \"${options.layout}\"`,\n );\n }\n return options.profile ?? legacyProfile;\n}\n","import type { ExtractedPage } from \"@boxpdf/reader\";\nimport {\n type SemanticBlock,\n type StructuredPage,\n structurePage,\n type Table,\n tableToRows,\n} from \"@boxpdf/reader/structure\";\n\nexport interface SemanticDocumentStats {\n pagesProcessed: number;\n peakBufferedPages: number;\n peakBufferedLines: number;\n mergedTables: number;\n suppressedFurniture: number;\n}\n\ninterface BufferedPage {\n width: number;\n height: number;\n structured: StructuredPage;\n}\n\ninterface ActiveTable {\n table: Table;\n header: string[] | undefined;\n}\n\nexport async function writeSemanticDocument(\n pages: AsyncIterable<ExtractedPage> | Iterable<ExtractedPage>,\n write: (chunk: string) => void | Promise<void>,\n lookaheadPages: number,\n): Promise<SemanticDocumentStats> {\n const stats: SemanticDocumentStats = {\n pagesProcessed: 0,\n peakBufferedPages: 0,\n peakBufferedLines: 0,\n mergedTables: 0,\n suppressedFurniture: 0,\n };\n const buffer: BufferedPage[] = [];\n const seenFurniture = new Set<string>();\n const sectionLevels: number[] = [];\n let activeTable: ActiveTable | undefined;\n await write('<article class=\"pdf-semantic-document\">');\n\n const closeTable = async () => {\n if (!activeTable) return;\n await write(\"</table>\");\n activeTable = undefined;\n };\n\n const closeSections = async (minimumLevel = 0) => {\n while ((sectionLevels.at(-1) ?? -1) >= minimumLevel && sectionLevels.length > 0) {\n await write(\"</section>\");\n sectionLevels.pop();\n }\n };\n\n const emitPage = async (page: BufferedPage, future: BufferedPage[]) => {\n const futureFurniture = new Set(future.flatMap((candidate) => marginSignatures(candidate)));\n const repeatedFurniture = new Set([...seenFurniture, ...futureFurniture]);\n for (const block of page.structured.blocks) {\n if (isRepeatedFurniture(block, page, repeatedFurniture)) {\n stats.suppressedFurniture += 1;\n continue;\n }\n if (block.type === \"table\") {\n const rows = tableToRows(block.table);\n if (activeTable && tablesContinue(activeTable.table, block.table, page.width)) {\n const continuationRows = sameRow(activeTable.header, rows[0]) ? rows.slice(1) : rows;\n for (const row of continuationRows) await write(tableRow(row, false));\n activeTable.table = block.table;\n stats.mergedTables += 1;\n continue;\n }\n await closeTable();\n const header = tableHeader(rows);\n await write(\"<table>\");\n for (const [index, row] of rows.entries())\n await write(tableRow(row, Boolean(header && index === 0)));\n activeTable = { table: block.table, header };\n continue;\n }\n await closeTable();\n if (block.type === \"heading\") {\n await closeSections(block.level);\n await write(\n `<section data-level=\"${block.level}\"><h${block.level}>${escapeHtml(block.text)}</h${block.level}>`,\n );\n sectionLevels.push(block.level);\n continue;\n }\n await write(semanticBlockHtml(block));\n }\n for (const signature of marginSignatures(page)) seenFurniture.add(signature);\n };\n\n for await (const page of pages) {\n const structured = structurePage(page);\n buffer.push({ width: page.width, height: page.height, structured });\n stats.pagesProcessed += 1;\n stats.peakBufferedPages = Math.max(stats.peakBufferedPages, buffer.length);\n stats.peakBufferedLines = Math.max(\n stats.peakBufferedLines,\n buffer.reduce((total, item) => total + item.structured.lines.length, 0),\n );\n if (buffer.length >= lookaheadPages) {\n const ready = buffer.shift();\n if (ready) await emitPage(ready, buffer);\n }\n }\n while (buffer.length > 0) {\n const ready = buffer.shift();\n if (ready) await emitPage(ready, buffer);\n }\n await closeTable();\n await closeSections();\n await write(\"</article>\");\n return stats;\n}\n\nfunction marginSignatures(page: BufferedPage): string[] {\n return page.structured.blocks.flatMap((block) =>\n blockLines(block)\n .filter((line) => isMarginLine(line.bounds.y, line.bounds.height, page.height))\n .map((line) => furnitureSignature(line.text)),\n );\n}\n\nfunction isRepeatedFurniture(\n block: SemanticBlock,\n page: BufferedPage,\n futureFurniture: Set<string>,\n): boolean {\n const lines = blockLines(block);\n return (\n lines.length > 0 &&\n lines.every(\n (line) =>\n isMarginLine(line.bounds.y, line.bounds.height, page.height) &&\n futureFurniture.has(furnitureSignature(line.text)),\n )\n );\n}\n\nfunction blockLines(block: SemanticBlock) {\n return block.type === \"list\" ? block.items.flatMap((item) => item.lines) : block.lines;\n}\n\nfunction isMarginLine(y: number, height: number, pageHeight: number): boolean {\n return y + height <= pageHeight * 0.12 || y >= pageHeight * 0.88;\n}\n\nfunction furnitureSignature(value: string): string {\n return value.toLocaleLowerCase(\"en\").replace(/\\d+/g, \"#\").replace(/\\s+/g, \" \").trim();\n}\n\nfunction tablesContinue(previous: Table, next: Table, pageWidth: number): boolean {\n if (previous.columns.length !== next.columns.length || previous.columns.length < 2) return false;\n return previous.columns.every(\n (column, index) =>\n Math.abs(column - (next.columns[index] ?? Number.POSITIVE_INFINITY)) / pageWidth <= 0.04,\n );\n}\n\nfunction tableHeader(rows: string[][]): string[] | undefined {\n const first = rows[0];\n if (!first) return undefined;\n return first.some((value) => /^(?:item|description|feature|qty|unit|amount|total)$/i.test(value))\n ? first\n : undefined;\n}\n\nfunction sameRow(left: string[] | undefined, right: string[] | undefined): boolean {\n return Boolean(\n left &&\n right &&\n left.length === right.length &&\n left.every((value, index) => value === right[index]),\n );\n}\n\nfunction tableRow(row: string[], header: boolean): string {\n const cell = header ? \"th\" : \"td\";\n return `<tr>${row.map((value) => `<${cell}>${escapeHtml(value)}</${cell}>`).join(\"\")}</tr>`;\n}\n\nfunction semanticBlockHtml(block: Exclude<SemanticBlock, { type: \"table\" }>): string {\n if (block.type === \"heading\")\n return `<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`;\n if (block.type === \"paragraph\") return `<p>${escapeHtml(block.text)}</p>`;\n if (block.type === \"definitionList\") {\n return `<dl>${block.entries\n .map(\n (entry) =>\n `<div><dt>${escapeHtml(entry.term)}</dt><dd>${escapeHtml(entry.description)}</dd></div>`,\n )\n .join(\"\")}</dl>`;\n }\n if (block.type === \"cardList\") {\n return `<div class=\"pdf-semantic-cards\">${block.items\n .map(\n (item) =>\n `<article><h3>${escapeHtml(item.title)}</h3>${item.details.map((detail) => `<p>${escapeHtml(detail)}</p>`).join(\"\")}</article>`,\n )\n .join(\"\")}</div>`;\n }\n if (block.type === \"sectionGroup\") {\n return `<div class=\"pdf-semantic-sections\">${block.items\n .map(\n (item) =>\n `<section><h3>${escapeHtml(item.label)}</h3>${item.content.map((content) => `<p>${escapeHtml(content)}</p>`).join(\"\")}</section>`,\n )\n .join(\"\")}</div>`;\n }\n const tag = block.ordered ? \"ol\" : \"ul\";\n return `<${tag}>${block.items.map((item) => `<li>${escapeHtml(item.text)}</li>`).join(\"\")}</${tag}>`;\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n"],"mappings":"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","names":["import_structure","escapeHtml","styles"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/semantic-document.ts"],"sourcesContent":["import type {\n EmbeddedFont,\n EmbeddedType3Font,\n ExtractedPage,\n RasterImage,\n TextSpan,\n Type3Glyph,\n VectorPath,\n} from \"@boxpdf/reader\";\nimport { structurePage, tableToHtml } from \"@boxpdf/reader/structure\";\nimport { type SemanticDocumentStats, writeSemanticDocument } from \"./semantic-document.js\";\n\nexport type { SemanticDocumentStats } from \"./semantic-document.js\";\n\nexport type HtmlLayout = \"positioned\" | \"flow\";\nexport type HtmlProfile = \"visual\" | \"semantic\";\nexport type HtmlWrite = (chunk: string) => void | Promise<void>;\n\nexport interface HtmlWriterOptions {\n /** Output intent. Visual preserves page presentation; semantic prioritizes reading order. */\n profile?: HtmlProfile;\n /** @deprecated Use `profile: \"visual\"` or `profile: \"semantic\"`. */\n layout?: HtmlLayout;\n title?: string;\n language?: string;\n includeDocument?: boolean;\n includeStyles?: boolean;\n /** Maximum extracted page models retained for document-level semantic decisions. */\n semanticLookaheadPages?: number;\n /** Receives bounded-buffer and document-inference statistics after semantic output completes. */\n onSemanticStats?: (stats: Readonly<SemanticDocumentStats>) => void;\n}\n\nconst styles = `.pdf-document{margin:0 auto}.pdf-page{box-sizing:border-box;margin:1rem auto;background:#fff;color:#000}.pdf-page--visual,.pdf-page--positioned{position:relative;overflow:hidden}.pdf-page-content{position:absolute;transform-origin:0 0}.pdf-span{position:absolute;white-space:pre;transform-origin:left bottom;unicode-bidi:isolate}.pdf-span[data-direction=ttb]{writing-mode:vertical-rl}.pdf-page--semantic,.pdf-page--flow{max-width:60rem;padding:1rem}.pdf-page--semantic p,.pdf-page--flow p{white-space:pre-wrap;unicode-bidi:plaintext}.pdf-page table{border-collapse:collapse}.pdf-page td{padding:.15rem .4rem;vertical-align:top}`;\n\nexport async function writeHtmlDocument(\n pages: AsyncIterable<ExtractedPage> | Iterable<ExtractedPage>,\n write: HtmlWrite,\n options: HtmlWriterOptions = {},\n): Promise<void> {\n const includeDocument = options.includeDocument ?? true;\n if (includeDocument) {\n await write(\"<!doctype html><html\");\n await write(\n ` lang=\"${escapeAttribute(options.language ?? \"en\")}\"><head><meta charset=\"utf-8\">`,\n );\n await write('<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">');\n await write(`<title>${escapeHtml(options.title ?? \"PDF document\")}</title>`);\n if (options.includeStyles ?? true) await write(`<style>${styles}</style>`);\n await write(\"</head><body>\");\n }\n await write('<main class=\"pdf-document\">');\n if (resolveProfile(options) === \"semantic\") {\n const lookahead = semanticLookahead(options.semanticLookaheadPages);\n const stats = await writeSemanticDocument(pages, write, lookahead);\n options.onSemanticStats?.(stats);\n } else {\n for await (const page of pages) await writePage(page, write, options);\n }\n await write(\"</main>\");\n if (includeDocument) await write(\"</body></html>\");\n}\n\nfunction semanticLookahead(value: number | undefined): number {\n const lookahead = value ?? 4;\n if (!Number.isSafeInteger(lookahead) || lookahead < 1 || lookahead > 16) {\n throw new RangeError(\"semanticLookaheadPages must be an integer between 1 and 16\");\n }\n return lookahead;\n}\n\nexport async function writePage(\n page: ExtractedPage,\n write: HtmlWrite,\n options: HtmlWriterOptions = {},\n): Promise<void> {\n if (resolveProfile(options) === \"semantic\") await writeFlowPage(page, write);\n else await writePositionedPage(page, write, options);\n}\n\nexport async function pageToHtml(\n page: ExtractedPage,\n options: HtmlWriterOptions = {},\n): Promise<string> {\n let output = \"\";\n await writePage(\n page,\n (chunk) => {\n output += chunk;\n },\n options,\n );\n return output;\n}\n\nasync function writePositionedPage(\n page: ExtractedPage,\n write: HtmlWrite,\n options: HtmlWriterOptions,\n): Promise<void> {\n const visualSpans = page.visualSpans ?? page.spans;\n const reflectedOverlay = usesReflectedVisualOverlay(page, visualSpans);\n const quarterTurn = page.rotate === 90 || page.rotate === 270;\n const displayWidth = quarterTurn ? page.height : page.width;\n const displayHeight = quarterTurn ? page.width : page.height;\n await write(\n `<section class=\"pdf-page pdf-page--visual pdf-page--positioned\" data-page=\"${page.number}\" data-rotate=\"${page.rotate}\" style=\"width:${number(displayWidth)}pt;height:${number(displayHeight)}pt\">`,\n );\n const fontAliases = new Map(\n (page.fonts ?? [])\n .filter((font) => font.format === \"truetype\" && !/(?:courier|^TTE)/i.test(font.family ?? \"\"))\n .map((font) => [font.id, `boxpdf-${page.number}-${font.id}`]),\n );\n const type3Fonts = new Map(\n (page.fonts ?? [])\n .filter((font): font is EmbeddedType3Font => font.format === \"type3\")\n .map((font) => [font.id, font]),\n );\n if ((options.includeStyles ?? true) && page.fonts?.length) {\n await write(`<style>${page.fonts.map((font) => fontFace(font, fontAliases)).join(\"\")}</style>`);\n }\n await write(\n `<div class=\"pdf-page-content pdf-page-content--${page.rotate}\" style=\"width:${number(page.width)}pt;height:${number(page.height)}pt${rotationTransform(page)}\">`,\n );\n await write(\n `<svg class=\"pdf-visual-text\" xmlns=\"http://www.w3.org/2000/svg\" width=\"${number(page.width)}pt\" height=\"${number(page.height)}pt\" viewBox=\"0 0 ${number(page.width)} ${number(page.height)}\">`,\n );\n const clipDefinitions =\n imageClipDefinitions(page.images ?? [], page.number, page.height) +\n pathClipDefinitions(page.paths ?? [], page.number);\n if (clipDefinitions) await write(`<defs>${clipDefinitions}</defs>`);\n if (reflectedOverlay) {\n for (const [index, image] of (page.images ?? []).entries()) {\n await write(visualImage(image, page.height, page.number, index));\n }\n }\n for (const fill of page.fills ?? []) {\n const points = fill.points.map(([x, y]) => `${number(x)},${number(page.height - y)}`).join(\" \");\n if (isCssHexColor(fill.color)) {\n const opacity = isUnitInterval(fill.opacity) ? ` fill-opacity=\"${number(fill.opacity)}\"` : \"\";\n await write(`<polygon points=\"${points}\" fill=\"${fill.color}\"${opacity}/>`);\n }\n }\n if (page.paths?.length) {\n await write(`<g transform=\"translate(0 ${number(page.height)}) scale(1 -1)\">`);\n for (const [pathIndex, path] of page.paths.entries()) {\n if (!isSvgPath(path.d)) continue;\n const fill = isCssHexColor(path.fill) ? path.fill : \"none\";\n const stroke = isCssHexColor(path.stroke) ? path.stroke : \"none\";\n const strokeWidth =\n path.strokeWidth !== undefined && Number.isFinite(path.strokeWidth) && path.strokeWidth >= 0\n ? ` stroke-width=\"${number(path.strokeWidth)}\"`\n : \"\";\n const fillRule = path.fillRule ? ` fill-rule=\"${path.fillRule}\"` : \"\";\n const fillOpacity = isUnitInterval(path.fillOpacity)\n ? ` fill-opacity=\"${number(path.fillOpacity)}\"`\n : \"\";\n const strokeOpacity = isUnitInterval(path.strokeOpacity)\n ? ` stroke-opacity=\"${number(path.strokeOpacity)}\"`\n : \"\";\n const dasharray = path.strokeDasharray?.every((value) => Number.isFinite(value) && value >= 0)\n ? ` stroke-dasharray=\"${path.strokeDasharray.map(number).join(\" \")}\"`\n : \"\";\n const dashoffset = Number.isFinite(path.strokeDashoffset)\n ? ` stroke-dashoffset=\"${number(path.strokeDashoffset ?? 0)}\"`\n : \"\";\n const linecap = path.strokeLinecap ? ` stroke-linecap=\"${path.strokeLinecap}\"` : \"\";\n const linejoin = path.strokeLinejoin ? ` stroke-linejoin=\"${path.strokeLinejoin}\"` : \"\";\n let output = `<path d=\"${path.d}\" fill=\"${fill}\" stroke=\"${stroke}\"${strokeWidth}${fillOpacity}${strokeOpacity}${dasharray}${dashoffset}${linecap}${linejoin}${fillRule}/>`;\n for (let index = (path.clips?.length ?? 0) - 1; index >= 0; index -= 1) {\n output = `<g clip-path=\"url(#${pathClipId(page.number, pathIndex, index)})\">${output}</g>`;\n }\n await write(output);\n }\n await write(\"</g>\");\n }\n if (!reflectedOverlay) {\n for (const [index, image] of (page.images ?? []).entries()) {\n await write(visualImage(image, page.height, page.number, index));\n }\n }\n for (const span of visualSpans) {\n if (!usesPositionedSpan(span)) {\n const type3 = span.fontAssetId ? type3Fonts.get(span.fontAssetId) : undefined;\n await write(\n type3\n ? visualType3Text(span, type3, page.height)\n : visualText(span, page.height, fontAliases, reflectedOverlay && page.rotate === 180),\n );\n }\n }\n await write(\"</svg>\");\n for (const span of visualSpans) {\n if (usesPositionedSpan(span)) await write(positionedSpan(span, fontAliases));\n }\n await write(\"</div></section>\");\n}\n\nfunction usesReflectedVisualOverlay(page: ExtractedPage, spans: TextSpan[]): boolean {\n return (\n Boolean(page.images?.length) &&\n Boolean(page.paths?.length || page.fills?.length) &&\n spans.length > 0 &&\n spans.every(\n (span) =>\n span.transform !== undefined &&\n Math.abs(span.transform[0] + 1) < 0.000_001 &&\n Math.abs(span.transform[1]) < 0.000_001 &&\n Math.abs(span.transform[2]) < 0.000_001 &&\n Math.abs(span.transform[3] - 1) < 0.000_001,\n )\n );\n}\n\nfunction visualImage(\n image: RasterImage,\n pageHeight: number,\n pageNumber: number,\n imageIndex: number,\n): string {\n const [a, b, c, d, e, f] = image.transform;\n const transform = [a, -b, -c, d, c + e, pageHeight - d - f].map(number).join(\" \");\n const opacity = isUnitInterval(image.opacity) ? ` opacity=\"${number(image.opacity)}\"` : \"\";\n const mime = image.format === \"jpeg\" ? \"image/jpeg\" : \"image/bmp\";\n const data = image.format === \"jpeg\" ? image.data : rgbBmp(image);\n let output = `<image width=\"1\" height=\"1\" preserveAspectRatio=\"none\" transform=\"matrix(${transform})\" href=\"data:${mime};base64,${base64(data)}\"${opacity}/>`;\n for (let index = (image.clips?.length ?? 0) - 1; index >= 0; index -= 1) {\n output = `<g clip-path=\"url(#${imageClipId(pageNumber, imageIndex, index)})\">${output}</g>`;\n }\n return output;\n}\n\nfunction imageClipDefinitions(\n images: RasterImage[],\n pageNumber: number,\n pageHeight: number,\n): string {\n return images\n .flatMap((image, imageIndex) =>\n (image.clips ?? []).map((clip, clipIndex) => {\n if (!isSvgPath(clip.d)) return \"\";\n const fillRule = clip.fillRule ? ` clip-rule=\"${clip.fillRule}\"` : \"\";\n return `<clipPath id=\"${imageClipId(pageNumber, imageIndex, clipIndex)}\" clipPathUnits=\"userSpaceOnUse\"><path d=\"${clip.d}\" transform=\"translate(0 ${number(pageHeight)}) scale(1 -1)\"${fillRule}/></clipPath>`;\n }),\n )\n .join(\"\");\n}\n\nfunction imageClipId(pageNumber: number, imageIndex: number, clipIndex: number): string {\n return `boxpdf-clip-${pageNumber}-${imageIndex}-${clipIndex}`;\n}\n\nfunction pathClipDefinitions(paths: VectorPath[], pageNumber: number): string {\n return paths\n .flatMap((path, pathIndex) =>\n (path.clips ?? []).map((clip, clipIndex) => {\n if (!isSvgPath(clip.d)) return \"\";\n const fillRule = clip.fillRule ? ` clip-rule=\"${clip.fillRule}\"` : \"\";\n return `<clipPath id=\"${pathClipId(pageNumber, pathIndex, clipIndex)}\" clipPathUnits=\"userSpaceOnUse\"><path d=\"${clip.d}\"${fillRule}/></clipPath>`;\n }),\n )\n .join(\"\");\n}\n\nfunction pathClipId(pageNumber: number, pathIndex: number, clipIndex: number): string {\n return `boxpdf-path-clip-${pageNumber}-${pathIndex}-${clipIndex}`;\n}\n\nfunction rgbBmp(image: RasterImage): Uint8Array {\n const stride = Math.ceil((image.width * 3) / 4) * 4;\n const output = new Uint8Array(54 + stride * image.height);\n const view = new DataView(output.buffer);\n output[0] = 0x42;\n output[1] = 0x4d;\n view.setUint32(2, output.length, true);\n view.setUint32(10, 54, true);\n view.setUint32(14, 40, true);\n view.setInt32(18, image.width, true);\n view.setInt32(22, -image.height, true);\n view.setUint16(26, 1, true);\n view.setUint16(28, 24, true);\n view.setUint32(34, stride * image.height, true);\n for (let row = 0; row < image.height; row += 1) {\n for (let column = 0; column < image.width; column += 1) {\n const source = (row * image.width + column) * 3;\n const target = 54 + row * stride + column * 3;\n output[target] = image.data[source + 2] ?? 0;\n output[target + 1] = image.data[source + 1] ?? 0;\n output[target + 2] = image.data[source] ?? 0;\n }\n }\n return output;\n}\n\nfunction rotationTransform(page: ExtractedPage): string {\n switch (page.rotate) {\n case 90:\n return `;transform:translate(${number(page.height)}pt,0) rotate(90deg)`;\n case 180:\n return `;transform:translate(${number(page.width)}pt,${number(page.height)}pt) rotate(180deg)`;\n case 270:\n return `;transform:translate(0,${number(page.width)}pt) rotate(270deg)`;\n default:\n return \"\";\n }\n}\n\nfunction positionedSpan(span: TextSpan, fontAliases: Map<string, string>): string {\n const direction = directionAttribute([span]);\n const style = [\n `left:${number(span.bounds.x)}pt`,\n `bottom:${number(span.bounds.y)}pt`,\n `width:${number(span.bounds.width)}pt`,\n `height:${number(span.bounds.height)}pt`,\n `font-size:${number(span.fontSize)}pt`,\n ...(isCssHexColor(span.color) ? [`color:${span.color}`] : []),\n ...(isUnitInterval(span.fillOpacity) ? [`opacity:${number(span.fillOpacity)}`] : []),\n ...fontStyles(\n span.fontFamily,\n span.fontAssetId ? fontAliases.get(span.fontAssetId) : undefined,\n ),\n ].join(\";\");\n return `<span class=\"pdf-span\"${direction} style=\"${style}\">${escapeHtml(span.text)}</span>`;\n}\n\nasync function writeFlowPage(page: ExtractedPage, write: HtmlWrite): Promise<void> {\n const structured = structurePage(page);\n await write(\n `<section class=\"pdf-page pdf-page--semantic pdf-page--flow\" data-page=\"${page.number}\">`,\n );\n for (const block of structured.blocks) {\n if (block.type === \"table\") await write(tableToHtml(block.table));\n else if (block.type === \"heading\") {\n await write(`<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`);\n } else if (block.type === \"paragraph\") {\n await write(\n `<p${directionAttribute(block.lines.flatMap((line) => line.spans))}>${escapeHtml(block.text)}</p>`,\n );\n } else if (block.type === \"definitionList\") {\n await write(\"<dl>\");\n for (const entry of block.entries) {\n await write(\n `<div><dt>${escapeHtml(entry.term)}</dt><dd>${escapeHtml(entry.description)}</dd></div>`,\n );\n }\n await write(\"</dl>\");\n } else if (block.type === \"cardList\") {\n await write('<div class=\"pdf-semantic-cards\">');\n for (const item of block.items) {\n await write(`<article><h3>${escapeHtml(item.title)}</h3>`);\n for (const detail of item.details) await write(`<p>${escapeHtml(detail)}</p>`);\n await write(\"</article>\");\n }\n await write(\"</div>\");\n } else if (block.type === \"sectionGroup\") {\n await write('<div class=\"pdf-semantic-sections\">');\n for (const item of block.items) {\n await write(`<section><h3>${escapeHtml(item.label)}</h3>`);\n for (const content of item.content) await write(`<p>${escapeHtml(content)}</p>`);\n await write(\"</section>\");\n }\n await write(\"</div>\");\n } else if (block.type === \"employment\") {\n await write(\n `<section><h3>${escapeHtml(block.role)}</h3><p>${escapeHtml(block.organization)}</p><p>${escapeHtml(block.date)}</p></section>`,\n );\n } else {\n const tag = block.ordered ? \"ol\" : \"ul\";\n await write(`<${tag}>`);\n for (const item of block.items) await write(`<li>${escapeHtml(item.text)}</li>`);\n await write(`</${tag}>`);\n }\n }\n await write(\"</section>\");\n}\n\nfunction visualText(\n span: TextSpan,\n pageHeight: number,\n fontAliases: Map<string, string>,\n counterRotateReflectedText = false,\n): string {\n if (span.renderingMode === 3 || span.renderingMode === 7) return \"\";\n if (!span.fontAssetId && isAdobeCjkFont(span.fontFamily)) return \"\";\n const direction = directionAttribute([span]);\n const font = fontStyles(\n span.fontFamily,\n span.fontAssetId ? fontAliases.get(span.fontAssetId) : undefined,\n ).join(\";\");\n const stroke = isCssHexColor(span.strokeColor) ? `stroke:${span.strokeColor}` : \"\";\n const strokeWidth =\n stroke && Number.isFinite(span.strokeWidth) && (span.strokeWidth ?? -1) >= 0\n ? `stroke-width:${number(span.strokeWidth ?? 0)}`\n : \"\";\n const strokeOnly = span.renderingMode === 1 || span.renderingMode === 5;\n const fillOpacity = isUnitInterval(span.fillOpacity)\n ? `fill-opacity:${number(span.fillOpacity)}`\n : \"\";\n const strokeOpacity = isUnitInterval(span.strokeOpacity)\n ? `stroke-opacity:${number(span.strokeOpacity)}`\n : \"\";\n const style = [\n isHebrewPaintOrder(span) ? \"unicode-bidi:bidi-override;direction:ltr\" : \"\",\n span.direction === \"ttb\" ? \"writing-mode:vertical-rl\" : \"\",\n strokeOnly ? \"fill:none\" : isCssHexColor(span.color) ? `fill:${span.color}` : \"\",\n stroke,\n strokeWidth,\n fillOpacity,\n strokeOpacity,\n font,\n ]\n .filter(Boolean)\n .join(\";\");\n const textExtent = span.direction === \"ttb\" ? span.bounds.height : span.bounds.width;\n const textLength =\n textExtent > 0 && !isHebrewPaintOrder(span)\n ? ` textLength=\"${number(textExtent)}\" lengthAdjust=\"${span.direction === \"ttb\" || usesSpacingAdjustment(span) ? \"spacing\" : \"spacingAndGlyphs\"}\"`\n : \"\";\n const transform =\n counterRotateReflectedText && span.transform\n ? ([\n span.transform[0],\n span.transform[1],\n span.transform[2],\n -span.transform[3],\n ] as TextSpan[\"transform\"])\n : span.transform;\n const transformed = hasNonIdentityTransform(transform);\n const rtlOffset = span.direction === \"rtl\" ? span.bounds.width : 0;\n const basisX = transform?.[0] ?? 1;\n const basisY = transform?.[1] ?? 0;\n const anchorX = span.bounds.x + basisX * rtlOffset;\n const anchorY = pageHeight - span.bounds.y + basisY * rtlOffset;\n const position = transformed\n ? ` x=\"0\" y=\"0\" transform=\"matrix(${transform?.map(number).join(\" \")} ${number(anchorX)} ${number(anchorY)})\"`\n : ` x=\"${number(anchorX)}\" y=\"${number(anchorY)}\"`;\n return `<text${direction}${position} font-size=\"${number(span.fontSize)}\"${textLength}${style ? ` style=\"${style}\"` : \"\"}>${escapeHtml(span.text)}</text>`;\n}\n\nfunction isAdobeCjkFont(fontFamily: string | undefined): boolean {\n return /^Adobe(?:Heiti|Song|Kaiti|Ming|Gothic|Mincho)Std-/i.test(fontFamily ?? \"\");\n}\n\nfunction visualType3Text(span: TextSpan, font: EmbeddedType3Font, pageHeight: number): string {\n if (span.renderingMode === 3 || span.renderingMode === 7) return \"\";\n const glyphs = new Map(font.glyphs.map((glyph) => [glyph.code, glyph]));\n const sequence = (span.glyphCodes ?? []).map((code) => glyphs.get(code));\n const totalAdvance = sequence.reduce((total, glyph) => total + (glyph?.advance ?? 0), 0);\n if (totalAdvance <= 0 || span.bounds.width <= 0 || span.fontSize <= 0) return \"\";\n const transform = span.transform ?? [1, 0, 0, 1];\n const outer = `matrix(${transform.map(number).join(\" \")} ${number(span.bounds.x)} ${number(pageHeight - span.bounds.y)})`;\n const xScale = span.bounds.width / totalAdvance;\n let offset = 0;\n let content = \"\";\n for (const glyph of sequence) {\n if (!glyph) continue;\n content += `<g transform=\"translate(${number(offset)} 0)\">${type3Glyph(glyph)}</g>`;\n offset += glyph.advance;\n }\n return `<g transform=\"${outer}\"><g transform=\"scale(${number(xScale)} ${number(-span.fontSize)})\">${content}</g></g>`;\n}\n\nfunction isHebrewPaintOrder(span: TextSpan): boolean {\n return span.direction === \"ltr\" && /[\\u0590-\\u05ff]/u.test(span.text);\n}\n\nfunction usesSpacingAdjustment(span: TextSpan): boolean {\n return !span.fontAssetId && /arial/i.test(span.fontFamily ?? \"\");\n}\n\nfunction type3Glyph(glyph: Type3Glyph): string {\n let output = \"\";\n for (const fill of glyph.fills ?? []) {\n if (!isCssHexColor(fill.color)) continue;\n const points = fill.points.map(([x, y]) => `${number(x)},${number(y)}`).join(\" \");\n const opacity = isUnitInterval(fill.opacity) ? ` fill-opacity=\"${number(fill.opacity)}\"` : \"\";\n output += `<polygon points=\"${points}\" fill=\"${fill.color}\"${opacity}/>`;\n }\n for (const path of glyph.paths ?? []) {\n if (!isSvgPath(path.d)) continue;\n const fill = isCssHexColor(path.fill) ? path.fill : \"none\";\n const stroke = isCssHexColor(path.stroke) ? path.stroke : \"none\";\n const width =\n path.strokeWidth !== undefined && Number.isFinite(path.strokeWidth) && path.strokeWidth >= 0\n ? ` stroke-width=\"${number(path.strokeWidth)}\"`\n : \"\";\n output += `<path d=\"${path.d}\" fill=\"${fill}\" stroke=\"${stroke}\"${width}/>`;\n }\n return (glyph.fills?.length ?? 0) > 64 && glyph.advance > 2\n ? `<g shape-rendering=\"crispEdges\">${output}</g>`\n : output;\n}\n\nfunction isCssHexColor(value: string | undefined): value is string {\n return /^#[\\da-f]{6}$/i.test(value ?? \"\");\n}\n\nfunction isUnitInterval(value: number | undefined): value is number {\n return Number.isFinite(value) && (value ?? -1) >= 0 && (value ?? 2) <= 1;\n}\n\nfunction isSvgPath(value: string): boolean {\n return value.length <= 1_000_000 && /^[\\d\\s.,+\\-eEMmLlCcZz]+$/.test(value);\n}\n\nfunction fontStyles(fontFamily: string | undefined, alias?: string): string[] {\n const normalized = fontFamily?.toLowerCase() ?? \"\";\n const styles: string[] = [];\n let fallback: string | undefined;\n if (/courier|mono|nimbusmono|^cmtt/.test(normalized)) {\n fallback = \"Courier New,Courier,monospace\";\n } else if (\n /times|minion|serif|baskerville|georgia|nimbusrom|guardian.*egyp|^cm[rs]y?\\d/.test(normalized)\n ) {\n fallback = \"Times New Roman,Times,serif\";\n } else if (/helvetica|arial|sans|nimbussan|calibre|myriad|panton|^tte/.test(normalized)) {\n fallback = \"Arial,Helvetica,sans-serif\";\n } else if (/^mstt/.test(normalized)) {\n fallback = \"Arial,Helvetica,sans-serif\";\n }\n if (alias || fallback) styles.push(`font-family:${[alias, fallback].filter(Boolean).join(\",\")}`);\n if (/bold|black|semibold|demi|medi|^tte/.test(normalized)) styles.push(\"font-weight:700\");\n if (/italic|oblique|slant|ital(?:$|[_-])/.test(normalized)) styles.push(\"font-style:italic\");\n return styles;\n}\n\nfunction isMonospace(fontFamily: string | undefined): boolean {\n return /courier|mono/i.test(fontFamily ?? \"\");\n}\n\nfunction usesPositionedSpan(span: TextSpan): boolean {\n return (\n !span.glyphCodes && isMonospace(span.fontFamily) && !hasNonIdentityTransform(span.transform)\n );\n}\n\nfunction hasNonIdentityTransform(transform: TextSpan[\"transform\"]): boolean {\n if (!transform) return false;\n const identity: [number, number, number, number] = [1, 0, 0, 1];\n return transform.some((value, index) => Math.abs(value - (identity[index] ?? 0)) > 0.000_001);\n}\n\nfunction fontFace(font: EmbeddedFont, aliases: Map<string, string>): string {\n if (font.format !== \"truetype\") return \"\";\n const alias = aliases.get(font.id);\n if (!alias) return \"\";\n const styles = fontStyles(font.family, alias).filter(\n (style) => !style.startsWith(\"font-family:\"),\n );\n return `@font-face{font-family:${alias};src:url(data:font/ttf;base64,${base64(font.data)}) format(\"truetype\");${styles.join(\";\")}}`;\n}\n\nfunction base64(bytes: Uint8Array): string {\n const alphabet = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n let output = \"\";\n for (let index = 0; index < bytes.length; index += 3) {\n const first = bytes[index] ?? 0;\n const second = bytes[index + 1] ?? 0;\n const third = bytes[index + 2] ?? 0;\n output += alphabet[first >> 2];\n output += alphabet[((first & 3) << 4) | (second >> 4)];\n output += index + 1 < bytes.length ? alphabet[((second & 15) << 2) | (third >> 6)] : \"=\";\n output += index + 2 < bytes.length ? alphabet[third & 63] : \"=\";\n }\n return output;\n}\n\nfunction directionAttribute(spans: TextSpan[]): string {\n const rtl = spans.filter((span) => span.direction === \"rtl\").length;\n const vertical = spans.filter((span) => span.direction === \"ttb\").length;\n if (vertical > rtl && vertical * 2 >= spans.length) return ' data-direction=\"ttb\"';\n return rtl * 2 >= spans.length && spans.length > 0 ? ' dir=\"rtl\"' : \"\";\n}\n\nfunction number(value: number): string {\n return Number.isFinite(value) ? String(Math.round(value * 1000) / 1000) : \"0\";\n}\n\nfunction escapeAttribute(value: string): string {\n return escapeHtml(value).replaceAll(\"`\", \"&#96;\");\n}\n\nfunction escapeHtml(value: string): string {\n return [...value]\n .map((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n if (codePoint === 13) return \"\\n\";\n return isForbiddenControl(codePoint) ? \"�\" : character;\n })\n .join(\"\")\n .replaceAll(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\")\n .replaceAll(\"'\", \"&#39;\");\n}\n\nfunction isForbiddenControl(codePoint: number): boolean {\n return (\n codePoint <= 8 ||\n codePoint === 11 ||\n codePoint === 12 ||\n (codePoint >= 14 && codePoint <= 31) ||\n codePoint === 127\n );\n}\n\nfunction resolveProfile(options: HtmlWriterOptions): HtmlProfile {\n const legacyProfile = options.layout === \"flow\" ? \"semantic\" : \"visual\";\n if (options.profile && options.layout && options.profile !== legacyProfile) {\n throw new Error(\n `conflicting HTML output options: profile \"${options.profile}\" does not match layout \"${options.layout}\"`,\n );\n }\n return options.profile ?? legacyProfile;\n}\n","import type { ExtractedPage } from \"@boxpdf/reader\";\nimport {\n type SemanticBlock,\n type StructuredPage,\n structurePage,\n type Table,\n tableToRows,\n} from \"@boxpdf/reader/structure\";\n\nexport interface SemanticDocumentStats {\n pagesProcessed: number;\n peakBufferedPages: number;\n peakBufferedLines: number;\n mergedTables: number;\n suppressedFurniture: number;\n}\n\ninterface BufferedPage {\n width: number;\n height: number;\n structured: StructuredPage;\n}\n\ninterface ActiveTable {\n table: Table;\n header: string[] | undefined;\n}\n\nexport async function writeSemanticDocument(\n pages: AsyncIterable<ExtractedPage> | Iterable<ExtractedPage>,\n write: (chunk: string) => void | Promise<void>,\n lookaheadPages: number,\n): Promise<SemanticDocumentStats> {\n const stats: SemanticDocumentStats = {\n pagesProcessed: 0,\n peakBufferedPages: 0,\n peakBufferedLines: 0,\n mergedTables: 0,\n suppressedFurniture: 0,\n };\n const buffer: BufferedPage[] = [];\n const seenFurniture = new Set<string>();\n const sectionLevels: number[] = [];\n let activeTable: ActiveTable | undefined;\n let headerOpen = false;\n let headerHasParagraph = false;\n let contentStarted = false;\n let employmentOpen = false;\n let pendingParagraph:\n | { block: Extract<SemanticBlock, { type: \"paragraph\" }>; height: number }\n | undefined;\n await write('<article class=\"pdf-semantic-document\">');\n\n const closeTable = async () => {\n if (!activeTable) return;\n await write(\"</table>\");\n activeTable = undefined;\n };\n\n const closeSections = async (minimumLevel = 0) => {\n while ((sectionLevels.at(-1) ?? -1) >= minimumLevel && sectionLevels.length > 0) {\n await write(\"</section>\");\n sectionLevels.pop();\n }\n };\n\n const flushPendingParagraph = async () => {\n if (!pendingParagraph) return;\n await write(semanticBlockHtml(pendingParagraph.block));\n pendingParagraph = undefined;\n };\n\n const closeEmployment = async () => {\n if (!employmentOpen) return;\n await write(\"</section>\");\n employmentOpen = false;\n };\n\n const emitPage = async (page: BufferedPage, future: BufferedPage[]) => {\n const futureFurniture = new Set(future.flatMap((candidate) => marginSignatures(candidate)));\n const repeatedFurniture = new Set([...seenFurniture, ...futureFurniture]);\n for (const block of page.structured.blocks) {\n if (isRepeatedFurniture(block, page, repeatedFurniture)) {\n stats.suppressedFurniture += 1;\n continue;\n }\n await flushPendingParagraph();\n if (employmentOpen && block.type !== \"list\") await closeEmployment();\n if (!contentStarted && !headerOpen && block.type === \"heading\" && block.level === 1) {\n await write(`<header><h1>${escapeHtml(block.text)}</h1>`);\n headerOpen = true;\n continue;\n }\n if (headerOpen) {\n if (block.type === \"paragraph\") {\n const tag = isContactBlock(block) ? \"address\" : \"p\";\n await write(`<${tag}>${escapeHtml(block.text)}</${tag}>`);\n headerHasParagraph = true;\n continue;\n }\n if (\n block.type === \"heading\" &&\n !headerHasParagraph &&\n (block.level === 1 || block.text.trimStart().startsWith(\"#\"))\n ) {\n await write(`<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`);\n continue;\n }\n await write(\"</header>\");\n headerOpen = false;\n contentStarted = true;\n }\n if (block.type === \"table\") {\n const rows = tableToRows(block.table);\n if (activeTable && tablesContinue(activeTable.table, block.table, page.width)) {\n const continuationRows = sameRow(activeTable.header, rows[0]) ? rows.slice(1) : rows;\n for (const row of continuationRows) await write(tableRow(row, false));\n activeTable.table = block.table;\n stats.mergedTables += 1;\n continue;\n }\n await closeTable();\n const header = tableHeader(rows);\n await write(\"<table>\");\n for (const [index, row] of rows.entries())\n await write(tableRow(row, Boolean(header && index === 0)));\n activeTable = { table: block.table, header };\n continue;\n }\n if (activeTable && block.type === \"definitionList\" && isFinancialSummary(block)) {\n const columns = activeTable.table.columns.length;\n await write(\n `<tfoot>${block.entries.map((entry) => financialSummaryRow(entry, columns)).join(\"\")}</tfoot>`,\n );\n await closeTable();\n continue;\n }\n await closeTable();\n if (block.type === \"heading\") {\n const level = contentStarted && block.level === 1 ? 2 : block.level;\n await closeSections(level);\n await write(\n `<section data-level=\"${level}\"><h${level}>${escapeHtml(block.text)}</h${level}>`,\n );\n sectionLevels.push(level);\n continue;\n }\n if (block.type === \"paragraph\") {\n if (isTitledRecord(block)) {\n const [institution, ...details] = block.lines;\n if (institution) await write(`<h3>${escapeHtml(institution.text)}</h3>`);\n for (const detail of details) await write(`<p>${escapeHtml(detail.text)}</p>`);\n continue;\n }\n if (isUnmarkedList(block)) {\n await write(\n `<ul>${block.lines.map((line) => `<li>${escapeHtml(line.text)}</li>`).join(\"\")}</ul>`,\n );\n continue;\n }\n pendingParagraph = { block, height: page.height };\n continue;\n }\n if (block.type === \"employment\") {\n await write(\n `<section><h3>${escapeHtml(block.role)}</h3><p>${escapeHtml(block.organization)}</p><p>${escapeHtml(block.date)}</p>`,\n );\n employmentOpen = true;\n continue;\n }\n await write(semanticBlockHtml(block));\n }\n for (const signature of marginSignatures(page)) seenFurniture.add(signature);\n };\n\n for await (const page of pages) {\n const structured = structurePage(page);\n buffer.push({ width: page.width, height: page.height, structured });\n stats.pagesProcessed += 1;\n stats.peakBufferedPages = Math.max(stats.peakBufferedPages, buffer.length);\n stats.peakBufferedLines = Math.max(\n stats.peakBufferedLines,\n buffer.reduce((total, item) => total + item.structured.lines.length, 0),\n );\n if (buffer.length >= lookaheadPages) {\n const ready = buffer.shift();\n if (ready) await emitPage(ready, buffer);\n }\n }\n while (buffer.length > 0) {\n const ready = buffer.shift();\n if (ready) await emitPage(ready, buffer);\n }\n if (headerOpen) await write(\"</header>\");\n await closeTable();\n await closeEmployment();\n if (pendingParagraph && isFooterParagraph(pendingParagraph.block, pendingParagraph.height)) {\n await closeSections();\n await write(`<footer>${semanticBlockHtml(pendingParagraph.block)}</footer>`);\n pendingParagraph = undefined;\n } else {\n await flushPendingParagraph();\n await closeSections();\n }\n await write(\"</article>\");\n return stats;\n}\n\nfunction isContactBlock(block: Extract<SemanticBlock, { type: \"paragraph\" }>): boolean {\n const text = block.text;\n const signals = [\n /@/.test(text),\n /\\+?\\d[\\d().\\s-]{7,}/.test(text),\n /\\bhttps?:\\/\\//i.test(text),\n /\\b\\w+\\.\\w{2,}\\b/i.test(text),\n ];\n return signals.filter(Boolean).length >= 2;\n}\n\nfunction isTitledRecord(block: Extract<SemanticBlock, { type: \"paragraph\" }>): boolean {\n if (block.lines.length < 2) return false;\n const [first, ...rest] = block.lines;\n if (!first || rest.length === 0) return false;\n const firstSize = Math.max(...first.spans.map((span) => span.fontSize));\n const restSize = Math.max(...rest.flatMap((line) => line.spans.map((span) => span.fontSize)));\n const emphasized = first.spans.some((span) =>\n /(?:bold|semibold|demi)/i.test(span.fontFamily ?? \"\"),\n );\n return emphasized || firstSize >= restSize * 1.08;\n}\n\nfunction isUnmarkedList(block: Extract<SemanticBlock, { type: \"paragraph\" }>): boolean {\n if (block.lines.length < 3) return false;\n const first = block.lines[0];\n if (!first) return false;\n const aligned = block.lines.every(\n (line) => Math.abs(line.bounds.x - first.bounds.x) <= Math.max(8, first.bounds.height),\n );\n const separated = block.lines.slice(1).every((line, index) => {\n const previous = block.lines[index];\n if (!previous) return false;\n const gap = previous.bounds.y - (line.bounds.y + line.bounds.height);\n return gap >= Math.min(previous.bounds.height, line.bounds.height) * 0.55;\n });\n return aligned && separated;\n}\n\nfunction isFooterParagraph(\n block: Extract<SemanticBlock, { type: \"paragraph\" }>,\n pageHeight: number,\n): boolean {\n const inBottomMargin = block.lines.every(\n (line) => line.bounds.y + line.bounds.height <= pageHeight * 0.15,\n );\n return inBottomMargin || /^(?:thanks|thank you)\\b/i.test(block.text.trim());\n}\n\nfunction marginSignatures(page: BufferedPage): string[] {\n return page.structured.blocks.flatMap((block) =>\n blockLines(block)\n .filter((line) => isMarginLine(line.bounds.y, line.bounds.height, page.height))\n .map((line) => furnitureSignature(line.text)),\n );\n}\n\nfunction isRepeatedFurniture(\n block: SemanticBlock,\n page: BufferedPage,\n futureFurniture: Set<string>,\n): boolean {\n const lines = blockLines(block);\n return (\n lines.length > 0 &&\n lines.every(\n (line) =>\n isMarginLine(line.bounds.y, line.bounds.height, page.height) &&\n futureFurniture.has(furnitureSignature(line.text)),\n )\n );\n}\n\nfunction blockLines(block: SemanticBlock) {\n return block.type === \"list\" ? block.items.flatMap((item) => item.lines) : block.lines;\n}\n\nfunction isMarginLine(y: number, height: number, pageHeight: number): boolean {\n return y + height <= pageHeight * 0.12 || y >= pageHeight * 0.88;\n}\n\nfunction furnitureSignature(value: string): string {\n return value.toLocaleLowerCase(\"en\").replace(/\\d+/g, \"#\").replace(/\\s+/g, \" \").trim();\n}\n\nfunction tablesContinue(previous: Table, next: Table, pageWidth: number): boolean {\n if (previous.columns.length !== next.columns.length || previous.columns.length < 2) return false;\n return previous.columns.every(\n (column, index) =>\n Math.abs(column - (next.columns[index] ?? Number.POSITIVE_INFINITY)) / pageWidth <= 0.04,\n );\n}\n\nfunction tableHeader(rows: string[][]): string[] | undefined {\n const first = rows[0];\n if (!first) return undefined;\n const later = rows.slice(1).flat();\n return first.every((value) => /\\p{L}/u.test(value) && !isNumericValue(value)) &&\n later.some(isNumericValue)\n ? first\n : undefined;\n}\n\nfunction sameRow(left: string[] | undefined, right: string[] | undefined): boolean {\n return Boolean(\n left &&\n right &&\n left.length === right.length &&\n left.every((value, index) => value === right[index]),\n );\n}\n\nfunction tableRow(row: string[], header: boolean): string {\n const cell = header ? \"th\" : \"td\";\n return `<tr>${row.map((value) => `<${cell}>${escapeHtml(value)}</${cell}>`).join(\"\")}</tr>`;\n}\n\nfunction isFinancialSummary(block: Extract<SemanticBlock, { type: \"definitionList\" }>): boolean {\n return (\n block.entries.length > 0 &&\n block.entries.every((entry) => isNumericValue(entry.description)) &&\n block.entries.some((entry) => /\\p{Sc}|%/u.test(entry.description))\n );\n}\n\nfunction isNumericValue(value: string): boolean {\n return /^(?:\\p{Sc}\\s*)?[\\d.,'’\\s]+(?:\\s*%)?$/u.test(value.trim());\n}\n\nfunction financialSummaryRow(\n entry: Extract<SemanticBlock, { type: \"definitionList\" }>[\"entries\"][number],\n columns: number,\n): string {\n const colspan = columns > 2 ? ` colspan=\"${columns - 1}\"` : \"\";\n return `<tr><th scope=\"row\"${colspan}>${escapeHtml(entry.term)}</th><td>${escapeHtml(entry.description)}</td></tr>`;\n}\n\nfunction semanticBlockHtml(block: Exclude<SemanticBlock, { type: \"table\" }>): string {\n if (block.type === \"heading\")\n return `<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`;\n if (block.type === \"paragraph\") return `<p>${escapeHtml(block.text)}</p>`;\n if (block.type === \"definitionList\") {\n if (\n block.entries.length <= 3 &&\n block.entries.some((entry) => entry.description.trim().split(/\\s+/).length >= 5) &&\n block.entries.every((entry) => /^[A-Z][A-Z\\s/-]*$/.test(entry.term.trim()))\n ) {\n return block.entries\n .map(\n (entry) =>\n `<section><h2>${escapeHtml(titleCase(entry.term))}</h2><p>${escapeHtml(entry.description)}</p></section>`,\n )\n .join(\"\");\n }\n const list = `<dl>${block.entries\n .map(\n (entry) =>\n `<div><dt>${escapeHtml(entry.term)}</dt><dd>${escapeHtml(entry.description)}</dd></div>`,\n )\n .join(\"\")}</dl>`;\n return isFinancialSummary(block) ? `<section>${list}</section>` : list;\n }\n if (block.type === \"cardList\") {\n return `<section><h2>Items ordered</h2><table><thead><tr><th scope=\"col\">Item</th><th scope=\"col\">Quantity</th><th scope=\"col\">Amount</th></tr></thead><tbody>${block.items.map(cardTableRow).join(\"\")}</tbody></table></section>`;\n }\n if (block.type === \"sectionGroup\") {\n return block.items.map(labeledSectionHtml).join(\"\");\n }\n if (block.type === \"employment\") {\n return `<section><h3>${escapeHtml(block.role)}</h3><p>${escapeHtml(block.organization)}</p><p>${escapeHtml(block.date)}</p></section>`;\n }\n const tag = block.ordered ? \"ol\" : \"ul\";\n return `<${tag}>${block.items.map((item) => `<li>${escapeHtml(item.text)}</li>`).join(\"\")}</${tag}>`;\n}\n\nfunction cardTableRow(item: Extract<SemanticBlock, { type: \"cardList\" }>[\"items\"][number]): string {\n const trailing = item.details.at(-1) ?? \"\";\n const match = /^\\s*[×x]\\s*(\\d+)\\s+(.+)$/u.exec(trailing);\n const description = item.details.slice(0, -1).join(\" \");\n const detail = description ? `<br><span>${escapeHtml(description)}</span>` : \"\";\n const quantity = match?.[1] ?? \"\";\n const amount = match?.[2] ?? trailing;\n return `<tr><th scope=\"row\">${escapeHtml(item.title)}${detail}</th><td>${escapeHtml(quantity)}</td><td>${escapeHtml(amount)}</td></tr>`;\n}\n\nfunction labeledSectionHtml(\n item: Extract<SemanticBlock, { type: \"sectionGroup\" }>[\"items\"][number],\n): string {\n const heading = titleCase(item.label);\n const postal = /\\b(?:ship|deliver|mail)(?:ed)?\\b/i.test(item.label);\n if (postal) {\n const [name, ...address] = item.content;\n const content = [name ? `<strong>${escapeHtml(name)}</strong>` : \"\", ...address.map(escapeHtml)]\n .filter(Boolean)\n .join(\"<br>\");\n return `<section><h2>${escapeHtml(heading)}</h2><address>${content}</address></section>`;\n }\n return `<section><h2>${escapeHtml(heading)}</h2>${item.content\n .map(\n (content, index) =>\n `<p>${index === 0 ? `<strong>${escapeHtml(content)}</strong>` : escapeHtml(content)}</p>`,\n )\n .join(\"\")}</section>`;\n}\n\nfunction titleCase(value: string): string {\n const normalized = value.trim().toLocaleLowerCase(\"en\");\n return normalized.replace(/^\\p{L}/u, (letter) => letter.toLocaleUpperCase(\"en\"));\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n"],"mappings":"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","names":["import_structure","escapeHtml","styles"]}
package/dist/index.js CHANGED
@@ -18,6 +18,11 @@ async function writeSemanticDocument(pages, write, lookaheadPages) {
18
18
  const seenFurniture = /* @__PURE__ */ new Set();
19
19
  const sectionLevels = [];
20
20
  let activeTable;
21
+ let headerOpen = false;
22
+ let headerHasParagraph = false;
23
+ let contentStarted = false;
24
+ let employmentOpen = false;
25
+ let pendingParagraph;
21
26
  await write('<article class="pdf-semantic-document">');
22
27
  const closeTable = async () => {
23
28
  if (!activeTable) return;
@@ -30,6 +35,16 @@ async function writeSemanticDocument(pages, write, lookaheadPages) {
30
35
  sectionLevels.pop();
31
36
  }
32
37
  };
38
+ const flushPendingParagraph = async () => {
39
+ if (!pendingParagraph) return;
40
+ await write(semanticBlockHtml(pendingParagraph.block));
41
+ pendingParagraph = void 0;
42
+ };
43
+ const closeEmployment = async () => {
44
+ if (!employmentOpen) return;
45
+ await write("</section>");
46
+ employmentOpen = false;
47
+ };
33
48
  const emitPage = async (page, future) => {
34
49
  const futureFurniture = new Set(future.flatMap((candidate) => marginSignatures(candidate)));
35
50
  const repeatedFurniture = /* @__PURE__ */ new Set([...seenFurniture, ...futureFurniture]);
@@ -38,6 +53,28 @@ async function writeSemanticDocument(pages, write, lookaheadPages) {
38
53
  stats.suppressedFurniture += 1;
39
54
  continue;
40
55
  }
56
+ await flushPendingParagraph();
57
+ if (employmentOpen && block.type !== "list") await closeEmployment();
58
+ if (!contentStarted && !headerOpen && block.type === "heading" && block.level === 1) {
59
+ await write(`<header><h1>${escapeHtml(block.text)}</h1>`);
60
+ headerOpen = true;
61
+ continue;
62
+ }
63
+ if (headerOpen) {
64
+ if (block.type === "paragraph") {
65
+ const tag = isContactBlock(block) ? "address" : "p";
66
+ await write(`<${tag}>${escapeHtml(block.text)}</${tag}>`);
67
+ headerHasParagraph = true;
68
+ continue;
69
+ }
70
+ if (block.type === "heading" && !headerHasParagraph && (block.level === 1 || block.text.trimStart().startsWith("#"))) {
71
+ await write(`<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`);
72
+ continue;
73
+ }
74
+ await write("</header>");
75
+ headerOpen = false;
76
+ contentStarted = true;
77
+ }
41
78
  if (block.type === "table") {
42
79
  const rows = tableToRows(block.table);
43
80
  if (activeTable && tablesContinue(activeTable.table, block.table, page.width)) {
@@ -55,13 +92,45 @@ async function writeSemanticDocument(pages, write, lookaheadPages) {
55
92
  activeTable = { table: block.table, header };
56
93
  continue;
57
94
  }
95
+ if (activeTable && block.type === "definitionList" && isFinancialSummary(block)) {
96
+ const columns = activeTable.table.columns.length;
97
+ await write(
98
+ `<tfoot>${block.entries.map((entry) => financialSummaryRow(entry, columns)).join("")}</tfoot>`
99
+ );
100
+ await closeTable();
101
+ continue;
102
+ }
58
103
  await closeTable();
59
104
  if (block.type === "heading") {
60
- await closeSections(block.level);
105
+ const level = contentStarted && block.level === 1 ? 2 : block.level;
106
+ await closeSections(level);
107
+ await write(
108
+ `<section data-level="${level}"><h${level}>${escapeHtml(block.text)}</h${level}>`
109
+ );
110
+ sectionLevels.push(level);
111
+ continue;
112
+ }
113
+ if (block.type === "paragraph") {
114
+ if (isTitledRecord(block)) {
115
+ const [institution, ...details] = block.lines;
116
+ if (institution) await write(`<h3>${escapeHtml(institution.text)}</h3>`);
117
+ for (const detail of details) await write(`<p>${escapeHtml(detail.text)}</p>`);
118
+ continue;
119
+ }
120
+ if (isUnmarkedList(block)) {
121
+ await write(
122
+ `<ul>${block.lines.map((line) => `<li>${escapeHtml(line.text)}</li>`).join("")}</ul>`
123
+ );
124
+ continue;
125
+ }
126
+ pendingParagraph = { block, height: page.height };
127
+ continue;
128
+ }
129
+ if (block.type === "employment") {
61
130
  await write(
62
- `<section data-level="${block.level}"><h${block.level}>${escapeHtml(block.text)}</h${block.level}>`
131
+ `<section><h3>${escapeHtml(block.role)}</h3><p>${escapeHtml(block.organization)}</p><p>${escapeHtml(block.date)}</p>`
63
132
  );
64
- sectionLevels.push(block.level);
133
+ employmentOpen = true;
65
134
  continue;
66
135
  }
67
136
  await write(semanticBlockHtml(block));
@@ -86,11 +155,62 @@ async function writeSemanticDocument(pages, write, lookaheadPages) {
86
155
  const ready = buffer.shift();
87
156
  if (ready) await emitPage(ready, buffer);
88
157
  }
158
+ if (headerOpen) await write("</header>");
89
159
  await closeTable();
90
- await closeSections();
160
+ await closeEmployment();
161
+ if (pendingParagraph && isFooterParagraph(pendingParagraph.block, pendingParagraph.height)) {
162
+ await closeSections();
163
+ await write(`<footer>${semanticBlockHtml(pendingParagraph.block)}</footer>`);
164
+ pendingParagraph = void 0;
165
+ } else {
166
+ await flushPendingParagraph();
167
+ await closeSections();
168
+ }
91
169
  await write("</article>");
92
170
  return stats;
93
171
  }
172
+ function isContactBlock(block) {
173
+ const text = block.text;
174
+ const signals = [
175
+ /@/.test(text),
176
+ /\+?\d[\d().\s-]{7,}/.test(text),
177
+ /\bhttps?:\/\//i.test(text),
178
+ /\b\w+\.\w{2,}\b/i.test(text)
179
+ ];
180
+ return signals.filter(Boolean).length >= 2;
181
+ }
182
+ function isTitledRecord(block) {
183
+ if (block.lines.length < 2) return false;
184
+ const [first, ...rest] = block.lines;
185
+ if (!first || rest.length === 0) return false;
186
+ const firstSize = Math.max(...first.spans.map((span) => span.fontSize));
187
+ const restSize = Math.max(...rest.flatMap((line) => line.spans.map((span) => span.fontSize)));
188
+ const emphasized = first.spans.some(
189
+ (span) => /(?:bold|semibold|demi)/i.test(span.fontFamily ?? "")
190
+ );
191
+ return emphasized || firstSize >= restSize * 1.08;
192
+ }
193
+ function isUnmarkedList(block) {
194
+ if (block.lines.length < 3) return false;
195
+ const first = block.lines[0];
196
+ if (!first) return false;
197
+ const aligned = block.lines.every(
198
+ (line) => Math.abs(line.bounds.x - first.bounds.x) <= Math.max(8, first.bounds.height)
199
+ );
200
+ const separated = block.lines.slice(1).every((line, index) => {
201
+ const previous = block.lines[index];
202
+ if (!previous) return false;
203
+ const gap = previous.bounds.y - (line.bounds.y + line.bounds.height);
204
+ return gap >= Math.min(previous.bounds.height, line.bounds.height) * 0.55;
205
+ });
206
+ return aligned && separated;
207
+ }
208
+ function isFooterParagraph(block, pageHeight) {
209
+ const inBottomMargin = block.lines.every(
210
+ (line) => line.bounds.y + line.bounds.height <= pageHeight * 0.15
211
+ );
212
+ return inBottomMargin || /^(?:thanks|thank you)\b/i.test(block.text.trim());
213
+ }
94
214
  function marginSignatures(page) {
95
215
  return page.structured.blocks.flatMap(
96
216
  (block) => blockLines(block).filter((line) => isMarginLine(line.bounds.y, line.bounds.height, page.height)).map((line) => furnitureSignature(line.text))
@@ -120,7 +240,8 @@ function tablesContinue(previous, next, pageWidth) {
120
240
  function tableHeader(rows) {
121
241
  const first = rows[0];
122
242
  if (!first) return void 0;
123
- return first.some((value) => /^(?:item|description|feature|qty|unit|amount|total)$/i.test(value)) ? first : void 0;
243
+ const later = rows.slice(1).flat();
244
+ return first.every((value) => /\p{L}/u.test(value) && !isNumericValue(value)) && later.some(isNumericValue) ? first : void 0;
124
245
  }
125
246
  function sameRow(left, right) {
126
247
  return Boolean(
@@ -131,28 +252,68 @@ function tableRow(row, header) {
131
252
  const cell = header ? "th" : "td";
132
253
  return `<tr>${row.map((value) => `<${cell}>${escapeHtml(value)}</${cell}>`).join("")}</tr>`;
133
254
  }
255
+ function isFinancialSummary(block) {
256
+ return block.entries.length > 0 && block.entries.every((entry) => isNumericValue(entry.description)) && block.entries.some((entry) => /\p{Sc}|%/u.test(entry.description));
257
+ }
258
+ function isNumericValue(value) {
259
+ return /^(?:\p{Sc}\s*)?[\d.,'’\s]+(?:\s*%)?$/u.test(value.trim());
260
+ }
261
+ function financialSummaryRow(entry, columns) {
262
+ const colspan = columns > 2 ? ` colspan="${columns - 1}"` : "";
263
+ return `<tr><th scope="row"${colspan}>${escapeHtml(entry.term)}</th><td>${escapeHtml(entry.description)}</td></tr>`;
264
+ }
134
265
  function semanticBlockHtml(block) {
135
266
  if (block.type === "heading")
136
267
  return `<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`;
137
268
  if (block.type === "paragraph") return `<p>${escapeHtml(block.text)}</p>`;
138
269
  if (block.type === "definitionList") {
139
- return `<dl>${block.entries.map(
270
+ if (block.entries.length <= 3 && block.entries.some((entry) => entry.description.trim().split(/\s+/).length >= 5) && block.entries.every((entry) => /^[A-Z][A-Z\s/-]*$/.test(entry.term.trim()))) {
271
+ return block.entries.map(
272
+ (entry) => `<section><h2>${escapeHtml(titleCase(entry.term))}</h2><p>${escapeHtml(entry.description)}</p></section>`
273
+ ).join("");
274
+ }
275
+ const list = `<dl>${block.entries.map(
140
276
  (entry) => `<div><dt>${escapeHtml(entry.term)}</dt><dd>${escapeHtml(entry.description)}</dd></div>`
141
277
  ).join("")}</dl>`;
278
+ return isFinancialSummary(block) ? `<section>${list}</section>` : list;
142
279
  }
143
280
  if (block.type === "cardList") {
144
- return `<div class="pdf-semantic-cards">${block.items.map(
145
- (item) => `<article><h3>${escapeHtml(item.title)}</h3>${item.details.map((detail) => `<p>${escapeHtml(detail)}</p>`).join("")}</article>`
146
- ).join("")}</div>`;
281
+ return `<section><h2>Items ordered</h2><table><thead><tr><th scope="col">Item</th><th scope="col">Quantity</th><th scope="col">Amount</th></tr></thead><tbody>${block.items.map(cardTableRow).join("")}</tbody></table></section>`;
147
282
  }
148
283
  if (block.type === "sectionGroup") {
149
- return `<div class="pdf-semantic-sections">${block.items.map(
150
- (item) => `<section><h3>${escapeHtml(item.label)}</h3>${item.content.map((content) => `<p>${escapeHtml(content)}</p>`).join("")}</section>`
151
- ).join("")}</div>`;
284
+ return block.items.map(labeledSectionHtml).join("");
285
+ }
286
+ if (block.type === "employment") {
287
+ return `<section><h3>${escapeHtml(block.role)}</h3><p>${escapeHtml(block.organization)}</p><p>${escapeHtml(block.date)}</p></section>`;
152
288
  }
153
289
  const tag = block.ordered ? "ol" : "ul";
154
290
  return `<${tag}>${block.items.map((item) => `<li>${escapeHtml(item.text)}</li>`).join("")}</${tag}>`;
155
291
  }
292
+ function cardTableRow(item) {
293
+ const trailing = item.details.at(-1) ?? "";
294
+ const match = /^\s*[×x]\s*(\d+)\s+(.+)$/u.exec(trailing);
295
+ const description = item.details.slice(0, -1).join(" ");
296
+ const detail = description ? `<br><span>${escapeHtml(description)}</span>` : "";
297
+ const quantity = match?.[1] ?? "";
298
+ const amount = match?.[2] ?? trailing;
299
+ return `<tr><th scope="row">${escapeHtml(item.title)}${detail}</th><td>${escapeHtml(quantity)}</td><td>${escapeHtml(amount)}</td></tr>`;
300
+ }
301
+ function labeledSectionHtml(item) {
302
+ const heading = titleCase(item.label);
303
+ const postal = /\b(?:ship|deliver|mail)(?:ed)?\b/i.test(item.label);
304
+ if (postal) {
305
+ const [name, ...address] = item.content;
306
+ const content = [name ? `<strong>${escapeHtml(name)}</strong>` : "", ...address.map(escapeHtml)].filter(Boolean).join("<br>");
307
+ return `<section><h2>${escapeHtml(heading)}</h2><address>${content}</address></section>`;
308
+ }
309
+ return `<section><h2>${escapeHtml(heading)}</h2>${item.content.map(
310
+ (content, index) => `<p>${index === 0 ? `<strong>${escapeHtml(content)}</strong>` : escapeHtml(content)}</p>`
311
+ ).join("")}</section>`;
312
+ }
313
+ function titleCase(value) {
314
+ const normalized = value.trim().toLocaleLowerCase("en");
315
+ return normalized.replace(/^\p{L}/u, (letter) => letter.toLocaleUpperCase("en"));
316
+ }
156
317
  function escapeHtml(value) {
157
318
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
158
319
  }
@@ -415,6 +576,10 @@ async function writeFlowPage(page, write) {
415
576
  await write("</section>");
416
577
  }
417
578
  await write("</div>");
579
+ } else if (block.type === "employment") {
580
+ await write(
581
+ `<section><h3>${escapeHtml2(block.role)}</h3><p>${escapeHtml2(block.organization)}</p><p>${escapeHtml2(block.date)}</p></section>`
582
+ );
418
583
  } else {
419
584
  const tag = block.ordered ? "ol" : "ul";
420
585
  await write(`<${tag}>`);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/semantic-document.ts"],"sourcesContent":["import type {\n EmbeddedFont,\n EmbeddedType3Font,\n ExtractedPage,\n RasterImage,\n TextSpan,\n Type3Glyph,\n VectorPath,\n} from \"@boxpdf/reader\";\nimport { structurePage, tableToHtml } from \"@boxpdf/reader/structure\";\nimport { type SemanticDocumentStats, writeSemanticDocument } from \"./semantic-document.js\";\n\nexport type { SemanticDocumentStats } from \"./semantic-document.js\";\n\nexport type HtmlLayout = \"positioned\" | \"flow\";\nexport type HtmlProfile = \"visual\" | \"semantic\";\nexport type HtmlWrite = (chunk: string) => void | Promise<void>;\n\nexport interface HtmlWriterOptions {\n /** Output intent. Visual preserves page presentation; semantic prioritizes reading order. */\n profile?: HtmlProfile;\n /** @deprecated Use `profile: \"visual\"` or `profile: \"semantic\"`. */\n layout?: HtmlLayout;\n title?: string;\n language?: string;\n includeDocument?: boolean;\n includeStyles?: boolean;\n /** Maximum extracted page models retained for document-level semantic decisions. */\n semanticLookaheadPages?: number;\n /** Receives bounded-buffer and document-inference statistics after semantic output completes. */\n onSemanticStats?: (stats: Readonly<SemanticDocumentStats>) => void;\n}\n\nconst styles = `.pdf-document{margin:0 auto}.pdf-page{box-sizing:border-box;margin:1rem auto;background:#fff;color:#000}.pdf-page--visual,.pdf-page--positioned{position:relative;overflow:hidden}.pdf-page-content{position:absolute;transform-origin:0 0}.pdf-span{position:absolute;white-space:pre;transform-origin:left bottom;unicode-bidi:isolate}.pdf-span[data-direction=ttb]{writing-mode:vertical-rl}.pdf-page--semantic,.pdf-page--flow{max-width:60rem;padding:1rem}.pdf-page--semantic p,.pdf-page--flow p{white-space:pre-wrap;unicode-bidi:plaintext}.pdf-page table{border-collapse:collapse}.pdf-page td{padding:.15rem .4rem;vertical-align:top}`;\n\nexport async function writeHtmlDocument(\n pages: AsyncIterable<ExtractedPage> | Iterable<ExtractedPage>,\n write: HtmlWrite,\n options: HtmlWriterOptions = {},\n): Promise<void> {\n const includeDocument = options.includeDocument ?? true;\n if (includeDocument) {\n await write(\"<!doctype html><html\");\n await write(\n ` lang=\"${escapeAttribute(options.language ?? \"en\")}\"><head><meta charset=\"utf-8\">`,\n );\n await write('<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">');\n await write(`<title>${escapeHtml(options.title ?? \"PDF document\")}</title>`);\n if (options.includeStyles ?? true) await write(`<style>${styles}</style>`);\n await write(\"</head><body>\");\n }\n await write('<main class=\"pdf-document\">');\n if (resolveProfile(options) === \"semantic\") {\n const lookahead = semanticLookahead(options.semanticLookaheadPages);\n const stats = await writeSemanticDocument(pages, write, lookahead);\n options.onSemanticStats?.(stats);\n } else {\n for await (const page of pages) await writePage(page, write, options);\n }\n await write(\"</main>\");\n if (includeDocument) await write(\"</body></html>\");\n}\n\nfunction semanticLookahead(value: number | undefined): number {\n const lookahead = value ?? 4;\n if (!Number.isSafeInteger(lookahead) || lookahead < 1 || lookahead > 16) {\n throw new RangeError(\"semanticLookaheadPages must be an integer between 1 and 16\");\n }\n return lookahead;\n}\n\nexport async function writePage(\n page: ExtractedPage,\n write: HtmlWrite,\n options: HtmlWriterOptions = {},\n): Promise<void> {\n if (resolveProfile(options) === \"semantic\") await writeFlowPage(page, write);\n else await writePositionedPage(page, write, options);\n}\n\nexport async function pageToHtml(\n page: ExtractedPage,\n options: HtmlWriterOptions = {},\n): Promise<string> {\n let output = \"\";\n await writePage(\n page,\n (chunk) => {\n output += chunk;\n },\n options,\n );\n return output;\n}\n\nasync function writePositionedPage(\n page: ExtractedPage,\n write: HtmlWrite,\n options: HtmlWriterOptions,\n): Promise<void> {\n const visualSpans = page.visualSpans ?? page.spans;\n const reflectedOverlay = usesReflectedVisualOverlay(page, visualSpans);\n const quarterTurn = page.rotate === 90 || page.rotate === 270;\n const displayWidth = quarterTurn ? page.height : page.width;\n const displayHeight = quarterTurn ? page.width : page.height;\n await write(\n `<section class=\"pdf-page pdf-page--visual pdf-page--positioned\" data-page=\"${page.number}\" data-rotate=\"${page.rotate}\" style=\"width:${number(displayWidth)}pt;height:${number(displayHeight)}pt\">`,\n );\n const fontAliases = new Map(\n (page.fonts ?? [])\n .filter((font) => font.format === \"truetype\" && !/(?:courier|^TTE)/i.test(font.family ?? \"\"))\n .map((font) => [font.id, `boxpdf-${page.number}-${font.id}`]),\n );\n const type3Fonts = new Map(\n (page.fonts ?? [])\n .filter((font): font is EmbeddedType3Font => font.format === \"type3\")\n .map((font) => [font.id, font]),\n );\n if ((options.includeStyles ?? true) && page.fonts?.length) {\n await write(`<style>${page.fonts.map((font) => fontFace(font, fontAliases)).join(\"\")}</style>`);\n }\n await write(\n `<div class=\"pdf-page-content pdf-page-content--${page.rotate}\" style=\"width:${number(page.width)}pt;height:${number(page.height)}pt${rotationTransform(page)}\">`,\n );\n await write(\n `<svg class=\"pdf-visual-text\" xmlns=\"http://www.w3.org/2000/svg\" width=\"${number(page.width)}pt\" height=\"${number(page.height)}pt\" viewBox=\"0 0 ${number(page.width)} ${number(page.height)}\">`,\n );\n const clipDefinitions =\n imageClipDefinitions(page.images ?? [], page.number, page.height) +\n pathClipDefinitions(page.paths ?? [], page.number);\n if (clipDefinitions) await write(`<defs>${clipDefinitions}</defs>`);\n if (reflectedOverlay) {\n for (const [index, image] of (page.images ?? []).entries()) {\n await write(visualImage(image, page.height, page.number, index));\n }\n }\n for (const fill of page.fills ?? []) {\n const points = fill.points.map(([x, y]) => `${number(x)},${number(page.height - y)}`).join(\" \");\n if (isCssHexColor(fill.color)) {\n const opacity = isUnitInterval(fill.opacity) ? ` fill-opacity=\"${number(fill.opacity)}\"` : \"\";\n await write(`<polygon points=\"${points}\" fill=\"${fill.color}\"${opacity}/>`);\n }\n }\n if (page.paths?.length) {\n await write(`<g transform=\"translate(0 ${number(page.height)}) scale(1 -1)\">`);\n for (const [pathIndex, path] of page.paths.entries()) {\n if (!isSvgPath(path.d)) continue;\n const fill = isCssHexColor(path.fill) ? path.fill : \"none\";\n const stroke = isCssHexColor(path.stroke) ? path.stroke : \"none\";\n const strokeWidth =\n path.strokeWidth !== undefined && Number.isFinite(path.strokeWidth) && path.strokeWidth >= 0\n ? ` stroke-width=\"${number(path.strokeWidth)}\"`\n : \"\";\n const fillRule = path.fillRule ? ` fill-rule=\"${path.fillRule}\"` : \"\";\n const fillOpacity = isUnitInterval(path.fillOpacity)\n ? ` fill-opacity=\"${number(path.fillOpacity)}\"`\n : \"\";\n const strokeOpacity = isUnitInterval(path.strokeOpacity)\n ? ` stroke-opacity=\"${number(path.strokeOpacity)}\"`\n : \"\";\n const dasharray = path.strokeDasharray?.every((value) => Number.isFinite(value) && value >= 0)\n ? ` stroke-dasharray=\"${path.strokeDasharray.map(number).join(\" \")}\"`\n : \"\";\n const dashoffset = Number.isFinite(path.strokeDashoffset)\n ? ` stroke-dashoffset=\"${number(path.strokeDashoffset ?? 0)}\"`\n : \"\";\n const linecap = path.strokeLinecap ? ` stroke-linecap=\"${path.strokeLinecap}\"` : \"\";\n const linejoin = path.strokeLinejoin ? ` stroke-linejoin=\"${path.strokeLinejoin}\"` : \"\";\n let output = `<path d=\"${path.d}\" fill=\"${fill}\" stroke=\"${stroke}\"${strokeWidth}${fillOpacity}${strokeOpacity}${dasharray}${dashoffset}${linecap}${linejoin}${fillRule}/>`;\n for (let index = (path.clips?.length ?? 0) - 1; index >= 0; index -= 1) {\n output = `<g clip-path=\"url(#${pathClipId(page.number, pathIndex, index)})\">${output}</g>`;\n }\n await write(output);\n }\n await write(\"</g>\");\n }\n if (!reflectedOverlay) {\n for (const [index, image] of (page.images ?? []).entries()) {\n await write(visualImage(image, page.height, page.number, index));\n }\n }\n for (const span of visualSpans) {\n if (!usesPositionedSpan(span)) {\n const type3 = span.fontAssetId ? type3Fonts.get(span.fontAssetId) : undefined;\n await write(\n type3\n ? visualType3Text(span, type3, page.height)\n : visualText(span, page.height, fontAliases, reflectedOverlay && page.rotate === 180),\n );\n }\n }\n await write(\"</svg>\");\n for (const span of visualSpans) {\n if (usesPositionedSpan(span)) await write(positionedSpan(span, fontAliases));\n }\n await write(\"</div></section>\");\n}\n\nfunction usesReflectedVisualOverlay(page: ExtractedPage, spans: TextSpan[]): boolean {\n return (\n Boolean(page.images?.length) &&\n Boolean(page.paths?.length || page.fills?.length) &&\n spans.length > 0 &&\n spans.every(\n (span) =>\n span.transform !== undefined &&\n Math.abs(span.transform[0] + 1) < 0.000_001 &&\n Math.abs(span.transform[1]) < 0.000_001 &&\n Math.abs(span.transform[2]) < 0.000_001 &&\n Math.abs(span.transform[3] - 1) < 0.000_001,\n )\n );\n}\n\nfunction visualImage(\n image: RasterImage,\n pageHeight: number,\n pageNumber: number,\n imageIndex: number,\n): string {\n const [a, b, c, d, e, f] = image.transform;\n const transform = [a, -b, -c, d, c + e, pageHeight - d - f].map(number).join(\" \");\n const opacity = isUnitInterval(image.opacity) ? ` opacity=\"${number(image.opacity)}\"` : \"\";\n const mime = image.format === \"jpeg\" ? \"image/jpeg\" : \"image/bmp\";\n const data = image.format === \"jpeg\" ? image.data : rgbBmp(image);\n let output = `<image width=\"1\" height=\"1\" preserveAspectRatio=\"none\" transform=\"matrix(${transform})\" href=\"data:${mime};base64,${base64(data)}\"${opacity}/>`;\n for (let index = (image.clips?.length ?? 0) - 1; index >= 0; index -= 1) {\n output = `<g clip-path=\"url(#${imageClipId(pageNumber, imageIndex, index)})\">${output}</g>`;\n }\n return output;\n}\n\nfunction imageClipDefinitions(\n images: RasterImage[],\n pageNumber: number,\n pageHeight: number,\n): string {\n return images\n .flatMap((image, imageIndex) =>\n (image.clips ?? []).map((clip, clipIndex) => {\n if (!isSvgPath(clip.d)) return \"\";\n const fillRule = clip.fillRule ? ` clip-rule=\"${clip.fillRule}\"` : \"\";\n return `<clipPath id=\"${imageClipId(pageNumber, imageIndex, clipIndex)}\" clipPathUnits=\"userSpaceOnUse\"><path d=\"${clip.d}\" transform=\"translate(0 ${number(pageHeight)}) scale(1 -1)\"${fillRule}/></clipPath>`;\n }),\n )\n .join(\"\");\n}\n\nfunction imageClipId(pageNumber: number, imageIndex: number, clipIndex: number): string {\n return `boxpdf-clip-${pageNumber}-${imageIndex}-${clipIndex}`;\n}\n\nfunction pathClipDefinitions(paths: VectorPath[], pageNumber: number): string {\n return paths\n .flatMap((path, pathIndex) =>\n (path.clips ?? []).map((clip, clipIndex) => {\n if (!isSvgPath(clip.d)) return \"\";\n const fillRule = clip.fillRule ? ` clip-rule=\"${clip.fillRule}\"` : \"\";\n return `<clipPath id=\"${pathClipId(pageNumber, pathIndex, clipIndex)}\" clipPathUnits=\"userSpaceOnUse\"><path d=\"${clip.d}\"${fillRule}/></clipPath>`;\n }),\n )\n .join(\"\");\n}\n\nfunction pathClipId(pageNumber: number, pathIndex: number, clipIndex: number): string {\n return `boxpdf-path-clip-${pageNumber}-${pathIndex}-${clipIndex}`;\n}\n\nfunction rgbBmp(image: RasterImage): Uint8Array {\n const stride = Math.ceil((image.width * 3) / 4) * 4;\n const output = new Uint8Array(54 + stride * image.height);\n const view = new DataView(output.buffer);\n output[0] = 0x42;\n output[1] = 0x4d;\n view.setUint32(2, output.length, true);\n view.setUint32(10, 54, true);\n view.setUint32(14, 40, true);\n view.setInt32(18, image.width, true);\n view.setInt32(22, -image.height, true);\n view.setUint16(26, 1, true);\n view.setUint16(28, 24, true);\n view.setUint32(34, stride * image.height, true);\n for (let row = 0; row < image.height; row += 1) {\n for (let column = 0; column < image.width; column += 1) {\n const source = (row * image.width + column) * 3;\n const target = 54 + row * stride + column * 3;\n output[target] = image.data[source + 2] ?? 0;\n output[target + 1] = image.data[source + 1] ?? 0;\n output[target + 2] = image.data[source] ?? 0;\n }\n }\n return output;\n}\n\nfunction rotationTransform(page: ExtractedPage): string {\n switch (page.rotate) {\n case 90:\n return `;transform:translate(${number(page.height)}pt,0) rotate(90deg)`;\n case 180:\n return `;transform:translate(${number(page.width)}pt,${number(page.height)}pt) rotate(180deg)`;\n case 270:\n return `;transform:translate(0,${number(page.width)}pt) rotate(270deg)`;\n default:\n return \"\";\n }\n}\n\nfunction positionedSpan(span: TextSpan, fontAliases: Map<string, string>): string {\n const direction = directionAttribute([span]);\n const style = [\n `left:${number(span.bounds.x)}pt`,\n `bottom:${number(span.bounds.y)}pt`,\n `width:${number(span.bounds.width)}pt`,\n `height:${number(span.bounds.height)}pt`,\n `font-size:${number(span.fontSize)}pt`,\n ...(isCssHexColor(span.color) ? [`color:${span.color}`] : []),\n ...(isUnitInterval(span.fillOpacity) ? [`opacity:${number(span.fillOpacity)}`] : []),\n ...fontStyles(\n span.fontFamily,\n span.fontAssetId ? fontAliases.get(span.fontAssetId) : undefined,\n ),\n ].join(\";\");\n return `<span class=\"pdf-span\"${direction} style=\"${style}\">${escapeHtml(span.text)}</span>`;\n}\n\nasync function writeFlowPage(page: ExtractedPage, write: HtmlWrite): Promise<void> {\n const structured = structurePage(page);\n await write(\n `<section class=\"pdf-page pdf-page--semantic pdf-page--flow\" data-page=\"${page.number}\">`,\n );\n for (const block of structured.blocks) {\n if (block.type === \"table\") await write(tableToHtml(block.table));\n else if (block.type === \"heading\") {\n await write(`<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`);\n } else if (block.type === \"paragraph\") {\n await write(\n `<p${directionAttribute(block.lines.flatMap((line) => line.spans))}>${escapeHtml(block.text)}</p>`,\n );\n } else if (block.type === \"definitionList\") {\n await write(\"<dl>\");\n for (const entry of block.entries) {\n await write(\n `<div><dt>${escapeHtml(entry.term)}</dt><dd>${escapeHtml(entry.description)}</dd></div>`,\n );\n }\n await write(\"</dl>\");\n } else if (block.type === \"cardList\") {\n await write('<div class=\"pdf-semantic-cards\">');\n for (const item of block.items) {\n await write(`<article><h3>${escapeHtml(item.title)}</h3>`);\n for (const detail of item.details) await write(`<p>${escapeHtml(detail)}</p>`);\n await write(\"</article>\");\n }\n await write(\"</div>\");\n } else if (block.type === \"sectionGroup\") {\n await write('<div class=\"pdf-semantic-sections\">');\n for (const item of block.items) {\n await write(`<section><h3>${escapeHtml(item.label)}</h3>`);\n for (const content of item.content) await write(`<p>${escapeHtml(content)}</p>`);\n await write(\"</section>\");\n }\n await write(\"</div>\");\n } else {\n const tag = block.ordered ? \"ol\" : \"ul\";\n await write(`<${tag}>`);\n for (const item of block.items) await write(`<li>${escapeHtml(item.text)}</li>`);\n await write(`</${tag}>`);\n }\n }\n await write(\"</section>\");\n}\n\nfunction visualText(\n span: TextSpan,\n pageHeight: number,\n fontAliases: Map<string, string>,\n counterRotateReflectedText = false,\n): string {\n if (span.renderingMode === 3 || span.renderingMode === 7) return \"\";\n if (!span.fontAssetId && isAdobeCjkFont(span.fontFamily)) return \"\";\n const direction = directionAttribute([span]);\n const font = fontStyles(\n span.fontFamily,\n span.fontAssetId ? fontAliases.get(span.fontAssetId) : undefined,\n ).join(\";\");\n const stroke = isCssHexColor(span.strokeColor) ? `stroke:${span.strokeColor}` : \"\";\n const strokeWidth =\n stroke && Number.isFinite(span.strokeWidth) && (span.strokeWidth ?? -1) >= 0\n ? `stroke-width:${number(span.strokeWidth ?? 0)}`\n : \"\";\n const strokeOnly = span.renderingMode === 1 || span.renderingMode === 5;\n const fillOpacity = isUnitInterval(span.fillOpacity)\n ? `fill-opacity:${number(span.fillOpacity)}`\n : \"\";\n const strokeOpacity = isUnitInterval(span.strokeOpacity)\n ? `stroke-opacity:${number(span.strokeOpacity)}`\n : \"\";\n const style = [\n isHebrewPaintOrder(span) ? \"unicode-bidi:bidi-override;direction:ltr\" : \"\",\n span.direction === \"ttb\" ? \"writing-mode:vertical-rl\" : \"\",\n strokeOnly ? \"fill:none\" : isCssHexColor(span.color) ? `fill:${span.color}` : \"\",\n stroke,\n strokeWidth,\n fillOpacity,\n strokeOpacity,\n font,\n ]\n .filter(Boolean)\n .join(\";\");\n const textExtent = span.direction === \"ttb\" ? span.bounds.height : span.bounds.width;\n const textLength =\n textExtent > 0 && !isHebrewPaintOrder(span)\n ? ` textLength=\"${number(textExtent)}\" lengthAdjust=\"${span.direction === \"ttb\" || usesSpacingAdjustment(span) ? \"spacing\" : \"spacingAndGlyphs\"}\"`\n : \"\";\n const transform =\n counterRotateReflectedText && span.transform\n ? ([\n span.transform[0],\n span.transform[1],\n span.transform[2],\n -span.transform[3],\n ] as TextSpan[\"transform\"])\n : span.transform;\n const transformed = hasNonIdentityTransform(transform);\n const rtlOffset = span.direction === \"rtl\" ? span.bounds.width : 0;\n const basisX = transform?.[0] ?? 1;\n const basisY = transform?.[1] ?? 0;\n const anchorX = span.bounds.x + basisX * rtlOffset;\n const anchorY = pageHeight - span.bounds.y + basisY * rtlOffset;\n const position = transformed\n ? ` x=\"0\" y=\"0\" transform=\"matrix(${transform?.map(number).join(\" \")} ${number(anchorX)} ${number(anchorY)})\"`\n : ` x=\"${number(anchorX)}\" y=\"${number(anchorY)}\"`;\n return `<text${direction}${position} font-size=\"${number(span.fontSize)}\"${textLength}${style ? ` style=\"${style}\"` : \"\"}>${escapeHtml(span.text)}</text>`;\n}\n\nfunction isAdobeCjkFont(fontFamily: string | undefined): boolean {\n return /^Adobe(?:Heiti|Song|Kaiti|Ming|Gothic|Mincho)Std-/i.test(fontFamily ?? \"\");\n}\n\nfunction visualType3Text(span: TextSpan, font: EmbeddedType3Font, pageHeight: number): string {\n if (span.renderingMode === 3 || span.renderingMode === 7) return \"\";\n const glyphs = new Map(font.glyphs.map((glyph) => [glyph.code, glyph]));\n const sequence = (span.glyphCodes ?? []).map((code) => glyphs.get(code));\n const totalAdvance = sequence.reduce((total, glyph) => total + (glyph?.advance ?? 0), 0);\n if (totalAdvance <= 0 || span.bounds.width <= 0 || span.fontSize <= 0) return \"\";\n const transform = span.transform ?? [1, 0, 0, 1];\n const outer = `matrix(${transform.map(number).join(\" \")} ${number(span.bounds.x)} ${number(pageHeight - span.bounds.y)})`;\n const xScale = span.bounds.width / totalAdvance;\n let offset = 0;\n let content = \"\";\n for (const glyph of sequence) {\n if (!glyph) continue;\n content += `<g transform=\"translate(${number(offset)} 0)\">${type3Glyph(glyph)}</g>`;\n offset += glyph.advance;\n }\n return `<g transform=\"${outer}\"><g transform=\"scale(${number(xScale)} ${number(-span.fontSize)})\">${content}</g></g>`;\n}\n\nfunction isHebrewPaintOrder(span: TextSpan): boolean {\n return span.direction === \"ltr\" && /[\\u0590-\\u05ff]/u.test(span.text);\n}\n\nfunction usesSpacingAdjustment(span: TextSpan): boolean {\n return !span.fontAssetId && /arial/i.test(span.fontFamily ?? \"\");\n}\n\nfunction type3Glyph(glyph: Type3Glyph): string {\n let output = \"\";\n for (const fill of glyph.fills ?? []) {\n if (!isCssHexColor(fill.color)) continue;\n const points = fill.points.map(([x, y]) => `${number(x)},${number(y)}`).join(\" \");\n const opacity = isUnitInterval(fill.opacity) ? ` fill-opacity=\"${number(fill.opacity)}\"` : \"\";\n output += `<polygon points=\"${points}\" fill=\"${fill.color}\"${opacity}/>`;\n }\n for (const path of glyph.paths ?? []) {\n if (!isSvgPath(path.d)) continue;\n const fill = isCssHexColor(path.fill) ? path.fill : \"none\";\n const stroke = isCssHexColor(path.stroke) ? path.stroke : \"none\";\n const width =\n path.strokeWidth !== undefined && Number.isFinite(path.strokeWidth) && path.strokeWidth >= 0\n ? ` stroke-width=\"${number(path.strokeWidth)}\"`\n : \"\";\n output += `<path d=\"${path.d}\" fill=\"${fill}\" stroke=\"${stroke}\"${width}/>`;\n }\n return (glyph.fills?.length ?? 0) > 64 && glyph.advance > 2\n ? `<g shape-rendering=\"crispEdges\">${output}</g>`\n : output;\n}\n\nfunction isCssHexColor(value: string | undefined): value is string {\n return /^#[\\da-f]{6}$/i.test(value ?? \"\");\n}\n\nfunction isUnitInterval(value: number | undefined): value is number {\n return Number.isFinite(value) && (value ?? -1) >= 0 && (value ?? 2) <= 1;\n}\n\nfunction isSvgPath(value: string): boolean {\n return value.length <= 1_000_000 && /^[\\d\\s.,+\\-eEMmLlCcZz]+$/.test(value);\n}\n\nfunction fontStyles(fontFamily: string | undefined, alias?: string): string[] {\n const normalized = fontFamily?.toLowerCase() ?? \"\";\n const styles: string[] = [];\n let fallback: string | undefined;\n if (/courier|mono|nimbusmono|^cmtt/.test(normalized)) {\n fallback = \"Courier New,Courier,monospace\";\n } else if (\n /times|minion|serif|baskerville|georgia|nimbusrom|guardian.*egyp|^cm[rs]y?\\d/.test(normalized)\n ) {\n fallback = \"Times New Roman,Times,serif\";\n } else if (/helvetica|arial|sans|nimbussan|calibre|myriad|panton|^tte/.test(normalized)) {\n fallback = \"Arial,Helvetica,sans-serif\";\n } else if (/^mstt/.test(normalized)) {\n fallback = \"Arial,Helvetica,sans-serif\";\n }\n if (alias || fallback) styles.push(`font-family:${[alias, fallback].filter(Boolean).join(\",\")}`);\n if (/bold|black|semibold|demi|medi|^tte/.test(normalized)) styles.push(\"font-weight:700\");\n if (/italic|oblique|slant|ital(?:$|[_-])/.test(normalized)) styles.push(\"font-style:italic\");\n return styles;\n}\n\nfunction isMonospace(fontFamily: string | undefined): boolean {\n return /courier|mono/i.test(fontFamily ?? \"\");\n}\n\nfunction usesPositionedSpan(span: TextSpan): boolean {\n return (\n !span.glyphCodes && isMonospace(span.fontFamily) && !hasNonIdentityTransform(span.transform)\n );\n}\n\nfunction hasNonIdentityTransform(transform: TextSpan[\"transform\"]): boolean {\n if (!transform) return false;\n const identity: [number, number, number, number] = [1, 0, 0, 1];\n return transform.some((value, index) => Math.abs(value - (identity[index] ?? 0)) > 0.000_001);\n}\n\nfunction fontFace(font: EmbeddedFont, aliases: Map<string, string>): string {\n if (font.format !== \"truetype\") return \"\";\n const alias = aliases.get(font.id);\n if (!alias) return \"\";\n const styles = fontStyles(font.family, alias).filter(\n (style) => !style.startsWith(\"font-family:\"),\n );\n return `@font-face{font-family:${alias};src:url(data:font/ttf;base64,${base64(font.data)}) format(\"truetype\");${styles.join(\";\")}}`;\n}\n\nfunction base64(bytes: Uint8Array): string {\n const alphabet = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n let output = \"\";\n for (let index = 0; index < bytes.length; index += 3) {\n const first = bytes[index] ?? 0;\n const second = bytes[index + 1] ?? 0;\n const third = bytes[index + 2] ?? 0;\n output += alphabet[first >> 2];\n output += alphabet[((first & 3) << 4) | (second >> 4)];\n output += index + 1 < bytes.length ? alphabet[((second & 15) << 2) | (third >> 6)] : \"=\";\n output += index + 2 < bytes.length ? alphabet[third & 63] : \"=\";\n }\n return output;\n}\n\nfunction directionAttribute(spans: TextSpan[]): string {\n const rtl = spans.filter((span) => span.direction === \"rtl\").length;\n const vertical = spans.filter((span) => span.direction === \"ttb\").length;\n if (vertical > rtl && vertical * 2 >= spans.length) return ' data-direction=\"ttb\"';\n return rtl * 2 >= spans.length && spans.length > 0 ? ' dir=\"rtl\"' : \"\";\n}\n\nfunction number(value: number): string {\n return Number.isFinite(value) ? String(Math.round(value * 1000) / 1000) : \"0\";\n}\n\nfunction escapeAttribute(value: string): string {\n return escapeHtml(value).replaceAll(\"`\", \"&#96;\");\n}\n\nfunction escapeHtml(value: string): string {\n return [...value]\n .map((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n if (codePoint === 13) return \"\\n\";\n return isForbiddenControl(codePoint) ? \"�\" : character;\n })\n .join(\"\")\n .replaceAll(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\")\n .replaceAll(\"'\", \"&#39;\");\n}\n\nfunction isForbiddenControl(codePoint: number): boolean {\n return (\n codePoint <= 8 ||\n codePoint === 11 ||\n codePoint === 12 ||\n (codePoint >= 14 && codePoint <= 31) ||\n codePoint === 127\n );\n}\n\nfunction resolveProfile(options: HtmlWriterOptions): HtmlProfile {\n const legacyProfile = options.layout === \"flow\" ? \"semantic\" : \"visual\";\n if (options.profile && options.layout && options.profile !== legacyProfile) {\n throw new Error(\n `conflicting HTML output options: profile \"${options.profile}\" does not match layout \"${options.layout}\"`,\n );\n }\n return options.profile ?? legacyProfile;\n}\n","import type { ExtractedPage } from \"@boxpdf/reader\";\nimport {\n type SemanticBlock,\n type StructuredPage,\n structurePage,\n type Table,\n tableToRows,\n} from \"@boxpdf/reader/structure\";\n\nexport interface SemanticDocumentStats {\n pagesProcessed: number;\n peakBufferedPages: number;\n peakBufferedLines: number;\n mergedTables: number;\n suppressedFurniture: number;\n}\n\ninterface BufferedPage {\n width: number;\n height: number;\n structured: StructuredPage;\n}\n\ninterface ActiveTable {\n table: Table;\n header: string[] | undefined;\n}\n\nexport async function writeSemanticDocument(\n pages: AsyncIterable<ExtractedPage> | Iterable<ExtractedPage>,\n write: (chunk: string) => void | Promise<void>,\n lookaheadPages: number,\n): Promise<SemanticDocumentStats> {\n const stats: SemanticDocumentStats = {\n pagesProcessed: 0,\n peakBufferedPages: 0,\n peakBufferedLines: 0,\n mergedTables: 0,\n suppressedFurniture: 0,\n };\n const buffer: BufferedPage[] = [];\n const seenFurniture = new Set<string>();\n const sectionLevels: number[] = [];\n let activeTable: ActiveTable | undefined;\n await write('<article class=\"pdf-semantic-document\">');\n\n const closeTable = async () => {\n if (!activeTable) return;\n await write(\"</table>\");\n activeTable = undefined;\n };\n\n const closeSections = async (minimumLevel = 0) => {\n while ((sectionLevels.at(-1) ?? -1) >= minimumLevel && sectionLevels.length > 0) {\n await write(\"</section>\");\n sectionLevels.pop();\n }\n };\n\n const emitPage = async (page: BufferedPage, future: BufferedPage[]) => {\n const futureFurniture = new Set(future.flatMap((candidate) => marginSignatures(candidate)));\n const repeatedFurniture = new Set([...seenFurniture, ...futureFurniture]);\n for (const block of page.structured.blocks) {\n if (isRepeatedFurniture(block, page, repeatedFurniture)) {\n stats.suppressedFurniture += 1;\n continue;\n }\n if (block.type === \"table\") {\n const rows = tableToRows(block.table);\n if (activeTable && tablesContinue(activeTable.table, block.table, page.width)) {\n const continuationRows = sameRow(activeTable.header, rows[0]) ? rows.slice(1) : rows;\n for (const row of continuationRows) await write(tableRow(row, false));\n activeTable.table = block.table;\n stats.mergedTables += 1;\n continue;\n }\n await closeTable();\n const header = tableHeader(rows);\n await write(\"<table>\");\n for (const [index, row] of rows.entries())\n await write(tableRow(row, Boolean(header && index === 0)));\n activeTable = { table: block.table, header };\n continue;\n }\n await closeTable();\n if (block.type === \"heading\") {\n await closeSections(block.level);\n await write(\n `<section data-level=\"${block.level}\"><h${block.level}>${escapeHtml(block.text)}</h${block.level}>`,\n );\n sectionLevels.push(block.level);\n continue;\n }\n await write(semanticBlockHtml(block));\n }\n for (const signature of marginSignatures(page)) seenFurniture.add(signature);\n };\n\n for await (const page of pages) {\n const structured = structurePage(page);\n buffer.push({ width: page.width, height: page.height, structured });\n stats.pagesProcessed += 1;\n stats.peakBufferedPages = Math.max(stats.peakBufferedPages, buffer.length);\n stats.peakBufferedLines = Math.max(\n stats.peakBufferedLines,\n buffer.reduce((total, item) => total + item.structured.lines.length, 0),\n );\n if (buffer.length >= lookaheadPages) {\n const ready = buffer.shift();\n if (ready) await emitPage(ready, buffer);\n }\n }\n while (buffer.length > 0) {\n const ready = buffer.shift();\n if (ready) await emitPage(ready, buffer);\n }\n await closeTable();\n await closeSections();\n await write(\"</article>\");\n return stats;\n}\n\nfunction marginSignatures(page: BufferedPage): string[] {\n return page.structured.blocks.flatMap((block) =>\n blockLines(block)\n .filter((line) => isMarginLine(line.bounds.y, line.bounds.height, page.height))\n .map((line) => furnitureSignature(line.text)),\n );\n}\n\nfunction isRepeatedFurniture(\n block: SemanticBlock,\n page: BufferedPage,\n futureFurniture: Set<string>,\n): boolean {\n const lines = blockLines(block);\n return (\n lines.length > 0 &&\n lines.every(\n (line) =>\n isMarginLine(line.bounds.y, line.bounds.height, page.height) &&\n futureFurniture.has(furnitureSignature(line.text)),\n )\n );\n}\n\nfunction blockLines(block: SemanticBlock) {\n return block.type === \"list\" ? block.items.flatMap((item) => item.lines) : block.lines;\n}\n\nfunction isMarginLine(y: number, height: number, pageHeight: number): boolean {\n return y + height <= pageHeight * 0.12 || y >= pageHeight * 0.88;\n}\n\nfunction furnitureSignature(value: string): string {\n return value.toLocaleLowerCase(\"en\").replace(/\\d+/g, \"#\").replace(/\\s+/g, \" \").trim();\n}\n\nfunction tablesContinue(previous: Table, next: Table, pageWidth: number): boolean {\n if (previous.columns.length !== next.columns.length || previous.columns.length < 2) return false;\n return previous.columns.every(\n (column, index) =>\n Math.abs(column - (next.columns[index] ?? Number.POSITIVE_INFINITY)) / pageWidth <= 0.04,\n );\n}\n\nfunction tableHeader(rows: string[][]): string[] | undefined {\n const first = rows[0];\n if (!first) return undefined;\n return first.some((value) => /^(?:item|description|feature|qty|unit|amount|total)$/i.test(value))\n ? first\n : undefined;\n}\n\nfunction sameRow(left: string[] | undefined, right: string[] | undefined): boolean {\n return Boolean(\n left &&\n right &&\n left.length === right.length &&\n left.every((value, index) => value === right[index]),\n );\n}\n\nfunction tableRow(row: string[], header: boolean): string {\n const cell = header ? \"th\" : \"td\";\n return `<tr>${row.map((value) => `<${cell}>${escapeHtml(value)}</${cell}>`).join(\"\")}</tr>`;\n}\n\nfunction semanticBlockHtml(block: Exclude<SemanticBlock, { type: \"table\" }>): string {\n if (block.type === \"heading\")\n return `<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`;\n if (block.type === \"paragraph\") return `<p>${escapeHtml(block.text)}</p>`;\n if (block.type === \"definitionList\") {\n return `<dl>${block.entries\n .map(\n (entry) =>\n `<div><dt>${escapeHtml(entry.term)}</dt><dd>${escapeHtml(entry.description)}</dd></div>`,\n )\n .join(\"\")}</dl>`;\n }\n if (block.type === \"cardList\") {\n return `<div class=\"pdf-semantic-cards\">${block.items\n .map(\n (item) =>\n `<article><h3>${escapeHtml(item.title)}</h3>${item.details.map((detail) => `<p>${escapeHtml(detail)}</p>`).join(\"\")}</article>`,\n )\n .join(\"\")}</div>`;\n }\n if (block.type === \"sectionGroup\") {\n return `<div class=\"pdf-semantic-sections\">${block.items\n .map(\n (item) =>\n `<section><h3>${escapeHtml(item.label)}</h3>${item.content.map((content) => `<p>${escapeHtml(content)}</p>`).join(\"\")}</section>`,\n )\n .join(\"\")}</div>`;\n }\n const tag = block.ordered ? \"ol\" : \"ul\";\n return `<${tag}>${block.items.map((item) => `<li>${escapeHtml(item.text)}</li>`).join(\"\")}</${tag}>`;\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n"],"mappings":"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","names":["structurePage","escapeHtml","structurePage","styles"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/semantic-document.ts"],"sourcesContent":["import type {\n EmbeddedFont,\n EmbeddedType3Font,\n ExtractedPage,\n RasterImage,\n TextSpan,\n Type3Glyph,\n VectorPath,\n} from \"@boxpdf/reader\";\nimport { structurePage, tableToHtml } from \"@boxpdf/reader/structure\";\nimport { type SemanticDocumentStats, writeSemanticDocument } from \"./semantic-document.js\";\n\nexport type { SemanticDocumentStats } from \"./semantic-document.js\";\n\nexport type HtmlLayout = \"positioned\" | \"flow\";\nexport type HtmlProfile = \"visual\" | \"semantic\";\nexport type HtmlWrite = (chunk: string) => void | Promise<void>;\n\nexport interface HtmlWriterOptions {\n /** Output intent. Visual preserves page presentation; semantic prioritizes reading order. */\n profile?: HtmlProfile;\n /** @deprecated Use `profile: \"visual\"` or `profile: \"semantic\"`. */\n layout?: HtmlLayout;\n title?: string;\n language?: string;\n includeDocument?: boolean;\n includeStyles?: boolean;\n /** Maximum extracted page models retained for document-level semantic decisions. */\n semanticLookaheadPages?: number;\n /** Receives bounded-buffer and document-inference statistics after semantic output completes. */\n onSemanticStats?: (stats: Readonly<SemanticDocumentStats>) => void;\n}\n\nconst styles = `.pdf-document{margin:0 auto}.pdf-page{box-sizing:border-box;margin:1rem auto;background:#fff;color:#000}.pdf-page--visual,.pdf-page--positioned{position:relative;overflow:hidden}.pdf-page-content{position:absolute;transform-origin:0 0}.pdf-span{position:absolute;white-space:pre;transform-origin:left bottom;unicode-bidi:isolate}.pdf-span[data-direction=ttb]{writing-mode:vertical-rl}.pdf-page--semantic,.pdf-page--flow{max-width:60rem;padding:1rem}.pdf-page--semantic p,.pdf-page--flow p{white-space:pre-wrap;unicode-bidi:plaintext}.pdf-page table{border-collapse:collapse}.pdf-page td{padding:.15rem .4rem;vertical-align:top}`;\n\nexport async function writeHtmlDocument(\n pages: AsyncIterable<ExtractedPage> | Iterable<ExtractedPage>,\n write: HtmlWrite,\n options: HtmlWriterOptions = {},\n): Promise<void> {\n const includeDocument = options.includeDocument ?? true;\n if (includeDocument) {\n await write(\"<!doctype html><html\");\n await write(\n ` lang=\"${escapeAttribute(options.language ?? \"en\")}\"><head><meta charset=\"utf-8\">`,\n );\n await write('<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">');\n await write(`<title>${escapeHtml(options.title ?? \"PDF document\")}</title>`);\n if (options.includeStyles ?? true) await write(`<style>${styles}</style>`);\n await write(\"</head><body>\");\n }\n await write('<main class=\"pdf-document\">');\n if (resolveProfile(options) === \"semantic\") {\n const lookahead = semanticLookahead(options.semanticLookaheadPages);\n const stats = await writeSemanticDocument(pages, write, lookahead);\n options.onSemanticStats?.(stats);\n } else {\n for await (const page of pages) await writePage(page, write, options);\n }\n await write(\"</main>\");\n if (includeDocument) await write(\"</body></html>\");\n}\n\nfunction semanticLookahead(value: number | undefined): number {\n const lookahead = value ?? 4;\n if (!Number.isSafeInteger(lookahead) || lookahead < 1 || lookahead > 16) {\n throw new RangeError(\"semanticLookaheadPages must be an integer between 1 and 16\");\n }\n return lookahead;\n}\n\nexport async function writePage(\n page: ExtractedPage,\n write: HtmlWrite,\n options: HtmlWriterOptions = {},\n): Promise<void> {\n if (resolveProfile(options) === \"semantic\") await writeFlowPage(page, write);\n else await writePositionedPage(page, write, options);\n}\n\nexport async function pageToHtml(\n page: ExtractedPage,\n options: HtmlWriterOptions = {},\n): Promise<string> {\n let output = \"\";\n await writePage(\n page,\n (chunk) => {\n output += chunk;\n },\n options,\n );\n return output;\n}\n\nasync function writePositionedPage(\n page: ExtractedPage,\n write: HtmlWrite,\n options: HtmlWriterOptions,\n): Promise<void> {\n const visualSpans = page.visualSpans ?? page.spans;\n const reflectedOverlay = usesReflectedVisualOverlay(page, visualSpans);\n const quarterTurn = page.rotate === 90 || page.rotate === 270;\n const displayWidth = quarterTurn ? page.height : page.width;\n const displayHeight = quarterTurn ? page.width : page.height;\n await write(\n `<section class=\"pdf-page pdf-page--visual pdf-page--positioned\" data-page=\"${page.number}\" data-rotate=\"${page.rotate}\" style=\"width:${number(displayWidth)}pt;height:${number(displayHeight)}pt\">`,\n );\n const fontAliases = new Map(\n (page.fonts ?? [])\n .filter((font) => font.format === \"truetype\" && !/(?:courier|^TTE)/i.test(font.family ?? \"\"))\n .map((font) => [font.id, `boxpdf-${page.number}-${font.id}`]),\n );\n const type3Fonts = new Map(\n (page.fonts ?? [])\n .filter((font): font is EmbeddedType3Font => font.format === \"type3\")\n .map((font) => [font.id, font]),\n );\n if ((options.includeStyles ?? true) && page.fonts?.length) {\n await write(`<style>${page.fonts.map((font) => fontFace(font, fontAliases)).join(\"\")}</style>`);\n }\n await write(\n `<div class=\"pdf-page-content pdf-page-content--${page.rotate}\" style=\"width:${number(page.width)}pt;height:${number(page.height)}pt${rotationTransform(page)}\">`,\n );\n await write(\n `<svg class=\"pdf-visual-text\" xmlns=\"http://www.w3.org/2000/svg\" width=\"${number(page.width)}pt\" height=\"${number(page.height)}pt\" viewBox=\"0 0 ${number(page.width)} ${number(page.height)}\">`,\n );\n const clipDefinitions =\n imageClipDefinitions(page.images ?? [], page.number, page.height) +\n pathClipDefinitions(page.paths ?? [], page.number);\n if (clipDefinitions) await write(`<defs>${clipDefinitions}</defs>`);\n if (reflectedOverlay) {\n for (const [index, image] of (page.images ?? []).entries()) {\n await write(visualImage(image, page.height, page.number, index));\n }\n }\n for (const fill of page.fills ?? []) {\n const points = fill.points.map(([x, y]) => `${number(x)},${number(page.height - y)}`).join(\" \");\n if (isCssHexColor(fill.color)) {\n const opacity = isUnitInterval(fill.opacity) ? ` fill-opacity=\"${number(fill.opacity)}\"` : \"\";\n await write(`<polygon points=\"${points}\" fill=\"${fill.color}\"${opacity}/>`);\n }\n }\n if (page.paths?.length) {\n await write(`<g transform=\"translate(0 ${number(page.height)}) scale(1 -1)\">`);\n for (const [pathIndex, path] of page.paths.entries()) {\n if (!isSvgPath(path.d)) continue;\n const fill = isCssHexColor(path.fill) ? path.fill : \"none\";\n const stroke = isCssHexColor(path.stroke) ? path.stroke : \"none\";\n const strokeWidth =\n path.strokeWidth !== undefined && Number.isFinite(path.strokeWidth) && path.strokeWidth >= 0\n ? ` stroke-width=\"${number(path.strokeWidth)}\"`\n : \"\";\n const fillRule = path.fillRule ? ` fill-rule=\"${path.fillRule}\"` : \"\";\n const fillOpacity = isUnitInterval(path.fillOpacity)\n ? ` fill-opacity=\"${number(path.fillOpacity)}\"`\n : \"\";\n const strokeOpacity = isUnitInterval(path.strokeOpacity)\n ? ` stroke-opacity=\"${number(path.strokeOpacity)}\"`\n : \"\";\n const dasharray = path.strokeDasharray?.every((value) => Number.isFinite(value) && value >= 0)\n ? ` stroke-dasharray=\"${path.strokeDasharray.map(number).join(\" \")}\"`\n : \"\";\n const dashoffset = Number.isFinite(path.strokeDashoffset)\n ? ` stroke-dashoffset=\"${number(path.strokeDashoffset ?? 0)}\"`\n : \"\";\n const linecap = path.strokeLinecap ? ` stroke-linecap=\"${path.strokeLinecap}\"` : \"\";\n const linejoin = path.strokeLinejoin ? ` stroke-linejoin=\"${path.strokeLinejoin}\"` : \"\";\n let output = `<path d=\"${path.d}\" fill=\"${fill}\" stroke=\"${stroke}\"${strokeWidth}${fillOpacity}${strokeOpacity}${dasharray}${dashoffset}${linecap}${linejoin}${fillRule}/>`;\n for (let index = (path.clips?.length ?? 0) - 1; index >= 0; index -= 1) {\n output = `<g clip-path=\"url(#${pathClipId(page.number, pathIndex, index)})\">${output}</g>`;\n }\n await write(output);\n }\n await write(\"</g>\");\n }\n if (!reflectedOverlay) {\n for (const [index, image] of (page.images ?? []).entries()) {\n await write(visualImage(image, page.height, page.number, index));\n }\n }\n for (const span of visualSpans) {\n if (!usesPositionedSpan(span)) {\n const type3 = span.fontAssetId ? type3Fonts.get(span.fontAssetId) : undefined;\n await write(\n type3\n ? visualType3Text(span, type3, page.height)\n : visualText(span, page.height, fontAliases, reflectedOverlay && page.rotate === 180),\n );\n }\n }\n await write(\"</svg>\");\n for (const span of visualSpans) {\n if (usesPositionedSpan(span)) await write(positionedSpan(span, fontAliases));\n }\n await write(\"</div></section>\");\n}\n\nfunction usesReflectedVisualOverlay(page: ExtractedPage, spans: TextSpan[]): boolean {\n return (\n Boolean(page.images?.length) &&\n Boolean(page.paths?.length || page.fills?.length) &&\n spans.length > 0 &&\n spans.every(\n (span) =>\n span.transform !== undefined &&\n Math.abs(span.transform[0] + 1) < 0.000_001 &&\n Math.abs(span.transform[1]) < 0.000_001 &&\n Math.abs(span.transform[2]) < 0.000_001 &&\n Math.abs(span.transform[3] - 1) < 0.000_001,\n )\n );\n}\n\nfunction visualImage(\n image: RasterImage,\n pageHeight: number,\n pageNumber: number,\n imageIndex: number,\n): string {\n const [a, b, c, d, e, f] = image.transform;\n const transform = [a, -b, -c, d, c + e, pageHeight - d - f].map(number).join(\" \");\n const opacity = isUnitInterval(image.opacity) ? ` opacity=\"${number(image.opacity)}\"` : \"\";\n const mime = image.format === \"jpeg\" ? \"image/jpeg\" : \"image/bmp\";\n const data = image.format === \"jpeg\" ? image.data : rgbBmp(image);\n let output = `<image width=\"1\" height=\"1\" preserveAspectRatio=\"none\" transform=\"matrix(${transform})\" href=\"data:${mime};base64,${base64(data)}\"${opacity}/>`;\n for (let index = (image.clips?.length ?? 0) - 1; index >= 0; index -= 1) {\n output = `<g clip-path=\"url(#${imageClipId(pageNumber, imageIndex, index)})\">${output}</g>`;\n }\n return output;\n}\n\nfunction imageClipDefinitions(\n images: RasterImage[],\n pageNumber: number,\n pageHeight: number,\n): string {\n return images\n .flatMap((image, imageIndex) =>\n (image.clips ?? []).map((clip, clipIndex) => {\n if (!isSvgPath(clip.d)) return \"\";\n const fillRule = clip.fillRule ? ` clip-rule=\"${clip.fillRule}\"` : \"\";\n return `<clipPath id=\"${imageClipId(pageNumber, imageIndex, clipIndex)}\" clipPathUnits=\"userSpaceOnUse\"><path d=\"${clip.d}\" transform=\"translate(0 ${number(pageHeight)}) scale(1 -1)\"${fillRule}/></clipPath>`;\n }),\n )\n .join(\"\");\n}\n\nfunction imageClipId(pageNumber: number, imageIndex: number, clipIndex: number): string {\n return `boxpdf-clip-${pageNumber}-${imageIndex}-${clipIndex}`;\n}\n\nfunction pathClipDefinitions(paths: VectorPath[], pageNumber: number): string {\n return paths\n .flatMap((path, pathIndex) =>\n (path.clips ?? []).map((clip, clipIndex) => {\n if (!isSvgPath(clip.d)) return \"\";\n const fillRule = clip.fillRule ? ` clip-rule=\"${clip.fillRule}\"` : \"\";\n return `<clipPath id=\"${pathClipId(pageNumber, pathIndex, clipIndex)}\" clipPathUnits=\"userSpaceOnUse\"><path d=\"${clip.d}\"${fillRule}/></clipPath>`;\n }),\n )\n .join(\"\");\n}\n\nfunction pathClipId(pageNumber: number, pathIndex: number, clipIndex: number): string {\n return `boxpdf-path-clip-${pageNumber}-${pathIndex}-${clipIndex}`;\n}\n\nfunction rgbBmp(image: RasterImage): Uint8Array {\n const stride = Math.ceil((image.width * 3) / 4) * 4;\n const output = new Uint8Array(54 + stride * image.height);\n const view = new DataView(output.buffer);\n output[0] = 0x42;\n output[1] = 0x4d;\n view.setUint32(2, output.length, true);\n view.setUint32(10, 54, true);\n view.setUint32(14, 40, true);\n view.setInt32(18, image.width, true);\n view.setInt32(22, -image.height, true);\n view.setUint16(26, 1, true);\n view.setUint16(28, 24, true);\n view.setUint32(34, stride * image.height, true);\n for (let row = 0; row < image.height; row += 1) {\n for (let column = 0; column < image.width; column += 1) {\n const source = (row * image.width + column) * 3;\n const target = 54 + row * stride + column * 3;\n output[target] = image.data[source + 2] ?? 0;\n output[target + 1] = image.data[source + 1] ?? 0;\n output[target + 2] = image.data[source] ?? 0;\n }\n }\n return output;\n}\n\nfunction rotationTransform(page: ExtractedPage): string {\n switch (page.rotate) {\n case 90:\n return `;transform:translate(${number(page.height)}pt,0) rotate(90deg)`;\n case 180:\n return `;transform:translate(${number(page.width)}pt,${number(page.height)}pt) rotate(180deg)`;\n case 270:\n return `;transform:translate(0,${number(page.width)}pt) rotate(270deg)`;\n default:\n return \"\";\n }\n}\n\nfunction positionedSpan(span: TextSpan, fontAliases: Map<string, string>): string {\n const direction = directionAttribute([span]);\n const style = [\n `left:${number(span.bounds.x)}pt`,\n `bottom:${number(span.bounds.y)}pt`,\n `width:${number(span.bounds.width)}pt`,\n `height:${number(span.bounds.height)}pt`,\n `font-size:${number(span.fontSize)}pt`,\n ...(isCssHexColor(span.color) ? [`color:${span.color}`] : []),\n ...(isUnitInterval(span.fillOpacity) ? [`opacity:${number(span.fillOpacity)}`] : []),\n ...fontStyles(\n span.fontFamily,\n span.fontAssetId ? fontAliases.get(span.fontAssetId) : undefined,\n ),\n ].join(\";\");\n return `<span class=\"pdf-span\"${direction} style=\"${style}\">${escapeHtml(span.text)}</span>`;\n}\n\nasync function writeFlowPage(page: ExtractedPage, write: HtmlWrite): Promise<void> {\n const structured = structurePage(page);\n await write(\n `<section class=\"pdf-page pdf-page--semantic pdf-page--flow\" data-page=\"${page.number}\">`,\n );\n for (const block of structured.blocks) {\n if (block.type === \"table\") await write(tableToHtml(block.table));\n else if (block.type === \"heading\") {\n await write(`<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`);\n } else if (block.type === \"paragraph\") {\n await write(\n `<p${directionAttribute(block.lines.flatMap((line) => line.spans))}>${escapeHtml(block.text)}</p>`,\n );\n } else if (block.type === \"definitionList\") {\n await write(\"<dl>\");\n for (const entry of block.entries) {\n await write(\n `<div><dt>${escapeHtml(entry.term)}</dt><dd>${escapeHtml(entry.description)}</dd></div>`,\n );\n }\n await write(\"</dl>\");\n } else if (block.type === \"cardList\") {\n await write('<div class=\"pdf-semantic-cards\">');\n for (const item of block.items) {\n await write(`<article><h3>${escapeHtml(item.title)}</h3>`);\n for (const detail of item.details) await write(`<p>${escapeHtml(detail)}</p>`);\n await write(\"</article>\");\n }\n await write(\"</div>\");\n } else if (block.type === \"sectionGroup\") {\n await write('<div class=\"pdf-semantic-sections\">');\n for (const item of block.items) {\n await write(`<section><h3>${escapeHtml(item.label)}</h3>`);\n for (const content of item.content) await write(`<p>${escapeHtml(content)}</p>`);\n await write(\"</section>\");\n }\n await write(\"</div>\");\n } else if (block.type === \"employment\") {\n await write(\n `<section><h3>${escapeHtml(block.role)}</h3><p>${escapeHtml(block.organization)}</p><p>${escapeHtml(block.date)}</p></section>`,\n );\n } else {\n const tag = block.ordered ? \"ol\" : \"ul\";\n await write(`<${tag}>`);\n for (const item of block.items) await write(`<li>${escapeHtml(item.text)}</li>`);\n await write(`</${tag}>`);\n }\n }\n await write(\"</section>\");\n}\n\nfunction visualText(\n span: TextSpan,\n pageHeight: number,\n fontAliases: Map<string, string>,\n counterRotateReflectedText = false,\n): string {\n if (span.renderingMode === 3 || span.renderingMode === 7) return \"\";\n if (!span.fontAssetId && isAdobeCjkFont(span.fontFamily)) return \"\";\n const direction = directionAttribute([span]);\n const font = fontStyles(\n span.fontFamily,\n span.fontAssetId ? fontAliases.get(span.fontAssetId) : undefined,\n ).join(\";\");\n const stroke = isCssHexColor(span.strokeColor) ? `stroke:${span.strokeColor}` : \"\";\n const strokeWidth =\n stroke && Number.isFinite(span.strokeWidth) && (span.strokeWidth ?? -1) >= 0\n ? `stroke-width:${number(span.strokeWidth ?? 0)}`\n : \"\";\n const strokeOnly = span.renderingMode === 1 || span.renderingMode === 5;\n const fillOpacity = isUnitInterval(span.fillOpacity)\n ? `fill-opacity:${number(span.fillOpacity)}`\n : \"\";\n const strokeOpacity = isUnitInterval(span.strokeOpacity)\n ? `stroke-opacity:${number(span.strokeOpacity)}`\n : \"\";\n const style = [\n isHebrewPaintOrder(span) ? \"unicode-bidi:bidi-override;direction:ltr\" : \"\",\n span.direction === \"ttb\" ? \"writing-mode:vertical-rl\" : \"\",\n strokeOnly ? \"fill:none\" : isCssHexColor(span.color) ? `fill:${span.color}` : \"\",\n stroke,\n strokeWidth,\n fillOpacity,\n strokeOpacity,\n font,\n ]\n .filter(Boolean)\n .join(\";\");\n const textExtent = span.direction === \"ttb\" ? span.bounds.height : span.bounds.width;\n const textLength =\n textExtent > 0 && !isHebrewPaintOrder(span)\n ? ` textLength=\"${number(textExtent)}\" lengthAdjust=\"${span.direction === \"ttb\" || usesSpacingAdjustment(span) ? \"spacing\" : \"spacingAndGlyphs\"}\"`\n : \"\";\n const transform =\n counterRotateReflectedText && span.transform\n ? ([\n span.transform[0],\n span.transform[1],\n span.transform[2],\n -span.transform[3],\n ] as TextSpan[\"transform\"])\n : span.transform;\n const transformed = hasNonIdentityTransform(transform);\n const rtlOffset = span.direction === \"rtl\" ? span.bounds.width : 0;\n const basisX = transform?.[0] ?? 1;\n const basisY = transform?.[1] ?? 0;\n const anchorX = span.bounds.x + basisX * rtlOffset;\n const anchorY = pageHeight - span.bounds.y + basisY * rtlOffset;\n const position = transformed\n ? ` x=\"0\" y=\"0\" transform=\"matrix(${transform?.map(number).join(\" \")} ${number(anchorX)} ${number(anchorY)})\"`\n : ` x=\"${number(anchorX)}\" y=\"${number(anchorY)}\"`;\n return `<text${direction}${position} font-size=\"${number(span.fontSize)}\"${textLength}${style ? ` style=\"${style}\"` : \"\"}>${escapeHtml(span.text)}</text>`;\n}\n\nfunction isAdobeCjkFont(fontFamily: string | undefined): boolean {\n return /^Adobe(?:Heiti|Song|Kaiti|Ming|Gothic|Mincho)Std-/i.test(fontFamily ?? \"\");\n}\n\nfunction visualType3Text(span: TextSpan, font: EmbeddedType3Font, pageHeight: number): string {\n if (span.renderingMode === 3 || span.renderingMode === 7) return \"\";\n const glyphs = new Map(font.glyphs.map((glyph) => [glyph.code, glyph]));\n const sequence = (span.glyphCodes ?? []).map((code) => glyphs.get(code));\n const totalAdvance = sequence.reduce((total, glyph) => total + (glyph?.advance ?? 0), 0);\n if (totalAdvance <= 0 || span.bounds.width <= 0 || span.fontSize <= 0) return \"\";\n const transform = span.transform ?? [1, 0, 0, 1];\n const outer = `matrix(${transform.map(number).join(\" \")} ${number(span.bounds.x)} ${number(pageHeight - span.bounds.y)})`;\n const xScale = span.bounds.width / totalAdvance;\n let offset = 0;\n let content = \"\";\n for (const glyph of sequence) {\n if (!glyph) continue;\n content += `<g transform=\"translate(${number(offset)} 0)\">${type3Glyph(glyph)}</g>`;\n offset += glyph.advance;\n }\n return `<g transform=\"${outer}\"><g transform=\"scale(${number(xScale)} ${number(-span.fontSize)})\">${content}</g></g>`;\n}\n\nfunction isHebrewPaintOrder(span: TextSpan): boolean {\n return span.direction === \"ltr\" && /[\\u0590-\\u05ff]/u.test(span.text);\n}\n\nfunction usesSpacingAdjustment(span: TextSpan): boolean {\n return !span.fontAssetId && /arial/i.test(span.fontFamily ?? \"\");\n}\n\nfunction type3Glyph(glyph: Type3Glyph): string {\n let output = \"\";\n for (const fill of glyph.fills ?? []) {\n if (!isCssHexColor(fill.color)) continue;\n const points = fill.points.map(([x, y]) => `${number(x)},${number(y)}`).join(\" \");\n const opacity = isUnitInterval(fill.opacity) ? ` fill-opacity=\"${number(fill.opacity)}\"` : \"\";\n output += `<polygon points=\"${points}\" fill=\"${fill.color}\"${opacity}/>`;\n }\n for (const path of glyph.paths ?? []) {\n if (!isSvgPath(path.d)) continue;\n const fill = isCssHexColor(path.fill) ? path.fill : \"none\";\n const stroke = isCssHexColor(path.stroke) ? path.stroke : \"none\";\n const width =\n path.strokeWidth !== undefined && Number.isFinite(path.strokeWidth) && path.strokeWidth >= 0\n ? ` stroke-width=\"${number(path.strokeWidth)}\"`\n : \"\";\n output += `<path d=\"${path.d}\" fill=\"${fill}\" stroke=\"${stroke}\"${width}/>`;\n }\n return (glyph.fills?.length ?? 0) > 64 && glyph.advance > 2\n ? `<g shape-rendering=\"crispEdges\">${output}</g>`\n : output;\n}\n\nfunction isCssHexColor(value: string | undefined): value is string {\n return /^#[\\da-f]{6}$/i.test(value ?? \"\");\n}\n\nfunction isUnitInterval(value: number | undefined): value is number {\n return Number.isFinite(value) && (value ?? -1) >= 0 && (value ?? 2) <= 1;\n}\n\nfunction isSvgPath(value: string): boolean {\n return value.length <= 1_000_000 && /^[\\d\\s.,+\\-eEMmLlCcZz]+$/.test(value);\n}\n\nfunction fontStyles(fontFamily: string | undefined, alias?: string): string[] {\n const normalized = fontFamily?.toLowerCase() ?? \"\";\n const styles: string[] = [];\n let fallback: string | undefined;\n if (/courier|mono|nimbusmono|^cmtt/.test(normalized)) {\n fallback = \"Courier New,Courier,monospace\";\n } else if (\n /times|minion|serif|baskerville|georgia|nimbusrom|guardian.*egyp|^cm[rs]y?\\d/.test(normalized)\n ) {\n fallback = \"Times New Roman,Times,serif\";\n } else if (/helvetica|arial|sans|nimbussan|calibre|myriad|panton|^tte/.test(normalized)) {\n fallback = \"Arial,Helvetica,sans-serif\";\n } else if (/^mstt/.test(normalized)) {\n fallback = \"Arial,Helvetica,sans-serif\";\n }\n if (alias || fallback) styles.push(`font-family:${[alias, fallback].filter(Boolean).join(\",\")}`);\n if (/bold|black|semibold|demi|medi|^tte/.test(normalized)) styles.push(\"font-weight:700\");\n if (/italic|oblique|slant|ital(?:$|[_-])/.test(normalized)) styles.push(\"font-style:italic\");\n return styles;\n}\n\nfunction isMonospace(fontFamily: string | undefined): boolean {\n return /courier|mono/i.test(fontFamily ?? \"\");\n}\n\nfunction usesPositionedSpan(span: TextSpan): boolean {\n return (\n !span.glyphCodes && isMonospace(span.fontFamily) && !hasNonIdentityTransform(span.transform)\n );\n}\n\nfunction hasNonIdentityTransform(transform: TextSpan[\"transform\"]): boolean {\n if (!transform) return false;\n const identity: [number, number, number, number] = [1, 0, 0, 1];\n return transform.some((value, index) => Math.abs(value - (identity[index] ?? 0)) > 0.000_001);\n}\n\nfunction fontFace(font: EmbeddedFont, aliases: Map<string, string>): string {\n if (font.format !== \"truetype\") return \"\";\n const alias = aliases.get(font.id);\n if (!alias) return \"\";\n const styles = fontStyles(font.family, alias).filter(\n (style) => !style.startsWith(\"font-family:\"),\n );\n return `@font-face{font-family:${alias};src:url(data:font/ttf;base64,${base64(font.data)}) format(\"truetype\");${styles.join(\";\")}}`;\n}\n\nfunction base64(bytes: Uint8Array): string {\n const alphabet = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n let output = \"\";\n for (let index = 0; index < bytes.length; index += 3) {\n const first = bytes[index] ?? 0;\n const second = bytes[index + 1] ?? 0;\n const third = bytes[index + 2] ?? 0;\n output += alphabet[first >> 2];\n output += alphabet[((first & 3) << 4) | (second >> 4)];\n output += index + 1 < bytes.length ? alphabet[((second & 15) << 2) | (third >> 6)] : \"=\";\n output += index + 2 < bytes.length ? alphabet[third & 63] : \"=\";\n }\n return output;\n}\n\nfunction directionAttribute(spans: TextSpan[]): string {\n const rtl = spans.filter((span) => span.direction === \"rtl\").length;\n const vertical = spans.filter((span) => span.direction === \"ttb\").length;\n if (vertical > rtl && vertical * 2 >= spans.length) return ' data-direction=\"ttb\"';\n return rtl * 2 >= spans.length && spans.length > 0 ? ' dir=\"rtl\"' : \"\";\n}\n\nfunction number(value: number): string {\n return Number.isFinite(value) ? String(Math.round(value * 1000) / 1000) : \"0\";\n}\n\nfunction escapeAttribute(value: string): string {\n return escapeHtml(value).replaceAll(\"`\", \"&#96;\");\n}\n\nfunction escapeHtml(value: string): string {\n return [...value]\n .map((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n if (codePoint === 13) return \"\\n\";\n return isForbiddenControl(codePoint) ? \"�\" : character;\n })\n .join(\"\")\n .replaceAll(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\")\n .replaceAll(\"'\", \"&#39;\");\n}\n\nfunction isForbiddenControl(codePoint: number): boolean {\n return (\n codePoint <= 8 ||\n codePoint === 11 ||\n codePoint === 12 ||\n (codePoint >= 14 && codePoint <= 31) ||\n codePoint === 127\n );\n}\n\nfunction resolveProfile(options: HtmlWriterOptions): HtmlProfile {\n const legacyProfile = options.layout === \"flow\" ? \"semantic\" : \"visual\";\n if (options.profile && options.layout && options.profile !== legacyProfile) {\n throw new Error(\n `conflicting HTML output options: profile \"${options.profile}\" does not match layout \"${options.layout}\"`,\n );\n }\n return options.profile ?? legacyProfile;\n}\n","import type { ExtractedPage } from \"@boxpdf/reader\";\nimport {\n type SemanticBlock,\n type StructuredPage,\n structurePage,\n type Table,\n tableToRows,\n} from \"@boxpdf/reader/structure\";\n\nexport interface SemanticDocumentStats {\n pagesProcessed: number;\n peakBufferedPages: number;\n peakBufferedLines: number;\n mergedTables: number;\n suppressedFurniture: number;\n}\n\ninterface BufferedPage {\n width: number;\n height: number;\n structured: StructuredPage;\n}\n\ninterface ActiveTable {\n table: Table;\n header: string[] | undefined;\n}\n\nexport async function writeSemanticDocument(\n pages: AsyncIterable<ExtractedPage> | Iterable<ExtractedPage>,\n write: (chunk: string) => void | Promise<void>,\n lookaheadPages: number,\n): Promise<SemanticDocumentStats> {\n const stats: SemanticDocumentStats = {\n pagesProcessed: 0,\n peakBufferedPages: 0,\n peakBufferedLines: 0,\n mergedTables: 0,\n suppressedFurniture: 0,\n };\n const buffer: BufferedPage[] = [];\n const seenFurniture = new Set<string>();\n const sectionLevels: number[] = [];\n let activeTable: ActiveTable | undefined;\n let headerOpen = false;\n let headerHasParagraph = false;\n let contentStarted = false;\n let employmentOpen = false;\n let pendingParagraph:\n | { block: Extract<SemanticBlock, { type: \"paragraph\" }>; height: number }\n | undefined;\n await write('<article class=\"pdf-semantic-document\">');\n\n const closeTable = async () => {\n if (!activeTable) return;\n await write(\"</table>\");\n activeTable = undefined;\n };\n\n const closeSections = async (minimumLevel = 0) => {\n while ((sectionLevels.at(-1) ?? -1) >= minimumLevel && sectionLevels.length > 0) {\n await write(\"</section>\");\n sectionLevels.pop();\n }\n };\n\n const flushPendingParagraph = async () => {\n if (!pendingParagraph) return;\n await write(semanticBlockHtml(pendingParagraph.block));\n pendingParagraph = undefined;\n };\n\n const closeEmployment = async () => {\n if (!employmentOpen) return;\n await write(\"</section>\");\n employmentOpen = false;\n };\n\n const emitPage = async (page: BufferedPage, future: BufferedPage[]) => {\n const futureFurniture = new Set(future.flatMap((candidate) => marginSignatures(candidate)));\n const repeatedFurniture = new Set([...seenFurniture, ...futureFurniture]);\n for (const block of page.structured.blocks) {\n if (isRepeatedFurniture(block, page, repeatedFurniture)) {\n stats.suppressedFurniture += 1;\n continue;\n }\n await flushPendingParagraph();\n if (employmentOpen && block.type !== \"list\") await closeEmployment();\n if (!contentStarted && !headerOpen && block.type === \"heading\" && block.level === 1) {\n await write(`<header><h1>${escapeHtml(block.text)}</h1>`);\n headerOpen = true;\n continue;\n }\n if (headerOpen) {\n if (block.type === \"paragraph\") {\n const tag = isContactBlock(block) ? \"address\" : \"p\";\n await write(`<${tag}>${escapeHtml(block.text)}</${tag}>`);\n headerHasParagraph = true;\n continue;\n }\n if (\n block.type === \"heading\" &&\n !headerHasParagraph &&\n (block.level === 1 || block.text.trimStart().startsWith(\"#\"))\n ) {\n await write(`<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`);\n continue;\n }\n await write(\"</header>\");\n headerOpen = false;\n contentStarted = true;\n }\n if (block.type === \"table\") {\n const rows = tableToRows(block.table);\n if (activeTable && tablesContinue(activeTable.table, block.table, page.width)) {\n const continuationRows = sameRow(activeTable.header, rows[0]) ? rows.slice(1) : rows;\n for (const row of continuationRows) await write(tableRow(row, false));\n activeTable.table = block.table;\n stats.mergedTables += 1;\n continue;\n }\n await closeTable();\n const header = tableHeader(rows);\n await write(\"<table>\");\n for (const [index, row] of rows.entries())\n await write(tableRow(row, Boolean(header && index === 0)));\n activeTable = { table: block.table, header };\n continue;\n }\n if (activeTable && block.type === \"definitionList\" && isFinancialSummary(block)) {\n const columns = activeTable.table.columns.length;\n await write(\n `<tfoot>${block.entries.map((entry) => financialSummaryRow(entry, columns)).join(\"\")}</tfoot>`,\n );\n await closeTable();\n continue;\n }\n await closeTable();\n if (block.type === \"heading\") {\n const level = contentStarted && block.level === 1 ? 2 : block.level;\n await closeSections(level);\n await write(\n `<section data-level=\"${level}\"><h${level}>${escapeHtml(block.text)}</h${level}>`,\n );\n sectionLevels.push(level);\n continue;\n }\n if (block.type === \"paragraph\") {\n if (isTitledRecord(block)) {\n const [institution, ...details] = block.lines;\n if (institution) await write(`<h3>${escapeHtml(institution.text)}</h3>`);\n for (const detail of details) await write(`<p>${escapeHtml(detail.text)}</p>`);\n continue;\n }\n if (isUnmarkedList(block)) {\n await write(\n `<ul>${block.lines.map((line) => `<li>${escapeHtml(line.text)}</li>`).join(\"\")}</ul>`,\n );\n continue;\n }\n pendingParagraph = { block, height: page.height };\n continue;\n }\n if (block.type === \"employment\") {\n await write(\n `<section><h3>${escapeHtml(block.role)}</h3><p>${escapeHtml(block.organization)}</p><p>${escapeHtml(block.date)}</p>`,\n );\n employmentOpen = true;\n continue;\n }\n await write(semanticBlockHtml(block));\n }\n for (const signature of marginSignatures(page)) seenFurniture.add(signature);\n };\n\n for await (const page of pages) {\n const structured = structurePage(page);\n buffer.push({ width: page.width, height: page.height, structured });\n stats.pagesProcessed += 1;\n stats.peakBufferedPages = Math.max(stats.peakBufferedPages, buffer.length);\n stats.peakBufferedLines = Math.max(\n stats.peakBufferedLines,\n buffer.reduce((total, item) => total + item.structured.lines.length, 0),\n );\n if (buffer.length >= lookaheadPages) {\n const ready = buffer.shift();\n if (ready) await emitPage(ready, buffer);\n }\n }\n while (buffer.length > 0) {\n const ready = buffer.shift();\n if (ready) await emitPage(ready, buffer);\n }\n if (headerOpen) await write(\"</header>\");\n await closeTable();\n await closeEmployment();\n if (pendingParagraph && isFooterParagraph(pendingParagraph.block, pendingParagraph.height)) {\n await closeSections();\n await write(`<footer>${semanticBlockHtml(pendingParagraph.block)}</footer>`);\n pendingParagraph = undefined;\n } else {\n await flushPendingParagraph();\n await closeSections();\n }\n await write(\"</article>\");\n return stats;\n}\n\nfunction isContactBlock(block: Extract<SemanticBlock, { type: \"paragraph\" }>): boolean {\n const text = block.text;\n const signals = [\n /@/.test(text),\n /\\+?\\d[\\d().\\s-]{7,}/.test(text),\n /\\bhttps?:\\/\\//i.test(text),\n /\\b\\w+\\.\\w{2,}\\b/i.test(text),\n ];\n return signals.filter(Boolean).length >= 2;\n}\n\nfunction isTitledRecord(block: Extract<SemanticBlock, { type: \"paragraph\" }>): boolean {\n if (block.lines.length < 2) return false;\n const [first, ...rest] = block.lines;\n if (!first || rest.length === 0) return false;\n const firstSize = Math.max(...first.spans.map((span) => span.fontSize));\n const restSize = Math.max(...rest.flatMap((line) => line.spans.map((span) => span.fontSize)));\n const emphasized = first.spans.some((span) =>\n /(?:bold|semibold|demi)/i.test(span.fontFamily ?? \"\"),\n );\n return emphasized || firstSize >= restSize * 1.08;\n}\n\nfunction isUnmarkedList(block: Extract<SemanticBlock, { type: \"paragraph\" }>): boolean {\n if (block.lines.length < 3) return false;\n const first = block.lines[0];\n if (!first) return false;\n const aligned = block.lines.every(\n (line) => Math.abs(line.bounds.x - first.bounds.x) <= Math.max(8, first.bounds.height),\n );\n const separated = block.lines.slice(1).every((line, index) => {\n const previous = block.lines[index];\n if (!previous) return false;\n const gap = previous.bounds.y - (line.bounds.y + line.bounds.height);\n return gap >= Math.min(previous.bounds.height, line.bounds.height) * 0.55;\n });\n return aligned && separated;\n}\n\nfunction isFooterParagraph(\n block: Extract<SemanticBlock, { type: \"paragraph\" }>,\n pageHeight: number,\n): boolean {\n const inBottomMargin = block.lines.every(\n (line) => line.bounds.y + line.bounds.height <= pageHeight * 0.15,\n );\n return inBottomMargin || /^(?:thanks|thank you)\\b/i.test(block.text.trim());\n}\n\nfunction marginSignatures(page: BufferedPage): string[] {\n return page.structured.blocks.flatMap((block) =>\n blockLines(block)\n .filter((line) => isMarginLine(line.bounds.y, line.bounds.height, page.height))\n .map((line) => furnitureSignature(line.text)),\n );\n}\n\nfunction isRepeatedFurniture(\n block: SemanticBlock,\n page: BufferedPage,\n futureFurniture: Set<string>,\n): boolean {\n const lines = blockLines(block);\n return (\n lines.length > 0 &&\n lines.every(\n (line) =>\n isMarginLine(line.bounds.y, line.bounds.height, page.height) &&\n futureFurniture.has(furnitureSignature(line.text)),\n )\n );\n}\n\nfunction blockLines(block: SemanticBlock) {\n return block.type === \"list\" ? block.items.flatMap((item) => item.lines) : block.lines;\n}\n\nfunction isMarginLine(y: number, height: number, pageHeight: number): boolean {\n return y + height <= pageHeight * 0.12 || y >= pageHeight * 0.88;\n}\n\nfunction furnitureSignature(value: string): string {\n return value.toLocaleLowerCase(\"en\").replace(/\\d+/g, \"#\").replace(/\\s+/g, \" \").trim();\n}\n\nfunction tablesContinue(previous: Table, next: Table, pageWidth: number): boolean {\n if (previous.columns.length !== next.columns.length || previous.columns.length < 2) return false;\n return previous.columns.every(\n (column, index) =>\n Math.abs(column - (next.columns[index] ?? Number.POSITIVE_INFINITY)) / pageWidth <= 0.04,\n );\n}\n\nfunction tableHeader(rows: string[][]): string[] | undefined {\n const first = rows[0];\n if (!first) return undefined;\n const later = rows.slice(1).flat();\n return first.every((value) => /\\p{L}/u.test(value) && !isNumericValue(value)) &&\n later.some(isNumericValue)\n ? first\n : undefined;\n}\n\nfunction sameRow(left: string[] | undefined, right: string[] | undefined): boolean {\n return Boolean(\n left &&\n right &&\n left.length === right.length &&\n left.every((value, index) => value === right[index]),\n );\n}\n\nfunction tableRow(row: string[], header: boolean): string {\n const cell = header ? \"th\" : \"td\";\n return `<tr>${row.map((value) => `<${cell}>${escapeHtml(value)}</${cell}>`).join(\"\")}</tr>`;\n}\n\nfunction isFinancialSummary(block: Extract<SemanticBlock, { type: \"definitionList\" }>): boolean {\n return (\n block.entries.length > 0 &&\n block.entries.every((entry) => isNumericValue(entry.description)) &&\n block.entries.some((entry) => /\\p{Sc}|%/u.test(entry.description))\n );\n}\n\nfunction isNumericValue(value: string): boolean {\n return /^(?:\\p{Sc}\\s*)?[\\d.,'’\\s]+(?:\\s*%)?$/u.test(value.trim());\n}\n\nfunction financialSummaryRow(\n entry: Extract<SemanticBlock, { type: \"definitionList\" }>[\"entries\"][number],\n columns: number,\n): string {\n const colspan = columns > 2 ? ` colspan=\"${columns - 1}\"` : \"\";\n return `<tr><th scope=\"row\"${colspan}>${escapeHtml(entry.term)}</th><td>${escapeHtml(entry.description)}</td></tr>`;\n}\n\nfunction semanticBlockHtml(block: Exclude<SemanticBlock, { type: \"table\" }>): string {\n if (block.type === \"heading\")\n return `<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`;\n if (block.type === \"paragraph\") return `<p>${escapeHtml(block.text)}</p>`;\n if (block.type === \"definitionList\") {\n if (\n block.entries.length <= 3 &&\n block.entries.some((entry) => entry.description.trim().split(/\\s+/).length >= 5) &&\n block.entries.every((entry) => /^[A-Z][A-Z\\s/-]*$/.test(entry.term.trim()))\n ) {\n return block.entries\n .map(\n (entry) =>\n `<section><h2>${escapeHtml(titleCase(entry.term))}</h2><p>${escapeHtml(entry.description)}</p></section>`,\n )\n .join(\"\");\n }\n const list = `<dl>${block.entries\n .map(\n (entry) =>\n `<div><dt>${escapeHtml(entry.term)}</dt><dd>${escapeHtml(entry.description)}</dd></div>`,\n )\n .join(\"\")}</dl>`;\n return isFinancialSummary(block) ? `<section>${list}</section>` : list;\n }\n if (block.type === \"cardList\") {\n return `<section><h2>Items ordered</h2><table><thead><tr><th scope=\"col\">Item</th><th scope=\"col\">Quantity</th><th scope=\"col\">Amount</th></tr></thead><tbody>${block.items.map(cardTableRow).join(\"\")}</tbody></table></section>`;\n }\n if (block.type === \"sectionGroup\") {\n return block.items.map(labeledSectionHtml).join(\"\");\n }\n if (block.type === \"employment\") {\n return `<section><h3>${escapeHtml(block.role)}</h3><p>${escapeHtml(block.organization)}</p><p>${escapeHtml(block.date)}</p></section>`;\n }\n const tag = block.ordered ? \"ol\" : \"ul\";\n return `<${tag}>${block.items.map((item) => `<li>${escapeHtml(item.text)}</li>`).join(\"\")}</${tag}>`;\n}\n\nfunction cardTableRow(item: Extract<SemanticBlock, { type: \"cardList\" }>[\"items\"][number]): string {\n const trailing = item.details.at(-1) ?? \"\";\n const match = /^\\s*[×x]\\s*(\\d+)\\s+(.+)$/u.exec(trailing);\n const description = item.details.slice(0, -1).join(\" \");\n const detail = description ? `<br><span>${escapeHtml(description)}</span>` : \"\";\n const quantity = match?.[1] ?? \"\";\n const amount = match?.[2] ?? trailing;\n return `<tr><th scope=\"row\">${escapeHtml(item.title)}${detail}</th><td>${escapeHtml(quantity)}</td><td>${escapeHtml(amount)}</td></tr>`;\n}\n\nfunction labeledSectionHtml(\n item: Extract<SemanticBlock, { type: \"sectionGroup\" }>[\"items\"][number],\n): string {\n const heading = titleCase(item.label);\n const postal = /\\b(?:ship|deliver|mail)(?:ed)?\\b/i.test(item.label);\n if (postal) {\n const [name, ...address] = item.content;\n const content = [name ? `<strong>${escapeHtml(name)}</strong>` : \"\", ...address.map(escapeHtml)]\n .filter(Boolean)\n .join(\"<br>\");\n return `<section><h2>${escapeHtml(heading)}</h2><address>${content}</address></section>`;\n }\n return `<section><h2>${escapeHtml(heading)}</h2>${item.content\n .map(\n (content, index) =>\n `<p>${index === 0 ? `<strong>${escapeHtml(content)}</strong>` : escapeHtml(content)}</p>`,\n )\n .join(\"\")}</section>`;\n}\n\nfunction titleCase(value: string): string {\n const normalized = value.trim().toLocaleLowerCase(\"en\");\n return normalized.replace(/^\\p{L}/u, (letter) => letter.toLocaleUpperCase(\"en\"));\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n"],"mappings":"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","names":["structurePage","escapeHtml","structurePage","styles"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boxpdf/html-writer",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Stream PDF pages from @boxpdf/reader to visual or semantic HTML.",
5
5
  "keywords": [
6
6
  "pdf",