Closed misaalanshori closed 1 year ago
Epub.js did not work when it was loaded using
@require
.
what is the UserScript
header code that not work ?
When loaded using @require
like this:
// @require https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js
// @require https://cdn.jsdelivr.net/npm/epubjs@0.3.93/dist/epub.min.js
Everything does seem to get loaded, but epub.js does not seem to work properly (it does not render the epub).
The fact that epub.js does not work properly here is not an issue with this plugin, but it seems to be an issue with how the scripts are loaded by @require
, so having this alternative way of loading scripts would bypass this issue with @require
This is an example of my userscript that i patched with this alternative method of loading libraries: Link to code
Here is the original unpatched userscript generated by vite-plugin-monkey
This patched version works as expected. the only changes are adding the function to insert the script elements, and changing the arguments to the main userscript function
epub.js/src/archive.js#L153 will failed in UserScript scope
import { GM_xmlhttpRequest } from '$';
import JSZip from 'jszip';
const getFileBlob = (url: string) => {
return new Promise<Blob>((resolve, reject) =>
GM_xmlhttpRequest({
method: 'GET',
url: url,
responseType: 'blob',
onload: (response) => {
const blob = response.response;
resolve(blob);
},
onerror: reject,
})
);
};
const fileUrl =
'https://archiveofourown.org/downloads/25830331/Locked%20Out.epub?updated_at=1667832644';
const epubBlob = await getFileBlob(fileUrl);
const epubArrayBuffer = await epubBlob.arrayBuffer();
const zip = await JSZip().loadAsync(epubArrayBuffer);
const fileTask = zip.file('META-INF/container.xml')?.async?.('string');
console.log(await fileTask);
It is always in pending state in UserScript scope
Okay, so is it possible to add this alternative method of loading the script so that it's loaded in the scope of the website instead of the userscript scope?
I was thinking maybe there could be another option added similar to externalGlobals
(maybe called externalWindowGlobals
) that works similarly to externalGlobals
but instead of loading the script using @require
, it would load it by inserting script tags to the body (like using the functions I shared above). This way some libraries can be loaded through @require
and some that need it can be loaded through inserted script tags.
Or another way could be adding a boolean option that would switch the externalGlobals
option to instead get loaded using the script tag method instead of using @require
.
Okay, so is it possible to add this alternative method of loading the script so that it's loaded in the scope of the website instead of the userscript scope?
# .npmrc , pnpm install
public-hoist-pattern[]=jszip
// vite.config.ts
import { defineConfig } from 'vite';
import monkey from 'vite-plugin-monkey';
import epubjsPkg from './node_modules/epubjs/package.json';
import jszipPkg from './node_modules/jszip/package.json';
const epubjs_code = `
import { unsafeWindow } from '$';
const importScript = (src) => {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = src;
script.addEventListener('load', () => {
resolve();
script.parentElement?.removeChild(script);
});
script.addEventListener('error', (e) => {
reject(e);
script.parentElement?.removeChild(script);
});
document.body.appendChild(script);
});
};
await importScript(
'https://cdn.jsdelivr.net/npm/jszip@${jszipPkg.version}/dist/jszip.min.js'
);
await importScript(
'https://cdn.jsdelivr.net/npm/epubjs@${epubjsPkg.version}/dist/epub.min.js'
);
export default unsafeWindow?.ePub;
`.trim();
export default defineConfig({
plugins: [
{
name: 'script:epubjs',
enforce: 'pre',
apply: 'build',
resolveId(source, importer, options) {
if (source == 'epubjs') return `\0epubjs`;
},
load(id, options) {
if (id == `\0epubjs`) {
return epubjs_code;
}
},
},
monkey({
entry: 'src/main.ts',
userscript: {
icon: 'https://vitejs.dev/logo.svg',
namespace: 'npm/vite-plugin-monkey',
match: ['https://songe.li/'],
noframes: true,
connect: [`archiveofourown.org`],
grant: ['unsafeWindow'],
},
}),
],
});
Is this problem solved ? I think it can be closed
Yeah I think we can close this
I am having some problems where epub.js does not work when loaded through @require. But from my testing it works when I load the script by inserting a script element into the HTML.
Here is the alternative loading method that worked with epub.js:
Epub.js did not work when it was loaded using
@require
.Is there a way to get this plugin to build the script to use this loading process instead of using @require? Maybe it's something that can be added?