viewer: use esbuild to bundle pdf viewer and worker

This improves maintainability:
1. no need to hardcode each script file in Android code
2. no need to symlink pdf.js and pdf.worker.js
3. adds sourcemaps in debug builds to help debug some pdf.js related
   issues
This commit is contained in:
octocorvus 2023-08-03 07:37:01 +00:00 committed by Daniel Micay
parent ddce9b76b4
commit 627a566c2f
12 changed files with 711 additions and 26 deletions

View File

@ -30,11 +30,10 @@
] ]
}, },
"globals": { "globals": {
"pdfjsLib": "readonly",
"channel": "readonly" "channel": "readonly"
}, },
"ignorePatterns": [ "ignorePatterns": [
"pdf.js", "/app/src/*/assets/viewer",
"pdf.worker.js" "build/"
] ]
} }

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ keystore.properties
/.idea /.idea
/releases /releases
/node_modules /node_modules
/app/src/*/assets/viewer

View File

@ -1 +0,0 @@
../../../../node_modules/pdfjs-dist/build/pdf.min.js

View File

@ -1 +0,0 @@
../../../../node_modules/pdfjs-dist/build/pdf.worker.min.js

View File

@ -309,7 +309,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
return new WebResourceResponse("application/pdf", null, mInputStream); return new WebResourceResponse("application/pdf", null, mInputStream);
} }
if ("/viewer.html".equals(path)) { if ("/viewer/index.html".equals(path)) {
final WebResourceResponse response = fromAsset("text/html", path); final WebResourceResponse response = fromAsset("text/html", path);
HashMap<String, String> headers = new HashMap<>(); HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Security-Policy", CONTENT_SECURITY_POLICY); headers.put("Content-Security-Policy", CONTENT_SECURITY_POLICY);
@ -319,11 +319,11 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
return response; return response;
} }
if ("/viewer.css".equals(path)) { if ("/viewer/main.css".equals(path)) {
return fromAsset("text/css", path); return fromAsset("text/css", path);
} }
if ("/viewer.js".equals(path) || "/pdf.js".equals(path) || "/pdf.worker.js".equals(path)) { if ("/viewer/js/index.js".equals(path) || "/viewer/js/worker.js".equals(path)) {
return fromAsset("application/javascript", path); return fromAsset("application/javascript", path);
} }
@ -520,7 +520,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
mDocumentState = 0; mDocumentState = 0;
showSystemUi(); showSystemUi();
invalidateOptionsMenu(); invalidateOptionsMenu();
binding.webview.loadUrl("https://localhost/viewer.html"); binding.webview.loadUrl("https://localhost/viewer/index.html");
} }
public void loadPdfWithPassword(final String password) { public void loadPdfWithPassword(final String password) {

574
package-lock.json generated
View File

@ -5,6 +5,7 @@
"packages": { "packages": {
"": { "": {
"devDependencies": { "devDependencies": {
"esbuild": "^0.19.2",
"eslint": "^8.49.0", "eslint": "^8.49.0",
"pdfjs-dist": "^3.10.111" "pdfjs-dist": "^3.10.111"
} }
@ -18,6 +19,358 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/@esbuild/android-arm": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.2.tgz",
"integrity": "sha512-tM8yLeYVe7pRyAu9VMi/Q7aunpLwD139EY1S99xbQkT4/q2qa6eA4ige/WJQYdJ8GBL1K33pPFhPfPdJ/WzT8Q==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.2.tgz",
"integrity": "sha512-lsB65vAbe90I/Qe10OjkmrdxSX4UJDjosDgb8sZUKcg3oefEuW2OT2Vozz8ef7wrJbMcmhvCC+hciF8jY/uAkw==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.2.tgz",
"integrity": "sha512-qK/TpmHt2M/Hg82WXHRc/W/2SGo/l1thtDHZWqFq7oi24AjZ4O/CpPSu6ZuYKFkEgmZlFoa7CooAyYmuvnaG8w==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.2.tgz",
"integrity": "sha512-Ora8JokrvrzEPEpZO18ZYXkH4asCdc1DLdcVy8TGf5eWtPO1Ie4WroEJzwI52ZGtpODy3+m0a2yEX9l+KUn0tA==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.2.tgz",
"integrity": "sha512-tP+B5UuIbbFMj2hQaUr6EALlHOIOmlLM2FK7jeFBobPy2ERdohI4Ka6ZFjZ1ZYsrHE/hZimGuU90jusRE0pwDw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.2.tgz",
"integrity": "sha512-YbPY2kc0acfzL1VPVK6EnAlig4f+l8xmq36OZkU0jzBVHcOTyQDhnKQaLzZudNJQyymd9OqQezeaBgkTGdTGeQ==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.2.tgz",
"integrity": "sha512-nSO5uZT2clM6hosjWHAsS15hLrwCvIWx+b2e3lZ3MwbYSaXwvfO528OF+dLjas1g3bZonciivI8qKR/Hm7IWGw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.2.tgz",
"integrity": "sha512-Odalh8hICg7SOD7XCj0YLpYCEc+6mkoq63UnExDCiRA2wXEmGlK5JVrW50vZR9Qz4qkvqnHcpH+OFEggO3PgTg==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.2.tgz",
"integrity": "sha512-ig2P7GeG//zWlU0AggA3pV1h5gdix0MA3wgB+NsnBXViwiGgY77fuN9Wr5uoCrs2YzaYfogXgsWZbm+HGr09xg==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.2.tgz",
"integrity": "sha512-mLfp0ziRPOLSTek0Gd9T5B8AtzKAkoZE70fneiiyPlSnUKKI4lp+mGEnQXcQEHLJAcIYDPSyBvsUbKUG2ri/XQ==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.2.tgz",
"integrity": "sha512-hn28+JNDTxxCpnYjdDYVMNTR3SKavyLlCHHkufHV91fkewpIyQchS1d8wSbmXhs1fiYDpNww8KTFlJ1dHsxeSw==",
"cpu": [
"loong64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.2.tgz",
"integrity": "sha512-KbXaC0Sejt7vD2fEgPoIKb6nxkfYW9OmFUK9XQE4//PvGIxNIfPk1NmlHmMg6f25x57rpmEFrn1OotASYIAaTg==",
"cpu": [
"mips64el"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.2.tgz",
"integrity": "sha512-dJ0kE8KTqbiHtA3Fc/zn7lCd7pqVr4JcT0JqOnbj4LLzYnp+7h8Qi4yjfq42ZlHfhOCM42rBh0EwHYLL6LEzcw==",
"cpu": [
"ppc64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.2.tgz",
"integrity": "sha512-7Z/jKNFufZ/bbu4INqqCN6DDlrmOTmdw6D0gH+6Y7auok2r02Ur661qPuXidPOJ+FSgbEeQnnAGgsVynfLuOEw==",
"cpu": [
"riscv64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.2.tgz",
"integrity": "sha512-U+RinR6aXXABFCcAY4gSlv4CL1oOVvSSCdseQmGO66H+XyuQGZIUdhG56SZaDJQcLmrSfRmx5XZOWyCJPRqS7g==",
"cpu": [
"s390x"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.2.tgz",
"integrity": "sha512-oxzHTEv6VPm3XXNaHPyUTTte+3wGv7qVQtqaZCrgstI16gCuhNOtBXLEBkBREP57YTd68P0VgDgG73jSD8bwXQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.2.tgz",
"integrity": "sha512-WNa5zZk1XpTTwMDompZmvQLHszDDDN7lYjEHCUmAGB83Bgs20EMs7ICD+oKeT6xt4phV4NDdSi/8OfjPbSbZfQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.2.tgz",
"integrity": "sha512-S6kI1aT3S++Dedb7vxIuUOb3oAxqxk2Rh5rOXOTYnzN8JzW1VzBd+IqPiSpgitu45042SYD3HCoEyhLKQcDFDw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.2.tgz",
"integrity": "sha512-VXSSMsmb+Z8LbsQGcBMiM+fYObDNRm8p7tkUDMPG/g4fhFX5DEFmjxIEa3N8Zr96SjsJ1woAhF0DUnS3MF3ARw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.2.tgz",
"integrity": "sha512-5NayUlSAyb5PQYFAU9x3bHdsqB88RC3aM9lKDAz4X1mo/EchMIT1Q+pSeBXNgkfNmRecLXA0O8xP+x8V+g/LKg==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.2.tgz",
"integrity": "sha512-47gL/ek1v36iN0wL9L4Q2MFdujR0poLZMJwhO2/N3gA89jgHp4MR8DKCmwYtGNksbfJb9JoTtbkoe6sDhg2QTA==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.2.tgz",
"integrity": "sha512-tcuhV7ncXBqbt/Ybf0IyrMcwVOAPDckMK9rXNHtF17UTK18OKLpg08glminN06pt2WCoALhXdLfSPbVvK/6fxw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@eslint-community/eslint-utils": { "node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
@ -465,6 +818,43 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"node_modules/esbuild": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.2.tgz",
"integrity": "sha512-G6hPax8UbFakEj3hWO0Vs52LQ8k3lnBhxZWomUJDxfz3rZTLqF5k/FCzuNdLx2RbpBiQQF9H9onlDDH1lZsnjg==",
"dev": true,
"hasInstallScript": true,
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=12"
},
"optionalDependencies": {
"@esbuild/android-arm": "0.19.2",
"@esbuild/android-arm64": "0.19.2",
"@esbuild/android-x64": "0.19.2",
"@esbuild/darwin-arm64": "0.19.2",
"@esbuild/darwin-x64": "0.19.2",
"@esbuild/freebsd-arm64": "0.19.2",
"@esbuild/freebsd-x64": "0.19.2",
"@esbuild/linux-arm": "0.19.2",
"@esbuild/linux-arm64": "0.19.2",
"@esbuild/linux-ia32": "0.19.2",
"@esbuild/linux-loong64": "0.19.2",
"@esbuild/linux-mips64el": "0.19.2",
"@esbuild/linux-ppc64": "0.19.2",
"@esbuild/linux-riscv64": "0.19.2",
"@esbuild/linux-s390x": "0.19.2",
"@esbuild/linux-x64": "0.19.2",
"@esbuild/netbsd-x64": "0.19.2",
"@esbuild/openbsd-x64": "0.19.2",
"@esbuild/sunos-x64": "0.19.2",
"@esbuild/win32-arm64": "0.19.2",
"@esbuild/win32-ia32": "0.19.2",
"@esbuild/win32-x64": "0.19.2"
}
},
"node_modules/escape-string-regexp": { "node_modules/escape-string-regexp": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@ -1716,6 +2106,160 @@
"integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
"dev": true "dev": true
}, },
"@esbuild/android-arm": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.2.tgz",
"integrity": "sha512-tM8yLeYVe7pRyAu9VMi/Q7aunpLwD139EY1S99xbQkT4/q2qa6eA4ige/WJQYdJ8GBL1K33pPFhPfPdJ/WzT8Q==",
"dev": true,
"optional": true
},
"@esbuild/android-arm64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.2.tgz",
"integrity": "sha512-lsB65vAbe90I/Qe10OjkmrdxSX4UJDjosDgb8sZUKcg3oefEuW2OT2Vozz8ef7wrJbMcmhvCC+hciF8jY/uAkw==",
"dev": true,
"optional": true
},
"@esbuild/android-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.2.tgz",
"integrity": "sha512-qK/TpmHt2M/Hg82WXHRc/W/2SGo/l1thtDHZWqFq7oi24AjZ4O/CpPSu6ZuYKFkEgmZlFoa7CooAyYmuvnaG8w==",
"dev": true,
"optional": true
},
"@esbuild/darwin-arm64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.2.tgz",
"integrity": "sha512-Ora8JokrvrzEPEpZO18ZYXkH4asCdc1DLdcVy8TGf5eWtPO1Ie4WroEJzwI52ZGtpODy3+m0a2yEX9l+KUn0tA==",
"dev": true,
"optional": true
},
"@esbuild/darwin-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.2.tgz",
"integrity": "sha512-tP+B5UuIbbFMj2hQaUr6EALlHOIOmlLM2FK7jeFBobPy2ERdohI4Ka6ZFjZ1ZYsrHE/hZimGuU90jusRE0pwDw==",
"dev": true,
"optional": true
},
"@esbuild/freebsd-arm64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.2.tgz",
"integrity": "sha512-YbPY2kc0acfzL1VPVK6EnAlig4f+l8xmq36OZkU0jzBVHcOTyQDhnKQaLzZudNJQyymd9OqQezeaBgkTGdTGeQ==",
"dev": true,
"optional": true
},
"@esbuild/freebsd-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.2.tgz",
"integrity": "sha512-nSO5uZT2clM6hosjWHAsS15hLrwCvIWx+b2e3lZ3MwbYSaXwvfO528OF+dLjas1g3bZonciivI8qKR/Hm7IWGw==",
"dev": true,
"optional": true
},
"@esbuild/linux-arm": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.2.tgz",
"integrity": "sha512-Odalh8hICg7SOD7XCj0YLpYCEc+6mkoq63UnExDCiRA2wXEmGlK5JVrW50vZR9Qz4qkvqnHcpH+OFEggO3PgTg==",
"dev": true,
"optional": true
},
"@esbuild/linux-arm64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.2.tgz",
"integrity": "sha512-ig2P7GeG//zWlU0AggA3pV1h5gdix0MA3wgB+NsnBXViwiGgY77fuN9Wr5uoCrs2YzaYfogXgsWZbm+HGr09xg==",
"dev": true,
"optional": true
},
"@esbuild/linux-ia32": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.2.tgz",
"integrity": "sha512-mLfp0ziRPOLSTek0Gd9T5B8AtzKAkoZE70fneiiyPlSnUKKI4lp+mGEnQXcQEHLJAcIYDPSyBvsUbKUG2ri/XQ==",
"dev": true,
"optional": true
},
"@esbuild/linux-loong64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.2.tgz",
"integrity": "sha512-hn28+JNDTxxCpnYjdDYVMNTR3SKavyLlCHHkufHV91fkewpIyQchS1d8wSbmXhs1fiYDpNww8KTFlJ1dHsxeSw==",
"dev": true,
"optional": true
},
"@esbuild/linux-mips64el": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.2.tgz",
"integrity": "sha512-KbXaC0Sejt7vD2fEgPoIKb6nxkfYW9OmFUK9XQE4//PvGIxNIfPk1NmlHmMg6f25x57rpmEFrn1OotASYIAaTg==",
"dev": true,
"optional": true
},
"@esbuild/linux-ppc64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.2.tgz",
"integrity": "sha512-dJ0kE8KTqbiHtA3Fc/zn7lCd7pqVr4JcT0JqOnbj4LLzYnp+7h8Qi4yjfq42ZlHfhOCM42rBh0EwHYLL6LEzcw==",
"dev": true,
"optional": true
},
"@esbuild/linux-riscv64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.2.tgz",
"integrity": "sha512-7Z/jKNFufZ/bbu4INqqCN6DDlrmOTmdw6D0gH+6Y7auok2r02Ur661qPuXidPOJ+FSgbEeQnnAGgsVynfLuOEw==",
"dev": true,
"optional": true
},
"@esbuild/linux-s390x": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.2.tgz",
"integrity": "sha512-U+RinR6aXXABFCcAY4gSlv4CL1oOVvSSCdseQmGO66H+XyuQGZIUdhG56SZaDJQcLmrSfRmx5XZOWyCJPRqS7g==",
"dev": true,
"optional": true
},
"@esbuild/linux-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.2.tgz",
"integrity": "sha512-oxzHTEv6VPm3XXNaHPyUTTte+3wGv7qVQtqaZCrgstI16gCuhNOtBXLEBkBREP57YTd68P0VgDgG73jSD8bwXQ==",
"dev": true,
"optional": true
},
"@esbuild/netbsd-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.2.tgz",
"integrity": "sha512-WNa5zZk1XpTTwMDompZmvQLHszDDDN7lYjEHCUmAGB83Bgs20EMs7ICD+oKeT6xt4phV4NDdSi/8OfjPbSbZfQ==",
"dev": true,
"optional": true
},
"@esbuild/openbsd-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.2.tgz",
"integrity": "sha512-S6kI1aT3S++Dedb7vxIuUOb3oAxqxk2Rh5rOXOTYnzN8JzW1VzBd+IqPiSpgitu45042SYD3HCoEyhLKQcDFDw==",
"dev": true,
"optional": true
},
"@esbuild/sunos-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.2.tgz",
"integrity": "sha512-VXSSMsmb+Z8LbsQGcBMiM+fYObDNRm8p7tkUDMPG/g4fhFX5DEFmjxIEa3N8Zr96SjsJ1woAhF0DUnS3MF3ARw==",
"dev": true,
"optional": true
},
"@esbuild/win32-arm64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.2.tgz",
"integrity": "sha512-5NayUlSAyb5PQYFAU9x3bHdsqB88RC3aM9lKDAz4X1mo/EchMIT1Q+pSeBXNgkfNmRecLXA0O8xP+x8V+g/LKg==",
"dev": true,
"optional": true
},
"@esbuild/win32-ia32": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.2.tgz",
"integrity": "sha512-47gL/ek1v36iN0wL9L4Q2MFdujR0poLZMJwhO2/N3gA89jgHp4MR8DKCmwYtGNksbfJb9JoTtbkoe6sDhg2QTA==",
"dev": true,
"optional": true
},
"@esbuild/win32-x64": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.2.tgz",
"integrity": "sha512-tcuhV7ncXBqbt/Ybf0IyrMcwVOAPDckMK9rXNHtF17UTK18OKLpg08glminN06pt2WCoALhXdLfSPbVvK/6fxw==",
"dev": true,
"optional": true
},
"@eslint-community/eslint-utils": { "@eslint-community/eslint-utils": {
"version": "4.4.0", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
@ -2054,6 +2598,36 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"esbuild": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.2.tgz",
"integrity": "sha512-G6hPax8UbFakEj3hWO0Vs52LQ8k3lnBhxZWomUJDxfz3rZTLqF5k/FCzuNdLx2RbpBiQQF9H9onlDDH1lZsnjg==",
"dev": true,
"requires": {
"@esbuild/android-arm": "0.19.2",
"@esbuild/android-arm64": "0.19.2",
"@esbuild/android-x64": "0.19.2",
"@esbuild/darwin-arm64": "0.19.2",
"@esbuild/darwin-x64": "0.19.2",
"@esbuild/freebsd-arm64": "0.19.2",
"@esbuild/freebsd-x64": "0.19.2",
"@esbuild/linux-arm": "0.19.2",
"@esbuild/linux-arm64": "0.19.2",
"@esbuild/linux-ia32": "0.19.2",
"@esbuild/linux-loong64": "0.19.2",
"@esbuild/linux-mips64el": "0.19.2",
"@esbuild/linux-ppc64": "0.19.2",
"@esbuild/linux-riscv64": "0.19.2",
"@esbuild/linux-s390x": "0.19.2",
"@esbuild/linux-x64": "0.19.2",
"@esbuild/netbsd-x64": "0.19.2",
"@esbuild/openbsd-x64": "0.19.2",
"@esbuild/sunos-x64": "0.19.2",
"@esbuild/win32-arm64": "0.19.2",
"@esbuild/win32-ia32": "0.19.2",
"@esbuild/win32-x64": "0.19.2"
}
},
"escape-string-regexp": { "escape-string-regexp": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",

View File

@ -1,6 +1,7 @@
{ {
"type": "module", "type": "module",
"devDependencies": { "devDependencies": {
"esbuild": "^0.19.2",
"eslint": "^8.49.0", "eslint": "^8.49.0",
"pdfjs-dist": "^3.10.111" "pdfjs-dist": "^3.10.111"
} }

107
process_static.js Normal file
View File

@ -0,0 +1,107 @@
import esbuild from "esbuild";
import { spawn } from "node:child_process";
import fs from "node:fs/promises";
import path from "node:path";
/**
* @typedef ProcessOptions
* @property {string} rootDir
* @property {string[]} entryPoints
* @property {string} outDir
* @property {boolean} production
*/
async function processStatic() {
const rootDir = "viewer";
const outDir = "app/src/main/assets/viewer";
const outDirDebug = "app/src/debug/assets/viewer";
await commandLine(getCommand("node_modules/.bin/eslint"), ".");
await processScripts({
rootDir,
entryPoints: ["js/index.js", "js/worker.js"],
outDir,
production: true,
});
await processScripts({
rootDir,
entryPoints: ["js/index.js", "js/worker.js"],
outDir: outDirDebug,
production: false,
});
await processStyles({
rootDir,
entryPoints: ["main.css"],
outDir,
production: true,
});
await processHtml({
rootDir,
entryPoints: ["index.html"],
outDir,
production: true,
});
}
/**
* @param {string} command
* @param {string} winExt
* @returns {string}
*/
function getCommand(command, winExt = "cmd") {
return path.resolve(globalThis.process.platform === "win32" ? `${command}.${winExt}` : command);
}
/**
* @param {string} command
* @param {...string} args
* @returns {Promise<void>}
*/
function commandLine(command, ...args) {
return new Promise((resolve, reject) => {
const subprocess = spawn(command, args, { shell: false, stdio: "inherit" });
subprocess.on("close", (code) => code === 0 ? resolve() : reject());
});
}
/**
* @param {ProcessOptions} options
*/
async function processScripts(options) {
const entryPoints = options.entryPoints.map((filepath) => path.join(options.rootDir, filepath));
await esbuild.build({
entryPoints,
bundle: true,
format: "esm",
platform: "browser",
target: "es2022",
outdir: path.join(options.outDir, "js"),
minify: options.production,
sourcemap: options.production ? false : "inline",
});
}
/**
* @param {ProcessOptions} options
*/
async function processStyles(options) {
const entryPoints = options.entryPoints.map((filepath) => path.join(options.rootDir, filepath));
await esbuild.build({
entryPoints,
bundle: true,
outdir: options.outDir,
minify: options.production,
});
}
/**
* @param {ProcessOptions} options
*/
async function processHtml(options) {
for (const entryPoint of options.entryPoints) {
await fs.copyFile(path.join(options.rootDir, entryPoint), path.join(options.outDir, entryPoint));
}
}
await processStatic();

