@fenfill/mcp 0.2.0 → 0.2.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 +3 -1
- package/THIRD_PARTY_NOTICES +1 -1
- package/dist/index.js +178 -58
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -138,7 +138,8 @@ workspace, free native-field (AcroForm) ones included.
|
|
|
138
138
|
a text/date field's stored `format` and `font_pt` (the size its value starts at; `font_auto`
|
|
139
139
|
when that follows the box height); a choice's options with their own boxes; a table's cells by
|
|
140
140
|
`(row, col)`, its `orientation` and headers (also printed on the image inside, or beside, the
|
|
141
|
-
first cell of each line as `R: …` / `C:
|
|
141
|
+
first cell of each line as `R: …` / `C: …`; a character the bundled fonts lack is shown as `?`
|
|
142
|
+
there, with a warning, and the legend keeps the full text); a `table_rows` table's columns and printed cells
|
|
142
143
|
with their boxes (fill values still go by column id). `warnings` and `placement_warnings` are
|
|
143
144
|
always present (`[]` = checked and clean): placement covers every box shown, so a plain preview
|
|
144
145
|
is a read-only placement audit (see the checks under `edit_template`). `crop`
|
|
@@ -314,6 +315,7 @@ fenfill web app for that workspace (for example, your logo if you have set one u
|
|
|
314
315
|
| `too_many_active_jobs` | Other analyses in the workspace (free native-field ones too) are still running; try again in a minute, or analyze fewer at once. |
|
|
315
316
|
| `template_conflict` | The template changed in fenfill since your edits began. Your local edits are kept: `edit_template` with `discard: true`, re-apply the ops, save again. |
|
|
316
317
|
| `invalid_schema` | fenfill (or the local check before it) refused the edited layout; `details` lists each item and reason. Fix them with `edit_template`. |
|
|
318
|
+
| `check_copy_failed` | `preview_page` could not build its outlined copy; `stage` and `id` say where. Fix or remove that field or group with `edit_template`, then preview again. |
|
|
317
319
|
| `request_too_large` | The edited template is too large to save in one request. |
|
|
318
320
|
| `answer_in_template` | Edited wording matches an answer from this session, so nothing was sent. Put the form's own wording back with `edit_template`. |
|
|
319
321
|
| `confirm_wording_needed` | The working copy has wording edited in an earlier session. Review the ids and properties in `changed`, then `save_template` with `confirm_wording: true`. |
|
package/THIRD_PARTY_NOTICES
CHANGED
package/dist/index.js
CHANGED
|
@@ -135572,6 +135572,37 @@ function layoutMultiline({
|
|
|
135572
135572
|
}
|
|
135573
135573
|
|
|
135574
135574
|
// ../../app/t/[template_id]/stampPdf.ts
|
|
135575
|
+
async function embedStampFaces(pdfDoc, fontkit, fonts) {
|
|
135576
|
+
const interFont = await pdfDoc.embedFont(fonts.inter, { subset: true });
|
|
135577
|
+
const dejaFont = await pdfDoc.embedFont(fonts.deja, { subset: true });
|
|
135578
|
+
const interKit = fontkit.create(new Uint8Array(fonts.inter));
|
|
135579
|
+
const covers = (cp) => {
|
|
135580
|
+
try {
|
|
135581
|
+
return interKit.hasGlyphForCodePoint(cp);
|
|
135582
|
+
} catch {
|
|
135583
|
+
return false;
|
|
135584
|
+
}
|
|
135585
|
+
};
|
|
135586
|
+
const splitRuns = (t) => splitByCoverage(t, (cp) => covers(cp) ? interFont : dejaFont).map((r) => ({
|
|
135587
|
+
font: r.key,
|
|
135588
|
+
text: r.text
|
|
135589
|
+
}));
|
|
135590
|
+
const measure = (t, s) => splitRuns(t).reduce((sum2, r) => sum2 + r.font.widthOfTextAtSize(r.text, s), 0);
|
|
135591
|
+
const draw = (page, t, x2, y, s, color) => {
|
|
135592
|
+
let cx2 = x2;
|
|
135593
|
+
for (const r of splitRuns(t)) {
|
|
135594
|
+
page.drawText(r.text, { x: cx2, y, size: s, font: r.font, color });
|
|
135595
|
+
cx2 += r.font.widthOfTextAtSize(r.text, s);
|
|
135596
|
+
}
|
|
135597
|
+
};
|
|
135598
|
+
let dejaSet;
|
|
135599
|
+
const hasGlyph = (cp) => {
|
|
135600
|
+
if (covers(cp)) return true;
|
|
135601
|
+
dejaSet ??= new Set(dejaFont.getCharacterSet());
|
|
135602
|
+
return dejaSet.has(cp);
|
|
135603
|
+
};
|
|
135604
|
+
return { measure, draw, hasGlyph };
|
|
135605
|
+
}
|
|
135575
135606
|
async function stampPdf({
|
|
135576
135607
|
pdfBytes,
|
|
135577
135608
|
marksByPage,
|
|
@@ -135605,29 +135636,12 @@ async function stampPdf({
|
|
|
135605
135636
|
return r.arrayBuffer();
|
|
135606
135637
|
})
|
|
135607
135638
|
]);
|
|
135608
|
-
const
|
|
135609
|
-
const dejaFont = await pdfDoc.embedFont(dejaBytes, { subset: true });
|
|
135639
|
+
const faces = await embedStampFaces(pdfDoc, fontkit, { inter: interBytes, deja: dejaBytes });
|
|
135610
135640
|
const pdfPages = pdfDoc.getPages();
|
|
135611
135641
|
const INK = rgb3(0.1, 0.1, 0.1);
|
|
135612
|
-
const
|
|
135613
|
-
const covers = (cp) => {
|
|
135614
|
-
try {
|
|
135615
|
-
return interKit.hasGlyphForCodePoint(cp);
|
|
135616
|
-
} catch {
|
|
135617
|
-
return false;
|
|
135618
|
-
}
|
|
135619
|
-
};
|
|
135620
|
-
const splitRuns = (t) => splitByCoverage(t, (cp) => covers(cp) ? interFont : dejaFont).map((r) => ({
|
|
135621
|
-
font: r.key,
|
|
135622
|
-
text: r.text
|
|
135623
|
-
}));
|
|
135624
|
-
const measure = (t, s) => splitRuns(t).reduce((sum2, r) => sum2 + r.font.widthOfTextAtSize(r.text, s), 0);
|
|
135642
|
+
const { measure } = faces;
|
|
135625
135643
|
const drawMixed = (page, t, x2, y, s) => {
|
|
135626
|
-
|
|
135627
|
-
for (const r of splitRuns(t)) {
|
|
135628
|
-
page.drawText(r.text, { x: cx2, y, size: s, font: r.font, color: INK });
|
|
135629
|
-
cx2 += r.font.widthOfTextAtSize(r.text, s);
|
|
135630
|
-
}
|
|
135644
|
+
faces.draw(page, t, x2, y, s, INK);
|
|
135631
135645
|
};
|
|
135632
135646
|
const drawMarkPdf = (page, shape, r, sizePt, overflow) => {
|
|
135633
135647
|
const fit = Math.min(r.w, r.h);
|
|
@@ -136602,9 +136616,34 @@ function checkTagIds(entries) {
|
|
|
136602
136616
|
return ids;
|
|
136603
136617
|
}
|
|
136604
136618
|
var hits = (a, b) => a.x < b.x + b.w && b.x < a.x + a.w && a.y < b.y + b.h && b.y < a.y + a.h;
|
|
136605
|
-
|
|
136619
|
+
var causeOf = (e4) => e4 instanceof Error && e4.message ? e4.message : String(e4);
|
|
136620
|
+
var oneLine = (s) => s.replace(/[\s\p{Cc}]+/gu, " ").trim();
|
|
136621
|
+
var asciiOnly = (s) => s.replace(/[^\x20-\x7e]/g, "?");
|
|
136622
|
+
var CheckCopyError = class extends Error {
|
|
136623
|
+
at;
|
|
136624
|
+
constructor(at, cause) {
|
|
136625
|
+
super(causeOf(cause));
|
|
136626
|
+
this.name = "CheckCopyError";
|
|
136627
|
+
this.at = { ...at };
|
|
136628
|
+
}
|
|
136629
|
+
};
|
|
136630
|
+
async function buildCheckPdf(stamped, entries, status, fonts, banner = true) {
|
|
136631
|
+
const at = { stage: "load" };
|
|
136632
|
+
try {
|
|
136633
|
+
return await drawCheckPdf(stamped, entries, status, fonts, banner, at);
|
|
136634
|
+
} catch (e4) {
|
|
136635
|
+
throw new CheckCopyError(at, e4);
|
|
136636
|
+
}
|
|
136637
|
+
}
|
|
136638
|
+
async function drawCheckPdf(stamped, entries, status, fonts, banner, at) {
|
|
136639
|
+
const step = (stage, id) => {
|
|
136640
|
+
at.stage = stage;
|
|
136641
|
+
at.id = id;
|
|
136642
|
+
};
|
|
136643
|
+
const notes = [];
|
|
136606
136644
|
const { PDFDocument: PDFDocument2, StandardFonts: StandardFonts2, rgb: rgb3 } = await Promise.resolve().then(() => __toESM(require_cjs()));
|
|
136607
136645
|
const doc = await PDFDocument2.load(stamped, { updateMetadata: false });
|
|
136646
|
+
step("fonts");
|
|
136608
136647
|
const helv = await doc.embedFont(StandardFonts2.Helvetica);
|
|
136609
136648
|
const pages = doc.getPages();
|
|
136610
136649
|
const COLORS = {
|
|
@@ -136615,6 +136654,7 @@ async function buildCheckPdf(stamped, entries, status, banner = true) {
|
|
|
136615
136654
|
};
|
|
136616
136655
|
const boxes = [];
|
|
136617
136656
|
for (const e4 of entries) {
|
|
136657
|
+
step("outline", e4.id);
|
|
136618
136658
|
const st = status(e4.id);
|
|
136619
136659
|
if (e4.kind === "field") {
|
|
136620
136660
|
boxes.push({ id: e4.id, page: e4.field.page, box: e4.field, st, thin: false, tagged: true });
|
|
@@ -136631,6 +136671,7 @@ async function buildCheckPdf(stamped, entries, status, banner = true) {
|
|
|
136631
136671
|
boxes.push({ id: c2.id, page: c2.field.page, box: c2.field, st, thin: true, tagged: false });
|
|
136632
136672
|
}
|
|
136633
136673
|
}
|
|
136674
|
+
step("tag");
|
|
136634
136675
|
const short = shortIds(checkTagIds(entries));
|
|
136635
136676
|
const SIZE = 5;
|
|
136636
136677
|
const rectOf = (b, pw, ph) => {
|
|
@@ -136640,47 +136681,92 @@ async function buildCheckPdf(stamped, entries, status, banner = true) {
|
|
|
136640
136681
|
};
|
|
136641
136682
|
const placedTags = /* @__PURE__ */ new Map();
|
|
136642
136683
|
const HEAD = 4;
|
|
136643
|
-
const heads = [];
|
|
136644
136684
|
const headColor = rgb3(0.15, 0.35, 0.75);
|
|
136685
|
+
const wanted = [];
|
|
136645
136686
|
for (const e4 of entries) {
|
|
136646
136687
|
if (e4.kind !== "table") continue;
|
|
136688
|
+
step("table headers", e4.id);
|
|
136647
136689
|
const g = e4.group;
|
|
136648
136690
|
const texts = (v) => Array.isArray(v) ? v : [];
|
|
136691
|
+
const lineOf = (raw) => typeof raw === "string" ? oneLine(raw) : "";
|
|
136649
136692
|
const firstOf = (key, k4) => e4.cells.filter((c2) => c2[key] === k4).sort((a, b) => key === "row" ? a.col - b.col : a.row - b.row).at(0);
|
|
136650
|
-
const
|
|
136651
|
-
|
|
136693
|
+
const want = (axis, index2, raw, cell, below) => {
|
|
136694
|
+
const text = lineOf(raw);
|
|
136695
|
+
if (!text || !cell) return;
|
|
136652
136696
|
const page = pages[cell.field.page - 1];
|
|
136653
|
-
if (
|
|
136654
|
-
const { width: pw, height: ph } = page.getSize();
|
|
136655
|
-
const cx2 = cell.field.xpct / 100 * pw;
|
|
136656
|
-
const top = ph - cell.field.ypct / 100 * ph;
|
|
136657
|
-
const w = cell.field.wpct / 100 * pw;
|
|
136658
|
-
const h = cell.field.hpct / 100 * ph;
|
|
136659
|
-
const inside = w >= 40 && h >= HEAD + 1;
|
|
136660
|
-
const room = inside ? w - 1 : prefix === "R" ? Math.min(120, cx2 - 1) : Math.max(2 * w, 30);
|
|
136661
|
-
let text = `${prefix}: ${raw.trim()}`;
|
|
136662
|
-
while (text.length > 4 && helv.widthOfTextAtSize(text, HEAD) > room) {
|
|
136663
|
-
text = `${text.slice(0, -2)}\u2026`;
|
|
136664
|
-
}
|
|
136665
|
-
const tw = helv.widthOfTextAtSize(text, HEAD);
|
|
136666
|
-
const x2 = inside ? cx2 + 0.6 : prefix === "R" ? cx2 - tw - 0.8 : cx2;
|
|
136667
|
-
const y = inside ? top - HEAD - 0.4 - below : prefix === "R" ? top - h / 2 - HEAD / 2 : top + 0.6;
|
|
136668
|
-
heads.push({ page, text, opts: { x: x2, y, size: HEAD, font: helv, color: headColor } });
|
|
136669
|
-
const taken = placedTags.get(cell.field.page) ?? [];
|
|
136670
|
-
taken.push({ x: x2, y, w: tw, h: HEAD + 0.6 });
|
|
136671
|
-
placedTags.set(cell.field.page, taken);
|
|
136697
|
+
if (page) wanted.push({ gid: e4.id, axis, index: index2, text, cell, page, below });
|
|
136672
136698
|
};
|
|
136673
136699
|
texts(g.header_rows).forEach((t, r) => {
|
|
136674
|
-
|
|
136700
|
+
want("row", r, t, firstOf("row", r), 0);
|
|
136675
136701
|
});
|
|
136676
136702
|
texts(g.header_cols).forEach((t, c2) => {
|
|
136677
136703
|
const cell = firstOf("col", c2);
|
|
136678
136704
|
const shared = cell !== void 0 && cell.col === firstOf("row", cell.row)?.col;
|
|
136679
|
-
const rowHead = cell ? texts(g.header_rows)[cell.row] :
|
|
136680
|
-
|
|
136705
|
+
const rowHead = cell ? lineOf(texts(g.header_rows)[cell.row]) : "";
|
|
136706
|
+
want("column", c2, t, cell, shared && rowHead ? HEAD + 0.6 : 0);
|
|
136681
136707
|
});
|
|
136682
136708
|
}
|
|
136709
|
+
const heads = [];
|
|
136710
|
+
const dropped = (h, e4) => `${h.gid}: ${h.axis} header ${String(h.index)} could not be drawn in the check copy: ${causeOf(e4)}`;
|
|
136711
|
+
if (wanted.length > 0) {
|
|
136712
|
+
step("fonts");
|
|
136713
|
+
const { default: fontkit } = await Promise.resolve().then(() => __toESM(require_fontkit_umd()));
|
|
136714
|
+
doc.registerFontkit(fontkit);
|
|
136715
|
+
const faces = await embedStampFaces(doc, fontkit, fonts);
|
|
136716
|
+
const unreadable = /* @__PURE__ */ new Set();
|
|
136717
|
+
for (const h of wanted) {
|
|
136718
|
+
step("table headers", h.gid);
|
|
136719
|
+
try {
|
|
136720
|
+
const { cell, page } = h;
|
|
136721
|
+
const prefix = h.axis === "row" ? "R" : "C";
|
|
136722
|
+
const { width: pw, height: ph } = page.getSize();
|
|
136723
|
+
const cx2 = cell.field.xpct / 100 * pw;
|
|
136724
|
+
const top = ph - cell.field.ypct / 100 * ph;
|
|
136725
|
+
const w = cell.field.wpct / 100 * pw;
|
|
136726
|
+
const ht = cell.field.hpct / 100 * ph;
|
|
136727
|
+
const inside = w >= 40 && ht >= HEAD + 1;
|
|
136728
|
+
const room = inside ? w - 1 : prefix === "R" ? Math.min(120, cx2 - 1) : Math.max(2 * w, 30);
|
|
136729
|
+
const chars3 = Array.from(
|
|
136730
|
+
`${prefix}: ${h.text}`,
|
|
136731
|
+
(ch) => faces.hasGlyph(ch.codePointAt(0) ?? 0) ? ch : "?"
|
|
136732
|
+
);
|
|
136733
|
+
if (chars3.join("") !== `${prefix}: ${h.text}` && !unreadable.has(h.gid)) {
|
|
136734
|
+
unreadable.add(h.gid);
|
|
136735
|
+
notes.push(
|
|
136736
|
+
`${h.gid}: the check copy cannot draw some header characters (shown as "?"); the legend's header_rows / header_cols hold the full text`
|
|
136737
|
+
);
|
|
136738
|
+
}
|
|
136739
|
+
const cut = (n) => `${chars3.slice(0, n).join("")}\u2026`;
|
|
136740
|
+
let text = chars3.join("");
|
|
136741
|
+
if (chars3.length > 4 && faces.measure(text, HEAD) > room) {
|
|
136742
|
+
let lo = 3;
|
|
136743
|
+
let hi = chars3.length - 2;
|
|
136744
|
+
while (lo < hi) {
|
|
136745
|
+
const mid = Math.ceil((lo + hi) / 2);
|
|
136746
|
+
if (faces.measure(cut(mid), HEAD) <= room) lo = mid;
|
|
136747
|
+
else hi = mid - 1;
|
|
136748
|
+
}
|
|
136749
|
+
text = cut(lo);
|
|
136750
|
+
}
|
|
136751
|
+
const tw = faces.measure(text, HEAD);
|
|
136752
|
+
const x2 = inside ? cx2 + 0.6 : prefix === "R" ? cx2 - tw - 0.8 : cx2;
|
|
136753
|
+
const y = inside ? top - HEAD - 0.4 - h.below : prefix === "R" ? top - ht / 2 - HEAD / 2 : top + 0.6;
|
|
136754
|
+
heads.push({
|
|
136755
|
+
head: h,
|
|
136756
|
+
draw: () => {
|
|
136757
|
+
faces.draw(page, text, x2, y, HEAD, headColor);
|
|
136758
|
+
}
|
|
136759
|
+
});
|
|
136760
|
+
const taken = placedTags.get(cell.field.page) ?? [];
|
|
136761
|
+
taken.push({ x: x2, y, w: tw, h: HEAD + 0.6 });
|
|
136762
|
+
placedTags.set(cell.field.page, taken);
|
|
136763
|
+
} catch (e4) {
|
|
136764
|
+
notes.push(dropped(h, e4));
|
|
136765
|
+
}
|
|
136766
|
+
}
|
|
136767
|
+
}
|
|
136683
136768
|
for (const b of boxes) {
|
|
136769
|
+
step("outline", b.id);
|
|
136684
136770
|
const page = pages[b.page - 1];
|
|
136685
136771
|
if (!page) continue;
|
|
136686
136772
|
const { width: pw, height: ph } = page.getSize();
|
|
@@ -136698,7 +136784,8 @@ async function buildCheckPdf(stamped, entries, status, banner = true) {
|
|
|
136698
136784
|
borderOpacity: 0.9
|
|
136699
136785
|
});
|
|
136700
136786
|
if (!b.tagged) continue;
|
|
136701
|
-
|
|
136787
|
+
step("tag", b.id);
|
|
136788
|
+
const tag = asciiOnly(short.get(b.id) ?? b.id);
|
|
136702
136789
|
const tw = helv.widthOfTextAtSize(tag, SIZE) + 1.6;
|
|
136703
136790
|
const th = SIZE + 1.2;
|
|
136704
136791
|
const right = x2 + w - tw;
|
|
@@ -136730,14 +136817,23 @@ async function buildCheckPdf(stamped, entries, status, banner = true) {
|
|
|
136730
136817
|
});
|
|
136731
136818
|
page.drawText(tag, { x: spot.x + 0.8, y: spot.y + 0.8, size: SIZE, font: helv, color });
|
|
136732
136819
|
}
|
|
136733
|
-
for (const h of heads)
|
|
136820
|
+
for (const h of heads) {
|
|
136821
|
+
step("table headers", h.head.gid);
|
|
136822
|
+
try {
|
|
136823
|
+
h.draw();
|
|
136824
|
+
} catch (e4) {
|
|
136825
|
+
notes.push(dropped(h.head, e4));
|
|
136826
|
+
}
|
|
136827
|
+
}
|
|
136828
|
+
step("banner");
|
|
136734
136829
|
const first = pages[0];
|
|
136735
136830
|
if (first && banner) {
|
|
136736
136831
|
const legend = "fenfill check copy: green = filled, orange = filled with a warning, red = skipped, grey = left empty. Tags are field-id prefixes.";
|
|
136737
136832
|
const { height: ph } = first.getSize();
|
|
136738
136833
|
first.drawText(legend, { x: 6, y: ph - 7, size: SIZE, font: helv, color: rgb3(0.3, 0.3, 0.35) });
|
|
136739
136834
|
}
|
|
136740
|
-
|
|
136835
|
+
step("save");
|
|
136836
|
+
return { pdf: await doc.save(), notes };
|
|
136741
136837
|
}
|
|
136742
136838
|
async function fillAgentPdf(a) {
|
|
136743
136839
|
if (!isRecord(a.render)) throw new TypeError("render must be the template's schema object");
|
|
@@ -136772,12 +136868,20 @@ async function fillAgentPdf(a) {
|
|
|
136772
136868
|
const warned = new Set(
|
|
136773
136869
|
placed.flatMap((w) => w.slice(0, w.indexOf(":")).split(" and ").map(topId))
|
|
136774
136870
|
);
|
|
136775
|
-
|
|
136776
|
-
|
|
136777
|
-
|
|
136778
|
-
|
|
136779
|
-
|
|
136780
|
-
|
|
136871
|
+
try {
|
|
136872
|
+
const built = await buildCheckPdf(
|
|
136873
|
+
pdf,
|
|
136874
|
+
m.entries,
|
|
136875
|
+
(id) => skippedIds.has(id) ? "skipped" : warned.has(id) ? "warned" : m.filledIds.has(id) ? "filled" : "empty",
|
|
136876
|
+
a.fonts,
|
|
136877
|
+
a.checkBanner !== false
|
|
136878
|
+
);
|
|
136879
|
+
res.checkPdf = built.pdf;
|
|
136880
|
+
warnings.push(...built.notes);
|
|
136881
|
+
} catch (e4) {
|
|
136882
|
+
const at = e4 instanceof CheckCopyError ? e4.at : { stage: "build" };
|
|
136883
|
+
res.checkError = { stage: at.stage, ...at.id ? { id: at.id } : {}, message: causeOf(e4) };
|
|
136884
|
+
}
|
|
136781
136885
|
}
|
|
136782
136886
|
return res;
|
|
136783
136887
|
}
|
|
@@ -137680,7 +137784,7 @@ function loadFonts(dir = defaultFontsDir()) {
|
|
|
137680
137784
|
}
|
|
137681
137785
|
|
|
137682
137786
|
// src/version.ts
|
|
137683
|
-
var VERSION = true ? "0.2.
|
|
137787
|
+
var VERSION = true ? "0.2.1" : "0.0.0-dev";
|
|
137684
137788
|
var USER_AGENT = `fenfill-mcp/${VERSION}`;
|
|
137685
137789
|
|
|
137686
137790
|
// src/fill.ts
|
|
@@ -137864,6 +137968,11 @@ function fillForbiddenError() {
|
|
|
137864
137968
|
hint: "fenfill can't fill this file; use a copy whose permissions allow form filling."
|
|
137865
137969
|
});
|
|
137866
137970
|
}
|
|
137971
|
+
function checkCopyFailed(err2) {
|
|
137972
|
+
const what = "The check copy could not be built";
|
|
137973
|
+
if (!err2) return `${what}.`;
|
|
137974
|
+
return `${what} (${[err2.stage, err2.id].filter(Boolean).join(", ")}): ${err2.message}`;
|
|
137975
|
+
}
|
|
137867
137976
|
async function checkPathFor(outputAbs, opts) {
|
|
137868
137977
|
return resolveOutputPath(outputAbs.replace(/\.pdf$/i, ".check.pdf"), opts);
|
|
137869
137978
|
}
|
|
@@ -137889,17 +137998,22 @@ async function stampAndWrite(a) {
|
|
|
137889
137998
|
await writeOutputAtomic(a.outputAbs, res.pdf, a.overwrite);
|
|
137890
137999
|
await a.cache.registerOutput(sha256Hex(res.pdf));
|
|
137891
138000
|
let checkPath;
|
|
138001
|
+
const warnings = [...res.warnings];
|
|
137892
138002
|
if (a.checkAbs && res.checkPdf) {
|
|
137893
138003
|
await writeOutputAtomic(a.checkAbs, res.checkPdf, a.overwrite);
|
|
137894
138004
|
await a.cache.registerOutput(sha256Hex(res.checkPdf));
|
|
137895
138005
|
checkPath = a.checkAbs;
|
|
138006
|
+
} else if (a.checkAbs) {
|
|
138007
|
+
warnings.push(
|
|
138008
|
+
`No check copy was written; the filled PDF is complete. ${checkCopyFailed(res.checkError)}`
|
|
138009
|
+
);
|
|
137896
138010
|
}
|
|
137897
138011
|
return {
|
|
137898
138012
|
output_path: a.outputAbs,
|
|
137899
138013
|
...checkPath ? { check_path: checkPath } : {},
|
|
137900
138014
|
filled: res.filled,
|
|
137901
138015
|
skipped: res.skipped,
|
|
137902
|
-
warnings
|
|
138016
|
+
warnings
|
|
137903
138017
|
};
|
|
137904
138018
|
}
|
|
137905
138019
|
|
|
@@ -142114,7 +142228,13 @@ async function previewPage(a) {
|
|
|
142114
142228
|
if (isFillForbiddenError(e4)) throw fillForbiddenError();
|
|
142115
142229
|
throw e4;
|
|
142116
142230
|
}
|
|
142117
|
-
if (!res.checkPdf)
|
|
142231
|
+
if (!res.checkPdf) {
|
|
142232
|
+
const err2 = res.checkError;
|
|
142233
|
+
throw new ToolError("check_copy_failed", checkCopyFailed(err2), {
|
|
142234
|
+
hint: err2?.id ? `Fix or remove ${err2.id} with edit_template, then preview again.` : "Preview again; if it persists, fill_form / fill_template still write the filled PDF, without a check copy.",
|
|
142235
|
+
details: { stage: err2?.stage, id: err2?.id }
|
|
142236
|
+
});
|
|
142237
|
+
}
|
|
142118
142238
|
const legend = legendRows(a.render, a.page);
|
|
142119
142239
|
const ids = new Set(legend.map((r) => r.id));
|
|
142120
142240
|
const skipped = res.skipped.filter((s) => ids.has(topId2(s.id)));
|
package/package.json
CHANGED