@caipira/vue-reader 0.0.1 → 0.0.3

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.
Files changed (68) hide show
  1. package/README.md +38 -24
  2. package/dist/src/composables/useEpubReader.d.ts +5 -27786
  3. package/dist/src/composables/useEpubReader.js +222 -4
  4. package/dist/src/composables/useEpubReaderLogging.d.ts +5 -0
  5. package/dist/src/composables/useEpubReaderLogging.js +27 -0
  6. package/dist/src/composables/useEpubReaderNavigation.d.ts +3 -3
  7. package/dist/src/composables/useEpubReaderNavigation.js +8 -15
  8. package/dist/src/composables/useEpubReaderState.d.ts +27794 -20
  9. package/dist/src/composables/useEpubReaderState.js +31 -21
  10. package/dist/{composables → src/composables}/useEpubReaderStrategy.d.ts +1 -1
  11. package/dist/src/composables/useEpubReaderWasm.d.ts +2 -0
  12. package/dist/{composables → src/composables}/useEpubReaderWasm.js +5 -5
  13. package/dist/src/composables/useEpubReaderZipFetcher.d.ts +2 -0
  14. package/dist/{composables → src/composables}/useEpubReaderZipFetcher.js +5 -5
  15. package/dist/src/composables/useReaderColors.d.ts +10 -0
  16. package/dist/src/composables/useReaderColors.js +38 -0
  17. package/dist/src/composables/useReaderSettings.d.ts +28 -11
  18. package/dist/src/composables/useReaderSettings.js +110 -36
  19. package/dist/src/index.d.ts +6 -9
  20. package/dist/src/index.js +5 -8
  21. package/dist/{services → src/services}/browser/epub.d.ts +1 -1
  22. package/dist/{services → src/services}/browser/manifest.d.ts +1 -1
  23. package/dist/{services → src/services}/browser/manifest.js +1 -1
  24. package/dist/{services → src/services}/browser/url-rewrite.d.ts +1 -1
  25. package/dist/{services → src/services}/browser/url-rewrite.js +1 -1
  26. package/dist/{services → src/services}/browser/zip-fetcher.d.ts +1 -1
  27. package/dist/{services → src/services}/browser/zip-fetcher.js +2 -2
  28. package/dist/{services → src/services}/common/progression.d.ts +3 -11
  29. package/dist/{services → src/services}/common/progression.js +1 -32
  30. package/dist/src/{core → services/common}/storage.d.ts +1 -1
  31. package/dist/src/{core → services/common}/storage.js +1 -2
  32. package/dist/{services → src/services}/common/title.d.ts +1 -1
  33. package/dist/{services → src/services}/common/word-decorations.d.ts +1 -1
  34. package/dist/{services → src/services}/common/word-decorations.js +2 -2
  35. package/dist/{services → src/services}/common/word-lookup.js +1 -1
  36. package/dist/{types → src/types}/common.d.ts +36 -1
  37. package/package.json +2 -2
  38. package/dist/composables/useEpubReaderWasm.d.ts +0 -2
  39. package/dist/composables/useEpubReaderZipFetcher.d.ts +0 -2
  40. package/dist/src/composables/useEpubReaderController.d.ts +0 -27787
  41. package/dist/src/composables/useEpubReaderController.js +0 -23
  42. package/dist/src/composables/useEpubReaderSettings.d.ts +0 -15
  43. package/dist/src/composables/useEpubReaderSettings.js +0 -8
  44. package/dist/src/composables/utils.d.ts +0 -2
  45. package/dist/src/composables/utils.js +0 -1
  46. package/dist/src/core/controller.d.ts +0 -27789
  47. package/dist/src/core/controller.js +0 -262
  48. package/dist/src/core/settings-store.d.ts +0 -16
  49. package/dist/src/core/settings-store.js +0 -58
  50. package/dist/src/settings/options.d.ts +0 -20
  51. package/dist/src/settings/options.js +0 -27
  52. package/dist/src/types.d.ts +0 -40
  53. package/dist/src/types.js +0 -1
  54. /package/dist/{composables → src/composables}/useEpubReaderStrategy.js +0 -0
  55. /package/dist/{services → src/services}/browser/epub.js +0 -0
  56. /package/dist/{services → src/services}/browser/url.d.ts +0 -0
  57. /package/dist/{services → src/services}/browser/url.js +0 -0
  58. /package/dist/src/{core → services/common}/fonts.d.ts +0 -0
  59. /package/dist/src/{core → services/common}/fonts.js +0 -0
  60. /package/dist/{services → src/services}/common/title.js +0 -0
  61. /package/dist/{services → src/services}/common/word-lookup.d.ts +0 -0
  62. /package/dist/{services → src/services}/wasm/frame-document-bridge.d.ts +0 -0
  63. /package/dist/{services → src/services}/wasm/frame-document-bridge.js +0 -0
  64. /package/dist/{services → src/services}/wasm/wasm-streamer.d.ts +0 -0
  65. /package/dist/{services → src/services}/wasm/wasm-streamer.js +0 -0
  66. /package/dist/{types → src/types}/browser.d.ts +0 -0
  67. /package/dist/{types → src/types}/browser.js +0 -0
  68. /package/dist/{types → src/types}/common.js +0 -0
@@ -1,8 +1,226 @@
1
- import { useEpubReaderController } from '../../src/composables/useEpubReaderController';
1
+ import { Publication as RPublication } from '@readium/shared';
2
+ import { EpubDefaults, EpubNavigator, EpubPreferences } from '@readium/navigator';
3
+ import { toRaw, watch, toValue, nextTick, computed, onMounted, onBeforeUnmount, } from 'vue';
4
+ import { getCurrentTitle } from '../../src/services/common/title';
5
+ import { generatePositions } from '../../src/services/common/progression';
6
+ import { setWasmStreamerConfig } from '../../src/services/wasm/wasm-streamer';
7
+ import { createSessionStorageAdapter } from '../../src/services/common/storage';
8
+ import { injectCurrentFontIntoIframe } from '../../src/services/common/fonts';
9
+ import { createReadiumWordLookupController } from '../../src/services/common/word-lookup';
10
+ import { createReadiumWordDecorationsController } from '../../src/services/common/word-decorations';
11
+ import { useReaderSettings } from '../../src/composables/useReaderSettings';
12
+ import { useEpubReaderWasm } from '../../src/composables/useEpubReaderWasm';
13
+ import { useEpubReaderState } from '../../src/composables/useEpubReaderState';
14
+ import { hasReaderDictionary } from '../../src/composables/useReaderDictionary';
15
+ import { onReaderColorsChange } from '../../src/composables/useReaderColors';
16
+ import { useEpubReaderZipFetcher } from '../../src/composables/useEpubReaderZipFetcher';
17
+ const ENABLE_EDGE_TAP_PAGE_TURN = false;
2
18
  export const useEpubReader = (src, containerRef, options) => {
3
- const controller = useEpubReaderController(src, containerRef, options);
19
+ const { error, loading, tocLinks, navigator, publication, totalPositions, currentPosition, currentChapterTitle, } = useEpubReaderState(containerRef);
20
+ const sourceRef = computed(() => toValue(src));
21
+ const storage = options?.storage ?? createSessionStorageAdapter();
22
+ const fontBaseUrl = options?.assets?.fontBaseUrl ?? '/fonts';
23
+ const { settings, hydrate, onSettingsChange } = useReaderSettings({
24
+ initialSettings: options?.settings,
25
+ preferences: options?.preferences,
26
+ });
27
+ let stopSettingsWatcher = null;
28
+ let activeChapterHref = '';
29
+ let chapterProgressions = new Map();
30
+ let activeSource = null;
31
+ let strategyFrameLoaded = null;
32
+ let stopReaderColorsWatcher = onReaderColorsChange((colors) => {
33
+ settings.backgroundColor = colors.background;
34
+ settings.textColor = colors.text;
35
+ });
36
+ let getProgress = (_idx, rawProg) => ({
37
+ progress: rawProg ?? 0,
38
+ resourceProgression: rawProg ?? 0,
39
+ });
40
+ const wordDecorations = hasReaderDictionary()
41
+ ? createReadiumWordDecorationsController(navigator, () => publication.value?.metadata?.languages?.[0])
42
+ : null;
43
+ const wordLookup = hasReaderDictionary()
44
+ ? createReadiumWordLookupController(() => publication.value?.metadata?.languages?.[0])
45
+ : null;
46
+ const applyPreferences = async () => {
47
+ if (!navigator.value) {
48
+ return;
49
+ }
50
+ await toRaw(navigator.value).submitPreferences(new EpubPreferences({
51
+ backgroundColor: settings.backgroundColor,
52
+ columnCount: settings.columnCount,
53
+ fontFamily: settings.fontFamily,
54
+ fontSize: settings.fontSize,
55
+ lineHeight: settings.lineHeight,
56
+ scroll: settings.scroll,
57
+ textAlign: settings.textAlign,
58
+ textColor: settings.textColor,
59
+ }));
60
+ await injectCurrentFontIntoIframe(containerRef.value, settings.fontFamily, fontBaseUrl);
61
+ };
62
+ const destroy = () => {
63
+ toRaw(navigator.value)?.destroy();
64
+ navigator.value = null;
65
+ publication.value = null;
66
+ tocLinks.value = [];
67
+ currentPosition.value = 0;
68
+ totalPositions.value = 0;
69
+ currentChapterTitle.value = '';
70
+ strategyFrameLoaded = null;
71
+ chapterProgressions = new Map();
72
+ activeChapterHref = '';
73
+ activeSource?.destroy();
74
+ activeSource = null;
75
+ wordDecorations?.destroy();
76
+ wordLookup?.destroy();
77
+ stopSettingsWatcher?.();
78
+ stopSettingsWatcher = null;
79
+ stopReaderColorsWatcher?.();
80
+ stopReaderColorsWatcher = null;
81
+ };
82
+ const selectStrategy = () => {
83
+ const strategy = options?.strategy ?? 'zip-fetcher';
84
+ if (strategy === 'wasm') {
85
+ setWasmStreamerConfig({
86
+ swUrl: options?.assets?.swUrl,
87
+ swScope: options?.assets?.swScope,
88
+ wasmUrl: options?.assets?.wasmUrl,
89
+ });
90
+ return useEpubReaderWasm();
91
+ }
92
+ return useEpubReaderZipFetcher();
93
+ };
94
+ const init = async () => {
95
+ if (!containerRef.value) {
96
+ return;
97
+ }
98
+ await hydrate();
99
+ loading.value = true;
100
+ error.value = null;
101
+ try {
102
+ const url = sourceRef.value;
103
+ const strategySource = selectStrategy();
104
+ const source = await strategySource.load(url);
105
+ activeSource = strategySource;
106
+ let pub;
107
+ let positions = [];
108
+ if (source.publication) {
109
+ pub = source.publication;
110
+ }
111
+ else {
112
+ pub = new RPublication({
113
+ manifest: source.manifest,
114
+ fetcher: source.fetcher,
115
+ });
116
+ }
117
+ getProgress = source.createProgressCalculator(pub);
118
+ chapterProgressions = source.chapterProgressions;
119
+ strategyFrameLoaded = source.onFrameLoaded ?? null;
120
+ positions = source.createPositions
121
+ ? (await source.createPositions(pub))
122
+ : generatePositions(pub);
123
+ publication.value = pub;
124
+ if (pub.toc) {
125
+ tocLinks.value = pub.toc.items.map((link) => ({
126
+ title: link.title || link.href,
127
+ link,
128
+ }));
129
+ }
130
+ if (positions.length === 0) {
131
+ positions = generatePositions(pub);
132
+ }
133
+ totalPositions.value = positions.length;
134
+ const initialLocator = storage.restorePosition(url, pub) ?? positions[0];
135
+ const listeners = {
136
+ positionChanged: (locator) => {
137
+ if (!locator) {
138
+ return;
139
+ }
140
+ activeChapterHref = locator.href.split('#')[0] ?? locator.href;
141
+ wordDecorations?.onPositionChanged(activeChapterHref);
142
+ const idx = publication.value
143
+ ? publication.value.readingOrder.findIndexWithHref(locator.href)
144
+ : -1;
145
+ if (idx < 0) {
146
+ return;
147
+ }
148
+ const { progress, resourceProgression } = getProgress(idx, locator.locations?.progression);
149
+ currentPosition.value = Math.round(Math.min(1, Math.max(0, progress)) * 100);
150
+ currentChapterTitle.value = getCurrentTitle(locator, chapterProgressions, tocLinks.value);
151
+ const persisted = locator.copyWithLocations({
152
+ position: idx + 1,
153
+ progression: resourceProgression,
154
+ });
155
+ storage.savePosition(url, persisted);
156
+ },
157
+ frameLoaded: async (wnd) => {
158
+ const nav = toRaw(navigator.value);
159
+ const currentHref = nav?.currentLocator?.href ?? activeChapterHref;
160
+ const chapterHref = (currentHref ?? '').split('#')[0] ?? '';
161
+ if (chapterHref) {
162
+ wordDecorations?.onFrameLoaded(wnd, chapterHref);
163
+ wordLookup?.onFrameLoaded(wnd);
164
+ }
165
+ if (chapterHref && strategyFrameLoaded) {
166
+ strategyFrameLoaded(wnd, chapterHref);
167
+ }
168
+ await injectCurrentFontIntoIframe(containerRef.value, settings.fontFamily, fontBaseUrl);
169
+ },
170
+ tap: () => !ENABLE_EDGE_TAP_PAGE_TURN,
171
+ click: () => !ENABLE_EDGE_TAP_PAGE_TURN,
172
+ zoom: () => { },
173
+ miscPointer: () => { },
174
+ scroll: () => { },
175
+ customEvent: () => { },
176
+ handleLocator: () => true,
177
+ textSelected: () => { },
178
+ contentProtection: () => { },
179
+ contextMenu: () => { },
180
+ peripheral: () => { },
181
+ };
182
+ navigator.value = new EpubNavigator(containerRef.value, pub, listeners, positions, initialLocator, {
183
+ preferences: new EpubPreferences(settings),
184
+ defaults: new EpubDefaults({}),
185
+ injectables: {
186
+ rules: [],
187
+ allowedDomains: [window.location.origin],
188
+ },
189
+ });
190
+ await toRaw(navigator.value).load();
191
+ await toRaw(navigator.value).submitPreferences(new EpubPreferences(settings));
192
+ stopSettingsWatcher = onSettingsChange(applyPreferences);
193
+ loading.value = false;
194
+ }
195
+ catch (e) {
196
+ error.value = e instanceof Error ? e.message : 'Unknown error loading EPUB';
197
+ loading.value = false;
198
+ }
199
+ };
200
+ const reload = async () => {
201
+ destroy();
202
+ await nextTick();
203
+ await init();
204
+ };
205
+ onMounted(async () => {
206
+ if (!sourceRef.value) {
207
+ error.value = 'No source URL provided';
208
+ return;
209
+ }
210
+ await init();
211
+ });
212
+ onBeforeUnmount(() => {
213
+ destroy();
214
+ });
215
+ watch(() => sourceRef.value, async (next, prev) => {
216
+ if (!next || next === prev) {
217
+ return;
218
+ }
219
+ await reload();
220
+ });
4
221
  return {
5
- ...controller,
6
- initReader: controller.actions.init,
222
+ init,
223
+ reload,
224
+ destroy,
7
225
  };
8
226
  };
@@ -0,0 +1,5 @@
1
+ export declare const useEpubReaderLogging: (namespace: string) => {
2
+ debug: (message: string, payload?: unknown) => void;
3
+ warn: (message: string, payload?: unknown) => void;
4
+ error: (message: string, payload?: unknown) => void;
5
+ };
@@ -0,0 +1,27 @@
1
+ import { useEpubReaderState, LOG_MODES } from '../../src/composables/useEpubReaderState';
2
+ export const useEpubReaderLogging = (namespace) => {
3
+ const { logMode } = useEpubReaderState();
4
+ const debug = (message, payload) => {
5
+ if ([LOG_MODES.NONE, LOG_MODES.ERROR, LOG_MODES.WARNING].includes(logMode.value)) {
6
+ return;
7
+ }
8
+ console.log(`[${namespace}] ${message}`, payload);
9
+ };
10
+ const warn = (message, payload) => {
11
+ if ([LOG_MODES.NONE, LOG_MODES.ERROR].includes(logMode.value)) {
12
+ return;
13
+ }
14
+ console.warn(`[${namespace}] ${message}`, payload);
15
+ };
16
+ const error = (message, payload) => {
17
+ if ([LOG_MODES.NONE].includes(logMode.value)) {
18
+ return;
19
+ }
20
+ console.error(`[${namespace}] ${message}`, payload);
21
+ };
22
+ return {
23
+ debug,
24
+ warn,
25
+ error,
26
+ };
27
+ };
@@ -1,6 +1,6 @@
1
- import type { ReturnTypeCreateController } from '../../src/composables/utils';
2
- export declare const useEpubReaderNavigation: (controller?: ReturnTypeCreateController) => {
1
+ import type { TocEntry } from '../../src/types/common';
2
+ export declare const useEpubReaderNavigation: () => {
3
3
  goForward: () => void;
4
4
  goBackward: () => void;
5
- goToLink: (link: import("..").TocEntry["link"]) => void;
5
+ goToLink: (link: TocEntry["link"]) => void;
6
6
  };
@@ -1,22 +1,15 @@
1
- import { useEpubReaderControllerRef } from '../../src/composables/useEpubReaderState';
2
- export const useEpubReaderNavigation = (controller) => {
3
- if (controller) {
4
- const { goForward, goBackward, goToLink } = controller.actions;
5
- return {
6
- goForward,
7
- goBackward,
8
- goToLink,
9
- };
10
- }
11
- const activeEpubReader = useEpubReaderControllerRef();
1
+ import { toRaw } from 'vue';
2
+ import { useEpubReaderState } from '../../src/composables/useEpubReaderState';
3
+ export const useEpubReaderNavigation = () => {
4
+ const { navigator } = useEpubReaderState();
12
5
  const goForward = () => {
13
- activeEpubReader.value?.actions?.goForward?.();
6
+ toRaw(navigator.value)?.goForward(false, () => { });
14
7
  };
15
8
  const goBackward = () => {
16
- activeEpubReader.value?.actions?.goBackward?.();
9
+ toRaw(navigator.value)?.goBackward(false, () => { });
17
10
  };
18
- const goToLink = (...args) => {
19
- activeEpubReader.value?.actions?.goToLink?.(...args);
11
+ const goToLink = (link) => {
12
+ toRaw(navigator.value)?.goLink(link, false, () => { });
20
13
  };
21
14
  return {
22
15
  goForward,