mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-08-03 12:57:20 +02:00
Compare commits
No commits in common. "3cd1b10433575e718b314fa7b7866b1ac9aa85ad" and "7081a1f112756c09b79134b52a5db052f201651e" have entirely different histories.
3cd1b10433
...
7081a1f112
@ -14,7 +14,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
_isValidExplicitDest,
|
collectActions,
|
||||||
|
isNumberArray,
|
||||||
|
MissingDataException,
|
||||||
|
PDF_VERSION_REGEXP,
|
||||||
|
recoverJsURL,
|
||||||
|
toRomanNumerals,
|
||||||
|
XRefEntryException,
|
||||||
|
} from "./core_utils.js";
|
||||||
|
import {
|
||||||
createValidAbsoluteUrl,
|
createValidAbsoluteUrl,
|
||||||
DocumentActionEventType,
|
DocumentActionEventType,
|
||||||
FormatError,
|
FormatError,
|
||||||
@ -26,15 +34,6 @@ import {
|
|||||||
stringToUTF8String,
|
stringToUTF8String,
|
||||||
warn,
|
warn,
|
||||||
} from "../shared/util.js";
|
} from "../shared/util.js";
|
||||||
import {
|
|
||||||
collectActions,
|
|
||||||
isNumberArray,
|
|
||||||
MissingDataException,
|
|
||||||
PDF_VERSION_REGEXP,
|
|
||||||
recoverJsURL,
|
|
||||||
toRomanNumerals,
|
|
||||||
XRefEntryException,
|
|
||||||
} from "./core_utils.js";
|
|
||||||
import {
|
import {
|
||||||
Dict,
|
Dict,
|
||||||
isDict,
|
isDict,
|
||||||
@ -54,13 +53,52 @@ import { FileSpec } from "./file_spec.js";
|
|||||||
import { MetadataParser } from "./metadata_parser.js";
|
import { MetadataParser } from "./metadata_parser.js";
|
||||||
import { StructTreeRoot } from "./struct_tree.js";
|
import { StructTreeRoot } from "./struct_tree.js";
|
||||||
|
|
||||||
const isRef = v => v instanceof Ref;
|
function isValidExplicitDest(dest) {
|
||||||
|
if (!Array.isArray(dest) || dest.length < 2) {
|
||||||
const isValidExplicitDest = _isValidExplicitDest.bind(
|
return false;
|
||||||
null,
|
}
|
||||||
/* validRef = */ isRef,
|
const [page, zoom, ...args] = dest;
|
||||||
/* validName = */ isName
|
if (!(page instanceof Ref) && !Number.isInteger(page)) {
|
||||||
);
|
return false;
|
||||||
|
}
|
||||||
|
if (!(zoom instanceof Name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const argsLen = args.length;
|
||||||
|
let allowNull = true;
|
||||||
|
switch (zoom.name) {
|
||||||
|
case "XYZ":
|
||||||
|
if (argsLen < 2 || argsLen > 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Fit":
|
||||||
|
case "FitB":
|
||||||
|
return argsLen === 0;
|
||||||
|
case "FitH":
|
||||||
|
case "FitBH":
|
||||||
|
case "FitV":
|
||||||
|
case "FitBV":
|
||||||
|
if (argsLen > 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "FitR":
|
||||||
|
if (argsLen !== 4) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
allowNull = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (const arg of args) {
|
||||||
|
if (!(typeof arg === "number" || (allowNull && arg === null))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
function fetchDest(dest) {
|
function fetchDest(dest) {
|
||||||
if (dest instanceof Dict) {
|
if (dest instanceof Dict) {
|
||||||
|
|||||||
@ -414,7 +414,9 @@ class ChunkedStreamManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chunksToRequest.sort((a, b) => a - b);
|
chunksToRequest.sort(function (a, b) {
|
||||||
|
return a - b;
|
||||||
|
});
|
||||||
return this._requestChunks(chunksToRequest);
|
return this._requestChunks(chunksToRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -576,7 +576,9 @@ function getRanges(glyphs, toUnicodeExtraMap, numGlyphs) {
|
|||||||
if (codes.length === 0) {
|
if (codes.length === 0) {
|
||||||
codes.push({ fontCharCode: 0, glyphId: 0 });
|
codes.push({ fontCharCode: 0, glyphId: 0 });
|
||||||
}
|
}
|
||||||
codes.sort((a, b) => a.fontCharCode - b.fontCharCode);
|
codes.sort(function fontGetRangesSort(a, b) {
|
||||||
|
return a.fontCharCode - b.fontCharCode;
|
||||||
|
});
|
||||||
|
|
||||||
// Split the sorted codes into ranges.
|
// Split the sorted codes into ranges.
|
||||||
const ranges = [];
|
const ranges = [];
|
||||||
@ -1775,7 +1777,9 @@ class Font {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// removing duplicate entries
|
// removing duplicate entries
|
||||||
mappings.sort((a, b) => a.charCode - b.charCode);
|
mappings.sort(function (a, b) {
|
||||||
|
return a.charCode - b.charCode;
|
||||||
|
});
|
||||||
const finalMappings = [],
|
const finalMappings = [],
|
||||||
seenCharCodes = new Set();
|
seenCharCodes = new Set();
|
||||||
for (const map of mappings) {
|
for (const map of mappings) {
|
||||||
|
|||||||
@ -374,7 +374,9 @@ function decodeBitmap(
|
|||||||
// Sorting is non-standard, and it is not required. But sorting increases
|
// Sorting is non-standard, and it is not required. But sorting increases
|
||||||
// the number of template bits that can be reused from the previous
|
// the number of template bits that can be reused from the previous
|
||||||
// contextLabel in the main loop.
|
// contextLabel in the main loop.
|
||||||
template.sort((a, b) => a.y - b.y || a.x - b.x);
|
template.sort(function (a, b) {
|
||||||
|
return a.y - b.y || a.x - b.x;
|
||||||
|
});
|
||||||
|
|
||||||
const templateLength = template.length;
|
const templateLength = template.length;
|
||||||
const templateX = new Int8Array(templateLength);
|
const templateX = new Int8Array(templateLength);
|
||||||
|
|||||||
@ -48,9 +48,11 @@ class RunLengthStream extends DecodeStream {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
n = 257 - n;
|
n = 257 - n;
|
||||||
|
const b = repeatHeader[1];
|
||||||
buffer = this.ensureBuffer(bufferLength + n + 1);
|
buffer = this.ensureBuffer(bufferLength + n + 1);
|
||||||
buffer.fill(repeatHeader[1], bufferLength, bufferLength + n);
|
for (let i = 0; i < n; i++) {
|
||||||
bufferLength += n;
|
buffer[bufferLength++] = b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.bufferLength = bufferLength;
|
this.bufferLength = bufferLength;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -321,7 +321,11 @@ class SimpleDOMNode {
|
|||||||
if (!this.childNodes) {
|
if (!this.childNodes) {
|
||||||
return this.nodeValue || "";
|
return this.nodeValue || "";
|
||||||
}
|
}
|
||||||
return this.childNodes.map(child => child.textContent).join("");
|
return this.childNodes
|
||||||
|
.map(function (child) {
|
||||||
|
return child.textContent;
|
||||||
|
})
|
||||||
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
get children() {
|
get children() {
|
||||||
|
|||||||
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
_isValidExplicitDest,
|
|
||||||
AbortException,
|
AbortException,
|
||||||
AnnotationMode,
|
AnnotationMode,
|
||||||
assert,
|
assert,
|
||||||
@ -596,20 +595,15 @@ function getFactoryUrlProp(val) {
|
|||||||
throw new Error(`Invalid factory url: "${val}" must include trailing slash.`);
|
throw new Error(`Invalid factory url: "${val}" must include trailing slash.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isRefProxy = v =>
|
function isRefProxy(ref) {
|
||||||
typeof v === "object" &&
|
return (
|
||||||
Number.isInteger(v?.num) &&
|
typeof ref === "object" &&
|
||||||
v.num >= 0 &&
|
Number.isInteger(ref?.num) &&
|
||||||
Number.isInteger(v?.gen) &&
|
ref.num >= 0 &&
|
||||||
v.gen >= 0;
|
Number.isInteger(ref?.gen) &&
|
||||||
|
ref.gen >= 0
|
||||||
const isNameProxy = v => typeof v === "object" && typeof v?.name === "string";
|
);
|
||||||
|
}
|
||||||
const isValidExplicitDest = _isValidExplicitDest.bind(
|
|
||||||
null,
|
|
||||||
/* validRef = */ isRefProxy,
|
|
||||||
/* validName = */ isNameProxy
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} OnProgressParameters
|
* @typedef {Object} OnProgressParameters
|
||||||
@ -2342,7 +2336,6 @@ class PDFWorker {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {PDFWorkerParameters} params - The worker initialization parameters.
|
* @param {PDFWorkerParameters} params - The worker initialization parameters.
|
||||||
* @returns {PDFWorker}
|
|
||||||
*/
|
*/
|
||||||
static fromPort(params) {
|
static fromPort(params) {
|
||||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
|
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
|
||||||
@ -3491,7 +3484,6 @@ const build =
|
|||||||
export {
|
export {
|
||||||
build,
|
build,
|
||||||
getDocument,
|
getDocument,
|
||||||
isValidExplicitDest,
|
|
||||||
LoopbackPort,
|
LoopbackPort,
|
||||||
PDFDataRangeTransport,
|
PDFDataRangeTransport,
|
||||||
PDFDocumentLoadingTask,
|
PDFDocumentLoadingTask,
|
||||||
|
|||||||
@ -45,7 +45,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
build,
|
build,
|
||||||
getDocument,
|
getDocument,
|
||||||
isValidExplicitDest,
|
|
||||||
PDFDataRangeTransport,
|
PDFDataRangeTransport,
|
||||||
PDFWorker,
|
PDFWorker,
|
||||||
version,
|
version,
|
||||||
@ -118,7 +117,6 @@ export {
|
|||||||
InvalidPDFException,
|
InvalidPDFException,
|
||||||
isDataScheme,
|
isDataScheme,
|
||||||
isPdfFile,
|
isPdfFile,
|
||||||
isValidExplicitDest,
|
|
||||||
noContextMenu,
|
noContextMenu,
|
||||||
normalizeUnicode,
|
normalizeUnicode,
|
||||||
OPS,
|
OPS,
|
||||||
|
|||||||
@ -1080,54 +1080,6 @@ function getUuid() {
|
|||||||
|
|
||||||
const AnnotationPrefix = "pdfjs_internal_id_";
|
const AnnotationPrefix = "pdfjs_internal_id_";
|
||||||
|
|
||||||
function _isValidExplicitDest(validRef, validName, dest) {
|
|
||||||
if (!Array.isArray(dest) || dest.length < 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const [page, zoom, ...args] = dest;
|
|
||||||
if (!validRef(page) && !Number.isInteger(page)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!validName(zoom)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const argsLen = args.length;
|
|
||||||
let allowNull = true;
|
|
||||||
switch (zoom.name) {
|
|
||||||
case "XYZ":
|
|
||||||
if (argsLen < 2 || argsLen > 3) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "Fit":
|
|
||||||
case "FitB":
|
|
||||||
return argsLen === 0;
|
|
||||||
case "FitH":
|
|
||||||
case "FitBH":
|
|
||||||
case "FitV":
|
|
||||||
case "FitBV":
|
|
||||||
if (argsLen > 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "FitR":
|
|
||||||
if (argsLen !== 4) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
allowNull = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (const arg of args) {
|
|
||||||
if (typeof arg === "number" || (allowNull && arg === null)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Remove this once `Uint8Array.prototype.toHex` is generally available.
|
// TODO: Remove this once `Uint8Array.prototype.toHex` is generally available.
|
||||||
function toHexUtil(arr) {
|
function toHexUtil(arr) {
|
||||||
if (Uint8Array.prototype.toHex) {
|
if (Uint8Array.prototype.toHex) {
|
||||||
@ -1167,7 +1119,6 @@ if (
|
|||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
_isValidExplicitDest,
|
|
||||||
AbortException,
|
AbortException,
|
||||||
AnnotationActionEventType,
|
AnnotationActionEventType,
|
||||||
AnnotationBorderStyleType,
|
AnnotationBorderStyleType,
|
||||||
|
|||||||
@ -42,7 +42,6 @@ function downloadFile(file, url, redirects = 0) {
|
|||||||
.get(url, async function (response) {
|
.get(url, async function (response) {
|
||||||
if ([301, 302, 307, 308].includes(response.statusCode)) {
|
if ([301, 302, 307, 308].includes(response.statusCode)) {
|
||||||
if (redirects > 10) {
|
if (redirects > 10) {
|
||||||
response.resume();
|
|
||||||
reject(new Error("Too many redirects"));
|
reject(new Error("Too many redirects"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -51,14 +50,12 @@ function downloadFile(file, url, redirects = 0) {
|
|||||||
await downloadFile(file, redirectTo, ++redirects);
|
await downloadFile(file, redirectTo, ++redirects);
|
||||||
resolve();
|
resolve();
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
response.resume();
|
|
||||||
reject(ex);
|
reject(ex);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.statusCode !== 200) {
|
if (response.statusCode !== 200) {
|
||||||
response.resume();
|
|
||||||
reject(new Error(`HTTP ${response.statusCode}`));
|
reject(new Error(`HTTP ${response.statusCode}`));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -91,7 +88,7 @@ async function downloadManifestFiles(manifest) {
|
|||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
console.error(`Error during downloading of ${url}:`, ex);
|
console.error(`Error during downloading of ${url}:`, ex);
|
||||||
fs.writeFileSync(file, ""); // making it empty file
|
fs.writeFileSync(file, ""); // making it empty file
|
||||||
fs.writeFileSync(`${file}.error`, ex.toString());
|
fs.writeFileSync(`${file}.error`, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,7 +49,10 @@ async function initializePDFJS(callback) {
|
|||||||
"pdfjs-test/font/font_os2_spec.js",
|
"pdfjs-test/font/font_os2_spec.js",
|
||||||
"pdfjs-test/font/font_post_spec.js",
|
"pdfjs-test/font/font_post_spec.js",
|
||||||
"pdfjs-test/font/font_fpgm_spec.js",
|
"pdfjs-test/font/font_fpgm_spec.js",
|
||||||
].map(moduleName => import(moduleName)) // eslint-disable-line no-unsanitized/method
|
].map(function (moduleName) {
|
||||||
|
// eslint-disable-next-line no-unsanitized/method
|
||||||
|
return import(moduleName);
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
|
|||||||
@ -13,46 +13,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { closePages, createPromise, loadAndWait } from "./test_utils.mjs";
|
||||||
awaitPromise,
|
|
||||||
closePages,
|
|
||||||
createPromise,
|
|
||||||
loadAndWait,
|
|
||||||
} from "./test_utils.mjs";
|
|
||||||
|
|
||||||
function waitForLinkAnnotations(page, pageNumber) {
|
function waitForLinkAnnotations(page) {
|
||||||
return page.evaluateHandle(
|
|
||||||
number => [
|
|
||||||
new Promise(resolve => {
|
|
||||||
const { eventBus } = window.PDFViewerApplication;
|
|
||||||
eventBus.on("linkannotationsadded", function listener(e) {
|
|
||||||
if (number === undefined || e.pageNumber === number) {
|
|
||||||
resolve();
|
|
||||||
eventBus.off("linkannotationsadded", listener);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
pageNumber
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function recordInitialLinkAnnotationsEvent(eventBus) {
|
|
||||||
globalThis.initialLinkAnnotationsEventFired = false;
|
|
||||||
eventBus.on(
|
|
||||||
"linkannotationsadded",
|
|
||||||
() => {
|
|
||||||
globalThis.initialLinkAnnotationsEventFired = true;
|
|
||||||
},
|
|
||||||
{ once: true }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
function waitForInitialLinkAnnotations(page) {
|
|
||||||
return createPromise(page, resolve => {
|
return createPromise(page, resolve => {
|
||||||
if (globalThis.initialLinkAnnotationsEventFired) {
|
|
||||||
resolve();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
window.PDFViewerApplication.eventBus.on("linkannotationsadded", resolve, {
|
window.PDFViewerApplication.eventBus.on("linkannotationsadded", resolve, {
|
||||||
once: true,
|
once: true,
|
||||||
});
|
});
|
||||||
@ -214,49 +178,4 @@ describe("autolinker", function () {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when highlighting search results", function () {
|
|
||||||
let pages;
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
pages = await loadAndWait(
|
|
||||||
"issue3115r.pdf",
|
|
||||||
".annotationLayer",
|
|
||||||
null,
|
|
||||||
{ eventBusSetup: recordInitialLinkAnnotationsEvent },
|
|
||||||
{ enableAutoLinking: true }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await closePages(pages);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("must find links that overlap with search results", async () => {
|
|
||||||
await Promise.all(
|
|
||||||
pages.map(async ([browserName, page]) => {
|
|
||||||
await awaitPromise(await waitForInitialLinkAnnotations(page));
|
|
||||||
|
|
||||||
const linkAnnotationsPromise = await waitForLinkAnnotations(page, 36);
|
|
||||||
|
|
||||||
// Search for "rich.edu"
|
|
||||||
await page.click("#viewFindButton");
|
|
||||||
await page.waitForSelector("#viewFindButton", { hidden: false });
|
|
||||||
await page.type("#findInput", "rich.edu");
|
|
||||||
await page.waitForSelector(".textLayer .highlight");
|
|
||||||
|
|
||||||
await awaitPromise(linkAnnotationsPromise);
|
|
||||||
|
|
||||||
const urls = await page.$$eval(
|
|
||||||
".page[data-page-number='36'] > .annotationLayer > .linkAnnotation > a",
|
|
||||||
annotations => annotations.map(a => a.href)
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(urls)
|
|
||||||
.withContext(`In ${browserName}`)
|
|
||||||
.toContain(jasmine.stringContaining("rich.edu"));
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -64,7 +64,9 @@ function flatten(stats) {
|
|||||||
});
|
});
|
||||||
// Use only overall results if not grouped by 'stat'
|
// Use only overall results if not grouped by 'stat'
|
||||||
if (!options.groupBy.includes("stat")) {
|
if (!options.groupBy.includes("stat")) {
|
||||||
rows = rows.filter(s => s.stat === "Overall");
|
rows = rows.filter(function (s) {
|
||||||
|
return s.stat === "Overall";
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
@ -127,7 +129,9 @@ function stat(baseline, current) {
|
|||||||
}
|
}
|
||||||
const rows = [];
|
const rows = [];
|
||||||
// collect rows and measure column widths
|
// collect rows and measure column widths
|
||||||
const width = labels.map(s => s.length);
|
const width = labels.map(function (s) {
|
||||||
|
return s.length;
|
||||||
|
});
|
||||||
rows.push(labels);
|
rows.push(labels);
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
const baselineMean = mean(baselineGroup[key]);
|
const baselineMean = mean(baselineGroup[key]);
|
||||||
@ -158,7 +162,9 @@ function stat(baseline, current) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add horizontal line
|
// add horizontal line
|
||||||
const hline = width.map(w => new Array(w + 1).join("-"));
|
const hline = width.map(function (w) {
|
||||||
|
return new Array(w + 1).join("-");
|
||||||
|
});
|
||||||
rows.splice(1, 0, hline);
|
rows.splice(1, 0, hline);
|
||||||
|
|
||||||
// print output
|
// print output
|
||||||
|
|||||||
@ -1051,7 +1051,9 @@ async function closeSession(browser) {
|
|||||||
await session.browser.close();
|
await session.browser.close();
|
||||||
}
|
}
|
||||||
session.closed = true;
|
session.closed = true;
|
||||||
const allClosed = sessions.every(s => s.closed);
|
const allClosed = sessions.every(function (s) {
|
||||||
|
return s.closed;
|
||||||
|
});
|
||||||
if (allClosed) {
|
if (allClosed) {
|
||||||
if (tempDir) {
|
if (tempDir) {
|
||||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||||
|
|||||||
@ -4869,9 +4869,9 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
|
|||||||
// Issue 6205 reported an issue with font rendering, so clear the loaded
|
// Issue 6205 reported an issue with font rendering, so clear the loaded
|
||||||
// fonts so that we can see whether loading PDFs in parallel does not
|
// fonts so that we can see whether loading PDFs in parallel does not
|
||||||
// cause any issues with the rendered fonts.
|
// cause any issues with the rendered fonts.
|
||||||
const destroyPromises = loadingTasks.map(loadingTask =>
|
const destroyPromises = loadingTasks.map(function (loadingTask) {
|
||||||
loadingTask.destroy()
|
return loadingTask.destroy();
|
||||||
);
|
});
|
||||||
await Promise.all(destroyPromises);
|
await Promise.all(destroyPromises);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -100,7 +100,10 @@ async function initializePDFJS(callback) {
|
|||||||
"pdfjs-test/unit/xfa_serialize_data_spec.js",
|
"pdfjs-test/unit/xfa_serialize_data_spec.js",
|
||||||
"pdfjs-test/unit/xfa_tohtml_spec.js",
|
"pdfjs-test/unit/xfa_tohtml_spec.js",
|
||||||
"pdfjs-test/unit/xml_spec.js",
|
"pdfjs-test/unit/xml_spec.js",
|
||||||
].map(moduleName => import(moduleName)) // eslint-disable-line no-unsanitized/method
|
].map(function (moduleName) {
|
||||||
|
// eslint-disable-next-line no-unsanitized/method
|
||||||
|
return import(moduleName);
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isNodeJS) {
|
if (isNodeJS) {
|
||||||
|
|||||||
@ -36,7 +36,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
build,
|
build,
|
||||||
getDocument,
|
getDocument,
|
||||||
isValidExplicitDest,
|
|
||||||
PDFDataRangeTransport,
|
PDFDataRangeTransport,
|
||||||
PDFWorker,
|
PDFWorker,
|
||||||
version,
|
version,
|
||||||
@ -95,7 +94,6 @@ const expectedAPI = Object.freeze({
|
|||||||
InvalidPDFException,
|
InvalidPDFException,
|
||||||
isDataScheme,
|
isDataScheme,
|
||||||
isPdfFile,
|
isPdfFile,
|
||||||
isValidExplicitDest,
|
|
||||||
noContextMenu,
|
noContextMenu,
|
||||||
normalizeUnicode,
|
normalizeUnicode,
|
||||||
OPS,
|
OPS,
|
||||||
|
|||||||
@ -69,55 +69,13 @@ function calculateLinkPosition(range, pdfPageView) {
|
|||||||
return { quadPoints, rect };
|
return { quadPoints, rect };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a DOM node `container` and an index into its text contents `offset`,
|
|
||||||
* returns a pair consisting of text node that the `offset` actually points
|
|
||||||
* to, together with the offset relative to that text node.
|
|
||||||
* When the offset points at the boundary between two node, the result will
|
|
||||||
* point to the first text node in depth-first traversal order.
|
|
||||||
*
|
|
||||||
* For example, given this DOM:
|
|
||||||
* <p>abc<span>def</span>ghi</p>
|
|
||||||
*
|
|
||||||
* textPosition(p, 0) -> [#text "abc", 0] (before `a`)
|
|
||||||
* textPosition(p, 2) -> [#text "abc", 2] (between `b` and `c`)
|
|
||||||
* textPosition(p, 3) -> [#text "abc", 3] (after `c`)
|
|
||||||
* textPosition(p, 5) -> [#text "def", 2] (between `e` and `f`)
|
|
||||||
* textPosition(p, 6) -> [#text "def", 3] (after `f`)
|
|
||||||
*/
|
|
||||||
function textPosition(container, offset) {
|
|
||||||
let currentContainer = container;
|
|
||||||
do {
|
|
||||||
if (currentContainer.nodeType === Node.TEXT_NODE) {
|
|
||||||
const currentLength = currentContainer.textContent.length;
|
|
||||||
if (offset <= currentLength) {
|
|
||||||
return [currentContainer, offset];
|
|
||||||
}
|
|
||||||
offset -= currentLength;
|
|
||||||
} else if (currentContainer.firstChild) {
|
|
||||||
currentContainer = currentContainer.firstChild;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!currentContainer.nextSibling && currentContainer !== container) {
|
|
||||||
currentContainer = currentContainer.parentNode;
|
|
||||||
}
|
|
||||||
if (currentContainer !== container) {
|
|
||||||
currentContainer = currentContainer.nextSibling;
|
|
||||||
}
|
|
||||||
} while (currentContainer !== container);
|
|
||||||
throw new Error("Offset is bigger than container's contents length.");
|
|
||||||
}
|
|
||||||
|
|
||||||
function createLinkAnnotation({ url, index, length }, pdfPageView, id) {
|
function createLinkAnnotation({ url, index, length }, pdfPageView, id) {
|
||||||
const highlighter = pdfPageView._textHighlighter;
|
const highlighter = pdfPageView._textHighlighter;
|
||||||
const [{ begin, end }] = highlighter._convertMatches([index], [length]);
|
const [{ begin, end }] = highlighter._convertMatches([index], [length]);
|
||||||
|
|
||||||
const range = new Range();
|
const range = new Range();
|
||||||
range.setStart(
|
range.setStart(highlighter.textDivs[begin.divIdx].firstChild, begin.offset);
|
||||||
...textPosition(highlighter.textDivs[begin.divIdx], begin.offset)
|
range.setEnd(highlighter.textDivs[end.divIdx].firstChild, end.offset);
|
||||||
);
|
|
||||||
range.setEnd(...textPosition(highlighter.textDivs[end.divIdx], end.offset));
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: `inferred_link_${id}`,
|
id: `inferred_link_${id}`,
|
||||||
|
|||||||
@ -398,7 +398,9 @@ class Stepper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getNextBreakPoint() {
|
getNextBreakPoint() {
|
||||||
this.breakPoints.sort((a, b) => a - b);
|
this.breakPoints.sort(function (a, b) {
|
||||||
|
return a - b;
|
||||||
|
});
|
||||||
for (const breakPoint of this.breakPoints) {
|
for (const breakPoint of this.breakPoints) {
|
||||||
if (breakPoint > this.currentIdx) {
|
if (breakPoint > this.currentIdx) {
|
||||||
return breakPoint;
|
return breakPoint;
|
||||||
@ -485,7 +487,9 @@ const Stats = (function Stats() {
|
|||||||
statsDiv.textContent = stat.toString();
|
statsDiv.textContent = stat.toString();
|
||||||
wrapper.append(title, statsDiv);
|
wrapper.append(title, statsDiv);
|
||||||
stats.push({ pageNumber, div: wrapper });
|
stats.push({ pageNumber, div: wrapper });
|
||||||
stats.sort((a, b) => a.pageNumber - b.pageNumber);
|
stats.sort(function (a, b) {
|
||||||
|
return a.pageNumber - b.pageNumber;
|
||||||
|
});
|
||||||
clear(this.panel);
|
clear(this.panel);
|
||||||
for (const entry of stats) {
|
for (const entry of stats) {
|
||||||
this.panel.append(entry.div);
|
this.panel.append(entry.div);
|
||||||
|
|||||||
@ -53,12 +53,6 @@ class ExternalServices extends BaseExternalServices {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class MLManager {
|
class MLManager {
|
||||||
static {
|
|
||||||
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
||||||
this.getFakeMLManager = options => new FakeMLManager(options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async isEnabledFor(_name) {
|
async isEnabledFor(_name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -74,82 +68,83 @@ class MLManager {
|
|||||||
guess(_data) {}
|
guess(_data) {}
|
||||||
|
|
||||||
toggleService(_name, _enabled) {}
|
toggleService(_name, _enabled) {}
|
||||||
|
|
||||||
|
static getFakeMLManager(options) {
|
||||||
|
return new FakeMLManager(options);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
class FakeMLManager {
|
||||||
// eslint-disable-next-line no-var
|
eventBus = null;
|
||||||
var FakeMLManager = class {
|
|
||||||
eventBus = null;
|
|
||||||
|
|
||||||
hasProgress = false;
|
hasProgress = false;
|
||||||
|
|
||||||
constructor({ enableGuessAltText, enableAltTextModelDownload }) {
|
constructor({ enableGuessAltText, enableAltTextModelDownload }) {
|
||||||
this.enableGuessAltText = enableGuessAltText;
|
this.enableGuessAltText = enableGuessAltText;
|
||||||
this.enableAltTextModelDownload = enableAltTextModelDownload;
|
this.enableAltTextModelDownload = enableAltTextModelDownload;
|
||||||
}
|
}
|
||||||
|
|
||||||
setEventBus(eventBus, abortSignal) {
|
setEventBus(eventBus, abortSignal) {
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
async isEnabledFor(_name) {
|
async isEnabledFor(_name) {
|
||||||
return this.enableGuessAltText;
|
return this.enableGuessAltText;
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteModel(_name) {
|
async deleteModel(_name) {
|
||||||
this.enableAltTextModelDownload = false;
|
this.enableAltTextModelDownload = false;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadModel(_name) {}
|
async loadModel(_name) {}
|
||||||
|
|
||||||
async downloadModel(_name) {
|
async downloadModel(_name) {
|
||||||
// Simulate downloading the model but with progress.
|
// Simulate downloading the model but with progress.
|
||||||
// The progress can be seen in the new alt-text dialog.
|
// The progress can be seen in the new alt-text dialog.
|
||||||
this.hasProgress = true;
|
this.hasProgress = true;
|
||||||
|
|
||||||
const { promise, resolve } = Promise.withResolvers();
|
const { promise, resolve } = Promise.withResolvers();
|
||||||
const total = 1e8;
|
const total = 1e8;
|
||||||
const end = 1.5 * total;
|
const end = 1.5 * total;
|
||||||
const increment = 5e6;
|
const increment = 5e6;
|
||||||
let loaded = 0;
|
let loaded = 0;
|
||||||
const id = setInterval(() => {
|
const id = setInterval(() => {
|
||||||
loaded += increment;
|
loaded += increment;
|
||||||
if (loaded <= end) {
|
if (loaded <= end) {
|
||||||
this.eventBus.dispatch("loadaiengineprogress", {
|
this.eventBus.dispatch("loadaiengineprogress", {
|
||||||
source: this,
|
source: this,
|
||||||
detail: {
|
detail: {
|
||||||
total,
|
total,
|
||||||
totalLoaded: loaded,
|
totalLoaded: loaded,
|
||||||
finished: loaded + increment >= end,
|
finished: loaded + increment >= end,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clearInterval(id);
|
clearInterval(id);
|
||||||
this.hasProgress = false;
|
this.hasProgress = false;
|
||||||
this.enableAltTextModelDownload = true;
|
this.enableAltTextModelDownload = true;
|
||||||
resolve(true);
|
resolve(true);
|
||||||
}, 900);
|
}, 900);
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
isReady(_name) {
|
isReady(_name) {
|
||||||
return this.enableAltTextModelDownload;
|
return this.enableAltTextModelDownload;
|
||||||
}
|
}
|
||||||
|
|
||||||
guess({ request: { data } }) {
|
guess({ request: { data } }) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resolve(data ? { output: "Fake alt text." } : { error: true });
|
resolve(data ? { output: "Fake alt text." } : { error: true });
|
||||||
}, 3000);
|
}, 3000);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleService(_name, enabled) {
|
toggleService(_name, enabled) {
|
||||||
this.enableGuessAltText = enabled;
|
this.enableGuessAltText = enabled;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { ExternalServices, initCom, MLManager, Preferences };
|
export { ExternalServices, initCom, MLManager, Preferences };
|
||||||
|
|||||||
@ -16,7 +16,6 @@
|
|||||||
/** @typedef {import("./event_utils").EventBus} EventBus */
|
/** @typedef {import("./event_utils").EventBus} EventBus */
|
||||||
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
|
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
|
||||||
|
|
||||||
import { isValidExplicitDest } from "pdfjs-lib";
|
|
||||||
import { parseQueryString } from "./ui_utils.js";
|
import { parseQueryString } from "./ui_utils.js";
|
||||||
|
|
||||||
const DEFAULT_LINK_REL = "noopener noreferrer nofollow";
|
const DEFAULT_LINK_REL = "noopener noreferrer nofollow";
|
||||||
@ -416,7 +415,7 @@ class PDFLinkService {
|
|||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
if (typeof dest === "string" || isValidExplicitDest(dest)) {
|
if (typeof dest === "string" || PDFLinkService.#isValidExplicitDest(dest)) {
|
||||||
this.goToDestination(dest);
|
this.goToDestination(dest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -487,6 +486,60 @@ class PDFLinkService {
|
|||||||
optionalContentConfig
|
optionalContentConfig
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static #isValidExplicitDest(dest) {
|
||||||
|
if (!Array.isArray(dest) || dest.length < 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const [page, zoom, ...args] = dest;
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
typeof page === "object" &&
|
||||||
|
Number.isInteger(page?.num) &&
|
||||||
|
Number.isInteger(page?.gen)
|
||||||
|
) &&
|
||||||
|
!Number.isInteger(page)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(typeof zoom === "object" && typeof zoom?.name === "string")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const argsLen = args.length;
|
||||||
|
let allowNull = true;
|
||||||
|
switch (zoom.name) {
|
||||||
|
case "XYZ":
|
||||||
|
if (argsLen < 2 || argsLen > 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Fit":
|
||||||
|
case "FitB":
|
||||||
|
return argsLen === 0;
|
||||||
|
case "FitH":
|
||||||
|
case "FitBH":
|
||||||
|
case "FitV":
|
||||||
|
case "FitBV":
|
||||||
|
if (argsLen > 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "FitR":
|
||||||
|
if (argsLen !== 4) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
allowNull = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (const arg of args) {
|
||||||
|
if (!(typeof arg === "number" || (allowNull && arg === null))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -39,7 +39,6 @@ const {
|
|||||||
InvalidPDFException,
|
InvalidPDFException,
|
||||||
isDataScheme,
|
isDataScheme,
|
||||||
isPdfFile,
|
isPdfFile,
|
||||||
isValidExplicitDest,
|
|
||||||
noContextMenu,
|
noContextMenu,
|
||||||
normalizeUnicode,
|
normalizeUnicode,
|
||||||
OPS,
|
OPS,
|
||||||
@ -91,7 +90,6 @@ export {
|
|||||||
InvalidPDFException,
|
InvalidPDFException,
|
||||||
isDataScheme,
|
isDataScheme,
|
||||||
isPdfFile,
|
isPdfFile,
|
||||||
isValidExplicitDest,
|
|
||||||
noContextMenu,
|
noContextMenu,
|
||||||
normalizeUnicode,
|
normalizeUnicode,
|
||||||
OPS,
|
OPS,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user