bookish-press 0.7.4 → 0.9.2

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 (276) hide show
  1. package/README.md +56 -9
  2. package/dist/components/Auth.svelte +29 -39
  3. package/dist/components/Auth.svelte.d.ts +5 -17
  4. package/dist/components/BookPreview.svelte +14 -20
  5. package/dist/components/BookPreview.svelte.d.ts +6 -18
  6. package/dist/components/Link.svelte +19 -30
  7. package/dist/components/Link.svelte.d.ts +7 -20
  8. package/dist/components/app/BookList.svelte +2 -3
  9. package/dist/components/app/BookList.svelte.d.ts +6 -18
  10. package/dist/components/app/Button.svelte +12 -8
  11. package/dist/components/app/Button.svelte.d.ts +10 -23
  12. package/dist/components/app/Feedback.svelte +4 -4
  13. package/dist/components/app/Feedback.svelte.d.ts +6 -19
  14. package/dist/components/app/Head.svelte +2 -2
  15. package/dist/components/app/Head.svelte.d.ts +6 -19
  16. package/dist/components/app/Large.svelte +4 -1
  17. package/dist/components/app/Large.svelte.d.ts +5 -28
  18. package/dist/components/app/Lead.svelte +4 -1
  19. package/dist/components/app/Lead.svelte.d.ts +5 -28
  20. package/dist/components/app/Link.svelte +12 -9
  21. package/dist/components/app/Link.svelte.d.ts +9 -22
  22. package/dist/components/app/Options.svelte +8 -6
  23. package/dist/components/app/Options.svelte.d.ts +8 -20
  24. package/dist/components/app/Paragraph.svelte +2 -2
  25. package/dist/components/app/Paragraph.svelte.d.ts +6 -19
  26. package/dist/components/app/Section.svelte +4 -1
  27. package/dist/components/app/Section.svelte.d.ts +5 -28
  28. package/dist/components/app/Table.svelte +4 -1
  29. package/dist/components/app/Table.svelte.d.ts +5 -28
  30. package/dist/components/app/TextInput.svelte +10 -8
  31. package/dist/components/app/TextInput.svelte.d.ts +12 -23
  32. package/dist/components/chapter/Atom.svelte +4 -7
  33. package/dist/components/chapter/Atom.svelte.d.ts +6 -19
  34. package/dist/components/chapter/Block.svelte +21 -23
  35. package/dist/components/chapter/Block.svelte.d.ts +5 -17
  36. package/dist/components/chapter/Callout.svelte +3 -5
  37. package/dist/components/chapter/Callout.svelte.d.ts +5 -17
  38. package/dist/components/chapter/CaptionedCode.svelte +12 -14
  39. package/dist/components/chapter/CaptionedCode.svelte.d.ts +5 -17
  40. package/dist/components/chapter/ChapterBody.svelte +14 -17
  41. package/dist/components/chapter/ChapterBody.svelte.d.ts +7 -19
  42. package/dist/components/chapter/ChapterBody.test.d.ts +1 -0
  43. package/dist/components/chapter/ChapterBody.test.js +85 -0
  44. package/dist/components/chapter/Citations.svelte +39 -45
  45. package/dist/components/chapter/Citations.svelte.d.ts +5 -17
  46. package/dist/components/chapter/Code.svelte +158 -155
  47. package/dist/components/chapter/Code.svelte.d.ts +10 -23
  48. package/dist/components/chapter/Comment.svelte +30 -23
  49. package/dist/components/chapter/Comment.svelte.d.ts +5 -17
  50. package/dist/components/chapter/Definition.svelte +36 -34
  51. package/dist/components/chapter/Definition.svelte.d.ts +5 -17
  52. package/dist/components/chapter/Embed.svelte +78 -72
  53. package/dist/components/chapter/Embed.svelte.d.ts +8 -20
  54. package/dist/components/chapter/ErrorMessage.svelte +2 -4
  55. package/dist/components/chapter/ErrorMessage.svelte.d.ts +5 -17
  56. package/dist/components/chapter/Figure.svelte +22 -29
  57. package/dist/components/chapter/Figure.svelte.d.ts +9 -22
  58. package/dist/components/chapter/Footnote.svelte +40 -32
  59. package/dist/components/chapter/Footnote.svelte.d.ts +5 -17
  60. package/dist/components/chapter/Format.svelte +26 -41
  61. package/dist/components/chapter/Format.svelte.d.ts +7 -18
  62. package/dist/components/chapter/InlineCode.svelte +7 -8
  63. package/dist/components/chapter/InlineCode.svelte.d.ts +5 -17
  64. package/dist/components/chapter/Label.svelte +5 -11
  65. package/dist/components/chapter/Label.svelte.d.ts +5 -17
  66. package/dist/components/chapter/LineBreak.svelte +1 -3
  67. package/dist/components/chapter/LineBreak.svelte.d.ts +5 -17
  68. package/dist/components/chapter/Link.svelte +17 -23
  69. package/dist/components/chapter/Link.svelte.d.ts +5 -17
  70. package/dist/components/chapter/List.svelte +9 -9
  71. package/dist/components/chapter/List.svelte.d.ts +6 -17
  72. package/dist/components/chapter/Marginal.svelte +59 -60
  73. package/dist/components/chapter/Marginal.svelte.d.ts +10 -22
  74. package/dist/components/chapter/Paragraph.svelte +8 -23
  75. package/dist/components/chapter/Paragraph.svelte.d.ts +6 -18
  76. package/dist/components/chapter/Positioned.svelte +2 -4
  77. package/dist/components/chapter/Positioned.svelte.d.ts +6 -19
  78. package/dist/components/chapter/Problem.svelte +3 -2
  79. package/dist/components/chapter/Problem.svelte.d.ts +5 -28
  80. package/dist/components/chapter/Python.svelte +45 -58
  81. package/dist/components/chapter/Python.svelte.d.ts +6 -18
  82. package/dist/components/chapter/Quote.svelte +5 -7
  83. package/dist/components/chapter/Quote.svelte.d.ts +5 -17
  84. package/dist/components/chapter/Rule.svelte +1 -3
  85. package/dist/components/chapter/Rule.svelte.d.ts +5 -17
  86. package/dist/components/chapter/Table.svelte +6 -8
  87. package/dist/components/chapter/Table.svelte.d.ts +5 -17
  88. package/dist/components/chapter/Text.svelte +54 -69
  89. package/dist/components/chapter/Text.svelte.d.ts +6 -18
  90. package/dist/components/controls/DarkToggle.svelte +7 -8
  91. package/dist/components/controls/DarkToggle.svelte.d.ts +6 -18
  92. package/dist/components/editor/BookishEditor.svelte +583 -761
  93. package/dist/components/editor/BookishEditor.svelte.d.ts +14 -26
  94. package/dist/components/editor/CalloutEditor.svelte +3 -3
  95. package/dist/components/editor/CalloutEditor.svelte.d.ts +5 -17
  96. package/dist/components/editor/CaptionedCodeEditor.svelte +5 -5
  97. package/dist/components/editor/CaptionedCodeEditor.svelte.d.ts +5 -17
  98. package/dist/components/editor/CaretView.svelte +23 -25
  99. package/dist/components/editor/CaretView.svelte.d.ts +15 -27
  100. package/dist/components/editor/CitationsEditor.svelte +25 -28
  101. package/dist/components/editor/CitationsEditor.svelte.d.ts +5 -17
  102. package/dist/components/editor/ConfirmButton.svelte +9 -6
  103. package/dist/components/editor/ConfirmButton.svelte.d.ts +8 -21
  104. package/dist/components/editor/DefinitionEditor.svelte +11 -15
  105. package/dist/components/editor/DefinitionEditor.svelte.d.ts +5 -17
  106. package/dist/components/editor/EmbedEditor.svelte +44 -45
  107. package/dist/components/editor/EmbedEditor.svelte.d.ts +5 -17
  108. package/dist/components/editor/Icon.svelte +1 -1
  109. package/dist/components/editor/Icon.svelte.d.ts +5 -17
  110. package/dist/components/editor/ImageChooser.svelte +15 -18
  111. package/dist/components/editor/ImageChooser.svelte.d.ts +6 -18
  112. package/dist/components/editor/ImageThumbnail.svelte +29 -24
  113. package/dist/components/editor/ImageThumbnail.svelte.d.ts +7 -19
  114. package/dist/components/editor/InlineCodeEditor.svelte +3 -3
  115. package/dist/components/editor/InlineCodeEditor.svelte.d.ts +5 -17
  116. package/dist/components/editor/LabelEditor.svelte +5 -6
  117. package/dist/components/editor/LabelEditor.svelte.d.ts +5 -17
  118. package/dist/components/editor/LanguageEditor.svelte +4 -5
  119. package/dist/components/editor/LanguageEditor.svelte.d.ts +6 -18
  120. package/dist/components/editor/LinkEditor.svelte +52 -68
  121. package/dist/components/editor/LinkEditor.svelte.d.ts +5 -17
  122. package/dist/components/editor/Note.svelte +4 -1
  123. package/dist/components/editor/Note.svelte.d.ts +5 -28
  124. package/dist/components/editor/Permissions.svelte +36 -34
  125. package/dist/components/editor/Permissions.svelte.d.ts +9 -21
  126. package/dist/components/editor/PositionEditor.svelte +6 -7
  127. package/dist/components/editor/PositionEditor.svelte.d.ts +6 -18
  128. package/dist/components/editor/QuoteEditor.svelte +3 -3
  129. package/dist/components/editor/QuoteEditor.svelte.d.ts +5 -17
  130. package/dist/components/editor/Switch.svelte +16 -11
  131. package/dist/components/editor/Switch.svelte.d.ts +9 -21
  132. package/dist/components/editor/TableEditor.svelte +3 -3
  133. package/dist/components/editor/TableEditor.svelte.d.ts +5 -17
  134. package/dist/components/editor/TextEditor.svelte +74 -87
  135. package/dist/components/editor/TextEditor.svelte.d.ts +13 -25
  136. package/dist/components/editor/Toggle.svelte +18 -21
  137. package/dist/components/editor/Toggle.svelte.d.ts +7 -20
  138. package/dist/components/editor/Toolbar.svelte +140 -145
  139. package/dist/components/editor/Toolbar.svelte.d.ts +5 -17
  140. package/dist/components/editor/ToolbarGroup.svelte +4 -4
  141. package/dist/components/editor/ToolbarGroup.svelte.d.ts +6 -19
  142. package/dist/components/editor/ToolbarSpacer.svelte +1 -1
  143. package/dist/components/editor/ToolbarSpacer.svelte.d.ts +22 -21
  144. package/dist/components/editor/URLEditor.svelte +3 -5
  145. package/dist/components/editor/URLEditor.svelte.d.ts +7 -19
  146. package/dist/components/page/Acknowledgements.svelte +14 -8
  147. package/dist/components/page/Acknowledgements.svelte.d.ts +3 -16
  148. package/dist/components/page/Analytics.svelte +2 -3
  149. package/dist/components/page/Analytics.svelte.d.ts +6 -17
  150. package/dist/components/page/Authors.svelte +29 -29
  151. package/dist/components/page/Authors.svelte.d.ts +11 -23
  152. package/dist/components/page/BookLoader.svelte +47 -43
  153. package/dist/components/page/BookLoader.svelte.d.ts +5 -17
  154. package/dist/components/page/BulkReferenceEditor.svelte +43 -26
  155. package/dist/components/page/BulkReferenceEditor.svelte.d.ts +3 -16
  156. package/dist/components/page/Chapter.svelte +224 -249
  157. package/dist/components/page/Chapter.svelte.d.ts +6 -18
  158. package/dist/components/page/ChapterContext.d.ts +3 -1
  159. package/dist/components/page/ChapterNumber.svelte +4 -1
  160. package/dist/components/page/ChapterNumber.svelte.d.ts +5 -28
  161. package/dist/components/page/ChapterTitle.svelte +4 -4
  162. package/dist/components/page/ChapterTitle.svelte.d.ts +6 -19
  163. package/dist/components/page/Contexts.js +2 -2
  164. package/dist/components/page/DefinitionView.svelte +51 -44
  165. package/dist/components/page/DefinitionView.svelte.d.ts +6 -18
  166. package/dist/components/page/Description.svelte +10 -4
  167. package/dist/components/page/Description.svelte.d.ts +16 -14
  168. package/dist/components/page/DownloadEPUB.svelte +234 -0
  169. package/dist/components/page/DownloadEPUB.svelte.d.ts +3 -0
  170. package/dist/components/page/EditableHeader.svelte +4 -6
  171. package/dist/components/page/EditableHeader.svelte.d.ts +7 -18
  172. package/dist/components/page/Edition.svelte +57 -71
  173. package/dist/components/page/Edition.svelte.d.ts +7 -20
  174. package/dist/components/page/EditionLoader.svelte +119 -82
  175. package/dist/components/page/EditionLoader.svelte.d.ts +6 -19
  176. package/dist/components/page/Editions.svelte +26 -31
  177. package/dist/components/page/Editions.svelte.d.ts +5 -17
  178. package/dist/components/page/Glossary.svelte +31 -35
  179. package/dist/components/page/Glossary.svelte.d.ts +3 -16
  180. package/dist/components/page/Header.svelte +43 -49
  181. package/dist/components/page/Header.svelte.d.ts +19 -30
  182. package/dist/components/page/Index.svelte +46 -46
  183. package/dist/components/page/Index.svelte.d.ts +3 -16
  184. package/dist/components/page/Instructions.svelte +2 -2
  185. package/dist/components/page/Instructions.svelte.d.ts +6 -19
  186. package/dist/components/page/License.svelte +13 -7
  187. package/dist/components/page/License.svelte.d.ts +16 -14
  188. package/dist/components/page/Loading.svelte +9 -9
  189. package/dist/components/page/Loading.svelte.d.ts +22 -21
  190. package/dist/components/page/Media.svelte +36 -27
  191. package/dist/components/page/Media.svelte.d.ts +3 -16
  192. package/dist/components/page/MediaPreview.svelte +22 -19
  193. package/dist/components/page/MediaPreview.svelte.d.ts +8 -21
  194. package/dist/components/page/Muted.svelte +4 -1
  195. package/dist/components/page/Muted.svelte.d.ts +5 -28
  196. package/dist/components/page/Outline.svelte +75 -97
  197. package/dist/components/page/Outline.svelte.d.ts +8 -20
  198. package/dist/components/page/Page.svelte +23 -33
  199. package/dist/components/page/Page.svelte.d.ts +7 -20
  200. package/dist/components/page/PageHeader.svelte +2 -2
  201. package/dist/components/page/PageHeader.svelte.d.ts +6 -19
  202. package/dist/components/page/PageParagraph.svelte +4 -1
  203. package/dist/components/page/PageParagraph.svelte.d.ts +5 -28
  204. package/dist/components/page/PossibleChapter.svelte +7 -7
  205. package/dist/components/page/PossibleChapter.svelte.d.ts +3 -16
  206. package/dist/components/page/PossibleReference.svelte +4 -5
  207. package/dist/components/page/PossibleReference.svelte.d.ts +6 -18
  208. package/dist/components/page/Print.svelte +11 -12
  209. package/dist/components/page/Print.svelte.d.ts +3 -16
  210. package/dist/components/page/Publish.svelte +47 -47
  211. package/dist/components/page/Publish.svelte.d.ts +3 -16
  212. package/dist/components/page/Reference.svelte +24 -35
  213. package/dist/components/page/Reference.svelte.d.ts +6 -18
  214. package/dist/components/page/References.svelte +21 -22
  215. package/dist/components/page/References.svelte.d.ts +3 -16
  216. package/dist/components/page/Rows.svelte +5 -2
  217. package/dist/components/page/Rows.svelte.d.ts +5 -28
  218. package/dist/components/page/Search.svelte +59 -61
  219. package/dist/components/page/Search.svelte.d.ts +3 -16
  220. package/dist/components/page/Status.svelte +2 -2
  221. package/dist/components/page/Status.svelte.d.ts +16 -14
  222. package/dist/components/page/SubdomainEditor.svelte +11 -11
  223. package/dist/components/page/SubdomainEditor.svelte.d.ts +16 -14
  224. package/dist/components/page/TableOfContents.svelte +157 -124
  225. package/dist/components/page/TableOfContents.svelte.d.ts +3 -16
  226. package/dist/components/page/TableOfContentsImage.svelte +6 -7
  227. package/dist/components/page/TableOfContentsImage.svelte.d.ts +6 -18
  228. package/dist/components/page/TableOfContentsRow.svelte +32 -32
  229. package/dist/components/page/TableOfContentsRow.svelte.d.ts +10 -22
  230. package/dist/components/page/ThemeEditor.svelte +35 -28
  231. package/dist/components/page/ThemeEditor.svelte.d.ts +3 -16
  232. package/dist/components/page/ThemeEditorPreview.svelte +11 -13
  233. package/dist/components/page/ThemeEditorPreview.svelte.d.ts +5 -17
  234. package/dist/components/page/ThemeSetEditor.svelte +4 -6
  235. package/dist/components/page/ThemeSetEditor.svelte.d.ts +7 -19
  236. package/dist/components/page/ThemeVariableEditor.svelte +9 -11
  237. package/dist/components/page/ThemeVariableEditor.svelte.d.ts +7 -19
  238. package/dist/components/page/Title.svelte +4 -1
  239. package/dist/components/page/Title.svelte.d.ts +5 -28
  240. package/dist/components/page/Unknown.svelte +11 -8
  241. package/dist/components/page/Unknown.svelte.d.ts +5 -17
  242. package/dist/epub/build.d.ts +39 -0
  243. package/dist/epub/build.js +143 -0
  244. package/dist/epub/build.test.d.ts +1 -0
  245. package/dist/epub/build.test.js +411 -0
  246. package/dist/epub/images.d.ts +79 -0
  247. package/dist/epub/images.js +260 -0
  248. package/dist/epub/images.test.d.ts +1 -0
  249. package/dist/epub/images.test.js +129 -0
  250. package/dist/epub/package.d.ts +75 -0
  251. package/dist/epub/package.js +392 -0
  252. package/dist/epub/stylesheet.test.d.ts +1 -0
  253. package/dist/epub/stylesheet.test.js +243 -0
  254. package/dist/epub/xhtml.d.ts +69 -0
  255. package/dist/epub/xhtml.js +367 -0
  256. package/dist/epub/xhtml.test.d.ts +1 -0
  257. package/dist/epub/xhtml.test.js +283 -0
  258. package/dist/epub/zip.d.ts +35 -0
  259. package/dist/epub/zip.js +202 -0
  260. package/dist/epub/zip.test.d.ts +1 -0
  261. package/dist/epub/zip.test.js +171 -0
  262. package/dist/index.d.ts +1 -0
  263. package/dist/index.js +1 -0
  264. package/dist/models/Firebase.js +18 -4
  265. package/dist/models/book/Book.js +2 -1
  266. package/dist/models/book/BookMedia.js +1 -2
  267. package/dist/models/book/Chapter.js +3 -2
  268. package/dist/models/book/ChapterID.d.ts +1 -1
  269. package/dist/models/book/Edition.d.ts +1 -1
  270. package/dist/models/book/Edition.js +6 -1
  271. package/dist/models/chapter/BlocksNode.js +3 -1
  272. package/dist/models/chapter/BlocksNode.test.js +5 -1
  273. package/dist/models/chapter/Node.test.js +2 -2
  274. package/dist/models/chapter/TextNode.js +8 -5
  275. package/dist/models/chapter/TextNode.test.js +8 -0
  276. package/package.json +36 -22
