@pdfme/generator
Advanced tools
Comparing version 1.1.10 to 1.2.0
@@ -81,2 +81,43 @@ "use strict"; | ||
}); | ||
describe('basic generator', () => { | ||
const textObject = (x, y) => ({ | ||
type: 'text', position: { x, y }, width: 100, height: 100, fontSize: 13, | ||
}); | ||
const singleSchemaTemplate = { | ||
basePdf: common_1.BLANK_PDF, | ||
schemas: [{ | ||
a: textObject(0, 0), | ||
b: textObject(25, 25), | ||
}], | ||
}; | ||
const multiSchemasTemplate = { | ||
basePdf: "data:application/pdf;base64,JVBERi0xLjcNJeLjz9MNCjYgMCBvYmoNPDwvTGluZWFyaXplZCAxL0wgMTg0NC9PIDgvRSAxMTEwL04gMi9UIDE1NzAvSCBbIDQyMyAxMzFdPj4NZW5kb2JqDSAgICAgICAgICAgICAgICAgICAgICAgDQoxMSAwIG9iag08PC9EZWNvZGVQYXJtczw8L0NvbHVtbnMgMy9QcmVkaWN0b3IgMTI+Pi9GaWx0ZXIvRmxhdGVEZWNvZGUvSURbPEJBMTk5MUY0MThCN0IyMTEwQTAwNjc0NThCNkJDNjIzPjxGOEE4OEZEMzMzNjQ2OTQ2QkE1ODMzM0M4MEFEMDFFNj5dL0luZGV4WzYgN10vTGVuZ3RoIDM2L1ByZXYgMTU3MS9Sb290IDcgMCBSL1NpemUgMTMvVHlwZS9YUmVmL1dbMSAyIDBdPj5zdHJlYW0NCmjeYmJkEGBiYJJiYmDQZWJgvA+k45gY/j4Aso0BAgwAISQDuA0KZW5kc3RyZWFtDWVuZG9iag1zdGFydHhyZWYNCjANCiUlRU9GDQogICAgICAgIA0KMTIgMCBvYmoNPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCA1Ny9TIDQ0Pj5zdHJlYW0NCmjeYmBgYGJgYLzCwAgkbRk4GBCAAyjGxMDCwNFwiOGAQvkhJCkGZihmYIhj4GhkSGEACDAAvy4F4g0KZW5kc3RyZWFtDWVuZG9iag03IDAgb2JqDTw8L1BhZ2VzIDUgMCBSL1R5cGUvQ2F0YWxvZz4+DWVuZG9iag04IDAgb2JqDTw8L0Fubm90c1tdL0JsZWVkQm94WzAgMCA1OTUuNDQgODQxLjkyXS9Db250ZW50cyA5IDAgUi9Dcm9wQm94WzAgMCA1OTUuNDQgODQxLjkyXS9NZWRpYUJveFswIDAgNTk1LjQ0IDg0MS45Ml0vUGFyZW50IDUgMCBSL1Jlc291cmNlczw8L1hPYmplY3Q8PC9GbTAgMTAgMCBSPj4+Pi9Sb3RhdGUgMC9UcmltQm94WzAgMCA1OTUuNDQgODQxLjkyXS9UeXBlL1BhZ2U+Pg1lbmRvYmoNOSAwIG9iag08PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDI2Pj5zdHJlYW0NCkiJKlQwUAjx0XfLNVBwyVcIVAAIMAAiagP4DQplbmRzdHJlYW0NZW5kb2JqDTEwIDAgb2JqDTw8L0JCb3hbMzI3NjguMCAzMjc2OC4wIC0zMjc2OC4wIC0zMjc2OC4wXS9GaWx0ZXIvRmxhdGVEZWNvZGUvRm9ybVR5cGUgMS9MZW5ndGggMTQvTWF0cml4WzEgMCAwIDEgMCAwXS9SZXNvdXJjZXM8PD4+L1N1YnR5cGUvRm9ybS9UeXBlL1hPYmplY3Q+PnN0cmVhbQ0KSIkq5ArkAggwAAKSANcNCmVuZHN0cmVhbQ1lbmRvYmoNMSAwIG9iag08PC9Bbm5vdHNbXS9CbGVlZEJveFswIDAgNTk1LjQ0IDg0MS45Ml0vQ29udGVudHMgMiAwIFIvQ3JvcEJveFswIDAgNTk1LjQ0IDg0MS45Ml0vTWVkaWFCb3hbMCAwIDU5NS40NCA4NDEuOTJdL1BhcmVudCA1IDAgUi9SZXNvdXJjZXM8PC9YT2JqZWN0PDwvRm0wIDEwIDAgUj4+Pj4vUm90YXRlIDAvVHJpbUJveFswIDAgNTk1LjQ0IDg0MS45Ml0vVHlwZS9QYWdlPj4NZW5kb2JqDTIgMCBvYmoNPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCAyNj4+c3RyZWFtDQpIiSpUMFAI8dF3yzVQcMlXCFQACDAAImoD+A0KZW5kc3RyZWFtDWVuZG9iag0zIDAgb2JqDTw8L0ZpbHRlci9GbGF0ZURlY29kZS9GaXJzdCA0L0xlbmd0aCA1Mi9OIDEvVHlwZS9PYmpTdG0+PnN0cmVhbQ0KaN4yVTBQsLHRd84vzStRMNL3zkwpjrYAigUpGILIWP2QyoJU/YDE9NRiOzuAAAMAETgMkw0KZW5kc3RyZWFtDWVuZG9iag00IDAgb2JqDTw8L0RlY29kZVBhcm1zPDwvQ29sdW1ucyAzL1ByZWRpY3RvciAxMj4+L0ZpbHRlci9GbGF0ZURlY29kZS9JRFs8QkExOTkxRjQxOEI3QjIxMTBBMDA2NzQ1OEI2QkM2MjM+PEY4QTg4RkQzMzM2NDY5NDZCQTU4MzMzQzgwQUQwMUU2Pl0vTGVuZ3RoIDMzL1Jvb3QgNyAwIFIvU2l6ZSA2L1R5cGUvWFJlZi9XWzEgMiAwXT4+c3RyZWFtDQpo3mJiYGBgYmQJY2JgvM/EwBAHpCcwMf56ABBgABstBBINCmVuZHN0cmVhbQ1lbmRvYmoNc3RhcnR4cmVmDQoxMTYNCiUlRU9GDQo=", | ||
schemas: [ | ||
{ a: textObject(0, 0) }, | ||
{ b: textObject(25, 25) }, | ||
], | ||
}; | ||
const singleInputs = [{ a: 'a', b: "b" }]; | ||
const multiInputs = [{ a: 'a-1', b: "b-1" }, { a: 'a-2', b: "b-2" }]; | ||
const testCases = [ | ||
{ template: singleSchemaTemplate, inputs: singleInputs, testName: 'singleSchemaTemplate with singleInputs' }, | ||
{ template: singleSchemaTemplate, inputs: multiInputs, testName: 'singleSchemaTemplate with multiInputs' }, | ||
{ template: multiSchemasTemplate, inputs: singleInputs, testName: 'multiSchemasTemplate with singleInputs' }, | ||
{ template: multiSchemasTemplate, inputs: multiInputs, testName: 'multiSchemasTemplate with multiInputs' }, | ||
]; | ||
testCases.forEach(({ template, inputs, testName }) => { | ||
test(testName, () => __awaiter(void 0, void 0, void 0, function* () { | ||
const pdf = yield (0, generate_1.default)({ inputs, template }); | ||
const tmpFile = getPdfTmpPath(`${testName}.pdf`); | ||
const assertFile = getPdfAssertPath(`${testName}.pdf`); | ||
(0, fs_1.writeFileSync)(tmpFile, pdf); | ||
const [actualPdf, expectedPdf] = yield Promise.all([ | ||
getPdf(tmpFile), | ||
getPdf(assertFile), | ||
]); | ||
// @ts-ignore | ||
expect(actualPdf.Pages).toEqual(expectedPdf.Pages); | ||
})); | ||
}); | ||
}); | ||
// TODO Slow test... need speed up, use Promise.all? | ||
@@ -99,6 +140,3 @@ describe('use labelmake.jp template', () => { | ||
template, | ||
options: { | ||
font, | ||
splitThreshold: 0, | ||
}, | ||
options: { font }, | ||
}); | ||
@@ -116,5 +154,5 @@ const hrend = process.hrtime(hrstart); | ||
}); | ||
describe('use nofont template', () => { | ||
describe('use fontColor template', () => { | ||
test(`sample`, () => __awaiter(void 0, void 0, void 0, function* () { | ||
const inputs = [{ a: 'here is Helvetica' }]; | ||
const inputs = [{ name: 'here is purple color' }]; | ||
const template = { | ||
@@ -124,7 +162,8 @@ basePdf: common_1.BLANK_PDF, | ||
{ | ||
a: { | ||
name: { | ||
type: 'text', | ||
position: { x: 0, y: 0 }, | ||
position: { x: 30, y: 30 }, | ||
width: 100, | ||
height: 100, | ||
height: 20, | ||
fontColor: '#7d2ae8', | ||
}, | ||
@@ -135,4 +174,4 @@ }, | ||
const pdf = yield (0, generate_1.default)({ inputs, template }); | ||
const tmpFile = getPdfTmpPath(`nofont.pdf`); | ||
const assertFile = getPdfAssertPath(`nofont.pdf`); | ||
const tmpFile = getPdfTmpPath(`fontColor.pdf`); | ||
const assertFile = getPdfAssertPath(`fontColor.pdf`); | ||
(0, fs_1.writeFileSync)(tmpFile, pdf); | ||
@@ -143,78 +182,52 @@ const res = yield Promise.all([getPdf(tmpFile), getPdf(assertFile)]); | ||
})); | ||
describe('use fontColor template', () => { | ||
test(`sample`, () => __awaiter(void 0, void 0, void 0, function* () { | ||
const inputs = [{ name: 'here is purple color' }]; | ||
const template = { | ||
basePdf: common_1.BLANK_PDF, | ||
schemas: [ | ||
{ | ||
name: { | ||
type: 'text', | ||
position: { x: 30, y: 30 }, | ||
width: 100, | ||
height: 20, | ||
fontColor: '#7d2ae8', | ||
}, | ||
}); | ||
describe('use fontSubset template', () => { | ||
test(`sample`, () => __awaiter(void 0, void 0, void 0, function* () { | ||
const inputs = [{ field1: 'SauceHanSansJP', field2: 'SauceHanSerifJP' }]; | ||
const template = { | ||
basePdf: common_1.BLANK_PDF, | ||
schemas: [ | ||
{ | ||
field1: { | ||
type: 'text', | ||
position: { x: 30, y: 30 }, | ||
width: 100, | ||
height: 20, | ||
fontName: 'SauceHanSansJP', | ||
}, | ||
], | ||
}; | ||
const pdf = yield (0, generate_1.default)({ inputs, template }); | ||
const tmpFile = getPdfTmpPath(`fontColor.pdf`); | ||
const assertFile = getPdfAssertPath(`fontColor.pdf`); | ||
(0, fs_1.writeFileSync)(tmpFile, pdf); | ||
const res = yield Promise.all([getPdf(tmpFile), getPdf(assertFile)]); | ||
const [a, e] = res; | ||
expect(a.Pages).toEqual(e.Pages); | ||
})); | ||
}); | ||
describe('use fontSubset template', () => { | ||
test(`sample`, () => __awaiter(void 0, void 0, void 0, function* () { | ||
const inputs = [{ field1: 'SauceHanSansJP', field2: 'SauceHanSerifJP' }]; | ||
const template = { | ||
basePdf: common_1.BLANK_PDF, | ||
schemas: [ | ||
{ | ||
field1: { | ||
type: 'text', | ||
position: { x: 30, y: 30 }, | ||
width: 100, | ||
height: 20, | ||
fontName: 'SauceHanSansJP', | ||
}, | ||
field2: { | ||
type: 'text', | ||
position: { x: 60, y: 60 }, | ||
width: 100, | ||
height: 20, | ||
fontName: 'SauceHanSerifJP', | ||
}, | ||
field2: { | ||
type: 'text', | ||
position: { x: 60, y: 60 }, | ||
width: 100, | ||
height: 20, | ||
fontName: 'SauceHanSerifJP', | ||
}, | ||
], | ||
}; | ||
jest.setTimeout(30000); | ||
const pdf = yield (0, generate_1.default)({ | ||
inputs, | ||
template, | ||
options: { | ||
font: { | ||
SauceHanSansJP: { | ||
data: SauceHanSansJPData, | ||
fallback: true, | ||
subset: false, | ||
}, | ||
SauceHanSerifJP: { | ||
data: SauceHanSerifJPData, | ||
subset: false, | ||
}, | ||
}, | ||
], | ||
}; | ||
jest.setTimeout(30000); | ||
const pdf = yield (0, generate_1.default)({ | ||
inputs, | ||
template, | ||
options: { | ||
font: { | ||
SauceHanSansJP: { | ||
data: SauceHanSansJPData, | ||
fallback: true, | ||
subset: false, | ||
}, | ||
SauceHanSerifJP: { | ||
data: SauceHanSerifJPData, | ||
subset: false, | ||
}, | ||
}, | ||
}); | ||
const tmpFile = getPdfTmpPath(`fontSubset.pdf`); | ||
const assertFile = getPdfAssertPath(`fontSubset.pdf`); | ||
(0, fs_1.writeFileSync)(tmpFile, pdf); | ||
const res = yield Promise.all([getPdf(tmpFile), getPdf(assertFile)]); | ||
const [a, e] = res; | ||
expect(a.Pages).toEqual(e.Pages); | ||
}), 10000); | ||
}); | ||
}, | ||
}); | ||
const tmpFile = getPdfTmpPath(`fontSubset.pdf`); | ||
const assertFile = getPdfAssertPath(`fontSubset.pdf`); | ||
(0, fs_1.writeFileSync)(tmpFile, pdf); | ||
const res = yield Promise.all([getPdf(tmpFile), getPdf(assertFile)]); | ||
const [a, e] = res; | ||
expect(a.Pages).toEqual(e.Pages); | ||
}), 10000); | ||
}); | ||
@@ -221,0 +234,0 @@ }); |
@@ -43,9 +43,9 @@ "use strict"; | ||
const { basePdf } = template; | ||
const fallbackFontName = (0, common_1.getFallbackFontName)(font); | ||
const pdfDoc = yield pdf_lib_1.PDFDocument.create(); | ||
pdfDoc.registerFontkit(fontkit); | ||
const fallbackFontName = (0, common_1.getFallbackFontName)(font); | ||
const fontObj = yield (0, helper_js_1.embedAndGetFontObj)({ pdfDoc, font }); | ||
const pdfFontObj = yield (0, helper_js_1.embedAndGetFontObj)({ pdfDoc, font }); | ||
const pagesAndBoxes = yield (0, helper_js_1.getEmbeddedPagesAndEmbedPdfBoxes)({ pdfDoc, basePdf }); | ||
const { embeddedPages, embedPdfBoxes } = pagesAndBoxes; | ||
return { pdfDoc, fontObj, fallbackFontName, embeddedPages, embedPdfBoxes }; | ||
return { pdfDoc, pdfFontObj, fallbackFontName, embeddedPages, embedPdfBoxes }; | ||
}); | ||
@@ -59,6 +59,6 @@ const postProcessing = (pdfDoc) => { | ||
const { inputs, template, options = {} } = props; | ||
const { font = (0, common_1.getDefaultFont)(), splitThreshold = 3 } = options; | ||
const { font = (0, common_1.getDefaultFont)() } = options; | ||
const { schemas } = template; | ||
const preRes = yield preprocessing({ inputs, template, font }); | ||
const { pdfDoc, fontObj, fallbackFontName, embeddedPages, embedPdfBoxes } = preRes; | ||
const { pdfDoc, pdfFontObj, fallbackFontName, embeddedPages, embedPdfBoxes } = preRes; | ||
const inputImageCache = {}; | ||
@@ -79,4 +79,3 @@ for (let i = 0; i < inputs.length; i += 1) { | ||
const input = inputObj[key]; | ||
const textSchemaSetting = { fontObj, fallbackFontName, splitThreshold }; | ||
// eslint-disable-next-line no-await-in-loop | ||
const fontSetting = { font, pdfFontObj, fallbackFontName }; | ||
yield (0, helper_js_1.drawInputByTemplateSchema)({ | ||
@@ -88,3 +87,3 @@ input, | ||
pageHeight, | ||
textSchemaSetting, | ||
fontSetting, | ||
inputImageCache, | ||
@@ -91,0 +90,0 @@ }); |
@@ -109,5 +109,5 @@ "use strict"; | ||
}; | ||
const getFontProp = (schema) => { | ||
const getFontProp = ({ input, font, schema }) => __awaiter(void 0, void 0, void 0, function* () { | ||
var _a, _b, _c, _d, _e; | ||
const size = (_a = schema.fontSize) !== null && _a !== void 0 ? _a : common_1.DEFAULT_FONT_SIZE; | ||
const size = schema.dynamicFontSize ? yield (0, common_1.calculateDynamicFontSize)({ textSchema: schema, font, input }) : (_a = schema.fontSize) !== null && _a !== void 0 ? _a : common_1.DEFAULT_FONT_SIZE; | ||
const color = hex2RgbColor((_b = schema.fontColor) !== null && _b !== void 0 ? _b : common_1.DEFAULT_FONT_COLOR); | ||
@@ -118,3 +118,3 @@ const alignment = (_c = schema.alignment) !== null && _c !== void 0 ? _c : common_1.DEFAULT_ALIGNMENT; | ||
return { size, color, alignment, lineHeight, characterSpacing }; | ||
}; | ||
}); | ||
const calcX = (x, alignment, boxWidth, textWidth) => { | ||
@@ -146,10 +146,9 @@ let addition = 0; | ||
/** | ||
* Incrementally check the current line for it's real length | ||
* and return the position where it exceeds the box width. | ||
* | ||
* return `null` to indicate if inputLine is shorter as the available bbox | ||
* Incrementally checks the current line for its real length | ||
* and returns the position where it exceeds the box width. | ||
* Returns `null` to indicate if inputLine is shorter as the available bbox. | ||
*/ | ||
const getOverPosition = (inputLine, isOverEval) => { | ||
for (let i = 0; i <= inputLine.length; i += 1) { | ||
if (isOverEval(inputLine.substr(0, i))) { | ||
for (let i = 0; i <= inputLine.length; i++) { | ||
if (isOverEval(inputLine.slice(0, i))) { | ||
return i; | ||
@@ -161,3 +160,3 @@ } | ||
/** | ||
* Get position of the split. Split the exceeding line at | ||
* Gets the position of the split. Splits the exceeding line at | ||
* the last whitespace over it exceeds the bounding box width. | ||
@@ -167,18 +166,13 @@ */ | ||
const overPos = getOverPosition(inputLine, isOverEval); | ||
/** | ||
* if input line is shorter as the available space. We split at the end of the line | ||
*/ | ||
if (overPos === null) | ||
return inputLine.length; | ||
return inputLine.length; // input line is shorter than the available space | ||
let overPosTmp = overPos; | ||
while (inputLine[overPosTmp] !== ' ' && overPosTmp >= 0) | ||
overPosTmp -= 1; | ||
/** | ||
* for very long lines with no whitespace use the original overPos and | ||
* split one char over so we do not overfill the box | ||
*/ | ||
while (inputLine[overPosTmp] !== ' ' && overPosTmp >= 0) { | ||
overPosTmp--; | ||
} | ||
// For very long lines with no whitespace use the original overPos | ||
return overPosTmp > 0 ? overPosTmp : overPos - 1; | ||
}; | ||
/** | ||
* recursively split the line at getSplitPosition. | ||
* Recursively splits the line at getSplitPosition. | ||
* If there is some leftover, split the rest again in the same manner. | ||
@@ -188,9 +182,5 @@ */ | ||
const splitPos = getSplitPosition(inputLine, isOverEval); | ||
const splittedLine = inputLine.substr(0, splitPos); | ||
const rest = inputLine.slice(splitPos).trimLeft(); | ||
/** | ||
* end recursion if there is no rest, return single splitted line in an array | ||
* so we can join them over the recursion | ||
*/ | ||
if (rest.length === 0) { | ||
const splittedLine = inputLine.substring(0, splitPos); | ||
const rest = inputLine.substring(splitPos).trimStart(); | ||
if (rest.length === 0) { // end recursion if there is no rest | ||
return [splittedLine]; | ||
@@ -200,9 +190,9 @@ } | ||
}; | ||
const drawInputByTextSchema = (arg) => { | ||
const { input, templateSchema, page, pageHeight, textSchemaSetting } = arg; | ||
const { fontObj, fallbackFontName, splitThreshold } = textSchemaSetting; | ||
const fontValue = fontObj[templateSchema.fontName ? templateSchema.fontName : fallbackFontName]; | ||
const drawInputByTextSchema = (arg) => __awaiter(void 0, void 0, void 0, function* () { | ||
const { input, templateSchema, page, pageHeight, fontSetting } = arg; | ||
const { font, pdfFontObj, fallbackFontName } = fontSetting; | ||
const pdfFontValue = pdfFontObj[templateSchema.fontName ? templateSchema.fontName : fallbackFontName]; | ||
drawBackgroundColor({ templateSchema, page, pageHeight }); | ||
const { width, rotate } = getSchemaSizeAndRotate(templateSchema); | ||
const { size, color, alignment, lineHeight, characterSpacing } = getFontProp(templateSchema); | ||
const { size, color, alignment, lineHeight, characterSpacing } = yield getFontProp({ input, font, schema: templateSchema }); | ||
page.pushOperators((0, pdf_lib_1.setCharacterSpacing)(characterSpacing)); | ||
@@ -212,12 +202,8 @@ let beforeLineOver = 0; | ||
const isOverEval = (testString) => { | ||
const testStringWidth = fontValue.widthOfTextAtSize(testString, size) + (testString.length - 1) * characterSpacing; | ||
/** | ||
* split if the difference is less then two pixel | ||
* (found out / tested this threshold heuristically, most probably widthOfTextAtSize is unprecise) | ||
**/ | ||
return width - testStringWidth <= splitThreshold; | ||
const testStringWidth = pdfFontValue.widthOfTextAtSize(testString, size) + (testString.length - 1) * characterSpacing; | ||
return width <= testStringWidth; | ||
}; | ||
const splitedLines = getSplittedLines(inputLine, isOverEval); | ||
const drawLine = (splitedLine, splitedLineIndex) => { | ||
const textWidth = fontValue.widthOfTextAtSize(splitedLine, size) + | ||
const textWidth = pdfFontValue.widthOfTextAtSize(splitedLine, size) + | ||
(splitedLine.length - 1) * characterSpacing; | ||
@@ -234,3 +220,3 @@ page.drawText(splitedLine, { | ||
maxWidth: width, | ||
font: fontValue, | ||
font: pdfFontValue, | ||
wordBreaks: [''], | ||
@@ -243,3 +229,3 @@ }); | ||
}); | ||
}; | ||
}); | ||
const getCacheKey = (templateSchema, input) => `${templateSchema.type}${input}`; | ||
@@ -291,3 +277,3 @@ const drawInputByImageSchema = (arg) => __awaiter(void 0, void 0, void 0, function* () { | ||
const templateSchema = arg.templateSchema; | ||
drawInputByTextSchema(Object.assign(Object.assign({}, arg), { templateSchema })); | ||
yield drawInputByTextSchema(Object.assign(Object.assign({}, arg), { templateSchema })); | ||
} | ||
@@ -294,0 +280,0 @@ else if ((0, common_1.isImageSchema)(arg.templateSchema)) { |
@@ -6,3 +6,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.validateBarcodeInput = exports.checkGenerateProps = exports.checkDesignerProps = exports.checkPreviewProps = exports.checkUIProps = exports.checkTemplate = exports.isBarcodeSchema = exports.isImageSchema = exports.isTextSchema = exports.HELVETICA = exports.BLANK_PDF = exports.generate = void 0; | ||
exports.validateBarcodeInput = exports.checkGenerateProps = exports.checkDesignerProps = exports.checkPreviewProps = exports.checkUIProps = exports.checkTemplate = exports.isBarcodeSchema = exports.isImageSchema = exports.isTextSchema = exports.DEFAULT_FONT_VALUE = exports.BLANK_PDF = exports.generate = void 0; | ||
const generate_js_1 = __importDefault(require("./generate.js")); | ||
@@ -12,3 +12,3 @@ exports.generate = generate_js_1.default; | ||
Object.defineProperty(exports, "BLANK_PDF", { enumerable: true, get: function () { return common_1.BLANK_PDF; } }); | ||
Object.defineProperty(exports, "HELVETICA", { enumerable: true, get: function () { return common_1.HELVETICA; } }); | ||
Object.defineProperty(exports, "DEFAULT_FONT_VALUE", { enumerable: true, get: function () { return common_1.DEFAULT_FONT_VALUE; } }); | ||
Object.defineProperty(exports, "isTextSchema", { enumerable: true, get: function () { return common_1.isTextSchema; } }); | ||
@@ -15,0 +15,0 @@ Object.defineProperty(exports, "isImageSchema", { enumerable: true, get: function () { return common_1.isImageSchema; } }); |
@@ -53,2 +53,43 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
}); | ||
describe('basic generator', () => { | ||
const textObject = (x, y) => ({ | ||
type: 'text', position: { x, y }, width: 100, height: 100, fontSize: 13, | ||
}); | ||
const singleSchemaTemplate = { | ||
basePdf: BLANK_PDF, | ||
schemas: [{ | ||
a: textObject(0, 0), | ||
b: textObject(25, 25), | ||
}], | ||
}; | ||
const multiSchemasTemplate = { | ||
basePdf: "data:application/pdf;base64,JVBERi0xLjcNJeLjz9MNCjYgMCBvYmoNPDwvTGluZWFyaXplZCAxL0wgMTg0NC9PIDgvRSAxMTEwL04gMi9UIDE1NzAvSCBbIDQyMyAxMzFdPj4NZW5kb2JqDSAgICAgICAgICAgICAgICAgICAgICAgDQoxMSAwIG9iag08PC9EZWNvZGVQYXJtczw8L0NvbHVtbnMgMy9QcmVkaWN0b3IgMTI+Pi9GaWx0ZXIvRmxhdGVEZWNvZGUvSURbPEJBMTk5MUY0MThCN0IyMTEwQTAwNjc0NThCNkJDNjIzPjxGOEE4OEZEMzMzNjQ2OTQ2QkE1ODMzM0M4MEFEMDFFNj5dL0luZGV4WzYgN10vTGVuZ3RoIDM2L1ByZXYgMTU3MS9Sb290IDcgMCBSL1NpemUgMTMvVHlwZS9YUmVmL1dbMSAyIDBdPj5zdHJlYW0NCmjeYmJkEGBiYJJiYmDQZWJgvA+k45gY/j4Aso0BAgwAISQDuA0KZW5kc3RyZWFtDWVuZG9iag1zdGFydHhyZWYNCjANCiUlRU9GDQogICAgICAgIA0KMTIgMCBvYmoNPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCA1Ny9TIDQ0Pj5zdHJlYW0NCmjeYmBgYGJgYLzCwAgkbRk4GBCAAyjGxMDCwNFwiOGAQvkhJCkGZihmYIhj4GhkSGEACDAAvy4F4g0KZW5kc3RyZWFtDWVuZG9iag03IDAgb2JqDTw8L1BhZ2VzIDUgMCBSL1R5cGUvQ2F0YWxvZz4+DWVuZG9iag04IDAgb2JqDTw8L0Fubm90c1tdL0JsZWVkQm94WzAgMCA1OTUuNDQgODQxLjkyXS9Db250ZW50cyA5IDAgUi9Dcm9wQm94WzAgMCA1OTUuNDQgODQxLjkyXS9NZWRpYUJveFswIDAgNTk1LjQ0IDg0MS45Ml0vUGFyZW50IDUgMCBSL1Jlc291cmNlczw8L1hPYmplY3Q8PC9GbTAgMTAgMCBSPj4+Pi9Sb3RhdGUgMC9UcmltQm94WzAgMCA1OTUuNDQgODQxLjkyXS9UeXBlL1BhZ2U+Pg1lbmRvYmoNOSAwIG9iag08PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDI2Pj5zdHJlYW0NCkiJKlQwUAjx0XfLNVBwyVcIVAAIMAAiagP4DQplbmRzdHJlYW0NZW5kb2JqDTEwIDAgb2JqDTw8L0JCb3hbMzI3NjguMCAzMjc2OC4wIC0zMjc2OC4wIC0zMjc2OC4wXS9GaWx0ZXIvRmxhdGVEZWNvZGUvRm9ybVR5cGUgMS9MZW5ndGggMTQvTWF0cml4WzEgMCAwIDEgMCAwXS9SZXNvdXJjZXM8PD4+L1N1YnR5cGUvRm9ybS9UeXBlL1hPYmplY3Q+PnN0cmVhbQ0KSIkq5ArkAggwAAKSANcNCmVuZHN0cmVhbQ1lbmRvYmoNMSAwIG9iag08PC9Bbm5vdHNbXS9CbGVlZEJveFswIDAgNTk1LjQ0IDg0MS45Ml0vQ29udGVudHMgMiAwIFIvQ3JvcEJveFswIDAgNTk1LjQ0IDg0MS45Ml0vTWVkaWFCb3hbMCAwIDU5NS40NCA4NDEuOTJdL1BhcmVudCA1IDAgUi9SZXNvdXJjZXM8PC9YT2JqZWN0PDwvRm0wIDEwIDAgUj4+Pj4vUm90YXRlIDAvVHJpbUJveFswIDAgNTk1LjQ0IDg0MS45Ml0vVHlwZS9QYWdlPj4NZW5kb2JqDTIgMCBvYmoNPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCAyNj4+c3RyZWFtDQpIiSpUMFAI8dF3yzVQcMlXCFQACDAAImoD+A0KZW5kc3RyZWFtDWVuZG9iag0zIDAgb2JqDTw8L0ZpbHRlci9GbGF0ZURlY29kZS9GaXJzdCA0L0xlbmd0aCA1Mi9OIDEvVHlwZS9PYmpTdG0+PnN0cmVhbQ0KaN4yVTBQsLHRd84vzStRMNL3zkwpjrYAigUpGILIWP2QyoJU/YDE9NRiOzuAAAMAETgMkw0KZW5kc3RyZWFtDWVuZG9iag00IDAgb2JqDTw8L0RlY29kZVBhcm1zPDwvQ29sdW1ucyAzL1ByZWRpY3RvciAxMj4+L0ZpbHRlci9GbGF0ZURlY29kZS9JRFs8QkExOTkxRjQxOEI3QjIxMTBBMDA2NzQ1OEI2QkM2MjM+PEY4QTg4RkQzMzM2NDY5NDZCQTU4MzMzQzgwQUQwMUU2Pl0vTGVuZ3RoIDMzL1Jvb3QgNyAwIFIvU2l6ZSA2L1R5cGUvWFJlZi9XWzEgMiAwXT4+c3RyZWFtDQpo3mJiYGBgYmQJY2JgvM/EwBAHpCcwMf56ABBgABstBBINCmVuZHN0cmVhbQ1lbmRvYmoNc3RhcnR4cmVmDQoxMTYNCiUlRU9GDQo=", | ||
schemas: [ | ||
{ a: textObject(0, 0) }, | ||
{ b: textObject(25, 25) }, | ||
], | ||
}; | ||
const singleInputs = [{ a: 'a', b: "b" }]; | ||
const multiInputs = [{ a: 'a-1', b: "b-1" }, { a: 'a-2', b: "b-2" }]; | ||
const testCases = [ | ||
{ template: singleSchemaTemplate, inputs: singleInputs, testName: 'singleSchemaTemplate with singleInputs' }, | ||
{ template: singleSchemaTemplate, inputs: multiInputs, testName: 'singleSchemaTemplate with multiInputs' }, | ||
{ template: multiSchemasTemplate, inputs: singleInputs, testName: 'multiSchemasTemplate with singleInputs' }, | ||
{ template: multiSchemasTemplate, inputs: multiInputs, testName: 'multiSchemasTemplate with multiInputs' }, | ||
]; | ||
testCases.forEach(({ template, inputs, testName }) => { | ||
test(testName, () => __awaiter(void 0, void 0, void 0, function* () { | ||
const pdf = yield generate({ inputs, template }); | ||
const tmpFile = getPdfTmpPath(`${testName}.pdf`); | ||
const assertFile = getPdfAssertPath(`${testName}.pdf`); | ||
writeFileSync(tmpFile, pdf); | ||
const [actualPdf, expectedPdf] = yield Promise.all([ | ||
getPdf(tmpFile), | ||
getPdf(assertFile), | ||
]); | ||
// @ts-ignore | ||
expect(actualPdf.Pages).toEqual(expectedPdf.Pages); | ||
})); | ||
}); | ||
}); | ||
// TODO Slow test... need speed up, use Promise.all? | ||
@@ -71,6 +112,3 @@ describe('use labelmake.jp template', () => { | ||
template, | ||
options: { | ||
font, | ||
splitThreshold: 0, | ||
}, | ||
options: { font }, | ||
}); | ||
@@ -88,5 +126,5 @@ const hrend = process.hrtime(hrstart); | ||
}); | ||
describe('use nofont template', () => { | ||
describe('use fontColor template', () => { | ||
test(`sample`, () => __awaiter(void 0, void 0, void 0, function* () { | ||
const inputs = [{ a: 'here is Helvetica' }]; | ||
const inputs = [{ name: 'here is purple color' }]; | ||
const template = { | ||
@@ -96,7 +134,8 @@ basePdf: BLANK_PDF, | ||
{ | ||
a: { | ||
name: { | ||
type: 'text', | ||
position: { x: 0, y: 0 }, | ||
position: { x: 30, y: 30 }, | ||
width: 100, | ||
height: 100, | ||
height: 20, | ||
fontColor: '#7d2ae8', | ||
}, | ||
@@ -107,4 +146,4 @@ }, | ||
const pdf = yield generate({ inputs, template }); | ||
const tmpFile = getPdfTmpPath(`nofont.pdf`); | ||
const assertFile = getPdfAssertPath(`nofont.pdf`); | ||
const tmpFile = getPdfTmpPath(`fontColor.pdf`); | ||
const assertFile = getPdfAssertPath(`fontColor.pdf`); | ||
writeFileSync(tmpFile, pdf); | ||
@@ -115,78 +154,52 @@ const res = yield Promise.all([getPdf(tmpFile), getPdf(assertFile)]); | ||
})); | ||
describe('use fontColor template', () => { | ||
test(`sample`, () => __awaiter(void 0, void 0, void 0, function* () { | ||
const inputs = [{ name: 'here is purple color' }]; | ||
const template = { | ||
basePdf: BLANK_PDF, | ||
schemas: [ | ||
{ | ||
name: { | ||
type: 'text', | ||
position: { x: 30, y: 30 }, | ||
width: 100, | ||
height: 20, | ||
fontColor: '#7d2ae8', | ||
}, | ||
}); | ||
describe('use fontSubset template', () => { | ||
test(`sample`, () => __awaiter(void 0, void 0, void 0, function* () { | ||
const inputs = [{ field1: 'SauceHanSansJP', field2: 'SauceHanSerifJP' }]; | ||
const template = { | ||
basePdf: BLANK_PDF, | ||
schemas: [ | ||
{ | ||
field1: { | ||
type: 'text', | ||
position: { x: 30, y: 30 }, | ||
width: 100, | ||
height: 20, | ||
fontName: 'SauceHanSansJP', | ||
}, | ||
], | ||
}; | ||
const pdf = yield generate({ inputs, template }); | ||
const tmpFile = getPdfTmpPath(`fontColor.pdf`); | ||
const assertFile = getPdfAssertPath(`fontColor.pdf`); | ||
writeFileSync(tmpFile, pdf); | ||
const res = yield Promise.all([getPdf(tmpFile), getPdf(assertFile)]); | ||
const [a, e] = res; | ||
expect(a.Pages).toEqual(e.Pages); | ||
})); | ||
}); | ||
describe('use fontSubset template', () => { | ||
test(`sample`, () => __awaiter(void 0, void 0, void 0, function* () { | ||
const inputs = [{ field1: 'SauceHanSansJP', field2: 'SauceHanSerifJP' }]; | ||
const template = { | ||
basePdf: BLANK_PDF, | ||
schemas: [ | ||
{ | ||
field1: { | ||
type: 'text', | ||
position: { x: 30, y: 30 }, | ||
width: 100, | ||
height: 20, | ||
fontName: 'SauceHanSansJP', | ||
}, | ||
field2: { | ||
type: 'text', | ||
position: { x: 60, y: 60 }, | ||
width: 100, | ||
height: 20, | ||
fontName: 'SauceHanSerifJP', | ||
}, | ||
field2: { | ||
type: 'text', | ||
position: { x: 60, y: 60 }, | ||
width: 100, | ||
height: 20, | ||
fontName: 'SauceHanSerifJP', | ||
}, | ||
], | ||
}; | ||
jest.setTimeout(30000); | ||
const pdf = yield generate({ | ||
inputs, | ||
template, | ||
options: { | ||
font: { | ||
SauceHanSansJP: { | ||
data: SauceHanSansJPData, | ||
fallback: true, | ||
subset: false, | ||
}, | ||
SauceHanSerifJP: { | ||
data: SauceHanSerifJPData, | ||
subset: false, | ||
}, | ||
}, | ||
], | ||
}; | ||
jest.setTimeout(30000); | ||
const pdf = yield generate({ | ||
inputs, | ||
template, | ||
options: { | ||
font: { | ||
SauceHanSansJP: { | ||
data: SauceHanSansJPData, | ||
fallback: true, | ||
subset: false, | ||
}, | ||
SauceHanSerifJP: { | ||
data: SauceHanSerifJPData, | ||
subset: false, | ||
}, | ||
}, | ||
}); | ||
const tmpFile = getPdfTmpPath(`fontSubset.pdf`); | ||
const assertFile = getPdfAssertPath(`fontSubset.pdf`); | ||
writeFileSync(tmpFile, pdf); | ||
const res = yield Promise.all([getPdf(tmpFile), getPdf(assertFile)]); | ||
const [a, e] = res; | ||
expect(a.Pages).toEqual(e.Pages); | ||
}), 10000); | ||
}); | ||
}, | ||
}); | ||
const tmpFile = getPdfTmpPath(`fontSubset.pdf`); | ||
const assertFile = getPdfAssertPath(`fontSubset.pdf`); | ||
writeFileSync(tmpFile, pdf); | ||
const res = yield Promise.all([getPdf(tmpFile), getPdf(assertFile)]); | ||
const [a, e] = res; | ||
expect(a.Pages).toEqual(e.Pages); | ||
}), 10000); | ||
}); | ||
@@ -193,0 +206,0 @@ }); |
@@ -12,3 +12,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
import * as fontkit from 'fontkit'; | ||
import { getDefaultFont, getFallbackFontName, checkGenerateProps } from '@pdfme/common'; | ||
import { getDefaultFont, getFallbackFontName, checkGenerateProps, } from '@pdfme/common'; | ||
import { getEmbeddedPagesAndEmbedPdfBoxes, drawInputByTemplateSchema, drawEmbeddedPage, embedAndGetFontObj, } from './helper.js'; | ||
@@ -19,9 +19,9 @@ import { TOOL_NAME } from './constants.js'; | ||
const { basePdf } = template; | ||
const fallbackFontName = getFallbackFontName(font); | ||
const pdfDoc = yield PDFDocument.create(); | ||
pdfDoc.registerFontkit(fontkit); | ||
const fallbackFontName = getFallbackFontName(font); | ||
const fontObj = yield embedAndGetFontObj({ pdfDoc, font }); | ||
const pdfFontObj = yield embedAndGetFontObj({ pdfDoc, font }); | ||
const pagesAndBoxes = yield getEmbeddedPagesAndEmbedPdfBoxes({ pdfDoc, basePdf }); | ||
const { embeddedPages, embedPdfBoxes } = pagesAndBoxes; | ||
return { pdfDoc, fontObj, fallbackFontName, embeddedPages, embedPdfBoxes }; | ||
return { pdfDoc, pdfFontObj, fallbackFontName, embeddedPages, embedPdfBoxes }; | ||
}); | ||
@@ -35,6 +35,6 @@ const postProcessing = (pdfDoc) => { | ||
const { inputs, template, options = {} } = props; | ||
const { font = getDefaultFont(), splitThreshold = 3 } = options; | ||
const { font = getDefaultFont() } = options; | ||
const { schemas } = template; | ||
const preRes = yield preprocessing({ inputs, template, font }); | ||
const { pdfDoc, fontObj, fallbackFontName, embeddedPages, embedPdfBoxes } = preRes; | ||
const { pdfDoc, pdfFontObj, fallbackFontName, embeddedPages, embedPdfBoxes } = preRes; | ||
const inputImageCache = {}; | ||
@@ -55,4 +55,3 @@ for (let i = 0; i < inputs.length; i += 1) { | ||
const input = inputObj[key]; | ||
const textSchemaSetting = { fontObj, fallbackFontName, splitThreshold }; | ||
// eslint-disable-next-line no-await-in-loop | ||
const fontSetting = { font, pdfFontObj, fallbackFontName }; | ||
yield drawInputByTemplateSchema({ | ||
@@ -64,3 +63,3 @@ input, | ||
pageHeight, | ||
textSchemaSetting, | ||
fontSetting, | ||
inputImageCache, | ||
@@ -67,0 +66,0 @@ }); |
@@ -12,3 +12,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
import bwipjs from 'bwip-js'; | ||
import { getB64BasePdf, b64toUint8Array, validateBarcodeInput, isTextSchema, isImageSchema, isBarcodeSchema, DEFAULT_FONT_SIZE, DEFAULT_ALIGNMENT, DEFAULT_LINE_HEIGHT, DEFAULT_CHARACTER_SPACING, DEFAULT_FONT_COLOR, } from '@pdfme/common'; | ||
import { getB64BasePdf, b64toUint8Array, validateBarcodeInput, isTextSchema, isImageSchema, isBarcodeSchema, DEFAULT_FONT_SIZE, DEFAULT_ALIGNMENT, DEFAULT_LINE_HEIGHT, DEFAULT_CHARACTER_SPACING, DEFAULT_FONT_COLOR, calculateDynamicFontSize, } from '@pdfme/common'; | ||
const barCodeType2Bcid = (type) => (type === 'nw7' ? 'rationalizedCodabar' : type); | ||
@@ -101,5 +101,5 @@ export const createBarCode = (arg) => __awaiter(void 0, void 0, void 0, function* () { | ||
}; | ||
const getFontProp = (schema) => { | ||
const getFontProp = ({ input, font, schema }) => __awaiter(void 0, void 0, void 0, function* () { | ||
var _a, _b, _c, _d, _e; | ||
const size = (_a = schema.fontSize) !== null && _a !== void 0 ? _a : DEFAULT_FONT_SIZE; | ||
const size = schema.dynamicFontSize ? yield calculateDynamicFontSize({ textSchema: schema, font, input }) : (_a = schema.fontSize) !== null && _a !== void 0 ? _a : DEFAULT_FONT_SIZE; | ||
const color = hex2RgbColor((_b = schema.fontColor) !== null && _b !== void 0 ? _b : DEFAULT_FONT_COLOR); | ||
@@ -110,3 +110,3 @@ const alignment = (_c = schema.alignment) !== null && _c !== void 0 ? _c : DEFAULT_ALIGNMENT; | ||
return { size, color, alignment, lineHeight, characterSpacing }; | ||
}; | ||
}); | ||
const calcX = (x, alignment, boxWidth, textWidth) => { | ||
@@ -138,10 +138,9 @@ let addition = 0; | ||
/** | ||
* Incrementally check the current line for it's real length | ||
* and return the position where it exceeds the box width. | ||
* | ||
* return `null` to indicate if inputLine is shorter as the available bbox | ||
* Incrementally checks the current line for its real length | ||
* and returns the position where it exceeds the box width. | ||
* Returns `null` to indicate if inputLine is shorter as the available bbox. | ||
*/ | ||
const getOverPosition = (inputLine, isOverEval) => { | ||
for (let i = 0; i <= inputLine.length; i += 1) { | ||
if (isOverEval(inputLine.substr(0, i))) { | ||
for (let i = 0; i <= inputLine.length; i++) { | ||
if (isOverEval(inputLine.slice(0, i))) { | ||
return i; | ||
@@ -153,3 +152,3 @@ } | ||
/** | ||
* Get position of the split. Split the exceeding line at | ||
* Gets the position of the split. Splits the exceeding line at | ||
* the last whitespace over it exceeds the bounding box width. | ||
@@ -159,18 +158,13 @@ */ | ||
const overPos = getOverPosition(inputLine, isOverEval); | ||
/** | ||
* if input line is shorter as the available space. We split at the end of the line | ||
*/ | ||
if (overPos === null) | ||
return inputLine.length; | ||
return inputLine.length; // input line is shorter than the available space | ||
let overPosTmp = overPos; | ||
while (inputLine[overPosTmp] !== ' ' && overPosTmp >= 0) | ||
overPosTmp -= 1; | ||
/** | ||
* for very long lines with no whitespace use the original overPos and | ||
* split one char over so we do not overfill the box | ||
*/ | ||
while (inputLine[overPosTmp] !== ' ' && overPosTmp >= 0) { | ||
overPosTmp--; | ||
} | ||
// For very long lines with no whitespace use the original overPos | ||
return overPosTmp > 0 ? overPosTmp : overPos - 1; | ||
}; | ||
/** | ||
* recursively split the line at getSplitPosition. | ||
* Recursively splits the line at getSplitPosition. | ||
* If there is some leftover, split the rest again in the same manner. | ||
@@ -180,9 +174,5 @@ */ | ||
const splitPos = getSplitPosition(inputLine, isOverEval); | ||
const splittedLine = inputLine.substr(0, splitPos); | ||
const rest = inputLine.slice(splitPos).trimLeft(); | ||
/** | ||
* end recursion if there is no rest, return single splitted line in an array | ||
* so we can join them over the recursion | ||
*/ | ||
if (rest.length === 0) { | ||
const splittedLine = inputLine.substring(0, splitPos); | ||
const rest = inputLine.substring(splitPos).trimStart(); | ||
if (rest.length === 0) { // end recursion if there is no rest | ||
return [splittedLine]; | ||
@@ -192,9 +182,9 @@ } | ||
}; | ||
const drawInputByTextSchema = (arg) => { | ||
const { input, templateSchema, page, pageHeight, textSchemaSetting } = arg; | ||
const { fontObj, fallbackFontName, splitThreshold } = textSchemaSetting; | ||
const fontValue = fontObj[templateSchema.fontName ? templateSchema.fontName : fallbackFontName]; | ||
const drawInputByTextSchema = (arg) => __awaiter(void 0, void 0, void 0, function* () { | ||
const { input, templateSchema, page, pageHeight, fontSetting } = arg; | ||
const { font, pdfFontObj, fallbackFontName } = fontSetting; | ||
const pdfFontValue = pdfFontObj[templateSchema.fontName ? templateSchema.fontName : fallbackFontName]; | ||
drawBackgroundColor({ templateSchema, page, pageHeight }); | ||
const { width, rotate } = getSchemaSizeAndRotate(templateSchema); | ||
const { size, color, alignment, lineHeight, characterSpacing } = getFontProp(templateSchema); | ||
const { size, color, alignment, lineHeight, characterSpacing } = yield getFontProp({ input, font, schema: templateSchema }); | ||
page.pushOperators(setCharacterSpacing(characterSpacing)); | ||
@@ -204,12 +194,8 @@ let beforeLineOver = 0; | ||
const isOverEval = (testString) => { | ||
const testStringWidth = fontValue.widthOfTextAtSize(testString, size) + (testString.length - 1) * characterSpacing; | ||
/** | ||
* split if the difference is less then two pixel | ||
* (found out / tested this threshold heuristically, most probably widthOfTextAtSize is unprecise) | ||
**/ | ||
return width - testStringWidth <= splitThreshold; | ||
const testStringWidth = pdfFontValue.widthOfTextAtSize(testString, size) + (testString.length - 1) * characterSpacing; | ||
return width <= testStringWidth; | ||
}; | ||
const splitedLines = getSplittedLines(inputLine, isOverEval); | ||
const drawLine = (splitedLine, splitedLineIndex) => { | ||
const textWidth = fontValue.widthOfTextAtSize(splitedLine, size) + | ||
const textWidth = pdfFontValue.widthOfTextAtSize(splitedLine, size) + | ||
(splitedLine.length - 1) * characterSpacing; | ||
@@ -226,3 +212,3 @@ page.drawText(splitedLine, { | ||
maxWidth: width, | ||
font: fontValue, | ||
font: pdfFontValue, | ||
wordBreaks: [''], | ||
@@ -235,3 +221,3 @@ }); | ||
}); | ||
}; | ||
}); | ||
const getCacheKey = (templateSchema, input) => `${templateSchema.type}${input}`; | ||
@@ -283,3 +269,3 @@ const drawInputByImageSchema = (arg) => __awaiter(void 0, void 0, void 0, function* () { | ||
const templateSchema = arg.templateSchema; | ||
drawInputByTextSchema(Object.assign(Object.assign({}, arg), { templateSchema })); | ||
yield drawInputByTextSchema(Object.assign(Object.assign({}, arg), { templateSchema })); | ||
} | ||
@@ -286,0 +272,0 @@ else if (isImageSchema(arg.templateSchema)) { |
import generate from './generate.js'; | ||
import { BLANK_PDF, HELVETICA, isTextSchema, isImageSchema, isBarcodeSchema, checkTemplate, checkUIProps, checkPreviewProps, checkDesignerProps, checkGenerateProps, validateBarcodeInput, } from '@pdfme/common'; | ||
export { generate, BLANK_PDF, HELVETICA, isTextSchema, isImageSchema, isBarcodeSchema, checkTemplate, checkUIProps, checkPreviewProps, checkDesignerProps, checkGenerateProps, validateBarcodeInput, }; | ||
import { BLANK_PDF, DEFAULT_FONT_VALUE, isTextSchema, isImageSchema, isBarcodeSchema, checkTemplate, checkUIProps, checkPreviewProps, checkDesignerProps, checkGenerateProps, validateBarcodeInput, } from '@pdfme/common'; | ||
export { generate, BLANK_PDF, DEFAULT_FONT_VALUE, isTextSchema, isImageSchema, isBarcodeSchema, checkTemplate, checkUIProps, checkPreviewProps, checkDesignerProps, checkGenerateProps, validateBarcodeInput, }; | ||
//# sourceMappingURL=index.js.map |
@@ -14,2 +14,6 @@ declare const _default: { | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -55,2 +59,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -96,2 +104,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -137,2 +149,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -178,2 +194,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -219,2 +239,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -260,2 +284,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -301,2 +329,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -342,2 +374,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -383,2 +419,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -424,2 +464,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -465,2 +509,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -506,2 +554,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -547,2 +599,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -588,2 +644,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -629,2 +689,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -670,2 +734,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -711,2 +779,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -752,2 +824,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -793,2 +869,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -834,2 +914,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -875,2 +959,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -916,2 +1004,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -957,2 +1049,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -998,2 +1094,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1039,2 +1139,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1080,2 +1184,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1121,2 +1229,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1162,2 +1274,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1203,2 +1319,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1244,2 +1364,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1285,2 +1409,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1326,2 +1454,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1367,2 +1499,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1408,2 +1544,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1449,2 +1589,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1490,2 +1634,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1531,2 +1679,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1572,2 +1724,6 @@ height: number; | ||
characterSpacing?: number | undefined; | ||
dynamicFontSize?: { | ||
max: number; | ||
min: number; | ||
} | undefined; | ||
type: "text"; | ||
@@ -1574,0 +1730,0 @@ height: number; |
@@ -47,8 +47,8 @@ /// <reference types="node" /> | ||
}>; | ||
interface TextSchemaSetting { | ||
fontObj: { | ||
interface FontSetting { | ||
font: Font; | ||
pdfFontObj: { | ||
[key: string]: PDFFont; | ||
}; | ||
fallbackFontName: string; | ||
splitThreshold: number; | ||
} | ||
@@ -61,3 +61,3 @@ export declare const drawInputByTemplateSchema: (arg: { | ||
pageHeight: number; | ||
textSchemaSetting: TextSchemaSetting; | ||
fontSetting: FontSetting; | ||
inputImageCache: InputImageCache; | ||
@@ -64,0 +64,0 @@ }) => Promise<void>; |
import generate from './generate.js'; | ||
import { BLANK_PDF, HELVETICA, isTextSchema, isImageSchema, isBarcodeSchema, checkTemplate, checkUIProps, checkPreviewProps, checkDesignerProps, checkGenerateProps, validateBarcodeInput } from '@pdfme/common'; | ||
import { BLANK_PDF, DEFAULT_FONT_VALUE, isTextSchema, isImageSchema, isBarcodeSchema, checkTemplate, checkUIProps, checkPreviewProps, checkDesignerProps, checkGenerateProps, validateBarcodeInput } from '@pdfme/common'; | ||
import type { Lang, Size, Alignment, SchemaType, BarCodeType, TextSchema, ImageSchema, BarcodeSchema, Schema, SchemaForUI, Font, BasePdf, Template, CommonProps, GeneratorOptions, GenerateProps, UIOptions, UIProps, PreviewProps, DesignerProps } from '@pdfme/common'; | ||
export { generate, BLANK_PDF, HELVETICA, isTextSchema, isImageSchema, isBarcodeSchema, checkTemplate, checkUIProps, checkPreviewProps, checkDesignerProps, checkGenerateProps, validateBarcodeInput, }; | ||
export { generate, BLANK_PDF, DEFAULT_FONT_VALUE, isTextSchema, isImageSchema, isBarcodeSchema, checkTemplate, checkUIProps, checkPreviewProps, checkDesignerProps, checkGenerateProps, validateBarcodeInput, }; | ||
export type { Lang, Size, Alignment, SchemaType, BarCodeType, TextSchema, ImageSchema, BarcodeSchema, Schema, SchemaForUI, Font, BasePdf, Template, CommonProps, GeneratorOptions, GenerateProps, UIOptions, UIProps, PreviewProps, DesignerProps, }; |
{ | ||
"name": "@pdfme/generator", | ||
"version": "1.1.10", | ||
"version": "1.2.0", | ||
"sideEffects": false, | ||
@@ -49,3 +49,3 @@ "author": "hand-dot", | ||
"dependencies": { | ||
"@pdfme/common": "^1.0.0", | ||
"@pdfme/common": "file:../common", | ||
"@pdfme/pdf-lib": "^1.17.3", | ||
@@ -52,0 +52,0 @@ "atob": "^2.1.2", |
import { PDFDocument } from '@pdfme/pdf-lib'; | ||
import * as fontkit from 'fontkit'; | ||
import type { GenerateProps, Template, Font } from '@pdfme/common'; | ||
import { getDefaultFont, getFallbackFontName, checkGenerateProps } from '@pdfme/common'; | ||
import type { | ||
Font, | ||
GenerateProps, | ||
SchemaInputs, | ||
Template, | ||
} from '@pdfme/common'; | ||
import { | ||
getDefaultFont, | ||
getFallbackFontName, | ||
checkGenerateProps, | ||
} from '@pdfme/common'; | ||
import { | ||
getEmbeddedPagesAndEmbedPdfBoxes, | ||
@@ -14,10 +23,6 @@ drawInputByTemplateSchema, | ||
const preprocessing = async (arg: { | ||
inputs: { [key: string]: string }[]; | ||
template: Template; | ||
font: Font; | ||
}) => { | ||
const preprocessing = async (arg: { inputs: SchemaInputs[]; template: Template; font: Font }) => { | ||
const { template, font } = arg; | ||
const { basePdf } = template; | ||
const fallbackFontName = getFallbackFontName(font); | ||
@@ -27,4 +32,3 @@ const pdfDoc = await PDFDocument.create(); | ||
const fallbackFontName = getFallbackFontName(font); | ||
const fontObj = await embedAndGetFontObj({ pdfDoc, font }); | ||
const pdfFontObj = await embedAndGetFontObj({ pdfDoc, font }); | ||
@@ -34,3 +38,3 @@ const pagesAndBoxes = await getEmbeddedPagesAndEmbedPdfBoxes({ pdfDoc, basePdf }); | ||
return { pdfDoc, fontObj, fallbackFontName, embeddedPages, embedPdfBoxes }; | ||
return { pdfDoc, pdfFontObj, fallbackFontName, embeddedPages, embedPdfBoxes }; | ||
}; | ||
@@ -46,7 +50,9 @@ | ||
const { inputs, template, options = {} } = props; | ||
const { font = getDefaultFont(), splitThreshold = 3 } = options; | ||
const { font = getDefaultFont() } = options; | ||
const { schemas } = template; | ||
const preRes = await preprocessing({ inputs, template, font }); | ||
const { pdfDoc, fontObj, fallbackFontName, embeddedPages, embedPdfBoxes } = preRes; | ||
const { pdfDoc, pdfFontObj, fallbackFontName, embeddedPages, embedPdfBoxes } = preRes; | ||
@@ -70,5 +76,4 @@ const inputImageCache: InputImageCache = {}; | ||
const input = inputObj[key]; | ||
const textSchemaSetting = { fontObj, fallbackFontName, splitThreshold }; | ||
const fontSetting = { font, pdfFontObj, fallbackFontName }; | ||
// eslint-disable-next-line no-await-in-loop | ||
await drawInputByTemplateSchema({ | ||
@@ -80,3 +85,3 @@ input, | ||
pageHeight, | ||
textSchemaSetting, | ||
fontSetting, | ||
inputImageCache, | ||
@@ -83,0 +88,0 @@ }); |
@@ -33,2 +33,3 @@ import { | ||
DEFAULT_FONT_COLOR, | ||
calculateDynamicFontSize, | ||
} from '@pdfme/common'; | ||
@@ -170,4 +171,4 @@ | ||
const getFontProp = (schema: TextSchema) => { | ||
const size = schema.fontSize ?? DEFAULT_FONT_SIZE; | ||
const getFontProp = async ({ input, font, schema }: { input: string, font: Font, schema: TextSchema }) => { | ||
const size = schema.dynamicFontSize ? await calculateDynamicFontSize({ textSchema: schema, font, input }) : schema.fontSize ?? DEFAULT_FONT_SIZE; | ||
const color = hex2RgbColor(schema.fontColor ?? DEFAULT_FONT_COLOR); | ||
@@ -213,11 +214,11 @@ const alignment = schema.alignment ?? DEFAULT_ALIGNMENT; | ||
type IsOverEval = (testString: string) => boolean; | ||
/** | ||
* Incrementally check the current line for it's real length | ||
* and return the position where it exceeds the box width. | ||
* | ||
* return `null` to indicate if inputLine is shorter as the available bbox | ||
* Incrementally checks the current line for its real length | ||
* and returns the position where it exceeds the box width. | ||
* Returns `null` to indicate if inputLine is shorter as the available bbox. | ||
*/ | ||
const getOverPosition = (inputLine: string, isOverEval: IsOverEval) => { | ||
for (let i = 0; i <= inputLine.length; i += 1) { | ||
if (isOverEval(inputLine.substr(0, i))) { | ||
for (let i = 0; i <= inputLine.length; i++) { | ||
if (isOverEval(inputLine.slice(0, i))) { | ||
return i; | ||
@@ -231,3 +232,3 @@ } | ||
/** | ||
* Get position of the split. Split the exceeding line at | ||
* Gets the position of the split. Splits the exceeding line at | ||
* the last whitespace over it exceeds the bounding box width. | ||
@@ -237,13 +238,10 @@ */ | ||
const overPos = getOverPosition(inputLine, isOverEval); | ||
/** | ||
* if input line is shorter as the available space. We split at the end of the line | ||
*/ | ||
if (overPos === null) return inputLine.length; | ||
if (overPos === null) return inputLine.length; // input line is shorter than the available space | ||
let overPosTmp = overPos; | ||
while (inputLine[overPosTmp] !== ' ' && overPosTmp >= 0) overPosTmp -= 1; | ||
/** | ||
* for very long lines with no whitespace use the original overPos and | ||
* split one char over so we do not overfill the box | ||
*/ | ||
while (inputLine[overPosTmp] !== ' ' && overPosTmp >= 0) { | ||
overPosTmp--; | ||
} | ||
// For very long lines with no whitespace use the original overPos | ||
return overPosTmp > 0 ? overPosTmp : overPos - 1; | ||
@@ -253,3 +251,3 @@ }; | ||
/** | ||
* recursively split the line at getSplitPosition. | ||
* Recursively splits the line at getSplitPosition. | ||
* If there is some leftover, split the rest again in the same manner. | ||
@@ -259,9 +257,6 @@ */ | ||
const splitPos = getSplitPosition(inputLine, isOverEval); | ||
const splittedLine = inputLine.substr(0, splitPos); | ||
const rest = inputLine.slice(splitPos).trimLeft(); | ||
/** | ||
* end recursion if there is no rest, return single splitted line in an array | ||
* so we can join them over the recursion | ||
*/ | ||
if (rest.length === 0) { | ||
const splittedLine = inputLine.substring(0, splitPos); | ||
const rest = inputLine.substring(splitPos).trimStart(); | ||
if (rest.length === 0) { // end recursion if there is no rest | ||
return [splittedLine]; | ||
@@ -273,11 +268,11 @@ } | ||
interface TextSchemaSetting { | ||
fontObj: { | ||
interface FontSetting { | ||
font: Font; | ||
pdfFontObj: { | ||
[key: string]: PDFFont; | ||
}; | ||
fallbackFontName: string; | ||
splitThreshold: number; | ||
} | ||
const drawInputByTextSchema = (arg: { | ||
const drawInputByTextSchema = async (arg: { | ||
input: string; | ||
@@ -288,8 +283,8 @@ templateSchema: TextSchema; | ||
pageHeight: number; | ||
textSchemaSetting: TextSchemaSetting; | ||
fontSetting: FontSetting; | ||
}) => { | ||
const { input, templateSchema, page, pageHeight, textSchemaSetting } = arg; | ||
const { fontObj, fallbackFontName, splitThreshold } = textSchemaSetting; | ||
const { input, templateSchema, page, pageHeight, fontSetting } = arg; | ||
const { font, pdfFontObj, fallbackFontName } = fontSetting; | ||
const fontValue = fontObj[templateSchema.fontName ? templateSchema.fontName : fallbackFontName]; | ||
const pdfFontValue = pdfFontObj[templateSchema.fontName ? templateSchema.fontName : fallbackFontName]; | ||
@@ -299,3 +294,4 @@ drawBackgroundColor({ templateSchema, page, pageHeight }); | ||
const { width, rotate } = getSchemaSizeAndRotate(templateSchema); | ||
const { size, color, alignment, lineHeight, characterSpacing } = getFontProp(templateSchema); | ||
const { size, color, alignment, lineHeight, characterSpacing } = await getFontProp({ input, font, schema: templateSchema }); | ||
page.pushOperators(setCharacterSpacing(characterSpacing)); | ||
@@ -308,9 +304,4 @@ | ||
const testStringWidth = | ||
fontValue.widthOfTextAtSize(testString, size) + (testString.length - 1) * characterSpacing; | ||
/** | ||
* split if the difference is less then two pixel | ||
* (found out / tested this threshold heuristically, most probably widthOfTextAtSize is unprecise) | ||
**/ | ||
return width - testStringWidth <= splitThreshold; | ||
pdfFontValue.widthOfTextAtSize(testString, size) + (testString.length - 1) * characterSpacing; | ||
return width <= testStringWidth; | ||
}; | ||
@@ -320,3 +311,3 @@ const splitedLines = getSplittedLines(inputLine, isOverEval); | ||
const textWidth = | ||
fontValue.widthOfTextAtSize(splitedLine, size) + | ||
pdfFontValue.widthOfTextAtSize(splitedLine, size) + | ||
(splitedLine.length - 1) * characterSpacing; | ||
@@ -334,3 +325,3 @@ page.drawText(splitedLine, { | ||
maxWidth: width, | ||
font: fontValue, | ||
font: pdfFontValue, | ||
wordBreaks: [''], | ||
@@ -412,3 +403,3 @@ }); | ||
pageHeight: number; | ||
textSchemaSetting: TextSchemaSetting; | ||
fontSetting: FontSetting; | ||
inputImageCache: InputImageCache; | ||
@@ -420,3 +411,3 @@ }) => { | ||
const templateSchema = arg.templateSchema as TextSchema; | ||
drawInputByTextSchema({ ...arg, templateSchema }); | ||
await drawInputByTextSchema({ ...arg, templateSchema }); | ||
} else if (isImageSchema(arg.templateSchema)) { | ||
@@ -423,0 +414,0 @@ const templateSchema = arg.templateSchema as ImageSchema; |
import generate from './generate.js'; | ||
import { | ||
BLANK_PDF, | ||
HELVETICA, | ||
DEFAULT_FONT_VALUE, | ||
isTextSchema, | ||
@@ -41,3 +41,3 @@ isImageSchema, | ||
BLANK_PDF, | ||
HELVETICA, | ||
DEFAULT_FONT_VALUE, | ||
isTextSchema, | ||
@@ -44,0 +44,0 @@ isImageSchema, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
237948
46
4169
4
- Removed@pdfme/common@1.2.6(transitive)
- Removedbuffer@6.0.3(transitive)
- Removedieee754@1.2.1(transitive)
- Removedzod@3.24.1(transitive)
Updated@pdfme/common@file:../common