>2]=f;return 0},k:function(a){a=G(a);window.console.log(a)},i:function(a){a=G(a);\nreturn Date.parse(a)},l:function(a,b,d,e){a=G(a);b=G(b);d=G(d);d=`Quickjs -- ${a}: ${b}\\n${d}`;0!==e?window.alert(d):window.console.error(d)}};\n(function(){function a(f){c.asm=f.exports;x=c.asm.m;ba();O=c.asm.v;da.unshift(c.asm.n);P--;c.monitorRunDependencies&&c.monitorRunDependencies(P);0==P&&(null!==Q&&(clearInterval(Q),Q=null),R&&(f=R,R=null,f()))}function b(f){a(f.instance)}function d(f){return ka().then(function(g){return WebAssembly.instantiate(g,e)}).then(function(g){return g}).then(f,function(g){u(\"failed to asynchronously prepare wasm: \"+g);w(g)})}var e={a:oa};P++;c.monitorRunDependencies&&c.monitorRunDependencies(P);if(c.instantiateWasm)try{return c.instantiateWasm(e,\na)}catch(f){return u(\"Module.instantiateWasm callback failed with error: \"+f),!1}(function(){return v||\"function\"!=typeof WebAssembly.instantiateStreaming||T(U)||\"function\"!=typeof fetch?d(b):fetch(U,{credentials:\"same-origin\"}).then(function(f){return WebAssembly.instantiateStreaming(f,e).then(b,function(g){u(\"wasm streaming compile failed: \"+g);u(\"falling back to ArrayBuffer instantiation\");return d(b)})})})().catch(n);return{}})();\nc.___wasm_call_ctors=function(){return(c.___wasm_call_ctors=c.asm.n).apply(null,arguments)};c._evalInSandbox=function(){return(c._evalInSandbox=c.asm.o).apply(null,arguments)};c._nukeSandbox=function(){return(c._nukeSandbox=c.asm.p).apply(null,arguments)};c._init=function(){return(c._init=c.asm.q).apply(null,arguments)};c._commFun=function(){return(c._commFun=c.asm.r).apply(null,arguments)};c._dumpMemoryUse=function(){return(c._dumpMemoryUse=c.asm.s).apply(null,arguments)};\nvar L=c._malloc=function(){return(L=c._malloc=c.asm.t).apply(null,arguments)};c._free=function(){return(c._free=c.asm.u).apply(null,arguments)};var E=c.stackSave=function(){return(E=c.stackSave=c.asm.w).apply(null,arguments)},F=c.stackRestore=function(){return(F=c.stackRestore=c.asm.x).apply(null,arguments)},A=c.stackAlloc=function(){return(A=c.stackAlloc=c.asm.y).apply(null,arguments)};c.ccall=z;\nc.cwrap=function(a,b,d,e){d=d||[];var f=d.every(function(g){return\"number\"===g});return\"string\"!==b&&f&&!e?c[\"_\"+a]:function(){return z(a,b,d,arguments,e)}};c.stringToNewUTF8=X;var Y;R=function pa(){Y||Z();Y||(R=pa)};\nfunction Z(){function a(){if(!Y&&(Y=!0,c.calledRun=!0,!y)){V(da);h(c);if(c.onRuntimeInitialized)c.onRuntimeInitialized();if(c.postRun)for(\"function\"==typeof c.postRun&&(c.postRun=[c.postRun]);c.postRun.length;){var b=c.postRun.shift();ea.unshift(b)}V(ea)}}if(!(0} args - Arguments of the function.\n */\n callSandboxFunction(name, args) {\n try {\n args = this.exportValueToSandbox(args);\n this.commFun(name, args);\n } catch (e) {\n this.win.console.error(e);\n }\n }\n\n createSandboxExternals() {\n // All the functions in externals object are called\n // from the sandbox.\n const externals = {\n setTimeout: (callbackId, nMilliseconds) => {\n if (\n typeof callbackId !== \"number\" ||\n typeof nMilliseconds !== \"number\"\n ) {\n return;\n }\n\n if (callbackId === 0) {\n // This callbackId corresponds to the one used for userActivation.\n // So here, we cancel the last userActivation.\n this.win.clearTimeout(this.timeoutIds.get(callbackId));\n }\n\n const id = this.win.setTimeout(() => {\n this.timeoutIds.delete(callbackId);\n this.callSandboxFunction(\"timeoutCb\", {\n callbackId,\n interval: false,\n });\n }, nMilliseconds);\n this.timeoutIds.set(callbackId, id);\n },\n clearTimeout: callbackId => {\n this.win.clearTimeout(this.timeoutIds.get(callbackId));\n this.timeoutIds.delete(callbackId);\n },\n setInterval: (callbackId, nMilliseconds) => {\n if (\n typeof callbackId !== \"number\" ||\n typeof nMilliseconds !== \"number\"\n ) {\n return;\n }\n const id = this.win.setInterval(() => {\n this.callSandboxFunction(\"timeoutCb\", {\n callbackId,\n interval: true,\n });\n }, nMilliseconds);\n this.timeoutIds.set(callbackId, id);\n },\n clearInterval: callbackId => {\n this.win.clearInterval(this.timeoutIds.get(callbackId));\n this.timeoutIds.delete(callbackId);\n },\n alert: cMsg => {\n if (typeof cMsg !== \"string\") {\n return;\n }\n this.win.alert(cMsg);\n },\n confirm: cMsg => {\n if (typeof cMsg !== \"string\") {\n return false;\n }\n return this.win.confirm(cMsg);\n },\n prompt: (cQuestion, cDefault) => {\n if (typeof cQuestion !== \"string\" || typeof cDefault !== \"string\") {\n return null;\n }\n return this.win.prompt(cQuestion, cDefault);\n },\n parseURL: cUrl => {\n const url = new this.win.URL(cUrl);\n const props = [\n \"hash\",\n \"host\",\n \"hostname\",\n \"href\",\n \"origin\",\n \"password\",\n \"pathname\",\n \"port\",\n \"protocol\",\n \"search\",\n \"searchParams\",\n \"username\",\n ];\n\n return Object.fromEntries(\n props.map(name => [name, url[name].toString()])\n );\n },\n send: data => {\n if (!data) {\n return;\n }\n const event = new this.win.CustomEvent(\"updatefromsandbox\", {\n detail: this.importValueFromSandbox(data),\n });\n this.win.dispatchEvent(event);\n },\n };\n Object.setPrototypeOf(externals, null);\n\n return (name, args) => {\n try {\n const result = externals[name](...args);\n return this.exportValueToSandbox(result);\n } catch (error) {\n throw this.createErrorForSandbox(error?.toString() ?? \"\");\n }\n };\n }\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __w_pdfjs_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __w_pdfjs_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","/* Copyright 2020 Mozilla Foundation\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport ModuleLoader from \"../external/quickjs/quickjs-eval.js\";\nimport { SandboxSupportBase } from \"./pdf.sandbox.external.js\";\n\n/* eslint-disable-next-line no-unused-vars */\nconst pdfjsVersion = PDFJSDev.eval(\"BUNDLE_VERSION\");\n/* eslint-disable-next-line no-unused-vars */\nconst pdfjsBuild = PDFJSDev.eval(\"BUNDLE_BUILD\");\n\nclass SandboxSupport extends SandboxSupportBase {\n exportValueToSandbox(val) {\n // The communication with the Quickjs sandbox is based on strings\n // So we use JSON.stringfy to serialize\n return JSON.stringify(val);\n }\n\n importValueFromSandbox(val) {\n return val;\n }\n\n createErrorForSandbox(errorMessage) {\n return new Error(errorMessage);\n }\n}\n\nclass Sandbox {\n constructor(win, module) {\n this.support = new SandboxSupport(win, this);\n\n // The \"external\" functions created in pdf.sandbox.external.js\n // are finally used here:\n // https://github.com/mozilla/pdf.js.quickjs/blob/main/src/myjs.js\n // They're called from the sandbox only.\n module.externalCall = this.support.createSandboxExternals();\n\n this._module = module;\n\n // 0 to display error using console.error\n // else display error using window.alert\n this._alertOnError = 0;\n }\n\n create(data) {\n if (PDFJSDev.test(\"TESTING\")) {\n this._module.ccall(\"nukeSandbox\", null, []);\n }\n const code = [PDFJSDev.eval(\"PDF_SCRIPTING_JS_SOURCE\")];\n\n if (PDFJSDev.test(\"TESTING\")) {\n code.push(\n `globalThis.sendResultForTesting = callExternalFunction.bind(null, \"send\");`\n );\n } else {\n code.push(\"delete dump;\");\n }\n\n let success = false;\n let buf = 0;\n try {\n const sandboxData = JSON.stringify(data);\n // \"pdfjsScripting.initSandbox...\" MUST be the last line to be evaluated\n // since the returned value is used for the communication.\n code.push(`pdfjsScripting.initSandbox({ data: ${sandboxData} })`);\n buf = this._module.stringToNewUTF8(code.join(\"\\n\"));\n\n success = !!this._module.ccall(\n \"init\",\n \"number\",\n [\"number\", \"number\"],\n [buf, this._alertOnError]\n );\n } catch (error) {\n console.error(error);\n } finally {\n if (buf) {\n this._module.ccall(\"free\", \"number\", [\"number\"], [buf]);\n }\n }\n\n if (success) {\n this.support.commFun = this._module.cwrap(\"commFun\", null, [\n \"string\",\n \"string\",\n ]);\n } else {\n this.nukeSandbox();\n throw new Error(\"Cannot start sandbox\");\n }\n }\n\n dispatchEvent(event) {\n this.support?.callSandboxFunction(\"dispatchEvent\", event);\n }\n\n dumpMemoryUse() {\n this._module?.ccall(\"dumpMemoryUse\", null, []);\n }\n\n nukeSandbox() {\n if (this._module !== null) {\n this.support.destroy();\n this.support = null;\n this._module.ccall(\"nukeSandbox\", null, []);\n this._module = null;\n }\n }\n\n evalForTesting(code, key) {\n if (PDFJSDev.test(\"TESTING\")) {\n this._module.ccall(\n \"evalInSandbox\",\n null,\n [\"string\", \"int\"],\n [\n `try {\n sendResultForTesting([{ id: \"${key}\", result: ${code} }]);\n } catch (error) {\n sendResultForTesting([{ id: \"${key}\", result: error.message }]);\n }`,\n this._alertOnError,\n ]\n );\n } else {\n throw new Error(\"Not implemented: evalForTesting\");\n }\n }\n}\n\nfunction QuickJSSandbox() {\n return ModuleLoader().then(module => {\n return new Sandbox(window, module);\n });\n}\n\nexport { QuickJSSandbox };\n"],"names":["Module","_scriptDir","document","currentScript","src","undefined","c","h","n","ready","Promise","a","b","r","Object","assign","t","indexOf","substr","replace","lastIndexOf","aa","print","console","log","bind","u","printErr","warn","v","wasmBinary","noExitRuntime","WebAssembly","w","x","y","z","d","e","f","string","l","p","S","length","A","B","C","array","D","set","g","k","m","q","E","apply","F","G","H","TextDecoder","I","NaN","buffer","decode","subarray","String","fromCharCode","charCodeAt","J","K","L","M","N","ba","HEAP8","Int8Array","HEAP16","Int16Array","HEAP32","Int32Array","HEAPU8","Uint8Array","HEAPU16","Uint16Array","HEAPU32","Uint32Array","HEAPF32","Float32Array","HEAPF64","Float64Array","O","ca","da","ea","fa","preRun","shift","unshift","P","Q","R","onAbort","RuntimeError","T","startsWith","U","ha","locateFile","ia","ja","slice","Error","ka","fetch","resolve","then","credentials","ok","arrayBuffer","catch","V","get","la","toTimeString","match","Date","getFullYear","getTimezoneOffset","Math","max","Number","W","X","ma","na","JSON","parse","externalCall","message","atob","charAt","oa","now","getSeconds","getMinutes","getHours","getDate","getMonth","getDay","getTime","min","window","alert","j","call","grow","byteLength","push","i","error","asm","exports","monitorRunDependencies","clearInterval","instance","instantiate","instantiateWasm","instantiateStreaming","___wasm_call_ctors","arguments","_evalInSandbox","o","_nukeSandbox","_init","_commFun","_dumpMemoryUse","s","_malloc","_free","stackSave","stackRestore","stackAlloc","ccall","cwrap","every","stringToNewUTF8","Y","pa","Z","calledRun","onRuntimeInitialized","postRun","setStatus","setTimeout","run","preInit","pop","_default","default","SandboxSupportBase","constructor","win","timeoutIds","Map","commFun","destroy","id","values","clearTimeout","exportValueToSandbox","val","importValueFromSandbox","createErrorForSandbox","errorMessage","callSandboxFunction","name","args","createSandboxExternals","externals","callbackId","nMilliseconds","delete","interval","setInterval","cMsg","confirm","prompt","cQuestion","cDefault","parseURL","cUrl","url","URL","props","fromEntries","map","toString","send","data","event","CustomEvent","detail","dispatchEvent","setPrototypeOf","result","_quickjsEval","_interopRequireDefault","require","_pdfSandboxExternal","obj","__esModule","pdfjsVersion","pdfjsBuild","SandboxSupport","stringify","Sandbox","module","support","_module","_alertOnError","create","code","success","buf","sandboxData","join","nukeSandbox","dumpMemoryUse","evalForTesting","key","QuickJSSandbox","ModuleLoader"],"sourceRoot":""}
\ No newline at end of file
diff --git a/src/main/resources/templates/view-pdf.html b/src/main/resources/templates/view-pdf.html
index 1338f37d..afa85a92 100644
--- a/src/main/resources/templates/view-pdf.html
+++ b/src/main/resources/templates/view-pdf.html
@@ -21,9 +21,8 @@
Drag & Drop PDF(s) inside dashed region
or
+ class="position-absolute invisible" type="file"
+ accept="application/pdf"/>
diff --git a/src/main/resources/templates/viewer.html b/src/main/resources/templates/viewer.html
new file mode 100644
index 00000000..0072be8f
--- /dev/null
+++ b/src/main/resources/templates/viewer.html
@@ -0,0 +1,553 @@
+
+
+
+
+
+
+
+ PDF.js viewer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+