package/README.md CHANGED
@@ -6,6 +6,50 @@ Bookish is a framework and platform for writing and publishing web-based books.
6
6
 
7
7
  I'm working on a 1.0 of the platform at [bookish.press](https://bookish.press) and expect to maintain the platform for the foreseeable future. Let me know if you'd like to help!
8
8
 
9
+ ## Hosting architecture
10
+
11
+ The app is a SvelteKit app. Server-side rendering runs on a [Cloud Run](https://cloud.google.com/run) service named `bookish-ssr` (region `us-central1`) in each Firebase project; Firebase Hosting serves the static client assets from `build/client` and rewrites everything else to that service (see `firebase.json`). The `stage` and `release` scripts handle both: they build the app locally with the environment-specific `.env` (which is inlined at build time), deploy the resulting `build/` to Cloud Run (see `Dockerfile` and `.gcloudignore`), and then run `firebase deploy` for hosting, rules, and functions.
12
+
13
+ One-time setup on a new machine: install the [gcloud CLI](https://cloud.google.com/sdk/docs/install) and run `gcloud auth login`. (This replaced the experimental Firebase Hosting "web frameworks" integration, which required `firebase experiments:enable webframeworks` and capped the Vite version; the old auto-generated `ssrbookishprod` Cloud Function can be deleted once the Cloud Run deploy is verified.)
14
+
15
+ ## The demo book
16
+
17
+ `npm run demo` seeds a book that uses every feature Bookish has into a set of
18
+ dedicated emulators, then serves it at <http://localhost:5173/demo>. Nothing is
19
+ uploaded and no sign-in is needed to read it; sign in as `demo@example.com` at
20
+ `/login` to edit it at `/write/demo/1`.
21
+
22
+ It exists so a change to the reading experience can be checked against
23
+ something real without hunting for a book that happens to exercise it. The
24
+ chapters cover every Bookdown construct — formatting, links of each kind,
25
+ footnotes, citations, definitions, lists, tables, quotes, callouts, code,
26
+ symbols, labels, comments — and the images are chosen to stress a small screen:
27
+ a photograph with fine texture, a diagram of hairlines, a stepped grey wedge,
28
+ extreme aspect ratios, transparency, and an SVG. That makes it the fastest way
29
+ to see what an EPUB export actually looks like on an e-reader.
30
+
31
+ The content lives in `scripts/demo-book.js` and the images are drawn by
32
+ `scripts/demo-images.js` rather than committed. Chapters must not use the ids
33
+ the reader reserves for its built-in pages (`references`, `search`, `media`,
34
+ `index`, `glossary`, `unknown`, `cover`); the seed script refuses to run if one
35
+ does.
36
+
37
+ It uses the offset emulator ports from `firebase.test.json`, so it does not
38
+ collide with another project's emulators on the default ports, and it builds
39
+ the app rather than running `vite dev` — the reader route's server render pulls
40
+ the chapter model through a module cycle that Vite's dev SSR evaluator cannot
41
+ order, though the production build resolves it fine.
42
+
43
+ ## The demo book
44
+
45
+ `npm run demo` seeds a book that uses every feature Bookish has into a set of dedicated emulators, then serves it at <http://localhost:5173/demo>. Nothing is uploaded and no sign-in is needed to read it; sign in as `demo@example.com` at `/login` to edit it at `/write/demo/1`.
46
+
47
+ It exists so a change to the reading experience can be checked against something real without hunting for a book that happens to exercise it. The chapters cover every Bookdown construct — formatting, links of each kind, footnotes, citations, definitions, lists, tables, quotes, callouts, code, symbols, labels, comments — and the images are chosen to stress a small screen: a photograph with fine texture, a diagram of hairlines, a stepped grey wedge, extreme aspect ratios, transparency, and an SVG. That makes it the fastest way to see what an EPUB export actually looks like on an e-reader.
48
+
49
+ The content lives in `scripts/demo-book.js` and the images are drawn by `scripts/demo-images.js` rather than committed. Chapters must not use the ids the reader reserves for its built-in pages (`references`, `search`, `media`, `index`, `glossary`, `unknown`, `cover`); the seed script refuses to run if one does.
50
+
51
+ It uses the offset emulator ports from `firebase.test.json`, so it doesn't collide with another project's emulators on the default ports, and it builds the app rather than running `vite dev` — the reader route's server render pulls the chapter model through a module cycle that Vite's dev SSR evaluator can't order, though the production build resolves it fine.
52
+
9
53
  ## Deployment notes
10
54
 
11
55
  There are two major components to Bookish: the authoring platform and the reading front end. Changes to the authoring platform that do not affect reading can be verified and deployed to Firebase without any other coordination. However, changes to the reading experience have downstream dependencies that need to be managed. Here's the general deployment workflow, which I'm currently using as reminders for myself:
@@ -13,14 +57,17 @@ There are two major components to Bookish: the authoring platform and the readin
13
57
  0. Ensure you're working in the `dev` branch
14
58
  1. Fix bugs, add features
15
59
  2. Ensure there are no type errors (`npm run check`) or failed tests (`npm run test`).
16
- 2. Test with emulator (`npm run emu`), if possible. (Some features aren't possible to perfectly emulate, such as authentication, hosting configurations, permissions.)
17
- 3. Test on the [staging server](https://bookish-dev-21ac3.web.app/`) (`npm run stage`).
18
- 4. Bump the version in `package.json`
19
- 5. Describe the changes in `CHANGELOG.md`, linking to any issues closed
20
- 6. Commit changes to `dev`, referring to any issues addressed
21
- 7. Release to production (`npm run release`)
22
- 8. Verify the change in production on [bookish.press](https://bookish.press)
23
- 9. Merge dev to main (`npm run merge`)
60
+ 3. Test with emulator (`npm run emu`), if possible. (Some features aren't possible to perfectly emulate, such as authentication, hosting configurations, permissions.)
61
+ 4. Test on the [staging server](https://bookish-dev-21ac3.web.app/`) (`npm run stage`).
62
+ 5. Bump the version in `package.json`
63
+ 6. Describe the changes in `CHANGELOG.md`, linking to any issues closed
64
+ 7. Commit changes to `dev`, referring to any issues addressed
65
+ 8. Release to production (`npm run release`)
66
+ 9. Verify the change in production on [bookish.press](https://bookish.press)
67
+ 10. Merge dev to main (`npm run merge`)
68
+
69
+ > **Svelte 5 note**: as of 0.8.0, `bookish-press` requires Svelte 5 (declared as a peer dependency), which is a breaking change for consumers. Until `bookish-reader` has been migrated to Svelte 5, publish with `npm publish --tag next` so `latest` keeps pointing at the last Svelte 4 compatible release; flip the tag once the reader has migrated. The `0.7.x` branch exists for emergency maintenance releases of the Svelte 4 line.
70
+
24
71
  10. If any of the changes affected the reading experience (essentially if any `.svelte` file or its dependencies in `/src/lib/components` changed), then we need to update the reader package for authors who pre-build their books manually:
25
72
  1. Update the bookish package with the Sveltekit package tooling (`npm run package`)
26
73
  2. Publish the package to npm (`npm publish`)
@@ -33,4 +80,4 @@ There are two major components to Bookish: the authoring platform and the readin
33
80
  1. Cloning the reader repo: `git clone https://github.com/amyjko/bookish-reader`
34
81
  2. Entering the repo directory: `cd bookish-reader`
35
82
  3. Binding the book: `bind.sh`
36
- 4. Deploying the bound book in the newly created `build` folder to wherever it's hosted.
83
+ 4. Deploying the bound book in the newly created `build` folder to wherever it's hosted.
@@ -1,55 +1,45 @@
1
- <script>import { sendSignInLinkToEmail } from 'firebase/auth';
2
- import { onDestroy, setContext } from 'svelte';
3
- import { writable } from 'svelte/store';
4
- import { auth } from '../models/Firebase';
5
- import { USER } from './page/Contexts';
6
- // Track the user and user loading status in state
7
- let loading = true;
8
- // The store that tracks the auth context.
1
+ <script lang="ts">import { sendSignInLinkToEmail } from "firebase/auth";
2
+ import { onDestroy, setContext } from "svelte";
3
+ import { writable } from "svelte/store";
4
+ import { auth } from "../models/Firebase";
5
+ import { USER } from "./page/Contexts";
6
+ let { children } = $props();
7
+ let loading = $state(true);
9
8
  const authentication = writable({
10
- user: null,
11
- loading: loading,
12
- login,
13
- logout,
9
+ user: null,
10
+ loading: true,
11
+ login,
12
+ logout
14
13
  });
15
- // Login using Firebase's password-less email verification
16
14
  async function login(email) {
17
- // If connected to firebase...
18
- if (auth) {
19
- const actionCodeSettings = {
20
- url: location.origin + '/confirm',
21
- handleCodeInApp: true,
22
- };
23
- // Ask Firebase to log in with the given email
24
- await sendSignInLinkToEmail(auth, email, actionCodeSettings);
25
- // Remember the email in local storage so we don't have to ask for it again
26
- // after returning to the link above.
27
- window.localStorage.setItem('email', email);
28
- }
15
+ if (auth) {
16
+ const actionCodeSettings = {
17
+ url: location.origin + "/confirm",
18
+ handleCodeInApp: true
19
+ };
20
+ await sendSignInLinkToEmail(auth, email, actionCodeSettings);
21
+ window.localStorage.setItem("email", email);
22
+ }
29
23
  }
30
24
  function updateAuth(user) {
31
- authentication.set({ user, loading: loading, login, logout });
25
+ authentication.set({ user, loading, login, logout });
32
26
  }
33
- // Logout using Firebase's authentication framework.
34
27
  function logout() {
35
- if (auth) {
36
- return auth.signOut().then(() => updateAuth(null));
37
- }
28
+ if (auth) {
29
+ return auth.signOut().then(() => updateAuth(null));
30
+ }
38
31
  }
39
- // On mount, subscribe to authentication changes.
40
32
  if (auth) {
41
- const unsubscribe = auth.onAuthStateChanged((user) => {
42
- loading = false;
43
- updateAuth(user);
44
- });
45
- // On unmount, stop subscribing.
46
- onDestroy(unsubscribe);
33
+ const unsubscribe = auth.onAuthStateChanged((user) => {
34
+ loading = false;
35
+ updateAuth(user);
36
+ });
37
+ onDestroy(unsubscribe);
47
38
  }
48
- // Expose the state and the login/logout functionality.
49
39
  setContext(USER, authentication);
50
40
  </script>
51
41
 
52
42
  <!-- Wrap whatever children are given in this context. -->
53
43
  {#if loading === false}
54
- <slot />
44
+ {@render children?.()}
55
45
  {/if}
@@ -1,18 +1,6 @@
1
- import { SvelteComponent } from "svelte";
2
- declare const __propDef: {
3
- props: Record<string, never>;
4
- events: {
5
- [evt: string]: CustomEvent<any>;
6
- };
7
- slots: {
8
- default: {};
9
- };
10
- exports?: {} | undefined;
11
- bindings?: string | undefined;
12
- };
13
- export type AuthProps = typeof __propDef.props;
14
- export type AuthEvents = typeof __propDef.events;
15
- export type AuthSlots = typeof __propDef.slots;
16
- export default class Auth extends SvelteComponent<AuthProps, AuthEvents, AuthSlots> {
1
+ interface Props {
2
+ children?: import('svelte').Snippet;
17
3
  }
18
- export {};
4
+ declare const Auth: import("svelte").Component<Props, {}, "">;
5
+ type Auth = ReturnType<typeof Auth>;
6
+ export default Auth;
@@ -1,23 +1,17 @@
1
- <script>import EmbedNode from '../models/chapter/EmbedNode';
2
- import Parser from '../models/chapter/Parser';
3
- import ChapterBody from './chapter/ChapterBody.svelte';
4
- import Embed from './chapter/Embed.svelte';
5
- import Link from './app/Link.svelte';
6
- export let book;
7
- export let write = false;
8
- $: refID = book.getID();
9
- $: cover = book.getCover();
10
- $: authors = book.getAuthors();
11
- $: description = book.getDescription();
12
- $: subdomain = book.getSubdomain();
13
- $: title = book.getTitle();
14
- $: embed = cover === null ? null : Parser.parseEmbed(undefined, cover);
15
- $: url =
16
- subdomain === null || write
17
- ? refID === undefined
18
- ? ''
19
- : (write ? '/write/' : '/') + refID
20
- : `/${subdomain}`;
1
+ <script lang="ts">import EmbedNode from "../models/chapter/EmbedNode";
2
+ import Parser from "../models/chapter/Parser";
3
+ import ChapterBody from "./chapter/ChapterBody.svelte";
4
+ import Embed from "./chapter/Embed.svelte";
5
+ import Link from "./app/Link.svelte";
6
+ let { book, write = false } = $props();
7
+ let refID = $derived(book.getID());
8
+ let cover = $derived(book.getCover());
9
+ let authors = $derived(book.getAuthors());
10
+ let description = $derived(book.getDescription());
11
+ let subdomain = $derived(book.getSubdomain());
12
+ let title = $derived(book.getTitle());
13
+ let embed = $derived(cover === null ? null : Parser.parseEmbed(void 0, cover));
14
+ let url = $derived(subdomain === null || write ? refID === void 0 ? "" : (write ? "/write/" : "/") + refID : `/${subdomain}`);
21
15
  </script>
22
16
 
23
17
  <article class="book-preview">
@@ -1,20 +1,8 @@
1
- import { SvelteComponent } from "svelte";
2
1
  import type Book from '../models/book/Book';
3
- declare const __propDef: {
4
- props: {
5
- book: Book;
6
- write?: boolean;
7
- };
8
- events: {
9
- [evt: string]: CustomEvent<any>;
10
- };
11
- slots: {};
12
- exports?: {} | undefined;
13
- bindings?: string | undefined;
14
- };
15
- export type BookPreviewProps = typeof __propDef.props;
16
- export type BookPreviewEvents = typeof __propDef.events;
17
- export type BookPreviewSlots = typeof __propDef.slots;
18
- export default class BookPreview extends SvelteComponent<BookPreviewProps, BookPreviewEvents, BookPreviewSlots> {
2
+ interface Props {
3
+ book: Book;
4
+ write?: boolean;
19
5
  }
20
- export {};
6
+ declare const BookPreview: import("svelte").Component<Props, {}, "">;
7
+ type BookPreview = ReturnType<typeof BookPreview>;
8
+ export default BookPreview;
@@ -1,41 +1,30 @@
1
- <script>import { page } from '$app/stores';
2
- export let to;
3
- export let linked = true;
4
- let link;
1
+ <script lang="ts">import { page } from "$app/state";
2
+ let { to, linked = true, children } = $props();
3
+ let link = $state();
5
4
  function scroll(event) {
6
- // No element? Bail.
7
- if (link === undefined)
8
- return;
9
- // No hash? No scroll.
10
- const hash = new URL(link.href).hash;
11
- if (hash === '')
12
- return;
13
- // Prevent the browser from scrolling.
14
- event.preventDefault();
15
- // Get the anchor
16
- const anchorId = new URL(link.href).hash.replace('#', '');
17
- const anchor = document.getElementById(anchorId);
18
- // No anchor? Bail.
19
- if (anchor === null)
20
- return;
21
- // Scroll to the anchor.
22
- window.scrollTo({
23
- top: anchor.offsetTop,
24
- behavior: 'smooth',
25
- });
26
- // Update the hash (without scrolling)
27
- history.pushState({}, '', hash);
5
+ if (link === void 0) return;
6
+ const hash = new URL(link.href).hash;
7
+ if (hash === "") return;
8
+ event.preventDefault();
9
+ const anchorId = new URL(link.href).hash.replace("#", "");
10
+ const anchor = document.getElementById(anchorId);
11
+ if (anchor === null) return;
12
+ window.scrollTo({
13
+ top: anchor.offsetTop,
14
+ behavior: "smooth"
15
+ });
16
+ history.pushState({}, "", hash);
28
17
  }
29
18
  </script>
30
19
 
31
- {#if !linked || $page.url.pathname === (to.charAt(to.length - 1) === '/' ? to.substring(0, to.length - 1) : to)}
32
- <slot />
20
+ {#if !linked || page.url.pathname === (to.charAt(to.length - 1) === '/' ? to.substring(0, to.length - 1) : to)}
21
+ {@render children?.()}
33
22
  {:else}
34
23
  <a
35
24
  href={to}
36
25
  bind:this={link}
37
- on:click={(event) => scroll(event)}
38
- target={to.startsWith('http') ? '_blank' : null}><slot /></a
26
+ onclick={(event) => scroll(event)}
27
+ target={to.startsWith('http') ? '_blank' : null}>{@render children?.()}</a
39
28
  >
40
29
  {/if}
41
30
 
@@ -1,21 +1,8 @@
1
- import { SvelteComponent } from "svelte";
2
- declare const __propDef: {
3
- props: {
4
- to: string;
5
- linked?: boolean;
6
- };
7
- events: {
8
- [evt: string]: CustomEvent<any>;
9
- };
10
- slots: {
11
- default: {};
12
- };
13
- exports?: {} | undefined;
14
- bindings?: string | undefined;
15
- };
16
- export type LinkProps = typeof __propDef.props;
17
- export type LinkEvents = typeof __propDef.events;
18
- export type LinkSlots = typeof __propDef.slots;
19
- export default class Link extends SvelteComponent<LinkProps, LinkEvents, LinkSlots> {
1
+ interface Props {
2
+ to: string;
3
+ linked?: boolean;
4
+ children?: import('svelte').Snippet;
20
5
  }
21
- export {};
6
+ declare const Link: import("svelte").Component<Props, {}, "">;
7
+ type Link = ReturnType<typeof Link>;
8
+ export default Link;
@@ -1,6 +1,5 @@
1
- <script>import BookPreview from '../BookPreview.svelte';
2
- export let books;
3
- export let write;
1
+ <script lang="ts">import BookPreview from "../BookPreview.svelte";
2
+ let { books, write } = $props();
4
3
  </script>
5
4
 
6
5
  <section class="previews">
@@ -1,20 +1,8 @@
1
- import { SvelteComponent } from "svelte";
2
1
  import type Book from '../../models/book/Book';
3
- declare const __propDef: {
4
- props: {
5
- books: Book[];
6
- write: boolean;
7
- };
8
- events: {
9
- [evt: string]: CustomEvent<any>;
10
- };
11
- slots: {};
12
- exports?: {} | undefined;
13
- bindings?: string | undefined;
14
- };
15
- export type BookListProps = typeof __propDef.props;
16
- export type BookListEvents = typeof __propDef.events;
17
- export type BookListSlots = typeof __propDef.slots;
18
- export default class BookList extends SvelteComponent<BookListProps, BookListEvents, BookListSlots> {
2
+ interface Props {
3
+ books: Book[];
4
+ write: boolean;
19
5
  }
20
- export {};
6
+ declare const BookList: import("svelte").Component<Props, {}, "">;
7
+ type BookList = ReturnType<typeof BookList>;
8
+ export default BookList;
@@ -1,20 +1,24 @@
1
- <script>export let type = null;
2
- export let tooltip;
3
- export let disabled = false;
4
- export let command;
1
+ <script lang="ts">let {
2
+ type = null,
3
+ tooltip,
4
+ disabled = false,
5
+ command,
6
+ class: classes,
7
+ children
8
+ } = $props();
5
9
  </script>
6
10
 
7
11
  <button
8
- class={$$props.class}
12
+ class={classes}
9
13
  title={tooltip}
10
14
  aria-label={tooltip}
11
15
  {type}
12
16
  {disabled}
13
- on:mousedown={command}
14
- on:keypress={(event) =>
17
+ onmousedown={command}
18
+ onkeypress={(event) =>
15
19
  event.key === ' ' || event.key === 'Enter' ? command() : undefined}
16
20
  >
17
- <slot />
21
+ {@render children?.()}
18
22
  </button>
19
23
 
20
24
  <style>
@@ -1,24 +1,11 @@
1
- import { SvelteComponent } from "svelte";
2
- declare const __propDef: {
3
- props: {
4
- [x: string]: any;
5
- type?: "submit" | "button" | null | undefined;
6
- tooltip: string;
7
- disabled?: boolean | undefined;
8
- command: () => void;
9
- };
10
- events: {
11
- [evt: string]: CustomEvent<any>;
12
- };
13
- slots: {
14
- default: {};
15
- };
16
- exports?: undefined;
17
- bindings?: undefined;
18
- };
19
- export type ButtonProps = typeof __propDef.props;
20
- export type ButtonEvents = typeof __propDef.events;
21
- export type ButtonSlots = typeof __propDef.slots;
22
- export default class Button extends SvelteComponent<ButtonProps, ButtonEvents, ButtonSlots> {
1
+ interface Props {
2
+ type?: 'submit' | 'button' | null;
3
+ tooltip: string;
4
+ disabled?: boolean;
5
+ command: () => void;
6
+ class?: string;
7
+ children?: import('svelte').Snippet;
23
8
  }
24
- export {};
9
+ declare const Button: import("svelte").Component<Props, {}, "">;
10
+ type Button = ReturnType<typeof Button>;
11
+ export default Button;
@@ -1,11 +1,11 @@
1
- <script>import Large from './Large.svelte';
2
- export let error = false;
1
+ <script lang="ts">import Large from "./Large.svelte";
2
+ let { error = false, children } = $props();
3
3
  </script>
4
4
 
5
5
  {#if error}
6
- <p role="alert"><slot /></p>
6
+ <p role="alert">{@render children?.()}</p>
7
7
  {:else}
8
- <p role="status" aria-live="polite"><Large><slot /></Large></p>
8
+ <p role="status" aria-live="polite"><Large>{@render children?.()}</Large></p>
9
9
  {/if}
10
10
 
11
11
  <style>
@@ -1,20 +1,7 @@
1
- import { SvelteComponent } from "svelte";
2
- declare const __propDef: {
3
- props: {
4
- error?: boolean;
5
- };
6
- events: {
7
- [evt: string]: CustomEvent<any>;
8
- };
9
- slots: {
10
- default: {};
11
- };
12
- exports?: {} | undefined;
13
- bindings?: string | undefined;
14
- };
15
- export type FeedbackProps = typeof __propDef.props;
16
- export type FeedbackEvents = typeof __propDef.events;
17
- export type FeedbackSlots = typeof __propDef.slots;
18
- export default class Feedback extends SvelteComponent<FeedbackProps, FeedbackEvents, FeedbackSlots> {
1
+ interface Props {
2
+ error?: boolean;
3
+ children?: import('svelte').Snippet;
19
4
  }
20
- export {};
5
+ declare const Feedback: import("svelte").Component<Props, {}, "">;
6
+ type Feedback = ReturnType<typeof Feedback>;
7
+ export default Feedback;
@@ -1,7 +1,7 @@
1
- <script>export let id = null;
1
+ <script lang="ts">let { id = null, children } = $props();
2
2
  </script>
3
3
 
4
- <h2 {id}><slot /></h2>
4
+ <h2 {id}>{@render children?.()}</h2>
5
5
 
6
6
  <style>
7
7
  h2 {
@@ -1,20 +1,7 @@
1
- import { SvelteComponent } from "svelte";
2
- declare const __propDef: {
3
- props: {
4
- id?: string | null;
5
- };
6
- events: {
7
- [evt: string]: CustomEvent<any>;
8
- };
9
- slots: {
10
- default: {};
11
- };
12
- exports?: {} | undefined;
13
- bindings?: string | undefined;
14
- };
15
- export type HeadProps = typeof __propDef.props;
16
- export type HeadEvents = typeof __propDef.events;
17
- export type HeadSlots = typeof __propDef.slots;
18
- export default class Head extends SvelteComponent<HeadProps, HeadEvents, HeadSlots> {
1
+ interface Props {
2
+ id?: string | null;
3
+ children?: import('svelte').Snippet;
19
4
  }
20
- export {};
5
+ declare const Head: import("svelte").Component<Props, {}, "">;
6
+ type Head = ReturnType<typeof Head>;
7
+ export default Head;
@@ -1,4 +1,7 @@
1
- <span><slot /></span>
1
+ <script lang="ts">let { children } = $props();
2
+ </script>
3
+
4
+ <span>{@render children?.()}</span>
2
5
 
3
6
  <style>
4
7
  span {
@@ -1,29 +1,6 @@
1
- /** @typedef {typeof __propDef.props} LargeProps */
2
- /** @typedef {typeof __propDef.events} LargeEvents */
3
- /** @typedef {typeof __propDef.slots} LargeSlots */
4
- export default class Large extends SvelteComponent<{
5
- [x: string]: never;
6
- }, {
7
- [evt: string]: CustomEvent<any>;
8
- }, {
9
- default: {};
10
- }> {
1
+ interface Props {
2
+ children?: import('svelte').Snippet;
11
3
  }
12
- export type LargeProps = typeof __propDef.props;
13
- export type LargeEvents = typeof __propDef.events;
14
- export type LargeSlots = typeof __propDef.slots;
15
- import { SvelteComponent } from "svelte";
16
- declare const __propDef: {
17
- props: {
18
- [x: string]: never;
19
- };
20
- events: {
21
- [evt: string]: CustomEvent<any>;
22
- };
23
- slots: {
24
- default: {};
25
- };
26
- exports?: undefined;
27
- bindings?: undefined;
28
- };
29
- export {};
4
+ declare const Large: import("svelte").Component<Props, {}, "">;
5
+ type Large = ReturnType<typeof Large>;
6
+ export default Large;
@@ -1,4 +1,7 @@
1
- <h1><slot /></h1>
1
+ <script lang="ts">let { children } = $props();
2
+ </script>
3
+
4
+ <h1>{@render children?.()}</h1>
2
5
 
3
6
  <style>
4
7
  h1 {
@@ -1,29 +1,6 @@
1
- /** @typedef {typeof __propDef.props} LeadProps */
2
- /** @typedef {typeof __propDef.events} LeadEvents */
3
- /** @typedef {typeof __propDef.slots} LeadSlots */
4
- export default class Lead extends SvelteComponent<{
5
- [x: string]: never;
6
- }, {
7
- [evt: string]: CustomEvent<any>;
8
- }, {
9
- default: {};
10
- }> {
1
+ interface Props {
2
+ children?: import('svelte').Snippet;
11
3
  }
12
- export type LeadProps = typeof __propDef.props;
13
- export type LeadEvents = typeof __propDef.events;
14
- export type LeadSlots = typeof __propDef.slots;
15
- import { SvelteComponent } from "svelte";
16
- declare const __propDef: {
17
- props: {
18
- [x: string]: never;
19
- };
20
- events: {
21
- [evt: string]: CustomEvent<any>;
22
- };
23
- slots: {
24
- default: {};
25
- };
26
- exports?: undefined;
27
- bindings?: undefined;
28
- };
29
- export {};
4
+ declare const Lead: import("svelte").Component<Props, {}, "">;
5
+ type Lead = ReturnType<typeof Lead>;
6
+ export default Lead;