reamkit 1.29.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/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 +5 -2
- package/dist/esm/pdf-reader/content.d.ts +17 -4
- package/dist/esm/pdf-reader/content.js +163 -11
- package/dist/esm/pdf-reader/display.js +16 -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 +96 -5
- package/dist/esm/pdf-reader/flow-build.js +210 -23
- 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 +638 -92
- 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 +8 -2
- package/dist/esm/pdf-reader/vector.js +34 -5
- package/dist/esm/word/docx-writer.js +137 -36
- 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({
|
|
@@ -514,7 +576,7 @@ function drawingFrame(float, cx, cy, head, graphic, state, rotation60k) {
|
|
|
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
|
}
|
|
@@ -822,22 +910,25 @@ function runXml(run, state, scope) {
|
|
|
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\"/>" : "";
|
|
824
912
|
if (run.field !== void 0 && run.text !== "") {
|
|
825
|
-
const
|
|
826
|
-
return
|
|
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;
|
|
827
915
|
}
|
|
828
916
|
if (run.text === "") return brk ? `<w:r>${rPr}${brk}</w:r>` : "";
|
|
829
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>`;
|
|
830
918
|
}
|
|
831
|
-
function rPrXml(r) {
|
|
919
|
+
function rPrXml(r, state) {
|
|
832
920
|
const out = [];
|
|
833
921
|
const states = (key) => r[key] !== void 0 && r[key] !== DEFAULT_RUN[key];
|
|
834
|
-
const fonts = rFontsXml(r.fontFamily);
|
|
922
|
+
const fonts = rFontsXml(r.fontFamily, state);
|
|
835
923
|
if (fonts) out.push(fonts);
|
|
836
|
-
if (states("bold")) out.push(toggle("w:b", r.bold));
|
|
837
|
-
if (states("italic")) out.push(toggle("w:i", r.italic));
|
|
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));
|
|
838
926
|
if (states("strike")) out.push(toggle("w:strike", r.strike));
|
|
839
927
|
if (states("colorHex")) out.push(`<w:color w:val="${r.colorHex}"/>`);
|
|
840
|
-
if (states("fontSizePt"))
|
|
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
|
+
}
|
|
841
932
|
if (states("underline")) out.push(underlineXml(r));
|
|
842
933
|
if (r.shadingColorHex !== void 0) out.push(runShdXml(r.shadingColorHex));
|
|
843
934
|
if (states("verticalAlign")) out.push(`<w:vertAlign w:val="${r.verticalAlign}"/>`);
|
|
@@ -854,15 +945,8 @@ function runShdXml(fill) {
|
|
|
854
945
|
}
|
|
855
946
|
function pPrBody(p) {
|
|
856
947
|
const out = [];
|
|
857
|
-
if (p.numbering) out.push(`<w:numPr><w:ilvl w:val="${p.numbering.ilvl}"/><w:numId w:val="${escapeAttr(p.numbering.numId)}"/></w:numPr>`);
|
|
858
|
-
if (p.outlineLevel !== void 0) out.push(`<w:outlineLvl w:val="${p.outlineLevel}"/>`);
|
|
859
948
|
if (p.pageBreakBefore) out.push("<w:pageBreakBefore/>");
|
|
860
|
-
if (p.
|
|
861
|
-
const ind = indXml(p);
|
|
862
|
-
if (ind) out.push(ind);
|
|
863
|
-
const spacing = spacingXml(p);
|
|
864
|
-
if (spacing) out.push(spacing);
|
|
865
|
-
if (JC.has(p.alignment) && p.alignment !== DEFAULT_PARA.alignment) out.push(`<w:jc w:val="${p.alignment}"/>`);
|
|
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>`);
|
|
866
950
|
const pBdr = bordersXml("w:pBdr", p.borders);
|
|
867
951
|
if (pBdr) out.push(pBdr);
|
|
868
952
|
const tabs = p.tabs ?? [];
|
|
@@ -874,6 +958,13 @@ function pPrBody(p) {
|
|
|
874
958
|
}).join("");
|
|
875
959
|
out.push(`<w:tabs>${stops}</w:tabs>`);
|
|
876
960
|
}
|
|
961
|
+
if (p.bidi !== void 0 && p.bidi !== DEFAULT_PARA.bidi) out.push(toggle("w:bidi", p.bidi));
|
|
962
|
+
const spacing = spacingXml(p);
|
|
963
|
+
if (spacing) out.push(spacing);
|
|
964
|
+
const ind = indXml(p);
|
|
965
|
+
if (ind) out.push(ind);
|
|
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}"/>`);
|
|
877
968
|
return out.join("");
|
|
878
969
|
}
|
|
879
970
|
function pPrWithSect(p, closingSectPr) {
|
|
@@ -920,12 +1011,22 @@ function spacingXml(p) {
|
|
|
920
1011
|
}
|
|
921
1012
|
return attrs.length > 0 ? `<w:spacing ${attrs.join(" ")}/>` : "";
|
|
922
1013
|
}
|
|
923
|
-
function rFontsXml(fonts) {
|
|
1014
|
+
function rFontsXml(fonts, state) {
|
|
1015
|
+
if (fonts === void 0) return "";
|
|
924
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
|
+
};
|
|
925
1023
|
const attrs = [];
|
|
926
|
-
if (fonts.ascii && fonts.ascii !== d.ascii) attrs.push(`w:ascii="${escapeAttr(fonts.ascii)}"`);
|
|
927
|
-
if (fonts.hAnsi && fonts.hAnsi !== d.hAnsi) attrs.push(`w:hAnsi="${escapeAttr(fonts.hAnsi)}"`);
|
|
928
|
-
|
|
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)}"`);
|
|
929
1030
|
return attrs.length > 0 ? `<w:rFonts ${attrs.join(" ")}/>` : "";
|
|
930
1031
|
}
|
|
931
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": {
|