@somecat/epub-reader 0.1.4 → 0.1.6
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/dist/core.cjs +19 -3
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +2 -2
- package/dist/core.d.ts +2 -2
- package/dist/core.js +19 -3
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +19 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +19 -3
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +322 -357
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +8 -1
- package/dist/react.d.ts +8 -1
- package/dist/react.js +322 -357
- package/dist/react.js.map +1 -1
- package/dist/{types-Dc66KVH2.d.cts → types-BQTZQhXd.d.cts} +4 -0
- package/dist/{types-Dc66KVH2.d.ts → types-BQTZQhXd.d.ts} +4 -0
- package/dist/vue.cjs +0 -0
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +57 -2
- package/dist/vue.d.ts +57 -2
- package/dist/vue.js +0 -0
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
- package/style.css +123 -42
package/dist/core.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require('foliate-js/view.js');
|
|
4
4
|
|
|
5
5
|
// src/core/reader.ts
|
|
6
|
-
var getContentCSS = (fontSize, isDark, extraCSS) => `
|
|
6
|
+
var getContentCSS = (fontSize, isDark, lineHeight, letterSpacing, extraCSS) => `
|
|
7
7
|
@namespace epub "http://www.idpf.org/2007/ops";
|
|
8
8
|
html {
|
|
9
9
|
color-scheme: ${isDark ? "dark" : "light"} !important;
|
|
@@ -12,9 +12,11 @@ body {
|
|
|
12
12
|
background-color: transparent !important;
|
|
13
13
|
color: ${isDark ? "#e0e0e0" : "black"} !important;
|
|
14
14
|
font-size: ${fontSize}% !important;
|
|
15
|
+
line-height: ${lineHeight} !important;
|
|
16
|
+
letter-spacing: ${letterSpacing}em !important;
|
|
15
17
|
}
|
|
16
18
|
p {
|
|
17
|
-
line-height:
|
|
19
|
+
line-height: inherit !important;
|
|
18
20
|
margin-bottom: 1em;
|
|
19
21
|
}
|
|
20
22
|
a {
|
|
@@ -34,6 +36,8 @@ function createEBookReader(container, options = {}) {
|
|
|
34
36
|
const {
|
|
35
37
|
darkMode: initialDarkMode = false,
|
|
36
38
|
fontSize: initialFontSize = 100,
|
|
39
|
+
lineHeight: initialLineHeight = 1.6,
|
|
40
|
+
letterSpacing: initialLetterSpacing = 0,
|
|
37
41
|
extraContentCSS,
|
|
38
42
|
onReady,
|
|
39
43
|
onError,
|
|
@@ -46,6 +50,8 @@ function createEBookReader(container, options = {}) {
|
|
|
46
50
|
let toc = [];
|
|
47
51
|
let fontSize = initialFontSize;
|
|
48
52
|
let darkMode = initialDarkMode;
|
|
53
|
+
let lineHeight = initialLineHeight;
|
|
54
|
+
let letterSpacing = initialLetterSpacing;
|
|
49
55
|
let searchToken = 0;
|
|
50
56
|
container.innerHTML = "";
|
|
51
57
|
const viewer = document.createElement("foliate-view");
|
|
@@ -57,7 +63,7 @@ function createEBookReader(container, options = {}) {
|
|
|
57
63
|
const applyStyles = () => {
|
|
58
64
|
if (destroyed) return;
|
|
59
65
|
if (!viewer.renderer?.setStyles) return;
|
|
60
|
-
viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, extraContentCSS));
|
|
66
|
+
viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, lineHeight, letterSpacing, extraContentCSS));
|
|
61
67
|
requestAnimationFrame(() => {
|
|
62
68
|
setTimeout(() => {
|
|
63
69
|
if (destroyed) return;
|
|
@@ -133,6 +139,16 @@ function createEBookReader(container, options = {}) {
|
|
|
133
139
|
fontSize = safe;
|
|
134
140
|
applyStyles();
|
|
135
141
|
},
|
|
142
|
+
setLineHeight(nextLineHeight) {
|
|
143
|
+
const safe = Math.min(3, Math.max(1, nextLineHeight));
|
|
144
|
+
lineHeight = safe;
|
|
145
|
+
applyStyles();
|
|
146
|
+
},
|
|
147
|
+
setLetterSpacing(nextLetterSpacing) {
|
|
148
|
+
const safe = Math.min(0.3, Math.max(0, nextLetterSpacing));
|
|
149
|
+
letterSpacing = safe;
|
|
150
|
+
applyStyles();
|
|
151
|
+
},
|
|
136
152
|
async search(query, opts = {}) {
|
|
137
153
|
const normalized = query.trim();
|
|
138
154
|
if (!normalized) {
|
package/dist/core.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/reader.ts"],"names":[],"mappings":"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","file":"core.cjs","sourcesContent":["import 'foliate-js/view.js'\r\nimport type { EBookReaderHandle, EBookReaderOptions, ProgressInfo, SearchOptions, SearchResult, TocItem } from './types.js'\r\n\r\ntype FoliateViewElement = HTMLElement & {\r\n book?: { toc?: TocItem[] }\r\n renderer?: {\r\n prevSection?: () => void\r\n nextSection?: () => void\r\n setStyles?: (css: string) => void\r\n render?: () => void\r\n expand?: () => void\r\n }\r\n open?: (file: File) => Promise<void>\r\n init?: (options?: unknown) => Promise<void>\r\n goLeft?: () => void\r\n goRight?: () => void\r\n goTo?: (target: string) => Promise<void> | void\r\n goToFraction?: (fraction: number) => Promise<void> | void\r\n search?: (options: unknown) => AsyncIterable<unknown>\r\n clearSearch?: () => void\r\n}\r\n\r\nconst getContentCSS = (fontSize: number, isDark: boolean, extraCSS?: string) => `\r\n@namespace epub \"http://www.idpf.org/2007/ops\";\r\nhtml {\r\n color-scheme: ${isDark ? 'dark' : 'light'} !important;\r\n}\r\nbody {\r\n background-color: transparent !important;\r\n color: ${isDark ? '#e0e0e0' : 'black'} !important;\r\n font-size: ${fontSize}% !important;\r\n}\r\np {\r\n line-height: 1.6;\r\n margin-bottom: 1em;\r\n}\r\na {\r\n color: ${isDark ? '#64b5f6' : '#2563eb'} !important;\r\n}\r\nimg {\r\n max-width: 100%;\r\n height: auto;\r\n object-fit: contain;\r\n ${isDark ? 'filter: brightness(0.8) contrast(1.2);' : ''}\r\n}\r\n${extraCSS ?? ''}\r\n`\r\n\r\nexport function createEBookReader(container: HTMLElement, options: EBookReaderOptions = {}): EBookReaderHandle {\r\n if (!container) throw new Error('container is required')\r\n if (!customElements.get('foliate-view')) throw new Error('foliate-view is not defined')\r\n\r\n const {\r\n darkMode: initialDarkMode = false,\r\n fontSize: initialFontSize = 100,\r\n extraContentCSS,\r\n onReady,\r\n onError,\r\n onProgress,\r\n onToc,\r\n onSearchProgress,\r\n onContentLoad,\r\n } = options\r\n\r\n let destroyed = false\r\n let toc: TocItem[] = []\r\n let fontSize = initialFontSize\r\n let darkMode = initialDarkMode\r\n let searchToken = 0\r\n\r\n container.innerHTML = ''\r\n\r\n const viewer = document.createElement('foliate-view') as FoliateViewElement\r\n viewer.style.display = 'block'\r\n viewer.style.width = '100%'\r\n viewer.style.height = '100%'\r\n viewer.setAttribute('margin', '48')\r\n viewer.setAttribute('gap', '0.07')\r\n\r\n const applyStyles = () => {\r\n if (destroyed) return\r\n if (!viewer.renderer?.setStyles) return\r\n viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, extraContentCSS))\r\n requestAnimationFrame(() => {\r\n setTimeout(() => {\r\n if (destroyed) return\r\n viewer.renderer?.render?.()\r\n viewer.renderer?.expand?.()\r\n }, 50)\r\n })\r\n }\r\n\r\n const handleLoad = (e: Event) => {\r\n applyStyles()\r\n const detail = (e as CustomEvent).detail as { doc?: Document } | undefined\r\n if (detail?.doc) onContentLoad?.(detail.doc)\r\n }\r\n\r\n const handleRelocate = (e: Event) => {\r\n const detail = (e as CustomEvent).detail as ProgressInfo\r\n onProgress?.(detail)\r\n }\r\n\r\n viewer.addEventListener('load', handleLoad as EventListener)\r\n viewer.addEventListener('relocate', handleRelocate as EventListener)\r\n\r\n container.appendChild(viewer)\r\n\r\n const handle: EBookReaderHandle = {\r\n async open(file) {\r\n if (destroyed) return\r\n if (!file) return\r\n\r\n try {\r\n viewer.clearSearch?.()\r\n searchToken++\r\n\r\n await viewer.open?.(file)\r\n\r\n const nextToc = viewer.book?.toc ?? []\r\n toc = nextToc\r\n onToc?.(toc)\r\n\r\n await viewer.init?.({ showTextStart: true })\r\n applyStyles()\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n },\r\n destroy() {\r\n if (destroyed) return\r\n destroyed = true\r\n searchToken++\r\n viewer.removeEventListener('load', handleLoad)\r\n viewer.removeEventListener('relocate', handleRelocate as EventListener)\r\n container.innerHTML = ''\r\n },\r\n prevPage() {\r\n viewer.goLeft?.()\r\n },\r\n nextPage() {\r\n viewer.goRight?.()\r\n },\r\n prevSection() {\r\n viewer.renderer?.prevSection?.()\r\n },\r\n nextSection() {\r\n viewer.renderer?.nextSection?.()\r\n },\r\n goTo(target) {\r\n if (!target) return\r\n viewer.goTo?.(target)\r\n },\r\n goToFraction(fraction) {\r\n const safe = Math.min(1, Math.max(0, fraction))\r\n viewer.goToFraction?.(safe)\r\n },\r\n setDarkMode(nextDarkMode) {\r\n darkMode = nextDarkMode\r\n applyStyles()\r\n },\r\n setFontSize(nextFontSize) {\r\n const safe = Math.min(300, Math.max(50, nextFontSize))\r\n fontSize = safe\r\n applyStyles()\r\n },\r\n async search(query, opts: SearchOptions = {}) {\r\n const normalized = query.trim()\r\n if (!normalized) {\r\n viewer.clearSearch?.()\r\n return []\r\n }\r\n\r\n const token = ++searchToken\r\n const results: SearchResult[] = []\r\n\r\n try {\r\n for await (const item of viewer.search?.({\r\n query: normalized,\r\n matchCase: Boolean(opts.matchCase),\r\n matchWholeWords: Boolean(opts.wholeWords),\r\n matchDiacritics: Boolean(opts.matchDiacritics),\r\n }) ?? []) {\r\n if (destroyed || token !== searchToken) return results\r\n\r\n if (item === 'done') {\r\n onSearchProgress?.({ done: true, progress: 1 })\r\n break\r\n }\r\n\r\n if (typeof item === 'object' && item && 'progress' in (item as any)) {\r\n const progress = (item as any).progress\r\n if (typeof progress === 'number') onSearchProgress?.({ progress })\r\n continue\r\n }\r\n\r\n const anyItem = item as any\r\n if (anyItem?.subitems?.length) {\r\n for (const sub of anyItem.subitems) {\r\n results.push({\r\n label: anyItem.label,\r\n cfi: sub?.cfi,\r\n excerpt: sub?.excerpt,\r\n title: sub?.title,\r\n })\r\n }\r\n } else if (anyItem?.cfi) {\r\n results.push({\r\n cfi: anyItem.cfi,\r\n excerpt: anyItem.excerpt,\r\n title: anyItem.title,\r\n })\r\n }\r\n }\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n\r\n return results\r\n },\r\n cancelSearch() {\r\n searchToken++\r\n },\r\n clearSearch() {\r\n viewer.clearSearch?.()\r\n },\r\n getToc() {\r\n return toc\r\n },\r\n }\r\n\r\n onReady?.(handle)\r\n return handle\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/reader.ts"],"names":[],"mappings":"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","file":"core.cjs","sourcesContent":["import 'foliate-js/view.js'\r\nimport type { EBookReaderHandle, EBookReaderOptions, ProgressInfo, SearchOptions, SearchResult, TocItem } from './types.js'\r\n\r\ntype FoliateViewElement = HTMLElement & {\r\n book?: { toc?: TocItem[] }\r\n renderer?: {\r\n prevSection?: () => void\r\n nextSection?: () => void\r\n setStyles?: (css: string) => void\r\n render?: () => void\r\n expand?: () => void\r\n }\r\n open?: (file: File) => Promise<void>\r\n init?: (options?: unknown) => Promise<void>\r\n goLeft?: () => void\r\n goRight?: () => void\r\n goTo?: (target: string) => Promise<void> | void\r\n goToFraction?: (fraction: number) => Promise<void> | void\r\n search?: (options: unknown) => AsyncIterable<unknown>\r\n clearSearch?: () => void\r\n}\r\n\r\nconst getContentCSS = (fontSize: number, isDark: boolean, lineHeight: number, letterSpacing: number, extraCSS?: string) => `\n@namespace epub \"http://www.idpf.org/2007/ops\";\r\nhtml {\r\n color-scheme: ${isDark ? 'dark' : 'light'} !important;\r\n}\r\nbody {\r\n background-color: transparent !important;\r\n color: ${isDark ? '#e0e0e0' : 'black'} !important;\r\n font-size: ${fontSize}% !important;\r\n line-height: ${lineHeight} !important;\n letter-spacing: ${letterSpacing}em !important;\n}\r\np {\r\n line-height: inherit !important;\n margin-bottom: 1em;\r\n}\r\na {\r\n color: ${isDark ? '#64b5f6' : '#2563eb'} !important;\r\n}\r\nimg {\r\n max-width: 100%;\r\n height: auto;\r\n object-fit: contain;\r\n ${isDark ? 'filter: brightness(0.8) contrast(1.2);' : ''}\r\n}\r\n${extraCSS ?? ''}\r\n`\r\n\r\nexport function createEBookReader(container: HTMLElement, options: EBookReaderOptions = {}): EBookReaderHandle {\r\n if (!container) throw new Error('container is required')\r\n if (!customElements.get('foliate-view')) throw new Error('foliate-view is not defined')\r\n\r\n const {\r\n darkMode: initialDarkMode = false,\r\n fontSize: initialFontSize = 100,\r\n lineHeight: initialLineHeight = 1.6,\n letterSpacing: initialLetterSpacing = 0,\n extraContentCSS,\r\n onReady,\r\n onError,\r\n onProgress,\r\n onToc,\r\n onSearchProgress,\r\n onContentLoad,\r\n } = options\r\n\r\n let destroyed = false\r\n let toc: TocItem[] = []\r\n let fontSize = initialFontSize\r\n let darkMode = initialDarkMode\r\n let lineHeight = initialLineHeight\n let letterSpacing = initialLetterSpacing\n let searchToken = 0\r\n\r\n container.innerHTML = ''\r\n\r\n const viewer = document.createElement('foliate-view') as FoliateViewElement\r\n viewer.style.display = 'block'\r\n viewer.style.width = '100%'\r\n viewer.style.height = '100%'\r\n viewer.setAttribute('margin', '48')\r\n viewer.setAttribute('gap', '0.07')\r\n\r\n const applyStyles = () => {\r\n if (destroyed) return\r\n if (!viewer.renderer?.setStyles) return\r\n viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, lineHeight, letterSpacing, extraContentCSS))\n requestAnimationFrame(() => {\r\n setTimeout(() => {\r\n if (destroyed) return\r\n viewer.renderer?.render?.()\r\n viewer.renderer?.expand?.()\r\n }, 50)\r\n })\r\n }\r\n\r\n const handleLoad = (e: Event) => {\r\n applyStyles()\r\n const detail = (e as CustomEvent).detail as { doc?: Document } | undefined\r\n if (detail?.doc) onContentLoad?.(detail.doc)\r\n }\r\n\r\n const handleRelocate = (e: Event) => {\r\n const detail = (e as CustomEvent).detail as ProgressInfo\r\n onProgress?.(detail)\r\n }\r\n\r\n viewer.addEventListener('load', handleLoad as EventListener)\r\n viewer.addEventListener('relocate', handleRelocate as EventListener)\r\n\r\n container.appendChild(viewer)\r\n\r\n const handle: EBookReaderHandle = {\r\n async open(file) {\r\n if (destroyed) return\r\n if (!file) return\r\n\r\n try {\r\n viewer.clearSearch?.()\r\n searchToken++\r\n\r\n await viewer.open?.(file)\r\n\r\n const nextToc = viewer.book?.toc ?? []\r\n toc = nextToc\r\n onToc?.(toc)\r\n\r\n await viewer.init?.({ showTextStart: true })\r\n applyStyles()\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n },\r\n destroy() {\r\n if (destroyed) return\r\n destroyed = true\r\n searchToken++\r\n viewer.removeEventListener('load', handleLoad)\r\n viewer.removeEventListener('relocate', handleRelocate as EventListener)\r\n container.innerHTML = ''\r\n },\r\n prevPage() {\r\n viewer.goLeft?.()\r\n },\r\n nextPage() {\r\n viewer.goRight?.()\r\n },\r\n prevSection() {\r\n viewer.renderer?.prevSection?.()\r\n },\r\n nextSection() {\r\n viewer.renderer?.nextSection?.()\r\n },\r\n goTo(target) {\r\n if (!target) return\r\n viewer.goTo?.(target)\r\n },\r\n goToFraction(fraction) {\r\n const safe = Math.min(1, Math.max(0, fraction))\r\n viewer.goToFraction?.(safe)\r\n },\r\n setDarkMode(nextDarkMode) {\r\n darkMode = nextDarkMode\r\n applyStyles()\r\n },\r\n setFontSize(nextFontSize) {\r\n const safe = Math.min(300, Math.max(50, nextFontSize))\r\n fontSize = safe\r\n applyStyles()\r\n },\r\n setLineHeight(nextLineHeight) {\n const safe = Math.min(3, Math.max(1, nextLineHeight))\n lineHeight = safe\n applyStyles()\n },\n setLetterSpacing(nextLetterSpacing) {\n const safe = Math.min(0.3, Math.max(0, nextLetterSpacing))\n letterSpacing = safe\n applyStyles()\n },\n async search(query, opts: SearchOptions = {}) {\r\n const normalized = query.trim()\r\n if (!normalized) {\r\n viewer.clearSearch?.()\r\n return []\r\n }\r\n\r\n const token = ++searchToken\r\n const results: SearchResult[] = []\r\n\r\n try {\r\n for await (const item of viewer.search?.({\r\n query: normalized,\r\n matchCase: Boolean(opts.matchCase),\r\n matchWholeWords: Boolean(opts.wholeWords),\r\n matchDiacritics: Boolean(opts.matchDiacritics),\r\n }) ?? []) {\r\n if (destroyed || token !== searchToken) return results\r\n\r\n if (item === 'done') {\r\n onSearchProgress?.({ done: true, progress: 1 })\r\n break\r\n }\r\n\r\n if (typeof item === 'object' && item && 'progress' in (item as any)) {\r\n const progress = (item as any).progress\r\n if (typeof progress === 'number') onSearchProgress?.({ progress })\r\n continue\r\n }\r\n\r\n const anyItem = item as any\r\n if (anyItem?.subitems?.length) {\r\n for (const sub of anyItem.subitems) {\r\n results.push({\r\n label: anyItem.label,\r\n cfi: sub?.cfi,\r\n excerpt: sub?.excerpt,\r\n title: sub?.title,\r\n })\r\n }\r\n } else if (anyItem?.cfi) {\r\n results.push({\r\n cfi: anyItem.cfi,\r\n excerpt: anyItem.excerpt,\r\n title: anyItem.title,\r\n })\r\n }\r\n }\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n\r\n return results\r\n },\r\n cancelSearch() {\r\n searchToken++\r\n },\r\n clearSearch() {\r\n viewer.clearSearch?.()\r\n },\r\n getToc() {\r\n return toc\r\n },\r\n }\r\n\r\n onReady?.(handle)\r\n return handle\r\n}\r\n"]}
|
package/dist/core.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as EBookReaderOptions, E as EBookReaderHandle } from './types-
|
|
2
|
-
export { P as ProgressInfo, S as SearchOptions, b as SearchResult, T as TocItem } from './types-
|
|
1
|
+
import { a as EBookReaderOptions, E as EBookReaderHandle } from './types-BQTZQhXd.cjs';
|
|
2
|
+
export { P as ProgressInfo, S as SearchOptions, b as SearchResult, T as TocItem } from './types-BQTZQhXd.cjs';
|
|
3
3
|
|
|
4
4
|
declare function createEBookReader(container: HTMLElement, options?: EBookReaderOptions): EBookReaderHandle;
|
|
5
5
|
|
package/dist/core.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as EBookReaderOptions, E as EBookReaderHandle } from './types-
|
|
2
|
-
export { P as ProgressInfo, S as SearchOptions, b as SearchResult, T as TocItem } from './types-
|
|
1
|
+
import { a as EBookReaderOptions, E as EBookReaderHandle } from './types-BQTZQhXd.js';
|
|
2
|
+
export { P as ProgressInfo, S as SearchOptions, b as SearchResult, T as TocItem } from './types-BQTZQhXd.js';
|
|
3
3
|
|
|
4
4
|
declare function createEBookReader(container: HTMLElement, options?: EBookReaderOptions): EBookReaderHandle;
|
|
5
5
|
|
package/dist/core.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import 'foliate-js/view.js';
|
|
2
2
|
|
|
3
3
|
// src/core/reader.ts
|
|
4
|
-
var getContentCSS = (fontSize, isDark, extraCSS) => `
|
|
4
|
+
var getContentCSS = (fontSize, isDark, lineHeight, letterSpacing, extraCSS) => `
|
|
5
5
|
@namespace epub "http://www.idpf.org/2007/ops";
|
|
6
6
|
html {
|
|
7
7
|
color-scheme: ${isDark ? "dark" : "light"} !important;
|
|
@@ -10,9 +10,11 @@ body {
|
|
|
10
10
|
background-color: transparent !important;
|
|
11
11
|
color: ${isDark ? "#e0e0e0" : "black"} !important;
|
|
12
12
|
font-size: ${fontSize}% !important;
|
|
13
|
+
line-height: ${lineHeight} !important;
|
|
14
|
+
letter-spacing: ${letterSpacing}em !important;
|
|
13
15
|
}
|
|
14
16
|
p {
|
|
15
|
-
line-height:
|
|
17
|
+
line-height: inherit !important;
|
|
16
18
|
margin-bottom: 1em;
|
|
17
19
|
}
|
|
18
20
|
a {
|
|
@@ -32,6 +34,8 @@ function createEBookReader(container, options = {}) {
|
|
|
32
34
|
const {
|
|
33
35
|
darkMode: initialDarkMode = false,
|
|
34
36
|
fontSize: initialFontSize = 100,
|
|
37
|
+
lineHeight: initialLineHeight = 1.6,
|
|
38
|
+
letterSpacing: initialLetterSpacing = 0,
|
|
35
39
|
extraContentCSS,
|
|
36
40
|
onReady,
|
|
37
41
|
onError,
|
|
@@ -44,6 +48,8 @@ function createEBookReader(container, options = {}) {
|
|
|
44
48
|
let toc = [];
|
|
45
49
|
let fontSize = initialFontSize;
|
|
46
50
|
let darkMode = initialDarkMode;
|
|
51
|
+
let lineHeight = initialLineHeight;
|
|
52
|
+
let letterSpacing = initialLetterSpacing;
|
|
47
53
|
let searchToken = 0;
|
|
48
54
|
container.innerHTML = "";
|
|
49
55
|
const viewer = document.createElement("foliate-view");
|
|
@@ -55,7 +61,7 @@ function createEBookReader(container, options = {}) {
|
|
|
55
61
|
const applyStyles = () => {
|
|
56
62
|
if (destroyed) return;
|
|
57
63
|
if (!viewer.renderer?.setStyles) return;
|
|
58
|
-
viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, extraContentCSS));
|
|
64
|
+
viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, lineHeight, letterSpacing, extraContentCSS));
|
|
59
65
|
requestAnimationFrame(() => {
|
|
60
66
|
setTimeout(() => {
|
|
61
67
|
if (destroyed) return;
|
|
@@ -131,6 +137,16 @@ function createEBookReader(container, options = {}) {
|
|
|
131
137
|
fontSize = safe;
|
|
132
138
|
applyStyles();
|
|
133
139
|
},
|
|
140
|
+
setLineHeight(nextLineHeight) {
|
|
141
|
+
const safe = Math.min(3, Math.max(1, nextLineHeight));
|
|
142
|
+
lineHeight = safe;
|
|
143
|
+
applyStyles();
|
|
144
|
+
},
|
|
145
|
+
setLetterSpacing(nextLetterSpacing) {
|
|
146
|
+
const safe = Math.min(0.3, Math.max(0, nextLetterSpacing));
|
|
147
|
+
letterSpacing = safe;
|
|
148
|
+
applyStyles();
|
|
149
|
+
},
|
|
134
150
|
async search(query, opts = {}) {
|
|
135
151
|
const normalized = query.trim();
|
|
136
152
|
if (!normalized) {
|
package/dist/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/reader.ts"],"names":[],"mappings":";;;AAsBA,IAAM,aAAA,GAAgB,CAAC,QAAA,EAAkB,MAAA,EAAiB,QAAA,KAAsB;AAAA;AAAA;AAAA,gBAAA,EAG9D,MAAA,GAAS,SAAS,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EAIhC,MAAA,GAAS,YAAY,OAAO,CAAA;AAAA,aAAA,EACxB,QAAQ,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EAOZ,MAAA,GAAS,YAAY,SAAS,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAAA,EAMrC,MAAA,GAAS,2CAA2C,EAAE;AAAA;AAAA,EAExD,YAAY,EAAE;AAAA,CAAA;AAGT,SAAS,iBAAA,CAAkB,SAAA,EAAwB,OAAA,GAA8B,EAAC,EAAsB;AAC7G,EAAA,IAAI,CAAC,SAAA,EAAW,MAAM,IAAI,MAAM,uBAAuB,CAAA;AACvD,EAAA,IAAI,CAAC,eAAe,GAAA,CAAI,cAAc,GAAG,MAAM,IAAI,MAAM,6BAA6B,CAAA;AAEtF,EAAA,MAAM;AAAA,IACJ,UAAU,eAAA,GAAkB,KAAA;AAAA,IAC5B,UAAU,eAAA,GAAkB,GAAA;AAAA,IAC5B,eAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,KAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACF,GAAI,OAAA;AAEJ,EAAA,IAAI,SAAA,GAAY,KAAA;AAChB,EAAA,IAAI,MAAiB,EAAC;AACtB,EAAA,IAAI,QAAA,GAAW,eAAA;AACf,EAAA,IAAI,QAAA,GAAW,eAAA;AACf,EAAA,IAAI,WAAA,GAAc,CAAA;AAElB,EAAA,SAAA,CAAU,SAAA,GAAY,EAAA;AAEtB,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,cAAc,CAAA;AACpD,EAAA,MAAA,CAAO,MAAM,OAAA,GAAU,OAAA;AACvB,EAAA,MAAA,CAAO,MAAM,KAAA,GAAQ,MAAA;AACrB,EAAA,MAAA,CAAO,MAAM,MAAA,GAAS,MAAA;AACtB,EAAA,MAAA,CAAO,YAAA,CAAa,UAAU,IAAI,CAAA;AAClC,EAAA,MAAA,CAAO,YAAA,CAAa,OAAO,MAAM,CAAA;AAEjC,EAAA,MAAM,cAAc,MAAM;AACxB,IAAA,IAAI,SAAA,EAAW;AACf,IAAA,IAAI,CAAC,MAAA,CAAO,QAAA,EAAU,SAAA,EAAW;AACjC,IAAA,MAAA,CAAO,SAAS,SAAA,CAAU,aAAA,CAAc,QAAA,EAAU,QAAA,EAAU,eAAe,CAAC,CAAA;AAC5E,IAAA,qBAAA,CAAsB,MAAM;AAC1B,MAAA,UAAA,CAAW,MAAM;AACf,QAAA,IAAI,SAAA,EAAW;AACf,QAAA,MAAA,CAAO,UAAU,MAAA,IAAS;AAC1B,QAAA,MAAA,CAAO,UAAU,MAAA,IAAS;AAAA,MAC5B,GAAG,EAAE,CAAA;AAAA,IACP,CAAC,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAM,UAAA,GAAa,CAAC,CAAA,KAAa;AAC/B,IAAA,WAAA,EAAY;AACZ,IAAA,MAAM,SAAU,CAAA,CAAkB,MAAA;AAClC,IAAA,IAAI,MAAA,EAAQ,GAAA,EAAK,aAAA,GAAgB,MAAA,CAAO,GAAG,CAAA;AAAA,EAC7C,CAAA;AAEA,EAAA,MAAM,cAAA,GAAiB,CAAC,CAAA,KAAa;AACnC,IAAA,MAAM,SAAU,CAAA,CAAkB,MAAA;AAClC,IAAA,UAAA,GAAa,MAAM,CAAA;AAAA,EACrB,CAAA;AAEA,EAAA,MAAA,CAAO,gBAAA,CAAiB,QAAQ,UAA2B,CAAA;AAC3D,EAAA,MAAA,CAAO,gBAAA,CAAiB,YAAY,cAA+B,CAAA;AAEnE,EAAA,SAAA,CAAU,YAAY,MAAM,CAAA;AAE5B,EAAA,MAAM,MAAA,GAA4B;AAAA,IAChC,MAAM,KAAK,IAAA,EAAM;AACf,MAAA,IAAI,SAAA,EAAW;AACf,MAAA,IAAI,CAAC,IAAA,EAAM;AAEX,MAAA,IAAI;AACF,QAAA,MAAA,CAAO,WAAA,IAAc;AACrB,QAAA,WAAA,EAAA;AAEA,QAAA,MAAM,MAAA,CAAO,OAAO,IAAI,CAAA;AAExB,QAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,EAAM,GAAA,IAAO,EAAC;AACrC,QAAA,GAAA,GAAM,OAAA;AACN,QAAA,KAAA,GAAQ,GAAG,CAAA;AAEX,QAAA,MAAM,MAAA,CAAO,IAAA,GAAO,EAAE,aAAA,EAAe,MAAM,CAAA;AAC3C,QAAA,WAAA,EAAY;AAAA,MACd,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,GAAU,KAAK,CAAA;AACf,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF,CAAA;AAAA,IACA,OAAA,GAAU;AACR,MAAA,IAAI,SAAA,EAAW;AACf,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA,WAAA,EAAA;AACA,MAAA,MAAA,CAAO,mBAAA,CAAoB,QAAQ,UAAU,CAAA;AAC7C,MAAA,MAAA,CAAO,mBAAA,CAAoB,YAAY,cAA+B,CAAA;AACtE,MAAA,SAAA,CAAU,SAAA,GAAY,EAAA;AAAA,IACxB,CAAA;AAAA,IACA,QAAA,GAAW;AACT,MAAA,MAAA,CAAO,MAAA,IAAS;AAAA,IAClB,CAAA;AAAA,IACA,QAAA,GAAW;AACT,MAAA,MAAA,CAAO,OAAA,IAAU;AAAA,IACnB,CAAA;AAAA,IACA,WAAA,GAAc;AACZ,MAAA,MAAA,CAAO,UAAU,WAAA,IAAc;AAAA,IACjC,CAAA;AAAA,IACA,WAAA,GAAc;AACZ,MAAA,MAAA,CAAO,UAAU,WAAA,IAAc;AAAA,IACjC,CAAA;AAAA,IACA,KAAK,MAAA,EAAQ;AACX,MAAA,IAAI,CAAC,MAAA,EAAQ;AACb,MAAA,MAAA,CAAO,OAAO,MAAM,CAAA;AAAA,IACtB,CAAA;AAAA,IACA,aAAa,QAAA,EAAU;AACrB,MAAA,MAAM,IAAA,GAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,CAAC,CAAA;AAC9C,MAAA,MAAA,CAAO,eAAe,IAAI,CAAA;AAAA,IAC5B,CAAA;AAAA,IACA,YAAY,YAAA,EAAc;AACxB,MAAA,QAAA,GAAW,YAAA;AACX,MAAA,WAAA,EAAY;AAAA,IACd,CAAA;AAAA,IACA,YAAY,YAAA,EAAc;AACxB,MAAA,MAAM,IAAA,GAAO,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,GAAA,CAAI,EAAA,EAAI,YAAY,CAAC,CAAA;AACrD,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,WAAA,EAAY;AAAA,IACd,CAAA;AAAA,IACA,MAAM,MAAA,CAAO,KAAA,EAAO,IAAA,GAAsB,EAAC,EAAG;AAC5C,MAAA,MAAM,UAAA,GAAa,MAAM,IAAA,EAAK;AAC9B,MAAA,IAAI,CAAC,UAAA,EAAY;AACf,QAAA,MAAA,CAAO,WAAA,IAAc;AACrB,QAAA,OAAO,EAAC;AAAA,MACV;AAEA,MAAA,MAAM,QAAQ,EAAE,WAAA;AAChB,MAAA,MAAM,UAA0B,EAAC;AAEjC,MAAA,IAAI;AACF,QAAA,WAAA,MAAiB,IAAA,IAAQ,OAAO,MAAA,GAAS;AAAA,UACvC,KAAA,EAAO,UAAA;AAAA,UACP,SAAA,EAAW,OAAA,CAAQ,IAAA,CAAK,SAAS,CAAA;AAAA,UACjC,eAAA,EAAiB,OAAA,CAAQ,IAAA,CAAK,UAAU,CAAA;AAAA,UACxC,eAAA,EAAiB,OAAA,CAAQ,IAAA,CAAK,eAAe;AAAA,SAC9C,CAAA,IAAK,EAAC,EAAG;AACR,UAAA,IAAI,SAAA,IAAa,KAAA,KAAU,WAAA,EAAa,OAAO,OAAA;AAE/C,UAAA,IAAI,SAAS,MAAA,EAAQ;AACnB,YAAA,gBAAA,GAAmB,EAAE,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,GAAG,CAAA;AAC9C,YAAA;AAAA,UACF;AAEA,UAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,IAAQ,cAAe,IAAA,EAAc;AACnE,YAAA,MAAM,WAAY,IAAA,CAAa,QAAA;AAC/B,YAAA,IAAI,OAAO,QAAA,KAAa,QAAA,EAAU,gBAAA,GAAmB,EAAE,UAAU,CAAA;AACjE,YAAA;AAAA,UACF;AAEA,UAAA,MAAM,OAAA,GAAU,IAAA;AAChB,UAAA,IAAI,OAAA,EAAS,UAAU,MAAA,EAAQ;AAC7B,YAAA,KAAA,MAAW,GAAA,IAAO,QAAQ,QAAA,EAAU;AAClC,cAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,gBACX,OAAO,OAAA,CAAQ,KAAA;AAAA,gBACf,KAAK,GAAA,EAAK,GAAA;AAAA,gBACV,SAAS,GAAA,EAAK,OAAA;AAAA,gBACd,OAAO,GAAA,EAAK;AAAA,eACb,CAAA;AAAA,YACH;AAAA,UACF,CAAA,MAAA,IAAW,SAAS,GAAA,EAAK;AACvB,YAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,cACX,KAAK,OAAA,CAAQ,GAAA;AAAA,cACb,SAAS,OAAA,CAAQ,OAAA;AAAA,cACjB,OAAO,OAAA,CAAQ;AAAA,aAChB,CAAA;AAAA,UACH;AAAA,QACF;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,GAAU,KAAK,CAAA;AACf,QAAA,MAAM,KAAA;AAAA,MACR;AAEA,MAAA,OAAO,OAAA;AAAA,IACT,CAAA;AAAA,IACA,YAAA,GAAe;AACb,MAAA,WAAA,EAAA;AAAA,IACF,CAAA;AAAA,IACA,WAAA,GAAc;AACZ,MAAA,MAAA,CAAO,WAAA,IAAc;AAAA,IACvB,CAAA;AAAA,IACA,MAAA,GAAS;AACP,MAAA,OAAO,GAAA;AAAA,IACT;AAAA,GACF;AAEA,EAAA,OAAA,GAAU,MAAM,CAAA;AAChB,EAAA,OAAO,MAAA;AACT","file":"core.js","sourcesContent":["import 'foliate-js/view.js'\r\nimport type { EBookReaderHandle, EBookReaderOptions, ProgressInfo, SearchOptions, SearchResult, TocItem } from './types.js'\r\n\r\ntype FoliateViewElement = HTMLElement & {\r\n book?: { toc?: TocItem[] }\r\n renderer?: {\r\n prevSection?: () => void\r\n nextSection?: () => void\r\n setStyles?: (css: string) => void\r\n render?: () => void\r\n expand?: () => void\r\n }\r\n open?: (file: File) => Promise<void>\r\n init?: (options?: unknown) => Promise<void>\r\n goLeft?: () => void\r\n goRight?: () => void\r\n goTo?: (target: string) => Promise<void> | void\r\n goToFraction?: (fraction: number) => Promise<void> | void\r\n search?: (options: unknown) => AsyncIterable<unknown>\r\n clearSearch?: () => void\r\n}\r\n\r\nconst getContentCSS = (fontSize: number, isDark: boolean, extraCSS?: string) => `\r\n@namespace epub \"http://www.idpf.org/2007/ops\";\r\nhtml {\r\n color-scheme: ${isDark ? 'dark' : 'light'} !important;\r\n}\r\nbody {\r\n background-color: transparent !important;\r\n color: ${isDark ? '#e0e0e0' : 'black'} !important;\r\n font-size: ${fontSize}% !important;\r\n}\r\np {\r\n line-height: 1.6;\r\n margin-bottom: 1em;\r\n}\r\na {\r\n color: ${isDark ? '#64b5f6' : '#2563eb'} !important;\r\n}\r\nimg {\r\n max-width: 100%;\r\n height: auto;\r\n object-fit: contain;\r\n ${isDark ? 'filter: brightness(0.8) contrast(1.2);' : ''}\r\n}\r\n${extraCSS ?? ''}\r\n`\r\n\r\nexport function createEBookReader(container: HTMLElement, options: EBookReaderOptions = {}): EBookReaderHandle {\r\n if (!container) throw new Error('container is required')\r\n if (!customElements.get('foliate-view')) throw new Error('foliate-view is not defined')\r\n\r\n const {\r\n darkMode: initialDarkMode = false,\r\n fontSize: initialFontSize = 100,\r\n extraContentCSS,\r\n onReady,\r\n onError,\r\n onProgress,\r\n onToc,\r\n onSearchProgress,\r\n onContentLoad,\r\n } = options\r\n\r\n let destroyed = false\r\n let toc: TocItem[] = []\r\n let fontSize = initialFontSize\r\n let darkMode = initialDarkMode\r\n let searchToken = 0\r\n\r\n container.innerHTML = ''\r\n\r\n const viewer = document.createElement('foliate-view') as FoliateViewElement\r\n viewer.style.display = 'block'\r\n viewer.style.width = '100%'\r\n viewer.style.height = '100%'\r\n viewer.setAttribute('margin', '48')\r\n viewer.setAttribute('gap', '0.07')\r\n\r\n const applyStyles = () => {\r\n if (destroyed) return\r\n if (!viewer.renderer?.setStyles) return\r\n viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, extraContentCSS))\r\n requestAnimationFrame(() => {\r\n setTimeout(() => {\r\n if (destroyed) return\r\n viewer.renderer?.render?.()\r\n viewer.renderer?.expand?.()\r\n }, 50)\r\n })\r\n }\r\n\r\n const handleLoad = (e: Event) => {\r\n applyStyles()\r\n const detail = (e as CustomEvent).detail as { doc?: Document } | undefined\r\n if (detail?.doc) onContentLoad?.(detail.doc)\r\n }\r\n\r\n const handleRelocate = (e: Event) => {\r\n const detail = (e as CustomEvent).detail as ProgressInfo\r\n onProgress?.(detail)\r\n }\r\n\r\n viewer.addEventListener('load', handleLoad as EventListener)\r\n viewer.addEventListener('relocate', handleRelocate as EventListener)\r\n\r\n container.appendChild(viewer)\r\n\r\n const handle: EBookReaderHandle = {\r\n async open(file) {\r\n if (destroyed) return\r\n if (!file) return\r\n\r\n try {\r\n viewer.clearSearch?.()\r\n searchToken++\r\n\r\n await viewer.open?.(file)\r\n\r\n const nextToc = viewer.book?.toc ?? []\r\n toc = nextToc\r\n onToc?.(toc)\r\n\r\n await viewer.init?.({ showTextStart: true })\r\n applyStyles()\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n },\r\n destroy() {\r\n if (destroyed) return\r\n destroyed = true\r\n searchToken++\r\n viewer.removeEventListener('load', handleLoad)\r\n viewer.removeEventListener('relocate', handleRelocate as EventListener)\r\n container.innerHTML = ''\r\n },\r\n prevPage() {\r\n viewer.goLeft?.()\r\n },\r\n nextPage() {\r\n viewer.goRight?.()\r\n },\r\n prevSection() {\r\n viewer.renderer?.prevSection?.()\r\n },\r\n nextSection() {\r\n viewer.renderer?.nextSection?.()\r\n },\r\n goTo(target) {\r\n if (!target) return\r\n viewer.goTo?.(target)\r\n },\r\n goToFraction(fraction) {\r\n const safe = Math.min(1, Math.max(0, fraction))\r\n viewer.goToFraction?.(safe)\r\n },\r\n setDarkMode(nextDarkMode) {\r\n darkMode = nextDarkMode\r\n applyStyles()\r\n },\r\n setFontSize(nextFontSize) {\r\n const safe = Math.min(300, Math.max(50, nextFontSize))\r\n fontSize = safe\r\n applyStyles()\r\n },\r\n async search(query, opts: SearchOptions = {}) {\r\n const normalized = query.trim()\r\n if (!normalized) {\r\n viewer.clearSearch?.()\r\n return []\r\n }\r\n\r\n const token = ++searchToken\r\n const results: SearchResult[] = []\r\n\r\n try {\r\n for await (const item of viewer.search?.({\r\n query: normalized,\r\n matchCase: Boolean(opts.matchCase),\r\n matchWholeWords: Boolean(opts.wholeWords),\r\n matchDiacritics: Boolean(opts.matchDiacritics),\r\n }) ?? []) {\r\n if (destroyed || token !== searchToken) return results\r\n\r\n if (item === 'done') {\r\n onSearchProgress?.({ done: true, progress: 1 })\r\n break\r\n }\r\n\r\n if (typeof item === 'object' && item && 'progress' in (item as any)) {\r\n const progress = (item as any).progress\r\n if (typeof progress === 'number') onSearchProgress?.({ progress })\r\n continue\r\n }\r\n\r\n const anyItem = item as any\r\n if (anyItem?.subitems?.length) {\r\n for (const sub of anyItem.subitems) {\r\n results.push({\r\n label: anyItem.label,\r\n cfi: sub?.cfi,\r\n excerpt: sub?.excerpt,\r\n title: sub?.title,\r\n })\r\n }\r\n } else if (anyItem?.cfi) {\r\n results.push({\r\n cfi: anyItem.cfi,\r\n excerpt: anyItem.excerpt,\r\n title: anyItem.title,\r\n })\r\n }\r\n }\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n\r\n return results\r\n },\r\n cancelSearch() {\r\n searchToken++\r\n },\r\n clearSearch() {\r\n viewer.clearSearch?.()\r\n },\r\n getToc() {\r\n return toc\r\n },\r\n }\r\n\r\n onReady?.(handle)\r\n return handle\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/reader.ts"],"names":[],"mappings":"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","file":"core.js","sourcesContent":["import 'foliate-js/view.js'\r\nimport type { EBookReaderHandle, EBookReaderOptions, ProgressInfo, SearchOptions, SearchResult, TocItem } from './types.js'\r\n\r\ntype FoliateViewElement = HTMLElement & {\r\n book?: { toc?: TocItem[] }\r\n renderer?: {\r\n prevSection?: () => void\r\n nextSection?: () => void\r\n setStyles?: (css: string) => void\r\n render?: () => void\r\n expand?: () => void\r\n }\r\n open?: (file: File) => Promise<void>\r\n init?: (options?: unknown) => Promise<void>\r\n goLeft?: () => void\r\n goRight?: () => void\r\n goTo?: (target: string) => Promise<void> | void\r\n goToFraction?: (fraction: number) => Promise<void> | void\r\n search?: (options: unknown) => AsyncIterable<unknown>\r\n clearSearch?: () => void\r\n}\r\n\r\nconst getContentCSS = (fontSize: number, isDark: boolean, lineHeight: number, letterSpacing: number, extraCSS?: string) => `\n@namespace epub \"http://www.idpf.org/2007/ops\";\r\nhtml {\r\n color-scheme: ${isDark ? 'dark' : 'light'} !important;\r\n}\r\nbody {\r\n background-color: transparent !important;\r\n color: ${isDark ? '#e0e0e0' : 'black'} !important;\r\n font-size: ${fontSize}% !important;\r\n line-height: ${lineHeight} !important;\n letter-spacing: ${letterSpacing}em !important;\n}\r\np {\r\n line-height: inherit !important;\n margin-bottom: 1em;\r\n}\r\na {\r\n color: ${isDark ? '#64b5f6' : '#2563eb'} !important;\r\n}\r\nimg {\r\n max-width: 100%;\r\n height: auto;\r\n object-fit: contain;\r\n ${isDark ? 'filter: brightness(0.8) contrast(1.2);' : ''}\r\n}\r\n${extraCSS ?? ''}\r\n`\r\n\r\nexport function createEBookReader(container: HTMLElement, options: EBookReaderOptions = {}): EBookReaderHandle {\r\n if (!container) throw new Error('container is required')\r\n if (!customElements.get('foliate-view')) throw new Error('foliate-view is not defined')\r\n\r\n const {\r\n darkMode: initialDarkMode = false,\r\n fontSize: initialFontSize = 100,\r\n lineHeight: initialLineHeight = 1.6,\n letterSpacing: initialLetterSpacing = 0,\n extraContentCSS,\r\n onReady,\r\n onError,\r\n onProgress,\r\n onToc,\r\n onSearchProgress,\r\n onContentLoad,\r\n } = options\r\n\r\n let destroyed = false\r\n let toc: TocItem[] = []\r\n let fontSize = initialFontSize\r\n let darkMode = initialDarkMode\r\n let lineHeight = initialLineHeight\n let letterSpacing = initialLetterSpacing\n let searchToken = 0\r\n\r\n container.innerHTML = ''\r\n\r\n const viewer = document.createElement('foliate-view') as FoliateViewElement\r\n viewer.style.display = 'block'\r\n viewer.style.width = '100%'\r\n viewer.style.height = '100%'\r\n viewer.setAttribute('margin', '48')\r\n viewer.setAttribute('gap', '0.07')\r\n\r\n const applyStyles = () => {\r\n if (destroyed) return\r\n if (!viewer.renderer?.setStyles) return\r\n viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, lineHeight, letterSpacing, extraContentCSS))\n requestAnimationFrame(() => {\r\n setTimeout(() => {\r\n if (destroyed) return\r\n viewer.renderer?.render?.()\r\n viewer.renderer?.expand?.()\r\n }, 50)\r\n })\r\n }\r\n\r\n const handleLoad = (e: Event) => {\r\n applyStyles()\r\n const detail = (e as CustomEvent).detail as { doc?: Document } | undefined\r\n if (detail?.doc) onContentLoad?.(detail.doc)\r\n }\r\n\r\n const handleRelocate = (e: Event) => {\r\n const detail = (e as CustomEvent).detail as ProgressInfo\r\n onProgress?.(detail)\r\n }\r\n\r\n viewer.addEventListener('load', handleLoad as EventListener)\r\n viewer.addEventListener('relocate', handleRelocate as EventListener)\r\n\r\n container.appendChild(viewer)\r\n\r\n const handle: EBookReaderHandle = {\r\n async open(file) {\r\n if (destroyed) return\r\n if (!file) return\r\n\r\n try {\r\n viewer.clearSearch?.()\r\n searchToken++\r\n\r\n await viewer.open?.(file)\r\n\r\n const nextToc = viewer.book?.toc ?? []\r\n toc = nextToc\r\n onToc?.(toc)\r\n\r\n await viewer.init?.({ showTextStart: true })\r\n applyStyles()\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n },\r\n destroy() {\r\n if (destroyed) return\r\n destroyed = true\r\n searchToken++\r\n viewer.removeEventListener('load', handleLoad)\r\n viewer.removeEventListener('relocate', handleRelocate as EventListener)\r\n container.innerHTML = ''\r\n },\r\n prevPage() {\r\n viewer.goLeft?.()\r\n },\r\n nextPage() {\r\n viewer.goRight?.()\r\n },\r\n prevSection() {\r\n viewer.renderer?.prevSection?.()\r\n },\r\n nextSection() {\r\n viewer.renderer?.nextSection?.()\r\n },\r\n goTo(target) {\r\n if (!target) return\r\n viewer.goTo?.(target)\r\n },\r\n goToFraction(fraction) {\r\n const safe = Math.min(1, Math.max(0, fraction))\r\n viewer.goToFraction?.(safe)\r\n },\r\n setDarkMode(nextDarkMode) {\r\n darkMode = nextDarkMode\r\n applyStyles()\r\n },\r\n setFontSize(nextFontSize) {\r\n const safe = Math.min(300, Math.max(50, nextFontSize))\r\n fontSize = safe\r\n applyStyles()\r\n },\r\n setLineHeight(nextLineHeight) {\n const safe = Math.min(3, Math.max(1, nextLineHeight))\n lineHeight = safe\n applyStyles()\n },\n setLetterSpacing(nextLetterSpacing) {\n const safe = Math.min(0.3, Math.max(0, nextLetterSpacing))\n letterSpacing = safe\n applyStyles()\n },\n async search(query, opts: SearchOptions = {}) {\r\n const normalized = query.trim()\r\n if (!normalized) {\r\n viewer.clearSearch?.()\r\n return []\r\n }\r\n\r\n const token = ++searchToken\r\n const results: SearchResult[] = []\r\n\r\n try {\r\n for await (const item of viewer.search?.({\r\n query: normalized,\r\n matchCase: Boolean(opts.matchCase),\r\n matchWholeWords: Boolean(opts.wholeWords),\r\n matchDiacritics: Boolean(opts.matchDiacritics),\r\n }) ?? []) {\r\n if (destroyed || token !== searchToken) return results\r\n\r\n if (item === 'done') {\r\n onSearchProgress?.({ done: true, progress: 1 })\r\n break\r\n }\r\n\r\n if (typeof item === 'object' && item && 'progress' in (item as any)) {\r\n const progress = (item as any).progress\r\n if (typeof progress === 'number') onSearchProgress?.({ progress })\r\n continue\r\n }\r\n\r\n const anyItem = item as any\r\n if (anyItem?.subitems?.length) {\r\n for (const sub of anyItem.subitems) {\r\n results.push({\r\n label: anyItem.label,\r\n cfi: sub?.cfi,\r\n excerpt: sub?.excerpt,\r\n title: sub?.title,\r\n })\r\n }\r\n } else if (anyItem?.cfi) {\r\n results.push({\r\n cfi: anyItem.cfi,\r\n excerpt: anyItem.excerpt,\r\n title: anyItem.title,\r\n })\r\n }\r\n }\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n\r\n return results\r\n },\r\n cancelSearch() {\r\n searchToken++\r\n },\r\n clearSearch() {\r\n viewer.clearSearch?.()\r\n },\r\n getToc() {\r\n return toc\r\n },\r\n }\r\n\r\n onReady?.(handle)\r\n return handle\r\n}\r\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require('foliate-js/view.js');
|
|
4
4
|
|
|
5
5
|
// src/core/reader.ts
|
|
6
|
-
var getContentCSS = (fontSize, isDark, extraCSS) => `
|
|
6
|
+
var getContentCSS = (fontSize, isDark, lineHeight, letterSpacing, extraCSS) => `
|
|
7
7
|
@namespace epub "http://www.idpf.org/2007/ops";
|
|
8
8
|
html {
|
|
9
9
|
color-scheme: ${isDark ? "dark" : "light"} !important;
|
|
@@ -12,9 +12,11 @@ body {
|
|
|
12
12
|
background-color: transparent !important;
|
|
13
13
|
color: ${isDark ? "#e0e0e0" : "black"} !important;
|
|
14
14
|
font-size: ${fontSize}% !important;
|
|
15
|
+
line-height: ${lineHeight} !important;
|
|
16
|
+
letter-spacing: ${letterSpacing}em !important;
|
|
15
17
|
}
|
|
16
18
|
p {
|
|
17
|
-
line-height:
|
|
19
|
+
line-height: inherit !important;
|
|
18
20
|
margin-bottom: 1em;
|
|
19
21
|
}
|
|
20
22
|
a {
|
|
@@ -34,6 +36,8 @@ function createEBookReader(container, options = {}) {
|
|
|
34
36
|
const {
|
|
35
37
|
darkMode: initialDarkMode = false,
|
|
36
38
|
fontSize: initialFontSize = 100,
|
|
39
|
+
lineHeight: initialLineHeight = 1.6,
|
|
40
|
+
letterSpacing: initialLetterSpacing = 0,
|
|
37
41
|
extraContentCSS,
|
|
38
42
|
onReady,
|
|
39
43
|
onError,
|
|
@@ -46,6 +50,8 @@ function createEBookReader(container, options = {}) {
|
|
|
46
50
|
let toc = [];
|
|
47
51
|
let fontSize = initialFontSize;
|
|
48
52
|
let darkMode = initialDarkMode;
|
|
53
|
+
let lineHeight = initialLineHeight;
|
|
54
|
+
let letterSpacing = initialLetterSpacing;
|
|
49
55
|
let searchToken = 0;
|
|
50
56
|
container.innerHTML = "";
|
|
51
57
|
const viewer = document.createElement("foliate-view");
|
|
@@ -57,7 +63,7 @@ function createEBookReader(container, options = {}) {
|
|
|
57
63
|
const applyStyles = () => {
|
|
58
64
|
if (destroyed) return;
|
|
59
65
|
if (!viewer.renderer?.setStyles) return;
|
|
60
|
-
viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, extraContentCSS));
|
|
66
|
+
viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, lineHeight, letterSpacing, extraContentCSS));
|
|
61
67
|
requestAnimationFrame(() => {
|
|
62
68
|
setTimeout(() => {
|
|
63
69
|
if (destroyed) return;
|
|
@@ -133,6 +139,16 @@ function createEBookReader(container, options = {}) {
|
|
|
133
139
|
fontSize = safe;
|
|
134
140
|
applyStyles();
|
|
135
141
|
},
|
|
142
|
+
setLineHeight(nextLineHeight) {
|
|
143
|
+
const safe = Math.min(3, Math.max(1, nextLineHeight));
|
|
144
|
+
lineHeight = safe;
|
|
145
|
+
applyStyles();
|
|
146
|
+
},
|
|
147
|
+
setLetterSpacing(nextLetterSpacing) {
|
|
148
|
+
const safe = Math.min(0.3, Math.max(0, nextLetterSpacing));
|
|
149
|
+
letterSpacing = safe;
|
|
150
|
+
applyStyles();
|
|
151
|
+
},
|
|
136
152
|
async search(query, opts = {}) {
|
|
137
153
|
const normalized = query.trim();
|
|
138
154
|
if (!normalized) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/reader.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import 'foliate-js/view.js'\r\nimport type { EBookReaderHandle, EBookReaderOptions, ProgressInfo, SearchOptions, SearchResult, TocItem } from './types.js'\r\n\r\ntype FoliateViewElement = HTMLElement & {\r\n book?: { toc?: TocItem[] }\r\n renderer?: {\r\n prevSection?: () => void\r\n nextSection?: () => void\r\n setStyles?: (css: string) => void\r\n render?: () => void\r\n expand?: () => void\r\n }\r\n open?: (file: File) => Promise<void>\r\n init?: (options?: unknown) => Promise<void>\r\n goLeft?: () => void\r\n goRight?: () => void\r\n goTo?: (target: string) => Promise<void> | void\r\n goToFraction?: (fraction: number) => Promise<void> | void\r\n search?: (options: unknown) => AsyncIterable<unknown>\r\n clearSearch?: () => void\r\n}\r\n\r\nconst getContentCSS = (fontSize: number, isDark: boolean, extraCSS?: string) => `\r\n@namespace epub \"http://www.idpf.org/2007/ops\";\r\nhtml {\r\n color-scheme: ${isDark ? 'dark' : 'light'} !important;\r\n}\r\nbody {\r\n background-color: transparent !important;\r\n color: ${isDark ? '#e0e0e0' : 'black'} !important;\r\n font-size: ${fontSize}% !important;\r\n}\r\np {\r\n line-height: 1.6;\r\n margin-bottom: 1em;\r\n}\r\na {\r\n color: ${isDark ? '#64b5f6' : '#2563eb'} !important;\r\n}\r\nimg {\r\n max-width: 100%;\r\n height: auto;\r\n object-fit: contain;\r\n ${isDark ? 'filter: brightness(0.8) contrast(1.2);' : ''}\r\n}\r\n${extraCSS ?? ''}\r\n`\r\n\r\nexport function createEBookReader(container: HTMLElement, options: EBookReaderOptions = {}): EBookReaderHandle {\r\n if (!container) throw new Error('container is required')\r\n if (!customElements.get('foliate-view')) throw new Error('foliate-view is not defined')\r\n\r\n const {\r\n darkMode: initialDarkMode = false,\r\n fontSize: initialFontSize = 100,\r\n extraContentCSS,\r\n onReady,\r\n onError,\r\n onProgress,\r\n onToc,\r\n onSearchProgress,\r\n onContentLoad,\r\n } = options\r\n\r\n let destroyed = false\r\n let toc: TocItem[] = []\r\n let fontSize = initialFontSize\r\n let darkMode = initialDarkMode\r\n let searchToken = 0\r\n\r\n container.innerHTML = ''\r\n\r\n const viewer = document.createElement('foliate-view') as FoliateViewElement\r\n viewer.style.display = 'block'\r\n viewer.style.width = '100%'\r\n viewer.style.height = '100%'\r\n viewer.setAttribute('margin', '48')\r\n viewer.setAttribute('gap', '0.07')\r\n\r\n const applyStyles = () => {\r\n if (destroyed) return\r\n if (!viewer.renderer?.setStyles) return\r\n viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, extraContentCSS))\r\n requestAnimationFrame(() => {\r\n setTimeout(() => {\r\n if (destroyed) return\r\n viewer.renderer?.render?.()\r\n viewer.renderer?.expand?.()\r\n }, 50)\r\n })\r\n }\r\n\r\n const handleLoad = (e: Event) => {\r\n applyStyles()\r\n const detail = (e as CustomEvent).detail as { doc?: Document } | undefined\r\n if (detail?.doc) onContentLoad?.(detail.doc)\r\n }\r\n\r\n const handleRelocate = (e: Event) => {\r\n const detail = (e as CustomEvent).detail as ProgressInfo\r\n onProgress?.(detail)\r\n }\r\n\r\n viewer.addEventListener('load', handleLoad as EventListener)\r\n viewer.addEventListener('relocate', handleRelocate as EventListener)\r\n\r\n container.appendChild(viewer)\r\n\r\n const handle: EBookReaderHandle = {\r\n async open(file) {\r\n if (destroyed) return\r\n if (!file) return\r\n\r\n try {\r\n viewer.clearSearch?.()\r\n searchToken++\r\n\r\n await viewer.open?.(file)\r\n\r\n const nextToc = viewer.book?.toc ?? []\r\n toc = nextToc\r\n onToc?.(toc)\r\n\r\n await viewer.init?.({ showTextStart: true })\r\n applyStyles()\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n },\r\n destroy() {\r\n if (destroyed) return\r\n destroyed = true\r\n searchToken++\r\n viewer.removeEventListener('load', handleLoad)\r\n viewer.removeEventListener('relocate', handleRelocate as EventListener)\r\n container.innerHTML = ''\r\n },\r\n prevPage() {\r\n viewer.goLeft?.()\r\n },\r\n nextPage() {\r\n viewer.goRight?.()\r\n },\r\n prevSection() {\r\n viewer.renderer?.prevSection?.()\r\n },\r\n nextSection() {\r\n viewer.renderer?.nextSection?.()\r\n },\r\n goTo(target) {\r\n if (!target) return\r\n viewer.goTo?.(target)\r\n },\r\n goToFraction(fraction) {\r\n const safe = Math.min(1, Math.max(0, fraction))\r\n viewer.goToFraction?.(safe)\r\n },\r\n setDarkMode(nextDarkMode) {\r\n darkMode = nextDarkMode\r\n applyStyles()\r\n },\r\n setFontSize(nextFontSize) {\r\n const safe = Math.min(300, Math.max(50, nextFontSize))\r\n fontSize = safe\r\n applyStyles()\r\n },\r\n async search(query, opts: SearchOptions = {}) {\r\n const normalized = query.trim()\r\n if (!normalized) {\r\n viewer.clearSearch?.()\r\n return []\r\n }\r\n\r\n const token = ++searchToken\r\n const results: SearchResult[] = []\r\n\r\n try {\r\n for await (const item of viewer.search?.({\r\n query: normalized,\r\n matchCase: Boolean(opts.matchCase),\r\n matchWholeWords: Boolean(opts.wholeWords),\r\n matchDiacritics: Boolean(opts.matchDiacritics),\r\n }) ?? []) {\r\n if (destroyed || token !== searchToken) return results\r\n\r\n if (item === 'done') {\r\n onSearchProgress?.({ done: true, progress: 1 })\r\n break\r\n }\r\n\r\n if (typeof item === 'object' && item && 'progress' in (item as any)) {\r\n const progress = (item as any).progress\r\n if (typeof progress === 'number') onSearchProgress?.({ progress })\r\n continue\r\n }\r\n\r\n const anyItem = item as any\r\n if (anyItem?.subitems?.length) {\r\n for (const sub of anyItem.subitems) {\r\n results.push({\r\n label: anyItem.label,\r\n cfi: sub?.cfi,\r\n excerpt: sub?.excerpt,\r\n title: sub?.title,\r\n })\r\n }\r\n } else if (anyItem?.cfi) {\r\n results.push({\r\n cfi: anyItem.cfi,\r\n excerpt: anyItem.excerpt,\r\n title: anyItem.title,\r\n })\r\n }\r\n }\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n\r\n return results\r\n },\r\n cancelSearch() {\r\n searchToken++\r\n },\r\n clearSearch() {\r\n viewer.clearSearch?.()\r\n },\r\n getToc() {\r\n return toc\r\n },\r\n }\r\n\r\n onReady?.(handle)\r\n return handle\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/reader.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import 'foliate-js/view.js'\r\nimport type { EBookReaderHandle, EBookReaderOptions, ProgressInfo, SearchOptions, SearchResult, TocItem } from './types.js'\r\n\r\ntype FoliateViewElement = HTMLElement & {\r\n book?: { toc?: TocItem[] }\r\n renderer?: {\r\n prevSection?: () => void\r\n nextSection?: () => void\r\n setStyles?: (css: string) => void\r\n render?: () => void\r\n expand?: () => void\r\n }\r\n open?: (file: File) => Promise<void>\r\n init?: (options?: unknown) => Promise<void>\r\n goLeft?: () => void\r\n goRight?: () => void\r\n goTo?: (target: string) => Promise<void> | void\r\n goToFraction?: (fraction: number) => Promise<void> | void\r\n search?: (options: unknown) => AsyncIterable<unknown>\r\n clearSearch?: () => void\r\n}\r\n\r\nconst getContentCSS = (fontSize: number, isDark: boolean, lineHeight: number, letterSpacing: number, extraCSS?: string) => `\n@namespace epub \"http://www.idpf.org/2007/ops\";\r\nhtml {\r\n color-scheme: ${isDark ? 'dark' : 'light'} !important;\r\n}\r\nbody {\r\n background-color: transparent !important;\r\n color: ${isDark ? '#e0e0e0' : 'black'} !important;\r\n font-size: ${fontSize}% !important;\r\n line-height: ${lineHeight} !important;\n letter-spacing: ${letterSpacing}em !important;\n}\r\np {\r\n line-height: inherit !important;\n margin-bottom: 1em;\r\n}\r\na {\r\n color: ${isDark ? '#64b5f6' : '#2563eb'} !important;\r\n}\r\nimg {\r\n max-width: 100%;\r\n height: auto;\r\n object-fit: contain;\r\n ${isDark ? 'filter: brightness(0.8) contrast(1.2);' : ''}\r\n}\r\n${extraCSS ?? ''}\r\n`\r\n\r\nexport function createEBookReader(container: HTMLElement, options: EBookReaderOptions = {}): EBookReaderHandle {\r\n if (!container) throw new Error('container is required')\r\n if (!customElements.get('foliate-view')) throw new Error('foliate-view is not defined')\r\n\r\n const {\r\n darkMode: initialDarkMode = false,\r\n fontSize: initialFontSize = 100,\r\n lineHeight: initialLineHeight = 1.6,\n letterSpacing: initialLetterSpacing = 0,\n extraContentCSS,\r\n onReady,\r\n onError,\r\n onProgress,\r\n onToc,\r\n onSearchProgress,\r\n onContentLoad,\r\n } = options\r\n\r\n let destroyed = false\r\n let toc: TocItem[] = []\r\n let fontSize = initialFontSize\r\n let darkMode = initialDarkMode\r\n let lineHeight = initialLineHeight\n let letterSpacing = initialLetterSpacing\n let searchToken = 0\r\n\r\n container.innerHTML = ''\r\n\r\n const viewer = document.createElement('foliate-view') as FoliateViewElement\r\n viewer.style.display = 'block'\r\n viewer.style.width = '100%'\r\n viewer.style.height = '100%'\r\n viewer.setAttribute('margin', '48')\r\n viewer.setAttribute('gap', '0.07')\r\n\r\n const applyStyles = () => {\r\n if (destroyed) return\r\n if (!viewer.renderer?.setStyles) return\r\n viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, lineHeight, letterSpacing, extraContentCSS))\n requestAnimationFrame(() => {\r\n setTimeout(() => {\r\n if (destroyed) return\r\n viewer.renderer?.render?.()\r\n viewer.renderer?.expand?.()\r\n }, 50)\r\n })\r\n }\r\n\r\n const handleLoad = (e: Event) => {\r\n applyStyles()\r\n const detail = (e as CustomEvent).detail as { doc?: Document } | undefined\r\n if (detail?.doc) onContentLoad?.(detail.doc)\r\n }\r\n\r\n const handleRelocate = (e: Event) => {\r\n const detail = (e as CustomEvent).detail as ProgressInfo\r\n onProgress?.(detail)\r\n }\r\n\r\n viewer.addEventListener('load', handleLoad as EventListener)\r\n viewer.addEventListener('relocate', handleRelocate as EventListener)\r\n\r\n container.appendChild(viewer)\r\n\r\n const handle: EBookReaderHandle = {\r\n async open(file) {\r\n if (destroyed) return\r\n if (!file) return\r\n\r\n try {\r\n viewer.clearSearch?.()\r\n searchToken++\r\n\r\n await viewer.open?.(file)\r\n\r\n const nextToc = viewer.book?.toc ?? []\r\n toc = nextToc\r\n onToc?.(toc)\r\n\r\n await viewer.init?.({ showTextStart: true })\r\n applyStyles()\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n },\r\n destroy() {\r\n if (destroyed) return\r\n destroyed = true\r\n searchToken++\r\n viewer.removeEventListener('load', handleLoad)\r\n viewer.removeEventListener('relocate', handleRelocate as EventListener)\r\n container.innerHTML = ''\r\n },\r\n prevPage() {\r\n viewer.goLeft?.()\r\n },\r\n nextPage() {\r\n viewer.goRight?.()\r\n },\r\n prevSection() {\r\n viewer.renderer?.prevSection?.()\r\n },\r\n nextSection() {\r\n viewer.renderer?.nextSection?.()\r\n },\r\n goTo(target) {\r\n if (!target) return\r\n viewer.goTo?.(target)\r\n },\r\n goToFraction(fraction) {\r\n const safe = Math.min(1, Math.max(0, fraction))\r\n viewer.goToFraction?.(safe)\r\n },\r\n setDarkMode(nextDarkMode) {\r\n darkMode = nextDarkMode\r\n applyStyles()\r\n },\r\n setFontSize(nextFontSize) {\r\n const safe = Math.min(300, Math.max(50, nextFontSize))\r\n fontSize = safe\r\n applyStyles()\r\n },\r\n setLineHeight(nextLineHeight) {\n const safe = Math.min(3, Math.max(1, nextLineHeight))\n lineHeight = safe\n applyStyles()\n },\n setLetterSpacing(nextLetterSpacing) {\n const safe = Math.min(0.3, Math.max(0, nextLetterSpacing))\n letterSpacing = safe\n applyStyles()\n },\n async search(query, opts: SearchOptions = {}) {\r\n const normalized = query.trim()\r\n if (!normalized) {\r\n viewer.clearSearch?.()\r\n return []\r\n }\r\n\r\n const token = ++searchToken\r\n const results: SearchResult[] = []\r\n\r\n try {\r\n for await (const item of viewer.search?.({\r\n query: normalized,\r\n matchCase: Boolean(opts.matchCase),\r\n matchWholeWords: Boolean(opts.wholeWords),\r\n matchDiacritics: Boolean(opts.matchDiacritics),\r\n }) ?? []) {\r\n if (destroyed || token !== searchToken) return results\r\n\r\n if (item === 'done') {\r\n onSearchProgress?.({ done: true, progress: 1 })\r\n break\r\n }\r\n\r\n if (typeof item === 'object' && item && 'progress' in (item as any)) {\r\n const progress = (item as any).progress\r\n if (typeof progress === 'number') onSearchProgress?.({ progress })\r\n continue\r\n }\r\n\r\n const anyItem = item as any\r\n if (anyItem?.subitems?.length) {\r\n for (const sub of anyItem.subitems) {\r\n results.push({\r\n label: anyItem.label,\r\n cfi: sub?.cfi,\r\n excerpt: sub?.excerpt,\r\n title: sub?.title,\r\n })\r\n }\r\n } else if (anyItem?.cfi) {\r\n results.push({\r\n cfi: anyItem.cfi,\r\n excerpt: anyItem.excerpt,\r\n title: anyItem.title,\r\n })\r\n }\r\n }\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n\r\n return results\r\n },\r\n cancelSearch() {\r\n searchToken++\r\n },\r\n clearSearch() {\r\n viewer.clearSearch?.()\r\n },\r\n getToc() {\r\n return toc\r\n },\r\n }\r\n\r\n onReady?.(handle)\r\n return handle\r\n}\r\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { E as EBookReaderHandle, a as EBookReaderOptions, P as ProgressInfo, S as SearchOptions, b as SearchResult, T as TocItem } from './types-
|
|
1
|
+
export { E as EBookReaderHandle, a as EBookReaderOptions, P as ProgressInfo, S as SearchOptions, b as SearchResult, T as TocItem } from './types-BQTZQhXd.cjs';
|
|
2
2
|
export { createEBookReader } from './core.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { E as EBookReaderHandle, a as EBookReaderOptions, P as ProgressInfo, S as SearchOptions, b as SearchResult, T as TocItem } from './types-
|
|
1
|
+
export { E as EBookReaderHandle, a as EBookReaderOptions, P as ProgressInfo, S as SearchOptions, b as SearchResult, T as TocItem } from './types-BQTZQhXd.js';
|
|
2
2
|
export { createEBookReader } from './core.js';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import 'foliate-js/view.js';
|
|
2
2
|
|
|
3
3
|
// src/core/reader.ts
|
|
4
|
-
var getContentCSS = (fontSize, isDark, extraCSS) => `
|
|
4
|
+
var getContentCSS = (fontSize, isDark, lineHeight, letterSpacing, extraCSS) => `
|
|
5
5
|
@namespace epub "http://www.idpf.org/2007/ops";
|
|
6
6
|
html {
|
|
7
7
|
color-scheme: ${isDark ? "dark" : "light"} !important;
|
|
@@ -10,9 +10,11 @@ body {
|
|
|
10
10
|
background-color: transparent !important;
|
|
11
11
|
color: ${isDark ? "#e0e0e0" : "black"} !important;
|
|
12
12
|
font-size: ${fontSize}% !important;
|
|
13
|
+
line-height: ${lineHeight} !important;
|
|
14
|
+
letter-spacing: ${letterSpacing}em !important;
|
|
13
15
|
}
|
|
14
16
|
p {
|
|
15
|
-
line-height:
|
|
17
|
+
line-height: inherit !important;
|
|
16
18
|
margin-bottom: 1em;
|
|
17
19
|
}
|
|
18
20
|
a {
|
|
@@ -32,6 +34,8 @@ function createEBookReader(container, options = {}) {
|
|
|
32
34
|
const {
|
|
33
35
|
darkMode: initialDarkMode = false,
|
|
34
36
|
fontSize: initialFontSize = 100,
|
|
37
|
+
lineHeight: initialLineHeight = 1.6,
|
|
38
|
+
letterSpacing: initialLetterSpacing = 0,
|
|
35
39
|
extraContentCSS,
|
|
36
40
|
onReady,
|
|
37
41
|
onError,
|
|
@@ -44,6 +48,8 @@ function createEBookReader(container, options = {}) {
|
|
|
44
48
|
let toc = [];
|
|
45
49
|
let fontSize = initialFontSize;
|
|
46
50
|
let darkMode = initialDarkMode;
|
|
51
|
+
let lineHeight = initialLineHeight;
|
|
52
|
+
let letterSpacing = initialLetterSpacing;
|
|
47
53
|
let searchToken = 0;
|
|
48
54
|
container.innerHTML = "";
|
|
49
55
|
const viewer = document.createElement("foliate-view");
|
|
@@ -55,7 +61,7 @@ function createEBookReader(container, options = {}) {
|
|
|
55
61
|
const applyStyles = () => {
|
|
56
62
|
if (destroyed) return;
|
|
57
63
|
if (!viewer.renderer?.setStyles) return;
|
|
58
|
-
viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, extraContentCSS));
|
|
64
|
+
viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, lineHeight, letterSpacing, extraContentCSS));
|
|
59
65
|
requestAnimationFrame(() => {
|
|
60
66
|
setTimeout(() => {
|
|
61
67
|
if (destroyed) return;
|
|
@@ -131,6 +137,16 @@ function createEBookReader(container, options = {}) {
|
|
|
131
137
|
fontSize = safe;
|
|
132
138
|
applyStyles();
|
|
133
139
|
},
|
|
140
|
+
setLineHeight(nextLineHeight) {
|
|
141
|
+
const safe = Math.min(3, Math.max(1, nextLineHeight));
|
|
142
|
+
lineHeight = safe;
|
|
143
|
+
applyStyles();
|
|
144
|
+
},
|
|
145
|
+
setLetterSpacing(nextLetterSpacing) {
|
|
146
|
+
const safe = Math.min(0.3, Math.max(0, nextLetterSpacing));
|
|
147
|
+
letterSpacing = safe;
|
|
148
|
+
applyStyles();
|
|
149
|
+
},
|
|
134
150
|
async search(query, opts = {}) {
|
|
135
151
|
const normalized = query.trim();
|
|
136
152
|
if (!normalized) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/reader.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import 'foliate-js/view.js'\r\nimport type { EBookReaderHandle, EBookReaderOptions, ProgressInfo, SearchOptions, SearchResult, TocItem } from './types.js'\r\n\r\ntype FoliateViewElement = HTMLElement & {\r\n book?: { toc?: TocItem[] }\r\n renderer?: {\r\n prevSection?: () => void\r\n nextSection?: () => void\r\n setStyles?: (css: string) => void\r\n render?: () => void\r\n expand?: () => void\r\n }\r\n open?: (file: File) => Promise<void>\r\n init?: (options?: unknown) => Promise<void>\r\n goLeft?: () => void\r\n goRight?: () => void\r\n goTo?: (target: string) => Promise<void> | void\r\n goToFraction?: (fraction: number) => Promise<void> | void\r\n search?: (options: unknown) => AsyncIterable<unknown>\r\n clearSearch?: () => void\r\n}\r\n\r\nconst getContentCSS = (fontSize: number, isDark: boolean, extraCSS?: string) => `\r\n@namespace epub \"http://www.idpf.org/2007/ops\";\r\nhtml {\r\n color-scheme: ${isDark ? 'dark' : 'light'} !important;\r\n}\r\nbody {\r\n background-color: transparent !important;\r\n color: ${isDark ? '#e0e0e0' : 'black'} !important;\r\n font-size: ${fontSize}% !important;\r\n}\r\np {\r\n line-height: 1.6;\r\n margin-bottom: 1em;\r\n}\r\na {\r\n color: ${isDark ? '#64b5f6' : '#2563eb'} !important;\r\n}\r\nimg {\r\n max-width: 100%;\r\n height: auto;\r\n object-fit: contain;\r\n ${isDark ? 'filter: brightness(0.8) contrast(1.2);' : ''}\r\n}\r\n${extraCSS ?? ''}\r\n`\r\n\r\nexport function createEBookReader(container: HTMLElement, options: EBookReaderOptions = {}): EBookReaderHandle {\r\n if (!container) throw new Error('container is required')\r\n if (!customElements.get('foliate-view')) throw new Error('foliate-view is not defined')\r\n\r\n const {\r\n darkMode: initialDarkMode = false,\r\n fontSize: initialFontSize = 100,\r\n extraContentCSS,\r\n onReady,\r\n onError,\r\n onProgress,\r\n onToc,\r\n onSearchProgress,\r\n onContentLoad,\r\n } = options\r\n\r\n let destroyed = false\r\n let toc: TocItem[] = []\r\n let fontSize = initialFontSize\r\n let darkMode = initialDarkMode\r\n let searchToken = 0\r\n\r\n container.innerHTML = ''\r\n\r\n const viewer = document.createElement('foliate-view') as FoliateViewElement\r\n viewer.style.display = 'block'\r\n viewer.style.width = '100%'\r\n viewer.style.height = '100%'\r\n viewer.setAttribute('margin', '48')\r\n viewer.setAttribute('gap', '0.07')\r\n\r\n const applyStyles = () => {\r\n if (destroyed) return\r\n if (!viewer.renderer?.setStyles) return\r\n viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, extraContentCSS))\r\n requestAnimationFrame(() => {\r\n setTimeout(() => {\r\n if (destroyed) return\r\n viewer.renderer?.render?.()\r\n viewer.renderer?.expand?.()\r\n }, 50)\r\n })\r\n }\r\n\r\n const handleLoad = (e: Event) => {\r\n applyStyles()\r\n const detail = (e as CustomEvent).detail as { doc?: Document } | undefined\r\n if (detail?.doc) onContentLoad?.(detail.doc)\r\n }\r\n\r\n const handleRelocate = (e: Event) => {\r\n const detail = (e as CustomEvent).detail as ProgressInfo\r\n onProgress?.(detail)\r\n }\r\n\r\n viewer.addEventListener('load', handleLoad as EventListener)\r\n viewer.addEventListener('relocate', handleRelocate as EventListener)\r\n\r\n container.appendChild(viewer)\r\n\r\n const handle: EBookReaderHandle = {\r\n async open(file) {\r\n if (destroyed) return\r\n if (!file) return\r\n\r\n try {\r\n viewer.clearSearch?.()\r\n searchToken++\r\n\r\n await viewer.open?.(file)\r\n\r\n const nextToc = viewer.book?.toc ?? []\r\n toc = nextToc\r\n onToc?.(toc)\r\n\r\n await viewer.init?.({ showTextStart: true })\r\n applyStyles()\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n },\r\n destroy() {\r\n if (destroyed) return\r\n destroyed = true\r\n searchToken++\r\n viewer.removeEventListener('load', handleLoad)\r\n viewer.removeEventListener('relocate', handleRelocate as EventListener)\r\n container.innerHTML = ''\r\n },\r\n prevPage() {\r\n viewer.goLeft?.()\r\n },\r\n nextPage() {\r\n viewer.goRight?.()\r\n },\r\n prevSection() {\r\n viewer.renderer?.prevSection?.()\r\n },\r\n nextSection() {\r\n viewer.renderer?.nextSection?.()\r\n },\r\n goTo(target) {\r\n if (!target) return\r\n viewer.goTo?.(target)\r\n },\r\n goToFraction(fraction) {\r\n const safe = Math.min(1, Math.max(0, fraction))\r\n viewer.goToFraction?.(safe)\r\n },\r\n setDarkMode(nextDarkMode) {\r\n darkMode = nextDarkMode\r\n applyStyles()\r\n },\r\n setFontSize(nextFontSize) {\r\n const safe = Math.min(300, Math.max(50, nextFontSize))\r\n fontSize = safe\r\n applyStyles()\r\n },\r\n async search(query, opts: SearchOptions = {}) {\r\n const normalized = query.trim()\r\n if (!normalized) {\r\n viewer.clearSearch?.()\r\n return []\r\n }\r\n\r\n const token = ++searchToken\r\n const results: SearchResult[] = []\r\n\r\n try {\r\n for await (const item of viewer.search?.({\r\n query: normalized,\r\n matchCase: Boolean(opts.matchCase),\r\n matchWholeWords: Boolean(opts.wholeWords),\r\n matchDiacritics: Boolean(opts.matchDiacritics),\r\n }) ?? []) {\r\n if (destroyed || token !== searchToken) return results\r\n\r\n if (item === 'done') {\r\n onSearchProgress?.({ done: true, progress: 1 })\r\n break\r\n }\r\n\r\n if (typeof item === 'object' && item && 'progress' in (item as any)) {\r\n const progress = (item as any).progress\r\n if (typeof progress === 'number') onSearchProgress?.({ progress })\r\n continue\r\n }\r\n\r\n const anyItem = item as any\r\n if (anyItem?.subitems?.length) {\r\n for (const sub of anyItem.subitems) {\r\n results.push({\r\n label: anyItem.label,\r\n cfi: sub?.cfi,\r\n excerpt: sub?.excerpt,\r\n title: sub?.title,\r\n })\r\n }\r\n } else if (anyItem?.cfi) {\r\n results.push({\r\n cfi: anyItem.cfi,\r\n excerpt: anyItem.excerpt,\r\n title: anyItem.title,\r\n })\r\n }\r\n }\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n\r\n return results\r\n },\r\n cancelSearch() {\r\n searchToken++\r\n },\r\n clearSearch() {\r\n viewer.clearSearch?.()\r\n },\r\n getToc() {\r\n return toc\r\n },\r\n }\r\n\r\n onReady?.(handle)\r\n return handle\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/reader.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import 'foliate-js/view.js'\r\nimport type { EBookReaderHandle, EBookReaderOptions, ProgressInfo, SearchOptions, SearchResult, TocItem } from './types.js'\r\n\r\ntype FoliateViewElement = HTMLElement & {\r\n book?: { toc?: TocItem[] }\r\n renderer?: {\r\n prevSection?: () => void\r\n nextSection?: () => void\r\n setStyles?: (css: string) => void\r\n render?: () => void\r\n expand?: () => void\r\n }\r\n open?: (file: File) => Promise<void>\r\n init?: (options?: unknown) => Promise<void>\r\n goLeft?: () => void\r\n goRight?: () => void\r\n goTo?: (target: string) => Promise<void> | void\r\n goToFraction?: (fraction: number) => Promise<void> | void\r\n search?: (options: unknown) => AsyncIterable<unknown>\r\n clearSearch?: () => void\r\n}\r\n\r\nconst getContentCSS = (fontSize: number, isDark: boolean, lineHeight: number, letterSpacing: number, extraCSS?: string) => `\n@namespace epub \"http://www.idpf.org/2007/ops\";\r\nhtml {\r\n color-scheme: ${isDark ? 'dark' : 'light'} !important;\r\n}\r\nbody {\r\n background-color: transparent !important;\r\n color: ${isDark ? '#e0e0e0' : 'black'} !important;\r\n font-size: ${fontSize}% !important;\r\n line-height: ${lineHeight} !important;\n letter-spacing: ${letterSpacing}em !important;\n}\r\np {\r\n line-height: inherit !important;\n margin-bottom: 1em;\r\n}\r\na {\r\n color: ${isDark ? '#64b5f6' : '#2563eb'} !important;\r\n}\r\nimg {\r\n max-width: 100%;\r\n height: auto;\r\n object-fit: contain;\r\n ${isDark ? 'filter: brightness(0.8) contrast(1.2);' : ''}\r\n}\r\n${extraCSS ?? ''}\r\n`\r\n\r\nexport function createEBookReader(container: HTMLElement, options: EBookReaderOptions = {}): EBookReaderHandle {\r\n if (!container) throw new Error('container is required')\r\n if (!customElements.get('foliate-view')) throw new Error('foliate-view is not defined')\r\n\r\n const {\r\n darkMode: initialDarkMode = false,\r\n fontSize: initialFontSize = 100,\r\n lineHeight: initialLineHeight = 1.6,\n letterSpacing: initialLetterSpacing = 0,\n extraContentCSS,\r\n onReady,\r\n onError,\r\n onProgress,\r\n onToc,\r\n onSearchProgress,\r\n onContentLoad,\r\n } = options\r\n\r\n let destroyed = false\r\n let toc: TocItem[] = []\r\n let fontSize = initialFontSize\r\n let darkMode = initialDarkMode\r\n let lineHeight = initialLineHeight\n let letterSpacing = initialLetterSpacing\n let searchToken = 0\r\n\r\n container.innerHTML = ''\r\n\r\n const viewer = document.createElement('foliate-view') as FoliateViewElement\r\n viewer.style.display = 'block'\r\n viewer.style.width = '100%'\r\n viewer.style.height = '100%'\r\n viewer.setAttribute('margin', '48')\r\n viewer.setAttribute('gap', '0.07')\r\n\r\n const applyStyles = () => {\r\n if (destroyed) return\r\n if (!viewer.renderer?.setStyles) return\r\n viewer.renderer.setStyles(getContentCSS(fontSize, darkMode, lineHeight, letterSpacing, extraContentCSS))\n requestAnimationFrame(() => {\r\n setTimeout(() => {\r\n if (destroyed) return\r\n viewer.renderer?.render?.()\r\n viewer.renderer?.expand?.()\r\n }, 50)\r\n })\r\n }\r\n\r\n const handleLoad = (e: Event) => {\r\n applyStyles()\r\n const detail = (e as CustomEvent).detail as { doc?: Document } | undefined\r\n if (detail?.doc) onContentLoad?.(detail.doc)\r\n }\r\n\r\n const handleRelocate = (e: Event) => {\r\n const detail = (e as CustomEvent).detail as ProgressInfo\r\n onProgress?.(detail)\r\n }\r\n\r\n viewer.addEventListener('load', handleLoad as EventListener)\r\n viewer.addEventListener('relocate', handleRelocate as EventListener)\r\n\r\n container.appendChild(viewer)\r\n\r\n const handle: EBookReaderHandle = {\r\n async open(file) {\r\n if (destroyed) return\r\n if (!file) return\r\n\r\n try {\r\n viewer.clearSearch?.()\r\n searchToken++\r\n\r\n await viewer.open?.(file)\r\n\r\n const nextToc = viewer.book?.toc ?? []\r\n toc = nextToc\r\n onToc?.(toc)\r\n\r\n await viewer.init?.({ showTextStart: true })\r\n applyStyles()\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n },\r\n destroy() {\r\n if (destroyed) return\r\n destroyed = true\r\n searchToken++\r\n viewer.removeEventListener('load', handleLoad)\r\n viewer.removeEventListener('relocate', handleRelocate as EventListener)\r\n container.innerHTML = ''\r\n },\r\n prevPage() {\r\n viewer.goLeft?.()\r\n },\r\n nextPage() {\r\n viewer.goRight?.()\r\n },\r\n prevSection() {\r\n viewer.renderer?.prevSection?.()\r\n },\r\n nextSection() {\r\n viewer.renderer?.nextSection?.()\r\n },\r\n goTo(target) {\r\n if (!target) return\r\n viewer.goTo?.(target)\r\n },\r\n goToFraction(fraction) {\r\n const safe = Math.min(1, Math.max(0, fraction))\r\n viewer.goToFraction?.(safe)\r\n },\r\n setDarkMode(nextDarkMode) {\r\n darkMode = nextDarkMode\r\n applyStyles()\r\n },\r\n setFontSize(nextFontSize) {\r\n const safe = Math.min(300, Math.max(50, nextFontSize))\r\n fontSize = safe\r\n applyStyles()\r\n },\r\n setLineHeight(nextLineHeight) {\n const safe = Math.min(3, Math.max(1, nextLineHeight))\n lineHeight = safe\n applyStyles()\n },\n setLetterSpacing(nextLetterSpacing) {\n const safe = Math.min(0.3, Math.max(0, nextLetterSpacing))\n letterSpacing = safe\n applyStyles()\n },\n async search(query, opts: SearchOptions = {}) {\r\n const normalized = query.trim()\r\n if (!normalized) {\r\n viewer.clearSearch?.()\r\n return []\r\n }\r\n\r\n const token = ++searchToken\r\n const results: SearchResult[] = []\r\n\r\n try {\r\n for await (const item of viewer.search?.({\r\n query: normalized,\r\n matchCase: Boolean(opts.matchCase),\r\n matchWholeWords: Boolean(opts.wholeWords),\r\n matchDiacritics: Boolean(opts.matchDiacritics),\r\n }) ?? []) {\r\n if (destroyed || token !== searchToken) return results\r\n\r\n if (item === 'done') {\r\n onSearchProgress?.({ done: true, progress: 1 })\r\n break\r\n }\r\n\r\n if (typeof item === 'object' && item && 'progress' in (item as any)) {\r\n const progress = (item as any).progress\r\n if (typeof progress === 'number') onSearchProgress?.({ progress })\r\n continue\r\n }\r\n\r\n const anyItem = item as any\r\n if (anyItem?.subitems?.length) {\r\n for (const sub of anyItem.subitems) {\r\n results.push({\r\n label: anyItem.label,\r\n cfi: sub?.cfi,\r\n excerpt: sub?.excerpt,\r\n title: sub?.title,\r\n })\r\n }\r\n } else if (anyItem?.cfi) {\r\n results.push({\r\n cfi: anyItem.cfi,\r\n excerpt: anyItem.excerpt,\r\n title: anyItem.title,\r\n })\r\n }\r\n }\r\n } catch (error) {\r\n onError?.(error)\r\n throw error\r\n }\r\n\r\n return results\r\n },\r\n cancelSearch() {\r\n searchToken++\r\n },\r\n clearSearch() {\r\n viewer.clearSearch?.()\r\n },\r\n getToc() {\r\n return toc\r\n },\r\n }\r\n\r\n onReady?.(handle)\r\n return handle\r\n}\r\n"]}
|