MCPcopy Create free account
hub / github.com/LibPDF-js/core / saveInternal

Method saveInternal

src/api/pdf.ts:3197–3341  ·  view source on GitHub ↗

* Internal save that returns full result including xref offset. * Used by signing to chain incremental updates.

(options: SaveOptions = {})

Source from the content-addressed store, hash-verified

3195 * Used by signing to chain incremental updates.
3196 */
3197 private saveInternal(options: SaveOptions = {}): { bytes: Uint8Array; xrefOffset: number } {
3198 // Finalize embedded fonts (creates PDF objects, optionally subsets)
3199 this.fonts.finalize(options.subsetFonts ?? false);
3200
3201 const wantsIncremental = options.incremental ?? false;
3202 const blocker = this.canSaveIncrementally();
3203
3204 // Check if incremental is requested but not possible
3205 if (wantsIncremental && blocker !== null) {
3206 this.ctx.registry.addWarning(
3207 `Incremental save not possible (${blocker}), performing full save`,
3208 );
3209 }
3210
3211 const useIncremental = wantsIncremental && blocker === null;
3212
3213 // If no changes and no security changes, return original bytes
3214 const hasSecurityChanges = this._pendingSecurity.action !== "none";
3215
3216 if (!this.hasChanges() && !this.fonts.hasEmbeddedFonts && !hasSecurityChanges) {
3217 return {
3218 bytes: this.originalBytes,
3219 xrefOffset: this.originalXRefOffset,
3220 };
3221 }
3222
3223 // Get root reference from trailer
3224 const root = this.ctx.info.trailer.getRef("Root");
3225
3226 if (!root) {
3227 throw new Error("Document has no catalog (missing /Root in trailer)");
3228 }
3229
3230 // Get optional info reference
3231 const infoRef = this.ctx.info.trailer.getRef("Info");
3232
3233 // Handle encryption based on pending security state
3234 let encryptRef: PdfRef | undefined;
3235 let fileId: [Uint8Array, Uint8Array] | undefined;
3236 let securityHandler: StandardSecurityHandler | undefined;
3237
3238 if (this._pendingSecurity.action === "encrypt" && this._pendingSecurity.options) {
3239 // Generate new encryption
3240 const encryption = generateEncryption(this._pendingSecurity.options);
3241
3242 // Register the encrypt dictionary
3243 encryptRef = this.ctx.registry.register(encryption.encryptDict);
3244 fileId = encryption.fileId;
3245 securityHandler = encryption.securityHandler;
3246 } else if (this._pendingSecurity.action === "none" && this.isEncrypted) {
3247 // Re-encrypt with original security - preserve encryption when saving encrypted documents
3248 const handler = this.ctx.info.securityHandler;
3249
3250 if (handler) {
3251 // Reconstruct the encrypt dict from the parsed encryption parameters
3252 // We can't resolve the original encrypt ref because it would try to decrypt it
3253 // (the encrypt dict is never encrypted in the PDF)
3254 const reconstructedDict = reconstructEncryptDict(handler.encryption);

Callers 1

saveMethod · 0.95

Calls 12

canSaveIncrementallyMethod · 0.95
hasChangesMethod · 0.95
generateEncryptionFunction · 0.90
reconstructEncryptDictFunction · 0.90
writeIncrementalFunction · 0.90
writeCompleteFunction · 0.90
finalizeMethod · 0.80
getArrayMethod · 0.80
atMethod · 0.80
addWarningMethod · 0.45
getRefMethod · 0.45
registerMethod · 0.45

Tested by

no test coverage detected