Last active
September 30, 2025 11:45
-
-
Save elmimmo/b0bf4be03df4527762ca405196f2c8a8 to your computer and use it in GitHub Desktop.
InCopy script to export blank PDF with annotations + Acrobat Quick Action JavaScript to import them into PDF exported from InDesign
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //DESCRIPTION:Export blank PDF with annotations for later import into PDF exported with InDesign | |
| (function () { | |
| // ============================ | |
| // Export all open documents to PDF | |
| // - Hides all layers before export (restores afterwards) | |
| // - Enables "Include notes as annotations" (best-effort across versions) | |
| // - Exports to the same folder as the document | |
| // - Forces file names to end with "_annotations.pdf" | |
| // - Shows a summary of failures at the end | |
| // ============================ | |
| function getPDFExportFormat() { | |
| // Be tolerant to naming differences across app versions | |
| try { if (ExportFormat && ExportFormat.PDF_TYPE !== undefined) return ExportFormat.PDF_TYPE; } catch (e) { } | |
| // try { if (ExportFormat && ExportFormat.pdfType !== undefined) return ExportFormat.pdfType; } catch (e) { } | |
| // try { if (ExportFormat && ExportFormat.adobePDF !== undefined) return ExportFormat.adobePDF; } catch (e) { } | |
| throw new Error("PDF export format is not available in this app/version."); | |
| } | |
| function setIncludeNotesAsAnnotations() { | |
| // Some versions expose different property names; try both. | |
| var ok = false; | |
| try { app.layoutPDFExportPreferences.includeNotes = true; ok = true; } catch (e) { } | |
| // try { app.layoutPDFExportPreferences.includeNotesAsAnnotations = true; ok = true; } catch (e) { } | |
| return ok; | |
| } | |
| function hideAllLayers(doc) { | |
| var states = []; | |
| var hadLayers = false; | |
| try { | |
| if (doc.layers && doc.layers.length > 0) { | |
| hadLayers = true; | |
| for (var i = 0; i < doc.layers.length; i++) { | |
| states[i] = doc.layers[i].visible; | |
| try { doc.layers[i].visible = false; } catch (e) { } | |
| } | |
| } | |
| } catch (e) { } | |
| return { hadLayers: hadLayers, states: states }; | |
| } | |
| function restoreLayerVisibility(doc, snapshot) { | |
| if (!snapshot || !snapshot.hadLayers) return; | |
| try { | |
| for (var i = 0; i < doc.layers.length && i < snapshot.states.length; i++) { | |
| try { doc.layers[i].visible = snapshot.states[i]; } catch (e) { } | |
| } | |
| } catch (e) { } | |
| } | |
| // Build "<base>_annotations.pdf" from the document name. | |
| function annotationsPDFName(name) { | |
| // Replace the last ".ext" (if any) with "_annotations.pdf"; if no extension, append it. | |
| return name.replace(/(?:\.[^.]+)?$/, "_annotations.pdf"); | |
| } | |
| function exportDocumentAsPDF(doc) { | |
| // 1) Resolve the document's own folder | |
| var folder = null; | |
| try { folder = doc.filePath; } catch (e) { } | |
| if (!folder) { | |
| throw new Error("Document is not saved (no containing folder)."); | |
| } | |
| // 2) Build the output name "<doc>_annotations.pdf" | |
| var pdfFileName = annotationsPDFName(doc.name); | |
| var pdfFilePath = folder.fsName + "/" + pdfFileName; | |
| // 3) Hide all layers (restore afterwards) | |
| var snapshot = hideAllLayers(doc); | |
| // 4) Ensure "Include notes as annotations" is enabled (best-effort) | |
| setIncludeNotesAsAnnotations(); | |
| // 5) Export to PDF without showing the dialog | |
| var fmt = getPDFExportFormat(); | |
| try { | |
| doc.exportFile(fmt, new File(pdfFilePath), false); | |
| } finally { | |
| // Always restore layer visibility even if export fails | |
| restoreLayerVisibility(doc, snapshot); | |
| } | |
| } | |
| // ============================ | |
| // Run | |
| // ============================ | |
| if (app.documents.length === 0) { | |
| alert("No documents are open."); | |
| return; | |
| } | |
| var failures = []; | |
| var successes = 0; | |
| for (var i = 0; i < app.documents.length; i++) { | |
| var doc = app.documents[i]; | |
| try { | |
| exportDocumentAsPDF(doc); | |
| successes++; | |
| } catch (e) { | |
| failures.push({ name: doc.name, reason: (e && e.message) ? e.message : String(e) }); | |
| } | |
| } | |
| // Final summary | |
| var msg = "Export finished.\n\nSuccesses: " + successes + "\n"; | |
| if (failures.length > 0) { | |
| msg += "Failures: " + failures.length + "\n\n"; | |
| for (var j = 0; j < failures.length; j++) { | |
| msg += "• " + failures[j].name + " — " + failures[j].reason + "\n"; | |
| } | |
| } else { | |
| msg += "Failures: 0"; | |
| } | |
| alert(msg); | |
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * ================================================================================ | |
| * Annotation Importer for Adobe Acrobat Quick Action | |
| * ================================================================================ | |
| * | |
| * Description: | |
| * This script is designed to be used as a step in an Adobe Acrobat Quick Action. | |
| * For each document processed by the action, it automatically finds a corresponding | |
| * "_annotations.pdf" file, copies all annotations from it, and adds them to the | |
| * target document. | |
| * | |
| * Workflow: | |
| * 1. For the current document (e.g., "MyFile.pdf"), it constructs the path for a | |
| * source document (e.g., "MyFile_annotations.pdf") expected to be in the | |
| * same directory. | |
| * 2. It opens the source document in the background. | |
| * 3. It copies all annotations from the source document. | |
| * 4. It closes the source document. | |
| * 5. It adds the copied annotations to the target document. | |
| * 6. It saves the target document. | |
| * | |
| * Behavior: | |
| * - On success, the script is completely silent. | |
| * - If the target document already contains annotations, it is skipped and a | |
| * message is logged to the console. | |
| * - If a source PDF is not found, or if it contains no annotations, an alert | |
| * will be displayed for that specific file, and a message is logged to the console. | |
| * | |
| * Usage: | |
| * - Create a new Quick Action in Adobe Acrobat. | |
| * - Add an "Execute JavaScript" step. | |
| * - Paste this entire script into the step's options. | |
| * - Run the action on one or more open files. | |
| * | |
| */ | |
| var targetDoc = this; | |
| // Check if the document is saved, as a path is required. | |
| if (!targetDoc.path) { | |
| console.println("\n--- Annotation Import Report ---\nFile: Unsaved Document\nStatus: SKIPPED\nReason: Document must be saved first.\n--------------------------------\n"); | |
| app.alert({ | |
| cMsg: "An unsaved document was skipped. Please save it and run the action again.", | |
| cTitle: "Unsaved Document", | |
| nIcon: 1 // Error Icon | |
| }); | |
| } else { | |
| // Safety Check: Skip if the document already has annotations. | |
| var existingAnnots = targetDoc.getAnnots(); | |
| if (existingAnnots && existingAnnots.length > 0) { | |
| console.println("\n--- Annotation Import Report ---\nFile: " + targetDoc.documentFileName + "\nStatus: SKIPPED\nReason: Document already contains " + existingAnnots.length + " annotation(s).\n--------------------------------\n"); | |
| } else { | |
| var suffix = "_annotations"; | |
| var sourcePath = targetDoc.path.replace(/\.pdf$/i, suffix + ".pdf"); | |
| var sourceDoc = null; // Initialize as null | |
| try { | |
| sourceDoc = app.openDoc({ cPath: sourcePath }); | |
| // If the line above fails, it jumps to catch, and sourceDoc remains null. | |
| // Force the script to wait for the document to be fully loaded. | |
| sourceDoc.syncAnnotScan(); | |
| var annots = sourceDoc.getAnnots(); | |
| if (annots && annots.length > 0) { | |
| // SUCCESS PATH: Silently process, save, and finish. | |
| targetDoc.bringToFront(); | |
| for (var i = 0; i < annots.length; i++) { | |
| targetDoc.addAnnot(annots[i].getProps()); | |
| } | |
| targetDoc.saveAs(targetDoc.path); | |
| } else { | |
| // FAILURE PATH 1: No annotations found. Show an alert. | |
| console.println("\n--- Annotation Import Report ---\nFile: " + targetDoc.documentFileName + "\nStatus: FAILED\nReason: Source file contains no annotations.\n--------------------------------\n"); | |
| app.alert({ | |
| cMsg: "Source file for '" + targetDoc.documentFileName + "' contains no annotations to import.", | |
| cTitle: "No Annotations Found", | |
| nIcon: 2 // Warning Icon | |
| }); | |
| } | |
| } catch (e) { | |
| // CATCH-ALL ERROR HANDLER | |
| if (sourceDoc == null) { | |
| // If sourceDoc is still null, the error came from app.openDoc. | |
| console.println("\n--- Annotation Import Report ---\nFile: " + targetDoc.documentFileName + "\nStatus: FAILED\nReason: Source file not found.\nPath Checked: " + sourcePath + "\n--------------------------------\n"); | |
| app.alert({ | |
| cMsg: "Source file not found for '" + targetDoc.documentFileName + "'.\n\nPath checked:\n" + sourcePath, | |
| cTitle: "Source Not Found", | |
| nIcon: 1 // Error Icon | |
| }); | |
| } else { | |
| // If sourceDoc exists, the error happened during processing. | |
| console.println("\n--- Annotation Import Report ---\nFile: " + targetDoc.documentFileName + "\nStatus: FAILED\nReason: An unexpected error occurred.\nError Details: " + e.toString() + "\n--------------------------------\n"); | |
| app.alert({ | |
| cMsg: "An unexpected error occurred while processing '" + targetDoc.documentFileName + "'.\n\nError: " + e.toString(), | |
| cTitle: "Unexpected Error", | |
| nIcon: 1 // Error Icon | |
| }); | |
| } | |
| } finally { | |
| // Final cleanup: ensure the source document is closed if it was opened. | |
| if (sourceDoc) { | |
| sourceDoc.closeDoc(true); | |
| } | |
| } | |
| } | |
| } |
Comments are disabled for this gist.