reamkit 1.24.0 → 1.25.1
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 +22 -11
- package/dist/esm/core/converter/facade.d.ts +3 -3
- package/dist/esm/core/converter/facade.js +12 -0
- package/dist/esm/core/converter/ream.d.ts +48 -4
- package/dist/esm/core/converter/ream.js +25 -4
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +17 -0
- package/dist/esm/core/outline.d.ts +17 -0
- package/dist/esm/core/outline.js +30 -0
- package/dist/esm/core/style-cascade/resolver.js +1 -0
- package/dist/esm/core/style-cascade/types.d.ts +3 -1
- package/dist/esm/excel/sheet-to-flow.d.ts +10 -0
- package/dist/esm/excel/sheet-to-flow.js +14 -1
- package/dist/esm/html/html-writer.js +3 -2
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/layout/page-doc.js +1 -1
- package/dist/esm/layout/styled-layout.js +41 -15
- package/dist/esm/markdown/markdown-writer.d.ts +41 -0
- package/dist/esm/markdown/markdown-writer.js +733 -0
- package/dist/esm/pdf/styled-page-emitter.js +20 -1
- package/dist/esm/pdf-reader/annots.d.ts +24 -0
- package/dist/esm/pdf-reader/annots.js +126 -0
- package/dist/esm/pdf-reader/content.d.ts +131 -5
- package/dist/esm/pdf-reader/content.js +169 -12
- package/dist/esm/pdf-reader/display.d.ts +56 -0
- package/dist/esm/pdf-reader/display.js +162 -0
- package/dist/esm/pdf-reader/document.d.ts +36 -1
- package/dist/esm/pdf-reader/document.js +92 -25
- package/dist/esm/pdf-reader/embedded-fonts.d.ts +31 -0
- package/dist/esm/pdf-reader/embedded-fonts.js +94 -0
- package/dist/esm/pdf-reader/flow-build.d.ts +61 -6
- package/dist/esm/pdf-reader/flow-build.js +128 -22
- package/dist/esm/pdf-reader/font.js +185 -4
- package/dist/esm/pdf-reader/image-decode.js +55 -4
- package/dist/esm/pdf-reader/images.d.ts +6 -0
- package/dist/esm/pdf-reader/images.js +25 -5
- package/dist/esm/pdf-reader/jpeg.d.ts +18 -0
- package/dist/esm/pdf-reader/jpeg.js +419 -0
- package/dist/esm/pdf-reader/layout.d.ts +1 -1
- package/dist/esm/pdf-reader/layout.js +221 -32
- package/dist/esm/pdf-reader/pattern-tint.d.ts +17 -0
- package/dist/esm/pdf-reader/pattern-tint.js +181 -0
- package/dist/esm/pdf-reader/reader.d.ts +9 -1
- package/dist/esm/pdf-reader/reader.js +23 -7
- package/dist/esm/pdf-reader/shading.d.ts +14 -0
- package/dist/esm/pdf-reader/shading.js +27 -1
- package/dist/esm/pdf-reader/tagged.js +156 -17
- package/dist/esm/pdf-reader/text.d.ts +13 -1
- package/dist/esm/pdf-reader/text.js +70 -3
- package/dist/esm/pdf-reader/vector.d.ts +25 -1
- package/dist/esm/pdf-reader/vector.js +168 -12
- package/dist/esm/pptx/slide-parser.js +5 -0
- package/dist/esm/word/docx-writer.js +79 -17
- package/dist/esm/word/drawing-parser.js +7 -1
- package/package.json +1 -1
|
@@ -447,19 +447,49 @@ function shapeDrawingXml(shape, losses, state, scope) {
|
|
|
447
447
|
function xfrmXml(t, cx, cy) {
|
|
448
448
|
return `<a:xfrm${t?.rotation60k !== void 0 ? ` rot="${t.rotation60k}"` : ""}${t?.flipH ? " flipH=\"1\"" : ""}${t?.flipV ? " flipV=\"1\"" : ""}><a:off x="0" y="0"/><a:ext cx="${cx}" cy="${cy}"/></a:xfrm>`;
|
|
449
449
|
}
|
|
450
|
+
/**
|
|
451
|
+
* The factor that carries a path into whole units, and the space it lands in.
|
|
452
|
+
*
|
|
453
|
+
* §20.1.10.16 — ST_Coordinate is a LONG: a path states its geometry in whole
|
|
454
|
+
* units, and a fractional one is not a value the attribute admits. Word does
|
|
455
|
+
* not round it, and does not ignore the shape: it refuses the document, saying
|
|
456
|
+
* only that it "experienced an error trying to open the file".
|
|
457
|
+
*
|
|
458
|
+
* A path space is arbitrary — `a:path w`/`h` declare the coordinate system the
|
|
459
|
+
* shape's extent is mapped onto — so a path that does not land on whole units
|
|
460
|
+
* is restated in a finer space rather than rounded where it stands. A path read
|
|
461
|
+
* off a PDF is in points, and a point split ten thousand ways is finer than any
|
|
462
|
+
* renderer draws. The factor is bounded so the space stays far inside the
|
|
463
|
+
* coordinate range whatever the path's own size, and a path already on whole
|
|
464
|
+
* units is left exactly as it is.
|
|
465
|
+
*/
|
|
466
|
+
var PATH_SPACE = 1e7;
|
|
467
|
+
function pathScale(g) {
|
|
468
|
+
const values = [g.pathWidth, g.pathHeight];
|
|
469
|
+
for (const c of g.commands) if (c.cmd === "move" || c.cmd === "line") values.push(c.x, c.y);
|
|
470
|
+
else if (c.cmd === "cubic") values.push(c.x1, c.y1, c.x2, c.y2, c.x, c.y);
|
|
471
|
+
else if (c.cmd === "quad") values.push(c.x1, c.y1, c.x, c.y);
|
|
472
|
+
else if (c.cmd === "arc") values.push(c.wR, c.hR);
|
|
473
|
+
if (values.every((v) => Number.isInteger(v))) return 1;
|
|
474
|
+
const span = Math.max(...values.map((v) => Number.isFinite(v) ? Math.abs(v) : 0), 1);
|
|
475
|
+
return Math.max(1, Math.floor(PATH_SPACE / span));
|
|
476
|
+
}
|
|
450
477
|
function geomXml(g) {
|
|
451
478
|
if (g.kind === "custom" && g.custom) {
|
|
479
|
+
const k = pathScale(g.custom);
|
|
480
|
+
const c1 = (v) => Number.isFinite(v) ? Math.round(v * k) : 0;
|
|
452
481
|
const cmds = g.custom.commands.map((c) => {
|
|
453
482
|
switch (c.cmd) {
|
|
454
|
-
case "move": return `<a:moveTo><a:pt x="${c.x}" y="${c.y}"/></a:moveTo>`;
|
|
455
|
-
case "line": return `<a:lnTo><a:pt x="${c.x}" y="${c.y}"/></a:lnTo>`;
|
|
456
|
-
case "cubic": return `<a:cubicBezTo><a:pt x="${c.x1}" y="${c.y1}"/><a:pt x="${c.x2}" y="${c.y2}"/><a:pt x="${c.x}" y="${c.y}"/></a:cubicBezTo>`;
|
|
457
|
-
case "quad": return `<a:quadBezTo><a:pt x="${c.x1}" y="${c.y1}"/><a:pt x="${c.x}" y="${c.y}"/></a:quadBezTo>`;
|
|
458
|
-
case "arc": return `<a:arcTo wR="${c.wR}" hR="${c.hR}" stAng="${c.stAng}" swAng="${c.swAng}"/>`;
|
|
483
|
+
case "move": return `<a:moveTo><a:pt x="${c1(c.x)}" y="${c1(c.y)}"/></a:moveTo>`;
|
|
484
|
+
case "line": return `<a:lnTo><a:pt x="${c1(c.x)}" y="${c1(c.y)}"/></a:lnTo>`;
|
|
485
|
+
case "cubic": return `<a:cubicBezTo><a:pt x="${c1(c.x1)}" y="${c1(c.y1)}"/><a:pt x="${c1(c.x2)}" y="${c1(c.y2)}"/><a:pt x="${c1(c.x)}" y="${c1(c.y)}"/></a:cubicBezTo>`;
|
|
486
|
+
case "quad": return `<a:quadBezTo><a:pt x="${c1(c.x1)}" y="${c1(c.y1)}"/><a:pt x="${c1(c.x)}" y="${c1(c.y)}"/></a:quadBezTo>`;
|
|
487
|
+
case "arc": return `<a:arcTo wR="${c1(c.wR)}" hR="${c1(c.hR)}" stAng="${Math.round(c.stAng)}" swAng="${Math.round(c.swAng)}"/>`;
|
|
459
488
|
case "close": return "<a:close/>";
|
|
460
489
|
}
|
|
461
490
|
}).join("");
|
|
462
|
-
const
|
|
491
|
+
const w = c1(g.custom.pathWidth);
|
|
492
|
+
const h = c1(g.custom.pathHeight);
|
|
463
493
|
return `<a:custGeom><a:avLst/><a:gdLst/><a:rect l="0" t="0" r="${w}" b="${h}"/><a:pathLst><a:path w="${w}" h="${h}">${cmds}</a:path></a:pathLst></a:custGeom>`;
|
|
464
494
|
}
|
|
465
495
|
const gds = g.adjust && g.adjust.size > 0 ? [...g.adjust].map(([n, v]) => `<a:gd name="${escapeAttr(n)}" fmla="val ${v}"/>`).join("") : "";
|
|
@@ -527,6 +557,16 @@ function tableXml(table, losses, state, scope) {
|
|
|
527
557
|
const rows = table.rows.map((row) => rowXml(row, losses, state, scope)).join("");
|
|
528
558
|
return `<w:tbl>${tblPrXml(table.properties)}<w:tblGrid>${grid}</w:tblGrid>${rows}</w:tbl>`;
|
|
529
559
|
}
|
|
560
|
+
/**
|
|
561
|
+
* §17.4.60 — `w:tblPr`. CT_Tbl declares it `minOccurs="1"`: a table states its
|
|
562
|
+
* properties even when it has none to state, and Word refuses to open a file
|
|
563
|
+
* whose `w:tbl` opens straight into its grid. Nothing else in the wild writes
|
|
564
|
+
* one without it — 5432 tables across the LibreOffice, Word and POI corpora,
|
|
565
|
+
* every one of them with a `w:tblPr` — and it went unnoticed here because a
|
|
566
|
+
* table read from a real document always carries SOMETHING (a width, a border,
|
|
567
|
+
* an alignment). One reconstructed from a PDF's glyph positions carries none of
|
|
568
|
+
* it, so `Ream.parse(pdf).convert('docx')` wrote a document Word turned away.
|
|
569
|
+
*/
|
|
530
570
|
function tblPrXml(p) {
|
|
531
571
|
const out = [];
|
|
532
572
|
if (p.widthType !== void 0) {
|
|
@@ -538,7 +578,7 @@ function tblPrXml(p) {
|
|
|
538
578
|
if (borders) out.push(borders);
|
|
539
579
|
const margins = cellMarginsXml("w:tblCellMar", p.defaultCellMargins);
|
|
540
580
|
if (margins) out.push(margins);
|
|
541
|
-
return
|
|
581
|
+
return `<w:tblPr>${out.join("")}</w:tblPr>`;
|
|
542
582
|
}
|
|
543
583
|
function rowXml(row, losses, state, scope) {
|
|
544
584
|
const trPr = [];
|
|
@@ -681,25 +721,47 @@ function pPrBody(p) {
|
|
|
681
721
|
if (ind) out.push(ind);
|
|
682
722
|
const spacing = spacingXml(p);
|
|
683
723
|
if (spacing) out.push(spacing);
|
|
684
|
-
if (p.alignment !== DEFAULT_PARA.alignment) out.push(`<w:jc w:val="${p.alignment}"/>`);
|
|
724
|
+
if (JC.has(p.alignment) && p.alignment !== DEFAULT_PARA.alignment) out.push(`<w:jc w:val="${p.alignment}"/>`);
|
|
685
725
|
return out.join("");
|
|
686
726
|
}
|
|
687
727
|
function pPrWithSect(p, closingSectPr) {
|
|
688
728
|
const inner = pPrBody(p) + (closingSectPr ?? "");
|
|
689
729
|
return inner !== "" ? `<w:pPr>${inner}</w:pPr>` : "";
|
|
690
730
|
}
|
|
731
|
+
/**
|
|
732
|
+
* Whether a measurement is one the file can state.
|
|
733
|
+
*
|
|
734
|
+
* A property that was COMPUTED rather than read can arrive `NaN` — an
|
|
735
|
+
* `undefined` that went through arithmetic, a share of a width that was zero —
|
|
736
|
+
* and `NaN` is not a value ST_SignedTwipsMeasure admits. Word does not ignore
|
|
737
|
+
* the attribute: it refuses the whole document, with no indication of what it
|
|
738
|
+
* objected to. `Ream.parse(pdf).convert('docx')` wrote 355 of them on one form.
|
|
739
|
+
*
|
|
740
|
+
* So a measurement is written only when there IS one, and a paragraph that
|
|
741
|
+
* cannot say how it is indented says nothing and inherits, which is what an
|
|
742
|
+
* absent attribute means (§17.3.1.12).
|
|
743
|
+
*/
|
|
744
|
+
var stated = (pt) => Number.isFinite(pt);
|
|
745
|
+
/** §17.18.44 ST_Jc — the tokens the attribute admits, so nothing else is written. */
|
|
746
|
+
var JC = new Set([
|
|
747
|
+
"left",
|
|
748
|
+
"right",
|
|
749
|
+
"center",
|
|
750
|
+
"both",
|
|
751
|
+
"distribute"
|
|
752
|
+
]);
|
|
691
753
|
function indXml(p) {
|
|
692
754
|
const attrs = [];
|
|
693
|
-
if (p.indentLeft !== DEFAULT_PARA.indentLeft) attrs.push(`w:left="${twips(p.indentLeft)}"`);
|
|
694
|
-
if (p.indentRight !== DEFAULT_PARA.indentRight) attrs.push(`w:right="${twips(p.indentRight)}"`);
|
|
695
|
-
if (p.indentFirstLine !== DEFAULT_PARA.indentFirstLine) if (p.indentFirstLine < 0) attrs.push(`w:hanging="${twips(-p.indentFirstLine)}"`);
|
|
755
|
+
if (stated(p.indentLeft) && p.indentLeft !== DEFAULT_PARA.indentLeft) attrs.push(`w:left="${twips(p.indentLeft)}"`);
|
|
756
|
+
if (stated(p.indentRight) && p.indentRight !== DEFAULT_PARA.indentRight) attrs.push(`w:right="${twips(p.indentRight)}"`);
|
|
757
|
+
if (stated(p.indentFirstLine) && p.indentFirstLine !== DEFAULT_PARA.indentFirstLine) if (p.indentFirstLine < 0) attrs.push(`w:hanging="${twips(-p.indentFirstLine)}"`);
|
|
696
758
|
else attrs.push(`w:firstLine="${twips(p.indentFirstLine)}"`);
|
|
697
759
|
return attrs.length > 0 ? `<w:ind ${attrs.join(" ")}/>` : "";
|
|
698
760
|
}
|
|
699
761
|
function spacingXml(p) {
|
|
700
762
|
const attrs = [];
|
|
701
|
-
if (p.spacingBefore !== DEFAULT_PARA.spacingBefore) attrs.push(`w:before="${twips(p.spacingBefore)}"`);
|
|
702
|
-
if (p.spacingAfter !== DEFAULT_PARA.spacingAfter) attrs.push(`w:after="${twips(p.spacingAfter)}"`);
|
|
763
|
+
if (stated(p.spacingBefore) && p.spacingBefore !== DEFAULT_PARA.spacingBefore) attrs.push(`w:before="${twips(p.spacingBefore)}"`);
|
|
764
|
+
if (stated(p.spacingAfter) && p.spacingAfter !== DEFAULT_PARA.spacingAfter) attrs.push(`w:after="${twips(p.spacingAfter)}"`);
|
|
703
765
|
if ((p.spacingLineRule !== DEFAULT_PARA.spacingLineRule || p.spacingLine !== DEFAULT_PARA.spacingLine) && p.spacingLine > 0) {
|
|
704
766
|
const lineVal = p.spacingLineRule === "auto" ? Math.round(p.spacingLine * 12) : twips(p.spacingLine);
|
|
705
767
|
attrs.push(`w:line="${lineVal}"`, `w:lineRule="${p.spacingLineRule}"`);
|
|
@@ -742,12 +804,12 @@ function levelXml(level) {
|
|
|
742
804
|
}
|
|
743
805
|
function rawParaPrXml(p) {
|
|
744
806
|
const attrs = [];
|
|
745
|
-
if (p.indentLeft !== void 0) attrs.push(`w:left="${twips(p.indentLeft)}"`);
|
|
746
|
-
if (p.indentRight !== void 0) attrs.push(`w:right="${twips(p.indentRight)}"`);
|
|
747
|
-
if (p.indentFirstLine !== void 0) if (p.indentFirstLine < 0) attrs.push(`w:hanging="${twips(-p.indentFirstLine)}"`);
|
|
807
|
+
if (p.indentLeft !== void 0 && stated(p.indentLeft)) attrs.push(`w:left="${twips(p.indentLeft)}"`);
|
|
808
|
+
if (p.indentRight !== void 0 && stated(p.indentRight)) attrs.push(`w:right="${twips(p.indentRight)}"`);
|
|
809
|
+
if (p.indentFirstLine !== void 0 && stated(p.indentFirstLine)) if (p.indentFirstLine < 0) attrs.push(`w:hanging="${twips(-p.indentFirstLine)}"`);
|
|
748
810
|
else attrs.push(`w:firstLine="${twips(p.indentFirstLine)}"`);
|
|
749
811
|
const ind = attrs.length > 0 ? `<w:ind ${attrs.join(" ")}/>` : "";
|
|
750
|
-
const jc = p.alignment !== void 0 ? `<w:jc w:val="${p.alignment}"/>` : "";
|
|
812
|
+
const jc = p.alignment !== void 0 && JC.has(p.alignment) ? `<w:jc w:val="${p.alignment}"/>` : "";
|
|
751
813
|
return ind || jc ? `<w:pPr>${jc}${ind}</w:pPr>` : "";
|
|
752
814
|
}
|
|
753
815
|
function rawRunPrXml(r) {
|
|
@@ -1042,7 +1042,11 @@ function vmlTextBox(shape, parseBody) {
|
|
|
1042
1042
|
const content = box ? poFindDescendant(box, "w:txbxContent") : void 0;
|
|
1043
1043
|
if (!content) return void 0;
|
|
1044
1044
|
const blocks = parseBody(poChildren(content));
|
|
1045
|
-
|
|
1045
|
+
if (blocks.length === 0) return void 0;
|
|
1046
|
+
return {
|
|
1047
|
+
content: blocks,
|
|
1048
|
+
upright: true
|
|
1049
|
+
};
|
|
1046
1050
|
}
|
|
1047
1051
|
/**
|
|
1048
1052
|
* The `@style` of a positioned VML shape as a float anchor: `position:absolute`
|
|
@@ -1653,11 +1657,13 @@ function parseTextBox(wsp, parseBody) {
|
|
|
1653
1657
|
const anchor = a === "ctr" ? "ctr" : a === "b" ? "b" : a === "t" ? "t" : void 0;
|
|
1654
1658
|
const v = bodyPr ? poAttr(bodyPr, "vert") : void 0;
|
|
1655
1659
|
const vertical = v === "vert270" ? "vert270" : v !== void 0 && v !== "horz" ? "vert" : void 0;
|
|
1660
|
+
const upright = bodyPr !== void 0 && poAttr(bodyPr, "upright") === "1";
|
|
1656
1661
|
const autoFit = bodyPr !== void 0 && poChildren(bodyPr).some((c) => poIs(c, "a:spAutoFit"));
|
|
1657
1662
|
return {
|
|
1658
1663
|
content,
|
|
1659
1664
|
...chain ? { chain } : {},
|
|
1660
1665
|
...vertical ? { vertical } : {},
|
|
1666
|
+
...upright ? { upright } : {},
|
|
1661
1667
|
...autoFit ? { autoFit: true } : {},
|
|
1662
1668
|
...lIns !== void 0 ? { insetLeft: emuToPt(lIns) } : {},
|
|
1663
1669
|
...tIns !== void 0 ? { insetTop: emuToPt(tIns) } : {},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reamkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.25.1",
|
|
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>",
|