reamkit 1.28.0 → 1.30.0
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/esm/core/converter/ream.d.ts +8 -0
- package/dist/esm/core/document-model/types.d.ts +2 -0
- package/dist/esm/core/drawingml/shape-render.js +13 -1
- package/dist/esm/core/fonts/index.d.ts +1 -1
- package/dist/esm/core/fonts/remote-fonts.d.ts +8 -0
- package/dist/esm/core/fonts/remote-fonts.js +100 -17
- package/dist/esm/core/ir/flow.d.ts +17 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/pdf-reader/annot-draw.js +93 -1
- package/dist/esm/pdf-reader/annots.d.ts +18 -0
- package/dist/esm/pdf-reader/annots.js +86 -9
- package/dist/esm/pdf-reader/cmap.js +13 -3
- package/dist/esm/pdf-reader/content.d.ts +32 -4
- package/dist/esm/pdf-reader/content.js +177 -12
- package/dist/esm/pdf-reader/display.js +16 -0
- package/dist/esm/pdf-reader/document.d.ts +8 -0
- package/dist/esm/pdf-reader/embedded-fonts.d.ts +24 -0
- package/dist/esm/pdf-reader/embedded-fonts.js +48 -9
- package/dist/esm/pdf-reader/flow-build.d.ts +101 -5
- package/dist/esm/pdf-reader/flow-build.js +219 -25
- package/dist/esm/pdf-reader/font.d.ts +27 -1
- package/dist/esm/pdf-reader/font.js +313 -29
- package/dist/esm/pdf-reader/glyf-outline.js +13 -2
- package/dist/esm/pdf-reader/glyph-shapes.d.ts +18 -0
- package/dist/esm/pdf-reader/glyph-shapes.js +57 -0
- package/dist/esm/pdf-reader/image-decode.js +70 -4
- package/dist/esm/pdf-reader/images.d.ts +5 -0
- package/dist/esm/pdf-reader/images.js +4 -2
- package/dist/esm/pdf-reader/jbig2.d.ts +40 -1
- package/dist/esm/pdf-reader/jbig2.js +78 -16
- package/dist/esm/pdf-reader/jpeg.d.ts +6 -3
- package/dist/esm/pdf-reader/jpeg.js +21 -1
- package/dist/esm/pdf-reader/layout.d.ts +26 -2
- package/dist/esm/pdf-reader/layout.js +974 -55
- package/dist/esm/pdf-reader/lexer.d.ts +10 -0
- package/dist/esm/pdf-reader/lexer.js +17 -0
- package/dist/esm/pdf-reader/pattern-tint.d.ts +11 -1
- package/dist/esm/pdf-reader/pattern-tint.js +21 -3
- package/dist/esm/pdf-reader/regions.d.ts +25 -0
- package/dist/esm/pdf-reader/regions.js +167 -0
- package/dist/esm/pdf-reader/shading.d.ts +58 -2
- package/dist/esm/pdf-reader/shading.js +181 -11
- package/dist/esm/pdf-reader/struct-tree.js +112 -8
- package/dist/esm/pdf-reader/tagged.js +27 -7
- package/dist/esm/pdf-reader/text-rules.js +1 -1
- package/dist/esm/pdf-reader/text.js +9 -14
- package/dist/esm/pdf-reader/vector.d.ts +10 -2
- package/dist/esm/pdf-reader/vector.js +35 -5
- package/dist/esm/word/docx-writer.js +156 -39
- package/dist/esm/word/drawing-parser.js +7 -2
- package/dist/esm/word/paragraph-properties.js +2 -0
- package/package.json +5 -3
|
@@ -17,6 +17,9 @@ var REL_NUMBERING = "http://schemas.openxmlformats.org/officeDocument/2006/relat
|
|
|
17
17
|
var REL_HYPERLINK = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
|
|
18
18
|
var REL_IMAGE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
|
|
19
19
|
var NUMBERING_PART = "word/numbering.xml";
|
|
20
|
+
var REL_FONT_TABLE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable";
|
|
21
|
+
var FONT_TABLE_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml";
|
|
22
|
+
var FONT_TABLE_PART = "word/fontTable.xml";
|
|
20
23
|
var REL_FOOTNOTES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes";
|
|
21
24
|
var REL_ENDNOTES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes";
|
|
22
25
|
var FOOTNOTES_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml";
|
|
@@ -127,7 +130,10 @@ function writeDocx(flow) {
|
|
|
127
130
|
drawingSeq: 0,
|
|
128
131
|
chartParts: [],
|
|
129
132
|
chartSeq: 0,
|
|
130
|
-
...flow.charts ? { charts: flow.charts } : {}
|
|
133
|
+
...flow.charts ? { charts: flow.charts } : {},
|
|
134
|
+
...flow.faceFamilies ? { faceFamilies: flow.faceFamilies } : {},
|
|
135
|
+
familiesUsed: /* @__PURE__ */ new Map(),
|
|
136
|
+
zRanks: zRanksOf(flow)
|
|
131
137
|
};
|
|
132
138
|
const docScope = newScope();
|
|
133
139
|
const extraParts = [];
|
|
@@ -179,6 +185,17 @@ function writeDocx(flow) {
|
|
|
179
185
|
}, state, losses, docScope, extraParts, extraPartRels);
|
|
180
186
|
const commentParaIds = emitComments(flow.comments, state, losses, docScope, extraParts, extraPartRels);
|
|
181
187
|
emitCommentsExtended(flow.comments, commentParaIds, docScope, extraParts);
|
|
188
|
+
const fontTablePart = state.familiesUsed.size > 0 ? {
|
|
189
|
+
path: FONT_TABLE_PART,
|
|
190
|
+
data: encoder.encode(fontTableXml(state.familiesUsed)),
|
|
191
|
+
contentType: FONT_TABLE_CONTENT_TYPE
|
|
192
|
+
} : void 0;
|
|
193
|
+
if (fontTablePart) docScope.rels.push({
|
|
194
|
+
id: `rId${++docScope.relSeq}`,
|
|
195
|
+
type: REL_FONT_TABLE,
|
|
196
|
+
target: "fontTable.xml",
|
|
197
|
+
targetMode: "Internal"
|
|
198
|
+
});
|
|
182
199
|
const partRelationships = [...docScope.rels.length > 0 ? [{
|
|
183
200
|
sourcePart: "word/document.xml",
|
|
184
201
|
relationships: docScope.rels
|
|
@@ -192,6 +209,7 @@ function writeDocx(flow) {
|
|
|
192
209
|
contentType: DOC_CONTENT_TYPE
|
|
193
210
|
},
|
|
194
211
|
...numberingPart ? [numberingPart] : [],
|
|
212
|
+
...fontTablePart ? [fontTablePart] : [],
|
|
195
213
|
...extraParts,
|
|
196
214
|
...state.chartParts,
|
|
197
215
|
...state.mediaParts
|
|
@@ -207,6 +225,47 @@ function writeDocx(flow) {
|
|
|
207
225
|
losses
|
|
208
226
|
};
|
|
209
227
|
}
|
|
228
|
+
function fontTableXml(families) {
|
|
229
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:fonts xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">${[...families.values()].map((f) => `<w:font w:name="${escapeAttr(f.family)}"><w:family w:val="${f.generic}"/><w:pitch w:val="${f.generic === "modern" ? "fixed" : "variable"}"/></w:font>`).join("")}</w:fonts>`;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* §20.4.2.3 `relativeHeight` — a float's z-order, written the way Word writes
|
|
233
|
+
* it: a rank over every z-order the document states, counted up from Word's
|
|
234
|
+
* own floor.
|
|
235
|
+
*
|
|
236
|
+
* The model's z-order is an ORDER, and may be any number. Written as it stood,
|
|
237
|
+
* a PDF's first two marks got 0 and 1 — which Word, and LibreOffice after it,
|
|
238
|
+
* read as "above everything": an "APPROVED" stamp's blue box came back over
|
|
239
|
+
* its own lettering. A tagged reading counts up from minus a million, and a
|
|
240
|
+
* negative number is not a value the attribute admits at all.
|
|
241
|
+
*/
|
|
242
|
+
function relativeHeight(zOrder, state) {
|
|
243
|
+
const at = (zOrder !== void 0 ? state.zRanks.get(zOrder) : void 0) ?? state.zRanks.size + ++state.drawingSeq;
|
|
244
|
+
const step = Math.max(1, Math.min(Z_STEP, Math.floor((Z_CEILING - Z_FLOOR) / Z_ROOM)));
|
|
245
|
+
return Math.min(Z_FLOOR + at * step, Z_CEILING);
|
|
246
|
+
}
|
|
247
|
+
/** Word's first float, and the highest value §20.4.2.3 lets a float take. */
|
|
248
|
+
var Z_FLOOR = 251658240;
|
|
249
|
+
var Z_CEILING = 503316479;
|
|
250
|
+
/** …and the step Word counts up in, while there is room for it. */
|
|
251
|
+
var Z_STEP = 1024;
|
|
252
|
+
var Z_ROOM = 1 << 17;
|
|
253
|
+
/** Every z-order the document's floats state, and each one's rank among them. */
|
|
254
|
+
function zRanksOf(flow) {
|
|
255
|
+
const seen = /* @__PURE__ */ new Set();
|
|
256
|
+
const visit = (blocks) => {
|
|
257
|
+
for (const el of blocks) {
|
|
258
|
+
const z = el.kind === "image" ? el.image.float?.zOrder : el.kind === "shape" ? el.shape.float?.zOrder : el.kind === "chart" ? el.chart.float?.zOrder : void 0;
|
|
259
|
+
if (z !== void 0 && Number.isFinite(z)) seen.add(z);
|
|
260
|
+
if (el.kind === "table") for (const row of el.table.rows) for (const cell of row.cells) visit(cell.content);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
visit(flow.body);
|
|
264
|
+
for (const band of flow.headersFooters?.values() ?? []) visit(band);
|
|
265
|
+
for (const note of flow.footnotes?.values() ?? []) visit(note);
|
|
266
|
+
for (const note of flow.endnotes?.values() ?? []) visit(note);
|
|
267
|
+
return new Map([...seen].sort((a, b) => a - b).map((z, i) => [z, i]));
|
|
268
|
+
}
|
|
210
269
|
function emitNotes(notes, cfg, state, losses, docScope, extraParts, extraPartRels) {
|
|
211
270
|
if (!notes || notes.size === 0) return;
|
|
212
271
|
const scope = newScope();
|
|
@@ -388,14 +447,17 @@ var docxWriter = {
|
|
|
388
447
|
*/
|
|
389
448
|
function emitBody(out, blocks, losses, state, scope, sectPrByClosingIndex) {
|
|
390
449
|
let carried = [];
|
|
450
|
+
let carrier;
|
|
391
451
|
const flush = () => {
|
|
392
|
-
if (carried.length > 0) out.push(`<w:p>${carried.join("")}</w:p>`);
|
|
452
|
+
if (carried.length > 0) out.push(`<w:p>${pPrWithSect(carrier ?? {})}${carried.join("")}</w:p>`);
|
|
393
453
|
carried = [];
|
|
454
|
+
carrier = void 0;
|
|
394
455
|
};
|
|
395
456
|
blocks.forEach((el, idx) => {
|
|
396
457
|
const closing = sectPrByClosingIndex.get(idx);
|
|
397
458
|
const anchored = closing === void 0 ? floatingDrawingRun(el, losses, state, scope) : void 0;
|
|
398
459
|
if (anchored !== void 0) {
|
|
460
|
+
carrier ??= el.kind === "image" ? el.image.paragraphProperties : el.kind === "shape" ? el.shape.paragraphProperties : void 0;
|
|
399
461
|
carried.push(anchored);
|
|
400
462
|
return;
|
|
401
463
|
}
|
|
@@ -411,7 +473,7 @@ function emitBody(out, blocks, losses, state, scope, sectPrByClosingIndex) {
|
|
|
411
473
|
*/
|
|
412
474
|
function floatingDrawingRun(el, losses, state, scope) {
|
|
413
475
|
if (el.kind === "image" && el.image.float) {
|
|
414
|
-
const drawing = drawingXml(el.image.resource, el.image.width, el.image.height, el.image.altText, state, scope, el.image.float);
|
|
476
|
+
const drawing = drawingXml(el.image.resource, el.image.width, el.image.height, el.image.altText, state, scope, el.image.float, el.image);
|
|
415
477
|
if (drawing === "") {
|
|
416
478
|
losses.push({
|
|
417
479
|
severity: "dropped",
|
|
@@ -435,7 +497,7 @@ function emitBlock(out, el, losses, state, scope, closingSectPr) {
|
|
|
435
497
|
return;
|
|
436
498
|
}
|
|
437
499
|
if (el.kind === "image") {
|
|
438
|
-
const drawing = drawingXml(el.image.resource, el.image.width, el.image.height, el.image.altText, state, scope, el.image.float);
|
|
500
|
+
const drawing = drawingXml(el.image.resource, el.image.width, el.image.height, el.image.altText, state, scope, el.image.float, el.image);
|
|
439
501
|
if (drawing) out.push(`<w:p>${pPrWithSect(el.image.paragraphProperties, closingSectPr)}<w:r>${drawing}</w:r></w:p>`);
|
|
440
502
|
else {
|
|
441
503
|
losses.push({
|
|
@@ -482,7 +544,7 @@ function chartBlockXml(chart, state, scope, losses) {
|
|
|
482
544
|
const cx = Math.round(chart.width * EMU_PER_PT);
|
|
483
545
|
const cy = Math.round(chart.height * EMU_PER_PT);
|
|
484
546
|
const id = ++state.drawingSeq;
|
|
485
|
-
return `<w:drawing><wp:inline xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"><wp:extent cx="${cx}" cy="${cy}"/><wp:docPr id="${id}" name="Chart ${id}"${chart.altText ? ` descr="${escapeAttr(chart.altText)}"` : ""}/><a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/chart"><c:chart xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:id="${relId}"/></a:graphicData></a:graphic></wp:inline></w:drawing>`;
|
|
547
|
+
return `<w:drawing><wp:inline xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" distT="0" distB="0" distL="0" distR="0"><wp:extent cx="${cx}" cy="${cy}"/><wp:docPr id="${id}" name="Chart ${id}"${chart.altText ? ` descr="${escapeAttr(chart.altText)}"` : ""}/><a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/chart"><c:chart xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:id="${relId}"/></a:graphicData></a:graphic></wp:inline></w:drawing>`;
|
|
486
548
|
}
|
|
487
549
|
/**
|
|
488
550
|
* §20.4.2.3 — the frame a drawing is placed by: `wp:anchor` where the block
|
|
@@ -510,11 +572,11 @@ function chartBlockXml(chart, state, scope, losses) {
|
|
|
510
572
|
*/
|
|
511
573
|
function drawingFrame(float, cx, cy, head, graphic, state, rotation60k) {
|
|
512
574
|
const WP_NS = " xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\"";
|
|
513
|
-
if (!float) return `<w:drawing><wp:inline${WP_NS}><wp:extent cx="${cx}" cy="${cy}"/>${head}${graphic}</wp:inline></w:drawing>`;
|
|
575
|
+
if (!float) return `<w:drawing><wp:inline${WP_NS} distT="0" distB="0" distL="0" distR="0"><wp:extent cx="${cx}" cy="${cy}"/>${head}${graphic}</wp:inline></w:drawing>`;
|
|
514
576
|
const emu = (pt) => Number.isFinite(pt) ? Math.round((pt ?? 0) * EMU_PER_PT) : 0;
|
|
515
577
|
const d = float.wrapDist;
|
|
516
578
|
const dist = ` distT="${String(emu(d?.topPt))}" distB="${String(emu(d?.bottomPt))}" distL="${String(emu(d?.leftPt))}" distR="${String(emu(d?.rightPt))}"`;
|
|
517
|
-
const z = float.zOrder
|
|
579
|
+
const z = relativeHeight(float.zOrder, state);
|
|
518
580
|
const attrs = `${dist} simplePos="0" relativeHeight="${String(z)}" behindDoc="${float.behind ? "1" : "0"}" locked="0" layoutInCell="${float.inCell === false ? "0" : "1"}" allowOverlap="1"`;
|
|
519
581
|
const pos = (tag, p, fallback) => {
|
|
520
582
|
const from = p?.relativeFrom ?? fallback;
|
|
@@ -550,7 +612,7 @@ function effectExtentXml(cx, cy, rotation60k) {
|
|
|
550
612
|
const v = overhang(cy, cx * s + cy * c);
|
|
551
613
|
return h === 0 && v === 0 ? none : `<wp:effectExtent l="${String(h)}" t="${String(v)}" r="${String(h)}" b="${String(v)}"/>`;
|
|
552
614
|
}
|
|
553
|
-
function drawingXml(resource, widthPt, heightPt, altText, state, scope, float) {
|
|
615
|
+
function drawingXml(resource, widthPt, heightPt, altText, state, scope, float, look) {
|
|
554
616
|
if (resource === void 0) return "";
|
|
555
617
|
const relId = mediaRelId(resource, state, scope);
|
|
556
618
|
if (relId === void 0) return "";
|
|
@@ -558,8 +620,15 @@ function drawingXml(resource, widthPt, heightPt, altText, state, scope, float) {
|
|
|
558
620
|
const cy = Math.round(heightPt * EMU_PER_PT);
|
|
559
621
|
const id = ++state.drawingSeq;
|
|
560
622
|
const descr = altText ? ` descr="${escapeAttr(altText)}"` : "";
|
|
561
|
-
const graphic = `<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:nvPicPr><pic:cNvPr id="${id}" name="Image ${id}"/><pic:cNvPicPr/></pic:nvPicPr><pic:blipFill><a:blip r:embed="${relId}"
|
|
562
|
-
return drawingFrame(float, cx, cy, `<wp:docPr id="${id}" name="Image ${id}"${descr}/>`, graphic, state);
|
|
623
|
+
const graphic = `<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:nvPicPr><pic:cNvPr id="${id}" name="Image ${id}"/><pic:cNvPicPr/></pic:nvPicPr><pic:blipFill><a:blip r:embed="${relId}">${look?.alpha !== void 0 && look.alpha < 1 ? `<a:alphaModFix amt="${String(Math.round(Math.max(0, look.alpha) * 1e5))}"/>` : ""}</a:blip>${srcRectXml(look?.crop)}<a:stretch><a:fillRect/></a:stretch></pic:blipFill><pic:spPr>${xfrmXml(look, cx, cy)}<a:prstGeom prst="rect"><a:avLst/></a:prstGeom></pic:spPr></pic:pic></a:graphicData></a:graphic>`;
|
|
624
|
+
return drawingFrame(float, cx, cy, `<wp:docPr id="${id}" name="Image ${id}"${descr}/>`, graphic, state, look?.rotation60k);
|
|
625
|
+
}
|
|
626
|
+
/** §20.1.8.55 `a:srcRect` — each edge cut away, in thousandths of a percent. */
|
|
627
|
+
function srcRectXml(crop) {
|
|
628
|
+
if (!crop) return "";
|
|
629
|
+
const edge = (name, v) => v > 0 ? ` ${name}="${String(Math.round(v * 1e5))}"` : "";
|
|
630
|
+
const attrs = edge("l", crop.left) + edge("t", crop.top) + edge("r", crop.right) + edge("b", crop.bottom);
|
|
631
|
+
return attrs === "" ? "" : `<a:srcRect${attrs}/>`;
|
|
563
632
|
}
|
|
564
633
|
var WPS_URI = "http://schemas.microsoft.com/office/word/2010/wordprocessingShape";
|
|
565
634
|
function shapeDrawingXml(shape, losses, state, scope) {
|
|
@@ -624,13 +693,24 @@ function geomXml(g) {
|
|
|
624
693
|
return `<a:prstGeom prst="${escapeAttr(g.preset ?? "rect")}"><a:avLst>${gds}</a:avLst></a:prstGeom>`;
|
|
625
694
|
}
|
|
626
695
|
function fillXml(f) {
|
|
627
|
-
if (f.kind === "solid" && f.colorHex) return `<a:solidFill
|
|
628
|
-
if (f.kind === "gradient" && f.gradient) return gradFillXml(f.gradient);
|
|
696
|
+
if (f.kind === "solid" && f.colorHex) return `<a:solidFill>${srgbXml(f.colorHex, f.alpha)}</a:solidFill>`;
|
|
697
|
+
if (f.kind === "gradient" && f.gradient) return gradFillXml(f.gradient, f.alpha);
|
|
629
698
|
return "<a:noFill/>";
|
|
630
699
|
}
|
|
631
|
-
|
|
700
|
+
/**
|
|
701
|
+
* §20.1.2.3.19 `a:srgbClr`, with the §20.1.2.3.1 `a:alpha` of a fill that is
|
|
702
|
+
* seen through. The model carried the opacity and the writer dropped it:
|
|
703
|
+
* bug1755507.pdf lays a card on a shadow painted at a fifth of full strength,
|
|
704
|
+
* and the shadow came back as a solid black slab around the card.
|
|
705
|
+
*/
|
|
706
|
+
function srgbXml(colorHex, alpha) {
|
|
707
|
+
if (alpha === void 0 || !(alpha < 1)) return `<a:srgbClr val="${colorHex}"/>`;
|
|
708
|
+
const val = Math.round(Math.max(0, alpha) * 1e5);
|
|
709
|
+
return `<a:srgbClr val="${colorHex}"><a:alpha val="${String(val)}"/></a:srgbClr>`;
|
|
710
|
+
}
|
|
711
|
+
function gradFillXml(g, alpha) {
|
|
632
712
|
return `<a:gradFill><a:gsLst>${g.stops.map((s) => {
|
|
633
|
-
return `<a:gs pos="${Math.round(Math.max(0, Math.min(1, s.offset)) * 1e5)}"
|
|
713
|
+
return `<a:gs pos="${Math.round(Math.max(0, Math.min(1, s.offset)) * 1e5)}">${srgbXml(s.colorHex, alpha)}</a:gs>`;
|
|
634
714
|
}).join("")}</a:gsLst>${g.kind === "radial" ? "<a:path path=\"circle\"/>" : `<a:lin ang="${Math.round(((g.angle ?? 0) % 360 + 360) % 360 * 6e4)}" scaled="1"/>`}</a:gradFill>`;
|
|
635
715
|
}
|
|
636
716
|
function lineXml(l) {
|
|
@@ -638,8 +718,13 @@ function lineXml(l) {
|
|
|
638
718
|
const cap = l.cap === "round" ? " cap=\"rnd\"" : l.cap === "square" ? " cap=\"sq\"" : l.cap === "flat" ? " cap=\"flat\"" : "";
|
|
639
719
|
const inner = [];
|
|
640
720
|
if (l.fill === "none") inner.push("<a:noFill/>");
|
|
641
|
-
else if (l.colorHex) inner.push(`<a:solidFill
|
|
642
|
-
|
|
721
|
+
else if (l.colorHex) inner.push(`<a:solidFill>${srgbXml(l.colorHex, l.alpha)}</a:solidFill>`);
|
|
722
|
+
const custom = l.customDash ?? [];
|
|
723
|
+
if (custom.length >= 2) {
|
|
724
|
+
const pairs = [];
|
|
725
|
+
for (let i = 0; i + 1 < custom.length; i += 2) pairs.push(`<a:ds d="${Math.round(custom[i] * 1e5)}" sp="${Math.round(custom[i + 1] * 1e5)}"/>`);
|
|
726
|
+
inner.push(`<a:custDash>${pairs.join("")}</a:custDash>`);
|
|
727
|
+
} else if (l.dash) inner.push(`<a:prstDash val="${l.dash}"/>`);
|
|
643
728
|
return `<a:ln${w}${cap}>${inner.join("")}</a:ln>`;
|
|
644
729
|
}
|
|
645
730
|
function txbxXml(text, losses, state, scope) {
|
|
@@ -704,6 +789,7 @@ function tblPrXml(p) {
|
|
|
704
789
|
if (p.alignment && p.alignment !== "left") out.push(`<w:jc w:val="${p.alignment}"/>`);
|
|
705
790
|
const borders = bordersXml("w:tblBorders", p.borders);
|
|
706
791
|
if (borders) out.push(borders);
|
|
792
|
+
if (p.layout === "fixed") out.push("<w:tblLayout w:type=\"fixed\"/>");
|
|
707
793
|
const margins = cellMarginsXml("w:tblCellMar", p.defaultCellMargins);
|
|
708
794
|
if (margins) out.push(margins);
|
|
709
795
|
return `<w:tblPr>${out.join("")}</w:tblPr>`;
|
|
@@ -747,9 +833,11 @@ var BORDER_SIDES = [
|
|
|
747
833
|
];
|
|
748
834
|
function bordersXml(tag, borders) {
|
|
749
835
|
if (!borders) return "";
|
|
750
|
-
const sides = BORDER_SIDES.map(([key,
|
|
836
|
+
const sides = BORDER_SIDES.map(([key, name]) => {
|
|
751
837
|
const b = borders[key];
|
|
752
838
|
if (!b) return "";
|
|
839
|
+
if (tag === "w:pBdr" && key === "insideV") return "";
|
|
840
|
+
const el = tag === "w:pBdr" && key === "insideH" ? "w:between" : name;
|
|
753
841
|
const sz = b.width !== void 0 ? ` w:sz="${Math.round(b.width * 8)}"` : "";
|
|
754
842
|
const color = b.colorHex !== void 0 ? ` w:color="${b.colorHex}"` : "";
|
|
755
843
|
return `<${el} w:val="${b.style}"${sz}${color}/>`;
|
|
@@ -809,10 +897,10 @@ function hyperlinkXml(run, inner, _state, scope) {
|
|
|
809
897
|
}
|
|
810
898
|
function runXml(run, state, scope) {
|
|
811
899
|
if (run.math !== void 0) return `<m:oMath xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math">${omathXml(run.math)}</m:oMath>`;
|
|
812
|
-
const rPr = rPrXml(run.properties);
|
|
900
|
+
const rPr = rPrXml(run.properties, state);
|
|
813
901
|
if (run.inlineImage !== void 0) {
|
|
814
902
|
const img = run.inlineImage;
|
|
815
|
-
const drawing = drawingXml(img.resource, img.width, img.height, void 0, state, scope);
|
|
903
|
+
const drawing = drawingXml(img.resource, img.width, img.height, void 0, state, scope, void 0, img);
|
|
816
904
|
if (drawing) return `<w:r>${rPr}${drawing}</w:r>`;
|
|
817
905
|
if (run.text === "" && !run.pageBreak) return "";
|
|
818
906
|
}
|
|
@@ -821,22 +909,30 @@ function runXml(run, state, scope) {
|
|
|
821
909
|
if (run.noteNumber) return `<w:r>${rPr}<${scope.noteKind === "endnote" ? "w:endnoteRef" : "w:footnoteRef"}/></w:r>`;
|
|
822
910
|
if (run.commentRef !== void 0) return `<w:r>${rPr}<w:commentReference w:id="${escapeAttr(run.commentRef)}"/></w:r>`;
|
|
823
911
|
const brk = run.pageBreak ? "<w:br w:type=\"page\"/>" : "";
|
|
912
|
+
if (run.field !== void 0 && run.text !== "") {
|
|
913
|
+
const piece = (inner) => `<w:r>${rPr}${inner}</w:r>`;
|
|
914
|
+
return piece("<w:fldChar w:fldCharType=\"begin\"/>") + piece(`<w:instrText xml:space="preserve"> ${run.field} </w:instrText>`) + piece("<w:fldChar w:fldCharType=\"separate\"/>") + piece(`<w:t xml:space="preserve">${escapeXml(run.text)}</w:t>`) + piece("<w:fldChar w:fldCharType=\"end\"/>") + brk;
|
|
915
|
+
}
|
|
824
916
|
if (run.text === "") return brk ? `<w:r>${rPr}${brk}</w:r>` : "";
|
|
825
|
-
return `<w:r>${rPr}
|
|
917
|
+
return `<w:r>${rPr}${run.text.split(" ").map((piece) => piece === "" ? "" : `<w:t xml:space="preserve">${escapeXml(piece)}</w:t>`).join("<w:tab/>")}${brk}</w:r>`;
|
|
826
918
|
}
|
|
827
|
-
function rPrXml(r) {
|
|
919
|
+
function rPrXml(r, state) {
|
|
828
920
|
const out = [];
|
|
829
|
-
const
|
|
921
|
+
const states = (key) => r[key] !== void 0 && r[key] !== DEFAULT_RUN[key];
|
|
922
|
+
const fonts = rFontsXml(r.fontFamily, state);
|
|
830
923
|
if (fonts) out.push(fonts);
|
|
831
|
-
if (
|
|
832
|
-
if (
|
|
833
|
-
if (
|
|
834
|
-
if (
|
|
835
|
-
if (
|
|
836
|
-
|
|
924
|
+
if (states("bold")) out.push(toggle("w:b", r.bold), toggle("w:bCs", r.bold));
|
|
925
|
+
if (states("italic")) out.push(toggle("w:i", r.italic), toggle("w:iCs", r.italic));
|
|
926
|
+
if (states("strike")) out.push(toggle("w:strike", r.strike));
|
|
927
|
+
if (states("colorHex")) out.push(`<w:color w:val="${r.colorHex}"/>`);
|
|
928
|
+
if (states("fontSizePt")) {
|
|
929
|
+
const half = Math.round(r.fontSizePt * 2);
|
|
930
|
+
out.push(`<w:sz w:val="${half}"/>`, `<w:szCs w:val="${half}"/>`);
|
|
931
|
+
}
|
|
932
|
+
if (states("underline")) out.push(underlineXml(r));
|
|
837
933
|
if (r.shadingColorHex !== void 0) out.push(runShdXml(r.shadingColorHex));
|
|
838
|
-
if (
|
|
839
|
-
if (
|
|
934
|
+
if (states("verticalAlign")) out.push(`<w:vertAlign w:val="${r.verticalAlign}"/>`);
|
|
935
|
+
if (states("rtl")) out.push(toggle("w:rtl", r.rtl));
|
|
840
936
|
if (r.lang !== void 0) out.push(`<w:lang w:val="${escapeAttr(r.lang)}"/>`);
|
|
841
937
|
return out.length > 0 ? `<w:rPr>${out.join("")}</w:rPr>` : "";
|
|
842
938
|
}
|
|
@@ -849,15 +945,26 @@ function runShdXml(fill) {
|
|
|
849
945
|
}
|
|
850
946
|
function pPrBody(p) {
|
|
851
947
|
const out = [];
|
|
852
|
-
if (p.numbering) out.push(`<w:numPr><w:ilvl w:val="${p.numbering.ilvl}"/><w:numId w:val="${escapeAttr(p.numbering.numId)}"/></w:numPr>`);
|
|
853
|
-
if (p.outlineLevel !== void 0) out.push(`<w:outlineLvl w:val="${p.outlineLevel}"/>`);
|
|
854
948
|
if (p.pageBreakBefore) out.push("<w:pageBreakBefore/>");
|
|
855
|
-
if (p.
|
|
856
|
-
const
|
|
857
|
-
if (
|
|
949
|
+
if (p.numbering) out.push(`<w:numPr><w:ilvl w:val="${p.numbering.ilvl}"/><w:numId w:val="${escapeAttr(p.numbering.numId)}"/></w:numPr>`);
|
|
950
|
+
const pBdr = bordersXml("w:pBdr", p.borders);
|
|
951
|
+
if (pBdr) out.push(pBdr);
|
|
952
|
+
const tabs = p.tabs ?? [];
|
|
953
|
+
if (tabs.length > 0) {
|
|
954
|
+
const stops = tabs.map((t) => {
|
|
955
|
+
const pos = twips(t.positionPt);
|
|
956
|
+
const leader = t.leader !== void 0 ? ` w:leader="${escapeAttr(t.leader)}"` : "";
|
|
957
|
+
return `<w:tab w:val="${escapeAttr(t.alignment ?? "left")}" w:pos="${String(pos)}"${leader}/>`;
|
|
958
|
+
}).join("");
|
|
959
|
+
out.push(`<w:tabs>${stops}</w:tabs>`);
|
|
960
|
+
}
|
|
961
|
+
if (p.bidi !== void 0 && p.bidi !== DEFAULT_PARA.bidi) out.push(toggle("w:bidi", p.bidi));
|
|
858
962
|
const spacing = spacingXml(p);
|
|
859
963
|
if (spacing) out.push(spacing);
|
|
964
|
+
const ind = indXml(p);
|
|
965
|
+
if (ind) out.push(ind);
|
|
860
966
|
if (JC.has(p.alignment) && p.alignment !== DEFAULT_PARA.alignment) out.push(`<w:jc w:val="${p.alignment}"/>`);
|
|
967
|
+
if (p.outlineLevel !== void 0) out.push(`<w:outlineLvl w:val="${p.outlineLevel}"/>`);
|
|
861
968
|
return out.join("");
|
|
862
969
|
}
|
|
863
970
|
function pPrWithSect(p, closingSectPr) {
|
|
@@ -904,12 +1011,22 @@ function spacingXml(p) {
|
|
|
904
1011
|
}
|
|
905
1012
|
return attrs.length > 0 ? `<w:spacing ${attrs.join(" ")}/>` : "";
|
|
906
1013
|
}
|
|
907
|
-
function rFontsXml(fonts) {
|
|
1014
|
+
function rFontsXml(fonts, state) {
|
|
1015
|
+
if (fonts === void 0) return "";
|
|
908
1016
|
const d = DEFAULT_RUN.fontFamily;
|
|
1017
|
+
const family = (name) => {
|
|
1018
|
+
const known = state?.faceFamilies?.get(name);
|
|
1019
|
+
if (known === void 0) return name;
|
|
1020
|
+
state?.familiesUsed.set(known.family, known);
|
|
1021
|
+
return known.family;
|
|
1022
|
+
};
|
|
909
1023
|
const attrs = [];
|
|
910
|
-
if (fonts.ascii && fonts.ascii !== d.ascii) attrs.push(`w:ascii="${escapeAttr(fonts.ascii)}"`);
|
|
911
|
-
if (fonts.hAnsi && fonts.hAnsi !== d.hAnsi) attrs.push(`w:hAnsi="${escapeAttr(fonts.hAnsi)}"`);
|
|
912
|
-
|
|
1024
|
+
if (fonts.ascii && fonts.ascii !== d.ascii) attrs.push(`w:ascii="${escapeAttr(family(fonts.ascii))}"`);
|
|
1025
|
+
if (fonts.hAnsi && fonts.hAnsi !== d.hAnsi) attrs.push(`w:hAnsi="${escapeAttr(family(fonts.hAnsi))}"`);
|
|
1026
|
+
const face = fonts.ascii !== void 0 && state?.faceFamilies?.has(fonts.ascii) === true ? family(fonts.ascii) : void 0;
|
|
1027
|
+
if (face !== void 0 && fonts.eastAsia === void 0) attrs.push(`w:eastAsia="${escapeAttr(face)}"`);
|
|
1028
|
+
if (fonts.cs && fonts.cs !== d.cs) attrs.push(`w:cs="${escapeAttr(family(fonts.cs))}"`);
|
|
1029
|
+
else if (face !== void 0) attrs.push(`w:cs="${escapeAttr(face)}"`);
|
|
913
1030
|
return attrs.length > 0 ? `<w:rFonts ${attrs.join(" ")}/>` : "";
|
|
914
1031
|
}
|
|
915
1032
|
function toggle(tag, on) {
|
|
@@ -2128,13 +2128,17 @@ function parseLine(spPr, resolveColor) {
|
|
|
2128
2128
|
const cap = capRaw === "rnd" ? "round" : capRaw === "sq" ? "square" : capRaw === "flat" ? "flat" : void 0;
|
|
2129
2129
|
let noFill = false;
|
|
2130
2130
|
let colorHex;
|
|
2131
|
+
let alpha;
|
|
2131
2132
|
let dash;
|
|
2132
2133
|
let customDash;
|
|
2133
2134
|
let headEnd;
|
|
2134
2135
|
let tailEnd;
|
|
2135
2136
|
for (const c of poChildren(ln)) if (poIs(c, "a:noFill")) noFill = true;
|
|
2136
|
-
else if (poIs(c, "a:solidFill"))
|
|
2137
|
-
|
|
2137
|
+
else if (poIs(c, "a:solidFill")) {
|
|
2138
|
+
alpha = containerAlpha(c);
|
|
2139
|
+
const hex = colorFromContainer(c, resolveColor);
|
|
2140
|
+
colorHex = hex !== void 0 && alpha !== void 0 ? unblendWhite(hex, alpha) : hex;
|
|
2141
|
+
} else if (poIs(c, "a:prstDash")) dash = normalizeDash(poAttr(c, "val"));
|
|
2138
2142
|
else if (poIs(c, "a:custDash")) customDash = parseCustDash(c);
|
|
2139
2143
|
else if (poIs(c, "a:headEnd")) headEnd = parseLineEnd(c);
|
|
2140
2144
|
else if (poIs(c, "a:tailEnd")) tailEnd = parseLineEnd(c);
|
|
@@ -2145,6 +2149,7 @@ function parseLine(spPr, resolveColor) {
|
|
|
2145
2149
|
...customDash && customDash.length > 0 ? { customDash } : {},
|
|
2146
2150
|
...cap ? { cap } : {},
|
|
2147
2151
|
...noFill ? { fill: "none" } : {},
|
|
2152
|
+
...alpha !== void 0 && alpha < 1 ? { alpha } : {},
|
|
2148
2153
|
...headEnd ? { headEnd } : {},
|
|
2149
2154
|
...tailEnd ? { tailEnd } : {}
|
|
2150
2155
|
};
|
|
@@ -271,10 +271,12 @@ function parseParagraphBorders(node) {
|
|
|
271
271
|
const bottom = edge("w:bottom");
|
|
272
272
|
const left = edge("w:left", "w:start");
|
|
273
273
|
const right = edge("w:right", "w:end");
|
|
274
|
+
const between = edge("w:between");
|
|
274
275
|
if (top) out.top = top;
|
|
275
276
|
if (bottom) out.bottom = bottom;
|
|
276
277
|
if (left) out.left = left;
|
|
277
278
|
if (right) out.right = right;
|
|
279
|
+
if (between) out.insideH = between;
|
|
278
280
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
279
281
|
}
|
|
280
282
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reamkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.30.0",
|
|
4
4
|
"description": "Ream — convert DOCX, XLSX, PPTX and PDF to PDF, SVG, HTML, DOCX and XLSX, built from scratch on the ECMA-376 and ISO 32000 specifications. Parse once, convert anywhere.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Alex Krassavin <info@reamkit.dev>",
|
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
"typecheck": "tsc -p tsconfig.eslint.json --noEmit",
|
|
64
64
|
"lint": "eslint .",
|
|
65
65
|
"lint:fix": "eslint . --fix",
|
|
66
|
-
"format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\" \"scripts/**/*.ts\"",
|
|
67
|
-
"format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\" \"scripts/**/*.ts\"",
|
|
66
|
+
"format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\" \"scripts/**/*.ts\" \"stand/**/*.ts\"",
|
|
67
|
+
"format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\" \"scripts/**/*.ts\" \"stand/**/*.ts\"",
|
|
68
68
|
"corpus:build": "tsx scripts/corpus/build-corpus.ts",
|
|
69
69
|
"corpus:fetch": "tsx scripts/corpus/fetch-corpus.ts",
|
|
70
70
|
"corpus:sandbox:build": "docker build -t docgen-losandbox:latest scripts/corpus/sandbox/",
|
|
@@ -77,6 +77,8 @@
|
|
|
77
77
|
"corpus:visual": "tsx scripts/corpus/visual-diff.ts",
|
|
78
78
|
"corpus:scout": "tsx scripts/corpus/scout.ts",
|
|
79
79
|
"corpus:pixel": "tsx scripts/corpus/pixel-scout.ts",
|
|
80
|
+
"stand": "tsx stand/serve.ts",
|
|
81
|
+
"stand:build": "tsx stand/build.ts",
|
|
80
82
|
"typecheck:dist": "tsc -p tsconfig.json --noEmit"
|
|
81
83
|
},
|
|
82
84
|
"dependencies": {
|