mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-07-26 00:47:21 +02:00
Merge pull request #21565 from calixteman/fix/pdf-editor-link-destinations
Preserve non-local PDF link destinations
This commit is contained in:
commit
7505eeaeb4
@ -1222,6 +1222,13 @@ class PDFEditor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const action = annotationDict.get("A");
|
const action = annotationDict.get("A");
|
||||||
|
if (action instanceof Dict && !isName(action.get("S"), "GoTo")) {
|
||||||
|
// Only GoTo actions point to pages in the current document. Other
|
||||||
|
// actions, such as GoToR, must not be filtered using the current
|
||||||
|
// document's page map.
|
||||||
|
newAnnotations[newAnnotationIndex] = annotationRef;
|
||||||
|
return;
|
||||||
|
}
|
||||||
const dest =
|
const dest =
|
||||||
action instanceof Dict
|
action instanceof Dict
|
||||||
? action.get("D")
|
? action.get("D")
|
||||||
@ -1233,9 +1240,9 @@ class PDFEditor {
|
|||||||
) {
|
) {
|
||||||
// Keep the annotation as is: it isn't linking to a deleted page.
|
// Keep the annotation as is: it isn't linking to a deleted page.
|
||||||
newAnnotations[newAnnotationIndex] = annotationRef;
|
newAnnotations[newAnnotationIndex] = annotationRef;
|
||||||
} else if (typeof dest === "string") {
|
} else if (dest instanceof Name || typeof dest === "string") {
|
||||||
const destString = stringToPDFString(
|
const destString = stringToPDFString(
|
||||||
dest,
|
dest instanceof Name ? dest.name : dest,
|
||||||
/* keepEscapeSequence = */ true
|
/* keepEscapeSequence = */ true
|
||||||
);
|
);
|
||||||
if (destinations.has(destString)) {
|
if (destinations.has(destString)) {
|
||||||
|
|||||||
@ -6392,6 +6392,49 @@ small scripts as well as for`);
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("Named destinations", function () {
|
describe("Named destinations", function () {
|
||||||
|
it("preserves name destinations and remote actions", async function () {
|
||||||
|
const objects = [
|
||||||
|
"1 0 obj\n<< /Type /Catalog /Pages 2 0 R " +
|
||||||
|
"/Dests << /foo [3 0 R /Fit] >> >>\nendobj\n",
|
||||||
|
"2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj\n",
|
||||||
|
"3 0 obj\n<< /Type /Page /Parent 2 0 R " +
|
||||||
|
"/MediaBox [0 0 100 100] /Annots [4 0 R 5 0 R] >>\nendobj\n",
|
||||||
|
"4 0 obj\n<< /Type /Annot /Subtype /Link /Rect [0 0 10 10] " +
|
||||||
|
"/Dest /foo >>\nendobj\n",
|
||||||
|
"5 0 obj\n<< /Type /Annot /Subtype /Link /Rect [10 0 20 10] " +
|
||||||
|
"/A << /S /GoToR /F (other.pdf) /D (target) >> >>\nendobj\n",
|
||||||
|
];
|
||||||
|
let pdfData = "%PDF-1.7\n";
|
||||||
|
const offsets = [];
|
||||||
|
for (const object of objects) {
|
||||||
|
offsets.push(pdfData.length);
|
||||||
|
pdfData += object;
|
||||||
|
}
|
||||||
|
const xrefOffset = pdfData.length;
|
||||||
|
pdfData += `xref\n0 ${objects.length + 1}\n`;
|
||||||
|
pdfData += "0000000000 65535 f \n";
|
||||||
|
for (const offset of offsets) {
|
||||||
|
pdfData += `${offset.toString().padStart(10, "0")} 00000 n \n`;
|
||||||
|
}
|
||||||
|
pdfData +=
|
||||||
|
`trailer\n<< /Size ${objects.length + 1} /Root 1 0 R >>\n` +
|
||||||
|
`startxref\n${xrefOffset}\n%%EOF\n`;
|
||||||
|
|
||||||
|
let loadingTask = getDocument({ data: stringToBytes(pdfData) });
|
||||||
|
let pdfDoc = await loadingTask.promise;
|
||||||
|
const data = await pdfDoc.extractPages([{ document: null }]);
|
||||||
|
await loadingTask.destroy();
|
||||||
|
|
||||||
|
loadingTask = getDocument({ data });
|
||||||
|
pdfDoc = await loadingTask.promise;
|
||||||
|
const annotations = await (await pdfDoc.getPage(1)).getAnnotations();
|
||||||
|
expect(annotations.length).toEqual(2);
|
||||||
|
expect(annotations[0].dest).toEqual("foo");
|
||||||
|
expect(annotations[1].unsafeUrl).toEqual("other.pdf#target");
|
||||||
|
expect(Object.keys(await pdfDoc.getDestinations())).toEqual(["foo"]);
|
||||||
|
await loadingTask.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
it("keeps colliding deduplicated destination names unique", async function () {
|
it("keeps colliding deduplicated destination names unique", async function () {
|
||||||
let loadingTask = getDocument(
|
let loadingTask = getDocument(
|
||||||
buildGetDocumentParams("named_dest_collision_for_editor.pdf")
|
buildGetDocumentParams("named_dest_collision_for_editor.pdf")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user