View File

@ -3,14 +3,13 @@
<head> <head>
<meta name="viewport" content="width=device-width, user-scalable=no" /> <meta name="viewport" content="width=device-width, user-scalable=no" />
<title>PDF</title> <title>PDF</title>
<link rel="stylesheet" href="viewer.css" /> <link rel="stylesheet" href="/viewer/main.css">
<script src="pdf.js"></script> <script type="module" src="/viewer/js/index.js"></script>
</head> </head>
<body> <body>
<div id="container"> <div id="container">
<canvas id="content"></canvas> <canvas id="content"></canvas>
<div id="text" class="textLayer"></div> <div id="text" class="textLayer"></div>
</div> </div>
<script src="viewer.js"></script>
</body> </body>
</html> </html>

View File

@ -1,6 +1,11 @@
"use strict"; import {
GlobalWorkerOptions,
PasswordResponses,
getDocument,
renderTextLayer,
} from "pdfjs-dist";
pdfjsLib.GlobalWorkerOptions.workerSrc = "/pdf.worker.js"; GlobalWorkerOptions.workerSrc = "/viewer/js/worker.js";
let pdfDoc = null; let pdfDoc = null;
let pageRendering = false; let pageRendering = false;
@ -166,7 +171,7 @@ function renderPage(pageNumber, zoom, prerender, prerenderTrigger=0) {
render(); render();
const newTextLayerDiv = textLayerDiv.cloneNode(); const newTextLayerDiv = textLayerDiv.cloneNode();
task = pdfjsLib.renderTextLayer({ task = renderTextLayer({
textContentSource: page.streamTextContent(), textContentSource: page.streamTextContent(),
container: newTextLayerDiv, container: newTextLayerDiv,
viewport: viewport viewport: viewport
@ -215,7 +220,7 @@ function renderPage(pageNumber, zoom, prerender, prerenderTrigger=0) {
}); });
} }
function onRenderPage(zoom) { globalThis.onRenderPage = function (zoom) {
if (pageRendering) { if (pageRendering) {
if (newPageNumber === channel.getPage() && newZoomRatio === channel.getZoomRatio() && if (newPageNumber === channel.getPage() && newZoomRatio === channel.getZoomRatio() &&
orientationDegrees === channel.getDocumentOrientationDegrees()) { orientationDegrees === channel.getDocumentOrientationDegrees()) {
@ -232,13 +237,13 @@ function onRenderPage(zoom) {
} else { } else {
renderPage(channel.getPage(), zoom, false); renderPage(channel.getPage(), zoom, false);
} }
} };
function isTextSelected() { globalThis.isTextSelected = function () {
return window.getSelection().toString() !== ""; return window.getSelection().toString() !== "";
} };
function toggleTextLayerVisibility() { globalThis.toggleTextLayerVisibility = function () {
let textLayerForeground = "red"; let textLayerForeground = "red";
let textLayerOpacity = 1; let textLayerOpacity = 1;
if (isTextLayerVisible) { if (isTextLayerVisible) {
@ -248,15 +253,15 @@ function toggleTextLayerVisibility() {
document.documentElement.style.setProperty("--text-layer-foreground", textLayerForeground); document.documentElement.style.setProperty("--text-layer-foreground", textLayerForeground);
document.documentElement.style.setProperty("--text-layer-opacity", textLayerOpacity.toString()); document.documentElement.style.setProperty("--text-layer-opacity", textLayerOpacity.toString());
isTextLayerVisible = !isTextLayerVisible; isTextLayerVisible = !isTextLayerVisible;
} };
function loadDocument() { globalThis.loadDocument = function () {
const pdfPassword = channel.getPassword(); const pdfPassword = channel.getPassword();
const loadingTask = pdfjsLib.getDocument({ url: "https://localhost/placeholder.pdf", password: pdfPassword }); const loadingTask = getDocument({ url: "https://localhost/placeholder.pdf", password: pdfPassword });
loadingTask.onPassword = (_, error) => { loadingTask.onPassword = (_, error) => {
if (error === pdfjsLib.PasswordResponses.NEED_PASSWORD) { if (error === PasswordResponses.NEED_PASSWORD) {
channel.showPasswordPrompt(); channel.showPasswordPrompt();
} else if (error === pdfjsLib.PasswordResponses.INCORRECT_PASSWORD) { } else if (error === PasswordResponses.INCORRECT_PASSWORD) {
channel.invalidPassword(); channel.invalidPassword();
} }
}; };
@ -274,7 +279,7 @@ function loadDocument() {
}, function (reason) { }, function (reason) {
console.error(reason.name + ": " + reason.message); console.error(reason.name + ": " + reason.message);
}); });
} };
window.onresize = () => { window.onresize = () => {
setLayerTransform(canvas.clientWidth, canvas.clientHeight, textLayerDiv); setLayerTransform(canvas.clientWidth, canvas.clientHeight, textLayerDiv);

1
viewer/js/worker.js Normal file
View File

@ -0,0 +1 @@
import "pdfjs-dist/build/pdf.worker.js";