@boxpdf/html-writer 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/index.cjs +255 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +259 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,6 +29,27 @@ lines, nesting, and tables to produce reflowable HTML. The visual model comes
|
|
|
29
29
|
first: semantic structure is derived from the complete page evidence rather
|
|
30
30
|
than inferred after presentation information has been discarded.
|
|
31
31
|
|
|
32
|
+
Document-level semantic output uses a bounded page window to merge tables that
|
|
33
|
+
continue across page boundaries, preserve section nesting across pages, and
|
|
34
|
+
suppress repeated margin furniture. It also expresses aligned product cards,
|
|
35
|
+
address groups, and financial summaries as useful HTML rather than loose text.
|
|
36
|
+
The default window retains at most four extracted text models; configure it
|
|
37
|
+
from one to sixteen pages without buffering PDF bytes, fonts, or raster images:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
await writeHtmlDocument(pdf.pages(), write, {
|
|
41
|
+
profile: "semantic",
|
|
42
|
+
semanticLookaheadPages: 4,
|
|
43
|
+
onSemanticStats(stats) {
|
|
44
|
+
console.log(stats.peakBufferedPages, stats.mergedTables);
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The reported statistics also include processed pages, peak buffered lines, and
|
|
50
|
+
suppressed furniture. Page-level `pageToHtml()` remains available when no
|
|
51
|
+
cross-page inference is wanted.
|
|
52
|
+
|
|
32
53
|
The legacy `layout: "positioned" | "flow"` option remains as an alias for
|
|
33
54
|
`profile: "visual" | "semantic"`. The current visual output surface excludes
|
|
34
55
|
images, vector graphics, and exact font reproduction; the PDFium parity report
|
package/dist/index.cjs
CHANGED
|
@@ -25,7 +25,162 @@ __export(index_exports, {
|
|
|
25
25
|
writePage: () => writePage
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
var import_structure2 = require("@boxpdf/reader/structure");
|
|
29
|
+
|
|
30
|
+
// src/semantic-document.ts
|
|
28
31
|
var import_structure = require("@boxpdf/reader/structure");
|
|
32
|
+
async function writeSemanticDocument(pages, write, lookaheadPages) {
|
|
33
|
+
const stats = {
|
|
34
|
+
pagesProcessed: 0,
|
|
35
|
+
peakBufferedPages: 0,
|
|
36
|
+
peakBufferedLines: 0,
|
|
37
|
+
mergedTables: 0,
|
|
38
|
+
suppressedFurniture: 0
|
|
39
|
+
};
|
|
40
|
+
const buffer = [];
|
|
41
|
+
const seenFurniture = /* @__PURE__ */ new Set();
|
|
42
|
+
const sectionLevels = [];
|
|
43
|
+
let activeTable;
|
|
44
|
+
await write('<article class="pdf-semantic-document">');
|
|
45
|
+
const closeTable = async () => {
|
|
46
|
+
if (!activeTable) return;
|
|
47
|
+
await write("</table>");
|
|
48
|
+
activeTable = void 0;
|
|
49
|
+
};
|
|
50
|
+
const closeSections = async (minimumLevel = 0) => {
|
|
51
|
+
while ((sectionLevels.at(-1) ?? -1) >= minimumLevel && sectionLevels.length > 0) {
|
|
52
|
+
await write("</section>");
|
|
53
|
+
sectionLevels.pop();
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const emitPage = async (page, future) => {
|
|
57
|
+
const futureFurniture = new Set(future.flatMap((candidate) => marginSignatures(candidate)));
|
|
58
|
+
const repeatedFurniture = /* @__PURE__ */ new Set([...seenFurniture, ...futureFurniture]);
|
|
59
|
+
for (const block of page.structured.blocks) {
|
|
60
|
+
if (isRepeatedFurniture(block, page, repeatedFurniture)) {
|
|
61
|
+
stats.suppressedFurniture += 1;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (block.type === "table") {
|
|
65
|
+
const rows = (0, import_structure.tableToRows)(block.table);
|
|
66
|
+
if (activeTable && tablesContinue(activeTable.table, block.table, page.width)) {
|
|
67
|
+
const continuationRows = sameRow(activeTable.header, rows[0]) ? rows.slice(1) : rows;
|
|
68
|
+
for (const row of continuationRows) await write(tableRow(row, false));
|
|
69
|
+
activeTable.table = block.table;
|
|
70
|
+
stats.mergedTables += 1;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
await closeTable();
|
|
74
|
+
const header = tableHeader(rows);
|
|
75
|
+
await write("<table>");
|
|
76
|
+
for (const [index, row] of rows.entries())
|
|
77
|
+
await write(tableRow(row, Boolean(header && index === 0)));
|
|
78
|
+
activeTable = { table: block.table, header };
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
await closeTable();
|
|
82
|
+
if (block.type === "heading") {
|
|
83
|
+
await closeSections(block.level);
|
|
84
|
+
await write(
|
|
85
|
+
`<section data-level="${block.level}"><h${block.level}>${escapeHtml(block.text)}</h${block.level}>`
|
|
86
|
+
);
|
|
87
|
+
sectionLevels.push(block.level);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
await write(semanticBlockHtml(block));
|
|
91
|
+
}
|
|
92
|
+
for (const signature of marginSignatures(page)) seenFurniture.add(signature);
|
|
93
|
+
};
|
|
94
|
+
for await (const page of pages) {
|
|
95
|
+
const structured = (0, import_structure.structurePage)(page);
|
|
96
|
+
buffer.push({ width: page.width, height: page.height, structured });
|
|
97
|
+
stats.pagesProcessed += 1;
|
|
98
|
+
stats.peakBufferedPages = Math.max(stats.peakBufferedPages, buffer.length);
|
|
99
|
+
stats.peakBufferedLines = Math.max(
|
|
100
|
+
stats.peakBufferedLines,
|
|
101
|
+
buffer.reduce((total, item) => total + item.structured.lines.length, 0)
|
|
102
|
+
);
|
|
103
|
+
if (buffer.length >= lookaheadPages) {
|
|
104
|
+
const ready = buffer.shift();
|
|
105
|
+
if (ready) await emitPage(ready, buffer);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
while (buffer.length > 0) {
|
|
109
|
+
const ready = buffer.shift();
|
|
110
|
+
if (ready) await emitPage(ready, buffer);
|
|
111
|
+
}
|
|
112
|
+
await closeTable();
|
|
113
|
+
await closeSections();
|
|
114
|
+
await write("</article>");
|
|
115
|
+
return stats;
|
|
116
|
+
}
|
|
117
|
+
function marginSignatures(page) {
|
|
118
|
+
return page.structured.blocks.flatMap(
|
|
119
|
+
(block) => blockLines(block).filter((line) => isMarginLine(line.bounds.y, line.bounds.height, page.height)).map((line) => furnitureSignature(line.text))
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
function isRepeatedFurniture(block, page, futureFurniture) {
|
|
123
|
+
const lines = blockLines(block);
|
|
124
|
+
return lines.length > 0 && lines.every(
|
|
125
|
+
(line) => isMarginLine(line.bounds.y, line.bounds.height, page.height) && futureFurniture.has(furnitureSignature(line.text))
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
function blockLines(block) {
|
|
129
|
+
return block.type === "list" ? block.items.flatMap((item) => item.lines) : block.lines;
|
|
130
|
+
}
|
|
131
|
+
function isMarginLine(y, height, pageHeight) {
|
|
132
|
+
return y + height <= pageHeight * 0.12 || y >= pageHeight * 0.88;
|
|
133
|
+
}
|
|
134
|
+
function furnitureSignature(value) {
|
|
135
|
+
return value.toLocaleLowerCase("en").replace(/\d+/g, "#").replace(/\s+/g, " ").trim();
|
|
136
|
+
}
|
|
137
|
+
function tablesContinue(previous, next, pageWidth) {
|
|
138
|
+
if (previous.columns.length !== next.columns.length || previous.columns.length < 2) return false;
|
|
139
|
+
return previous.columns.every(
|
|
140
|
+
(column, index) => Math.abs(column - (next.columns[index] ?? Number.POSITIVE_INFINITY)) / pageWidth <= 0.04
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
function tableHeader(rows) {
|
|
144
|
+
const first = rows[0];
|
|
145
|
+
if (!first) return void 0;
|
|
146
|
+
return first.some((value) => /^(?:item|description|feature|qty|unit|amount|total)$/i.test(value)) ? first : void 0;
|
|
147
|
+
}
|
|
148
|
+
function sameRow(left, right) {
|
|
149
|
+
return Boolean(
|
|
150
|
+
left && right && left.length === right.length && left.every((value, index) => value === right[index])
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
function tableRow(row, header) {
|
|
154
|
+
const cell = header ? "th" : "td";
|
|
155
|
+
return `<tr>${row.map((value) => `<${cell}>${escapeHtml(value)}</${cell}>`).join("")}</tr>`;
|
|
156
|
+
}
|
|
157
|
+
function semanticBlockHtml(block) {
|
|
158
|
+
if (block.type === "heading")
|
|
159
|
+
return `<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`;
|
|
160
|
+
if (block.type === "paragraph") return `<p>${escapeHtml(block.text)}</p>`;
|
|
161
|
+
if (block.type === "definitionList") {
|
|
162
|
+
return `<dl>${block.entries.map(
|
|
163
|
+
(entry) => `<div><dt>${escapeHtml(entry.term)}</dt><dd>${escapeHtml(entry.description)}</dd></div>`
|
|
164
|
+
).join("")}</dl>`;
|
|
165
|
+
}
|
|
166
|
+
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>`;
|
|
170
|
+
}
|
|
171
|
+
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>`;
|
|
175
|
+
}
|
|
176
|
+
const tag = block.ordered ? "ol" : "ul";
|
|
177
|
+
return `<${tag}>${block.items.map((item) => `<li>${escapeHtml(item.text)}</li>`).join("")}</${tag}>`;
|
|
178
|
+
}
|
|
179
|
+
function escapeHtml(value) {
|
|
180
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// src/index.ts
|
|
29
184
|
var 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}`;
|
|
30
185
|
async function writeHtmlDocument(pages, write, options = {}) {
|
|
31
186
|
const includeDocument = options.includeDocument ?? true;
|
|
@@ -35,15 +190,28 @@ async function writeHtmlDocument(pages, write, options = {}) {
|
|
|
35
190
|
` lang="${escapeAttribute(options.language ?? "en")}"><head><meta charset="utf-8">`
|
|
36
191
|
);
|
|
37
192
|
await write('<meta name="viewport" content="width=device-width,initial-scale=1">');
|
|
38
|
-
await write(`<title>${
|
|
193
|
+
await write(`<title>${escapeHtml2(options.title ?? "PDF document")}</title>`);
|
|
39
194
|
if (options.includeStyles ?? true) await write(`<style>${styles}</style>`);
|
|
40
195
|
await write("</head><body>");
|
|
41
196
|
}
|
|
42
197
|
await write('<main class="pdf-document">');
|
|
43
|
-
|
|
198
|
+
if (resolveProfile(options) === "semantic") {
|
|
199
|
+
const lookahead = semanticLookahead(options.semanticLookaheadPages);
|
|
200
|
+
const stats = await writeSemanticDocument(pages, write, lookahead);
|
|
201
|
+
options.onSemanticStats?.(stats);
|
|
202
|
+
} else {
|
|
203
|
+
for await (const page of pages) await writePage(page, write, options);
|
|
204
|
+
}
|
|
44
205
|
await write("</main>");
|
|
45
206
|
if (includeDocument) await write("</body></html>");
|
|
46
207
|
}
|
|
208
|
+
function semanticLookahead(value) {
|
|
209
|
+
const lookahead = value ?? 4;
|
|
210
|
+
if (!Number.isSafeInteger(lookahead) || lookahead < 1 || lookahead > 16) {
|
|
211
|
+
throw new RangeError("semanticLookaheadPages must be an integer between 1 and 16");
|
|
212
|
+
}
|
|
213
|
+
return lookahead;
|
|
214
|
+
}
|
|
47
215
|
async function writePage(page, write, options = {}) {
|
|
48
216
|
if (resolveProfile(options) === "semantic") await writeFlowPage(page, write);
|
|
49
217
|
else await writePositionedPage(page, write, options);
|
|
@@ -83,8 +251,12 @@ async function writePositionedPage(page, write, options) {
|
|
|
83
251
|
await write(
|
|
84
252
|
`<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)}">`
|
|
85
253
|
);
|
|
254
|
+
const clipDefinitions = imageClipDefinitions(page.images ?? [], page.number, page.height) + pathClipDefinitions(page.paths ?? [], page.number);
|
|
255
|
+
if (clipDefinitions) await write(`<defs>${clipDefinitions}</defs>`);
|
|
86
256
|
if (reflectedOverlay) {
|
|
87
|
-
for (const image of page.images ?? [])
|
|
257
|
+
for (const [index, image] of (page.images ?? []).entries()) {
|
|
258
|
+
await write(visualImage(image, page.height, page.number, index));
|
|
259
|
+
}
|
|
88
260
|
}
|
|
89
261
|
for (const fill of page.fills ?? []) {
|
|
90
262
|
const points = fill.points.map(([x, y]) => `${number(x)},${number(page.height - y)}`).join(" ");
|
|
@@ -95,7 +267,7 @@ async function writePositionedPage(page, write, options) {
|
|
|
95
267
|
}
|
|
96
268
|
if (page.paths?.length) {
|
|
97
269
|
await write(`<g transform="translate(0 ${number(page.height)}) scale(1 -1)">`);
|
|
98
|
-
for (const path of page.paths) {
|
|
270
|
+
for (const [pathIndex, path] of page.paths.entries()) {
|
|
99
271
|
if (!isSvgPath(path.d)) continue;
|
|
100
272
|
const fill = isCssHexColor(path.fill) ? path.fill : "none";
|
|
101
273
|
const stroke = isCssHexColor(path.stroke) ? path.stroke : "none";
|
|
@@ -107,14 +279,18 @@ async function writePositionedPage(page, write, options) {
|
|
|
107
279
|
const dashoffset = Number.isFinite(path.strokeDashoffset) ? ` stroke-dashoffset="${number(path.strokeDashoffset ?? 0)}"` : "";
|
|
108
280
|
const linecap = path.strokeLinecap ? ` stroke-linecap="${path.strokeLinecap}"` : "";
|
|
109
281
|
const linejoin = path.strokeLinejoin ? ` stroke-linejoin="${path.strokeLinejoin}"` : "";
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
282
|
+
let output = `<path d="${path.d}" fill="${fill}" stroke="${stroke}"${strokeWidth}${fillOpacity}${strokeOpacity}${dasharray}${dashoffset}${linecap}${linejoin}${fillRule}/>`;
|
|
283
|
+
for (let index = (path.clips?.length ?? 0) - 1; index >= 0; index -= 1) {
|
|
284
|
+
output = `<g clip-path="url(#${pathClipId(page.number, pathIndex, index)})">${output}</g>`;
|
|
285
|
+
}
|
|
286
|
+
await write(output);
|
|
113
287
|
}
|
|
114
288
|
await write("</g>");
|
|
115
289
|
}
|
|
116
290
|
if (!reflectedOverlay) {
|
|
117
|
-
for (const image of page.images ?? [])
|
|
291
|
+
for (const [index, image] of (page.images ?? []).entries()) {
|
|
292
|
+
await write(visualImage(image, page.height, page.number, index));
|
|
293
|
+
}
|
|
118
294
|
}
|
|
119
295
|
for (const span of visualSpans) {
|
|
120
296
|
if (!usesPositionedSpan(span)) {
|
|
@@ -135,13 +311,41 @@ function usesReflectedVisualOverlay(page, spans) {
|
|
|
135
311
|
(span) => span.transform !== void 0 && Math.abs(span.transform[0] + 1) < 1e-6 && Math.abs(span.transform[1]) < 1e-6 && Math.abs(span.transform[2]) < 1e-6 && Math.abs(span.transform[3] - 1) < 1e-6
|
|
136
312
|
);
|
|
137
313
|
}
|
|
138
|
-
function visualImage(image, pageHeight) {
|
|
314
|
+
function visualImage(image, pageHeight, pageNumber, imageIndex) {
|
|
139
315
|
const [a, b, c, d, e, f] = image.transform;
|
|
140
316
|
const transform = [a, -b, -c, d, c + e, pageHeight - d - f].map(number).join(" ");
|
|
141
317
|
const opacity = isUnitInterval(image.opacity) ? ` opacity="${number(image.opacity)}"` : "";
|
|
142
318
|
const mime = image.format === "jpeg" ? "image/jpeg" : "image/bmp";
|
|
143
319
|
const data = image.format === "jpeg" ? image.data : rgbBmp(image);
|
|
144
|
-
|
|
320
|
+
let output = `<image width="1" height="1" preserveAspectRatio="none" transform="matrix(${transform})" href="data:${mime};base64,${base64(data)}"${opacity}/>`;
|
|
321
|
+
for (let index = (image.clips?.length ?? 0) - 1; index >= 0; index -= 1) {
|
|
322
|
+
output = `<g clip-path="url(#${imageClipId(pageNumber, imageIndex, index)})">${output}</g>`;
|
|
323
|
+
}
|
|
324
|
+
return output;
|
|
325
|
+
}
|
|
326
|
+
function imageClipDefinitions(images, pageNumber, pageHeight) {
|
|
327
|
+
return images.flatMap(
|
|
328
|
+
(image, imageIndex) => (image.clips ?? []).map((clip, clipIndex) => {
|
|
329
|
+
if (!isSvgPath(clip.d)) return "";
|
|
330
|
+
const fillRule = clip.fillRule ? ` clip-rule="${clip.fillRule}"` : "";
|
|
331
|
+
return `<clipPath id="${imageClipId(pageNumber, imageIndex, clipIndex)}" clipPathUnits="userSpaceOnUse"><path d="${clip.d}" transform="translate(0 ${number(pageHeight)}) scale(1 -1)"${fillRule}/></clipPath>`;
|
|
332
|
+
})
|
|
333
|
+
).join("");
|
|
334
|
+
}
|
|
335
|
+
function imageClipId(pageNumber, imageIndex, clipIndex) {
|
|
336
|
+
return `boxpdf-clip-${pageNumber}-${imageIndex}-${clipIndex}`;
|
|
337
|
+
}
|
|
338
|
+
function pathClipDefinitions(paths, pageNumber) {
|
|
339
|
+
return paths.flatMap(
|
|
340
|
+
(path, pathIndex) => (path.clips ?? []).map((clip, clipIndex) => {
|
|
341
|
+
if (!isSvgPath(clip.d)) return "";
|
|
342
|
+
const fillRule = clip.fillRule ? ` clip-rule="${clip.fillRule}"` : "";
|
|
343
|
+
return `<clipPath id="${pathClipId(pageNumber, pathIndex, clipIndex)}" clipPathUnits="userSpaceOnUse"><path d="${clip.d}"${fillRule}/></clipPath>`;
|
|
344
|
+
})
|
|
345
|
+
).join("");
|
|
346
|
+
}
|
|
347
|
+
function pathClipId(pageNumber, pathIndex, clipIndex) {
|
|
348
|
+
return `boxpdf-path-clip-${pageNumber}-${pathIndex}-${clipIndex}`;
|
|
145
349
|
}
|
|
146
350
|
function rgbBmp(image) {
|
|
147
351
|
const stride = Math.ceil(image.width * 3 / 4) * 4;
|
|
@@ -195,28 +399,51 @@ function positionedSpan(span, fontAliases) {
|
|
|
195
399
|
span.fontAssetId ? fontAliases.get(span.fontAssetId) : void 0
|
|
196
400
|
)
|
|
197
401
|
].join(";");
|
|
198
|
-
return `<span class="pdf-span"${direction} style="${style}">${
|
|
402
|
+
return `<span class="pdf-span"${direction} style="${style}">${escapeHtml2(span.text)}</span>`;
|
|
199
403
|
}
|
|
200
404
|
async function writeFlowPage(page, write) {
|
|
201
|
-
const structured = (0,
|
|
202
|
-
const tables = [...structured.tables].sort((left, right) => right.bounds.y - left.bounds.y);
|
|
203
|
-
const emittedTables = /* @__PURE__ */ new Set();
|
|
405
|
+
const structured = (0, import_structure2.structurePage)(page);
|
|
204
406
|
await write(
|
|
205
407
|
`<section class="pdf-page pdf-page--semantic pdf-page--flow" data-page="${page.number}">`
|
|
206
408
|
);
|
|
207
|
-
for (const
|
|
208
|
-
|
|
209
|
-
if (
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
409
|
+
for (const block of structured.blocks) {
|
|
410
|
+
if (block.type === "table") await write((0, import_structure2.tableToHtml)(block.table));
|
|
411
|
+
else if (block.type === "heading") {
|
|
412
|
+
await write(`<h${block.level}>${escapeHtml2(block.text)}</h${block.level}>`);
|
|
413
|
+
} else if (block.type === "paragraph") {
|
|
414
|
+
await write(
|
|
415
|
+
`<p${directionAttribute(block.lines.flatMap((line) => line.spans))}>${escapeHtml2(block.text)}</p>`
|
|
416
|
+
);
|
|
417
|
+
} else if (block.type === "definitionList") {
|
|
418
|
+
await write("<dl>");
|
|
419
|
+
for (const entry of block.entries) {
|
|
420
|
+
await write(
|
|
421
|
+
`<div><dt>${escapeHtml2(entry.term)}</dt><dd>${escapeHtml2(entry.description)}</dd></div>`
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
await write("</dl>");
|
|
425
|
+
} else if (block.type === "cardList") {
|
|
426
|
+
await write('<div class="pdf-semantic-cards">');
|
|
427
|
+
for (const item of block.items) {
|
|
428
|
+
await write(`<article><h3>${escapeHtml2(item.title)}</h3>`);
|
|
429
|
+
for (const detail of item.details) await write(`<p>${escapeHtml2(detail)}</p>`);
|
|
430
|
+
await write("</article>");
|
|
431
|
+
}
|
|
432
|
+
await write("</div>");
|
|
433
|
+
} else if (block.type === "sectionGroup") {
|
|
434
|
+
await write('<div class="pdf-semantic-sections">');
|
|
435
|
+
for (const item of block.items) {
|
|
436
|
+
await write(`<section><h3>${escapeHtml2(item.label)}</h3>`);
|
|
437
|
+
for (const content of item.content) await write(`<p>${escapeHtml2(content)}</p>`);
|
|
438
|
+
await write("</section>");
|
|
213
439
|
}
|
|
214
|
-
|
|
440
|
+
await write("</div>");
|
|
441
|
+
} else {
|
|
442
|
+
const tag = block.ordered ? "ol" : "ul";
|
|
443
|
+
await write(`<${tag}>`);
|
|
444
|
+
for (const item of block.items) await write(`<li>${escapeHtml2(item.text)}</li>`);
|
|
445
|
+
await write(`</${tag}>`);
|
|
215
446
|
}
|
|
216
|
-
await write(`<p${directionAttribute(line.spans)}>${escapeHtml(line.text)}</p>`);
|
|
217
|
-
}
|
|
218
|
-
for (const table of tables) {
|
|
219
|
-
if (!emittedTables.has(table)) await write((0, import_structure.tableToHtml)(table));
|
|
220
447
|
}
|
|
221
448
|
await write("</section>");
|
|
222
449
|
}
|
|
@@ -258,7 +485,7 @@ function visualText(span, pageHeight, fontAliases, counterRotateReflectedText =
|
|
|
258
485
|
const anchorX = span.bounds.x + basisX * rtlOffset;
|
|
259
486
|
const anchorY = pageHeight - span.bounds.y + basisY * rtlOffset;
|
|
260
487
|
const position = transformed ? ` x="0" y="0" transform="matrix(${transform?.map(number).join(" ")} ${number(anchorX)} ${number(anchorY)})"` : ` x="${number(anchorX)}" y="${number(anchorY)}"`;
|
|
261
|
-
return `<text${direction}${position} font-size="${number(span.fontSize)}"${textLength}${style ? ` style="${style}"` : ""}>${
|
|
488
|
+
return `<text${direction}${position} font-size="${number(span.fontSize)}"${textLength}${style ? ` style="${style}"` : ""}>${escapeHtml2(span.text)}</text>`;
|
|
262
489
|
}
|
|
263
490
|
function isAdobeCjkFont(fontFamily) {
|
|
264
491
|
return /^Adobe(?:Heiti|Song|Kaiti|Ming|Gothic|Mincho)Std-/i.test(fontFamily ?? "");
|
|
@@ -371,16 +598,13 @@ function directionAttribute(spans) {
|
|
|
371
598
|
if (vertical > rtl && vertical * 2 >= spans.length) return ' data-direction="ttb"';
|
|
372
599
|
return rtl * 2 >= spans.length && spans.length > 0 ? ' dir="rtl"' : "";
|
|
373
600
|
}
|
|
374
|
-
function containsY(table, y) {
|
|
375
|
-
return y >= table.bounds.y && y <= table.bounds.y + table.bounds.height;
|
|
376
|
-
}
|
|
377
601
|
function number(value) {
|
|
378
602
|
return Number.isFinite(value) ? String(Math.round(value * 1e3) / 1e3) : "0";
|
|
379
603
|
}
|
|
380
604
|
function escapeAttribute(value) {
|
|
381
|
-
return
|
|
605
|
+
return escapeHtml2(value).replaceAll("`", "`");
|
|
382
606
|
}
|
|
383
|
-
function
|
|
607
|
+
function escapeHtml2(value) {
|
|
384
608
|
return [...value].map((character) => {
|
|
385
609
|
const codePoint = character.codePointAt(0) ?? 0;
|
|
386
610
|
if (codePoint === 13) return "\n";
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n EmbeddedFont,\n EmbeddedType3Font,\n ExtractedPage,\n RasterImage,\n TextSpan,\n Type3Glyph,\n} from \"@boxpdf/reader\";\nimport { structurePage, type Table, tableToHtml } from \"@boxpdf/reader/structure\";\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}\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 for await (const page of pages) await writePage(page, write, options);\n await write(\"</main>\");\n if (includeDocument) await write(\"</body></html>\");\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 if (reflectedOverlay) {\n for (const image of page.images ?? []) await write(visualImage(image, page.height));\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 path of page.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 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 await write(\n `<path d=\"${path.d}\" fill=\"${fill}\" stroke=\"${stroke}\"${strokeWidth}${fillOpacity}${strokeOpacity}${dasharray}${dashoffset}${linecap}${linejoin}${fillRule}/>`,\n );\n }\n await write(\"</g>\");\n }\n if (!reflectedOverlay) {\n for (const image of page.images ?? []) await write(visualImage(image, page.height));\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(image: RasterImage, pageHeight: number): 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 return `<image width=\"1\" height=\"1\" preserveAspectRatio=\"none\" transform=\"matrix(${transform})\" href=\"data:${mime};base64,${base64(data)}\"${opacity}/>`;\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 const tables = [...structured.tables].sort((left, right) => right.bounds.y - left.bounds.y);\n const emittedTables = new Set<Table>();\n await write(\n `<section class=\"pdf-page pdf-page--semantic pdf-page--flow\" data-page=\"${page.number}\">`,\n );\n for (const line of structured.lines) {\n const table = tables.find((candidate) => containsY(candidate, line.bounds.y));\n if (table) {\n if (!emittedTables.has(table)) {\n await write(tableToHtml(table));\n emittedTables.add(table);\n }\n continue;\n }\n await write(`<p${directionAttribute(line.spans)}>${escapeHtml(line.text)}</p>`);\n }\n for (const table of tables) {\n if (!emittedTables.has(table)) await write(tableToHtml(table));\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 containsY(table: Table, y: number): boolean {\n return y >= table.bounds.y && y <= table.bounds.y + table.bounds.height;\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(\"`\", \"`\");\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(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\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"],"mappings":"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","names":["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 {\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(\"`\", \"`\");\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(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\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, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n"],"mappings":"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","names":["import_structure","escapeHtml","styles"]}
|