omitly-mcp 5.3.0 → 5.5.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.
@@ -0,0 +1,175 @@
1
+ /**
2
+ * omitly#1841 phase B: the writers built on `extractPagesDoc` (design 4.3).
3
+ *
4
+ * `extractPagesTo` serves `extract_pages` and `split_pdf`; `composePages` serves
5
+ * `edit_pages`. Both start from `extractPages`' default-deny preparation (pages
6
+ * not kept are neutered in the private source copy first), never from a fresh
7
+ * document with pages copied in, because that route pulls excluded pages back in
8
+ * through form widgets (the #1004 leak). Signatures are removed in the SOURCE
9
+ * before anything is copied.
10
+ */
11
+ import { PDFName, PDFNumber } from "pdf-lib";
12
+ import { LAYERS_WARNING, SIGNATURE_WARNING, clearSigFlags, scrubDestinationFields, scrubDestinationSignatures, sourceFacts, stripSignaturesFromSource, } from "./docFacts.js";
13
+ import { extractPagesDoc, openExtractionSession } from "./pageOps.js";
14
+ import { EditRefusal } from "./refusals.js";
15
+ const A4 = [595.28, 841.89];
16
+ const LETTER = [612, 792];
17
+ function isAscending(xs) {
18
+ for (let i = 1; i < xs.length; i++)
19
+ if (xs[i] <= xs[i - 1])
20
+ return false;
21
+ return true;
22
+ }
23
+ /** Shared source inspection: range check, dynamic-XFA refusal, signature removal. */
24
+ function makeInspector(zeroBasedPages, onItem) {
25
+ return (src) => {
26
+ const pageCount = src.getPageCount();
27
+ for (const p of zeroBasedPages) {
28
+ if (p >= pageCount)
29
+ throw new EditRefusal("page_out_of_range", { item: p + 1, pageCount });
30
+ }
31
+ const facts = sourceFacts(src);
32
+ if (facts.xfa === "dynamic")
33
+ throw new EditRefusal("xfa");
34
+ // Before anything is copied; see docFacts.stripSignaturesFromSource.
35
+ const signed = stripSignaturesFromSource(src);
36
+ onItem(facts, signed);
37
+ };
38
+ }
39
+ /** Turn a prepared extraction into the writer's result: lost codes, warnings, the destination
40
+ * backstop, and the save. Shared by the one-shot and the session path. */
41
+ async function finishExtraction(doc, zeroBasedPages, facts, signedInSource) {
42
+ clearSigFlags(doc);
43
+ const lost = [];
44
+ const warnings = [];
45
+ let signed = signedInSource;
46
+ if (facts?.pageLabels && !isAscending(zeroBasedPages)) {
47
+ // copyPageLabelsForExtractedPages assumes ascending order.
48
+ doc.catalog.delete(PDFName.of("PageLabels"));
49
+ lost.push("page_labels");
50
+ }
51
+ if (facts?.layers) {
52
+ lost.push("layers");
53
+ warnings.push(LAYERS_WARNING);
54
+ }
55
+ if (facts?.xfa === "static")
56
+ lost.push("xfa");
57
+ // Backstops: anything the source scrubs missed, just before the bytes are written.
58
+ scrubDestinationFields(doc);
59
+ if (scrubDestinationSignatures(doc))
60
+ signed = true;
61
+ if (signed)
62
+ warnings.push(SIGNATURE_WARNING);
63
+ const out = await doc.save();
64
+ return { bytes: out, pageCount: doc.getPageCount(), lost, warnings };
65
+ }
66
+ /** `extract_pages`: keep these pages (0-based), in this order. */
67
+ export async function extractPagesTo(bytes, zeroBasedPages) {
68
+ let facts;
69
+ let signed = false;
70
+ const doc = await extractPagesDoc(bytes, zeroBasedPages, {
71
+ preserveCatalog: true,
72
+ inspectSource: makeInspector(zeroBasedPages, (f, s) => {
73
+ facts = f;
74
+ signed = s;
75
+ }),
76
+ });
77
+ return finishExtraction(doc, zeroBasedPages, facts, signed);
78
+ }
79
+ /** `split_pdf`: parse the input ONCE, then one default-deny extraction per range (the same code as
80
+ * `extractPagesTo`, with its source mutations undone between ranges; see openExtractionSession). */
81
+ export async function openRangeExtractor(bytes) {
82
+ let facts;
83
+ let signed = false;
84
+ // Facts and the signature scrub of the SOURCE are properties of the document, not of a range:
85
+ // done once, here, before any copy. The page-range check is per range, below.
86
+ const session = await openExtractionSession(bytes, {
87
+ inspectSource: makeInspector([], (f, s) => {
88
+ facts = f;
89
+ signed = s;
90
+ }),
91
+ });
92
+ return {
93
+ async extract(zeroBasedPages) {
94
+ for (const p of zeroBasedPages) {
95
+ if (p >= session.pageCount)
96
+ throw new EditRefusal("page_out_of_range", { item: p + 1, pageCount: session.pageCount });
97
+ }
98
+ const doc = await session.extract(zeroBasedPages, { preserveCatalog: true });
99
+ return finishExtraction(doc, zeroBasedPages, facts, signed);
100
+ },
101
+ };
102
+ }
103
+ /** `edit_pages`: the final page list. */
104
+ export async function composePages(bytes, layout) {
105
+ const sources = [];
106
+ const seen = new Set();
107
+ let hasBlank = false;
108
+ for (const e of layout) {
109
+ if ("blank" in e) {
110
+ hasBlank = true;
111
+ continue;
112
+ }
113
+ if (seen.has(e.source))
114
+ throw new EditRefusal("duplicate_page", { item: e.source });
115
+ seen.add(e.source);
116
+ sources.push(e.source - 1);
117
+ }
118
+ if (sources.length === 0)
119
+ throw new EditRefusal("no_source_pages");
120
+ let facts;
121
+ let signed = false;
122
+ const doc = await extractPagesDoc(bytes, sources, {
123
+ preserveCatalog: true,
124
+ inspectSource: makeInspector(sources, (f, s) => {
125
+ facts = f;
126
+ signed = s;
127
+ }),
128
+ });
129
+ clearSigFlags(doc);
130
+ const extracted = doc.getPages(); // in `sources` order, which is list order
131
+ const echo = [];
132
+ let next = 0;
133
+ let out = 0;
134
+ for (const e of layout) {
135
+ if ("blank" in e) {
136
+ const prev = out > 0 ? doc.getPage(out - 1).getSize() : undefined;
137
+ const [w, h] = e.size === "Letter" ? LETTER : e.size === "A4" ? A4 : prev ? [prev.width, prev.height] : A4;
138
+ doc.insertPage(out, [w, h]);
139
+ echo.push({ pageNumber: out + 1, from: "blank", rotation: 0 });
140
+ }
141
+ else {
142
+ const page = extracted[next++];
143
+ const existing = page.node.Rotate()?.asNumber() ?? 0;
144
+ // Written directly: pdf-lib's setRotation throws on any non-multiple of 90,
145
+ // and some real files carry one.
146
+ const angle = (((existing + e.rotate) % 360) + 360) % 360;
147
+ if (e.rotate !== 0)
148
+ page.node.set(PDFName.of("Rotate"), PDFNumber.of(angle));
149
+ echo.push({ pageNumber: out + 1, from: e.source, rotation: angle });
150
+ }
151
+ out++;
152
+ }
153
+ const lost = [];
154
+ const warnings = [];
155
+ const reordered = !isAscending(sources);
156
+ if (facts?.pageLabels && (reordered || hasBlank)) {
157
+ // Their numbering would now be wrong.
158
+ doc.catalog.delete(PDFName.of("PageLabels"));
159
+ lost.push("page_labels");
160
+ }
161
+ if (facts?.layers) {
162
+ lost.push("layers");
163
+ warnings.push(LAYERS_WARNING);
164
+ }
165
+ if (facts?.xfa === "static")
166
+ lost.push("xfa");
167
+ scrubDestinationFields(doc);
168
+ if (scrubDestinationSignatures(doc))
169
+ signed = true;
170
+ if (signed)
171
+ warnings.push(SIGNATURE_WARNING);
172
+ const saved = await doc.save();
173
+ return { bytes: saved, pageCount: doc.getPageCount(), lost, warnings, layout: echo };
174
+ }
175
+ //# sourceMappingURL=compose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose.js","sourceRoot":"","sources":["../../src/pdf-edit/compose.ts"],"names":[],"mappings":"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"}