mirror of
https://github.com/zen-browser/pdf.js.git
synced 2025-07-08 01:10:08 +02:00
[api-minor] Expose the /Desc-attribute of file attachments in the viewer (issue 18030)
In the viewer this will be displayed in the `title` of the hyperlink, which is probably the best we can do here given how the viewer is implemented.
This commit is contained in:
parent
1241758605
commit
bf4e36d1b5
7 changed files with 48 additions and 12 deletions
|
@ -13,7 +13,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { stringToPDFString, warn } from "../shared/util.js";
|
import { shadow, stringToPDFString, warn } from "../shared/util.js";
|
||||||
import { BaseStream } from "./base_stream.js";
|
import { BaseStream } from "./base_stream.js";
|
||||||
import { Dict } from "./primitives.js";
|
import { Dict } from "./primitives.js";
|
||||||
|
|
||||||
|
@ -53,9 +53,6 @@ class FileSpec {
|
||||||
if (root.has("FS")) {
|
if (root.has("FS")) {
|
||||||
this.fs = root.get("FS");
|
this.fs = root.get("FS");
|
||||||
}
|
}
|
||||||
this.description = root.has("Desc")
|
|
||||||
? stringToPDFString(root.get("Desc"))
|
|
||||||
: "";
|
|
||||||
if (root.has("RF")) {
|
if (root.has("RF")) {
|
||||||
warn("Related file specifications are not supported");
|
warn("Related file specifications are not supported");
|
||||||
}
|
}
|
||||||
|
@ -102,10 +99,21 @@ class FileSpec {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get description() {
|
||||||
|
let description = "";
|
||||||
|
|
||||||
|
const desc = this.root?.get("Desc");
|
||||||
|
if (desc && typeof desc === "string") {
|
||||||
|
description = stringToPDFString(desc);
|
||||||
|
}
|
||||||
|
return shadow(this, "description", description);
|
||||||
|
}
|
||||||
|
|
||||||
get serializable() {
|
get serializable() {
|
||||||
return {
|
return {
|
||||||
filename: this.filename,
|
filename: this.filename,
|
||||||
content: this.content,
|
content: this.content,
|
||||||
|
description: this.description,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -857,6 +857,9 @@ class LinkAnnotationElement extends AnnotationElement {
|
||||||
*/
|
*/
|
||||||
#bindAttachment(link, attachment, dest = null) {
|
#bindAttachment(link, attachment, dest = null) {
|
||||||
link.href = this.linkService.getAnchorUrl("");
|
link.href = this.linkService.getAnchorUrl("");
|
||||||
|
if (attachment.description) {
|
||||||
|
link.title = attachment.description;
|
||||||
|
}
|
||||||
link.onclick = () => {
|
link.onclick = () => {
|
||||||
this.downloadManager?.openOrDownloadData(
|
this.downloadManager?.openOrDownloadData(
|
||||||
attachment.content,
|
attachment.content,
|
||||||
|
@ -2856,7 +2859,7 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
super(parameters, { isRenderable: true });
|
super(parameters, { isRenderable: true });
|
||||||
|
|
||||||
const { filename, content } = this.data.file;
|
const { filename, content, description } = this.data.file;
|
||||||
this.filename = getFilenameFromUrl(filename, /* onlyStripPath = */ true);
|
this.filename = getFilenameFromUrl(filename, /* onlyStripPath = */ true);
|
||||||
this.content = content;
|
this.content = content;
|
||||||
|
|
||||||
|
@ -2864,6 +2867,7 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
|
||||||
source: this,
|
source: this,
|
||||||
filename,
|
filename,
|
||||||
content,
|
content,
|
||||||
|
description,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
|
@ -54,6 +54,7 @@
|
||||||
!issue17056.pdf
|
!issue17056.pdf
|
||||||
!issue17679.pdf
|
!issue17679.pdf
|
||||||
!issue17679_2.pdf
|
!issue17679_2.pdf
|
||||||
|
!issue18030.pdf
|
||||||
!issue14953.pdf
|
!issue14953.pdf
|
||||||
!issue15367.pdf
|
!issue15367.pdf
|
||||||
!issue15372.pdf
|
!issue15372.pdf
|
||||||
|
|
BIN
test/pdfs/issue18030.pdf
Normal file
BIN
test/pdfs/issue18030.pdf
Normal file
Binary file not shown.
|
@ -4005,7 +4005,7 @@ describe("annotation", function () {
|
||||||
const fileSpecRef = Ref.get(19, 0);
|
const fileSpecRef = Ref.get(19, 0);
|
||||||
const fileSpecDict = new Dict();
|
const fileSpecDict = new Dict();
|
||||||
fileSpecDict.set("Type", Name.get("Filespec"));
|
fileSpecDict.set("Type", Name.get("Filespec"));
|
||||||
fileSpecDict.set("Desc", "");
|
fileSpecDict.set("Desc", "abc");
|
||||||
fileSpecDict.set("EF", embeddedFileDict);
|
fileSpecDict.set("EF", embeddedFileDict);
|
||||||
fileSpecDict.set("UF", "Test.txt");
|
fileSpecDict.set("UF", "Test.txt");
|
||||||
|
|
||||||
|
@ -4035,6 +4035,7 @@ describe("annotation", function () {
|
||||||
expect(data.annotationType).toEqual(AnnotationType.FILEATTACHMENT);
|
expect(data.annotationType).toEqual(AnnotationType.FILEATTACHMENT);
|
||||||
expect(data.file.filename).toEqual("Test.txt");
|
expect(data.file.filename).toEqual("Test.txt");
|
||||||
expect(data.file.content).toEqual(stringToBytes("Test attachment"));
|
expect(data.file.content).toEqual(stringToBytes("Test attachment"));
|
||||||
|
expect(data.file.description).toEqual("abc");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1475,11 +1475,28 @@ describe("api", function () {
|
||||||
const pdfDoc = await loadingTask.promise;
|
const pdfDoc = await loadingTask.promise;
|
||||||
const attachments = await pdfDoc.getAttachments();
|
const attachments = await pdfDoc.getAttachments();
|
||||||
|
|
||||||
const attachment = attachments["foo.txt"];
|
const { filename, content, description } = attachments["foo.txt"];
|
||||||
expect(attachment.filename).toEqual("foo.txt");
|
expect(filename).toEqual("foo.txt");
|
||||||
expect(attachment.content).toEqual(
|
expect(content).toEqual(
|
||||||
new Uint8Array([98, 97, 114, 32, 98, 97, 122, 32, 10])
|
new Uint8Array([98, 97, 114, 32, 98, 97, 122, 32, 10])
|
||||||
);
|
);
|
||||||
|
expect(description).toEqual("");
|
||||||
|
|
||||||
|
await loadingTask.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("gets attachments, with /Desc", async function () {
|
||||||
|
const loadingTask = getDocument(buildGetDocumentParams("issue18030.pdf"));
|
||||||
|
const pdfDoc = await loadingTask.promise;
|
||||||
|
const attachments = await pdfDoc.getAttachments();
|
||||||
|
|
||||||
|
const { filename, content, description } = attachments["empty.pdf"];
|
||||||
|
expect(filename).toEqual("Empty page.pdf");
|
||||||
|
expect(content instanceof Uint8Array).toEqual(true);
|
||||||
|
expect(content.length).toEqual(2357);
|
||||||
|
expect(description).toEqual(
|
||||||
|
"SHA512: 06bec56808f93846f1d41ff0be4e54079c1291b860378c801c0f35f1d127a8680923ff6de59bd5a9692f01f0d97ca4f26da178ed03635fa4813d86c58a6c981a"
|
||||||
|
);
|
||||||
|
|
||||||
await loadingTask.destroy();
|
await loadingTask.destroy();
|
||||||
});
|
});
|
||||||
|
|
|
@ -94,7 +94,10 @@ class PDFAttachmentViewer extends BaseTreeViewer {
|
||||||
/**
|
/**
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
_bindLink(element, { content, filename }) {
|
_bindLink(element, { content, description, filename }) {
|
||||||
|
if (description) {
|
||||||
|
element.title = description;
|
||||||
|
}
|
||||||
element.onclick = () => {
|
element.onclick = () => {
|
||||||
this.downloadManager.openOrDownloadData(content, filename);
|
this.downloadManager.openOrDownloadData(content, filename);
|
||||||
return false;
|
return false;
|
||||||
|
@ -120,6 +123,7 @@ class PDFAttachmentViewer extends BaseTreeViewer {
|
||||||
for (const name in attachments) {
|
for (const name in attachments) {
|
||||||
const item = attachments[name];
|
const item = attachments[name];
|
||||||
const content = item.content,
|
const content = item.content,
|
||||||
|
description = item.description,
|
||||||
filename = getFilenameFromUrl(
|
filename = getFilenameFromUrl(
|
||||||
item.filename,
|
item.filename,
|
||||||
/* onlyStripPath = */ true
|
/* onlyStripPath = */ true
|
||||||
|
@ -129,7 +133,7 @@ class PDFAttachmentViewer extends BaseTreeViewer {
|
||||||
div.className = "treeItem";
|
div.className = "treeItem";
|
||||||
|
|
||||||
const element = document.createElement("a");
|
const element = document.createElement("a");
|
||||||
this._bindLink(element, { content, filename });
|
this._bindLink(element, { content, description, filename });
|
||||||
element.textContent = this._normalizeTextContent(filename);
|
element.textContent = this._normalizeTextContent(filename);
|
||||||
|
|
||||||
div.append(element);
|
div.append(element);
|
||||||
|
@ -144,7 +148,7 @@ class PDFAttachmentViewer extends BaseTreeViewer {
|
||||||
/**
|
/**
|
||||||
* Used to append FileAttachment annotations to the sidebar.
|
* Used to append FileAttachment annotations to the sidebar.
|
||||||
*/
|
*/
|
||||||
#appendAttachment({ filename, content }) {
|
#appendAttachment({ filename, content, description }) {
|
||||||
const renderedPromise = this._renderedCapability.promise;
|
const renderedPromise = this._renderedCapability.promise;
|
||||||
|
|
||||||
renderedPromise.then(() => {
|
renderedPromise.then(() => {
|
||||||
|
@ -161,6 +165,7 @@ class PDFAttachmentViewer extends BaseTreeViewer {
|
||||||
attachments[filename] = {
|
attachments[filename] = {
|
||||||
filename,
|
filename,
|
||||||
content,
|
content,
|
||||||
|
description,
|
||||||
};
|
};
|
||||||
this.render({
|
this.render({
|
||||||
attachments,
|
attachments,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue