wolfy-reader 0.1.0

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 (233) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +277 -0
  3. package/dist/core/book.d.ts +75 -0
  4. package/dist/core/book.d.ts.map +1 -0
  5. package/dist/core/book.js +2 -0
  6. package/dist/core/book.js.map +1 -0
  7. package/dist/core/errors.d.ts +17 -0
  8. package/dist/core/errors.d.ts.map +1 -0
  9. package/dist/core/errors.js +29 -0
  10. package/dist/core/errors.js.map +1 -0
  11. package/dist/core/format.d.ts +13 -0
  12. package/dist/core/format.d.ts.map +1 -0
  13. package/dist/core/format.js +2 -0
  14. package/dist/core/format.js.map +1 -0
  15. package/dist/core/graphemes.d.ts +36 -0
  16. package/dist/core/graphemes.d.ts.map +1 -0
  17. package/dist/core/graphemes.js +62 -0
  18. package/dist/core/graphemes.js.map +1 -0
  19. package/dist/core/index.d.ts +11 -0
  20. package/dist/core/index.d.ts.map +1 -0
  21. package/dist/core/index.js +6 -0
  22. package/dist/core/index.js.map +1 -0
  23. package/dist/core/lookup.d.ts +10 -0
  24. package/dist/core/lookup.d.ts.map +1 -0
  25. package/dist/core/lookup.js +16 -0
  26. package/dist/core/lookup.js.map +1 -0
  27. package/dist/core/open.d.ts +12 -0
  28. package/dist/core/open.d.ts.map +1 -0
  29. package/dist/core/open.js +23 -0
  30. package/dist/core/open.js.map +1 -0
  31. package/dist/core/position.d.ts +121 -0
  32. package/dist/core/position.d.ts.map +1 -0
  33. package/dist/core/position.js +327 -0
  34. package/dist/core/position.js.map +1 -0
  35. package/dist/core/reading-text.d.ts +77 -0
  36. package/dist/core/reading-text.d.ts.map +1 -0
  37. package/dist/core/reading-text.js +144 -0
  38. package/dist/core/reading-text.js.map +1 -0
  39. package/dist/core/source.d.ts +17 -0
  40. package/dist/core/source.d.ts.map +1 -0
  41. package/dist/core/source.js +39 -0
  42. package/dist/core/source.js.map +1 -0
  43. package/dist/core/storage.d.ts +7 -0
  44. package/dist/core/storage.d.ts.map +1 -0
  45. package/dist/core/storage.js +2 -0
  46. package/dist/core/storage.js.map +1 -0
  47. package/dist/core/text.d.ts +18 -0
  48. package/dist/core/text.d.ts.map +1 -0
  49. package/dist/core/text.js +32 -0
  50. package/dist/core/text.js.map +1 -0
  51. package/dist/formats/epub/href.d.ts +14 -0
  52. package/dist/formats/epub/href.d.ts.map +1 -0
  53. package/dist/formats/epub/href.js +52 -0
  54. package/dist/formats/epub/href.js.map +1 -0
  55. package/dist/formats/epub/index.d.ts +3 -0
  56. package/dist/formats/epub/index.d.ts.map +1 -0
  57. package/dist/formats/epub/index.js +223 -0
  58. package/dist/formats/epub/index.js.map +1 -0
  59. package/dist/formats/epub/opf.d.ts +27 -0
  60. package/dist/formats/epub/opf.d.ts.map +1 -0
  61. package/dist/formats/epub/opf.js +110 -0
  62. package/dist/formats/epub/opf.js.map +1 -0
  63. package/dist/formats/epub/toc.d.ts +6 -0
  64. package/dist/formats/epub/toc.d.ts.map +1 -0
  65. package/dist/formats/epub/toc.js +88 -0
  66. package/dist/formats/epub/toc.js.map +1 -0
  67. package/dist/formats/fb2/index.d.ts +13 -0
  68. package/dist/formats/fb2/index.d.ts.map +1 -0
  69. package/dist/formats/fb2/index.js +317 -0
  70. package/dist/formats/fb2/index.js.map +1 -0
  71. package/dist/formats/index.d.ts +4 -0
  72. package/dist/formats/index.d.ts.map +1 -0
  73. package/dist/formats/index.js +4 -0
  74. package/dist/formats/index.js.map +1 -0
  75. package/dist/formats/text/index.d.ts +11 -0
  76. package/dist/formats/text/index.d.ts.map +1 -0
  77. package/dist/formats/text/index.js +201 -0
  78. package/dist/formats/text/index.js.map +1 -0
  79. package/dist/formats/xml.d.ts +33 -0
  80. package/dist/formats/xml.d.ts.map +1 -0
  81. package/dist/formats/xml.js +321 -0
  82. package/dist/formats/xml.js.map +1 -0
  83. package/dist/index.d.ts +27 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +28 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/layout/chunk.d.ts +51 -0
  88. package/dist/layout/chunk.d.ts.map +1 -0
  89. package/dist/layout/chunk.js +131 -0
  90. package/dist/layout/chunk.js.map +1 -0
  91. package/dist/layout/index.d.ts +238 -0
  92. package/dist/layout/index.d.ts.map +1 -0
  93. package/dist/layout/index.js +476 -0
  94. package/dist/layout/index.js.map +1 -0
  95. package/dist/reader/index.d.ts +231 -0
  96. package/dist/reader/index.d.ts.map +1 -0
  97. package/dist/reader/index.js +958 -0
  98. package/dist/reader/index.js.map +1 -0
  99. package/dist/reader/input.d.ts +69 -0
  100. package/dist/reader/input.d.ts.map +1 -0
  101. package/dist/reader/input.js +75 -0
  102. package/dist/reader/input.js.map +1 -0
  103. package/dist/search/extract.d.ts +51 -0
  104. package/dist/search/extract.d.ts.map +1 -0
  105. package/dist/search/extract.js +401 -0
  106. package/dist/search/extract.js.map +1 -0
  107. package/dist/search/index.d.ts +11 -0
  108. package/dist/search/index.d.ts.map +1 -0
  109. package/dist/search/index.js +11 -0
  110. package/dist/search/index.js.map +1 -0
  111. package/dist/search/matcher.d.ts +56 -0
  112. package/dist/search/matcher.d.ts.map +1 -0
  113. package/dist/search/matcher.js +128 -0
  114. package/dist/search/matcher.js.map +1 -0
  115. package/dist/search/normalize.d.ts +48 -0
  116. package/dist/search/normalize.d.ts.map +1 -0
  117. package/dist/search/normalize.js +103 -0
  118. package/dist/search/normalize.js.map +1 -0
  119. package/dist/view/allowlist.d.ts +59 -0
  120. package/dist/view/allowlist.d.ts.map +1 -0
  121. package/dist/view/allowlist.js +198 -0
  122. package/dist/view/allowlist.js.map +1 -0
  123. package/dist/view/appearance.d.ts +137 -0
  124. package/dist/view/appearance.d.ts.map +1 -0
  125. package/dist/view/appearance.js +274 -0
  126. package/dist/view/appearance.js.map +1 -0
  127. package/dist/view/css.d.ts +24 -0
  128. package/dist/view/css.d.ts.map +1 -0
  129. package/dist/view/css.js +153 -0
  130. package/dist/view/css.js.map +1 -0
  131. package/dist/view/frame.d.ts +54 -0
  132. package/dist/view/frame.d.ts.map +1 -0
  133. package/dist/view/frame.js +980 -0
  134. package/dist/view/frame.js.map +1 -0
  135. package/dist/view/host.d.ts +160 -0
  136. package/dist/view/host.d.ts.map +1 -0
  137. package/dist/view/host.js +385 -0
  138. package/dist/view/host.js.map +1 -0
  139. package/dist/view/index.d.ts +12 -0
  140. package/dist/view/index.d.ts.map +1 -0
  141. package/dist/view/index.js +7 -0
  142. package/dist/view/index.js.map +1 -0
  143. package/dist/view/protocol.d.ts +220 -0
  144. package/dist/view/protocol.d.ts.map +1 -0
  145. package/dist/view/protocol.js +246 -0
  146. package/dist/view/protocol.js.map +1 -0
  147. package/dist/view/reference.d.ts +18 -0
  148. package/dist/view/reference.d.ts.map +1 -0
  149. package/dist/view/reference.js +25 -0
  150. package/dist/view/reference.js.map +1 -0
  151. package/dist/view/resources.d.ts +51 -0
  152. package/dist/view/resources.d.ts.map +1 -0
  153. package/dist/view/resources.js +242 -0
  154. package/dist/view/resources.js.map +1 -0
  155. package/dist/view/sanitize.d.ts +32 -0
  156. package/dist/view/sanitize.d.ts.map +1 -0
  157. package/dist/view/sanitize.js +226 -0
  158. package/dist/view/sanitize.js.map +1 -0
  159. package/dist/zip/central.d.ts +12 -0
  160. package/dist/zip/central.d.ts.map +1 -0
  161. package/dist/zip/central.js +72 -0
  162. package/dist/zip/central.js.map +1 -0
  163. package/dist/zip/crc32.d.ts +3 -0
  164. package/dist/zip/crc32.d.ts.map +1 -0
  165. package/dist/zip/crc32.js +28 -0
  166. package/dist/zip/crc32.js.map +1 -0
  167. package/dist/zip/eocd.d.ts +9 -0
  168. package/dist/zip/eocd.d.ts.map +1 -0
  169. package/dist/zip/eocd.js +84 -0
  170. package/dist/zip/eocd.js.map +1 -0
  171. package/dist/zip/errors.d.ts +19 -0
  172. package/dist/zip/errors.d.ts.map +1 -0
  173. package/dist/zip/errors.js +37 -0
  174. package/dist/zip/errors.js.map +1 -0
  175. package/dist/zip/index.d.ts +18 -0
  176. package/dist/zip/index.d.ts.map +1 -0
  177. package/dist/zip/index.js +78 -0
  178. package/dist/zip/index.js.map +1 -0
  179. package/dist/zip/inflate.d.ts +2 -0
  180. package/dist/zip/inflate.d.ts.map +1 -0
  181. package/dist/zip/inflate.js +43 -0
  182. package/dist/zip/inflate.js.map +1 -0
  183. package/dist/zip/source.d.ts +15 -0
  184. package/dist/zip/source.d.ts.map +1 -0
  185. package/dist/zip/source.js +34 -0
  186. package/dist/zip/source.js.map +1 -0
  187. package/package.json +75 -0
  188. package/src/core/book.ts +80 -0
  189. package/src/core/errors.ts +31 -0
  190. package/src/core/format.ts +14 -0
  191. package/src/core/graphemes.ts +73 -0
  192. package/src/core/index.ts +27 -0
  193. package/src/core/lookup.ts +16 -0
  194. package/src/core/open.ts +31 -0
  195. package/src/core/position.ts +485 -0
  196. package/src/core/reading-text.ts +200 -0
  197. package/src/core/source.ts +61 -0
  198. package/src/core/storage.ts +6 -0
  199. package/src/core/text.ts +35 -0
  200. package/src/formats/epub/href.ts +54 -0
  201. package/src/formats/epub/index.ts +235 -0
  202. package/src/formats/epub/opf.ts +143 -0
  203. package/src/formats/epub/toc.ts +120 -0
  204. package/src/formats/fb2/index.ts +348 -0
  205. package/src/formats/index.ts +3 -0
  206. package/src/formats/text/index.ts +208 -0
  207. package/src/formats/xml.ts +326 -0
  208. package/src/index.ts +26 -0
  209. package/src/layout/chunk.ts +169 -0
  210. package/src/layout/index.ts +573 -0
  211. package/src/reader/index.ts +1206 -0
  212. package/src/reader/input.ts +122 -0
  213. package/src/search/extract.ts +403 -0
  214. package/src/search/index.ts +10 -0
  215. package/src/search/matcher.ts +187 -0
  216. package/src/search/normalize.ts +122 -0
  217. package/src/view/allowlist.ts +273 -0
  218. package/src/view/appearance.ts +380 -0
  219. package/src/view/css.ts +172 -0
  220. package/src/view/frame.ts +1018 -0
  221. package/src/view/host.ts +527 -0
  222. package/src/view/index.ts +24 -0
  223. package/src/view/protocol.ts +412 -0
  224. package/src/view/reference.ts +30 -0
  225. package/src/view/resources.ts +265 -0
  226. package/src/view/sanitize.ts +266 -0
  227. package/src/zip/central.ts +85 -0
  228. package/src/zip/crc32.ts +30 -0
  229. package/src/zip/eocd.ts +97 -0
  230. package/src/zip/errors.ts +41 -0
  231. package/src/zip/index.ts +114 -0
  232. package/src/zip/inflate.ts +41 -0
  233. package/src/zip/source.ts +51 -0
@@ -0,0 +1,274 @@
1
+ /**
2
+ * The appearance system's theme half: the `--wr-*` CSS custom-property contract,
3
+ * the built-in themes, and the frame stylesheet that delivers them so publisher
4
+ * CSS can restyle its own content but can never reach the theme variables.
5
+ *
6
+ * This module is pure and DOM-free. It maps an {@link Appearance} to a variable
7
+ * set and emits the `<style>` the frame injects at document-assembly time — no
8
+ * `document`, no `window`, no protocol traffic. The frame-injection seam lives in
9
+ * `frame.ts`; the reader facade owns the live appearance state.
10
+ *
11
+ * The typography half (font family, size, line height, alignment, hyphenation,
12
+ * columns) adds more `--wr-*` names to the same namespace and rides the same
13
+ * cascade. The reflowing knobs (font, size, line height, columns) change chunk
14
+ * geometry, so the reader re-lays out and restores the reading position for them
15
+ * rather than repainting in place the way a colour change does.
16
+ */
17
+ import { CONTENT_ROOT_ID } from './frame.js';
18
+ /**
19
+ * The built-in themes. Each is a full {@link ThemeVariables} set so a forced
20
+ * theme is self-contained — it needs no media query to be complete.
21
+ */
22
+ export const THEMES = {
23
+ light: {
24
+ '--wr-background': '#ffffff',
25
+ '--wr-color': '#1a1a1a',
26
+ '--wr-link-color': '#1a5fb4',
27
+ '--wr-selection-background': '#b4d5fe',
28
+ '--wr-selection-color': '#1a1a1a',
29
+ },
30
+ dark: {
31
+ '--wr-background': '#121212',
32
+ '--wr-color': '#e6e6e6',
33
+ '--wr-link-color': '#8ab4f8',
34
+ '--wr-selection-background': '#2f5fb0',
35
+ '--wr-selection-color': '#ffffff',
36
+ },
37
+ sepia: {
38
+ '--wr-background': '#f4ecd8',
39
+ '--wr-color': '#5b4636',
40
+ '--wr-link-color': '#8a5a1a',
41
+ '--wr-selection-background': '#e0cfa8',
42
+ '--wr-selection-color': '#5b4636',
43
+ },
44
+ };
45
+ /** The default theme when the host does not force one and the OS is in light mode. */
46
+ const DEFAULT_LIGHT = { ...THEMES.light };
47
+ /** The default theme when the host does not force one and the OS is in dark mode. */
48
+ const DEFAULT_DARK = { ...THEMES.dark };
49
+ /** The cascade layer the theme reset lives in, so publisher rules outrank it. */
50
+ const THEME_LAYER = 'wolfy-reader-theme';
51
+ /** Normalize a custom-property key to its `--`-prefixed form. */
52
+ function normalizeVarName(name) {
53
+ return name.startsWith('--') ? name : `--${name}`;
54
+ }
55
+ /**
56
+ * Merge two partial `Appearance`s. `update` wins field-by-field; `customProperties`
57
+ * shallow-merges (an update's keys override the base's, and only the base's other
58
+ * keys survive). Passing `theme: undefined` in `update` does not clear the base
59
+ * theme — omit the key to keep it, since `exactOptionalPropertyTypes` distinguishes
60
+ * absent from `undefined`.
61
+ */
62
+ export function mergeAppearance(base, update) {
63
+ const merged = {};
64
+ const theme = 'theme' in update ? update.theme : base.theme;
65
+ if (theme !== undefined)
66
+ merged.theme = theme;
67
+ const custom = { ...(base.customProperties ?? {}), ...(update.customProperties ?? {}) };
68
+ if (Object.keys(custom).length > 0)
69
+ merged.customProperties = custom;
70
+ const fontFamily = 'fontFamily' in update ? update.fontFamily : base.fontFamily;
71
+ if (fontFamily !== undefined)
72
+ merged.fontFamily = fontFamily;
73
+ const fontSize = 'fontSize' in update ? update.fontSize : base.fontSize;
74
+ if (fontSize !== undefined)
75
+ merged.fontSize = fontSize;
76
+ const lineHeight = 'lineHeight' in update ? update.lineHeight : base.lineHeight;
77
+ if (lineHeight !== undefined)
78
+ merged.lineHeight = lineHeight;
79
+ const margin = 'margin' in update ? update.margin : base.margin;
80
+ if (margin !== undefined)
81
+ merged.margin = margin;
82
+ const textAlign = 'textAlign' in update ? update.textAlign : base.textAlign;
83
+ if (textAlign !== undefined)
84
+ merged.textAlign = textAlign;
85
+ const justify = 'justify' in update ? update.justify : base.justify;
86
+ if (justify !== undefined)
87
+ merged.justify = justify;
88
+ const hyphenate = 'hyphenate' in update ? update.hyphenate : base.hyphenate;
89
+ if (hyphenate !== undefined)
90
+ merged.hyphenate = hyphenate;
91
+ const columns = 'columns' in update ? update.columns : base.columns;
92
+ if (columns !== undefined)
93
+ merged.columns = columns;
94
+ return merged;
95
+ }
96
+ /**
97
+ * The resolved `--wr-*` variables for a forced theme, or `null` when no theme is
98
+ * forced (the frame follows `prefers-color-scheme` instead). Custom properties
99
+ * merge over the theme's base and win; for `theme: 'custom'` the base is the light
100
+ * theme so an incomplete custom set still yields a complete, readable variable set.
101
+ */
102
+ export function resolveThemeProperties(appearance) {
103
+ const theme = appearance.theme;
104
+ const custom = appearance.customProperties;
105
+ if (theme === undefined && custom === undefined)
106
+ return null;
107
+ const base = theme === undefined || theme === 'custom'
108
+ ? { ...(theme === 'custom' ? DEFAULT_LIGHT : {}) }
109
+ : { ...THEMES[theme] };
110
+ // With no theme and only custom properties, seed from the light theme so a
111
+ // partial custom set is still complete; a forced-null default (below) covers
112
+ // the truly-unset case.
113
+ if (theme === undefined && custom !== undefined)
114
+ Object.assign(base, DEFAULT_LIGHT);
115
+ if (custom !== undefined) {
116
+ for (const [name, value] of Object.entries(custom))
117
+ base[normalizeVarName(name)] = value;
118
+ }
119
+ return base;
120
+ }
121
+ /**
122
+ * The resolved typography `--wr-*` variables for an appearance, or `null` when no
123
+ * typography knob is set. `columns` maps to `--wr-column-count`; `justify` folds
124
+ * into `--wr-text-align` (an explicit `textAlign` wins over `justify`). Only the
125
+ * knobs the caller supplied are emitted — an unset knob leaves the publisher's own
126
+ * value in place rather than forcing a default.
127
+ */
128
+ export function resolveTypographyProperties(appearance) {
129
+ const vars = {};
130
+ if (appearance.fontFamily !== undefined)
131
+ vars['--wr-font-family'] = appearance.fontFamily;
132
+ if (appearance.fontSize !== undefined)
133
+ vars['--wr-font-size'] = `${appearance.fontSize}px`;
134
+ if (appearance.lineHeight !== undefined)
135
+ vars['--wr-line-height'] = String(appearance.lineHeight);
136
+ const align = resolveTextAlign(appearance);
137
+ if (align !== undefined)
138
+ vars['--wr-text-align'] = align;
139
+ if (appearance.hyphenate !== undefined) {
140
+ vars['--wr-hyphens'] = appearance.hyphenate ? 'auto' : 'manual';
141
+ }
142
+ if (appearance.columns !== undefined)
143
+ vars['--wr-column-count'] = String(appearance.columns);
144
+ return Object.keys(vars).length === 0 ? null : vars;
145
+ }
146
+ /** The effective text alignment: an explicit `textAlign` wins over `justify`. */
147
+ function resolveTextAlign(appearance) {
148
+ if (appearance.textAlign !== undefined)
149
+ return appearance.textAlign;
150
+ if (appearance.justify !== undefined)
151
+ return appearance.justify ? 'justify' : 'start';
152
+ return undefined;
153
+ }
154
+ /** Serialize a variable set into `--name: value;` declarations. */
155
+ function declarations(vars) {
156
+ return Object.entries(vars)
157
+ .map(([name, value]) => `${name}:${value}`)
158
+ .join(';');
159
+ }
160
+ /** The `:root` variable block for a set of resolved theme variables. */
161
+ function forcedRoot(vars) {
162
+ return `:root{${declarations(vars)}}`;
163
+ }
164
+ /**
165
+ * The `prefers-color-scheme`-driven default variables, used when the host does
166
+ * not force a theme. Light values sit at `:root`; a `@media (prefers-color-scheme:
167
+ * dark)` block swaps them, so the frame picks up the OS mode on its own opaque
168
+ * origin — the resolution stays inside the frame rather than being sniffed by the
169
+ * host. A forced theme's explicit `:root` block (emitted after this) overrides it.
170
+ */
171
+ function preferenceDefaults() {
172
+ return (`:root{${declarations(DEFAULT_LIGHT)}}` +
173
+ `@media (prefers-color-scheme: dark){:root{${declarations(DEFAULT_DARK)}}}`);
174
+ }
175
+ /**
176
+ * The reading surface — the outermost background and base text colour, anchored
177
+ * on the content root. This belongs to the reader, not the book, so it is set
178
+ * unlayered and `!important` at id specificity: an id selector plus `!important`
179
+ * outranks even a publisher `*{…!important}` or `body{…!important}`, so a hostile
180
+ * book cannot repaint the surface out from under the theme. It only pins the
181
+ * content root's *own* background/colour; descendants a book styles (`p{color}`)
182
+ * still win for themselves, because that is a direct match on the descendant.
183
+ */
184
+ function surfaceGuarantee() {
185
+ return (`#${CONTENT_ROOT_ID}{` +
186
+ `background:var(--wr-background) !important;` +
187
+ `color:var(--wr-color) !important` +
188
+ `}`);
189
+ }
190
+ /**
191
+ * The themeable defaults that consume the `--wr-*` variables: the html/body
192
+ * fallback surface, link colour and selection colours. These live in a cascade
193
+ * layer, so an unlayered publisher rule of any specificity outranks them *for the
194
+ * properties it sets* — a book restyling its own links or background wins — while
195
+ * the `--wr-*` variables themselves are unreachable by publisher CSS (they are
196
+ * custom-property names the book does not know). An unstyled book still themes
197
+ * fully, because nothing overrides the layer.
198
+ */
199
+ function themeableDefaults() {
200
+ return (`@layer ${THEME_LAYER}{` +
201
+ `html{background:var(--wr-background);color:var(--wr-color)}` +
202
+ `body{background:var(--wr-background);color:var(--wr-color)}` +
203
+ `a{color:var(--wr-link-color)}` +
204
+ `::selection{background:var(--wr-selection-background);color:var(--wr-selection-color)}` +
205
+ `}`);
206
+ }
207
+ /**
208
+ * The unlayered typography block: the reader's own font, size, line height,
209
+ * alignment and hyphenation, anchored on the content root and set `!important` at
210
+ * id specificity — the same cascade device as {@link surfaceGuarantee}. An id
211
+ * selector plus `!important` outranks even a hostile publisher `*{…!important}`,
212
+ * so a user's typography choice wins the reading surface; a descendant the book
213
+ * styles directly (`p{font-size:20px}`) still wins for itself, which is the
214
+ * intended split. Only the knobs actually set emit a declaration, and each reads
215
+ * its own `--wr-*` variable (unreachable by publisher CSS). `column-count` is not
216
+ * here — column geometry is per-chunk and applied frame-side by the paginator.
217
+ */
218
+ function typographyGuarantee(vars) {
219
+ const rules = [];
220
+ if (vars['--wr-font-family'] !== undefined)
221
+ rules.push('font-family:var(--wr-font-family) !important');
222
+ if (vars['--wr-font-size'] !== undefined)
223
+ rules.push('font-size:var(--wr-font-size) !important');
224
+ if (vars['--wr-line-height'] !== undefined)
225
+ rules.push('line-height:var(--wr-line-height) !important');
226
+ if (vars['--wr-text-align'] !== undefined)
227
+ rules.push('text-align:var(--wr-text-align) !important');
228
+ if (vars['--wr-hyphens'] !== undefined) {
229
+ rules.push('-webkit-hyphens:var(--wr-hyphens) !important', 'hyphens:var(--wr-hyphens) !important');
230
+ }
231
+ if (rules.length === 0)
232
+ return '';
233
+ return `:root{${declarations(vars)}}#${CONTENT_ROOT_ID}{${rules.join(';')}}`;
234
+ }
235
+ /**
236
+ * The full appearance stylesheet the frame injects at document assembly, before
237
+ * the publisher's `headHtml`. It carries the theme half (colours) and the
238
+ * typography half (font/size/line-height/alignment/hyphenation) through one
239
+ * `--wr-*` namespace. It declares the theme layer first (so its ordering is fixed
240
+ * regardless of any `@layer` a book declares later), emits the themeable defaults
241
+ * and the unlayered surface guarantee, then the `prefers-color-scheme` defaults,
242
+ * then — if a theme is forced — an unlayered `:root` block that overrides the
243
+ * media query, and finally the unlayered typography guarantee. `null` from
244
+ * {@link resolveThemeProperties} means "follow the OS"; a variable set means
245
+ * "force it".
246
+ */
247
+ export function themeStyleSheet(appearance) {
248
+ const forced = resolveThemeProperties(appearance);
249
+ const typography = resolveTypographyProperties(appearance);
250
+ return (`@layer ${THEME_LAYER};` +
251
+ themeableDefaults() +
252
+ surfaceGuarantee() +
253
+ preferenceDefaults() +
254
+ (forced === null ? '' : forcedRoot(forced)) +
255
+ (typography === null ? '' : typographyGuarantee(typography)));
256
+ }
257
+ /**
258
+ * The typography knobs that change chunk geometry and therefore require a re-layout
259
+ * (a `paginate`), not just a variable poke: font family, font size, line height,
260
+ * page margin, and column count. Alignment and hyphenation can shift line breaks
261
+ * too, so they are treated as reflowing to be safe. Whether an `update` touches any
262
+ * of these decides which path {@link Reader.setAppearance} takes.
263
+ */
264
+ export function isReflowingUpdate(update) {
265
+ return (update.fontFamily !== undefined ||
266
+ update.fontSize !== undefined ||
267
+ update.lineHeight !== undefined ||
268
+ update.margin !== undefined ||
269
+ update.textAlign !== undefined ||
270
+ update.justify !== undefined ||
271
+ update.hyphenate !== undefined ||
272
+ update.columns !== undefined);
273
+ }
274
+ //# sourceMappingURL=appearance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appearance.js","sourceRoot":"","sources":["../../src/view/appearance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export type CssReferenceKind = 'import' | 'url';
2
+ export interface CssReference {
3
+ readonly kind: CssReferenceKind;
4
+ /** The reference as written, with quotes and escapes removed. */
5
+ readonly value: string;
6
+ /** Index of the first character of the replaceable token. */
7
+ readonly start: number;
8
+ /** Index one past the last character of the replaceable token. */
9
+ readonly end: number;
10
+ }
11
+ /**
12
+ * Finds every `url(...)` and `@import` target in a stylesheet.
13
+ *
14
+ * This is a token-level scan that understands strings and comments, not a CSS
15
+ * parser: those two constructs are the only ones a renderer has to rewrite, and
16
+ * a conforming parser is orders of magnitude more code for no extra coverage.
17
+ */
18
+ export declare function findCssReferences(css: string): CssReference[];
19
+ /**
20
+ * Rewrites every reference the scan finds. A replacer returning undefined
21
+ * leaves the reference exactly as written.
22
+ */
23
+ export declare function rewriteCssReferences(css: string, replace: (reference: CssReference) => Promise<string | undefined>): Promise<string>;
24
+ //# sourceMappingURL=css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../../src/view/css.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AA2FD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,EAAE,CAsC7D;AAMD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CAAC,SAAS,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAChE,OAAO,CAAC,MAAM,CAAC,CAYjB"}
@@ -0,0 +1,153 @@
1
+ const IDENT_CHAR = /[A-Za-z0-9_\-\\\u0080-\uFFFF]/;
2
+ function isIdentChar(character) {
3
+ return character !== '' && IDENT_CHAR.test(character);
4
+ }
5
+ function matchesAt(css, index, literal) {
6
+ return css.slice(index, index + literal.length).toLowerCase() === literal;
7
+ }
8
+ function skipComment(css, index) {
9
+ const close = css.indexOf('*/', index + 2);
10
+ return close === -1 ? css.length : close + 2;
11
+ }
12
+ function skipSpace(css, index) {
13
+ let i = index;
14
+ while (i < css.length) {
15
+ const character = css.charAt(i);
16
+ if (character === '/' && css.charAt(i + 1) === '*') {
17
+ i = skipComment(css, i);
18
+ continue;
19
+ }
20
+ if (character === ' ' || character === '\t' || character === '\n' || character === '\r' || character === '\f') {
21
+ i += 1;
22
+ continue;
23
+ }
24
+ return i;
25
+ }
26
+ return i;
27
+ }
28
+ function readString(css, index) {
29
+ const quote = css.charAt(index);
30
+ let i = index + 1;
31
+ let value = '';
32
+ while (i < css.length) {
33
+ const character = css.charAt(i);
34
+ if (character === '\\') {
35
+ if (css.charAt(i + 1) !== '\n')
36
+ value += css.charAt(i + 1);
37
+ i += 2;
38
+ continue;
39
+ }
40
+ if (character === quote)
41
+ return { value, end: i + 1 };
42
+ if (character === '\n')
43
+ return null;
44
+ value += character;
45
+ i += 1;
46
+ }
47
+ return null;
48
+ }
49
+ function readUrl(css, index) {
50
+ let i = skipSpace(css, index + 4);
51
+ let value;
52
+ const quote = css.charAt(i);
53
+ if (quote === '"' || quote === "'") {
54
+ const string = readString(css, i);
55
+ if (string === null)
56
+ return null;
57
+ value = string.value;
58
+ i = skipSpace(css, string.end);
59
+ }
60
+ else {
61
+ let raw = '';
62
+ while (i < css.length && css.charAt(i) !== ')') {
63
+ if (css.charAt(i) === '\\') {
64
+ raw += css.charAt(i + 1);
65
+ i += 2;
66
+ continue;
67
+ }
68
+ raw += css.charAt(i);
69
+ i += 1;
70
+ }
71
+ value = raw.trim();
72
+ }
73
+ if (css.charAt(i) !== ')')
74
+ return null;
75
+ return { value, end: i + 1 };
76
+ }
77
+ function readReference(css, index) {
78
+ const character = css.charAt(index);
79
+ if (character === '"' || character === "'")
80
+ return readString(css, index);
81
+ if (matchesAt(css, index, 'url('))
82
+ return readUrl(css, index);
83
+ return null;
84
+ }
85
+ /**
86
+ * Finds every `url(...)` and `@import` target in a stylesheet.
87
+ *
88
+ * This is a token-level scan that understands strings and comments, not a CSS
89
+ * parser: those two constructs are the only ones a renderer has to rewrite, and
90
+ * a conforming parser is orders of magnitude more code for no extra coverage.
91
+ */
92
+ export function findCssReferences(css) {
93
+ const references = [];
94
+ let i = 0;
95
+ while (i < css.length) {
96
+ const character = css.charAt(i);
97
+ if (character === '/' && css.charAt(i + 1) === '*') {
98
+ i = skipComment(css, i);
99
+ continue;
100
+ }
101
+ if (character === '"' || character === "'") {
102
+ const string = readString(css, i);
103
+ i = string === null ? i + 1 : string.end;
104
+ continue;
105
+ }
106
+ if (character === '@' && matchesAt(css, i, '@import') && !isIdentChar(css.charAt(i + 7))) {
107
+ const start = skipSpace(css, i + 7);
108
+ const token = readReference(css, start);
109
+ if (token === null) {
110
+ i += 7;
111
+ continue;
112
+ }
113
+ references.push({ kind: 'import', value: token.value, start, end: token.end });
114
+ i = token.end;
115
+ continue;
116
+ }
117
+ if (matchesAt(css, i, 'url(') && !isIdentChar(css.charAt(i - 1))) {
118
+ const token = readUrl(css, i);
119
+ if (token === null) {
120
+ i += 1;
121
+ continue;
122
+ }
123
+ references.push({ kind: 'url', value: token.value, start: i, end: token.end });
124
+ i = token.end;
125
+ continue;
126
+ }
127
+ i += 1;
128
+ }
129
+ return references;
130
+ }
131
+ function escapeCssUrl(url) {
132
+ return url.replace(/[\\"]/g, '\\$&').replace(/[\n\r]/g, '');
133
+ }
134
+ /**
135
+ * Rewrites every reference the scan finds. A replacer returning undefined
136
+ * leaves the reference exactly as written.
137
+ */
138
+ export async function rewriteCssReferences(css, replace) {
139
+ const references = findCssReferences(css);
140
+ if (references.length === 0)
141
+ return css;
142
+ let out = '';
143
+ let cursor = 0;
144
+ for (const reference of references) {
145
+ const replacement = await replace(reference);
146
+ if (replacement === undefined)
147
+ continue;
148
+ out += `${css.slice(cursor, reference.start)}url("${escapeCssUrl(replacement)}")`;
149
+ cursor = reference.end;
150
+ }
151
+ return out + css.slice(cursor);
152
+ }
153
+ //# sourceMappingURL=css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css.js","sourceRoot":"","sources":["../../src/view/css.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ export declare const CONTENT_ROOT_ID = "wolfy-reader-content";
2
+ /** Class marking each per-chunk container the host emits into the frame body. */
3
+ export declare const CHUNK_CLASS = "wolfy-reader-chunk";
4
+ /** Cumulative character offset of a chunk's first glyph into the section text. */
5
+ export declare const CHUNK_START_ATTR = "data-chunk-start";
6
+ /** Cumulative character offset just past a chunk's last glyph. */
7
+ export declare const CHUNK_END_ATTR = "data-chunk-end";
8
+ /** Zero-based index of a chunk in section order. */
9
+ export declare const CHUNK_INDEX_ATTR = "data-chunk-index";
10
+ /** Class every draw-only decoration overlay box carries, alongside the caller's class. */
11
+ export declare const DECORATION_CLASS = "wolfy-reader-decoration";
12
+ export declare function createNonce(): string;
13
+ export declare function coordinationScript(hostOrigin: string, keyboardNav?: boolean): string;
14
+ /** One chunk's markup plus its character count, as `chunkElement` reports it. */
15
+ export interface ChunkPart {
16
+ readonly html: string;
17
+ readonly chars: number;
18
+ }
19
+ /**
20
+ * Wraps each chunk in its own container element, tagging it with the cumulative
21
+ * character range it covers in the section's concatenated text. Offsets are
22
+ * end-exclusive: chunk *i* covers `[start, end)`, and chunk *i+1* starts exactly
23
+ * at the previous `end`, so the ranges tile the section text without gap or
24
+ * overlap. The frame reads these attributes to build per-chunk multi-column
25
+ * contexts and to map pages to character offsets.
26
+ *
27
+ * The container is a `<div class="wolfy-reader-chunk">`; the char count comes from
28
+ * `chunkElement` (`textContent.length` of the chunk's nodes), so it matches what
29
+ * the frame measures with `textContent` at runtime.
30
+ */
31
+ export declare function assembleChunkedBody(chunks: readonly ChunkPart[]): string;
32
+ export interface FrameDocumentParts {
33
+ readonly headHtml: string;
34
+ readonly bodyHtml: string;
35
+ readonly nonce: string;
36
+ readonly hostOrigin: string;
37
+ /**
38
+ * The appearance theme stylesheet ({@link themeStyleSheet}). Injected before
39
+ * the publisher's `headHtml` so its cascade layer loses specificity fights on
40
+ * the properties the book sets, while the theme variables it declares stay
41
+ * unreachable by publisher CSS. Omit for an unthemed document.
42
+ */
43
+ readonly themeCss?: string;
44
+ /**
45
+ * Whether the host acts on forwarded navigation keydowns. Baked into the
46
+ * coordination script (not a wire message — no protocol change): when `false`
47
+ * the frame still forwards nav keys but no longer `preventDefault`s them, so
48
+ * a key the host will ignore keeps its default action instead of going dead.
49
+ * Defaults to `true`.
50
+ */
51
+ readonly keyboardNav?: boolean;
52
+ }
53
+ export declare function assembleFrameDocument(parts: FrameDocumentParts): string;
54
+ //# sourceMappingURL=frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../src/view/frame.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,yBAAyB,CAAC;AAEtD,iFAAiF;AACjF,eAAO,MAAM,WAAW,uBAAuB,CAAC;AAChD,kFAAkF;AAClF,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AACnD,kEAAkE;AAClE,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAC/C,oDAAoD;AACpD,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAEnD,0FAA0F;AAC1F,eAAO,MAAM,gBAAgB,4BAA4B,CAAC;AA+C1D,wBAAgB,WAAW,IAAI,MAAM,CAIpC;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,GAAE,OAAc,GAAG,MAAM,CAi2B1F;AAED,iFAAiF;AACjF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,CAcxE;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CA2BvE"}