Skip to content

Commit

Permalink
fixup! Enable automatic URL linking
Browse files Browse the repository at this point in the history
  • Loading branch information
ryzokuken committed Jan 22, 2025
1 parent e649e72 commit 6e9c0db
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 66 deletions.
34 changes: 25 additions & 9 deletions test/integration/autolinker_spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,19 @@
import { closePages, loadAndWait } from "./test_utils.mjs";

describe("autolinker", function () {
describe("mozilla.org.pdf", function () {
describe("bug1019475_2.pdf", function () {
let pages;

beforeAll(async () => {
pages = await loadAndWait("mozilla.org.pdf", ".annotationLayer");
pages = await loadAndWait(
"bug1019475_2.pdf",
".annotationLayer",
null,
null,
{
enableAutoLinking: true,
}
);
});

afterAll(async () => {
Expand All @@ -43,11 +51,19 @@ describe("autolinker", function () {
});
});

describe("link.pdf", function () {
describe("bug1019475_1.pdf", function () {
let pages;

beforeAll(async () => {
pages = await loadAndWait("link.pdf", ".annotationLayer");
pages = await loadAndWait(
"bug1019475_1.pdf",
".annotationLayer",
null,
null,
{
enableAutoLinking: true,
}
);
});

afterAll(async () => {
Expand All @@ -57,16 +73,16 @@ describe("autolinker", function () {
it("must not add links when unnecessary", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
const links = await page.$$eval(
const linkIds = await page.$$eval(
".annotationLayer > .linkAnnotation > a",
annotations =>
annotations.map(a => a.getAttribute("data-element-id"))
);
expect(links.length).withContext(`In ${browserName}`).toEqual(3);
links.forEach(link =>
expect(link)
expect(linkIds.length).withContext(`In ${browserName}`).toEqual(3);
linkIds.forEach(id =>
expect(id)
.withContext(`In ${browserName}`)
.not.toEqual("undefined")
.not.toContain("added_link_")
);
})
);
Expand Down
123 changes: 67 additions & 56 deletions web/annotation_layer_builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,16 @@ class AnnotationLayerBuilder {
* @param {PageViewport} viewport
* @param {Object} options
* @param {string} intent (default value is 'display')
* @param {Array<Object>} inferredLinkAnnotations
* @param {Array<Object>} [inferredLinkAnnotations]
* @returns {Promise<void>} A promise that is resolved when rendering of the
* annotations is complete.
*/
async render(viewport, options, intent = "display", inferredLinkAnnotations) {
async render(
viewport,
options,
intent = "display",
inferredLinkAnnotations = null
) {
if (this.div) {
if (this._cancelled || !this.annotationLayer) {
return;
Expand All @@ -120,60 +125,11 @@ class AnnotationLayerBuilder {
return;
}

const uniqueLinks = inferredLinkAnnotations.filter(link => {
for (const annotation of annotations) {
const annotationRects = annot => {
if (annot.quadPoints) {
const rects = [];
for (let i = 2, ii = annot.quadPoints.length; i < ii; i += 8) {
const trX = annot.quadPoints[i];
const trY = annot.quadPoints[i + 1];
const blX = annot.quadPoints[i + 2];
const blY = annot.quadPoints[i + 3];
rects.push(blX, blY, trX, trY);
}
return rects;
}
return [annotation.rect];
};

const intersectAnnotations = (annot1, annot2) => {
const intersections = [];
const annot1Rects = annotationRects(annot1);
const annot2Rects = annotationRects(annot2);
for (const rect1 of annot1Rects) {
for (const rect2 of annot2Rects) {
const intersection = Util.intersect(rect1, rect2);
if (intersection) {
intersections.push(intersection);
}
}
}
return intersections;
};

const areaRects = rects => {
let totalArea = 0;
for (const rect of rects) {
totalArea +=
Math.abs(rect[2] - rect[0]) * Math.abs(rect[3] - rect[1]);
}
return totalArea;
};

let intersections; // TODO: Add a test case to verify that we can find the intersection between two annotations with quadPoints properly.
if (
annotation.annotationType === AnnotationType.LINK &&
annotation.url === link.url &&
(intersections = intersectAnnotations(annotation, link)).length > 0 &&
areaRects(intersections) / areaRects(annotationRects(link)) > 0.5 // If the overlap is more than 50%.
) {
return false;
}
}
return true;
});
annotations.push(...uniqueLinks);
if (inferredLinkAnnotations?.length) {
annotations.push(
...this.#checkInferredLinks(inferredLinkAnnotations, annotations)
);
}

// Create an annotation layer div and render the annotations
// if there is at least one annotation.
Expand Down Expand Up @@ -266,6 +222,61 @@ class AnnotationLayerBuilder {
section.inert = disableFormElements;
}
}

#checkInferredLinks(inferredLinks, annotations) {
return inferredLinks.filter(link => {
for (const annotation of annotations) {
const annotationRects = annot => {
if (annot.quadPoints) {
const rects = [];
for (let i = 2, ii = annot.quadPoints.length; i < ii; i += 8) {
const trX = annot.quadPoints[i];
const trY = annot.quadPoints[i + 1];
const blX = annot.quadPoints[i + 2];
const blY = annot.quadPoints[i + 3];
rects.push(blX, blY, trX, trY);
}
return rects;
}
return [annot.rect];
};

const intersectAnnotations = (annot1, annot2) => {
const intersections = [];
const annot1Rects = annotationRects(annot1);
const annot2Rects = annotationRects(annot2);
for (const rect1 of annot1Rects) {
for (const rect2 of annot2Rects) {
const intersection = Util.intersect(rect1, rect2);
if (intersection) {
intersections.push(intersection);
}
}
}
return intersections;
};

const areaRects = rects => {
let totalArea = 0;
for (const rect of rects) {
totalArea += Math.abs((rect[2] - rect[0]) * (rect[3] - rect[1]));
}
return totalArea;
};

let intersections; // TODO: Add a test case to verify that we can find the intersection between two annotations with quadPoints properly.
if (
annotation.annotationType === AnnotationType.LINK &&
annotation.url === link.url &&
(intersections = intersectAnnotations(annotation, link)).length > 0 &&
areaRects(intersections) / areaRects(annotationRects(link)) > 0.5 // If the overlap is more than 50%.
) {
return false;
}
}
return true;
});
}
}

export { AnnotationLayerBuilder };
2 changes: 1 addition & 1 deletion web/pdf_page_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ class PDFPageView {
regularAnnotations: true,
};

#inferredLinkAnnotations = [];
#inferredLinkAnnotations = null;

#layers = [null, null, null, null];

Expand Down
4 changes: 4 additions & 0 deletions web/pdfjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@

const {
AbortException,
AnnotationBorderStyleType,
AnnotationEditorLayer,
AnnotationEditorParamsType,
AnnotationEditorType,
AnnotationEditorUIManager,
AnnotationLayer,
AnnotationMode,
AnnotationType,
build,
ColorPicker,
createValidAbsoluteUrl,
Expand Down Expand Up @@ -62,12 +64,14 @@ const {

export {
AbortException,
AnnotationBorderStyleType,
AnnotationEditorLayer,
AnnotationEditorParamsType,
AnnotationEditorType,
AnnotationEditorUIManager,
AnnotationLayer,
AnnotationMode,
AnnotationType,
build,
ColorPicker,
createValidAbsoluteUrl,
Expand Down

0 comments on commit 6e9c0db

Please sign in to comment.