mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-08-04 05:17:24 +02:00
Find the PDF filename in a URL hash in two linear steps
Searching for a name followed by ".pdf" is quadratic on a hash which doesn't contain one, so locate the last ".pdf" first and then extend it to the left.
This commit is contained in:
parent
7fc7072f9c
commit
7862875438
@ -188,10 +188,22 @@ function getPdfFilenameFromUrl(url, defaultFilename = "document.pdf") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (newURL.hash) {
|
if (newURL.hash) {
|
||||||
const reFilename = /[^/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
|
// Locate the last ".pdf" and then extend it to the left, up to the closest
|
||||||
const hashFilename = reFilename.exec(newURL.hash);
|
// separator. Both steps are linear, whereas a single pattern starting with
|
||||||
if (hashFilename) {
|
// `[^/?#=]+` is quadratic on a hash which contains no ".pdf" at all.
|
||||||
return decode(hashFilename[0]);
|
const { hash } = newURL;
|
||||||
|
let extensionStart = -1;
|
||||||
|
for (const { index } of hash.matchAll(/\.pdf\b/gi)) {
|
||||||
|
extensionStart = index;
|
||||||
|
}
|
||||||
|
if (extensionStart > 0) {
|
||||||
|
let filenameStart = extensionStart;
|
||||||
|
while (filenameStart > 0 && !"/?#=".includes(hash[filenameStart - 1])) {
|
||||||
|
filenameStart--;
|
||||||
|
}
|
||||||
|
if (filenameStart < extensionStart) {
|
||||||
|
return decode(hash.slice(filenameStart, extensionStart + 4));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -122,6 +122,30 @@ describe("display_utils", function () {
|
|||||||
expect(
|
expect(
|
||||||
getPdfFilenameFromUrl("http://www.example.com/pdfs/pdf.html#file2.pdf")
|
getPdfFilenameFromUrl("http://www.example.com/pdfs/pdf.html#file2.pdf")
|
||||||
).toEqual("file2.pdf");
|
).toEqual("file2.pdf");
|
||||||
|
// Only the last ".pdf" of the hash is used.
|
||||||
|
expect(getPdfFilenameFromUrl("/pdfs/pdfs.html#a.pdf/b.pdf")).toEqual(
|
||||||
|
"b.pdf"
|
||||||
|
);
|
||||||
|
// A ".pdf" which isn't preceded by a name is ignored.
|
||||||
|
expect(getPdfFilenameFromUrl("/pdfs/pdfs.html#=.pdf")).toEqual(
|
||||||
|
"document.pdf"
|
||||||
|
);
|
||||||
|
// An invalid last ".pdf" prevents an earlier valid one from being used.
|
||||||
|
expect(getPdfFilenameFromUrl("/pdfs/pdfs.html#a.pdf/=.pdf")).toEqual(
|
||||||
|
"document.pdf"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("gets PDF filename from a long hash string efficiently", function () {
|
||||||
|
// Scanning the hash for a name is quadratic when it contains no ".pdf".
|
||||||
|
const url = `/pdfs/pdfs.html#${"a".repeat(200000)}`;
|
||||||
|
|
||||||
|
const startTime = performance.now();
|
||||||
|
const filename = getPdfFilenameFromUrl(url);
|
||||||
|
const duration = performance.now() - startTime;
|
||||||
|
|
||||||
|
expect(filename).toEqual("document.pdf");
|
||||||
|
expect(duration).toBeLessThan(1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("gets correct PDF filename when multiple ones are present", function () {
|
it("gets correct PDF filename when multiple ones are present", function () {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user