Ensure that various URL-related options are applied in the xfaLayer too

Note how both the annotationLayer and the document outline will apply various URL-related options when creating the link-elements.
For consistency the `xfaLayer`-rendering should obviously use the same options, to ensure that the existing options are indeed applied to all URLs regardless of where they originate.
This commit is contained in:
Jonas Jenwald 2021-09-30 10:40:21 +02:00
parent 284d259054
commit bb9c905c5d
7 changed files with 53 additions and 9 deletions

View File

@ -1094,7 +1094,6 @@ class Button extends XFAObject {
if (!href) { if (!href) {
continue; continue;
} }
const target = jsURL.newWindow ? "_blank" : undefined;
// we've an url so generate a <a> // we've an url so generate a <a>
htmlButton.children.push({ htmlButton.children.push({
@ -1102,7 +1101,7 @@ class Button extends XFAObject {
attributes: { attributes: {
id: "link" + this[$uid], id: "link" + this[$uid],
href, href,
target, newWindow: jsURL.newWindow,
class: ["xfaLink"], class: ["xfaLink"],
style: {}, style: {},
}, },

View File

@ -13,6 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { addLinkAttributes, LinkTarget } from "./display_utils.js";
import { XfaText } from "./xfa_text.js"; import { XfaText } from "./xfa_text.js";
class XfaLayer { class XfaLayer {
@ -84,8 +85,10 @@ class XfaLayer {
} }
} }
static setAttributes(html, element, storage, intent) { static setAttributes({ html, element, storage = null, intent, linkService }) {
const { attributes } = element; const { attributes } = element;
const isHTMLAnchorElement = html instanceof HTMLAnchorElement;
if (attributes.type === "radio") { if (attributes.type === "radio") {
// Avoid to have a radio group when printing with the same as one // Avoid to have a radio group when printing with the same as one
// already displayed. // already displayed.
@ -105,6 +108,9 @@ class XfaLayer {
} else if (key === "class") { } else if (key === "class") {
html.setAttribute(key, value.join(" ")); html.setAttribute(key, value.join(" "));
} else { } else {
if (isHTMLAnchorElement && (key === "href" || key === "newWindow")) {
continue; // Handled below.
}
html.setAttribute(key, value); html.setAttribute(key, value);
} }
} else { } else {
@ -112,6 +118,17 @@ class XfaLayer {
} }
} }
if (isHTMLAnchorElement) {
addLinkAttributes(html, {
url: attributes.href,
target: attributes.newWindow
? LinkTarget.BLANK
: linkService.externalLinkTarget,
rel: linkService.externalLinkRel,
enabled: linkService.externalLinkEnabled,
});
}
// Set the value after the others to be sure overwrite // Set the value after the others to be sure overwrite
// any other values. // any other values.
if (storage && attributes.dataId) { if (storage && attributes.dataId) {
@ -121,11 +138,17 @@ class XfaLayer {
static render(parameters) { static render(parameters) {
const storage = parameters.annotationStorage; const storage = parameters.annotationStorage;
const linkService = parameters.linkService;
const root = parameters.xfa; const root = parameters.xfa;
const intent = parameters.intent || "display"; const intent = parameters.intent || "display";
const rootHtml = document.createElement(root.name); const rootHtml = document.createElement(root.name);
if (root.attributes) { if (root.attributes) {
this.setAttributes(rootHtml, root); this.setAttributes({
html: rootHtml,
element: root,
intent,
linkService,
});
} }
const stack = [[root, -1, rootHtml]]; const stack = [[root, -1, rootHtml]];
@ -169,7 +192,13 @@ class XfaLayer {
html.appendChild(childHtml); html.appendChild(childHtml);
if (child.attributes) { if (child.attributes) {
this.setAttributes(childHtml, child, storage, intent); this.setAttributes({
html: childHtml,
element: child,
storage,
intent,
linkService,
});
} }
if (child.children && child.children.length > 0) { if (child.children && child.children.length > 0) {

View File

@ -334,6 +334,7 @@ var rasterizeXfaLayer = (function rasterizeXfaLayerClosure() {
div, div,
viewport: viewport.clone({ dontFlip: true }), viewport: viewport.clone({ dontFlip: true }),
annotationStorage, annotationStorage,
linkService: new SimpleLinkService(),
intent: isPrint ? "print" : "display", intent: isPrint ? "print" : "display",
}); });

View File

@ -640,10 +640,10 @@ describe("XFAFactory", function () {
const pages = factory.getPages(); const pages = factory.getPages();
let a = searchHtmlNode(pages, "name", "a"); let a = searchHtmlNode(pages, "name", "a");
expect(a.attributes.href).toEqual("https://github.com/mozilla/pdf.js"); expect(a.attributes.href).toEqual("https://github.com/mozilla/pdf.js");
expect(a.attributes.target).toEqual("_blank"); expect(a.attributes.newWindow).toEqual(true);
a = searchHtmlNode(pages, "name", "a", false, [1]); a = searchHtmlNode(pages, "name", "a", false, [1]);
expect(a.attributes.href).toEqual("https://github.com/allizom/pdf.js"); expect(a.attributes.href).toEqual("https://github.com/allizom/pdf.js");
expect(a.attributes.target).toBe(undefined); expect(a.attributes.newWindow).toEqual(false);
}); });
}); });

View File

@ -1358,6 +1358,7 @@ class BaseViewer {
* @param {PDFPage} pdfPage * @param {PDFPage} pdfPage
* @param {AnnotationStorage} [annotationStorage] - Storage for annotation * @param {AnnotationStorage} [annotationStorage] - Storage for annotation
* data in forms. * data in forms.
* @property {IPDFLinkService} linkService
* @returns {XfaLayerBuilder} * @returns {XfaLayerBuilder}
*/ */
createXfaLayerBuilder(pageDiv, pdfPage, annotationStorage = null) { createXfaLayerBuilder(pageDiv, pdfPage, annotationStorage = null) {
@ -1366,6 +1367,7 @@ class BaseViewer {
pdfPage, pdfPage,
annotationStorage: annotationStorage:
annotationStorage || this.pdfDocument?.annotationStorage, annotationStorage || this.pdfDocument?.annotationStorage,
linkService: this.linkService,
}); });
} }

View File

@ -191,9 +191,16 @@ class IPDFXfaLayerFactory {
/** /**
* @param {HTMLDivElement} pageDiv * @param {HTMLDivElement} pageDiv
* @param {PDFPage} pdfPage * @param {PDFPage} pdfPage
* @param {AnnotationStorage} [annotationStorage]
* @param {Object} [xfaHtml]
* @returns {XfaLayerBuilder} * @returns {XfaLayerBuilder}
*/ */
createXfaLayerBuilder(pageDiv, pdfPage) {} createXfaLayerBuilder(
pageDiv,
pdfPage,
annotationStorage = null,
xfaHtml = null
) {}
} }
/** /**

View File

@ -15,6 +15,7 @@
/** @typedef {import("./interfaces").IPDFXfaLayerFactory} IPDFXfaLayerFactory */ /** @typedef {import("./interfaces").IPDFXfaLayerFactory} IPDFXfaLayerFactory */
import { SimpleLinkService } from "./pdf_link_service.js";
import { XfaLayer } from "pdfjs-lib"; import { XfaLayer } from "pdfjs-lib";
/** /**
@ -22,6 +23,7 @@ import { XfaLayer } from "pdfjs-lib";
* @property {HTMLDivElement} pageDiv * @property {HTMLDivElement} pageDiv
* @property {PDFPage} pdfPage * @property {PDFPage} pdfPage
* @property {AnnotationStorage} [annotationStorage] * @property {AnnotationStorage} [annotationStorage]
* @property {IPDFLinkService} linkService
* @property {Object} [xfaHtml] * @property {Object} [xfaHtml]
*/ */
@ -29,10 +31,11 @@ class XfaLayerBuilder {
/** /**
* @param {XfaLayerBuilderOptions} options * @param {XfaLayerBuilderOptions} options
*/ */
constructor({ pageDiv, pdfPage, annotationStorage, xfaHtml }) { constructor({ pageDiv, pdfPage, annotationStorage, linkService, xfaHtml }) {
this.pageDiv = pageDiv; this.pageDiv = pageDiv;
this.pdfPage = pdfPage; this.pdfPage = pdfPage;
this.annotationStorage = annotationStorage; this.annotationStorage = annotationStorage;
this.linkService = linkService;
this.xfaHtml = xfaHtml; this.xfaHtml = xfaHtml;
this.div = null; this.div = null;
@ -54,6 +57,7 @@ class XfaLayerBuilder {
xfa: this.xfaHtml, xfa: this.xfaHtml,
page: null, page: null,
annotationStorage: this.annotationStorage, annotationStorage: this.annotationStorage,
linkService: this.linkService,
intent, intent,
}; };
@ -80,6 +84,7 @@ class XfaLayerBuilder {
xfa, xfa,
page: this.pdfPage, page: this.pdfPage,
annotationStorage: this.annotationStorage, annotationStorage: this.annotationStorage,
linkService: this.linkService,
intent, intent,
}; };
@ -129,6 +134,7 @@ class DefaultXfaLayerFactory {
pageDiv, pageDiv,
pdfPage, pdfPage,
annotationStorage, annotationStorage,
linkService: new SimpleLinkService(),
xfaHtml, xfaHtml,
}); });
} }