@f-o-t/pdf 0.4.0 → 0.4.2
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/{index-18zt1kda.js → index-jpay67x2.js} +60 -33
- package/dist/{index-18zt1kda.js.map → index-jpay67x2.js.map} +4 -4
- package/dist/{index-35skpe4f.js → index-mstpgjxs.js} +104 -27
- package/dist/index-mstpgjxs.js.map +13 -0
- package/dist/index.js +2 -2
- package/dist/plugins/editing/document.d.ts.map +1 -1
- package/dist/plugins/editing/index.js +1 -1
- package/dist/plugins/editing/page.d.ts.map +1 -1
- package/dist/plugins/editing/parser.d.ts +14 -3
- package/dist/plugins/editing/parser.d.ts.map +1 -1
- package/dist/plugins/parsing/index.js +1 -1
- package/dist/plugins/parsing/parser.d.ts.map +1 -1
- package/dist/plugins/parsing/reader.d.ts +7 -5
- package/dist/plugins/parsing/reader.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/index-35skpe4f.js.map +0 -13
|
@@ -329,11 +329,37 @@ class PDFParser {
|
|
|
329
329
|
}
|
|
330
330
|
streamDataStart++;
|
|
331
331
|
}
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
332
|
+
const lengthVal = dictionary.Length;
|
|
333
|
+
let data;
|
|
334
|
+
if (typeof lengthVal === "number") {
|
|
335
|
+
data = this.data.slice(streamDataStart, streamDataStart + lengthVal);
|
|
336
|
+
} else {
|
|
337
|
+
const marker = new TextEncoder().encode("endstream");
|
|
338
|
+
let endPos = streamDataStart;
|
|
339
|
+
while (endPos < this.data.length - marker.length) {
|
|
340
|
+
if (this.data[endPos] === marker[0]) {
|
|
341
|
+
let match = true;
|
|
342
|
+
for (let j = 1;j < marker.length; j++) {
|
|
343
|
+
if (this.data[endPos + j] !== marker[j]) {
|
|
344
|
+
match = false;
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (match)
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
endPos++;
|
|
352
|
+
}
|
|
353
|
+
let dataEnd = endPos;
|
|
354
|
+
if (dataEnd > streamDataStart && this.data[dataEnd - 1] === 10)
|
|
355
|
+
dataEnd--;
|
|
356
|
+
if (dataEnd > streamDataStart && this.data[dataEnd - 1] === 13)
|
|
357
|
+
dataEnd--;
|
|
358
|
+
data = this.data.slice(streamDataStart, dataEnd);
|
|
359
|
+
}
|
|
360
|
+
const afterStream = streamDataStart + data.length;
|
|
361
|
+
this.lexer = new PDFLexer(this.data.subarray(afterStream));
|
|
362
|
+
this.currentToken = this.lexer.nextToken();
|
|
337
363
|
while (this.currentToken.type !== "ENDSTREAM" /* ENDSTREAM */ && this.currentToken.type !== "EOF" /* EOF */) {
|
|
338
364
|
this.advance();
|
|
339
365
|
}
|
|
@@ -432,15 +458,30 @@ class NotImplementedError extends PDFError {
|
|
|
432
458
|
class PDFReader {
|
|
433
459
|
data;
|
|
434
460
|
objects = new Map;
|
|
461
|
+
xrefTable = new Map;
|
|
435
462
|
constructor(data) {
|
|
436
463
|
this.data = data;
|
|
437
464
|
}
|
|
465
|
+
resolveObject(objectNum) {
|
|
466
|
+
if (this.objects.has(objectNum))
|
|
467
|
+
return this.resolveObject(objectNum);
|
|
468
|
+
const offset = this.xrefTable.get(objectNum);
|
|
469
|
+
if (offset === undefined)
|
|
470
|
+
return;
|
|
471
|
+
try {
|
|
472
|
+
const parser = new PDFParser(this.data.subarray(offset));
|
|
473
|
+
const obj = parser.parseIndirectObject();
|
|
474
|
+
this.objects.set(objectNum, obj.value);
|
|
475
|
+
return obj.value;
|
|
476
|
+
} catch {
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
438
480
|
parse() {
|
|
439
481
|
const xrefOffset = this.findStartXRef();
|
|
440
|
-
|
|
482
|
+
this.xrefTable = this.parseXRefTable(xrefOffset);
|
|
441
483
|
const trailer = this.parseTrailer(xrefOffset);
|
|
442
484
|
const catalogRef = trailer.Root;
|
|
443
|
-
this.readObjects(xrefTable);
|
|
444
485
|
const version = this.parseVersion();
|
|
445
486
|
const pages = this.parsePages(catalogRef);
|
|
446
487
|
return {
|
|
@@ -451,17 +492,16 @@ class PDFReader {
|
|
|
451
492
|
};
|
|
452
493
|
}
|
|
453
494
|
findStartXRef() {
|
|
454
|
-
const
|
|
455
|
-
const
|
|
456
|
-
const match =
|
|
495
|
+
const tailSize = Math.min(256, this.data.length);
|
|
496
|
+
const tail = new TextDecoder().decode(this.data.subarray(this.data.length - tailSize));
|
|
497
|
+
const match = tail.match(/startxref\s+(\d+)/);
|
|
457
498
|
if (!match) {
|
|
458
499
|
throw new PDFParseError("Could not find startxref");
|
|
459
500
|
}
|
|
460
501
|
return parseInt(match[1], 10);
|
|
461
502
|
}
|
|
462
503
|
parseXRefTable(offset) {
|
|
463
|
-
const
|
|
464
|
-
const content = decoder.decode(this.data.slice(offset));
|
|
504
|
+
const content = new TextDecoder().decode(this.data.subarray(offset));
|
|
465
505
|
const lines = content.split(`
|
|
466
506
|
`);
|
|
467
507
|
const xref = new Map;
|
|
@@ -490,8 +530,7 @@ class PDFReader {
|
|
|
490
530
|
return xref;
|
|
491
531
|
}
|
|
492
532
|
parseTrailer(xrefOffset) {
|
|
493
|
-
const
|
|
494
|
-
const content = decoder.decode(this.data.slice(xrefOffset));
|
|
533
|
+
const content = new TextDecoder().decode(this.data.subarray(xrefOffset));
|
|
495
534
|
const trailerMatch = content.match(/trailer\s*<<[\s\S]*?>>/);
|
|
496
535
|
if (!trailerMatch) {
|
|
497
536
|
throw new PDFParseError("Could not find trailer");
|
|
@@ -499,29 +538,18 @@ class PDFReader {
|
|
|
499
538
|
const parser = new PDFParser(new TextEncoder().encode(trailerMatch[0].replace("trailer", "")));
|
|
500
539
|
return parser.parseValue();
|
|
501
540
|
}
|
|
502
|
-
readObjects(xrefTable) {
|
|
503
|
-
for (const [objectNum, offset] of xrefTable) {
|
|
504
|
-
try {
|
|
505
|
-
const objData = this.data.slice(offset);
|
|
506
|
-
const parser = new PDFParser(objData);
|
|
507
|
-
const obj = parser.parseIndirectObject();
|
|
508
|
-
this.objects.set(objectNum, obj.value);
|
|
509
|
-
} catch (error) {}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
541
|
parseVersion() {
|
|
513
|
-
const
|
|
514
|
-
const header = decoder.decode(this.data.slice(0, 20));
|
|
542
|
+
const header = new TextDecoder().decode(this.data.subarray(0, 20));
|
|
515
543
|
const match = header.match(/%PDF-(\d+\.\d+)/);
|
|
516
544
|
return match ? match[1] : "1.7";
|
|
517
545
|
}
|
|
518
546
|
parsePages(catalogRef) {
|
|
519
|
-
const catalog = this.
|
|
547
|
+
const catalog = this.resolveObject(catalogRef.objectNumber);
|
|
520
548
|
if (!catalog) {
|
|
521
549
|
throw new PDFParseError("Catalog not found");
|
|
522
550
|
}
|
|
523
551
|
const pagesRef = catalog.Pages;
|
|
524
|
-
const pagesTree = this.
|
|
552
|
+
const pagesTree = this.resolveObject(pagesRef.objectNumber);
|
|
525
553
|
if (!pagesTree) {
|
|
526
554
|
throw new PDFParseError("Pages tree not found");
|
|
527
555
|
}
|
|
@@ -537,7 +565,7 @@ class PDFReader {
|
|
|
537
565
|
return pages;
|
|
538
566
|
}
|
|
539
567
|
parsePage(ref) {
|
|
540
|
-
const pageDict = this.
|
|
568
|
+
const pageDict = this.resolveObject(ref.objectNumber);
|
|
541
569
|
if (!pageDict)
|
|
542
570
|
return null;
|
|
543
571
|
const mediaBox = pageDict.MediaBox;
|
|
@@ -553,11 +581,10 @@ class PDFReader {
|
|
|
553
581
|
return { ref, size, content };
|
|
554
582
|
}
|
|
555
583
|
extractText(ref) {
|
|
556
|
-
const stream = this.
|
|
584
|
+
const stream = this.resolveObject(ref.objectNumber);
|
|
557
585
|
if (!stream || !stream.data)
|
|
558
586
|
return "";
|
|
559
|
-
const
|
|
560
|
-
const content = decoder.decode(stream.data);
|
|
587
|
+
const content = new TextDecoder().decode(stream.data);
|
|
561
588
|
const texts = [];
|
|
562
589
|
const tjRegex = /\(([^)]*)\)\s*Tj/g;
|
|
563
590
|
let match;
|
|
@@ -586,4 +613,4 @@ class PDFReader {
|
|
|
586
613
|
}
|
|
587
614
|
export { PDFError, PDFParseError, PDFGenerationError, InvalidPDFObjectError, FontNotFoundError, InvalidImageError, PDFSignatureError, PDFEncryptionError, NotImplementedError, TokenType, PDFLexer, PDFParser, PDFReader };
|
|
588
615
|
|
|
589
|
-
//# debugId=
|
|
616
|
+
//# debugId=37462435C72ADD9564756E2164756E21
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
"sources": ["../src/plugins/parsing/lexer.ts", "../src/plugins/parsing/parser.ts", "../src/errors.ts", "../src/plugins/parsing/reader.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"/**\n * PDF token types\n */\nexport enum TokenType {\n // Primitives\n NUMBER = \"NUMBER\",\n STRING = \"STRING\",\n NAME = \"NAME\",\n BOOLEAN = \"BOOLEAN\",\n NULL = \"NULL\",\n\n // Delimiters\n ARRAY_START = \"ARRAY_START\", // [\n ARRAY_END = \"ARRAY_END\", // ]\n DICT_START = \"DICT_START\", // <<\n DICT_END = \"DICT_END\", // >>\n\n // Keywords\n OBJ = \"OBJ\", // obj\n ENDOBJ = \"ENDOBJ\", // endobj\n STREAM = \"STREAM\", // stream\n ENDSTREAM = \"ENDSTREAM\", // endstream\n XREF = \"XREF\", // xref\n TRAILER = \"TRAILER\", // trailer\n STARTXREF = \"STARTXREF\", // startxref\n R = \"R\", // R (reference)\n\n // Special\n EOF = \"EOF\",\n}\n\n/**\n * PDF token\n */\nexport interface Token {\n type: TokenType;\n value: any;\n position: number;\n}\n\n/**\n * PDF Lexer\n */\nexport class PDFLexer {\n private data: Uint8Array;\n private position: number = 0;\n\n constructor(data: Uint8Array) {\n this.data = data;\n }\n\n /**\n * Get next token\n */\n nextToken(): Token {\n this.skipWhitespace();\n\n if (this.position >= this.data.length) {\n return { type: TokenType.EOF, value: null, position: this.position };\n }\n\n const char = String.fromCharCode(this.data[this.position]!);\n\n // Delimiters\n if (char === \"[\") {\n this.position++;\n return { type: TokenType.ARRAY_START, value: \"[\", position: this.position - 1 };\n }\n if (char === \"]\") {\n this.position++;\n return { type: TokenType.ARRAY_END, value: \"]\", position: this.position - 1 };\n }\n if (char === \"<\" && this.peek() === \"<\") {\n this.position += 2;\n return { type: TokenType.DICT_START, value: \"<<\", position: this.position - 2 };\n }\n if (char === \">\" && this.peek() === \">\") {\n this.position += 2;\n return { type: TokenType.DICT_END, value: \">>\", position: this.position - 2 };\n }\n\n // Name (starts with /)\n if (char === \"/\") {\n return this.readName();\n }\n\n // String (starts with ()\n if (char === \"(\") {\n return this.readString();\n }\n\n // Number or keyword\n if (char === \"-\" || char === \"+\" || char === \".\" || (char >= \"0\" && char <= \"9\")) {\n return this.readNumber();\n }\n\n // Keyword or boolean\n return this.readKeyword();\n }\n\n /**\n * Peek at next character without consuming\n */\n private peek(): string {\n if (this.position + 1 >= this.data.length) return \"\";\n return String.fromCharCode(this.data[this.position + 1]!);\n }\n\n /**\n * Skip whitespace and comments\n */\n private skipWhitespace(): void {\n while (this.position < this.data.length) {\n const char = this.data[this.position]!;\n\n // Whitespace\n if (char === 0x20 || char === 0x09 || char === 0x0A || char === 0x0D || char === 0x00) {\n this.position++;\n continue;\n }\n\n // Comment (starts with %)\n if (char === 0x25) {\n while (this.position < this.data.length && this.data[this.position]! !== 0x0A && this.data[this.position]! !== 0x0D) {\n this.position++;\n }\n continue;\n }\n\n break;\n }\n }\n\n /**\n * Read a name token\n */\n private readName(): Token {\n const start = this.position;\n this.position++; // Skip /\n\n let value = \"\";\n while (this.position < this.data.length) {\n const char = String.fromCharCode(this.data[this.position]!);\n if (this.isDelimiter(char) || this.isWhitespace(this.data[this.position]!)) {\n break;\n }\n value += char;\n this.position++;\n }\n\n return { type: TokenType.NAME, value, position: start };\n }\n\n /**\n * Read a string token\n */\n private readString(): Token {\n const start = this.position;\n this.position++; // Skip (\n\n let value = \"\";\n let depth = 1;\n\n while (this.position < this.data.length && depth > 0) {\n const char = String.fromCharCode(this.data[this.position]!);\n\n if (char === \"\\\\\") {\n // Escape sequence\n this.position++;\n if (this.position < this.data.length) {\n const escaped = String.fromCharCode(this.data[this.position]!);\n value += escaped === \"n\" ? \"\\n\" : escaped === \"r\" ? \"\\r\" : escaped === \"t\" ? \"\\t\" : escaped;\n }\n } else if (char === \"(\") {\n depth++;\n value += char;\n } else if (char === \")\") {\n depth--;\n if (depth > 0) value += char;\n } else {\n value += char;\n }\n\n this.position++;\n }\n\n return { type: TokenType.STRING, value, position: start };\n }\n\n /**\n * Read a number token\n */\n private readNumber(): Token {\n const start = this.position;\n let value = \"\";\n\n while (this.position < this.data.length) {\n const char = String.fromCharCode(this.data[this.position]!);\n if (char === \"-\" || char === \"+\" || char === \".\" || (char >= \"0\" && char <= \"9\")) {\n value += char;\n this.position++;\n } else {\n break;\n }\n }\n\n return { type: TokenType.NUMBER, value: value.includes(\".\") ? parseFloat(value) : parseInt(value, 10), position: start };\n }\n\n /**\n * Read a keyword token\n */\n private readKeyword(): Token {\n const start = this.position;\n let value = \"\";\n\n while (this.position < this.data.length) {\n const char = String.fromCharCode(this.data[this.position]!);\n if (this.isDelimiter(char) || this.isWhitespace(this.data[this.position]!)) {\n break;\n }\n value += char;\n this.position++;\n }\n\n // Check for keywords\n const upper = value.toUpperCase();\n if (upper === \"OBJ\") return { type: TokenType.OBJ, value, position: start };\n if (upper === \"ENDOBJ\") return { type: TokenType.ENDOBJ, value, position: start };\n if (upper === \"STREAM\") return { type: TokenType.STREAM, value, position: start };\n if (upper === \"ENDSTREAM\") return { type: TokenType.ENDSTREAM, value, position: start };\n if (upper === \"XREF\") return { type: TokenType.XREF, value, position: start };\n if (upper === \"TRAILER\") return { type: TokenType.TRAILER, value, position: start };\n if (upper === \"STARTXREF\") return { type: TokenType.STARTXREF, value, position: start };\n if (upper === \"R\") return { type: TokenType.R, value, position: start };\n if (upper === \"TRUE\") return { type: TokenType.BOOLEAN, value: true, position: start };\n if (upper === \"FALSE\") return { type: TokenType.BOOLEAN, value: false, position: start };\n if (upper === \"NULL\") return { type: TokenType.NULL, value: null, position: start };\n\n // Unknown keyword - treat as name without /\n return { type: TokenType.NAME, value, position: start };\n }\n\n /**\n * Check if character is delimiter\n */\n private isDelimiter(char: string): boolean {\n return [\"(\", \")\", \"<\", \">\", \"[\", \"]\", \"{\", \"}\", \"/\", \"%\"].includes(char);\n }\n\n /**\n * Check if byte is whitespace\n */\n private isWhitespace(byte: number): boolean {\n return byte === 0x20 || byte === 0x09 || byte === 0x0A || byte === 0x0D || byte === 0x00;\n }\n}\n",
|
|
6
|
-
"// @ts-nocheck\nimport { PDFLexer, TokenType, type Token } from \"./lexer.ts\";\nimport type { PDFValue, PDFDictionary, PDFArray, PDFRef, PDFStream } from \"../../types.ts\";\nimport { createDictionary, createArray, createRef, createName, createStream } from \"../../core/objects.ts\";\n\n/**\n * PDF Parser\n */\nexport class PDFParser {\n private lexer: PDFLexer;\n private currentToken: Token;\n private nextToken: Token | null = null;\n private data: Uint8Array;\n\n constructor(data: Uint8Array) {\n this.data = data;\n this.lexer = new PDFLexer(data);\n this.currentToken = this.lexer.nextToken();\n }\n\n /**\n * Parse a PDF value\n */\n parseValue(): PDFValue {\n switch (this.currentToken.type) {\n case TokenType.NUMBER:\n return this.parseNumberOrRef();\n case TokenType.STRING:\n return this.parseString();\n case TokenType.NAME:\n return this.parseName();\n case TokenType.BOOLEAN:\n return this.parseBoolean();\n case TokenType.NULL:\n return this.parseNull();\n case TokenType.ARRAY_START:\n return this.parseArray();\n case TokenType.DICT_START:\n return this.parseDictionary();\n default:\n throw new Error(`Unexpected token: ${this.currentToken.type}`);\n }\n }\n\n /**\n * Parse number or reference (number number R)\n */\n private parseNumberOrRef(): number | PDFRef {\n const first = this.currentToken.value as number;\n this.advance();\n\n // Check if this is a reference (two numbers followed by R)\n if (this.currentToken.type === TokenType.NUMBER) {\n const second = this.currentToken.value as number;\n this.advance();\n\n if ((this.currentToken.type as any) === TokenType.R) {\n this.advance();\n return createRef(first, second);\n }\n\n // Not a reference - we consumed the second number, need to put it back\n // Put the current token (third token) into nextToken buffer\n // Then restore second number as current token\n const thirdToken = this.currentToken;\n this.currentToken = { type: TokenType.NUMBER, value: second, position: 0 };\n this.nextToken = thirdToken;\n return first;\n }\n\n return first;\n }\n\n /**\n * Parse string\n */\n private parseString(): string {\n const value = this.currentToken.value as string;\n this.advance();\n return value;\n }\n\n /**\n * Parse name\n */\n private parseName(): PDFValue {\n const value = this.currentToken.value as string;\n this.advance();\n return createName(value);\n }\n\n /**\n * Parse boolean\n */\n private parseBoolean(): boolean {\n const value = this.currentToken.value as boolean;\n this.advance();\n return value;\n }\n\n /**\n * Parse null\n */\n private parseNull(): null {\n this.advance();\n return null;\n }\n\n /**\n * Parse array\n */\n private parseArray(): PDFArray {\n this.advance(); // Skip [\n const values: PDFValue[] = [];\n\n while (this.currentToken.type !== TokenType.ARRAY_END) {\n if (this.currentToken.type === TokenType.EOF) {\n throw new Error(\"Unexpected EOF in array\");\n }\n values.push(this.parseValue());\n }\n\n this.advance(); // Skip ]\n return createArray(values);\n }\n\n /**\n * Parse dictionary\n */\n private parseDictionary(): PDFDictionary {\n this.advance(); // Skip <<\n const entries: Record<string, PDFValue> = {};\n\n while (this.currentToken.type !== TokenType.DICT_END) {\n if (this.currentToken.type === TokenType.EOF) {\n throw new Error(\"Unexpected EOF in dictionary\");\n }\n\n // Key must be a name\n if (this.currentToken.type !== TokenType.NAME) {\n throw new Error(`Expected name in dictionary, got ${this.currentToken.type}`);\n }\n const key = this.currentToken.value as string;\n this.advance();\n\n // Value\n const value = this.parseValue();\n entries[key] = value;\n }\n\n this.advance(); // Skip >>\n return createDictionary(entries);\n }\n\n /**\n * Parse indirect object\n */\n parseIndirectObject(): { ref: PDFRef; value: PDFValue } {\n // Parse: objectNumber generation obj\n if (this.currentToken.type !== TokenType.NUMBER) {\n throw new Error(\"Expected object number\");\n }\n const objectNumber = this.currentToken.value as number;\n this.advance();\n\n if (this.currentToken.type !== TokenType.NUMBER) {\n throw new Error(\"Expected generation number\");\n }\n const generation = this.currentToken.value as number;\n this.advance();\n\n if ((this.currentToken.type as any) !== TokenType.OBJ) {\n throw new Error(\"Expected 'obj' keyword\");\n }\n this.advance();\n\n // Parse object value\n let value: PDFValue = this.parseValue();\n\n // Check for stream\n if (this.currentToken.type === TokenType.STREAM) {\n value = this.parseStream(value as PDFDictionary);\n }\n\n // Expect endobj\n if (this.currentToken.type !== TokenType.ENDOBJ) {\n throw new Error(\"Expected 'endobj' keyword\");\n }\n this.advance();\n\n return {\n ref: createRef(objectNumber, generation),\n value,\n };\n }\n\n /**\n * Parse stream (dictionary already parsed)\n */\n private parseStream(dictionary: PDFDictionary): PDFStream {\n // Get current position where 'stream' keyword is\n const streamKeywordPos = this.currentToken.position;\n this.advance(); // Skip 'stream'\n\n // Find the actual start of stream data (after 'stream' keyword and newline)\n // The stream keyword is followed by either \\n or \\r\\n\n let streamDataStart = streamKeywordPos + 6; // 'stream' is 6 characters\n \n // Skip the newline after 'stream'\n while (streamDataStart < this.data.length) {\n const byte = this.data[streamDataStart];\n if (byte === 0x0D || byte === 0x0A) { // \\r or \\n\n streamDataStart++;\n // Handle \\r\\n\n if (byte === 0x0D && this.data[streamDataStart] === 0x0A) {\n streamDataStart++;\n }\n break;\n }\n streamDataStart++;\n }\n\n // Get stream length\n const
|
|
6
|
+
"// @ts-nocheck\nimport { PDFLexer, TokenType, type Token } from \"./lexer.ts\";\nimport type { PDFValue, PDFDictionary, PDFArray, PDFRef, PDFStream } from \"../../types.ts\";\nimport { createDictionary, createArray, createRef, createName, createStream } from \"../../core/objects.ts\";\n\n/**\n * PDF Parser\n */\nexport class PDFParser {\n private lexer: PDFLexer;\n private currentToken: Token;\n private nextToken: Token | null = null;\n private data: Uint8Array;\n\n constructor(data: Uint8Array) {\n this.data = data;\n this.lexer = new PDFLexer(data);\n this.currentToken = this.lexer.nextToken();\n }\n\n /**\n * Parse a PDF value\n */\n parseValue(): PDFValue {\n switch (this.currentToken.type) {\n case TokenType.NUMBER:\n return this.parseNumberOrRef();\n case TokenType.STRING:\n return this.parseString();\n case TokenType.NAME:\n return this.parseName();\n case TokenType.BOOLEAN:\n return this.parseBoolean();\n case TokenType.NULL:\n return this.parseNull();\n case TokenType.ARRAY_START:\n return this.parseArray();\n case TokenType.DICT_START:\n return this.parseDictionary();\n default:\n throw new Error(`Unexpected token: ${this.currentToken.type}`);\n }\n }\n\n /**\n * Parse number or reference (number number R)\n */\n private parseNumberOrRef(): number | PDFRef {\n const first = this.currentToken.value as number;\n this.advance();\n\n // Check if this is a reference (two numbers followed by R)\n if (this.currentToken.type === TokenType.NUMBER) {\n const second = this.currentToken.value as number;\n this.advance();\n\n if ((this.currentToken.type as any) === TokenType.R) {\n this.advance();\n return createRef(first, second);\n }\n\n // Not a reference - we consumed the second number, need to put it back\n // Put the current token (third token) into nextToken buffer\n // Then restore second number as current token\n const thirdToken = this.currentToken;\n this.currentToken = { type: TokenType.NUMBER, value: second, position: 0 };\n this.nextToken = thirdToken;\n return first;\n }\n\n return first;\n }\n\n /**\n * Parse string\n */\n private parseString(): string {\n const value = this.currentToken.value as string;\n this.advance();\n return value;\n }\n\n /**\n * Parse name\n */\n private parseName(): PDFValue {\n const value = this.currentToken.value as string;\n this.advance();\n return createName(value);\n }\n\n /**\n * Parse boolean\n */\n private parseBoolean(): boolean {\n const value = this.currentToken.value as boolean;\n this.advance();\n return value;\n }\n\n /**\n * Parse null\n */\n private parseNull(): null {\n this.advance();\n return null;\n }\n\n /**\n * Parse array\n */\n private parseArray(): PDFArray {\n this.advance(); // Skip [\n const values: PDFValue[] = [];\n\n while (this.currentToken.type !== TokenType.ARRAY_END) {\n if (this.currentToken.type === TokenType.EOF) {\n throw new Error(\"Unexpected EOF in array\");\n }\n values.push(this.parseValue());\n }\n\n this.advance(); // Skip ]\n return createArray(values);\n }\n\n /**\n * Parse dictionary\n */\n private parseDictionary(): PDFDictionary {\n this.advance(); // Skip <<\n const entries: Record<string, PDFValue> = {};\n\n while (this.currentToken.type !== TokenType.DICT_END) {\n if (this.currentToken.type === TokenType.EOF) {\n throw new Error(\"Unexpected EOF in dictionary\");\n }\n\n // Key must be a name\n if (this.currentToken.type !== TokenType.NAME) {\n throw new Error(`Expected name in dictionary, got ${this.currentToken.type}`);\n }\n const key = this.currentToken.value as string;\n this.advance();\n\n // Value\n const value = this.parseValue();\n entries[key] = value;\n }\n\n this.advance(); // Skip >>\n return createDictionary(entries);\n }\n\n /**\n * Parse indirect object\n */\n parseIndirectObject(): { ref: PDFRef; value: PDFValue } {\n // Parse: objectNumber generation obj\n if (this.currentToken.type !== TokenType.NUMBER) {\n throw new Error(\"Expected object number\");\n }\n const objectNumber = this.currentToken.value as number;\n this.advance();\n\n if (this.currentToken.type !== TokenType.NUMBER) {\n throw new Error(\"Expected generation number\");\n }\n const generation = this.currentToken.value as number;\n this.advance();\n\n if ((this.currentToken.type as any) !== TokenType.OBJ) {\n throw new Error(\"Expected 'obj' keyword\");\n }\n this.advance();\n\n // Parse object value\n let value: PDFValue = this.parseValue();\n\n // Check for stream\n if (this.currentToken.type === TokenType.STREAM) {\n value = this.parseStream(value as PDFDictionary);\n }\n\n // Expect endobj\n if (this.currentToken.type !== TokenType.ENDOBJ) {\n throw new Error(\"Expected 'endobj' keyword\");\n }\n this.advance();\n\n return {\n ref: createRef(objectNumber, generation),\n value,\n };\n }\n\n /**\n * Parse stream (dictionary already parsed)\n */\n private parseStream(dictionary: PDFDictionary): PDFStream {\n // Get current position where 'stream' keyword is\n const streamKeywordPos = this.currentToken.position;\n this.advance(); // Skip 'stream'\n\n // Find the actual start of stream data (after 'stream' keyword and newline)\n // The stream keyword is followed by either \\n or \\r\\n\n let streamDataStart = streamKeywordPos + 6; // 'stream' is 6 characters\n \n // Skip the newline after 'stream'\n while (streamDataStart < this.data.length) {\n const byte = this.data[streamDataStart];\n if (byte === 0x0D || byte === 0x0A) { // \\r or \\n\n streamDataStart++;\n // Handle \\r\\n\n if (byte === 0x0D && this.data[streamDataStart] === 0x0A) {\n streamDataStart++;\n }\n break;\n }\n streamDataStart++;\n }\n\n // Get stream length — may be a direct number or an indirect reference\n const lengthVal = dictionary.Length;\n let data: Uint8Array;\n\n if (typeof lengthVal === \"number\") {\n // Direct length: slice exactly\n data = this.data.slice(streamDataStart, streamDataStart + lengthVal);\n } else {\n // Indirect reference or missing — scan raw bytes for 'endstream' marker\n // instead of tokenizing binary data (which freezes the lexer)\n const marker = new TextEncoder().encode(\"endstream\");\n let endPos = streamDataStart;\n while (endPos < this.data.length - marker.length) {\n if (this.data[endPos] === marker[0]) {\n let match = true;\n for (let j = 1; j < marker.length; j++) {\n if (this.data[endPos + j] !== marker[j]) { match = false; break; }\n }\n if (match) break;\n }\n endPos++;\n }\n // Trim trailing whitespace (\\r\\n or \\n before endstream)\n let dataEnd = endPos;\n if (dataEnd > streamDataStart && this.data[dataEnd - 1] === 0x0A) dataEnd--;\n if (dataEnd > streamDataStart && this.data[dataEnd - 1] === 0x0D) dataEnd--;\n data = this.data.slice(streamDataStart, dataEnd);\n }\n\n // Skip past stream data — create a new lexer starting after the stream\n // to avoid tokenizing binary content byte-by-byte\n const afterStream = streamDataStart + data.length;\n this.lexer = new PDFLexer(this.data.subarray(afterStream));\n this.currentToken = this.lexer.nextToken();\n\n // Skip any whitespace tokens until we hit endstream\n while (this.currentToken.type !== TokenType.ENDSTREAM && this.currentToken.type !== TokenType.EOF) {\n this.advance();\n }\n\n if (this.currentToken.type !== TokenType.ENDSTREAM) {\n throw new Error(\"Expected 'endstream' keyword\");\n }\n this.advance();\n\n return createStream(data, dictionary);\n }\n\n /**\n * Advance to next token\n */\n private advance(): void {\n if (this.nextToken !== null) {\n this.currentToken = this.nextToken;\n this.nextToken = null;\n } else {\n this.currentToken = this.lexer.nextToken();\n }\n }\n\n /**\n * Check if more tokens available\n */\n hasMore(): boolean {\n return this.currentToken.type !== TokenType.EOF;\n }\n}\n",
|
|
7
7
|
"/**\n * Base error class for all PDF errors\n */\nexport class PDFError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PDFError\";\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Error thrown when PDF parsing fails\n */\nexport class PDFParseError extends PDFError {\n constructor(\n message: string,\n public readonly offset?: number,\n ) {\n super(message);\n this.name = \"PDFParseError\";\n }\n}\n\n/**\n * Error thrown when PDF generation fails\n */\nexport class PDFGenerationError extends PDFError {\n constructor(message: string) {\n super(message);\n this.name = \"PDFGenerationError\";\n }\n}\n\n/**\n * Error thrown when PDF object is invalid\n */\nexport class InvalidPDFObjectError extends PDFError {\n constructor(\n public readonly objectType: string,\n reason: string,\n ) {\n super(`Invalid ${objectType}: ${reason}`);\n this.name = \"InvalidPDFObjectError\";\n }\n}\n\n/**\n * Error thrown when font is not found\n */\nexport class FontNotFoundError extends PDFError {\n constructor(public readonly fontName: string) {\n super(`Font not found: ${fontName}`);\n this.name = \"FontNotFoundError\";\n }\n}\n\n/**\n * Error thrown when image is invalid\n */\nexport class InvalidImageError extends PDFError {\n constructor(reason: string) {\n super(`Invalid image: ${reason}`);\n this.name = \"InvalidImageError\";\n }\n}\n\n/**\n * Error thrown when PDF signature fails\n */\nexport class PDFSignatureError extends PDFError {\n constructor(reason: string) {\n super(`PDF signature error: ${reason}`);\n this.name = \"PDFSignatureError\";\n }\n}\n\n/**\n * Error thrown when PDF encryption fails\n */\nexport class PDFEncryptionError extends PDFError {\n constructor(reason: string) {\n super(`PDF encryption error: ${reason}`);\n this.name = \"PDFEncryptionError\";\n }\n}\n\n/**\n * Error thrown when required feature is not implemented\n */\nexport class NotImplementedError extends PDFError {\n constructor(feature: string) {\n super(`Feature not yet implemented: ${feature}`);\n this.name = \"NotImplementedError\";\n }\n}\n",
|
|
8
|
-
"import { PDFParser } from \"./parser.ts\";\nimport type { PDFDictionary, PDFRef, PDFArray } from \"../../types.ts\";\nimport { PDFParseError } from \"../../errors.ts\";\n\n/**\n * Parsed PDF Document\n */\nexport interface ParsedPDF {\n version: string;\n catalog: PDFRef;\n pages: ParsedPDFPage[];\n objects: Map<number, any>;\n}\n\n/**\n * Parsed PDF Page\n */\nexport interface ParsedPDFPage {\n ref: PDFRef;\n size: { width: number; height: number };\n content: string;\n}\n\n/**\n * PDF Reader - reads and parses existing PDFs\n */\nexport class PDFReader {\n private data: Uint8Array;\n private objects: Map<number, any> = new Map();\n\n constructor(data: Uint8Array) {\n this.data = data;\n }\n\n /**\n * Parse PDF file\n */\n parse(): ParsedPDF {\n // 1. Find and parse xref table\n const xrefOffset = this.findStartXRef();\n
|
|
8
|
+
"import { PDFParser } from \"./parser.ts\";\nimport type { PDFDictionary, PDFRef, PDFArray } from \"../../types.ts\";\nimport { PDFParseError } from \"../../errors.ts\";\n\n/**\n * Parsed PDF Document\n */\nexport interface ParsedPDF {\n version: string;\n catalog: PDFRef;\n pages: ParsedPDFPage[];\n objects: Map<number, any>;\n}\n\n/**\n * Parsed PDF Page\n */\nexport interface ParsedPDFPage {\n ref: PDFRef;\n size: { width: number; height: number };\n content: string;\n}\n\n/**\n * PDF Reader - reads and parses existing PDFs\n */\nexport class PDFReader {\n private data: Uint8Array;\n private objects: Map<number, any> = new Map();\n private xrefTable: Map<number, number> = new Map();\n\n constructor(data: Uint8Array) {\n this.data = data;\n }\n\n /**\n * Lazily resolve an object by number — parses on first access.\n */\n private resolveObject(objectNum: number): any {\n if (this.objects.has(objectNum)) return this.resolveObject(objectNum);\n const offset = this.xrefTable.get(objectNum);\n if (offset === undefined) return undefined;\n try {\n const parser = new PDFParser(this.data.subarray(offset));\n const obj = parser.parseIndirectObject();\n this.objects.set(objectNum, obj.value);\n return obj.value;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Parse PDF file\n */\n parse(): ParsedPDF {\n // 1. Find and parse xref table\n const xrefOffset = this.findStartXRef();\n this.xrefTable = this.parseXRefTable(xrefOffset);\n\n // 2. Parse trailer\n const trailer = this.parseTrailer(xrefOffset);\n const catalogRef = trailer.Root as PDFRef;\n\n // 3. Get PDF version from header\n const version = this.parseVersion();\n\n // 4. Parse pages (objects are resolved lazily on demand)\n const pages = this.parsePages(catalogRef);\n\n return {\n version,\n catalog: catalogRef,\n pages,\n objects: this.objects,\n };\n }\n\n /**\n * Find startxref offset by scanning backwards from EOF.\n * Only decodes the last 256 bytes instead of the entire PDF.\n */\n private findStartXRef(): number {\n const tailSize = Math.min(256, this.data.length);\n const tail = new TextDecoder().decode(\n this.data.subarray(this.data.length - tailSize),\n );\n const match = tail.match(/startxref\\s+(\\d+)/);\n if (!match) {\n throw new PDFParseError(\"Could not find startxref\");\n }\n return parseInt(match[1]!, 10);\n }\n\n /**\n * Parse xref table\n */\n private parseXRefTable(offset: number): Map<number, number> {\n const content = new TextDecoder().decode(this.data.subarray(offset));\n const lines = content.split(\"\\n\");\n\n const xref = new Map<number, number>();\n let i = 0;\n\n // Skip \"xref\" keyword\n while (i < lines.length && !lines[i]!.trim().startsWith(\"xref\")) i++;\n i++;\n\n // Parse subsections\n while (i < lines.length && !lines[i]!.trim().startsWith(\"trailer\")) {\n const subsection = lines[i]!.trim().split(/\\s+/);\n if (subsection.length === 2) {\n const start = parseInt(subsection[0]!, 10);\n const count = parseInt(subsection[1]!, 10);\n i++;\n\n // Parse entries\n for (let j = 0; j < count; j++) {\n const entry = lines[i]!.trim().split(/\\s+/);\n if (entry.length >= 3 && entry[2] === \"n\") {\n const offset = parseInt(entry[0]!, 10);\n xref.set(start + j, offset);\n }\n i++;\n }\n } else {\n i++;\n }\n }\n\n return xref;\n }\n\n /**\n * Parse trailer dictionary\n */\n private parseTrailer(xrefOffset: number): PDFDictionary {\n const content = new TextDecoder().decode(this.data.subarray(xrefOffset));\n const trailerMatch = content.match(/trailer\\s*<<[\\s\\S]*?>>/);\n if (!trailerMatch) {\n throw new PDFParseError(\"Could not find trailer\");\n }\n\n const parser = new PDFParser(new TextEncoder().encode(trailerMatch[0].replace(\"trailer\", \"\")));\n return parser.parseValue() as PDFDictionary;\n }\n\n /**\n * Parse PDF version from header\n */\n private parseVersion(): string {\n const header = new TextDecoder().decode(this.data.subarray(0, 20));\n const match = header.match(/%PDF-(\\d+\\.\\d+)/);\n return match ? match[1]! : \"1.7\";\n }\n\n /**\n * Parse pages from catalog\n */\n private parsePages(catalogRef: PDFRef): ParsedPDFPage[] {\n const catalog = this.resolveObject(catalogRef.objectNumber) as PDFDictionary;\n if (!catalog) {\n throw new PDFParseError(\"Catalog not found\");\n }\n\n const pagesRef = catalog.Pages as PDFRef;\n const pagesTree = this.resolveObject(pagesRef.objectNumber) as PDFDictionary;\n if (!pagesTree) {\n throw new PDFParseError(\"Pages tree not found\");\n }\n\n const kids = pagesTree.Kids as PDFArray;\n const pages: ParsedPDFPage[] = [];\n\n for (const kidRef of kids) {\n if (kidRef != null && typeof kidRef === \"object\" && \"objectNumber\" in kidRef) {\n const page = this.parsePage(kidRef as PDFRef);\n if (page) pages.push(page);\n }\n }\n\n return pages;\n }\n\n /**\n * Parse a single page\n */\n private parsePage(ref: PDFRef): ParsedPDFPage | null {\n const pageDict = this.resolveObject(ref.objectNumber) as PDFDictionary;\n if (!pageDict) return null;\n\n const mediaBox = pageDict.MediaBox as PDFArray;\n const size = {\n width: mediaBox[2] as number,\n height: mediaBox[3] as number,\n };\n\n // Extract content\n let content = \"\";\n const contentsRef = pageDict.Contents as PDFRef;\n if (contentsRef && typeof contentsRef === \"object\" && \"objectNumber\" in contentsRef) {\n content = this.extractText(contentsRef);\n }\n\n return { ref, size, content };\n }\n\n /**\n * Extract text from content stream\n */\n private extractText(ref: PDFRef): string {\n const stream = this.resolveObject(ref.objectNumber);\n if (!stream || !stream.data) return \"\";\n\n const content = new TextDecoder().decode(stream.data);\n\n const texts: string[] = [];\n\n // Match (text) Tj — single string show\n const tjRegex = /\\(([^)]*)\\)\\s*Tj/g;\n let match;\n while ((match = tjRegex.exec(content)) !== null) {\n texts.push(match[1]!);\n }\n\n // Match [...] TJ — array show (mix of strings and kerning numbers)\n const tjArrayRegex = /\\[((?:[^[\\]]*?))\\]\\s*TJ/gi;\n while ((match = tjArrayRegex.exec(content)) !== null) {\n const arrayContent = match[1]!;\n const stringParts: string[] = [];\n const partRegex = /\\(([^)]*)\\)/g;\n let partMatch;\n while ((partMatch = partRegex.exec(arrayContent)) !== null) {\n stringParts.push(partMatch[1]!);\n }\n if (stringParts.length > 0) {\n texts.push(stringParts.join(\"\"));\n }\n }\n\n // Match ' and \" operators (move to next line and show)\n const quoteRegex = /\\(([^)]*)\\)\\s*['\"]/g;\n while ((match = quoteRegex.exec(content)) !== null) {\n texts.push(match[1]!);\n }\n\n return texts.join(\" \");\n }\n}\n"
|
|
9
9
|
],
|
|
10
|
-
"mappings": "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",
|
|
11
|
-
"debugId": "
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "37462435C72ADD9564756E2164756E21",
|
|
12
12
|
"names": []
|
|
13
13
|
}
|
|
@@ -41,13 +41,34 @@ function parseTrailer(pdfStr) {
|
|
|
41
41
|
prevXref: prevMatch ? parseInt(prevMatch[1], 10) : findStartXref(pdfStr)
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
-
function
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
function buildObjectIndex(pdfStr) {
|
|
45
|
+
const index = new Map;
|
|
46
|
+
const regex = /(?:^|\s)(\d+)\s+0\s+obj/gm;
|
|
47
|
+
let m;
|
|
48
|
+
while ((m = regex.exec(pdfStr)) !== null) {
|
|
49
|
+
const objNum = parseInt(m[1], 10);
|
|
50
|
+
if (!index.has(objNum)) {
|
|
51
|
+
index.set(objNum, m.index + m[0].length);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return index;
|
|
55
|
+
}
|
|
56
|
+
function extractObjectDictContent(pdfStr, objNum, objIndex) {
|
|
57
|
+
let searchStart;
|
|
58
|
+
if (objIndex) {
|
|
59
|
+
const pos = objIndex.get(objNum);
|
|
60
|
+
if (pos === undefined) {
|
|
61
|
+
throw new Error(`Cannot find object ${objNum} in PDF`);
|
|
62
|
+
}
|
|
63
|
+
searchStart = pos;
|
|
64
|
+
} else {
|
|
65
|
+
const objRegex = new RegExp(`(?:^|\\s)${objNum}\\s+0\\s+obj`, "m");
|
|
66
|
+
const match = pdfStr.match(objRegex);
|
|
67
|
+
if (!match || match.index === undefined) {
|
|
68
|
+
throw new Error(`Cannot find object ${objNum} in PDF`);
|
|
69
|
+
}
|
|
70
|
+
searchStart = match.index + match[0].length;
|
|
49
71
|
}
|
|
50
|
-
const searchStart = match.index + match[0].length;
|
|
51
72
|
const dictStart = pdfStr.indexOf("<<", searchStart);
|
|
52
73
|
if (dictStart === -1 || dictStart > searchStart + 200) {
|
|
53
74
|
throw new Error(`Cannot find dictionary start for object ${objNum}`);
|
|
@@ -58,19 +79,19 @@ function extractObjectDictContent(pdfStr, objNum) {
|
|
|
58
79
|
}
|
|
59
80
|
return pdfStr.slice(dictStart + 2, dictEnd);
|
|
60
81
|
}
|
|
61
|
-
function
|
|
62
|
-
const rootContent = extractObjectDictContent(pdfStr, rootNum);
|
|
82
|
+
function findPageObjectsIndexed(pdfStr, rootNum, objIndex) {
|
|
83
|
+
const rootContent = extractObjectDictContent(pdfStr, rootNum, objIndex);
|
|
63
84
|
const pagesMatch = rootContent.match(/\/Pages\s+(\d+)\s+\d+\s+R/);
|
|
64
85
|
if (!pagesMatch)
|
|
65
86
|
throw new Error("Cannot find Pages ref in Root catalog");
|
|
66
87
|
const pagesNum = parseInt(pagesMatch[1], 10);
|
|
67
|
-
return
|
|
88
|
+
return collectPageLeafsIndexed(pdfStr, pagesNum, new Set, objIndex);
|
|
68
89
|
}
|
|
69
|
-
function
|
|
90
|
+
function collectPageLeafsIndexed(pdfStr, objNum, visited, objIndex) {
|
|
70
91
|
if (visited.has(objNum))
|
|
71
92
|
return [];
|
|
72
93
|
visited.add(objNum);
|
|
73
|
-
const content = extractObjectDictContent(pdfStr, objNum);
|
|
94
|
+
const content = extractObjectDictContent(pdfStr, objNum, objIndex);
|
|
74
95
|
const typeMatch = content.match(/\/Type\s+\/(\w+)/);
|
|
75
96
|
if (typeMatch?.[1] === "Page") {
|
|
76
97
|
return [objNum];
|
|
@@ -87,16 +108,16 @@ function collectPageLeafs(pdfStr, objNum, visited) {
|
|
|
87
108
|
}
|
|
88
109
|
const pages = [];
|
|
89
110
|
for (const ref of refs) {
|
|
90
|
-
pages.push(...
|
|
111
|
+
pages.push(...collectPageLeafsIndexed(pdfStr, ref, visited, objIndex));
|
|
91
112
|
}
|
|
92
113
|
return pages;
|
|
93
114
|
}
|
|
94
|
-
function getMediaBox(pdfStr, pageObjNum) {
|
|
115
|
+
function getMediaBox(pdfStr, pageObjNum, objIndex) {
|
|
95
116
|
const visited = new Set;
|
|
96
117
|
let objNum = pageObjNum;
|
|
97
118
|
while (objNum !== null && !visited.has(objNum)) {
|
|
98
119
|
visited.add(objNum);
|
|
99
|
-
const content = extractObjectDictContent(pdfStr, objNum);
|
|
120
|
+
const content = extractObjectDictContent(pdfStr, objNum, objIndex);
|
|
100
121
|
const mediaBoxMatch = content.match(/\/MediaBox\s*\[\s*([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s*\]/);
|
|
101
122
|
if (mediaBoxMatch) {
|
|
102
123
|
return [
|
|
@@ -114,13 +135,14 @@ function getMediaBox(pdfStr, pageObjNum) {
|
|
|
114
135
|
function parsePdfStructure(pdfStr) {
|
|
115
136
|
const xrefOffset = findStartXref(pdfStr);
|
|
116
137
|
const trailer = parseTrailer(pdfStr);
|
|
117
|
-
const
|
|
138
|
+
const objIndex = buildObjectIndex(pdfStr);
|
|
139
|
+
const rootContent = extractObjectDictContent(pdfStr, trailer.root, objIndex);
|
|
118
140
|
const pagesMatch = rootContent.match(/\/Pages\s+(\d+)\s+\d+\s+R/);
|
|
119
141
|
if (!pagesMatch)
|
|
120
142
|
throw new Error("Cannot find Pages ref in Root catalog");
|
|
121
143
|
const pagesNum = parseInt(pagesMatch[1], 10);
|
|
122
|
-
const pageNums =
|
|
123
|
-
const pageDictContents = pageNums.map((pn) => extractObjectDictContent(pdfStr, pn));
|
|
144
|
+
const pageNums = findPageObjectsIndexed(pdfStr, trailer.root, objIndex);
|
|
145
|
+
const pageDictContents = pageNums.map((pn) => extractObjectDictContent(pdfStr, pn, objIndex));
|
|
124
146
|
return {
|
|
125
147
|
xrefOffset,
|
|
126
148
|
rootNum: trailer.root,
|
|
@@ -129,7 +151,8 @@ function parsePdfStructure(pdfStr) {
|
|
|
129
151
|
pagesNum,
|
|
130
152
|
pageNums,
|
|
131
153
|
rootDictContent: rootContent,
|
|
132
|
-
pageDictContents
|
|
154
|
+
pageDictContents,
|
|
155
|
+
objIndex
|
|
133
156
|
};
|
|
134
157
|
}
|
|
135
158
|
function findMatchingDictEnd(str, startPos) {
|
|
@@ -184,7 +207,7 @@ function findMatchingArrayEnd(str, startPos) {
|
|
|
184
207
|
}
|
|
185
208
|
return -1;
|
|
186
209
|
}
|
|
187
|
-
function parseResourcesDict(pageContent, pdfStr) {
|
|
210
|
+
function parseResourcesDict(pageContent, pdfStr, objIndex) {
|
|
188
211
|
const result = {};
|
|
189
212
|
const inlineMatch = pageContent.match(/\/Resources\s*<</);
|
|
190
213
|
if (inlineMatch) {
|
|
@@ -200,7 +223,7 @@ function parseResourcesDict(pageContent, pdfStr) {
|
|
|
200
223
|
const refMatch = pageContent.match(/\/Resources\s+(\d+)\s+\d+\s+R/);
|
|
201
224
|
if (refMatch) {
|
|
202
225
|
const objNum = parseInt(refMatch[1], 10);
|
|
203
|
-
const objContent = extractObjectDictContent(pdfStr, objNum);
|
|
226
|
+
const objContent = extractObjectDictContent(pdfStr, objNum, objIndex);
|
|
204
227
|
return parseResourceEntries(objContent);
|
|
205
228
|
}
|
|
206
229
|
return result;
|
|
@@ -280,6 +303,55 @@ function parseResourceEntries(content) {
|
|
|
280
303
|
}
|
|
281
304
|
|
|
282
305
|
// src/plugins/editing/page.ts
|
|
306
|
+
function toWinAnsi(text) {
|
|
307
|
+
let out = "";
|
|
308
|
+
for (let i = 0;i < text.length; i++) {
|
|
309
|
+
const code = text.charCodeAt(i);
|
|
310
|
+
let byte;
|
|
311
|
+
if (code < 128) {
|
|
312
|
+
byte = code;
|
|
313
|
+
} else {
|
|
314
|
+
byte = UNICODE_TO_WIN_ANSI.get(code) ?? 63;
|
|
315
|
+
}
|
|
316
|
+
const ch = String.fromCharCode(byte);
|
|
317
|
+
if (ch === "\\" || ch === "(" || ch === ")") {
|
|
318
|
+
out += `\\${ch}`;
|
|
319
|
+
} else {
|
|
320
|
+
out += ch;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return out;
|
|
324
|
+
}
|
|
325
|
+
var UNICODE_TO_WIN_ANSI = new Map([
|
|
326
|
+
[8364, 128],
|
|
327
|
+
[8218, 130],
|
|
328
|
+
[402, 131],
|
|
329
|
+
[8222, 132],
|
|
330
|
+
[8230, 133],
|
|
331
|
+
[8224, 134],
|
|
332
|
+
[8225, 135],
|
|
333
|
+
[710, 136],
|
|
334
|
+
[8240, 137],
|
|
335
|
+
[352, 138],
|
|
336
|
+
[8249, 139],
|
|
337
|
+
[338, 140],
|
|
338
|
+
[381, 142],
|
|
339
|
+
[8216, 145],
|
|
340
|
+
[8217, 146],
|
|
341
|
+
[8220, 147],
|
|
342
|
+
[8221, 148],
|
|
343
|
+
[8226, 149],
|
|
344
|
+
[8211, 150],
|
|
345
|
+
[8212, 151],
|
|
346
|
+
[732, 152],
|
|
347
|
+
[8482, 153],
|
|
348
|
+
[353, 154],
|
|
349
|
+
[8250, 155],
|
|
350
|
+
[339, 156],
|
|
351
|
+
[382, 158],
|
|
352
|
+
[376, 159],
|
|
353
|
+
...Array.from({ length: 96 }, (_, i) => [160 + i, 160 + i])
|
|
354
|
+
]);
|
|
283
355
|
function parseHexColor(hex) {
|
|
284
356
|
if (!hex)
|
|
285
357
|
return null;
|
|
@@ -316,11 +388,11 @@ class PdfPageImpl {
|
|
|
316
388
|
if (rgb) {
|
|
317
389
|
this.operators.push(`${rgb[0].toFixed(3)} ${rgb[1].toFixed(3)} ${rgb[2].toFixed(3)} rg`);
|
|
318
390
|
}
|
|
319
|
-
const
|
|
391
|
+
const encoded = toWinAnsi(text);
|
|
320
392
|
this.operators.push("BT");
|
|
321
393
|
this.operators.push(`/F1 ${size} Tf`);
|
|
322
394
|
this.operators.push(`${x} ${y} Td`);
|
|
323
|
-
this.operators.push(`(${
|
|
395
|
+
this.operators.push(`(${encoded}) Tj`);
|
|
324
396
|
this.operators.push("ET");
|
|
325
397
|
}
|
|
326
398
|
drawRectangle(options) {
|
|
@@ -359,7 +431,11 @@ class PdfPageImpl {
|
|
|
359
431
|
buildContentStream() {
|
|
360
432
|
const content = this.operators.join(`
|
|
361
433
|
`);
|
|
362
|
-
|
|
434
|
+
const bytes = new Uint8Array(content.length);
|
|
435
|
+
for (let i = 0;i < content.length; i++) {
|
|
436
|
+
bytes[i] = content.charCodeAt(i);
|
|
437
|
+
}
|
|
438
|
+
return bytes;
|
|
363
439
|
}
|
|
364
440
|
getImageRefs() {
|
|
365
441
|
return new Map(this.imageRefs);
|
|
@@ -439,9 +515,10 @@ class PdfDocumentImpl {
|
|
|
439
515
|
this.structure = parsePdfStructure(this.pdfStr);
|
|
440
516
|
this.nextObjNum = this.structure.size;
|
|
441
517
|
this.fontObjNum = this.nextObjNum++;
|
|
518
|
+
const { objIndex } = this.structure;
|
|
442
519
|
for (let i = 0;i < this.structure.pageNums.length; i++) {
|
|
443
520
|
const pageNum = this.structure.pageNums[i];
|
|
444
|
-
const mediaBox = getMediaBox(this.pdfStr, pageNum);
|
|
521
|
+
const mediaBox = getMediaBox(this.pdfStr, pageNum, objIndex);
|
|
445
522
|
const width = mediaBox[2] - mediaBox[0];
|
|
446
523
|
const height = mediaBox[3] - mediaBox[1];
|
|
447
524
|
const dictContent = this.structure.pageDictContents[i];
|
|
@@ -490,7 +567,7 @@ class PdfDocumentImpl {
|
|
|
490
567
|
if (anyDirty || this.embeddedImages.length > 0) {
|
|
491
568
|
objects.push({
|
|
492
569
|
objNum: this.fontObjNum,
|
|
493
|
-
content: "<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>"
|
|
570
|
+
content: "<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >>"
|
|
494
571
|
});
|
|
495
572
|
}
|
|
496
573
|
for (const img of this.embeddedImages) {
|
|
@@ -574,7 +651,7 @@ class PdfDocumentImpl {
|
|
|
574
651
|
newResources[resType] = rest.join(" ");
|
|
575
652
|
}
|
|
576
653
|
}
|
|
577
|
-
const existingResources = parseResourcesDict(pageContent, this.pdfStr);
|
|
654
|
+
const existingResources = parseResourcesDict(pageContent, this.pdfStr, this.structure.objIndex);
|
|
578
655
|
const mergedResources = mergeResourcesDicts(existingResources, newResources);
|
|
579
656
|
const resourceEntries = Object.entries(mergedResources).map(([name, value]) => `${name} ${value}`).join(`
|
|
580
657
|
`);
|
|
@@ -917,4 +994,4 @@ function countPdfPages(data) {
|
|
|
917
994
|
|
|
918
995
|
export { PdfDocumentImpl, findByteRange, extractBytesToSign, embedSignature, loadPdf, countPdfPages };
|
|
919
996
|
|
|
920
|
-
//# debugId=
|
|
997
|
+
//# debugId=A37956E5F13AB5E164756E2164756E21
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/plugins/editing/parser.ts", "../src/plugins/editing/page.ts", "../src/plugins/editing/document.ts", "../src/plugins/editing/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Lightweight PDF structure parser for incremental editing\n *\n * Parses just enough of an existing PDF to enable incremental updates:\n * - Finds the cross-reference table via startxref\n * - Reads the trailer to get Root, Size, Info\n * - Follows Root -> Pages -> Kids to locate page objects\n * - Extracts MediaBox dimensions from pages\n *\n * All public functions accept a pre-decoded latin1 string (`pdfStr`) rather\n * than the raw Uint8Array so that the caller can decode ONCE and reuse the\n * string across many calls — avoiding O(pages) redundant allocations.\n */\n\n/**\n * Parsed PDF structure needed for incremental updates\n */\nexport type PdfStructure = {\n\txrefOffset: number;\n\trootNum: number;\n\tinfoNum: number | null;\n\tsize: number;\n\tpagesNum: number;\n\tpageNums: number[];\n\trootDictContent: string;\n\tpageDictContents: string[];\n\t/** Pre-built object position index for O(1) lookups */\n\tobjIndex: Map<number, number>;\n};\n\n/**\n * Find the byte offset recorded after the last `startxref` keyword\n */\nexport function findStartXref(pdfStr: string): number {\n\tconst idx = pdfStr.lastIndexOf(\"startxref\");\n\tif (idx === -1) throw new Error(\"Cannot find startxref in PDF\");\n\tconst after = pdfStr.slice(idx + 9).trim().split(/[\\r\\n\\s]/)[0];\n\treturn parseInt(after!, 10);\n}\n\n/**\n * Parse the trailer dictionary to extract Root, Size, Info, and Prev xref offset.\n *\n * Supports both traditional trailers (`trailer << ... >>`) and\n * cross-reference streams (PDF 1.5+) where the trailer entries live\n * inside the xref stream object dictionary.\n */\nexport function parseTrailer(pdfStr: string): {\n\troot: number;\n\tsize: number;\n\tinfo: number | null;\n\tprevXref: number;\n} {\n\tconst startxrefIdx = pdfStr.lastIndexOf(\"startxref\");\n\n\t// Try traditional trailer first\n\tconst trailerIdx = pdfStr.lastIndexOf(\"trailer\");\n\n\tlet dictStr: string;\n\n\tif (trailerIdx !== -1 && trailerIdx < startxrefIdx) {\n\t\t// Traditional trailer\n\t\tdictStr = pdfStr.slice(trailerIdx, startxrefIdx);\n\t} else {\n\t\t// Cross-reference stream (PDF 1.5+): startxref points to an object\n\t\t// whose dictionary contains the trailer entries (Root, Size, Info, etc.)\n\t\tconst xrefOffset = findStartXref(pdfStr);\n\t\tconst xrefObjStr = pdfStr.slice(xrefOffset, xrefOffset + 4096);\n\t\tconst dictStart = xrefObjStr.indexOf(\"<<\");\n\t\tif (dictStart === -1) {\n\t\t\tthrow new Error(\"Cannot find trailer or xref stream dictionary in PDF\");\n\t\t}\n\t\tconst dictEnd = findMatchingDictEnd(xrefObjStr, dictStart);\n\t\tif (dictEnd === -1) {\n\t\t\tthrow new Error(\"Cannot find end of xref stream dictionary\");\n\t\t}\n\t\tdictStr = xrefObjStr.slice(dictStart, dictEnd + 2);\n\t}\n\n\tconst rootMatch = dictStr.match(/\\/Root\\s+(\\d+)\\s+\\d+\\s+R/);\n\tif (!rootMatch) throw new Error(\"Cannot find Root ref in trailer\");\n\n\tconst sizeMatch = dictStr.match(/\\/Size\\s+(\\d+)/);\n\tif (!sizeMatch) throw new Error(\"Cannot find Size in trailer\");\n\n\tconst infoMatch = dictStr.match(/\\/Info\\s+(\\d+)\\s+\\d+\\s+R/);\n\tconst prevMatch = dictStr.match(/\\/Prev\\s+(\\d+)/);\n\n\treturn {\n\t\troot: parseInt(rootMatch[1]!, 10),\n\t\tsize: parseInt(sizeMatch[1]!, 10),\n\t\tinfo: infoMatch ? parseInt(infoMatch[1]!, 10) : null,\n\t\tprevXref: prevMatch ? parseInt(prevMatch[1]!, 10) : findStartXref(pdfStr),\n\t};\n}\n\n/**\n * Build an index mapping object numbers to their position (end of \"N 0 obj\" marker)\n * in a single O(fileSize) pass. Callers look up objects in O(1) instead of\n * scanning the entire string with a new regex per object.\n */\nexport function buildObjectIndex(pdfStr: string): Map<number, number> {\n\tconst index = new Map<number, number>();\n\tconst regex = /(?:^|\\s)(\\d+)\\s+0\\s+obj/gm;\n\tlet m: RegExpExecArray | null;\n\twhile ((m = regex.exec(pdfStr)) !== null) {\n\t\tconst objNum = parseInt(m[1]!, 10);\n\t\tif (!index.has(objNum)) {\n\t\t\tindex.set(objNum, m.index! + m[0].length);\n\t\t}\n\t}\n\treturn index;\n}\n\n/**\n * Extract the dictionary content (between outer << and >>) for a given object number.\n * Returns the content string without the delimiters.\n *\n * When called with a pre-built objIndex, lookups are O(1).\n * Falls back to a per-call regex search if no index is provided.\n */\nexport function extractObjectDictContent(\n\tpdfStr: string,\n\tobjNum: number,\n\tobjIndex?: Map<number, number>,\n): string {\n\tlet searchStart: number;\n\n\tif (objIndex) {\n\t\tconst pos = objIndex.get(objNum);\n\t\tif (pos === undefined) {\n\t\t\tthrow new Error(`Cannot find object ${objNum} in PDF`);\n\t\t}\n\t\tsearchStart = pos;\n\t} else {\n\t\tconst objRegex = new RegExp(`(?:^|\\\\s)${objNum}\\\\s+0\\\\s+obj`, \"m\");\n\t\tconst match = pdfStr.match(objRegex);\n\t\tif (!match || match.index === undefined) {\n\t\t\tthrow new Error(`Cannot find object ${objNum} in PDF`);\n\t\t}\n\t\tsearchStart = match.index + match[0].length;\n\t}\n\n\tconst dictStart = pdfStr.indexOf(\"<<\", searchStart);\n\tif (dictStart === -1 || dictStart > searchStart + 200) {\n\t\tthrow new Error(`Cannot find dictionary start for object ${objNum}`);\n\t}\n\n\tconst dictEnd = findMatchingDictEnd(pdfStr, dictStart);\n\tif (dictEnd === -1) {\n\t\tthrow new Error(`Cannot find dictionary end for object ${objNum}`);\n\t}\n\n\treturn pdfStr.slice(dictStart + 2, dictEnd);\n}\n\n/**\n * Find all LEAF page object numbers by following Root -> Pages -> Kids recursively.\n *\n * The PDF page tree can be arbitrarily deep — every ~100-200 pages, PDF tools\n * create intermediate Pages nodes (Type=Pages) that group their children.\n * This function recurses until it reaches actual Page leaves (Type=Page).\n */\nexport function findPageObjects(pdfStr: string, rootNum: number): number[] {\n\tconst rootContent = extractObjectDictContent(pdfStr, rootNum);\n\tconst pagesMatch = rootContent.match(/\\/Pages\\s+(\\d+)\\s+\\d+\\s+R/);\n\tif (!pagesMatch) throw new Error(\"Cannot find Pages ref in Root catalog\");\n\tconst pagesNum = parseInt(pagesMatch[1]!, 10);\n\n\treturn collectPageLeafs(pdfStr, pagesNum, new Set());\n}\n\n/** Index-accelerated version of findPageObjects */\nfunction findPageObjectsIndexed(\n\tpdfStr: string,\n\trootNum: number,\n\tobjIndex: Map<number, number>,\n): number[] {\n\tconst rootContent = extractObjectDictContent(pdfStr, rootNum, objIndex);\n\tconst pagesMatch = rootContent.match(/\\/Pages\\s+(\\d+)\\s+\\d+\\s+R/);\n\tif (!pagesMatch) throw new Error(\"Cannot find Pages ref in Root catalog\");\n\tconst pagesNum = parseInt(pagesMatch[1]!, 10);\n\n\treturn collectPageLeafsIndexed(pdfStr, pagesNum, new Set(), objIndex);\n}\n\n/**\n * Recursively collect leaf Page object numbers from a page tree node.\n * Handles both flat trees (all Kids are Pages) and nested trees\n * (intermediate Pages nodes with their own Kids arrays).\n */\nfunction collectPageLeafs(\n\tpdfStr: string,\n\tobjNum: number,\n\tvisited: Set<number>,\n): number[] {\n\tif (visited.has(objNum)) return []; // guard against malformed circular refs\n\tvisited.add(objNum);\n\n\tconst content = extractObjectDictContent(pdfStr, objNum);\n\n\t// Distinguish leaf Page from intermediate Pages node via /Type\n\tconst typeMatch = content.match(/\\/Type\\s+\\/(\\w+)/);\n\tif (typeMatch?.[1] === \"Page\") {\n\t\treturn [objNum];\n\t}\n\n\t// Intermediate Pages node — recurse into each kid\n\tconst kidsMatch = content.match(/\\/Kids\\s*\\[([^\\]]+)\\]/);\n\tif (!kidsMatch) {\n\t\t// Malformed node: no Kids and not a leaf — treat as single page (best effort)\n\t\treturn [objNum];\n\t}\n\n\tconst refs: number[] = [];\n\tconst refRegex = /(\\d+)\\s+\\d+\\s+R/g;\n\tlet m: RegExpExecArray | null;\n\twhile ((m = refRegex.exec(kidsMatch[1]!)) !== null) {\n\t\trefs.push(parseInt(m[1]!, 10));\n\t}\n\n\tconst pages: number[] = [];\n\tfor (const ref of refs) {\n\t\tpages.push(...collectPageLeafs(pdfStr, ref, visited));\n\t}\n\treturn pages;\n}\n\n/** Index-accelerated version of collectPageLeafs */\nfunction collectPageLeafsIndexed(\n\tpdfStr: string,\n\tobjNum: number,\n\tvisited: Set<number>,\n\tobjIndex: Map<number, number>,\n): number[] {\n\tif (visited.has(objNum)) return [];\n\tvisited.add(objNum);\n\n\tconst content = extractObjectDictContent(pdfStr, objNum, objIndex);\n\n\tconst typeMatch = content.match(/\\/Type\\s+\\/(\\w+)/);\n\tif (typeMatch?.[1] === \"Page\") {\n\t\treturn [objNum];\n\t}\n\n\tconst kidsMatch = content.match(/\\/Kids\\s*\\[([^\\]]+)\\]/);\n\tif (!kidsMatch) {\n\t\treturn [objNum];\n\t}\n\n\tconst refs: number[] = [];\n\tconst refRegex = /(\\d+)\\s+\\d+\\s+R/g;\n\tlet m: RegExpExecArray | null;\n\twhile ((m = refRegex.exec(kidsMatch[1]!)) !== null) {\n\t\trefs.push(parseInt(m[1]!, 10));\n\t}\n\n\tconst pages: number[] = [];\n\tfor (const ref of refs) {\n\t\tpages.push(...collectPageLeafsIndexed(pdfStr, ref, visited, objIndex));\n\t}\n\treturn pages;\n}\n\n/**\n * Get the MediaBox for a page object: [x1, y1, x2, y2].\n *\n * Per the PDF spec, /MediaBox is inherited: if the Page object itself does not\n * carry the entry, we walk up the /Parent chain until we find one.\n */\nexport function getMediaBox(\n\tpdfStr: string,\n\tpageObjNum: number,\n\tobjIndex?: Map<number, number>,\n): [number, number, number, number] {\n\tconst visited = new Set<number>(); // guard against malformed circular refs\n\tlet objNum: number | null = pageObjNum;\n\n\twhile (objNum !== null && !visited.has(objNum)) {\n\t\tvisited.add(objNum);\n\t\tconst content = extractObjectDictContent(pdfStr, objNum, objIndex);\n\n\t\tconst mediaBoxMatch = content.match(\n\t\t\t/\\/MediaBox\\s*\\[\\s*([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)\\s*\\]/,\n\t\t);\n\t\tif (mediaBoxMatch) {\n\t\t\treturn [\n\t\t\t\tparseFloat(mediaBoxMatch[1]!),\n\t\t\t\tparseFloat(mediaBoxMatch[2]!),\n\t\t\t\tparseFloat(mediaBoxMatch[3]!),\n\t\t\t\tparseFloat(mediaBoxMatch[4]!),\n\t\t\t];\n\t\t}\n\n\t\t// Walk up the parent chain\n\t\tconst parentMatch = content.match(/\\/Parent\\s+(\\d+)\\s+\\d+\\s+R/);\n\t\tobjNum = parentMatch ? parseInt(parentMatch[1]!, 10) : null;\n\t}\n\n\tthrow new Error(`Cannot find MediaBox for page object ${pageObjNum}`);\n}\n\n/**\n * Parse the full PDF structure needed for incremental editing.\n *\n * @param pdfStr - The PDF file decoded as a latin1 string (decode ONCE and pass here)\n */\nexport function parsePdfStructure(pdfStr: string): PdfStructure {\n\tconst xrefOffset = findStartXref(pdfStr);\n\tconst trailer = parseTrailer(pdfStr);\n\n\t// Build object position index once — all subsequent lookups are O(1)\n\tconst objIndex = buildObjectIndex(pdfStr);\n\n\tconst rootContent = extractObjectDictContent(pdfStr, trailer.root, objIndex);\n\tconst pagesMatch = rootContent.match(/\\/Pages\\s+(\\d+)\\s+\\d+\\s+R/);\n\tif (!pagesMatch) throw new Error(\"Cannot find Pages ref in Root catalog\");\n\tconst pagesNum = parseInt(pagesMatch[1]!, 10);\n\n\tconst pageNums = findPageObjectsIndexed(pdfStr, trailer.root, objIndex);\n\tconst pageDictContents = pageNums.map((pn) =>\n\t\textractObjectDictContent(pdfStr, pn, objIndex),\n\t);\n\n\treturn {\n\t\txrefOffset,\n\t\trootNum: trailer.root,\n\t\tinfoNum: trailer.info,\n\t\tsize: trailer.size,\n\t\tpagesNum,\n\t\tpageNums,\n\t\trootDictContent: rootContent,\n\t\tpageDictContents,\n\t\tobjIndex,\n\t};\n}\n\n/**\n * Find the position of the >> that closes the dictionary starting at startPos.\n * Handles nested << >> and skips PDF string literals in parentheses.\n */\nfunction findMatchingDictEnd(str: string, startPos: number): number {\n\tlet depth = 0;\n\tlet i = startPos;\n\n\twhile (i < str.length - 1) {\n\t\tif (str[i] === \"(\") {\n\t\t\t// skip parenthesized string\n\t\t\ti++;\n\t\t\twhile (i < str.length && str[i] !== \")\") {\n\t\t\t\tif (str[i] === \"\\\\\") i++;\n\t\t\t\ti++;\n\t\t\t}\n\t\t\ti++; // skip ')'\n\t\t} else if (str[i] === \"<\" && str[i + 1] === \"<\") {\n\t\t\tdepth++;\n\t\t\ti += 2;\n\t\t} else if (str[i] === \">\" && str[i + 1] === \">\") {\n\t\t\tdepth--;\n\t\t\tif (depth === 0) return i;\n\t\t\ti += 2;\n\t\t} else {\n\t\t\ti++;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/**\n * Find the position of the ] that closes the array starting at startPos.\n * Handles nested [ ] and skips PDF string literals in parentheses.\n */\nfunction findMatchingArrayEnd(str: string, startPos: number): number {\n\tlet depth = 0;\n\tlet i = startPos;\n\n\twhile (i < str.length) {\n\t\tif (str[i] === \"(\") {\n\t\t\t// skip parenthesized string\n\t\t\ti++;\n\t\t\twhile (i < str.length && str[i] !== \")\") {\n\t\t\t\tif (str[i] === \"\\\\\") i++;\n\t\t\t\ti++;\n\t\t\t}\n\t\t\ti++; // skip ')'\n\t\t} else if (str[i] === \"[\") {\n\t\t\tdepth++;\n\t\t\ti++;\n\t\t} else if (str[i] === \"]\") {\n\t\t\tdepth--;\n\t\t\tif (depth === 0) return i;\n\t\t\ti++;\n\t\t} else {\n\t\t\ti++;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/**\n * Parse a Resources dictionary from page content, handling both inline\n * dictionaries and indirect references.\n *\n * Returns a map of resource type names to their dictionary/array content strings.\n * Example: { \"/Font\": \"<< /F1 10 0 R >>\", \"/ProcSet\": \"[/PDF /Text]\" }\n */\nexport function parseResourcesDict(\n\tpageContent: string,\n\tpdfStr: string,\n\tobjIndex?: Map<number, number>,\n): Record<string, string> {\n\tconst result: Record<string, string> = {};\n\n\t// Check for inline Resources dictionary\n\tconst inlineMatch = pageContent.match(/\\/Resources\\s*<</);\n\tif (inlineMatch) {\n\t\tconst resIdx = pageContent.indexOf(\"/Resources\");\n\t\tconst resStart = pageContent.indexOf(\"<<\", resIdx);\n\t\tconst resEnd = findMatchingDictEnd(pageContent, resStart);\n\n\t\tif (resEnd === -1) {\n\t\t\tthrow new Error(\"Cannot find end of Resources dictionary\");\n\t\t}\n\n\t\tconst resContent = pageContent.slice(resStart + 2, resEnd);\n\t\treturn parseResourceEntries(resContent);\n\t}\n\n\t// Check for indirect Resources reference\n\tconst refMatch = pageContent.match(/\\/Resources\\s+(\\d+)\\s+\\d+\\s+R/);\n\tif (refMatch) {\n\t\tconst objNum = parseInt(refMatch[1]!, 10);\n\t\tconst objContent = extractObjectDictContent(pdfStr, objNum, objIndex);\n\t\treturn parseResourceEntries(objContent);\n\t}\n\n\t// No Resources found\n\treturn result;\n}\n\n/**\n * Merge two Resources dictionaries, combining entries from both.\n *\n * For dictionary-type entries like /Font, /XObject, extracts individual\n * name-reference pairs and combines them. For array-type entries like\n * /ProcSet, uses the existing value (no merge needed).\n *\n * @param existing - Parsed Resources from original page\n * @param additions - New Resources to add (from signature appearance)\n * @returns Merged Resources dictionary entries\n */\nexport function mergeResourcesDicts(\n\texisting: Record<string, string>,\n\tadditions: Record<string, string>,\n): Record<string, string> {\n\tconst result = { ...existing };\n\n\tfor (const [resType, addValue] of Object.entries(additions)) {\n\t\tif (!result[resType]) {\n\t\t\t// No existing entry for this type, just add it\n\t\t\tresult[resType] = addValue;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst existingValue = result[resType]!;\n\n\t\t// Arrays (like /ProcSet) - keep existing, don't merge\n\t\tif (existingValue.startsWith(\"[\")) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Dictionaries - merge entries\n\t\tif (existingValue.startsWith(\"<<\")) {\n\t\t\tresult[resType] = mergeDictEntries(existingValue, addValue);\n\t\t} else {\n\t\t\tthrow new Error(`Unexpected resource format for ${resType}: ${existingValue}`);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Merge two PDF dictionary strings by combining their name-reference pairs.\n *\n * Example:\n * existing: \"<< /F1 10 0 R /F2 11 0 R >>\"\n * additions: \"<< /SigF1 20 0 R >>\"\n * result: \"<< /F1 10 0 R /F2 11 0 R /SigF1 20 0 R >>\"\n */\nfunction mergeDictEntries(existing: string, additions: string): string {\n\t// Extract entries from both dictionaries\n\tconst existingEntries = extractDictEntries(existing);\n\tconst additionEntries = extractDictEntries(additions);\n\n\t// Combine (additions override existing if same key)\n\tconst merged = { ...existingEntries, ...additionEntries };\n\n\t// Rebuild dictionary string\n\tconst entries = Object.entries(merged)\n\t\t.map(([name, ref]) => `${name} ${ref}`)\n\t\t.join(\" \");\n\n\treturn `<< ${entries} >>`;\n}\n\n/**\n * Extract name-reference pairs from a PDF dictionary string.\n *\n * Example: \"<< /F1 10 0 R /F2 11 0 R >>\"\n * Returns: { \"/F1\": \"10 0 R\", \"/F2\": \"11 0 R\" }\n */\nfunction extractDictEntries(dict: string): Record<string, string> {\n\tconst entries: Record<string, string> = {};\n\n\t// Remove outer << >>\n\tconst inner = dict.replace(/^<<\\s*/, \"\").replace(/\\s*>>$/, \"\");\n\n\t// Match /Name objNum gen R patterns\n\t// Pattern matches PDF names with hyphens, dots, and hex-encoded characters\n\tconst regex = /(\\/[^\\s<>\\[\\]()\\/]+)\\s+(\\d+\\s+\\d+\\s+R)/g;\n\tlet match: RegExpExecArray | null;\n\n\twhile ((match = regex.exec(inner)) !== null) {\n\t\tentries[match[1]!] = match[2]!;\n\t}\n\n\treturn entries;\n}\n\n/**\n * Parse individual resource entries from a Resources dictionary content string.\n *\n * Extracts top-level entries like /Font, /XObject, /ExtGState, etc.\n */\nfunction parseResourceEntries(content: string): Record<string, string> {\n\tconst result: Record<string, string> = {};\n\n\t// Resource entry names to extract\n\tconst resourceTypes = [\n\t\t\"/Font\",\n\t\t\"/XObject\",\n\t\t\"/ExtGState\",\n\t\t\"/ColorSpace\",\n\t\t\"/Pattern\",\n\t\t\"/Shading\",\n\t\t\"/ProcSet\",\n\t];\n\n\tfor (const resType of resourceTypes) {\n\t\t// Use regex to match resource type at dictionary level (not nested inside values)\n\t\t// Pattern: /ResourceType followed by whitespace and then either << or [\n\t\tconst pattern = new RegExp(\n\t\t\t`${resType.replace(/\\//g, \"\\\\/\")}\\\\s+([<\\\\[])`\n\t\t);\n\t\tconst match = content.match(pattern);\n\n\t\tif (!match) continue;\n\n\t\tconst idx = match.index!;\n\n\t\t// Find the value (either << dict >> or [ array ])\n\t\tlet valueStart = idx + resType.length;\n\t\twhile (valueStart < content.length && /\\s/.test(content[valueStart]!)) {\n\t\t\tvalueStart++;\n\t\t}\n\n\t\tif (content[valueStart] === \"<\" && content[valueStart + 1] === \"<\") {\n\t\t\t// Dictionary value\n\t\t\tconst dictEnd = findMatchingDictEnd(content, valueStart);\n\t\t\tif (dictEnd === -1) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot find end of ${resType} dictionary`\n\t\t\t\t);\n\t\t\t}\n\t\t\tresult[resType] = content.slice(valueStart, dictEnd + 2);\n\t\t} else if (content[valueStart] === \"[\") {\n\t\t\t// Array value\n\t\t\tconst arrayEnd = findMatchingArrayEnd(content, valueStart);\n\t\t\tif (arrayEnd === -1) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot find end of ${resType} array`\n\t\t\t\t);\n\t\t\t}\n\t\t\tresult[resType] = content.slice(valueStart, arrayEnd + 1);\n\t\t}\n\t}\n\n\treturn result;\n}\n",
|
|
6
|
+
"/**\n * PdfPage implementation for the editing plugin\n *\n * Collects drawing operations as PDF content stream operators.\n * The accumulated operators are later serialised as a new content stream\n * object appended via incremental update.\n */\n\nimport type { PdfImage, PdfPage, TextOptions, RectOptions, ImageOptions } from \"./types.ts\";\n\n/**\n * Parse a hex colour string like \"#RRGGBB\" into normalised [r, g, b] values (0-1).\n * Returns null for invalid/missing input so callers can fall back to defaults.\n */\n/**\n * Convert a UTF-16 JS string to a WinAnsiEncoding-escaped PDF string.\n * Characters outside WinAnsi are replaced with '?'.\n */\nfunction toWinAnsi(text: string): string {\n\tlet out = \"\";\n\tfor (let i = 0; i < text.length; i++) {\n\t\tconst code = text.charCodeAt(i);\n\t\tlet byte: number;\n\n\t\tif (code < 0x80) {\n\t\t\tbyte = code;\n\t\t} else {\n\t\t\t// Map Unicode code points to WinAnsiEncoding bytes\n\t\t\tbyte = UNICODE_TO_WIN_ANSI.get(code) ?? 0x3f; // '?'\n\t\t}\n\n\t\tconst ch = String.fromCharCode(byte);\n\t\tif (ch === \"\\\\\" || ch === \"(\" || ch === \")\") {\n\t\t\tout += `\\\\${ch}`;\n\t\t} else {\n\t\t\tout += ch;\n\t\t}\n\t}\n\treturn out;\n}\n\n/**\n * Mapping from Unicode code points to WinAnsiEncoding byte values\n * for characters in the 0x80-0xFF range that differ from Unicode.\n */\nconst UNICODE_TO_WIN_ANSI = new Map<number, number>([\n\t// 0x80-0x9F range (WinAnsi-specific mappings)\n\t[0x20ac, 0x80], // €\n\t[0x201a, 0x82], // ‚\n\t[0x0192, 0x83], // ƒ\n\t[0x201e, 0x84], // „\n\t[0x2026, 0x85], // …\n\t[0x2020, 0x86], // †\n\t[0x2021, 0x87], // ‡\n\t[0x02c6, 0x88], // ˆ\n\t[0x2030, 0x89], // ‰\n\t[0x0160, 0x8a], // Š\n\t[0x2039, 0x8b], // ‹\n\t[0x0152, 0x8c], // Œ\n\t[0x017d, 0x8e], // Ž\n\t[0x2018, 0x91], // '\n\t[0x2019, 0x92], // '\n\t[0x201c, 0x93], // \"\n\t[0x201d, 0x94], // \"\n\t[0x2022, 0x95], // •\n\t[0x2013, 0x96], // –\n\t[0x2014, 0x97], // —\n\t[0x02dc, 0x98], // ˜\n\t[0x2122, 0x99], // ™\n\t[0x0161, 0x9a], // š\n\t[0x203a, 0x9b], // ›\n\t[0x0153, 0x9c], // œ\n\t[0x017e, 0x9e], // ž\n\t[0x0178, 0x9f], // Ÿ\n\t// 0xA0-0xFF: Unicode and WinAnsi are identical\n\t...Array.from({ length: 96 }, (_, i) => [0xa0 + i, 0xa0 + i] as [number, number]),\n]);\n\nfunction parseHexColor(hex: string | undefined): [number, number, number] | null {\n\tif (!hex) return null;\n\tconst m = hex.match(/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);\n\tif (!m) return null;\n\treturn [\n\t\tparseInt(m[1]!, 16) / 255,\n\t\tparseInt(m[2]!, 16) / 255,\n\t\tparseInt(m[3]!, 16) / 255,\n\t];\n}\n\nexport class PdfPageImpl implements PdfPage {\n\treadonly width: number;\n\treadonly height: number;\n\n\t/** The existing page object number in the original PDF */\n\treadonly pageObjNum: number;\n\t/** The raw dictionary content string of the original page */\n\treadonly originalDictContent: string;\n\n\t/** Accumulated content-stream operators added by draw* methods */\n\tprivate operators: string[] = [];\n\n\t/** Images referenced by drawImage (name -> obj num) */\n\tprivate imageRefs: Map<string, number> = new Map();\n\n\t/** Font object number allocated by the document (set externally) */\n\tfontObjNum = 0;\n\n\t/** Whether any drawing operations have been recorded */\n\tget dirty(): boolean {\n\t\treturn this.operators.length > 0;\n\t}\n\n\tconstructor(\n\t\tpageObjNum: number,\n\t\twidth: number,\n\t\theight: number,\n\t\toriginalDictContent: string,\n\t) {\n\t\tthis.pageObjNum = pageObjNum;\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t\tthis.originalDictContent = originalDictContent;\n\t}\n\n\t/**\n\t * Draw text on the page using Helvetica\n\t */\n\tdrawText(text: string, options: TextOptions): void {\n\t\tconst { x, y, size = 12, color } = options;\n\t\tconst rgb = parseHexColor(color);\n\n\t\tif (rgb) {\n\t\t\tthis.operators.push(`${rgb[0].toFixed(3)} ${rgb[1].toFixed(3)} ${rgb[2].toFixed(3)} rg`);\n\t\t}\n\n\t\t// Encode text as WinAnsiEncoding and escape special PDF string characters\n\t\tconst encoded = toWinAnsi(text);\n\n\t\tthis.operators.push(\"BT\");\n\t\tthis.operators.push(`/F1 ${size} Tf`);\n\t\tthis.operators.push(`${x} ${y} Td`);\n\t\tthis.operators.push(`(${encoded}) Tj`);\n\t\tthis.operators.push(\"ET\");\n\t}\n\n\t/**\n\t * Draw a rectangle on the page\n\t */\n\tdrawRectangle(options: RectOptions): void {\n\t\tconst { x, y, width, height, color, borderColor, borderWidth } = options;\n\n\t\tconst fillRgb = parseHexColor(color);\n\t\tconst strokeRgb = parseHexColor(borderColor);\n\n\t\tif (fillRgb) {\n\t\t\tthis.operators.push(`${fillRgb[0].toFixed(3)} ${fillRgb[1].toFixed(3)} ${fillRgb[2].toFixed(3)} rg`);\n\t\t}\n\t\tif (strokeRgb) {\n\t\t\tthis.operators.push(`${strokeRgb[0].toFixed(3)} ${strokeRgb[1].toFixed(3)} ${strokeRgb[2].toFixed(3)} RG`);\n\t\t}\n\t\tif (borderWidth !== undefined) {\n\t\t\tthis.operators.push(`${borderWidth} w`);\n\t\t}\n\n\t\tthis.operators.push(`${x} ${y} ${width} ${height} re`);\n\n\t\tif (fillRgb && strokeRgb) {\n\t\t\tthis.operators.push(\"B\"); // fill and stroke\n\t\t} else if (fillRgb) {\n\t\t\tthis.operators.push(\"f\"); // fill only\n\t\t} else if (strokeRgb) {\n\t\t\tthis.operators.push(\"S\"); // stroke only\n\t\t} else {\n\t\t\tthis.operators.push(\"f\"); // default: fill with current colour (black)\n\t\t}\n\t}\n\n\t/**\n\t * Draw an embedded image on the page\n\t */\n\tdrawImage(image: PdfImage, options: ImageOptions): void {\n\t\tconst { x, y, width, height } = options;\n\t\tconst imgName = `Im${image.objectNumber}`;\n\t\tthis.imageRefs.set(imgName, image.objectNumber);\n\n\t\tthis.operators.push(\"q\");\n\t\tthis.operators.push(`${width} 0 0 ${height} ${x} ${y} cm`);\n\t\tthis.operators.push(`/${imgName} Do`);\n\t\tthis.operators.push(\"Q\");\n\t}\n\n\t/**\n\t * Build the content stream bytes for the accumulated operators\n\t */\n\tbuildContentStream(): Uint8Array {\n\t\tconst content = this.operators.join(\"\\n\");\n\t\t// Write raw bytes — toWinAnsi already produced byte values in the\n\t\t// 0x00-0xFF range. TextEncoder would re-encode bytes >= 0x80 as\n\t\t// multi-byte UTF-8 sequences, corrupting WinAnsi characters like \"á\".\n\t\tconst bytes = new Uint8Array(content.length);\n\t\tfor (let i = 0; i < content.length; i++) {\n\t\t\tbytes[i] = content.charCodeAt(i);\n\t\t}\n\t\treturn bytes;\n\t}\n\n\t/**\n\t * Get image references used in drawing operations\n\t */\n\tgetImageRefs(): Map<string, number> {\n\t\treturn new Map(this.imageRefs);\n\t}\n}\n",
|
|
7
|
+
"/**\n * PdfDocument implementation for the editing plugin\n *\n * Manages loading an existing PDF, tracking modifications, and producing an\n * incremental update (appended after the original %%EOF) that adds or\n * overrides objects without rewriting the original content.\n */\n\nimport {\n\tparsePdfStructure,\n\tgetMediaBox,\n\textractObjectDictContent,\n\tparseResourcesDict,\n\tmergeResourcesDicts,\n} from \"./parser.ts\";\nimport { PdfPageImpl } from \"./page.ts\";\nimport type {\n\tPdfDocument,\n\tPdfImage,\n\tPdfPage,\n\tSignaturePlaceholderOptions,\n} from \"./types.ts\";\n\nconst BYTE_RANGE_PLACEHOLDER = \"0 0000000000 0000000000 0000000000\";\nconst DEFAULT_SIGNATURE_LENGTH = 16384;\n\nconst latin1Encoder = new TextEncoder(); // UTF-8 but we only feed ASCII/latin1-safe chars\nconst latin1Decoder = new TextDecoder(\"latin1\");\n\n// Pre-encoded byte patterns for PDF structure search (avoids per-call allocation)\nconst CONTENTS_MARKER = latin1Encoder.encode(\"/Contents <\");\nconst BYTE_RANGE_MARKER = latin1Encoder.encode(\"/ByteRange [\");\n\n/**\n * Search for the last occurrence of `pattern` inside `data`.\n * Returns the byte offset of the first byte of the match, or -1.\n */\nfunction findLastBytes(data: Uint8Array, pattern: Uint8Array): number {\n\touter: for (let i = data.length - pattern.length; i >= 0; i--) {\n\t\tfor (let j = 0; j < pattern.length; j++) {\n\t\t\tif (data[i + j] !== pattern[j]) continue outer;\n\t\t}\n\t\treturn i;\n\t}\n\treturn -1;\n}\n\n/**\n * Parse PNG IHDR to extract width, height, bit depth, and colour type.\n */\nfunction parsePngIhdr(data: Uint8Array): {\n\twidth: number;\n\theight: number;\n\tbitDepth: number;\n\tcolorType: number;\n} {\n\t// PNG signature: 8 bytes, then first chunk is IHDR\n\tconst sig = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];\n\tfor (let i = 0; i < sig.length; i++) {\n\t\tif (data[i] !== sig[i]) throw new Error(\"Not a valid PNG file\");\n\t}\n\n\t// IHDR chunk starts at offset 8\n\t// 4 bytes length + 4 bytes \"IHDR\" + 13 bytes data\n\tconst view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\tconst chunkType = latin1Decoder.decode(data.slice(12, 16));\n\tif (chunkType !== \"IHDR\") throw new Error(\"First PNG chunk is not IHDR\");\n\n\treturn {\n\t\twidth: view.getUint32(16),\n\t\theight: view.getUint32(20),\n\t\tbitDepth: data[24]!,\n\t\tcolorType: data[25]!,\n\t};\n}\n\n/**\n * Extract and concatenate all IDAT chunk data from a PNG\n */\nfunction extractIdatData(data: Uint8Array): Uint8Array {\n\tconst view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\tconst chunks: Uint8Array[] = [];\n\tlet offset = 8; // skip PNG signature\n\n\twhile (offset < data.length) {\n\t\tconst chunkLen = view.getUint32(offset);\n\t\tconst chunkType = latin1Decoder.decode(data.slice(offset + 4, offset + 8));\n\n\t\tif (chunkType === \"IDAT\") {\n\t\t\tchunks.push(data.slice(offset + 8, offset + 8 + chunkLen));\n\t\t}\n\n\t\t// skip: length(4) + type(4) + data(chunkLen) + crc(4)\n\t\toffset += 12 + chunkLen;\n\t}\n\n\tif (chunks.length === 0) throw new Error(\"No IDAT chunks found in PNG\");\n\n\t// Concatenate all IDAT data\n\tconst totalLen = chunks.reduce((s, c) => s + c.length, 0);\n\tconst result = new Uint8Array(totalLen);\n\tlet pos = 0;\n\tfor (const chunk of chunks) {\n\t\tresult.set(chunk, pos);\n\t\tpos += chunk.length;\n\t}\n\treturn result;\n}\n\nexport class PdfDocumentImpl implements PdfDocument {\n\tprivate originalData: Uint8Array;\n\tprivate pdfStr: string; // latin1 string decoded ONCE — reused by all parser calls\n\tprivate structure: ReturnType<typeof parsePdfStructure>;\n\tprivate pages: PdfPageImpl[] = [];\n\tprivate nextObjNum: number;\n\tprivate fontObjNum: number;\n\tprivate embeddedImages: Array<{\n\t\tobjNum: number;\n\t\twidth: number;\n\t\theight: number;\n\t\tidatData: Uint8Array;\n\t\tcolorType: number;\n\t\tbitDepth: number;\n\t}> = [];\n\n\tconstructor(data: Uint8Array) {\n\t\tthis.originalData = data;\n\t\t// Decode the PDF bytes to a latin1 string exactly ONCE.\n\t\t// All parser helpers reuse this string so we never create redundant copies.\n\t\tthis.pdfStr = latin1Decoder.decode(data);\n\t\tthis.structure = parsePdfStructure(this.pdfStr);\n\n\t\t// Allocate a font object number right away (Helvetica)\n\t\tthis.nextObjNum = this.structure.size;\n\t\tthis.fontObjNum = this.nextObjNum++;\n\n\t\t// Build page objects (reuse pre-built object index for O(1) lookups)\n\t\tconst { objIndex } = this.structure;\n\t\tfor (let i = 0; i < this.structure.pageNums.length; i++) {\n\t\t\tconst pageNum = this.structure.pageNums[i]!;\n\t\t\tconst mediaBox = getMediaBox(this.pdfStr, pageNum, objIndex);\n\t\t\tconst width = mediaBox[2] - mediaBox[0];\n\t\t\tconst height = mediaBox[3] - mediaBox[1];\n\t\t\tconst dictContent = this.structure.pageDictContents[i]!;\n\t\t\tconst page = new PdfPageImpl(pageNum, width, height, dictContent);\n\t\t\tpage.fontObjNum = this.fontObjNum;\n\t\t\tthis.pages.push(page);\n\t\t}\n\t}\n\n\tget pageCount(): number {\n\t\treturn this.pages.length;\n\t}\n\n\tgetPage(index: number): PdfPage {\n\t\tif (index < 0 || index >= this.pages.length) {\n\t\t\tthrow new Error(\n\t\t\t\t`Page index ${index} out of range (0-${this.pages.length - 1})`,\n\t\t\t);\n\t\t}\n\t\treturn this.pages[index]!;\n\t}\n\n\tembedPng(data: Uint8Array): PdfImage {\n\t\tconst ihdr = parsePngIhdr(data);\n\t\tconst idatData = extractIdatData(data);\n\t\tconst objNum = this.nextObjNum++;\n\n\t\tthis.embeddedImages.push({\n\t\t\tobjNum,\n\t\t\twidth: ihdr.width,\n\t\t\theight: ihdr.height,\n\t\t\tidatData,\n\t\t\tcolorType: ihdr.colorType,\n\t\t\tbitDepth: ihdr.bitDepth,\n\t\t});\n\n\t\treturn {\n\t\t\tobjectNumber: objNum,\n\t\t\twidth: ihdr.width,\n\t\t\theight: ihdr.height,\n\t\t};\n\t}\n\n\t/**\n\t * Save the modified PDF using an incremental update\n\t */\n\tsave(): Uint8Array {\n\t\treturn this.buildIncrementalUpdate(false).pdf;\n\t}\n\n\t/**\n\t * Save with a signature placeholder for digital signing\n\t */\n\tsaveWithPlaceholder(options: SignaturePlaceholderOptions): {\n\t\tpdf: Uint8Array;\n\t\tbyteRange: [number, number, number, number];\n\t} {\n\t\treturn this.buildIncrementalUpdate(true, options);\n\t}\n\n\tprivate buildIncrementalUpdate(\n\t\twithSignature: boolean,\n\t\tsigOptions?: SignaturePlaceholderOptions,\n\t): { pdf: Uint8Array; byteRange: [number, number, number, number] } {\n\t\tconst objects: Array<{ objNum: number; content: string; streamData?: Uint8Array }> = [];\n\t\tlet currentNextObj = this.nextObjNum;\n\n\t\t// --- 1. Font object (Helvetica, always emitted if any page is dirty) ---\n\t\tconst anyDirty = this.pages.some((p) => p.dirty);\n\t\tif (anyDirty || this.embeddedImages.length > 0) {\n\t\t\tobjects.push({\n\t\t\t\tobjNum: this.fontObjNum,\n\t\t\t\tcontent: \"<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >>\",\n\t\t\t});\n\t\t}\n\n\t\t// --- 2. Embedded image XObjects ---\n\t\tfor (const img of this.embeddedImages) {\n\t\t\tconst colorSpace = img.colorType === 2 ? \"/DeviceRGB\" : img.colorType === 0 ? \"/DeviceGray\" : \"/DeviceRGB\";\n\t\t\tconst colors = img.colorType === 2 ? 3 : 1;\n\t\t\tconst bpc = img.bitDepth;\n\n\t\t\t// PNG IDAT data uses per-row filter bytes. Tell the PDF reader\n\t\t\t// via DecodeParms with Predictor 15 (PNG optimum prediction).\n\t\t\tobjects.push({\n\t\t\t\tobjNum: img.objNum,\n\t\t\t\tcontent: [\n\t\t\t\t\t\"<< /Type /XObject\",\n\t\t\t\t\t\"/Subtype /Image\",\n\t\t\t\t\t`/Width ${img.width}`,\n\t\t\t\t\t`/Height ${img.height}`,\n\t\t\t\t\t`/ColorSpace ${colorSpace}`,\n\t\t\t\t\t`/BitsPerComponent ${bpc}`,\n\t\t\t\t\t\"/Filter /FlateDecode\",\n\t\t\t\t\t`/DecodeParms << /Predictor 15 /Colors ${colors} /BitsPerComponent ${bpc} /Columns ${img.width} >>`,\n\t\t\t\t\t`/Length ${img.idatData.length}`,\n\t\t\t\t\t\">>\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\tstreamData: img.idatData,\n\t\t\t});\n\t\t}\n\n\t\t// --- 3. Wrapper save-state streams + content streams for dirty pages ---\n\t\t// The original page content may modify the CTM (e.g. Y-axis flip for\n\t\t// top-left origin). We wrap the original content in q/Q so our new\n\t\t// drawing operators run with the default PDF coordinate system.\n\t\tconst wrapperStreamMap = new Map<number, number>(); // pageObjNum -> wrapperStreamObjNum\n\t\tconst contentStreamMap = new Map<number, number>(); // pageObjNum -> contentStreamObjNum\n\t\tfor (const page of this.pages) {\n\t\t\tif (!page.dirty) continue;\n\n\t\t\t// \"save state\" stream — placed BEFORE original content\n\t\t\tconst wrapperObjNum = currentNextObj++;\n\t\t\twrapperStreamMap.set(page.pageObjNum, wrapperObjNum);\n\t\t\tconst wrapperData = latin1Encoder.encode(\"q\");\n\t\t\tobjects.push({\n\t\t\t\tobjNum: wrapperObjNum,\n\t\t\t\tcontent: `<< /Length ${wrapperData.length} >>`,\n\t\t\t\tstreamData: wrapperData,\n\t\t\t});\n\n\t\t\t// Actual content stream — prefixed with Q to restore state\n\t\t\tconst contentObjNum = currentNextObj++;\n\t\t\tcontentStreamMap.set(page.pageObjNum, contentObjNum);\n\t\t\tconst pageStreamData = page.buildContentStream();\n\t\t\tconst prefixedData = new Uint8Array(2 + pageStreamData.length);\n\t\t\tprefixedData[0] = 0x51; // 'Q'\n\t\t\tprefixedData[1] = 0x0a; // '\\n'\n\t\t\tprefixedData.set(pageStreamData, 2);\n\t\t\tobjects.push({\n\t\t\t\tobjNum: contentObjNum,\n\t\t\t\tcontent: `<< /Length ${prefixedData.length} >>`,\n\t\t\t\tstreamData: prefixedData,\n\t\t\t});\n\t\t}\n\n\t\t// --- 4. Updated page dictionaries (add new content stream + font/image resources) ---\n\t\tfor (const page of this.pages) {\n\t\t\tif (!page.dirty && !this.hasImagesForPage(page)) continue;\n\n\t\t\tlet pageContent = page.originalDictContent;\n\n\t\t\t// Add or replace Contents reference if page is dirty\n\t\t\tif (page.dirty) {\n\t\t\t\tconst contentObjNum = contentStreamMap.get(page.pageObjNum)!;\n\t\t\t\tconst wrapperObjNum = wrapperStreamMap.get(page.pageObjNum)!;\n\n\t\t\t\tif (pageContent.match(/\\/Contents\\s/)) {\n\t\t\t\t\t// Replace existing Contents with an array: [wrapper, original, new]\n\t\t\t\t\t// The wrapper stream saves graphics state (q) before original content,\n\t\t\t\t\t// and the new stream restores it (Q) before our drawing operators.\n\t\t\t\t\tpageContent = pageContent.replace(\n\t\t\t\t\t\t/\\/Contents\\s+(\\d+\\s+\\d+\\s+R)/,\n\t\t\t\t\t\t`/Contents [${wrapperObjNum} 0 R $1 ${contentObjNum} 0 R]`,\n\t\t\t\t\t);\n\t\t\t\t\t// Also handle existing Contents arrays\n\t\t\t\t\tpageContent = pageContent.replace(\n\t\t\t\t\t\t/\\/Contents\\s*\\[([^\\]]+)\\]/,\n\t\t\t\t\t\t(match, inner) => {\n\t\t\t\t\t\t\t// If we already added our ref above, skip\n\t\t\t\t\t\t\tif (inner.includes(`${contentObjNum} 0 R`)) return match;\n\t\t\t\t\t\t\treturn `/Contents [${wrapperObjNum} 0 R ${inner.trim()} ${contentObjNum} 0 R]`;\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tpageContent += `\\n/Contents ${contentObjNum} 0 R`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Build signature's new resources\n\t\t\tconst newResourceParts: string[] = [];\n\t\t\tnewResourceParts.push(`/Font << /F1 ${this.fontObjNum} 0 R >>`);\n\n\t\t\t// Image resources\n\t\t\tconst imageRefs = page.dirty ? (page as PdfPageImpl).getImageRefs() : new Map<string, number>();\n\t\t\tif (imageRefs.size > 0) {\n\t\t\t\tconst xobjEntries = Array.from(imageRefs.entries())\n\t\t\t\t\t.map(([name, objNum]) => `/${name} ${objNum} 0 R`)\n\t\t\t\t\t.join(\" \");\n\t\t\t\tnewResourceParts.push(`/XObject << ${xobjEntries} >>`);\n\t\t\t}\n\n\t\t\tconst newResources: Record<string, string> = {};\n\t\t\tfor (const part of newResourceParts) {\n\t\t\t\tconst [resType, ...rest] = part.split(/\\s+/);\n\t\t\t\tif (resType) {\n\t\t\t\t\tnewResources[resType] = rest.join(\" \");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Parse existing Resources from page\n\t\t\tconst existingResources = parseResourcesDict(pageContent, this.pdfStr, this.structure.objIndex);\n\n\t\t\t// Merge existing with new\n\t\t\tconst mergedResources = mergeResourcesDicts(existingResources, newResources);\n\n\t\t\t// Build merged Resources dictionary string\n\t\t\tconst resourceEntries = Object.entries(mergedResources)\n\t\t\t\t.map(([name, value]) => `${name} ${value}`)\n\t\t\t\t.join(\"\\n\");\n\n\t\t\t// Update page content with merged Resources\n\t\t\tif (pageContent.match(/\\/Resources\\s*<</)) {\n\t\t\t\t// Replace existing inline Resources\n\t\t\t\tconst resIdx = pageContent.indexOf(\"/Resources\");\n\t\t\t\tconst resStart = pageContent.indexOf(\"<<\", resIdx);\n\t\t\t\tif (resStart !== -1) {\n\t\t\t\t\tconst resEnd = findMatchingDictEndInContent(pageContent, resStart);\n\t\t\t\t\tif (resEnd !== -1) {\n\t\t\t\t\t\tpageContent =\n\t\t\t\t\t\t\tpageContent.slice(0, resStart) +\n\t\t\t\t\t\t\t`<< ${resourceEntries} >>` +\n\t\t\t\t\t\t\tpageContent.slice(resEnd + 2);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (pageContent.match(/\\/Resources\\s+\\d+\\s+\\d+\\s+R/)) {\n\t\t\t\t// Replace indirect reference with merged inline dictionary\n\t\t\t\tpageContent = pageContent.replace(\n\t\t\t\t\t/\\/Resources\\s+\\d+\\s+\\d+\\s+R/,\n\t\t\t\t\t`/Resources << ${resourceEntries} >>`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// No resources at all — add them\n\t\t\t\tpageContent += `\\n/Resources << ${resourceEntries} >>`;\n\t\t\t}\n\n\t\t\tobjects.push({\n\t\t\t\tobjNum: page.pageObjNum,\n\t\t\t\tcontent: `<<${pageContent}\\n>>`,\n\t\t\t});\n\t\t}\n\n\t\t// --- 5. Signature placeholder objects (if requested) ---\n\t\tlet sigObjNum = 0;\n\t\tlet widgetObjNum = 0;\n\t\tlet acroFormObjNum = 0;\n\n\t\tif (withSignature && sigOptions) {\n\t\t\tsigObjNum = currentNextObj++;\n\t\t\twidgetObjNum = currentNextObj++;\n\t\t\tacroFormObjNum = currentNextObj++;\n\n\t\t\tconst signatureLength = sigOptions.signatureLength ?? DEFAULT_SIGNATURE_LENGTH;\n\t\t\tconst reason = sigOptions.reason ?? \"Digitally signed\";\n\t\t\tconst name = sigOptions.name ?? \"Digital Signature\";\n\t\t\tconst location = sigOptions.location ?? \"\";\n\t\t\tconst contactInfo = sigOptions.contactInfo ?? \"\";\n\t\t\tconst signingTime = formatPdfDate(new Date());\n\t\t\tconst contentsPlaceholder = \"0\".repeat(signatureLength * 2);\n\n\t\t\tconst sigParts = [\n\t\t\t\t\"<< /Type /Sig\",\n\t\t\t\t\"/Filter /Adobe.PPKLite\",\n\t\t\t\t\"/SubFilter /adbe.pkcs7.detached\",\n\t\t\t\t`/ByteRange [${BYTE_RANGE_PLACEHOLDER}]`,\n\t\t\t\t`/Contents <${contentsPlaceholder}>`,\n\t\t\t\t`/Reason ${pdfString(reason)}`,\n\t\t\t\t`/M ${pdfString(signingTime)}`,\n\t\t\t\t`/Name ${pdfString(name)}`,\n\t\t\t];\n\t\t\tif (location) sigParts.push(`/Location ${pdfString(location)}`);\n\t\t\tif (contactInfo) sigParts.push(`/ContactInfo ${pdfString(contactInfo)}`);\n\t\t\tsigParts.push(\">>\");\n\n\t\t\tobjects.push({ objNum: sigObjNum, content: sigParts.join(\"\\n\") });\n\n\t\t\t// Resolve which page hosts the signature widget annotation.\n\t\t\t// Defaults to page 0; callers pass `appearancePage` to match the\n\t\t\t// visual appearance location so PDF readers navigate correctly.\n\t\t\tconst sigPageIdx = Math.min(\n\t\t\t\tMath.max(sigOptions.appearancePage ?? 0, 0),\n\t\t\t\tthis.pages.length - 1,\n\t\t\t);\n\t\t\tconst sigPageNum = this.structure.pageNums[sigPageIdx]!;\n\n\t\t\t// Widget annotation\n\t\t\tobjects.push({\n\t\t\t\tobjNum: widgetObjNum,\n\t\t\t\tcontent: [\n\t\t\t\t\t\"<< /Type /Annot\",\n\t\t\t\t\t\"/Subtype /Widget\",\n\t\t\t\t\t\"/FT /Sig\",\n\t\t\t\t\t\"/Rect [0 0 0 0]\",\n\t\t\t\t\t`/V ${sigObjNum} 0 R`,\n\t\t\t\t\t`/T ${pdfString(\"Signature1\")}`,\n\t\t\t\t\t\"/F 4\",\n\t\t\t\t\t`/P ${sigPageNum} 0 R`,\n\t\t\t\t\t\">>\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t});\n\n\t\t\t// AcroForm\n\t\t\tobjects.push({\n\t\t\t\tobjNum: acroFormObjNum,\n\t\t\t\tcontent: [\n\t\t\t\t\t\"<< /Type /AcroForm\",\n\t\t\t\t\t\"/SigFlags 3\",\n\t\t\t\t\t`/Fields [${widgetObjNum} 0 R]`,\n\t\t\t\t\t\">>\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t});\n\n\t\t\t// Updated Root catalog with AcroForm\n\t\t\tlet rootContent = this.structure.rootDictContent;\n\t\t\trootContent = rootContent.replace(/\\/AcroForm\\s+\\d+\\s+\\d+\\s+R/g, \"\");\n\t\t\trootContent = rootContent.replace(/\\/Perms\\s*<<[^>]*>>/g, \"\");\n\t\t\trootContent = rootContent.replace(/\\/Perms\\s+\\d+\\s+\\d+\\s+R/g, \"\");\n\n\t\t\tobjects.push({\n\t\t\t\tobjNum: this.structure.rootNum,\n\t\t\t\tcontent: `<<${rootContent}\\n/AcroForm ${acroFormObjNum} 0 R\\n>>`,\n\t\t\t});\n\n\t\t\t// Updated sigPage with Annots\n\t\t\tconst sigPage = this.pages[sigPageIdx]!;\n\t\t\tlet pageContent: string;\n\n\t\t\t// Check if we already have this page in objects (from dirty page update)\n\t\t\tconst existingPageObj = objects.find((o) => o.objNum === sigPage.pageObjNum);\n\t\t\tif (existingPageObj) {\n\t\t\t\t// Extract content from existing updated page (strip outer << >>)\n\t\t\t\tpageContent = existingPageObj.content.slice(2, existingPageObj.content.length - 2);\n\t\t\t} else {\n\t\t\t\tpageContent = sigPage.originalDictContent;\n\t\t\t}\n\n\t\t\tif (pageContent.includes(\"/Annots\")) {\n\t\t\t\tconst bracketEnd = pageContent.indexOf(\"]\", pageContent.indexOf(\"/Annots\"));\n\t\t\t\tpageContent =\n\t\t\t\t\tpageContent.slice(0, bracketEnd) +\n\t\t\t\t\t` ${widgetObjNum} 0 R` +\n\t\t\t\t\tpageContent.slice(bracketEnd);\n\t\t\t} else {\n\t\t\t\tpageContent += `\\n/Annots [${widgetObjNum} 0 R]`;\n\t\t\t}\n\n\t\t\t// Update or add the page object\n\t\t\tif (existingPageObj) {\n\t\t\t\texistingPageObj.content = `<<${pageContent}\\n>>`;\n\t\t\t} else {\n\t\t\t\tobjects.push({\n\t\t\t\t\tobjNum: sigPage.pageObjNum,\n\t\t\t\t\tcontent: `<<${pageContent}\\n>>`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// --- Serialise incremental update ---\n\t\tconst newSize = currentNextObj;\n\t\tconst appendParts: Uint8Array[] = [];\n\t\tconst objectOffsets: Array<{ objNum: number; offset: number }> = [];\n\n\t\t// Compute starting byte offset (after original data)\n\t\tlet currentOffset = this.originalData.length;\n\n\t\tfor (const obj of objects) {\n\t\t\t// Separator newline\n\t\t\tconst sep = latin1Encoder.encode(\"\\n\");\n\t\t\tappendParts.push(sep);\n\t\t\tcurrentOffset += sep.length;\n\n\t\t\tobjectOffsets.push({ objNum: obj.objNum, offset: currentOffset });\n\n\t\t\tif (obj.streamData) {\n\t\t\t\t// Object with stream\n\t\t\t\tconst header = latin1Encoder.encode(`${obj.objNum} 0 obj\\n${obj.content}\\nstream\\n`);\n\t\t\t\tappendParts.push(header);\n\t\t\t\tcurrentOffset += header.length;\n\n\t\t\t\tappendParts.push(obj.streamData);\n\t\t\t\tcurrentOffset += obj.streamData.length;\n\n\t\t\t\tconst footer = latin1Encoder.encode(\"\\nendstream\\nendobj\\n\");\n\t\t\t\tappendParts.push(footer);\n\t\t\t\tcurrentOffset += footer.length;\n\t\t\t} else {\n\t\t\t\tconst objBytes = latin1Encoder.encode(\n\t\t\t\t\t`${obj.objNum} 0 obj\\n${obj.content}\\nendobj\\n`,\n\t\t\t\t);\n\t\t\t\tappendParts.push(objBytes);\n\t\t\t\tcurrentOffset += objBytes.length;\n\t\t\t}\n\t\t}\n\n\t\t// Xref table\n\t\tconst xrefOffset = currentOffset;\n\t\tconst xrefStr = buildXrefTable(objectOffsets);\n\t\tconst xrefBytes = latin1Encoder.encode(xrefStr);\n\t\tappendParts.push(xrefBytes);\n\t\tcurrentOffset += xrefBytes.length;\n\n\t\t// Trailer\n\t\tconst trailerLines = [\"<<\", `/Size ${newSize}`, `/Root ${this.structure.rootNum} 0 R`];\n\t\tif (this.structure.infoNum !== null) {\n\t\t\ttrailerLines.push(`/Info ${this.structure.infoNum} 0 R`);\n\t\t}\n\t\ttrailerLines.push(`/Prev ${this.structure.xrefOffset}`, \">>\");\n\n\t\tconst trailerStr =\n\t\t\t`trailer\\n${trailerLines.join(\"\\n\")}\\nstartxref\\n${xrefOffset}\\n%%EOF`;\n\t\tconst trailerBytes = latin1Encoder.encode(trailerStr);\n\t\tappendParts.push(trailerBytes);\n\n\t\t// Combine original + append parts\n\t\tconst totalAppendLength = appendParts.reduce((s, p) => s + p.length, 0);\n\t\tconst result = new Uint8Array(this.originalData.length + totalAppendLength);\n\t\tresult.set(this.originalData, 0);\n\t\tlet pos = this.originalData.length;\n\t\tfor (const part of appendParts) {\n\t\t\tresult.set(part, pos);\n\t\t\tpos += part.length;\n\t\t}\n\n\t\t// --- Calculate byte range for signature ---\n\t\tlet byteRange: [number, number, number, number] = [0, 0, 0, 0];\n\n\t\tif (withSignature) {\n\t\t\tconst br = updateByteRangeInPlace(result);\n\t\t\treturn { pdf: result, byteRange: br };\n\t\t}\n\n\t\treturn { pdf: result, byteRange };\n\t}\n\n\tprivate hasImagesForPage(page: PdfPageImpl): boolean {\n\t\treturn page.dirty && page.getImageRefs().size > 0;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction buildXrefTable(\n\tentries: Array<{ objNum: number; offset: number }>,\n): string {\n\tconst sorted = [...entries].sort((a, b) => a.objNum - b.objNum);\n\n\tconst subsections: Array<{ start: number; offsets: number[] }> = [];\n\tfor (const entry of sorted) {\n\t\tconst last = subsections[subsections.length - 1];\n\t\tif (last && entry.objNum === last.start + last.offsets.length) {\n\t\t\tlast.offsets.push(entry.offset);\n\t\t} else {\n\t\t\tsubsections.push({ start: entry.objNum, offsets: [entry.offset] });\n\t\t}\n\t}\n\n\tlet result = \"xref\\n\";\n\tfor (const sub of subsections) {\n\t\tresult += `${sub.start} ${sub.offsets.length}\\n`;\n\t\tfor (const offset of sub.offsets) {\n\t\t\tresult += `${String(offset).padStart(10, \"0\")} 00000 n \\n`;\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction formatPdfDate(date: Date): string {\n\tconst y = date.getUTCFullYear();\n\tconst m = String(date.getUTCMonth() + 1).padStart(2, \"0\");\n\tconst d = String(date.getUTCDate()).padStart(2, \"0\");\n\tconst h = String(date.getUTCHours()).padStart(2, \"0\");\n\tconst min = String(date.getUTCMinutes()).padStart(2, \"0\");\n\tconst s = String(date.getUTCSeconds()).padStart(2, \"0\");\n\treturn `D:${y}${m}${d}${h}${min}${s}Z`;\n}\n\nfunction pdfString(str: string): string {\n\tconst escaped = str\n\t\t.replace(/\\\\/g, \"\\\\\\\\\")\n\t\t.replace(/\\(/g, \"\\\\(\")\n\t\t.replace(/\\)/g, \"\\\\)\");\n\treturn `(${escaped})`;\n}\n\n/**\n * Find and overwrite the ByteRange placeholder in an assembled PDF buffer.\n * Modifies `pdf` in-place. Returns the final byte range values.\n */\nfunction updateByteRangeInPlace(pdf: Uint8Array): [number, number, number, number] {\n\t// Locate /Contents < ... >\n\tconst contentsIdx = findLastBytes(pdf, CONTENTS_MARKER);\n\tif (contentsIdx === -1) throw new Error(\"Cannot find Contents in signature\");\n\tconst contentsStart = contentsIdx + CONTENTS_MARKER.length;\n\tlet contentsEnd = contentsStart;\n\twhile (contentsEnd < pdf.length && pdf[contentsEnd] !== 0x3e) contentsEnd++;\n\tif (contentsEnd >= pdf.length) throw new Error(\"Cannot find end of Contents hex\");\n\n\tconst br: [number, number, number, number] = [\n\t\t0,\n\t\tcontentsStart - 1,\n\t\tcontentsEnd + 1,\n\t\tpdf.length - (contentsEnd + 1),\n\t];\n\n\t// Locate /ByteRange [ ... ]\n\tconst brIdx = findLastBytes(pdf, BYTE_RANGE_MARKER);\n\tif (brIdx === -1) throw new Error(\"Cannot find ByteRange in PDF\");\n\tconst brStart = brIdx + BYTE_RANGE_MARKER.length;\n\tlet brEnd = brStart;\n\twhile (brEnd < pdf.length && pdf[brEnd] !== 0x5d) brEnd++;\n\tif (brEnd >= pdf.length) throw new Error(\"Cannot find end of ByteRange\");\n\n\tconst placeholderLen = brEnd - brStart;\n\tconst brValueStr = `${br[0]} ${br[1]} ${br[2]} ${br[3]}`.padEnd(placeholderLen, \" \");\n\tpdf.set(latin1Encoder.encode(brValueStr), brStart);\n\n\treturn br;\n}\n\n/**\n * Find matching >> for a << in a content string\n */\nfunction findMatchingDictEndInContent(str: string, startPos: number): number {\n\tlet depth = 0;\n\tlet i = startPos;\n\n\twhile (i < str.length - 1) {\n\t\tif (str[i] === \"(\") {\n\t\t\ti++;\n\t\t\twhile (i < str.length && str[i] !== \")\") {\n\t\t\t\tif (str[i] === \"\\\\\") i++;\n\t\t\t\ti++;\n\t\t\t}\n\t\t\ti++;\n\t\t} else if (str[i] === \"<\" && str[i + 1] === \"<\") {\n\t\t\tdepth++;\n\t\t\ti += 2;\n\t\t} else if (str[i] === \">\" && str[i + 1] === \">\") {\n\t\t\tdepth--;\n\t\t\tif (depth === 0) return i;\n\t\t\ti += 2;\n\t\t} else {\n\t\t\ti++;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n// ---------------------------------------------------------------------------\n// Signature utility exports (for use by the e-signature library)\n// ---------------------------------------------------------------------------\n\n/**\n * Find the ByteRange and Contents placeholder in a signed PDF\n */\nexport function findByteRange(pdfData: Uint8Array): {\n\tbyteRange: [number, number, number, number];\n\tcontentsStart: number;\n\tcontentsEnd: number;\n\tplaceholderLength: number;\n} {\n\tconst contentsIdx = findLastBytes(pdfData, CONTENTS_MARKER);\n\tif (contentsIdx === -1) throw new Error(\"Could not find Contents in PDF\");\n\n\tconst contentsStart = contentsIdx + CONTENTS_MARKER.length;\n\tlet contentsEnd = contentsStart;\n\twhile (contentsEnd < pdfData.length && pdfData[contentsEnd] !== 0x3e) contentsEnd++;\n\tif (contentsEnd >= pdfData.length) throw new Error(\"Could not find end of Contents field\");\n\n\tconst placeholderLength = contentsEnd - contentsStart;\n\tconst byteRange: [number, number, number, number] = [\n\t\t0,\n\t\tcontentsStart - 1,\n\t\tcontentsEnd + 1,\n\t\tpdfData.length - (contentsEnd + 1),\n\t];\n\n\treturn { byteRange, contentsStart, contentsEnd, placeholderLength };\n}\n\n/**\n * Extract the bytes that need to be signed according to the ByteRange\n */\nexport function extractBytesToSign(\n\tpdfData: Uint8Array,\n\tbyteRange: [number, number, number, number],\n): Uint8Array {\n\tconst [offset1, length1, offset2, length2] = byteRange;\n\n\tif (offset1 < 0 || length1 <= 0 || offset2 <= 0 || length2 <= 0) {\n\t\tthrow new Error(`Invalid ByteRange values: [${byteRange.join(\", \")}]`);\n\t}\n\n\tif (offset1 + length1 > pdfData.length || offset2 + length2 > pdfData.length) {\n\t\tthrow new Error(\"ByteRange exceeds PDF data size\");\n\t}\n\n\t// Use subarray (zero-copy views) to avoid two intermediate allocations before\n\t// writing into the final combined buffer.\n\tconst chunk1 = pdfData.subarray(offset1, offset1 + length1);\n\tconst chunk2 = pdfData.subarray(offset2, offset2 + length2);\n\n\tconst result = new Uint8Array(chunk1.length + chunk2.length);\n\tresult.set(chunk1, 0);\n\tresult.set(chunk2, chunk1.length);\n\treturn result;\n}\n\n/**\n * Embed a signature (as raw bytes) into the Contents placeholder.\n *\n * **Mutates `pdfData` in-place** and returns the same buffer. Callers must not\n * retain a reference to `pdfData` and expect it to remain unchanged after this call.\n */\nexport function embedSignature(\n\tpdfData: Uint8Array,\n\tsignature: Uint8Array,\n): Uint8Array {\n\tconst { contentsStart, placeholderLength } = findByteRange(pdfData);\n\n\t// Convert signature to hex\n\tconst hexChars: string[] = [];\n\tfor (let i = 0; i < signature.length; i++) {\n\t\thexChars.push(signature[i]!.toString(16).padStart(2, \"0\"));\n\t}\n\tconst signatureHex = hexChars.join(\"\");\n\n\tif (signatureHex.length > placeholderLength) {\n\t\tthrow new Error(\n\t\t\t`Signature too large: ${signatureHex.length} hex chars, placeholder is ${placeholderLength}`,\n\t\t);\n\t}\n\n\tconst paddedHex = signatureHex.padEnd(placeholderLength, \"0\");\n\tconst hexBytes = new TextEncoder().encode(paddedHex);\n\n\t// Patch the placeholder in-place — pdfData is a freshly-created buffer from\n\t// saveWithPlaceholder() and not shared with any other consumer at this point,\n\t// so mutating it avoids allocating a full PDF-sized copy.\n\tpdfData.set(hexBytes, contentsStart);\n\treturn pdfData;\n}\n",
|
|
8
|
+
"/**\n * PDF Editing Plugin\n *\n * Load existing PDFs, modify them (draw text, rectangles, images),\n * and save with incremental updates. Also supports creating signature\n * placeholders for digital signing workflows.\n */\n\nexport type {\n\tPdfDocument,\n\tPdfPage,\n\tPdfImage,\n\tTextOptions,\n\tRectOptions,\n\tImageOptions,\n\tSignaturePlaceholderOptions,\n} from \"./types.ts\";\n\nexport { PdfDocumentImpl } from \"./document.ts\";\n\nexport {\n\tfindByteRange,\n\textractBytesToSign,\n\tembedSignature,\n} from \"./document.ts\";\n\nimport { PdfDocumentImpl } from \"./document.ts\";\nimport { parsePdfStructure } from \"./parser.ts\";\nimport type { PdfDocument } from \"./types.ts\";\n\n/**\n * Load an existing PDF for editing\n *\n * @param data - The PDF file contents as a Uint8Array\n * @returns A PdfDocument that can be modified and saved\n */\nexport function loadPdf(data: Uint8Array): PdfDocument {\n\treturn new PdfDocumentImpl(data);\n}\n\n/**\n * Count the number of pages in a PDF without fully loading it.\n *\n * @param data - The PDF file contents as a Uint8Array\n * @returns The number of pages in the PDF\n */\nexport function countPdfPages(data: Uint8Array): number {\n\tconst pdfStr = new TextDecoder(\"latin1\").decode(data);\n\tconst structure = parsePdfStructure(pdfStr);\n\treturn structure.pageNums.length;\n}\n"
|
|
9
|
+
],
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "A37956E5F13AB5E164756E2164756E21",
|
|
12
|
+
"names": []
|
|
13
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
PDFReader,
|
|
43
43
|
PDFSignatureError,
|
|
44
44
|
TokenType
|
|
45
|
-
} from "./index-
|
|
45
|
+
} from "./index-jpay67x2.js";
|
|
46
46
|
import {
|
|
47
47
|
createArray,
|
|
48
48
|
createDictionary,
|
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
} from "./index-4jtcmpfh.js";
|
|
58
58
|
import {
|
|
59
59
|
countPdfPages
|
|
60
|
-
} from "./index-
|
|
60
|
+
} from "./index-mstpgjxs.js";
|
|
61
61
|
export {
|
|
62
62
|
serializeValue,
|
|
63
63
|
serializeStream,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../../src/plugins/editing/document.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,KAAK,EACX,WAAW,EACX,QAAQ,EACR,OAAO,EACP,2BAA2B,EAC3B,MAAM,YAAY,CAAC;AAwFpB,qBAAa,eAAgB,YAAW,WAAW;IAClD,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAuC;IACxD,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,cAAc,CAOd;gBAEI,IAAI,EAAE,UAAU;
|
|
1
|
+
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../../src/plugins/editing/document.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,KAAK,EACX,WAAW,EACX,QAAQ,EACR,OAAO,EACP,2BAA2B,EAC3B,MAAM,YAAY,CAAC;AAwFpB,qBAAa,eAAgB,YAAW,WAAW;IAClD,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAuC;IACxD,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,cAAc,CAOd;gBAEI,IAAI,EAAE,UAAU;IAyB5B,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAS/B,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ;IAqBpC;;OAEG;IACH,IAAI,IAAI,UAAU;IAIlB;;OAEG;IACH,mBAAmB,CAAC,OAAO,EAAE,2BAA2B,GAAG;QAC1D,GAAG,EAAE,UAAU,CAAC;QAChB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;KAC5C;IAID,OAAO,CAAC,sBAAsB;IA4W9B,OAAO,CAAC,gBAAgB;CAGxB;AAsHD;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG;IACnD,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;CAC1B,CAkBA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GACzC,UAAU,CAoBZ;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC7B,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,UAAU,GACnB,UAAU,CAwBZ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../src/plugins/editing/page.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../src/plugins/editing/page.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAiF5F,qBAAa,WAAY,YAAW,OAAO;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,6DAA6D;IAC7D,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IAErC,kEAAkE;IAClE,OAAO,CAAC,SAAS,CAAgB;IAEjC,uDAAuD;IACvD,OAAO,CAAC,SAAS,CAAkC;IAEnD,oEAAoE;IACpE,UAAU,SAAK;IAEf,wDAAwD;IACxD,IAAI,KAAK,IAAI,OAAO,CAEnB;gBAGA,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,mBAAmB,EAAE,MAAM;IAQ5B;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI;IAkBlD;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IA6BzC;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAWvD;;OAEG;IACH,kBAAkB,IAAI,UAAU;IAYhC;;OAEG;IACH,YAAY,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;CAGnC"}
|
|
@@ -23,6 +23,8 @@ export type PdfStructure = {
|
|
|
23
23
|
pageNums: number[];
|
|
24
24
|
rootDictContent: string;
|
|
25
25
|
pageDictContents: string[];
|
|
26
|
+
/** Pre-built object position index for O(1) lookups */
|
|
27
|
+
objIndex: Map<number, number>;
|
|
26
28
|
};
|
|
27
29
|
/**
|
|
28
30
|
* Find the byte offset recorded after the last `startxref` keyword
|
|
@@ -41,11 +43,20 @@ export declare function parseTrailer(pdfStr: string): {
|
|
|
41
43
|
info: number | null;
|
|
42
44
|
prevXref: number;
|
|
43
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* Build an index mapping object numbers to their position (end of "N 0 obj" marker)
|
|
48
|
+
* in a single O(fileSize) pass. Callers look up objects in O(1) instead of
|
|
49
|
+
* scanning the entire string with a new regex per object.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildObjectIndex(pdfStr: string): Map<number, number>;
|
|
44
52
|
/**
|
|
45
53
|
* Extract the dictionary content (between outer << and >>) for a given object number.
|
|
46
54
|
* Returns the content string without the delimiters.
|
|
55
|
+
*
|
|
56
|
+
* When called with a pre-built objIndex, lookups are O(1).
|
|
57
|
+
* Falls back to a per-call regex search if no index is provided.
|
|
47
58
|
*/
|
|
48
|
-
export declare function extractObjectDictContent(pdfStr: string, objNum: number): string;
|
|
59
|
+
export declare function extractObjectDictContent(pdfStr: string, objNum: number, objIndex?: Map<number, number>): string;
|
|
49
60
|
/**
|
|
50
61
|
* Find all LEAF page object numbers by following Root -> Pages -> Kids recursively.
|
|
51
62
|
*
|
|
@@ -60,7 +71,7 @@ export declare function findPageObjects(pdfStr: string, rootNum: number): number
|
|
|
60
71
|
* Per the PDF spec, /MediaBox is inherited: if the Page object itself does not
|
|
61
72
|
* carry the entry, we walk up the /Parent chain until we find one.
|
|
62
73
|
*/
|
|
63
|
-
export declare function getMediaBox(pdfStr: string, pageObjNum: number): [number, number, number, number];
|
|
74
|
+
export declare function getMediaBox(pdfStr: string, pageObjNum: number, objIndex?: Map<number, number>): [number, number, number, number];
|
|
64
75
|
/**
|
|
65
76
|
* Parse the full PDF structure needed for incremental editing.
|
|
66
77
|
*
|
|
@@ -74,7 +85,7 @@ export declare function parsePdfStructure(pdfStr: string): PdfStructure;
|
|
|
74
85
|
* Returns a map of resource type names to their dictionary/array content strings.
|
|
75
86
|
* Example: { "/Font": "<< /F1 10 0 R >>", "/ProcSet": "[/PDF /Text]" }
|
|
76
87
|
*/
|
|
77
|
-
export declare function parseResourcesDict(pageContent: string, pdfStr: string): Record<string, string>;
|
|
88
|
+
export declare function parseResourcesDict(pageContent: string, pdfStr: string, objIndex?: Map<number, number>): Record<string, string>;
|
|
78
89
|
/**
|
|
79
90
|
* Merge two Resources dictionaries, combining entries from both.
|
|
80
91
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/plugins/editing/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/plugins/editing/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,uDAAuD;IACvD,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B,CAAC;AAEF;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CACjB,CA0CA;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAWpE;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACvC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,MAAM,CA6BR;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAOzE;AA8FD;;;;;GAKG;AACH,wBAAgB,WAAW,CAC1B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CA0BlC;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CA4B9D;AAkED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CACjC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA4BxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA0BxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/plugins/parsing/parser.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAA2B,MAAM,EAAa,MAAM,gBAAgB,CAAC;AAG3F;;GAEG;AACH,qBAAa,SAAS;IACnB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,IAAI,CAAa;gBAEb,IAAI,EAAE,UAAU;IAM5B;;OAEG;IACH,UAAU,IAAI,QAAQ;IAqBtB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA0BxB;;OAEG;IACH,OAAO,CAAC,WAAW;IAMnB;;OAEG;IACH,OAAO,CAAC,SAAS;IAMjB;;OAEG;IACH,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,OAAO,CAAC,SAAS;IAKjB;;OAEG;IACH,OAAO,CAAC,UAAU;IAelB;;OAEG;IACH,OAAO,CAAC,eAAe;IAyBvB;;OAEG;IACH,mBAAmB,IAAI;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,QAAQ,CAAA;KAAE;IAuCvD;;OAEG;IACH,OAAO,CAAC,WAAW;
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/plugins/parsing/parser.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAA2B,MAAM,EAAa,MAAM,gBAAgB,CAAC;AAG3F;;GAEG;AACH,qBAAa,SAAS;IACnB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,IAAI,CAAa;gBAEb,IAAI,EAAE,UAAU;IAM5B;;OAEG;IACH,UAAU,IAAI,QAAQ;IAqBtB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA0BxB;;OAEG;IACH,OAAO,CAAC,WAAW;IAMnB;;OAEG;IACH,OAAO,CAAC,SAAS;IAMjB;;OAEG;IACH,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,OAAO,CAAC,SAAS;IAKjB;;OAEG;IACH,OAAO,CAAC,UAAU;IAelB;;OAEG;IACH,OAAO,CAAC,eAAe;IAyBvB;;OAEG;IACH,mBAAmB,IAAI;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,QAAQ,CAAA;KAAE;IAuCvD;;OAEG;IACH,OAAO,CAAC,WAAW;IAuEnB;;OAEG;IACH,OAAO,CAAC,OAAO;IASf;;OAEG;IACH,OAAO,IAAI,OAAO;CAGpB"}
|
|
@@ -25,13 +25,19 @@ export interface ParsedPDFPage {
|
|
|
25
25
|
export declare class PDFReader {
|
|
26
26
|
private data;
|
|
27
27
|
private objects;
|
|
28
|
+
private xrefTable;
|
|
28
29
|
constructor(data: Uint8Array);
|
|
30
|
+
/**
|
|
31
|
+
* Lazily resolve an object by number — parses on first access.
|
|
32
|
+
*/
|
|
33
|
+
private resolveObject;
|
|
29
34
|
/**
|
|
30
35
|
* Parse PDF file
|
|
31
36
|
*/
|
|
32
37
|
parse(): ParsedPDF;
|
|
33
38
|
/**
|
|
34
|
-
* Find startxref offset
|
|
39
|
+
* Find startxref offset by scanning backwards from EOF.
|
|
40
|
+
* Only decodes the last 256 bytes instead of the entire PDF.
|
|
35
41
|
*/
|
|
36
42
|
private findStartXRef;
|
|
37
43
|
/**
|
|
@@ -42,10 +48,6 @@ export declare class PDFReader {
|
|
|
42
48
|
* Parse trailer dictionary
|
|
43
49
|
*/
|
|
44
50
|
private parseTrailer;
|
|
45
|
-
/**
|
|
46
|
-
* Read all objects from xref table
|
|
47
|
-
*/
|
|
48
|
-
private readObjects;
|
|
49
51
|
/**
|
|
50
52
|
* Parse PDF version from header
|
|
51
53
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../../src/plugins/parsing/reader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,MAAM,EAAY,MAAM,gBAAgB,CAAC;AAGtE;;GAEG;AACH,MAAM,WAAW,SAAS;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,SAAS;IACnB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,OAAO,CAA+B;
|
|
1
|
+
{"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../../src/plugins/parsing/reader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,MAAM,EAAY,MAAM,gBAAgB,CAAC;AAGtE;;GAEG;AACH,MAAM,WAAW,SAAS;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,SAAS;IACnB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,SAAS,CAAkC;gBAEvC,IAAI,EAAE,UAAU;IAI5B;;OAEG;IACH,OAAO,CAAC,aAAa;IAcrB;;OAEG;IACH,KAAK,IAAI,SAAS;IAuBlB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAYrB;;OAEG;IACH,OAAO,CAAC,cAAc;IAoCtB;;OAEG;IACH,OAAO,CAAC,YAAY;IAWpB;;OAEG;IACH,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,OAAO,CAAC,UAAU;IAyBlB;;OAEG;IACH,OAAO,CAAC,SAAS;IAoBjB;;OAEG;IACH,OAAO,CAAC,WAAW;CAsCrB"}
|
package/package.json
CHANGED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/plugins/editing/parser.ts", "../src/plugins/editing/page.ts", "../src/plugins/editing/document.ts", "../src/plugins/editing/index.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * Lightweight PDF structure parser for incremental editing\n *\n * Parses just enough of an existing PDF to enable incremental updates:\n * - Finds the cross-reference table via startxref\n * - Reads the trailer to get Root, Size, Info\n * - Follows Root -> Pages -> Kids to locate page objects\n * - Extracts MediaBox dimensions from pages\n *\n * All public functions accept a pre-decoded latin1 string (`pdfStr`) rather\n * than the raw Uint8Array so that the caller can decode ONCE and reuse the\n * string across many calls — avoiding O(pages) redundant allocations.\n */\n\n/**\n * Parsed PDF structure needed for incremental updates\n */\nexport type PdfStructure = {\n\txrefOffset: number;\n\trootNum: number;\n\tinfoNum: number | null;\n\tsize: number;\n\tpagesNum: number;\n\tpageNums: number[];\n\trootDictContent: string;\n\tpageDictContents: string[];\n};\n\n/**\n * Find the byte offset recorded after the last `startxref` keyword\n */\nexport function findStartXref(pdfStr: string): number {\n\tconst idx = pdfStr.lastIndexOf(\"startxref\");\n\tif (idx === -1) throw new Error(\"Cannot find startxref in PDF\");\n\tconst after = pdfStr.slice(idx + 9).trim().split(/[\\r\\n\\s]/)[0];\n\treturn parseInt(after!, 10);\n}\n\n/**\n * Parse the trailer dictionary to extract Root, Size, Info, and Prev xref offset.\n *\n * Supports both traditional trailers (`trailer << ... >>`) and\n * cross-reference streams (PDF 1.5+) where the trailer entries live\n * inside the xref stream object dictionary.\n */\nexport function parseTrailer(pdfStr: string): {\n\troot: number;\n\tsize: number;\n\tinfo: number | null;\n\tprevXref: number;\n} {\n\tconst startxrefIdx = pdfStr.lastIndexOf(\"startxref\");\n\n\t// Try traditional trailer first\n\tconst trailerIdx = pdfStr.lastIndexOf(\"trailer\");\n\n\tlet dictStr: string;\n\n\tif (trailerIdx !== -1 && trailerIdx < startxrefIdx) {\n\t\t// Traditional trailer\n\t\tdictStr = pdfStr.slice(trailerIdx, startxrefIdx);\n\t} else {\n\t\t// Cross-reference stream (PDF 1.5+): startxref points to an object\n\t\t// whose dictionary contains the trailer entries (Root, Size, Info, etc.)\n\t\tconst xrefOffset = findStartXref(pdfStr);\n\t\tconst xrefObjStr = pdfStr.slice(xrefOffset, xrefOffset + 4096);\n\t\tconst dictStart = xrefObjStr.indexOf(\"<<\");\n\t\tif (dictStart === -1) {\n\t\t\tthrow new Error(\"Cannot find trailer or xref stream dictionary in PDF\");\n\t\t}\n\t\tconst dictEnd = findMatchingDictEnd(xrefObjStr, dictStart);\n\t\tif (dictEnd === -1) {\n\t\t\tthrow new Error(\"Cannot find end of xref stream dictionary\");\n\t\t}\n\t\tdictStr = xrefObjStr.slice(dictStart, dictEnd + 2);\n\t}\n\n\tconst rootMatch = dictStr.match(/\\/Root\\s+(\\d+)\\s+\\d+\\s+R/);\n\tif (!rootMatch) throw new Error(\"Cannot find Root ref in trailer\");\n\n\tconst sizeMatch = dictStr.match(/\\/Size\\s+(\\d+)/);\n\tif (!sizeMatch) throw new Error(\"Cannot find Size in trailer\");\n\n\tconst infoMatch = dictStr.match(/\\/Info\\s+(\\d+)\\s+\\d+\\s+R/);\n\tconst prevMatch = dictStr.match(/\\/Prev\\s+(\\d+)/);\n\n\treturn {\n\t\troot: parseInt(rootMatch[1]!, 10),\n\t\tsize: parseInt(sizeMatch[1]!, 10),\n\t\tinfo: infoMatch ? parseInt(infoMatch[1]!, 10) : null,\n\t\tprevXref: prevMatch ? parseInt(prevMatch[1]!, 10) : findStartXref(pdfStr),\n\t};\n}\n\n/**\n * Extract the dictionary content (between outer << and >>) for a given object number.\n * Returns the content string without the delimiters.\n */\nexport function extractObjectDictContent(\n\tpdfStr: string,\n\tobjNum: number,\n): string {\n\tconst objRegex = new RegExp(`(?:^|\\\\s)${objNum}\\\\s+0\\\\s+obj`, \"m\");\n\tconst match = pdfStr.match(objRegex);\n\tif (!match || match.index === undefined) {\n\t\tthrow new Error(`Cannot find object ${objNum} in PDF`);\n\t}\n\n\tconst searchStart = match.index + match[0].length;\n\tconst dictStart = pdfStr.indexOf(\"<<\", searchStart);\n\tif (dictStart === -1 || dictStart > searchStart + 200) {\n\t\tthrow new Error(`Cannot find dictionary start for object ${objNum}`);\n\t}\n\n\tconst dictEnd = findMatchingDictEnd(pdfStr, dictStart);\n\tif (dictEnd === -1) {\n\t\tthrow new Error(`Cannot find dictionary end for object ${objNum}`);\n\t}\n\n\treturn pdfStr.slice(dictStart + 2, dictEnd);\n}\n\n/**\n * Find all LEAF page object numbers by following Root -> Pages -> Kids recursively.\n *\n * The PDF page tree can be arbitrarily deep — every ~100-200 pages, PDF tools\n * create intermediate Pages nodes (Type=Pages) that group their children.\n * This function recurses until it reaches actual Page leaves (Type=Page).\n */\nexport function findPageObjects(pdfStr: string, rootNum: number): number[] {\n\tconst rootContent = extractObjectDictContent(pdfStr, rootNum);\n\tconst pagesMatch = rootContent.match(/\\/Pages\\s+(\\d+)\\s+\\d+\\s+R/);\n\tif (!pagesMatch) throw new Error(\"Cannot find Pages ref in Root catalog\");\n\tconst pagesNum = parseInt(pagesMatch[1]!, 10);\n\n\treturn collectPageLeafs(pdfStr, pagesNum, new Set());\n}\n\n/**\n * Recursively collect leaf Page object numbers from a page tree node.\n * Handles both flat trees (all Kids are Pages) and nested trees\n * (intermediate Pages nodes with their own Kids arrays).\n */\nfunction collectPageLeafs(\n\tpdfStr: string,\n\tobjNum: number,\n\tvisited: Set<number>,\n): number[] {\n\tif (visited.has(objNum)) return []; // guard against malformed circular refs\n\tvisited.add(objNum);\n\n\tconst content = extractObjectDictContent(pdfStr, objNum);\n\n\t// Distinguish leaf Page from intermediate Pages node via /Type\n\tconst typeMatch = content.match(/\\/Type\\s+\\/(\\w+)/);\n\tif (typeMatch?.[1] === \"Page\") {\n\t\treturn [objNum];\n\t}\n\n\t// Intermediate Pages node — recurse into each kid\n\tconst kidsMatch = content.match(/\\/Kids\\s*\\[([^\\]]+)\\]/);\n\tif (!kidsMatch) {\n\t\t// Malformed node: no Kids and not a leaf — treat as single page (best effort)\n\t\treturn [objNum];\n\t}\n\n\tconst refs: number[] = [];\n\tconst refRegex = /(\\d+)\\s+\\d+\\s+R/g;\n\tlet m: RegExpExecArray | null;\n\twhile ((m = refRegex.exec(kidsMatch[1]!)) !== null) {\n\t\trefs.push(parseInt(m[1]!, 10));\n\t}\n\n\tconst pages: number[] = [];\n\tfor (const ref of refs) {\n\t\tpages.push(...collectPageLeafs(pdfStr, ref, visited));\n\t}\n\treturn pages;\n}\n\n/**\n * Get the MediaBox for a page object: [x1, y1, x2, y2].\n *\n * Per the PDF spec, /MediaBox is inherited: if the Page object itself does not\n * carry the entry, we walk up the /Parent chain until we find one.\n */\nexport function getMediaBox(\n\tpdfStr: string,\n\tpageObjNum: number,\n): [number, number, number, number] {\n\tconst visited = new Set<number>(); // guard against malformed circular refs\n\tlet objNum: number | null = pageObjNum;\n\n\twhile (objNum !== null && !visited.has(objNum)) {\n\t\tvisited.add(objNum);\n\t\tconst content = extractObjectDictContent(pdfStr, objNum);\n\n\t\tconst mediaBoxMatch = content.match(\n\t\t\t/\\/MediaBox\\s*\\[\\s*([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)\\s*\\]/,\n\t\t);\n\t\tif (mediaBoxMatch) {\n\t\t\treturn [\n\t\t\t\tparseFloat(mediaBoxMatch[1]!),\n\t\t\t\tparseFloat(mediaBoxMatch[2]!),\n\t\t\t\tparseFloat(mediaBoxMatch[3]!),\n\t\t\t\tparseFloat(mediaBoxMatch[4]!),\n\t\t\t];\n\t\t}\n\n\t\t// Walk up the parent chain\n\t\tconst parentMatch = content.match(/\\/Parent\\s+(\\d+)\\s+\\d+\\s+R/);\n\t\tobjNum = parentMatch ? parseInt(parentMatch[1]!, 10) : null;\n\t}\n\n\tthrow new Error(`Cannot find MediaBox for page object ${pageObjNum}`);\n}\n\n/**\n * Parse the full PDF structure needed for incremental editing.\n *\n * @param pdfStr - The PDF file decoded as a latin1 string (decode ONCE and pass here)\n */\nexport function parsePdfStructure(pdfStr: string): PdfStructure {\n\tconst xrefOffset = findStartXref(pdfStr);\n\tconst trailer = parseTrailer(pdfStr);\n\n\tconst rootContent = extractObjectDictContent(pdfStr, trailer.root);\n\tconst pagesMatch = rootContent.match(/\\/Pages\\s+(\\d+)\\s+\\d+\\s+R/);\n\tif (!pagesMatch) throw new Error(\"Cannot find Pages ref in Root catalog\");\n\tconst pagesNum = parseInt(pagesMatch[1]!, 10);\n\n\tconst pageNums = findPageObjects(pdfStr, trailer.root);\n\tconst pageDictContents = pageNums.map((pn) =>\n\t\textractObjectDictContent(pdfStr, pn),\n\t);\n\n\treturn {\n\t\txrefOffset,\n\t\trootNum: trailer.root,\n\t\tinfoNum: trailer.info,\n\t\tsize: trailer.size,\n\t\tpagesNum,\n\t\tpageNums,\n\t\trootDictContent: rootContent,\n\t\tpageDictContents,\n\t};\n}\n\n/**\n * Find the position of the >> that closes the dictionary starting at startPos.\n * Handles nested << >> and skips PDF string literals in parentheses.\n */\nfunction findMatchingDictEnd(str: string, startPos: number): number {\n\tlet depth = 0;\n\tlet i = startPos;\n\n\twhile (i < str.length - 1) {\n\t\tif (str[i] === \"(\") {\n\t\t\t// skip parenthesized string\n\t\t\ti++;\n\t\t\twhile (i < str.length && str[i] !== \")\") {\n\t\t\t\tif (str[i] === \"\\\\\") i++;\n\t\t\t\ti++;\n\t\t\t}\n\t\t\ti++; // skip ')'\n\t\t} else if (str[i] === \"<\" && str[i + 1] === \"<\") {\n\t\t\tdepth++;\n\t\t\ti += 2;\n\t\t} else if (str[i] === \">\" && str[i + 1] === \">\") {\n\t\t\tdepth--;\n\t\t\tif (depth === 0) return i;\n\t\t\ti += 2;\n\t\t} else {\n\t\t\ti++;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/**\n * Find the position of the ] that closes the array starting at startPos.\n * Handles nested [ ] and skips PDF string literals in parentheses.\n */\nfunction findMatchingArrayEnd(str: string, startPos: number): number {\n\tlet depth = 0;\n\tlet i = startPos;\n\n\twhile (i < str.length) {\n\t\tif (str[i] === \"(\") {\n\t\t\t// skip parenthesized string\n\t\t\ti++;\n\t\t\twhile (i < str.length && str[i] !== \")\") {\n\t\t\t\tif (str[i] === \"\\\\\") i++;\n\t\t\t\ti++;\n\t\t\t}\n\t\t\ti++; // skip ')'\n\t\t} else if (str[i] === \"[\") {\n\t\t\tdepth++;\n\t\t\ti++;\n\t\t} else if (str[i] === \"]\") {\n\t\t\tdepth--;\n\t\t\tif (depth === 0) return i;\n\t\t\ti++;\n\t\t} else {\n\t\t\ti++;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/**\n * Parse a Resources dictionary from page content, handling both inline\n * dictionaries and indirect references.\n *\n * Returns a map of resource type names to their dictionary/array content strings.\n * Example: { \"/Font\": \"<< /F1 10 0 R >>\", \"/ProcSet\": \"[/PDF /Text]\" }\n */\nexport function parseResourcesDict(\n\tpageContent: string,\n\tpdfStr: string,\n): Record<string, string> {\n\tconst result: Record<string, string> = {};\n\n\t// Check for inline Resources dictionary\n\tconst inlineMatch = pageContent.match(/\\/Resources\\s*<</);\n\tif (inlineMatch) {\n\t\tconst resIdx = pageContent.indexOf(\"/Resources\");\n\t\tconst resStart = pageContent.indexOf(\"<<\", resIdx);\n\t\tconst resEnd = findMatchingDictEnd(pageContent, resStart);\n\n\t\tif (resEnd === -1) {\n\t\t\tthrow new Error(\"Cannot find end of Resources dictionary\");\n\t\t}\n\n\t\tconst resContent = pageContent.slice(resStart + 2, resEnd);\n\t\treturn parseResourceEntries(resContent);\n\t}\n\n\t// Check for indirect Resources reference\n\tconst refMatch = pageContent.match(/\\/Resources\\s+(\\d+)\\s+\\d+\\s+R/);\n\tif (refMatch) {\n\t\tconst objNum = parseInt(refMatch[1]!, 10);\n\t\tconst objContent = extractObjectDictContent(pdfStr, objNum);\n\t\treturn parseResourceEntries(objContent);\n\t}\n\n\t// No Resources found\n\treturn result;\n}\n\n/**\n * Merge two Resources dictionaries, combining entries from both.\n *\n * For dictionary-type entries like /Font, /XObject, extracts individual\n * name-reference pairs and combines them. For array-type entries like\n * /ProcSet, uses the existing value (no merge needed).\n *\n * @param existing - Parsed Resources from original page\n * @param additions - New Resources to add (from signature appearance)\n * @returns Merged Resources dictionary entries\n */\nexport function mergeResourcesDicts(\n\texisting: Record<string, string>,\n\tadditions: Record<string, string>,\n): Record<string, string> {\n\tconst result = { ...existing };\n\n\tfor (const [resType, addValue] of Object.entries(additions)) {\n\t\tif (!result[resType]) {\n\t\t\t// No existing entry for this type, just add it\n\t\t\tresult[resType] = addValue;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst existingValue = result[resType]!;\n\n\t\t// Arrays (like /ProcSet) - keep existing, don't merge\n\t\tif (existingValue.startsWith(\"[\")) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Dictionaries - merge entries\n\t\tif (existingValue.startsWith(\"<<\")) {\n\t\t\tresult[resType] = mergeDictEntries(existingValue, addValue);\n\t\t} else {\n\t\t\tthrow new Error(`Unexpected resource format for ${resType}: ${existingValue}`);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Merge two PDF dictionary strings by combining their name-reference pairs.\n *\n * Example:\n * existing: \"<< /F1 10 0 R /F2 11 0 R >>\"\n * additions: \"<< /SigF1 20 0 R >>\"\n * result: \"<< /F1 10 0 R /F2 11 0 R /SigF1 20 0 R >>\"\n */\nfunction mergeDictEntries(existing: string, additions: string): string {\n\t// Extract entries from both dictionaries\n\tconst existingEntries = extractDictEntries(existing);\n\tconst additionEntries = extractDictEntries(additions);\n\n\t// Combine (additions override existing if same key)\n\tconst merged = { ...existingEntries, ...additionEntries };\n\n\t// Rebuild dictionary string\n\tconst entries = Object.entries(merged)\n\t\t.map(([name, ref]) => `${name} ${ref}`)\n\t\t.join(\" \");\n\n\treturn `<< ${entries} >>`;\n}\n\n/**\n * Extract name-reference pairs from a PDF dictionary string.\n *\n * Example: \"<< /F1 10 0 R /F2 11 0 R >>\"\n * Returns: { \"/F1\": \"10 0 R\", \"/F2\": \"11 0 R\" }\n */\nfunction extractDictEntries(dict: string): Record<string, string> {\n\tconst entries: Record<string, string> = {};\n\n\t// Remove outer << >>\n\tconst inner = dict.replace(/^<<\\s*/, \"\").replace(/\\s*>>$/, \"\");\n\n\t// Match /Name objNum gen R patterns\n\t// Pattern matches PDF names with hyphens, dots, and hex-encoded characters\n\tconst regex = /(\\/[^\\s<>\\[\\]()\\/]+)\\s+(\\d+\\s+\\d+\\s+R)/g;\n\tlet match: RegExpExecArray | null;\n\n\twhile ((match = regex.exec(inner)) !== null) {\n\t\tentries[match[1]!] = match[2]!;\n\t}\n\n\treturn entries;\n}\n\n/**\n * Parse individual resource entries from a Resources dictionary content string.\n *\n * Extracts top-level entries like /Font, /XObject, /ExtGState, etc.\n */\nfunction parseResourceEntries(content: string): Record<string, string> {\n\tconst result: Record<string, string> = {};\n\n\t// Resource entry names to extract\n\tconst resourceTypes = [\n\t\t\"/Font\",\n\t\t\"/XObject\",\n\t\t\"/ExtGState\",\n\t\t\"/ColorSpace\",\n\t\t\"/Pattern\",\n\t\t\"/Shading\",\n\t\t\"/ProcSet\",\n\t];\n\n\tfor (const resType of resourceTypes) {\n\t\t// Use regex to match resource type at dictionary level (not nested inside values)\n\t\t// Pattern: /ResourceType followed by whitespace and then either << or [\n\t\tconst pattern = new RegExp(\n\t\t\t`${resType.replace(/\\//g, \"\\\\/\")}\\\\s+([<\\\\[])`\n\t\t);\n\t\tconst match = content.match(pattern);\n\n\t\tif (!match) continue;\n\n\t\tconst idx = match.index!;\n\n\t\t// Find the value (either << dict >> or [ array ])\n\t\tlet valueStart = idx + resType.length;\n\t\twhile (valueStart < content.length && /\\s/.test(content[valueStart]!)) {\n\t\t\tvalueStart++;\n\t\t}\n\n\t\tif (content[valueStart] === \"<\" && content[valueStart + 1] === \"<\") {\n\t\t\t// Dictionary value\n\t\t\tconst dictEnd = findMatchingDictEnd(content, valueStart);\n\t\t\tif (dictEnd === -1) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot find end of ${resType} dictionary`\n\t\t\t\t);\n\t\t\t}\n\t\t\tresult[resType] = content.slice(valueStart, dictEnd + 2);\n\t\t} else if (content[valueStart] === \"[\") {\n\t\t\t// Array value\n\t\t\tconst arrayEnd = findMatchingArrayEnd(content, valueStart);\n\t\t\tif (arrayEnd === -1) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot find end of ${resType} array`\n\t\t\t\t);\n\t\t\t}\n\t\t\tresult[resType] = content.slice(valueStart, arrayEnd + 1);\n\t\t}\n\t}\n\n\treturn result;\n}\n",
|
|
6
|
-
"/**\n * PdfPage implementation for the editing plugin\n *\n * Collects drawing operations as PDF content stream operators.\n * The accumulated operators are later serialised as a new content stream\n * object appended via incremental update.\n */\n\nimport type { PdfImage, PdfPage, TextOptions, RectOptions, ImageOptions } from \"./types.ts\";\n\n/**\n * Parse a hex colour string like \"#RRGGBB\" into normalised [r, g, b] values (0-1).\n * Returns null for invalid/missing input so callers can fall back to defaults.\n */\nfunction parseHexColor(hex: string | undefined): [number, number, number] | null {\n\tif (!hex) return null;\n\tconst m = hex.match(/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);\n\tif (!m) return null;\n\treturn [\n\t\tparseInt(m[1]!, 16) / 255,\n\t\tparseInt(m[2]!, 16) / 255,\n\t\tparseInt(m[3]!, 16) / 255,\n\t];\n}\n\nexport class PdfPageImpl implements PdfPage {\n\treadonly width: number;\n\treadonly height: number;\n\n\t/** The existing page object number in the original PDF */\n\treadonly pageObjNum: number;\n\t/** The raw dictionary content string of the original page */\n\treadonly originalDictContent: string;\n\n\t/** Accumulated content-stream operators added by draw* methods */\n\tprivate operators: string[] = [];\n\n\t/** Images referenced by drawImage (name -> obj num) */\n\tprivate imageRefs: Map<string, number> = new Map();\n\n\t/** Font object number allocated by the document (set externally) */\n\tfontObjNum = 0;\n\n\t/** Whether any drawing operations have been recorded */\n\tget dirty(): boolean {\n\t\treturn this.operators.length > 0;\n\t}\n\n\tconstructor(\n\t\tpageObjNum: number,\n\t\twidth: number,\n\t\theight: number,\n\t\toriginalDictContent: string,\n\t) {\n\t\tthis.pageObjNum = pageObjNum;\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t\tthis.originalDictContent = originalDictContent;\n\t}\n\n\t/**\n\t * Draw text on the page using Helvetica\n\t */\n\tdrawText(text: string, options: TextOptions): void {\n\t\tconst { x, y, size = 12, color } = options;\n\t\tconst rgb = parseHexColor(color);\n\n\t\tif (rgb) {\n\t\t\tthis.operators.push(`${rgb[0].toFixed(3)} ${rgb[1].toFixed(3)} ${rgb[2].toFixed(3)} rg`);\n\t\t}\n\n\t\t// Escape special PDF string characters\n\t\tconst escaped = text\n\t\t\t.replace(/\\\\/g, \"\\\\\\\\\")\n\t\t\t.replace(/\\(/g, \"\\\\(\")\n\t\t\t.replace(/\\)/g, \"\\\\)\");\n\n\t\tthis.operators.push(\"BT\");\n\t\tthis.operators.push(`/F1 ${size} Tf`);\n\t\tthis.operators.push(`${x} ${y} Td`);\n\t\tthis.operators.push(`(${escaped}) Tj`);\n\t\tthis.operators.push(\"ET\");\n\t}\n\n\t/**\n\t * Draw a rectangle on the page\n\t */\n\tdrawRectangle(options: RectOptions): void {\n\t\tconst { x, y, width, height, color, borderColor, borderWidth } = options;\n\n\t\tconst fillRgb = parseHexColor(color);\n\t\tconst strokeRgb = parseHexColor(borderColor);\n\n\t\tif (fillRgb) {\n\t\t\tthis.operators.push(`${fillRgb[0].toFixed(3)} ${fillRgb[1].toFixed(3)} ${fillRgb[2].toFixed(3)} rg`);\n\t\t}\n\t\tif (strokeRgb) {\n\t\t\tthis.operators.push(`${strokeRgb[0].toFixed(3)} ${strokeRgb[1].toFixed(3)} ${strokeRgb[2].toFixed(3)} RG`);\n\t\t}\n\t\tif (borderWidth !== undefined) {\n\t\t\tthis.operators.push(`${borderWidth} w`);\n\t\t}\n\n\t\tthis.operators.push(`${x} ${y} ${width} ${height} re`);\n\n\t\tif (fillRgb && strokeRgb) {\n\t\t\tthis.operators.push(\"B\"); // fill and stroke\n\t\t} else if (fillRgb) {\n\t\t\tthis.operators.push(\"f\"); // fill only\n\t\t} else if (strokeRgb) {\n\t\t\tthis.operators.push(\"S\"); // stroke only\n\t\t} else {\n\t\t\tthis.operators.push(\"f\"); // default: fill with current colour (black)\n\t\t}\n\t}\n\n\t/**\n\t * Draw an embedded image on the page\n\t */\n\tdrawImage(image: PdfImage, options: ImageOptions): void {\n\t\tconst { x, y, width, height } = options;\n\t\tconst imgName = `Im${image.objectNumber}`;\n\t\tthis.imageRefs.set(imgName, image.objectNumber);\n\n\t\tthis.operators.push(\"q\");\n\t\tthis.operators.push(`${width} 0 0 ${height} ${x} ${y} cm`);\n\t\tthis.operators.push(`/${imgName} Do`);\n\t\tthis.operators.push(\"Q\");\n\t}\n\n\t/**\n\t * Build the content stream bytes for the accumulated operators\n\t */\n\tbuildContentStream(): Uint8Array {\n\t\tconst content = this.operators.join(\"\\n\");\n\t\treturn new TextEncoder().encode(content);\n\t}\n\n\t/**\n\t * Get image references used in drawing operations\n\t */\n\tgetImageRefs(): Map<string, number> {\n\t\treturn new Map(this.imageRefs);\n\t}\n}\n",
|
|
7
|
-
"/**\n * PdfDocument implementation for the editing plugin\n *\n * Manages loading an existing PDF, tracking modifications, and producing an\n * incremental update (appended after the original %%EOF) that adds or\n * overrides objects without rewriting the original content.\n */\n\nimport {\n\tparsePdfStructure,\n\tgetMediaBox,\n\textractObjectDictContent,\n\tparseResourcesDict,\n\tmergeResourcesDicts,\n} from \"./parser.ts\";\nimport { PdfPageImpl } from \"./page.ts\";\nimport type {\n\tPdfDocument,\n\tPdfImage,\n\tPdfPage,\n\tSignaturePlaceholderOptions,\n} from \"./types.ts\";\n\nconst BYTE_RANGE_PLACEHOLDER = \"0 0000000000 0000000000 0000000000\";\nconst DEFAULT_SIGNATURE_LENGTH = 16384;\n\nconst latin1Encoder = new TextEncoder(); // UTF-8 but we only feed ASCII/latin1-safe chars\nconst latin1Decoder = new TextDecoder(\"latin1\");\n\n// Pre-encoded byte patterns for PDF structure search (avoids per-call allocation)\nconst CONTENTS_MARKER = latin1Encoder.encode(\"/Contents <\");\nconst BYTE_RANGE_MARKER = latin1Encoder.encode(\"/ByteRange [\");\n\n/**\n * Search for the last occurrence of `pattern` inside `data`.\n * Returns the byte offset of the first byte of the match, or -1.\n */\nfunction findLastBytes(data: Uint8Array, pattern: Uint8Array): number {\n\touter: for (let i = data.length - pattern.length; i >= 0; i--) {\n\t\tfor (let j = 0; j < pattern.length; j++) {\n\t\t\tif (data[i + j] !== pattern[j]) continue outer;\n\t\t}\n\t\treturn i;\n\t}\n\treturn -1;\n}\n\n/**\n * Parse PNG IHDR to extract width, height, bit depth, and colour type.\n */\nfunction parsePngIhdr(data: Uint8Array): {\n\twidth: number;\n\theight: number;\n\tbitDepth: number;\n\tcolorType: number;\n} {\n\t// PNG signature: 8 bytes, then first chunk is IHDR\n\tconst sig = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];\n\tfor (let i = 0; i < sig.length; i++) {\n\t\tif (data[i] !== sig[i]) throw new Error(\"Not a valid PNG file\");\n\t}\n\n\t// IHDR chunk starts at offset 8\n\t// 4 bytes length + 4 bytes \"IHDR\" + 13 bytes data\n\tconst view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\tconst chunkType = latin1Decoder.decode(data.slice(12, 16));\n\tif (chunkType !== \"IHDR\") throw new Error(\"First PNG chunk is not IHDR\");\n\n\treturn {\n\t\twidth: view.getUint32(16),\n\t\theight: view.getUint32(20),\n\t\tbitDepth: data[24]!,\n\t\tcolorType: data[25]!,\n\t};\n}\n\n/**\n * Extract and concatenate all IDAT chunk data from a PNG\n */\nfunction extractIdatData(data: Uint8Array): Uint8Array {\n\tconst view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\tconst chunks: Uint8Array[] = [];\n\tlet offset = 8; // skip PNG signature\n\n\twhile (offset < data.length) {\n\t\tconst chunkLen = view.getUint32(offset);\n\t\tconst chunkType = latin1Decoder.decode(data.slice(offset + 4, offset + 8));\n\n\t\tif (chunkType === \"IDAT\") {\n\t\t\tchunks.push(data.slice(offset + 8, offset + 8 + chunkLen));\n\t\t}\n\n\t\t// skip: length(4) + type(4) + data(chunkLen) + crc(4)\n\t\toffset += 12 + chunkLen;\n\t}\n\n\tif (chunks.length === 0) throw new Error(\"No IDAT chunks found in PNG\");\n\n\t// Concatenate all IDAT data\n\tconst totalLen = chunks.reduce((s, c) => s + c.length, 0);\n\tconst result = new Uint8Array(totalLen);\n\tlet pos = 0;\n\tfor (const chunk of chunks) {\n\t\tresult.set(chunk, pos);\n\t\tpos += chunk.length;\n\t}\n\treturn result;\n}\n\nexport class PdfDocumentImpl implements PdfDocument {\n\tprivate originalData: Uint8Array;\n\tprivate pdfStr: string; // latin1 string decoded ONCE — reused by all parser calls\n\tprivate structure: ReturnType<typeof parsePdfStructure>;\n\tprivate pages: PdfPageImpl[] = [];\n\tprivate nextObjNum: number;\n\tprivate fontObjNum: number;\n\tprivate embeddedImages: Array<{\n\t\tobjNum: number;\n\t\twidth: number;\n\t\theight: number;\n\t\tidatData: Uint8Array;\n\t\tcolorType: number;\n\t\tbitDepth: number;\n\t}> = [];\n\n\tconstructor(data: Uint8Array) {\n\t\tthis.originalData = data;\n\t\t// Decode the PDF bytes to a latin1 string exactly ONCE.\n\t\t// All parser helpers reuse this string so we never create redundant copies.\n\t\tthis.pdfStr = latin1Decoder.decode(data);\n\t\tthis.structure = parsePdfStructure(this.pdfStr);\n\n\t\t// Allocate a font object number right away (Helvetica)\n\t\tthis.nextObjNum = this.structure.size;\n\t\tthis.fontObjNum = this.nextObjNum++;\n\n\t\t// Build page objects\n\t\tfor (let i = 0; i < this.structure.pageNums.length; i++) {\n\t\t\tconst pageNum = this.structure.pageNums[i]!;\n\t\t\tconst mediaBox = getMediaBox(this.pdfStr, pageNum);\n\t\t\tconst width = mediaBox[2] - mediaBox[0];\n\t\t\tconst height = mediaBox[3] - mediaBox[1];\n\t\t\tconst dictContent = this.structure.pageDictContents[i]!;\n\t\t\tconst page = new PdfPageImpl(pageNum, width, height, dictContent);\n\t\t\tpage.fontObjNum = this.fontObjNum;\n\t\t\tthis.pages.push(page);\n\t\t}\n\t}\n\n\tget pageCount(): number {\n\t\treturn this.pages.length;\n\t}\n\n\tgetPage(index: number): PdfPage {\n\t\tif (index < 0 || index >= this.pages.length) {\n\t\t\tthrow new Error(\n\t\t\t\t`Page index ${index} out of range (0-${this.pages.length - 1})`,\n\t\t\t);\n\t\t}\n\t\treturn this.pages[index]!;\n\t}\n\n\tembedPng(data: Uint8Array): PdfImage {\n\t\tconst ihdr = parsePngIhdr(data);\n\t\tconst idatData = extractIdatData(data);\n\t\tconst objNum = this.nextObjNum++;\n\n\t\tthis.embeddedImages.push({\n\t\t\tobjNum,\n\t\t\twidth: ihdr.width,\n\t\t\theight: ihdr.height,\n\t\t\tidatData,\n\t\t\tcolorType: ihdr.colorType,\n\t\t\tbitDepth: ihdr.bitDepth,\n\t\t});\n\n\t\treturn {\n\t\t\tobjectNumber: objNum,\n\t\t\twidth: ihdr.width,\n\t\t\theight: ihdr.height,\n\t\t};\n\t}\n\n\t/**\n\t * Save the modified PDF using an incremental update\n\t */\n\tsave(): Uint8Array {\n\t\treturn this.buildIncrementalUpdate(false).pdf;\n\t}\n\n\t/**\n\t * Save with a signature placeholder for digital signing\n\t */\n\tsaveWithPlaceholder(options: SignaturePlaceholderOptions): {\n\t\tpdf: Uint8Array;\n\t\tbyteRange: [number, number, number, number];\n\t} {\n\t\treturn this.buildIncrementalUpdate(true, options);\n\t}\n\n\tprivate buildIncrementalUpdate(\n\t\twithSignature: boolean,\n\t\tsigOptions?: SignaturePlaceholderOptions,\n\t): { pdf: Uint8Array; byteRange: [number, number, number, number] } {\n\t\tconst objects: Array<{ objNum: number; content: string; streamData?: Uint8Array }> = [];\n\t\tlet currentNextObj = this.nextObjNum;\n\n\t\t// --- 1. Font object (Helvetica, always emitted if any page is dirty) ---\n\t\tconst anyDirty = this.pages.some((p) => p.dirty);\n\t\tif (anyDirty || this.embeddedImages.length > 0) {\n\t\t\tobjects.push({\n\t\t\t\tobjNum: this.fontObjNum,\n\t\t\t\tcontent: \"<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>\",\n\t\t\t});\n\t\t}\n\n\t\t// --- 2. Embedded image XObjects ---\n\t\tfor (const img of this.embeddedImages) {\n\t\t\tconst colorSpace = img.colorType === 2 ? \"/DeviceRGB\" : img.colorType === 0 ? \"/DeviceGray\" : \"/DeviceRGB\";\n\t\t\tconst colors = img.colorType === 2 ? 3 : 1;\n\t\t\tconst bpc = img.bitDepth;\n\n\t\t\t// PNG IDAT data uses per-row filter bytes. Tell the PDF reader\n\t\t\t// via DecodeParms with Predictor 15 (PNG optimum prediction).\n\t\t\tobjects.push({\n\t\t\t\tobjNum: img.objNum,\n\t\t\t\tcontent: [\n\t\t\t\t\t\"<< /Type /XObject\",\n\t\t\t\t\t\"/Subtype /Image\",\n\t\t\t\t\t`/Width ${img.width}`,\n\t\t\t\t\t`/Height ${img.height}`,\n\t\t\t\t\t`/ColorSpace ${colorSpace}`,\n\t\t\t\t\t`/BitsPerComponent ${bpc}`,\n\t\t\t\t\t\"/Filter /FlateDecode\",\n\t\t\t\t\t`/DecodeParms << /Predictor 15 /Colors ${colors} /BitsPerComponent ${bpc} /Columns ${img.width} >>`,\n\t\t\t\t\t`/Length ${img.idatData.length}`,\n\t\t\t\t\t\">>\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\tstreamData: img.idatData,\n\t\t\t});\n\t\t}\n\n\t\t// --- 3. Wrapper save-state streams + content streams for dirty pages ---\n\t\t// The original page content may modify the CTM (e.g. Y-axis flip for\n\t\t// top-left origin). We wrap the original content in q/Q so our new\n\t\t// drawing operators run with the default PDF coordinate system.\n\t\tconst wrapperStreamMap = new Map<number, number>(); // pageObjNum -> wrapperStreamObjNum\n\t\tconst contentStreamMap = new Map<number, number>(); // pageObjNum -> contentStreamObjNum\n\t\tfor (const page of this.pages) {\n\t\t\tif (!page.dirty) continue;\n\n\t\t\t// \"save state\" stream — placed BEFORE original content\n\t\t\tconst wrapperObjNum = currentNextObj++;\n\t\t\twrapperStreamMap.set(page.pageObjNum, wrapperObjNum);\n\t\t\tconst wrapperData = latin1Encoder.encode(\"q\");\n\t\t\tobjects.push({\n\t\t\t\tobjNum: wrapperObjNum,\n\t\t\t\tcontent: `<< /Length ${wrapperData.length} >>`,\n\t\t\t\tstreamData: wrapperData,\n\t\t\t});\n\n\t\t\t// Actual content stream — prefixed with Q to restore state\n\t\t\tconst contentObjNum = currentNextObj++;\n\t\t\tcontentStreamMap.set(page.pageObjNum, contentObjNum);\n\t\t\tconst pageStreamData = page.buildContentStream();\n\t\t\tconst prefixedData = new Uint8Array(2 + pageStreamData.length);\n\t\t\tprefixedData[0] = 0x51; // 'Q'\n\t\t\tprefixedData[1] = 0x0a; // '\\n'\n\t\t\tprefixedData.set(pageStreamData, 2);\n\t\t\tobjects.push({\n\t\t\t\tobjNum: contentObjNum,\n\t\t\t\tcontent: `<< /Length ${prefixedData.length} >>`,\n\t\t\t\tstreamData: prefixedData,\n\t\t\t});\n\t\t}\n\n\t\t// --- 4. Updated page dictionaries (add new content stream + font/image resources) ---\n\t\tfor (const page of this.pages) {\n\t\t\tif (!page.dirty && !this.hasImagesForPage(page)) continue;\n\n\t\t\tlet pageContent = page.originalDictContent;\n\n\t\t\t// Add or replace Contents reference if page is dirty\n\t\t\tif (page.dirty) {\n\t\t\t\tconst contentObjNum = contentStreamMap.get(page.pageObjNum)!;\n\t\t\t\tconst wrapperObjNum = wrapperStreamMap.get(page.pageObjNum)!;\n\n\t\t\t\tif (pageContent.match(/\\/Contents\\s/)) {\n\t\t\t\t\t// Replace existing Contents with an array: [wrapper, original, new]\n\t\t\t\t\t// The wrapper stream saves graphics state (q) before original content,\n\t\t\t\t\t// and the new stream restores it (Q) before our drawing operators.\n\t\t\t\t\tpageContent = pageContent.replace(\n\t\t\t\t\t\t/\\/Contents\\s+(\\d+\\s+\\d+\\s+R)/,\n\t\t\t\t\t\t`/Contents [${wrapperObjNum} 0 R $1 ${contentObjNum} 0 R]`,\n\t\t\t\t\t);\n\t\t\t\t\t// Also handle existing Contents arrays\n\t\t\t\t\tpageContent = pageContent.replace(\n\t\t\t\t\t\t/\\/Contents\\s*\\[([^\\]]+)\\]/,\n\t\t\t\t\t\t(match, inner) => {\n\t\t\t\t\t\t\t// If we already added our ref above, skip\n\t\t\t\t\t\t\tif (inner.includes(`${contentObjNum} 0 R`)) return match;\n\t\t\t\t\t\t\treturn `/Contents [${wrapperObjNum} 0 R ${inner.trim()} ${contentObjNum} 0 R]`;\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tpageContent += `\\n/Contents ${contentObjNum} 0 R`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Build signature's new resources\n\t\t\tconst newResourceParts: string[] = [];\n\t\t\tnewResourceParts.push(`/Font << /F1 ${this.fontObjNum} 0 R >>`);\n\n\t\t\t// Image resources\n\t\t\tconst imageRefs = page.dirty ? (page as PdfPageImpl).getImageRefs() : new Map<string, number>();\n\t\t\tif (imageRefs.size > 0) {\n\t\t\t\tconst xobjEntries = Array.from(imageRefs.entries())\n\t\t\t\t\t.map(([name, objNum]) => `/${name} ${objNum} 0 R`)\n\t\t\t\t\t.join(\" \");\n\t\t\t\tnewResourceParts.push(`/XObject << ${xobjEntries} >>`);\n\t\t\t}\n\n\t\t\tconst newResources: Record<string, string> = {};\n\t\t\tfor (const part of newResourceParts) {\n\t\t\t\tconst [resType, ...rest] = part.split(/\\s+/);\n\t\t\t\tif (resType) {\n\t\t\t\t\tnewResources[resType] = rest.join(\" \");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Parse existing Resources from page\n\t\t\tconst existingResources = parseResourcesDict(pageContent, this.pdfStr);\n\n\t\t\t// Merge existing with new\n\t\t\tconst mergedResources = mergeResourcesDicts(existingResources, newResources);\n\n\t\t\t// Build merged Resources dictionary string\n\t\t\tconst resourceEntries = Object.entries(mergedResources)\n\t\t\t\t.map(([name, value]) => `${name} ${value}`)\n\t\t\t\t.join(\"\\n\");\n\n\t\t\t// Update page content with merged Resources\n\t\t\tif (pageContent.match(/\\/Resources\\s*<</)) {\n\t\t\t\t// Replace existing inline Resources\n\t\t\t\tconst resIdx = pageContent.indexOf(\"/Resources\");\n\t\t\t\tconst resStart = pageContent.indexOf(\"<<\", resIdx);\n\t\t\t\tif (resStart !== -1) {\n\t\t\t\t\tconst resEnd = findMatchingDictEndInContent(pageContent, resStart);\n\t\t\t\t\tif (resEnd !== -1) {\n\t\t\t\t\t\tpageContent =\n\t\t\t\t\t\t\tpageContent.slice(0, resStart) +\n\t\t\t\t\t\t\t`<< ${resourceEntries} >>` +\n\t\t\t\t\t\t\tpageContent.slice(resEnd + 2);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (pageContent.match(/\\/Resources\\s+\\d+\\s+\\d+\\s+R/)) {\n\t\t\t\t// Replace indirect reference with merged inline dictionary\n\t\t\t\tpageContent = pageContent.replace(\n\t\t\t\t\t/\\/Resources\\s+\\d+\\s+\\d+\\s+R/,\n\t\t\t\t\t`/Resources << ${resourceEntries} >>`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// No resources at all — add them\n\t\t\t\tpageContent += `\\n/Resources << ${resourceEntries} >>`;\n\t\t\t}\n\n\t\t\tobjects.push({\n\t\t\t\tobjNum: page.pageObjNum,\n\t\t\t\tcontent: `<<${pageContent}\\n>>`,\n\t\t\t});\n\t\t}\n\n\t\t// --- 5. Signature placeholder objects (if requested) ---\n\t\tlet sigObjNum = 0;\n\t\tlet widgetObjNum = 0;\n\t\tlet acroFormObjNum = 0;\n\n\t\tif (withSignature && sigOptions) {\n\t\t\tsigObjNum = currentNextObj++;\n\t\t\twidgetObjNum = currentNextObj++;\n\t\t\tacroFormObjNum = currentNextObj++;\n\n\t\t\tconst signatureLength = sigOptions.signatureLength ?? DEFAULT_SIGNATURE_LENGTH;\n\t\t\tconst reason = sigOptions.reason ?? \"Digitally signed\";\n\t\t\tconst name = sigOptions.name ?? \"Digital Signature\";\n\t\t\tconst location = sigOptions.location ?? \"\";\n\t\t\tconst contactInfo = sigOptions.contactInfo ?? \"\";\n\t\t\tconst signingTime = formatPdfDate(new Date());\n\t\t\tconst contentsPlaceholder = \"0\".repeat(signatureLength * 2);\n\n\t\t\tconst sigParts = [\n\t\t\t\t\"<< /Type /Sig\",\n\t\t\t\t\"/Filter /Adobe.PPKLite\",\n\t\t\t\t\"/SubFilter /adbe.pkcs7.detached\",\n\t\t\t\t`/ByteRange [${BYTE_RANGE_PLACEHOLDER}]`,\n\t\t\t\t`/Contents <${contentsPlaceholder}>`,\n\t\t\t\t`/Reason ${pdfString(reason)}`,\n\t\t\t\t`/M ${pdfString(signingTime)}`,\n\t\t\t\t`/Name ${pdfString(name)}`,\n\t\t\t];\n\t\t\tif (location) sigParts.push(`/Location ${pdfString(location)}`);\n\t\t\tif (contactInfo) sigParts.push(`/ContactInfo ${pdfString(contactInfo)}`);\n\t\t\tsigParts.push(\">>\");\n\n\t\t\tobjects.push({ objNum: sigObjNum, content: sigParts.join(\"\\n\") });\n\n\t\t\t// Resolve which page hosts the signature widget annotation.\n\t\t\t// Defaults to page 0; callers pass `appearancePage` to match the\n\t\t\t// visual appearance location so PDF readers navigate correctly.\n\t\t\tconst sigPageIdx = Math.min(\n\t\t\t\tMath.max(sigOptions.appearancePage ?? 0, 0),\n\t\t\t\tthis.pages.length - 1,\n\t\t\t);\n\t\t\tconst sigPageNum = this.structure.pageNums[sigPageIdx]!;\n\n\t\t\t// Widget annotation\n\t\t\tobjects.push({\n\t\t\t\tobjNum: widgetObjNum,\n\t\t\t\tcontent: [\n\t\t\t\t\t\"<< /Type /Annot\",\n\t\t\t\t\t\"/Subtype /Widget\",\n\t\t\t\t\t\"/FT /Sig\",\n\t\t\t\t\t\"/Rect [0 0 0 0]\",\n\t\t\t\t\t`/V ${sigObjNum} 0 R`,\n\t\t\t\t\t`/T ${pdfString(\"Signature1\")}`,\n\t\t\t\t\t\"/F 4\",\n\t\t\t\t\t`/P ${sigPageNum} 0 R`,\n\t\t\t\t\t\">>\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t});\n\n\t\t\t// AcroForm\n\t\t\tobjects.push({\n\t\t\t\tobjNum: acroFormObjNum,\n\t\t\t\tcontent: [\n\t\t\t\t\t\"<< /Type /AcroForm\",\n\t\t\t\t\t\"/SigFlags 3\",\n\t\t\t\t\t`/Fields [${widgetObjNum} 0 R]`,\n\t\t\t\t\t\">>\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t});\n\n\t\t\t// Updated Root catalog with AcroForm\n\t\t\tlet rootContent = this.structure.rootDictContent;\n\t\t\trootContent = rootContent.replace(/\\/AcroForm\\s+\\d+\\s+\\d+\\s+R/g, \"\");\n\t\t\trootContent = rootContent.replace(/\\/Perms\\s*<<[^>]*>>/g, \"\");\n\t\t\trootContent = rootContent.replace(/\\/Perms\\s+\\d+\\s+\\d+\\s+R/g, \"\");\n\n\t\t\tobjects.push({\n\t\t\t\tobjNum: this.structure.rootNum,\n\t\t\t\tcontent: `<<${rootContent}\\n/AcroForm ${acroFormObjNum} 0 R\\n>>`,\n\t\t\t});\n\n\t\t\t// Updated sigPage with Annots\n\t\t\tconst sigPage = this.pages[sigPageIdx]!;\n\t\t\tlet pageContent: string;\n\n\t\t\t// Check if we already have this page in objects (from dirty page update)\n\t\t\tconst existingPageObj = objects.find((o) => o.objNum === sigPage.pageObjNum);\n\t\t\tif (existingPageObj) {\n\t\t\t\t// Extract content from existing updated page (strip outer << >>)\n\t\t\t\tpageContent = existingPageObj.content.slice(2, existingPageObj.content.length - 2);\n\t\t\t} else {\n\t\t\t\tpageContent = sigPage.originalDictContent;\n\t\t\t}\n\n\t\t\tif (pageContent.includes(\"/Annots\")) {\n\t\t\t\tconst bracketEnd = pageContent.indexOf(\"]\", pageContent.indexOf(\"/Annots\"));\n\t\t\t\tpageContent =\n\t\t\t\t\tpageContent.slice(0, bracketEnd) +\n\t\t\t\t\t` ${widgetObjNum} 0 R` +\n\t\t\t\t\tpageContent.slice(bracketEnd);\n\t\t\t} else {\n\t\t\t\tpageContent += `\\n/Annots [${widgetObjNum} 0 R]`;\n\t\t\t}\n\n\t\t\t// Update or add the page object\n\t\t\tif (existingPageObj) {\n\t\t\t\texistingPageObj.content = `<<${pageContent}\\n>>`;\n\t\t\t} else {\n\t\t\t\tobjects.push({\n\t\t\t\t\tobjNum: sigPage.pageObjNum,\n\t\t\t\t\tcontent: `<<${pageContent}\\n>>`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// --- Serialise incremental update ---\n\t\tconst newSize = currentNextObj;\n\t\tconst appendParts: Uint8Array[] = [];\n\t\tconst objectOffsets: Array<{ objNum: number; offset: number }> = [];\n\n\t\t// Compute starting byte offset (after original data)\n\t\tlet currentOffset = this.originalData.length;\n\n\t\tfor (const obj of objects) {\n\t\t\t// Separator newline\n\t\t\tconst sep = latin1Encoder.encode(\"\\n\");\n\t\t\tappendParts.push(sep);\n\t\t\tcurrentOffset += sep.length;\n\n\t\t\tobjectOffsets.push({ objNum: obj.objNum, offset: currentOffset });\n\n\t\t\tif (obj.streamData) {\n\t\t\t\t// Object with stream\n\t\t\t\tconst header = latin1Encoder.encode(`${obj.objNum} 0 obj\\n${obj.content}\\nstream\\n`);\n\t\t\t\tappendParts.push(header);\n\t\t\t\tcurrentOffset += header.length;\n\n\t\t\t\tappendParts.push(obj.streamData);\n\t\t\t\tcurrentOffset += obj.streamData.length;\n\n\t\t\t\tconst footer = latin1Encoder.encode(\"\\nendstream\\nendobj\\n\");\n\t\t\t\tappendParts.push(footer);\n\t\t\t\tcurrentOffset += footer.length;\n\t\t\t} else {\n\t\t\t\tconst objBytes = latin1Encoder.encode(\n\t\t\t\t\t`${obj.objNum} 0 obj\\n${obj.content}\\nendobj\\n`,\n\t\t\t\t);\n\t\t\t\tappendParts.push(objBytes);\n\t\t\t\tcurrentOffset += objBytes.length;\n\t\t\t}\n\t\t}\n\n\t\t// Xref table\n\t\tconst xrefOffset = currentOffset;\n\t\tconst xrefStr = buildXrefTable(objectOffsets);\n\t\tconst xrefBytes = latin1Encoder.encode(xrefStr);\n\t\tappendParts.push(xrefBytes);\n\t\tcurrentOffset += xrefBytes.length;\n\n\t\t// Trailer\n\t\tconst trailerLines = [\"<<\", `/Size ${newSize}`, `/Root ${this.structure.rootNum} 0 R`];\n\t\tif (this.structure.infoNum !== null) {\n\t\t\ttrailerLines.push(`/Info ${this.structure.infoNum} 0 R`);\n\t\t}\n\t\ttrailerLines.push(`/Prev ${this.structure.xrefOffset}`, \">>\");\n\n\t\tconst trailerStr =\n\t\t\t`trailer\\n${trailerLines.join(\"\\n\")}\\nstartxref\\n${xrefOffset}\\n%%EOF`;\n\t\tconst trailerBytes = latin1Encoder.encode(trailerStr);\n\t\tappendParts.push(trailerBytes);\n\n\t\t// Combine original + append parts\n\t\tconst totalAppendLength = appendParts.reduce((s, p) => s + p.length, 0);\n\t\tconst result = new Uint8Array(this.originalData.length + totalAppendLength);\n\t\tresult.set(this.originalData, 0);\n\t\tlet pos = this.originalData.length;\n\t\tfor (const part of appendParts) {\n\t\t\tresult.set(part, pos);\n\t\t\tpos += part.length;\n\t\t}\n\n\t\t// --- Calculate byte range for signature ---\n\t\tlet byteRange: [number, number, number, number] = [0, 0, 0, 0];\n\n\t\tif (withSignature) {\n\t\t\tconst br = updateByteRangeInPlace(result);\n\t\t\treturn { pdf: result, byteRange: br };\n\t\t}\n\n\t\treturn { pdf: result, byteRange };\n\t}\n\n\tprivate hasImagesForPage(page: PdfPageImpl): boolean {\n\t\treturn page.dirty && page.getImageRefs().size > 0;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction buildXrefTable(\n\tentries: Array<{ objNum: number; offset: number }>,\n): string {\n\tconst sorted = [...entries].sort((a, b) => a.objNum - b.objNum);\n\n\tconst subsections: Array<{ start: number; offsets: number[] }> = [];\n\tfor (const entry of sorted) {\n\t\tconst last = subsections[subsections.length - 1];\n\t\tif (last && entry.objNum === last.start + last.offsets.length) {\n\t\t\tlast.offsets.push(entry.offset);\n\t\t} else {\n\t\t\tsubsections.push({ start: entry.objNum, offsets: [entry.offset] });\n\t\t}\n\t}\n\n\tlet result = \"xref\\n\";\n\tfor (const sub of subsections) {\n\t\tresult += `${sub.start} ${sub.offsets.length}\\n`;\n\t\tfor (const offset of sub.offsets) {\n\t\t\tresult += `${String(offset).padStart(10, \"0\")} 00000 n \\n`;\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction formatPdfDate(date: Date): string {\n\tconst y = date.getUTCFullYear();\n\tconst m = String(date.getUTCMonth() + 1).padStart(2, \"0\");\n\tconst d = String(date.getUTCDate()).padStart(2, \"0\");\n\tconst h = String(date.getUTCHours()).padStart(2, \"0\");\n\tconst min = String(date.getUTCMinutes()).padStart(2, \"0\");\n\tconst s = String(date.getUTCSeconds()).padStart(2, \"0\");\n\treturn `D:${y}${m}${d}${h}${min}${s}Z`;\n}\n\nfunction pdfString(str: string): string {\n\tconst escaped = str\n\t\t.replace(/\\\\/g, \"\\\\\\\\\")\n\t\t.replace(/\\(/g, \"\\\\(\")\n\t\t.replace(/\\)/g, \"\\\\)\");\n\treturn `(${escaped})`;\n}\n\n/**\n * Find and overwrite the ByteRange placeholder in an assembled PDF buffer.\n * Modifies `pdf` in-place. Returns the final byte range values.\n */\nfunction updateByteRangeInPlace(pdf: Uint8Array): [number, number, number, number] {\n\t// Locate /Contents < ... >\n\tconst contentsIdx = findLastBytes(pdf, CONTENTS_MARKER);\n\tif (contentsIdx === -1) throw new Error(\"Cannot find Contents in signature\");\n\tconst contentsStart = contentsIdx + CONTENTS_MARKER.length;\n\tlet contentsEnd = contentsStart;\n\twhile (contentsEnd < pdf.length && pdf[contentsEnd] !== 0x3e) contentsEnd++;\n\tif (contentsEnd >= pdf.length) throw new Error(\"Cannot find end of Contents hex\");\n\n\tconst br: [number, number, number, number] = [\n\t\t0,\n\t\tcontentsStart - 1,\n\t\tcontentsEnd + 1,\n\t\tpdf.length - (contentsEnd + 1),\n\t];\n\n\t// Locate /ByteRange [ ... ]\n\tconst brIdx = findLastBytes(pdf, BYTE_RANGE_MARKER);\n\tif (brIdx === -1) throw new Error(\"Cannot find ByteRange in PDF\");\n\tconst brStart = brIdx + BYTE_RANGE_MARKER.length;\n\tlet brEnd = brStart;\n\twhile (brEnd < pdf.length && pdf[brEnd] !== 0x5d) brEnd++;\n\tif (brEnd >= pdf.length) throw new Error(\"Cannot find end of ByteRange\");\n\n\tconst placeholderLen = brEnd - brStart;\n\tconst brValueStr = `${br[0]} ${br[1]} ${br[2]} ${br[3]}`.padEnd(placeholderLen, \" \");\n\tpdf.set(latin1Encoder.encode(brValueStr), brStart);\n\n\treturn br;\n}\n\n/**\n * Find matching >> for a << in a content string\n */\nfunction findMatchingDictEndInContent(str: string, startPos: number): number {\n\tlet depth = 0;\n\tlet i = startPos;\n\n\twhile (i < str.length - 1) {\n\t\tif (str[i] === \"(\") {\n\t\t\ti++;\n\t\t\twhile (i < str.length && str[i] !== \")\") {\n\t\t\t\tif (str[i] === \"\\\\\") i++;\n\t\t\t\ti++;\n\t\t\t}\n\t\t\ti++;\n\t\t} else if (str[i] === \"<\" && str[i + 1] === \"<\") {\n\t\t\tdepth++;\n\t\t\ti += 2;\n\t\t} else if (str[i] === \">\" && str[i + 1] === \">\") {\n\t\t\tdepth--;\n\t\t\tif (depth === 0) return i;\n\t\t\ti += 2;\n\t\t} else {\n\t\t\ti++;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n// ---------------------------------------------------------------------------\n// Signature utility exports (for use by the e-signature library)\n// ---------------------------------------------------------------------------\n\n/**\n * Find the ByteRange and Contents placeholder in a signed PDF\n */\nexport function findByteRange(pdfData: Uint8Array): {\n\tbyteRange: [number, number, number, number];\n\tcontentsStart: number;\n\tcontentsEnd: number;\n\tplaceholderLength: number;\n} {\n\tconst contentsIdx = findLastBytes(pdfData, CONTENTS_MARKER);\n\tif (contentsIdx === -1) throw new Error(\"Could not find Contents in PDF\");\n\n\tconst contentsStart = contentsIdx + CONTENTS_MARKER.length;\n\tlet contentsEnd = contentsStart;\n\twhile (contentsEnd < pdfData.length && pdfData[contentsEnd] !== 0x3e) contentsEnd++;\n\tif (contentsEnd >= pdfData.length) throw new Error(\"Could not find end of Contents field\");\n\n\tconst placeholderLength = contentsEnd - contentsStart;\n\tconst byteRange: [number, number, number, number] = [\n\t\t0,\n\t\tcontentsStart - 1,\n\t\tcontentsEnd + 1,\n\t\tpdfData.length - (contentsEnd + 1),\n\t];\n\n\treturn { byteRange, contentsStart, contentsEnd, placeholderLength };\n}\n\n/**\n * Extract the bytes that need to be signed according to the ByteRange\n */\nexport function extractBytesToSign(\n\tpdfData: Uint8Array,\n\tbyteRange: [number, number, number, number],\n): Uint8Array {\n\tconst [offset1, length1, offset2, length2] = byteRange;\n\n\tif (offset1 < 0 || length1 <= 0 || offset2 <= 0 || length2 <= 0) {\n\t\tthrow new Error(`Invalid ByteRange values: [${byteRange.join(\", \")}]`);\n\t}\n\n\tif (offset1 + length1 > pdfData.length || offset2 + length2 > pdfData.length) {\n\t\tthrow new Error(\"ByteRange exceeds PDF data size\");\n\t}\n\n\t// Use subarray (zero-copy views) to avoid two intermediate allocations before\n\t// writing into the final combined buffer.\n\tconst chunk1 = pdfData.subarray(offset1, offset1 + length1);\n\tconst chunk2 = pdfData.subarray(offset2, offset2 + length2);\n\n\tconst result = new Uint8Array(chunk1.length + chunk2.length);\n\tresult.set(chunk1, 0);\n\tresult.set(chunk2, chunk1.length);\n\treturn result;\n}\n\n/**\n * Embed a signature (as raw bytes) into the Contents placeholder.\n *\n * **Mutates `pdfData` in-place** and returns the same buffer. Callers must not\n * retain a reference to `pdfData` and expect it to remain unchanged after this call.\n */\nexport function embedSignature(\n\tpdfData: Uint8Array,\n\tsignature: Uint8Array,\n): Uint8Array {\n\tconst { contentsStart, placeholderLength } = findByteRange(pdfData);\n\n\t// Convert signature to hex\n\tconst hexChars: string[] = [];\n\tfor (let i = 0; i < signature.length; i++) {\n\t\thexChars.push(signature[i]!.toString(16).padStart(2, \"0\"));\n\t}\n\tconst signatureHex = hexChars.join(\"\");\n\n\tif (signatureHex.length > placeholderLength) {\n\t\tthrow new Error(\n\t\t\t`Signature too large: ${signatureHex.length} hex chars, placeholder is ${placeholderLength}`,\n\t\t);\n\t}\n\n\tconst paddedHex = signatureHex.padEnd(placeholderLength, \"0\");\n\tconst hexBytes = new TextEncoder().encode(paddedHex);\n\n\t// Patch the placeholder in-place — pdfData is a freshly-created buffer from\n\t// saveWithPlaceholder() and not shared with any other consumer at this point,\n\t// so mutating it avoids allocating a full PDF-sized copy.\n\tpdfData.set(hexBytes, contentsStart);\n\treturn pdfData;\n}\n",
|
|
8
|
-
"/**\n * PDF Editing Plugin\n *\n * Load existing PDFs, modify them (draw text, rectangles, images),\n * and save with incremental updates. Also supports creating signature\n * placeholders for digital signing workflows.\n */\n\nexport type {\n\tPdfDocument,\n\tPdfPage,\n\tPdfImage,\n\tTextOptions,\n\tRectOptions,\n\tImageOptions,\n\tSignaturePlaceholderOptions,\n} from \"./types.ts\";\n\nexport { PdfDocumentImpl } from \"./document.ts\";\n\nexport {\n\tfindByteRange,\n\textractBytesToSign,\n\tembedSignature,\n} from \"./document.ts\";\n\nimport { PdfDocumentImpl } from \"./document.ts\";\nimport { parsePdfStructure } from \"./parser.ts\";\nimport type { PdfDocument } from \"./types.ts\";\n\n/**\n * Load an existing PDF for editing\n *\n * @param data - The PDF file contents as a Uint8Array\n * @returns A PdfDocument that can be modified and saved\n */\nexport function loadPdf(data: Uint8Array): PdfDocument {\n\treturn new PdfDocumentImpl(data);\n}\n\n/**\n * Count the number of pages in a PDF without fully loading it.\n *\n * @param data - The PDF file contents as a Uint8Array\n * @returns The number of pages in the PDF\n */\nexport function countPdfPages(data: Uint8Array): number {\n\tconst pdfStr = new TextDecoder(\"latin1\").decode(data);\n\tconst structure = parsePdfStructure(pdfStr);\n\treturn structure.pageNums.length;\n}\n"
|
|
9
|
-
],
|
|
10
|
-
"mappings": "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",
|
|
11
|
-
"debugId": "C149D920AE5494F964756E2164756E21",
|
|
12
|
-
"names": []
|
|
13
|
-
}
|