@caipira/vue-reader 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +153 -0
- package/dist/composables/useEpubReaderStrategy.d.ts +19 -0
- package/dist/composables/useEpubReaderStrategy.js +1 -0
- package/dist/composables/useEpubReaderWasm.d.ts +2 -0
- package/dist/composables/useEpubReaderWasm.js +131 -0
- package/dist/composables/useEpubReaderZipFetcher.d.ts +2 -0
- package/dist/composables/useEpubReaderZipFetcher.js +29 -0
- package/dist/services/browser/epub.d.ts +4 -0
- package/dist/services/browser/epub.js +22 -0
- package/dist/services/browser/manifest.d.ts +7 -0
- package/dist/services/browser/manifest.js +224 -0
- package/dist/services/browser/url-rewrite.d.ts +5 -0
- package/dist/services/browser/url-rewrite.js +183 -0
- package/dist/services/browser/url.d.ts +11 -0
- package/dist/services/browser/url.js +82 -0
- package/dist/services/browser/zip-fetcher.d.ts +12 -0
- package/dist/services/browser/zip-fetcher.js +123 -0
- package/dist/services/common/progression.d.ts +32 -0
- package/dist/services/common/progression.js +169 -0
- package/dist/services/common/title.d.ts +11 -0
- package/dist/services/common/title.js +40 -0
- package/dist/services/common/word-decorations.d.ts +4 -0
- package/dist/services/common/word-decorations.js +316 -0
- package/dist/services/common/word-lookup.d.ts +4 -0
- package/dist/services/common/word-lookup.js +154 -0
- package/dist/services/wasm/frame-document-bridge.d.ts +1 -0
- package/dist/services/wasm/frame-document-bridge.js +84 -0
- package/dist/services/wasm/wasm-streamer.d.ts +35 -0
- package/dist/services/wasm/wasm-streamer.js +157 -0
- package/dist/src/composables/useEpubReader.d.ts +27788 -0
- package/dist/src/composables/useEpubReader.js +8 -0
- package/dist/src/composables/useEpubReaderController.d.ts +27787 -0
- package/dist/src/composables/useEpubReaderController.js +23 -0
- package/dist/src/composables/useEpubReaderNavigation.d.ts +6 -0
- package/dist/src/composables/useEpubReaderNavigation.js +26 -0
- package/dist/src/composables/useEpubReaderSettings.d.ts +15 -0
- package/dist/src/composables/useEpubReaderSettings.js +8 -0
- package/dist/src/composables/useEpubReaderState.d.ts +22 -0
- package/dist/src/composables/useEpubReaderState.js +29 -0
- package/dist/src/composables/useReaderDictionary.d.ts +8 -0
- package/dist/src/composables/useReaderDictionary.js +13 -0
- package/dist/src/composables/useReaderSettings.d.ts +25 -0
- package/dist/src/composables/useReaderSettings.js +42 -0
- package/dist/src/composables/utils.d.ts +2 -0
- package/dist/src/composables/utils.js +1 -0
- package/dist/src/core/controller.d.ts +27789 -0
- package/dist/src/core/controller.js +262 -0
- package/dist/src/core/fonts.d.ts +1 -0
- package/dist/src/core/fonts.js +55 -0
- package/dist/src/core/settings-store.d.ts +16 -0
- package/dist/src/core/settings-store.js +58 -0
- package/dist/src/core/storage.d.ts +2 -0
- package/dist/src/core/storage.js +38 -0
- package/dist/src/index.d.ts +13 -0
- package/dist/src/index.js +11 -0
- package/dist/src/settings/options.d.ts +20 -0
- package/dist/src/settings/options.js +27 -0
- package/dist/src/types.d.ts +40 -0
- package/dist/src/types.js +1 -0
- package/dist/types/browser.d.ts +1 -0
- package/dist/types/browser.js +1 -0
- package/dist/types/common.d.ts +55 -0
- package/dist/types/common.js +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { HttpFetcher, Link, Manifest, Publication } from '@readium/shared';
|
|
2
|
+
const config = {
|
|
3
|
+
swScope: '/epub-streamer/',
|
|
4
|
+
swUrl: '/sw.js',
|
|
5
|
+
wasmUrl: '/wasm/epub-streamer-server.wasm?v=1',
|
|
6
|
+
};
|
|
7
|
+
let swRegistration = null;
|
|
8
|
+
let swReady = null;
|
|
9
|
+
const buildSwRegistrationUrl = () => {
|
|
10
|
+
const joiner = config.swUrl.includes('?') ? '&' : '?';
|
|
11
|
+
return `${config.swUrl}${joiner}wasmUrl=${encodeURIComponent(config.wasmUrl)}`;
|
|
12
|
+
};
|
|
13
|
+
const setWasmStreamerConfig = (next) => {
|
|
14
|
+
const changed = (next.swScope !== undefined && next.swScope !== config.swScope) ||
|
|
15
|
+
(next.swUrl !== undefined && next.swUrl !== config.swUrl) ||
|
|
16
|
+
(next.wasmUrl !== undefined && next.wasmUrl !== config.wasmUrl);
|
|
17
|
+
if (!changed) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (next.swScope !== undefined) {
|
|
21
|
+
config.swScope = next.swScope;
|
|
22
|
+
}
|
|
23
|
+
if (next.swUrl !== undefined) {
|
|
24
|
+
config.swUrl = next.swUrl;
|
|
25
|
+
}
|
|
26
|
+
if (next.wasmUrl !== undefined) {
|
|
27
|
+
config.wasmUrl = next.wasmUrl;
|
|
28
|
+
}
|
|
29
|
+
swRegistration = null;
|
|
30
|
+
swReady = null;
|
|
31
|
+
};
|
|
32
|
+
async function ensureController(timeoutMs = 8000) {
|
|
33
|
+
if (navigator.serviceWorker.controller)
|
|
34
|
+
return;
|
|
35
|
+
await new Promise((resolve, reject) => {
|
|
36
|
+
const timer = setTimeout(() => {
|
|
37
|
+
navigator.serviceWorker.removeEventListener('controllerchange', onChange);
|
|
38
|
+
reject(new Error('Service Worker did not take control of the page'));
|
|
39
|
+
}, timeoutMs);
|
|
40
|
+
const onChange = () => {
|
|
41
|
+
if (!navigator.serviceWorker.controller)
|
|
42
|
+
return;
|
|
43
|
+
clearTimeout(timer);
|
|
44
|
+
navigator.serviceWorker.removeEventListener('controllerchange', onChange);
|
|
45
|
+
resolve();
|
|
46
|
+
};
|
|
47
|
+
navigator.serviceWorker.addEventListener('controllerchange', onChange);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function resolvers() {
|
|
51
|
+
let resolve;
|
|
52
|
+
let reject;
|
|
53
|
+
const promise = new Promise((res, rej) => {
|
|
54
|
+
resolve = res;
|
|
55
|
+
reject = rej;
|
|
56
|
+
});
|
|
57
|
+
return { promise, resolve, reject };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Ensure the Service Worker is registered.
|
|
61
|
+
*
|
|
62
|
+
* Register the root-level SW script so it can control the whole page.
|
|
63
|
+
* The passthrough callback in sw.js ensures only requests under
|
|
64
|
+
* /epub-streamer/webpub/ reach the Go handler; everything else goes to the
|
|
65
|
+
* network normally.
|
|
66
|
+
*/
|
|
67
|
+
async function ensureSW() {
|
|
68
|
+
if (swReady)
|
|
69
|
+
return swReady;
|
|
70
|
+
swReady = (async () => {
|
|
71
|
+
swRegistration = await navigator.serviceWorker.register(buildSwRegistrationUrl(), {
|
|
72
|
+
scope: '/',
|
|
73
|
+
});
|
|
74
|
+
await navigator.serviceWorker.ready;
|
|
75
|
+
if (!navigator.serviceWorker.controller) {
|
|
76
|
+
await ensureController();
|
|
77
|
+
}
|
|
78
|
+
return swRegistration;
|
|
79
|
+
})();
|
|
80
|
+
return swReady;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Tell the Service Worker / WASM module to load a publication from a URL.
|
|
84
|
+
* The WASM module fetches the EPUB from the given URL, parses it, and
|
|
85
|
+
* makes it available via the streamer endpoints.
|
|
86
|
+
*/
|
|
87
|
+
async function loadPublication(bookId, epubUrl) {
|
|
88
|
+
await ensureSW();
|
|
89
|
+
const sw = swRegistration.active;
|
|
90
|
+
if (!sw)
|
|
91
|
+
throw new Error('Service Worker not active');
|
|
92
|
+
const { promise, resolve, reject } = resolvers();
|
|
93
|
+
const timeout = setTimeout(() => {
|
|
94
|
+
navigator.serviceWorker.removeEventListener('message', handler);
|
|
95
|
+
reject(new Error('Timeout waiting for SW load response'));
|
|
96
|
+
}, 30000);
|
|
97
|
+
const handler = (e) => {
|
|
98
|
+
if (e.data?.type === 'load:done' && e.data.bookId === bookId) {
|
|
99
|
+
clearTimeout(timeout);
|
|
100
|
+
navigator.serviceWorker.removeEventListener('message', handler);
|
|
101
|
+
if (e.data.success) {
|
|
102
|
+
resolve();
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
reject(new Error(e.data.error || 'Failed to load publication'));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
navigator.serviceWorker.addEventListener('message', handler);
|
|
110
|
+
sw.postMessage({ type: 'load', bookId, epubUrl });
|
|
111
|
+
return promise;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Create a Readium Publication backed by the WASM streamer.
|
|
115
|
+
*
|
|
116
|
+
* The HttpFetcher resolves resource requests against the base URL,
|
|
117
|
+
* which points into the SW scope. The SW intercepts these and
|
|
118
|
+
* the Go WASM handler serves them.
|
|
119
|
+
*/
|
|
120
|
+
async function createPublication(bookId) {
|
|
121
|
+
const baseUrl = new URL(`${config.swScope}webpub/${bookId}/`, window.location.origin).toString();
|
|
122
|
+
const fetcher = new HttpFetcher(undefined, baseUrl);
|
|
123
|
+
const manifestResource = fetcher.get(new Link({
|
|
124
|
+
href: 'manifest.json',
|
|
125
|
+
type: 'application/webpub+json',
|
|
126
|
+
}));
|
|
127
|
+
const manifestData = (await manifestResource.readAsJSON());
|
|
128
|
+
const manifest = Manifest.deserialize(manifestData);
|
|
129
|
+
if (!manifest)
|
|
130
|
+
throw new Error('Failed to parse manifest');
|
|
131
|
+
// Set the self link so pub.baseURL resolves to the streamer's base URL.
|
|
132
|
+
// This is critical for the <base> tag injected into the navigator iframe:
|
|
133
|
+
// without it, relative URLs in EPUB content (images, CSS, etc.) would
|
|
134
|
+
// resolve against "/" instead of "/epub-streamer/webpub/{bookId}/",
|
|
135
|
+
// bypassing the service worker and returning 404 from the origin server.
|
|
136
|
+
manifest.setSelfLink(baseUrl + 'manifest.json');
|
|
137
|
+
return new Publication({ manifest, fetcher });
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Unload a publication from the WASM streamer (cleanup).
|
|
141
|
+
*/
|
|
142
|
+
async function unloadPublication(bookId) {
|
|
143
|
+
const sw = swRegistration?.active;
|
|
144
|
+
if (!sw)
|
|
145
|
+
return;
|
|
146
|
+
const { promise, resolve } = resolvers();
|
|
147
|
+
const handler = (e) => {
|
|
148
|
+
if (e.data?.type === 'unload:done' && e.data.bookId === bookId) {
|
|
149
|
+
navigator.serviceWorker.removeEventListener('message', handler);
|
|
150
|
+
resolve();
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
navigator.serviceWorker.addEventListener('message', handler);
|
|
154
|
+
sw.postMessage({ type: 'unload', bookId });
|
|
155
|
+
return promise;
|
|
156
|
+
}
|
|
157
|
+
export { ensureSW, loadPublication, createPublication, unloadPublication, setWasmStreamerConfig, };
|