@muhammara/native-core 7.0.0-rc.2 → 7.1.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/index.js +230 -32
- package/lib/Recipe.js +30 -14
- package/lib/recipe/appendPage.js +1 -1
- package/lib/recipe/colors.js +1 -2
- package/lib/recipe/encrypt.js +1 -2
- package/lib/recipe/graphics-state.js +2 -1
- package/lib/recipe/image.js +9 -6
- package/lib/recipe/info.js +17 -10
- package/lib/recipe/insertPage.js +1 -2
- package/lib/recipe/page.js +54 -11
- package/lib/recipe/shapes.js +3 -3
- package/lib/recipe/split.js +1 -2
- package/lib/recipe/table.js +2 -0
- package/lib/recipe/text.helper.js +6 -4
- package/lib/recipe/text.js +403 -40
- package/lib/recipe/utils.js +12 -0
- package/lib/recipe/vector-line.js +1 -2
- package/lib/recipe/vector-polygon.js +1 -1
- package/lib/recipe/vector.js +7 -8
- package/lib/recipe-constants.js +1 -1
- package/licenses/AdobeGlyphList.txt +29 -0
- package/muhammara.d.ts +59 -9
- package/package.json +2 -1
package/lib/recipe/page.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const muhammara = require("../muhammara");
|
|
2
1
|
const { PAGE_CONTEXT_STATE } = require("./utils");
|
|
3
2
|
const { PageLayout, Colorspace } = require("../recipe-constants");
|
|
4
3
|
const {
|
|
@@ -541,11 +540,17 @@ function writePageLabels(writer, copyingContext, pageLabels) {
|
|
|
541
540
|
* @param {number} [margins.bottom] - Bottom margin.
|
|
542
541
|
* @returns {Recipe} The recipe instance.
|
|
543
542
|
* @throws {Error} If pages were deleted with deletePage() on this Recipe.
|
|
543
|
+
* @throws {Error} If another page is still active; call endPage() first.
|
|
544
544
|
*/
|
|
545
545
|
exports.createPage = function createPage(pageWidth, pageHeight, margins) {
|
|
546
546
|
if (this.deletedPages?.size) {
|
|
547
547
|
throw new Error("createPage cannot be combined with deletePage");
|
|
548
548
|
}
|
|
549
|
+
// Opening a second page over an active one leaves the first page
|
|
550
|
+
// unfinished: the writer then crashes or silently drops it at endPDF().
|
|
551
|
+
if (this.page) {
|
|
552
|
+
throw new Error("Finish the current page before creating another page");
|
|
553
|
+
}
|
|
549
554
|
if (!pageWidth && !pageHeight) {
|
|
550
555
|
[pageWidth, pageHeight] = this.default.pageSize;
|
|
551
556
|
} else if (
|
|
@@ -605,17 +610,45 @@ exports.createPage = function createPage(pageWidth, pageHeight, margins) {
|
|
|
605
610
|
}
|
|
606
611
|
|
|
607
612
|
this.moveTo(0, 0);
|
|
613
|
+
resetTextBox(this, 0, 0);
|
|
608
614
|
return this;
|
|
609
615
|
};
|
|
610
616
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
}
|
|
617
|
+
/**
|
|
618
|
+
* Forget the previous page's text box, so text() without coordinates starts
|
|
619
|
+
* at the margins of the new active page instead of the last text position,
|
|
620
|
+
* and movedown() starts from the given cursor.
|
|
621
|
+
* @private
|
|
622
|
+
* @param {Recipe} recipe - The recipe instance.
|
|
623
|
+
* @param {number} x - The text cursor x on the new active page.
|
|
624
|
+
* @param {number} y - The text cursor y on the new active page.
|
|
625
|
+
* @returns {void}
|
|
626
|
+
*/
|
|
627
|
+
function resetTextBox(recipe, x, y) {
|
|
628
|
+
recipe.x = x;
|
|
629
|
+
recipe.y = y;
|
|
630
|
+
recipe.box = undefined;
|
|
631
|
+
recipe._textOptions = undefined;
|
|
632
|
+
recipe._previousTextObjects = [];
|
|
633
|
+
recipe._firstLineHeight = 0;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Map the PageBox names, which setPageBox() also accepts, to the addon's
|
|
638
|
+
* ePDFPageBox constants.
|
|
639
|
+
* @private
|
|
640
|
+
* @param {Object} muhammara - The addon API the Recipe was created for.
|
|
641
|
+
* @returns {Object<string, number>} The page box constants by name.
|
|
642
|
+
*/
|
|
643
|
+
function pageBoxConstants(muhammara) {
|
|
644
|
+
return {
|
|
645
|
+
[muhammara.PageBox.MEDIA]: muhammara.ePDFPageBoxMediaBox,
|
|
646
|
+
[muhammara.PageBox.CROP]: muhammara.ePDFPageBoxCropBox,
|
|
647
|
+
[muhammara.PageBox.BLEED]: muhammara.ePDFPageBoxBleedBox,
|
|
648
|
+
[muhammara.PageBox.TRIM]: muhammara.ePDFPageBoxTrimBox,
|
|
649
|
+
[muhammara.PageBox.ART]: muhammara.ePDFPageBoxArtBox,
|
|
650
|
+
};
|
|
651
|
+
}
|
|
619
652
|
|
|
620
653
|
/**
|
|
621
654
|
* Validate a page rotation. PDF allows only multiples of 90 degrees.
|
|
@@ -677,7 +710,8 @@ exports.rotate = function rotate(rotation) {
|
|
|
677
710
|
* @throws {TypeError} If no page is active.
|
|
678
711
|
*/
|
|
679
712
|
exports.setPageBox = function setPageBox(box, left, bottom, right, top) {
|
|
680
|
-
|
|
713
|
+
const muhammara = this.muhammara;
|
|
714
|
+
box = pageBoxConstants(muhammara)[box] ?? box;
|
|
681
715
|
if ([left, bottom, right, top].some((value) => typeof value === "bigint")) {
|
|
682
716
|
throw new TypeError("setPageBox coordinates must be numbers");
|
|
683
717
|
}
|
|
@@ -720,6 +754,8 @@ exports.endPage = function endPage() {
|
|
|
720
754
|
if (!this.page) {
|
|
721
755
|
return this;
|
|
722
756
|
}
|
|
757
|
+
// A flow still waiting for its end is drawn on the page it started on.
|
|
758
|
+
this._flushTextFlow();
|
|
723
759
|
|
|
724
760
|
if (this.page.endContext) {
|
|
725
761
|
if (this.contextState === PAGE_CONTEXT_STATE.ACTIVE_EDIT)
|
|
@@ -746,6 +782,7 @@ exports.endPage = function endPage() {
|
|
|
746
782
|
* @returns {Recipe} The recipe instance.
|
|
747
783
|
* @throws {Error} If the Recipe was not constructed from an existing PDF.
|
|
748
784
|
* @throws {Error} If the page does not exist in the source PDF.
|
|
785
|
+
* @throws {Error} If another page is still active; call endPage() first.
|
|
749
786
|
*/
|
|
750
787
|
exports.editPage = function editPage(pageNumber) {
|
|
751
788
|
if (this.isNewPDF) {
|
|
@@ -753,9 +790,14 @@ exports.editPage = function editPage(pageNumber) {
|
|
|
753
790
|
"editPage requires a Recipe constructed from an existing PDF",
|
|
754
791
|
);
|
|
755
792
|
}
|
|
793
|
+
// As in createPage, an active page left unfinished crashes the writer or is
|
|
794
|
+
// silently dropped at endPDF().
|
|
795
|
+
if (this.page) {
|
|
796
|
+
throw new Error("Finish the current page before editing another page");
|
|
797
|
+
}
|
|
756
798
|
const pdfWriter = this.writer;
|
|
757
799
|
const pageIndex = pageNumber - 1;
|
|
758
|
-
const pageModifier = new muhammara.PDFPageModifier(
|
|
800
|
+
const pageModifier = new this.muhammara.PDFPageModifier(
|
|
759
801
|
pdfWriter,
|
|
760
802
|
pageIndex,
|
|
761
803
|
true,
|
|
@@ -766,6 +808,7 @@ exports.editPage = function editPage(pageNumber) {
|
|
|
766
808
|
this.editingPage = true;
|
|
767
809
|
this.contextState = PAGE_CONTEXT_STATE.ACTIVE_EDIT;
|
|
768
810
|
this.modifiedSourcePages.add(pageNumber);
|
|
811
|
+
resetTextBox(this, this._margin.left, this._margin.top);
|
|
769
812
|
|
|
770
813
|
this._resumePageRotation(pageNumber);
|
|
771
814
|
|
package/lib/recipe/shapes.js
CHANGED
|
@@ -214,7 +214,7 @@ function _n_gon(sides, cx, cy, radius, options = {}) {
|
|
|
214
214
|
* @param {number} [options.lineWidth] - The line width
|
|
215
215
|
* @param {number} [options.opacity] - The opacity
|
|
216
216
|
* @param {number[]} [options.dash] - The dash style [number, number]
|
|
217
|
-
* @param {number} [options.rotation=0] -
|
|
217
|
+
* @param {number} [options.rotation=0] - Clockwise rotation in degrees, +/- 0 through 360.
|
|
218
218
|
* @param {number[]} [options.rotationOrigin=[cx,cy]] - [originX, originY]
|
|
219
219
|
* @param {number} [options.rotationVertice] - the number of the vertice to be used as rotation origin
|
|
220
220
|
* @param {number} [options.skewX] - the angle skew off the x-axis
|
|
@@ -293,7 +293,7 @@ function _oddStar(ngon) {
|
|
|
293
293
|
* @param {number} [options.lineWidth] - The line width
|
|
294
294
|
* @param {number} [options.opacity] - The opacity
|
|
295
295
|
* @param {number[]} [options.dash] - The dash style [number, number]
|
|
296
|
-
* @param {number} [options.rotation] -
|
|
296
|
+
* @param {number} [options.rotation] - Clockwise rotation in degrees, +/- 0 through 360. Default: 0
|
|
297
297
|
* @param {number[]} [options.rotationOrigin] - [originX, originY] Default: x, y
|
|
298
298
|
* @param {number} [options.skewX] - the angle skew off the x-axis
|
|
299
299
|
* @param {number} [options.skewY] - the angle skew off the y-axis.
|
|
@@ -508,7 +508,7 @@ function flipY(x, ngon) {
|
|
|
508
508
|
* @param {number} [options.lineWidth] - The line width
|
|
509
509
|
* @param {number} [options.opacity] - The opacity
|
|
510
510
|
* @param {number[]} [options.dash] - The dash style [number, number]
|
|
511
|
-
* @param {number} [options.rotation] -
|
|
511
|
+
* @param {number} [options.rotation] - Clockwise rotation in degrees, +/- 0 through 360. Default: 0
|
|
512
512
|
* @param {number[]} [options.rotationOrigin] - [originX, originY] Default: x, y
|
|
513
513
|
* @param {number} [options.skewX] - the angle skew off the x-axis
|
|
514
514
|
* @param {number} [options.skewY] - the angle skew off the y-axis.
|
package/lib/recipe/split.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const muhammara = require("../muhammara");
|
|
2
1
|
const path = require("path");
|
|
3
2
|
const utils = require("./utils");
|
|
4
3
|
|
|
@@ -19,7 +18,7 @@ exports.split = function split(outputDir = "", prefix) {
|
|
|
19
18
|
prefix = prefix || this.filename;
|
|
20
19
|
for (let i = 0; i < this.metadata.pages; i++) {
|
|
21
20
|
const newPdf = path.join(outputDir, `${prefix}-${i + 1}.pdf`);
|
|
22
|
-
const pdfWriter = muhammara.createWriter(newPdf);
|
|
21
|
+
const pdfWriter = this.muhammara.createWriter(newPdf);
|
|
23
22
|
utils.appendPDFPageFromPDFWithAnnotations(pdfWriter, this._getReader(), i);
|
|
24
23
|
pdfWriter.end();
|
|
25
24
|
}
|
package/lib/recipe/table.js
CHANGED
|
@@ -212,6 +212,8 @@ exports.table = function table(x, y, contents, options = {}) {
|
|
|
212
212
|
if (!Array.isArray(contents) || contents.length === 0) {
|
|
213
213
|
return this;
|
|
214
214
|
}
|
|
215
|
+
// An open text flow is drawn before the table starts its own text.
|
|
216
|
+
this._flushTextFlow();
|
|
215
217
|
var columns = tableFields(contents, options).map((field) => {
|
|
216
218
|
var column =
|
|
217
219
|
options.columns &&
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var { cloneOptions, resolveFontSize } = require("./utils");
|
|
1
|
+
var { cloneOptions, resolveFontSize, trimBreakableEnd } = require("./utils");
|
|
2
2
|
var { HorizontalAlign, VerticalAlign } = require("../recipe-constants");
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -70,8 +70,8 @@ const Word = class Word {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
|
-
* Mark the word as the last of its line, trimming
|
|
74
|
-
* measuring it again.
|
|
73
|
+
* Mark the word as the last of its line, trimming the spaces around it
|
|
74
|
+
* but a trailing non-breaking space, and measuring it again when trimmed.
|
|
75
75
|
* @param {boolean} [value=true] - Whether the word is last.
|
|
76
76
|
* @returns {void}
|
|
77
77
|
*/
|
|
@@ -79,7 +79,9 @@ const Word = class Word {
|
|
|
79
79
|
// indicate last word in line (for justification)
|
|
80
80
|
this._last = value;
|
|
81
81
|
if (this._last) {
|
|
82
|
-
|
|
82
|
+
const trimmed = trimBreakableEnd(this._value.trimStart());
|
|
83
|
+
if (trimmed === this._text) return;
|
|
84
|
+
this._value = trimmed;
|
|
83
85
|
this._text = this._value;
|
|
84
86
|
this._dimensions = this._pathOptions.font.calculateTextDimensions(
|
|
85
87
|
this._text,
|