@signiphi/pdf-signer 0.2.0-beta.25 → 0.2.0-beta.26
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/components/index.js +147 -14
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +147 -14
- package/dist/components/index.mjs.map +1 -1
- package/dist/hooks/index.js +136 -6
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +136 -6
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/index.js +154 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +154 -19
- package/dist/index.mjs.map +1 -1
- package/dist/utils/date-validation.d.ts.map +1 -1
- package/dist/utils/index.js +154 -19
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +154 -19
- package/dist/utils/index.mjs.map +1 -1
- package/dist/utils/pdf-manipulation.d.ts.map +1 -1
- package/dist/utils/pdf-text-wrapping.d.ts +42 -0
- package/dist/utils/pdf-text-wrapping.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/components/index.js
CHANGED
|
@@ -617,6 +617,118 @@ function isRequiredField(field, fieldName, fieldType) {
|
|
|
617
617
|
return false;
|
|
618
618
|
}
|
|
619
619
|
|
|
620
|
+
// src/utils/pdf-text-wrapping.ts
|
|
621
|
+
function wrapTextToLines(text, font, fontSize, maxWidth) {
|
|
622
|
+
if (!text) return [];
|
|
623
|
+
if (maxWidth <= 0) return [text];
|
|
624
|
+
const measure = (s) => {
|
|
625
|
+
try {
|
|
626
|
+
return font.widthOfTextAtSize(s, fontSize);
|
|
627
|
+
} catch {
|
|
628
|
+
return s.length * fontSize * 0.5;
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
const breakLongWord = (word) => {
|
|
632
|
+
const chunks = [];
|
|
633
|
+
let current = "";
|
|
634
|
+
for (const ch of word) {
|
|
635
|
+
const candidate = current + ch;
|
|
636
|
+
if (measure(candidate) > maxWidth && current.length > 0) {
|
|
637
|
+
chunks.push(current);
|
|
638
|
+
current = ch;
|
|
639
|
+
} else {
|
|
640
|
+
current = candidate;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
if (current.length > 0) chunks.push(current);
|
|
644
|
+
return chunks;
|
|
645
|
+
};
|
|
646
|
+
const segments = text.split("\n");
|
|
647
|
+
const lines = [];
|
|
648
|
+
for (const segment of segments) {
|
|
649
|
+
if (segment.length === 0) {
|
|
650
|
+
lines.push("");
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
const words = segment.split(/(\s+)/).filter((token) => token.length > 0);
|
|
654
|
+
let current = "";
|
|
655
|
+
for (const token of words) {
|
|
656
|
+
const candidate = current + token;
|
|
657
|
+
if (measure(candidate) <= maxWidth) {
|
|
658
|
+
current = candidate;
|
|
659
|
+
continue;
|
|
660
|
+
}
|
|
661
|
+
if (current.trim().length > 0) {
|
|
662
|
+
lines.push(current.trimEnd());
|
|
663
|
+
current = "";
|
|
664
|
+
}
|
|
665
|
+
const trimmedToken = token.trimStart();
|
|
666
|
+
if (measure(trimmedToken) <= maxWidth) {
|
|
667
|
+
current = trimmedToken;
|
|
668
|
+
} else {
|
|
669
|
+
const broken = breakLongWord(trimmedToken);
|
|
670
|
+
for (let i = 0; i < broken.length - 1; i++) {
|
|
671
|
+
const piece = broken[i];
|
|
672
|
+
if (piece !== void 0) lines.push(piece);
|
|
673
|
+
}
|
|
674
|
+
current = broken[broken.length - 1] ?? "";
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
lines.push(current.trimEnd());
|
|
678
|
+
}
|
|
679
|
+
return lines;
|
|
680
|
+
}
|
|
681
|
+
var MIN_MULTILINE_FONT_SIZE = 8;
|
|
682
|
+
function findFittingFontSize(text, font, preferredSize, maxWidth, maxHeight) {
|
|
683
|
+
if (preferredSize <= MIN_MULTILINE_FONT_SIZE) return preferredSize;
|
|
684
|
+
for (let size = preferredSize; size >= MIN_MULTILINE_FONT_SIZE; size -= 1) {
|
|
685
|
+
const lines = wrapTextToLines(text, font, size, maxWidth);
|
|
686
|
+
if (lines.length * size * 1.2 <= maxHeight) return size;
|
|
687
|
+
}
|
|
688
|
+
return MIN_MULTILINE_FONT_SIZE;
|
|
689
|
+
}
|
|
690
|
+
function drawWrappedText(page, text, opts) {
|
|
691
|
+
if (!text) return;
|
|
692
|
+
const { x, y, width, height, fontSize, font, color, multiline } = opts;
|
|
693
|
+
const padding = opts.padding ?? 2;
|
|
694
|
+
const innerWidth = Math.max(0, width - padding * 2);
|
|
695
|
+
if (!multiline) {
|
|
696
|
+
let display = text.replace(/\n/g, " ");
|
|
697
|
+
if (font.widthOfTextAtSize(display, fontSize) > innerWidth) {
|
|
698
|
+
let truncated = "";
|
|
699
|
+
for (const ch of display) {
|
|
700
|
+
if (font.widthOfTextAtSize(truncated + ch, fontSize) > innerWidth) break;
|
|
701
|
+
truncated += ch;
|
|
702
|
+
}
|
|
703
|
+
display = truncated;
|
|
704
|
+
}
|
|
705
|
+
page.drawText(display, {
|
|
706
|
+
x: x + padding,
|
|
707
|
+
y: y + (height - fontSize) / 2,
|
|
708
|
+
size: fontSize,
|
|
709
|
+
font,
|
|
710
|
+
color
|
|
711
|
+
});
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
const innerHeight = Math.max(0, height - padding * 2);
|
|
715
|
+
const fittedSize = findFittingFontSize(text, font, fontSize, innerWidth, innerHeight);
|
|
716
|
+
const lineHeight = fittedSize * 1.2;
|
|
717
|
+
const allLines = wrapTextToLines(text, font, fittedSize, innerWidth);
|
|
718
|
+
for (let i = 0; i < allLines.length; i++) {
|
|
719
|
+
const line = allLines[i];
|
|
720
|
+
if (!line) continue;
|
|
721
|
+
const lineY = y + height - padding - fittedSize - i * lineHeight;
|
|
722
|
+
page.drawText(line, {
|
|
723
|
+
x: x + padding,
|
|
724
|
+
y: lineY,
|
|
725
|
+
size: fittedSize,
|
|
726
|
+
font,
|
|
727
|
+
color
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
620
732
|
// src/utils/pdf-manipulation.ts
|
|
621
733
|
async function readPdfFormFields(pdfBytes) {
|
|
622
734
|
try {
|
|
@@ -1261,6 +1373,21 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
|
|
|
1261
1373
|
const labelFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
|
|
1262
1374
|
const isDateField = fieldName.toLowerCase().includes("date") || fieldName.toLowerCase().includes("_date");
|
|
1263
1375
|
const fontSize = isDateField ? 14 : extractFieldFontSize(fieldName, field, extractedFormFields);
|
|
1376
|
+
let isMultiline = false;
|
|
1377
|
+
if (!isDateField) {
|
|
1378
|
+
try {
|
|
1379
|
+
const textFieldField = field;
|
|
1380
|
+
if (typeof textFieldField.isMultiline === "function") {
|
|
1381
|
+
isMultiline = textFieldField.isMultiline() === true;
|
|
1382
|
+
}
|
|
1383
|
+
} catch {
|
|
1384
|
+
isMultiline = false;
|
|
1385
|
+
}
|
|
1386
|
+
if (!isMultiline) {
|
|
1387
|
+
isMultiline = fieldInfo?.multiline === true;
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
const valueFont = await pdfDoc.embedFont(StandardFonts.Helvetica);
|
|
1264
1391
|
for (const widget of widgets) {
|
|
1265
1392
|
const result = getWidgetRectangleAndPage(widget, pages);
|
|
1266
1393
|
if (!result) continue;
|
|
@@ -1278,12 +1405,15 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
|
|
|
1278
1405
|
});
|
|
1279
1406
|
}
|
|
1280
1407
|
if (fieldValue && fieldValue.trim()) {
|
|
1281
|
-
page
|
|
1282
|
-
x: rect.x
|
|
1283
|
-
y: rect.y
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1408
|
+
drawWrappedText(page, fieldValue, {
|
|
1409
|
+
x: rect.x,
|
|
1410
|
+
y: rect.y,
|
|
1411
|
+
width: rect.width,
|
|
1412
|
+
height: rect.height,
|
|
1413
|
+
fontSize,
|
|
1414
|
+
font: valueFont,
|
|
1415
|
+
color: rgb(0, 0, 0),
|
|
1416
|
+
multiline: isMultiline
|
|
1287
1417
|
});
|
|
1288
1418
|
}
|
|
1289
1419
|
}
|
|
@@ -2043,14 +2173,17 @@ function parseAndValidateDate(value) {
|
|
|
2043
2173
|
} catch {
|
|
2044
2174
|
}
|
|
2045
2175
|
}
|
|
2046
|
-
const
|
|
2047
|
-
if (
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2176
|
+
const looksLikeNumericDate = /^\d{1,4}[\/.\-]\d{1,2}[\/.\-]\d{1,4}$/.test(sanitizedValue);
|
|
2177
|
+
if (!looksLikeNumericDate) {
|
|
2178
|
+
const nativeParsed = new Date(sanitizedValue);
|
|
2179
|
+
if (dateFns.isValid(nativeParsed) && !isNaN(nativeParsed.getTime())) {
|
|
2180
|
+
return {
|
|
2181
|
+
isValid: true,
|
|
2182
|
+
date: nativeParsed,
|
|
2183
|
+
isoString: toIsoDateString(nativeParsed),
|
|
2184
|
+
originalValue
|
|
2185
|
+
};
|
|
2186
|
+
}
|
|
2054
2187
|
}
|
|
2055
2188
|
return {
|
|
2056
2189
|
isValid: false,
|