bookish-press 0.4.45 → 0.4.47

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 (533) hide show
  1. package/.env.example +8 -0
  2. package/.firebaserc +8 -0
  3. package/.prettierignore +8 -0
  4. package/.prettierrc.json +5 -0
  5. package/_update-notifier-last-checked +0 -0
  6. package/firebase.json +46 -0
  7. package/firestore.indexes.json +4 -0
  8. package/firestore.rules +59 -0
  9. package/functions/.eslintrc.js +28 -0
  10. package/functions/package-lock.json +12595 -0
  11. package/functions/package.json +43 -0
  12. package/functions/src/index.ts +345 -0
  13. package/functions/tsconfig.dev.json +3 -0
  14. package/functions/tsconfig.json +15 -0
  15. package/package.json +53 -270
  16. package/scripts/claims.cjs +99 -0
  17. package/src/app.d.ts +9 -0
  18. package/src/app.html +24 -0
  19. package/src/lib/components/Auth.svelte +65 -0
  20. package/{components/Authentication.d.ts → src/lib/components/Authentication.ts} +2 -0
  21. package/{components → src/lib/components}/BookPreview.svelte +27 -22
  22. package/{components → src/lib/components}/External.svelte +2 -1
  23. package/src/lib/components/Link.svelte +58 -0
  24. package/{components → src/lib/components}/app/BookList.svelte +6 -3
  25. package/{components → src/lib/components}/app/Button.svelte +5 -4
  26. package/{components → src/lib/components}/app/Feedback.svelte +11 -7
  27. package/{components → src/lib/components}/app/Head.svelte +2 -1
  28. package/{components → src/lib/components}/app/Large.svelte +0 -0
  29. package/{components → src/lib/components}/app/Lead.svelte +0 -0
  30. package/{components → src/lib/components}/app/Link.svelte +4 -3
  31. package/{components → src/lib/components}/app/Options.svelte +5 -4
  32. package/{components → src/lib/components}/app/Paragraph.svelte +2 -1
  33. package/{components → src/lib/components}/app/Section.svelte +0 -0
  34. package/{components → src/lib/components}/app/Table.svelte +0 -0
  35. package/{components → src/lib/components}/app/TextInput.svelte +12 -9
  36. package/{components → src/lib/components}/chapter/Atom.svelte +18 -12
  37. package/src/lib/components/chapter/Block.svelte +42 -0
  38. package/{components → src/lib/components}/chapter/Callout.svelte +6 -3
  39. package/{components → src/lib/components}/chapter/CaptionedCode.svelte +21 -13
  40. package/{components → src/lib/components}/chapter/ChapterBody.svelte +13 -9
  41. package/{components → src/lib/components}/chapter/Citations.svelte +34 -33
  42. package/{components → src/lib/components}/chapter/Code.svelte +63 -58
  43. package/{components → src/lib/components}/chapter/Comment.svelte +30 -18
  44. package/{components → src/lib/components}/chapter/Definition.svelte +23 -17
  45. package/{components → src/lib/components}/chapter/Embed.svelte +97 -77
  46. package/src/lib/components/chapter/ErrorMessage.svelte +12 -0
  47. package/{components → src/lib/components}/chapter/ExtendedPrism.js +0 -0
  48. package/{components → src/lib/components}/chapter/Figure.svelte +34 -26
  49. package/{components → src/lib/components}/chapter/Footnote.svelte +32 -20
  50. package/{components → src/lib/components}/chapter/Format.svelte +39 -34
  51. package/{components → src/lib/components}/chapter/InlineCode.svelte +9 -5
  52. package/{components → src/lib/components}/chapter/Label.svelte +23 -14
  53. package/{components → src/lib/components}/chapter/Link.svelte +27 -21
  54. package/{components → src/lib/components}/chapter/List.svelte +5 -3
  55. package/{components → src/lib/components}/chapter/Marginal.svelte +54 -41
  56. package/{components → src/lib/components}/chapter/Paragraph.svelte +25 -20
  57. package/{components → src/lib/components}/chapter/Positioned.svelte +4 -1
  58. package/{components → src/lib/components}/chapter/Problem.svelte +0 -0
  59. package/src/lib/components/chapter/Python.svelte +144 -0
  60. package/{components → src/lib/components}/chapter/Quote.svelte +9 -5
  61. package/{components → src/lib/components}/chapter/Rule.svelte +4 -1
  62. package/{components → src/lib/components}/chapter/Table.svelte +11 -7
  63. package/src/lib/components/chapter/Text.svelte +109 -0
  64. package/src/lib/components/editor/BookishEditor.svelte +1101 -0
  65. package/src/lib/components/editor/CalloutEditor.svelte +14 -0
  66. package/{components → src/lib/components}/editor/CaptionedCodeEditor.svelte +10 -6
  67. package/src/lib/components/editor/CaretContext.ts +55 -0
  68. package/{components/editor/CaretState.d.ts → src/lib/components/editor/CaretState.ts} +6 -7
  69. package/{components/editor/CaretUtilities.d.ts → src/lib/components/editor/CaretUtilities.ts} +1 -0
  70. package/{components → src/lib/components}/editor/CaretView.svelte +25 -20
  71. package/src/lib/components/editor/CitationsEditor.svelte +64 -0
  72. package/{components/editor/Clipboard.d.ts → src/lib/components/editor/Clipboard.ts} +2 -1
  73. package/{components/editor/Command.d.ts → src/lib/components/editor/Command.ts} +8 -2
  74. package/{components/editor/Commands.js → src/lib/components/editor/Commands.ts} +730 -315
  75. package/src/lib/components/editor/ConfirmButton.svelte +51 -0
  76. package/src/lib/components/editor/DefinitionEditor.svelte +44 -0
  77. package/src/lib/components/editor/EmbedEditor.svelte +152 -0
  78. package/{components → src/lib/components}/editor/Icon.svelte +2 -1
  79. package/{components → src/lib/components}/editor/ImageChooser.svelte +24 -19
  80. package/src/lib/components/editor/InlineCodeEditor.svelte +16 -0
  81. package/{components → src/lib/components}/editor/LabelEditor.svelte +14 -9
  82. package/{components → src/lib/components}/editor/LanguageEditor.svelte +8 -5
  83. package/src/lib/components/editor/LinkEditor.svelte +110 -0
  84. package/{components → src/lib/components}/editor/Note.svelte +0 -0
  85. package/{components → src/lib/components}/editor/Permissions.svelte +43 -36
  86. package/src/lib/components/editor/PositionEditor.svelte +21 -0
  87. package/src/lib/components/editor/QuoteEditor.svelte +14 -0
  88. package/{components → src/lib/components}/editor/Switch.svelte +14 -11
  89. package/src/lib/components/editor/TableEditor.svelte +14 -0
  90. package/{components → src/lib/components}/editor/TextEditor.svelte +101 -89
  91. package/src/lib/components/editor/Toggle.svelte +47 -0
  92. package/src/lib/components/editor/Toolbar.svelte +297 -0
  93. package/{components → src/lib/components}/editor/ToolbarGroup.svelte +5 -3
  94. package/{components → src/lib/components}/editor/ToolbarSpacer.svelte +0 -0
  95. package/src/lib/components/editor/URLEditor.svelte +15 -0
  96. package/{components/editor/UndoState.d.ts → src/lib/components/editor/UndoState.ts} +3 -2
  97. package/{components → src/lib/components}/editor/icons/annotate.svg +0 -0
  98. package/{components → src/lib/components}/editor/icons/block.svg +0 -0
  99. package/{components → src/lib/components}/editor/icons/bold.svg +0 -0
  100. package/{components → src/lib/components}/editor/icons/bullets.svg +0 -0
  101. package/{components → src/lib/components}/editor/icons/callout.svg +0 -0
  102. package/{components → src/lib/components}/editor/icons/citation.svg +0 -0
  103. package/{components → src/lib/components}/editor/icons/clear.svg +0 -0
  104. package/{components → src/lib/components}/editor/icons/clipboard.svg +0 -0
  105. package/{components → src/lib/components}/editor/icons/code.svg +0 -0
  106. package/{components → src/lib/components}/editor/icons/columnafter.svg +0 -0
  107. package/{components → src/lib/components}/editor/icons/columnbefore.svg +0 -0
  108. package/{components → src/lib/components}/editor/icons/comment.svg +0 -0
  109. package/{components → src/lib/components}/editor/icons/copy.svg +0 -0
  110. package/{components → src/lib/components}/editor/icons/cut.svg +0 -0
  111. package/{components → src/lib/components}/editor/icons/define.svg +0 -0
  112. package/{components → src/lib/components}/editor/icons/deletecolumn.svg +0 -0
  113. package/{components → src/lib/components}/editor/icons/deleterow.svg +0 -0
  114. package/{components → src/lib/components}/editor/icons/footnote.svg +0 -0
  115. package/{components → src/lib/components}/editor/icons/header1.svg +0 -0
  116. package/{components → src/lib/components}/editor/icons/header2.svg +0 -0
  117. package/{components → src/lib/components}/editor/icons/header3.svg +0 -0
  118. package/{components → src/lib/components}/editor/icons/home.svg +0 -0
  119. package/{components → src/lib/components}/editor/icons/indent.svg +0 -0
  120. package/{components → src/lib/components}/editor/icons/italic.svg +0 -0
  121. package/{components → src/lib/components}/editor/icons/label.svg +0 -0
  122. package/{components → src/lib/components}/editor/icons/left.svg +0 -0
  123. package/{components → src/lib/components}/editor/icons/level.svg +0 -0
  124. package/{components → src/lib/components}/editor/icons/link.svg +0 -0
  125. package/{components → src/lib/components}/editor/icons/list.svg +0 -0
  126. package/{components → src/lib/components}/editor/icons/media.svg +0 -0
  127. package/{components → src/lib/components}/editor/icons/middle.svg +0 -0
  128. package/{components → src/lib/components}/editor/icons/numbers.svg +0 -0
  129. package/{components → src/lib/components}/editor/icons/paragraph.svg +0 -0
  130. package/{components → src/lib/components}/editor/icons/paste.svg +0 -0
  131. package/{components → src/lib/components}/editor/icons/quote.svg +0 -0
  132. package/{components → src/lib/components}/editor/icons/redo.svg +0 -0
  133. package/{components → src/lib/components}/editor/icons/right.svg +0 -0
  134. package/{components → src/lib/components}/editor/icons/rowabove.svg +0 -0
  135. package/{components → src/lib/components}/editor/icons/rowbelow.svg +0 -0
  136. package/{components → src/lib/components}/editor/icons/rule.svg +0 -0
  137. package/{components → src/lib/components}/editor/icons/sub.svg +0 -0
  138. package/{components → src/lib/components}/editor/icons/super.svg +0 -0
  139. package/{components → src/lib/components}/editor/icons/table.svg +0 -0
  140. package/{components → src/lib/components}/editor/icons/text.svg +0 -0
  141. package/{components → src/lib/components}/editor/icons/time.svg +0 -0
  142. package/{components → src/lib/components}/editor/icons/undo.svg +0 -0
  143. package/{components → src/lib/components}/editor/icons/unindent.svg +0 -0
  144. package/{components → src/lib/components}/editor/icons/unlink.svg +0 -0
  145. package/{components → src/lib/components}/page/Acknowledgements.svelte +19 -10
  146. package/src/lib/components/page/Authors.svelte +92 -0
  147. package/src/lib/components/page/BookLoader.svelte +77 -0
  148. package/src/lib/components/page/BulkReferenceEditor.svelte +86 -0
  149. package/src/lib/components/page/Chapter.svelte +449 -0
  150. package/src/lib/components/page/ChapterContext.ts +13 -0
  151. package/{components → src/lib/components}/page/ChapterNumber.svelte +0 -0
  152. package/{components → src/lib/components}/page/ChapterTitle.svelte +4 -2
  153. package/src/lib/components/page/Contexts.ts +176 -0
  154. package/{components → src/lib/components}/page/DefinitionView.svelte +52 -37
  155. package/{components → src/lib/components}/page/Description.svelte +15 -7
  156. package/src/lib/components/page/Edition.svelte +189 -0
  157. package/src/lib/components/page/EditionLoader.svelte +123 -0
  158. package/{components → src/lib/components}/page/Editions.svelte +22 -18
  159. package/{components → src/lib/components}/page/Glossary.svelte +33 -28
  160. package/{components → src/lib/components}/page/Header.svelte +59 -52
  161. package/{components → src/lib/components}/page/Index.svelte +48 -41
  162. package/{components → src/lib/components}/page/Instructions.svelte +2 -1
  163. package/{components → src/lib/components}/page/License.svelte +17 -9
  164. package/{components → src/lib/components}/page/Loading.svelte +0 -0
  165. package/{components → src/lib/components}/page/Media.svelte +44 -27
  166. package/{components → src/lib/components}/page/MediaPreview.svelte +3 -2
  167. package/{components → src/lib/components}/page/Muted.svelte +0 -0
  168. package/{components → src/lib/components}/page/Outline.svelte +140 -110
  169. package/src/lib/components/page/Page.svelte +94 -0
  170. package/{components → src/lib/components}/page/PageHeader.svelte +2 -1
  171. package/{components → src/lib/components}/page/PageParagraph.svelte +0 -0
  172. package/src/lib/components/page/PossibleChapter.svelte +16 -0
  173. package/src/lib/components/page/PossibleReference.svelte +14 -0
  174. package/{components → src/lib/components}/page/Print.svelte +5 -3
  175. package/{components → src/lib/components}/page/Publish.svelte +59 -52
  176. package/{components → src/lib/components}/page/Reference.svelte +39 -30
  177. package/{components → src/lib/components}/page/References.svelte +18 -14
  178. package/{components → src/lib/components}/page/Rows.svelte +0 -0
  179. package/src/lib/components/page/Search.svelte +153 -0
  180. package/{components → src/lib/components}/page/Status.svelte +5 -3
  181. package/{components → src/lib/components}/page/SubdomainEditor.svelte +16 -13
  182. package/{components → src/lib/components}/page/TableOfContents.svelte +79 -68
  183. package/src/lib/components/page/TableOfContentsImage.svelte +22 -0
  184. package/{components → src/lib/components}/page/TableOfContentsRow.svelte +34 -24
  185. package/{components → src/lib/components}/page/ThemeEditor.svelte +44 -33
  186. package/{components → src/lib/components}/page/ThemeEditorPreview.svelte +21 -12
  187. package/src/lib/components/page/ThemeSetEditor.svelte +21 -0
  188. package/{components → src/lib/components}/page/ThemeVariableEditor.svelte +18 -14
  189. package/{components → src/lib/components}/page/Title.svelte +0 -0
  190. package/{components → src/lib/components}/page/Unknown.svelte +10 -8
  191. package/{components/page/margins.js → src/lib/components/page/margins.ts} +79 -46
  192. package/{index.js → src/lib/index.js} +0 -0
  193. package/src/lib/models/CRUD.ts +469 -0
  194. package/{models/Firebase.js → src/lib/models/Firebase.ts} +26 -16
  195. package/src/lib/models/book/Book.ts +283 -0
  196. package/src/lib/models/book/BookMedia.ts +182 -0
  197. package/src/lib/models/book/BookSaveStatus.ts +8 -0
  198. package/src/lib/models/book/Chapter.ts +462 -0
  199. package/{models/book/ChapterID.js → src/lib/models/book/ChapterID.ts} +1 -0
  200. package/src/lib/models/book/Definition.ts +2 -0
  201. package/src/lib/models/book/Edition.ts +1216 -0
  202. package/src/lib/models/book/Reference.ts +171 -0
  203. package/{models/book/Schema.js → src/lib/models/book/Schema.ts} +1 -0
  204. package/{models/book/Theme.js → src/lib/models/book/Theme.ts} +111 -6
  205. package/{models/book/ThemeColors.d.ts → src/lib/models/book/ThemeColors.ts} +6 -0
  206. package/{models/book/Words.js → src/lib/models/book/Words.ts} +1 -0
  207. package/{models/chapter/AtomNode.js → src/lib/models/chapter/AtomNode.ts} +30 -10
  208. package/{models/chapter/BlockNode.js → src/lib/models/chapter/BlockNode.ts} +80 -47
  209. package/src/lib/models/chapter/BlocksNode.test.ts +867 -0
  210. package/{models/chapter/BlocksNode.js → src/lib/models/chapter/BlocksNode.ts} +571 -359
  211. package/{models/chapter/Bookkeeping.d.ts → src/lib/models/chapter/Bookkeeping.ts} +0 -0
  212. package/src/lib/models/chapter/CalloutNode.ts +79 -0
  213. package/{models/chapter/Caret.js → src/lib/models/chapter/Caret.ts} +50 -26
  214. package/src/lib/models/chapter/ChapterNode.ts +169 -0
  215. package/{models/chapter/CitationsNode.js → src/lib/models/chapter/CitationsNode.ts} +17 -10
  216. package/{models/chapter/CodeNode.js → src/lib/models/chapter/CodeNode.ts} +125 -62
  217. package/src/lib/models/chapter/CommentNode.ts +61 -0
  218. package/{models/chapter/DefinitionNode.js → src/lib/models/chapter/DefinitionNode.ts} +14 -8
  219. package/src/lib/models/chapter/Edit.ts +6 -0
  220. package/src/lib/models/chapter/EmbedNode.ts +257 -0
  221. package/{models/chapter/ErrorNode.js → src/lib/models/chapter/ErrorNode.ts} +15 -8
  222. package/src/lib/models/chapter/FootnoteNode.ts +59 -0
  223. package/src/lib/models/chapter/FormatNode.test.ts +137 -0
  224. package/{models/chapter/FormatNode.js → src/lib/models/chapter/FormatNode.ts} +443 -262
  225. package/{models/chapter/InlineCodeNode.js → src/lib/models/chapter/InlineCodeNode.ts} +17 -9
  226. package/{models/chapter/LabelNode.js → src/lib/models/chapter/LabelNode.ts} +26 -10
  227. package/{models/chapter/LinkNode.js → src/lib/models/chapter/LinkNode.ts} +12 -7
  228. package/{models/chapter/ListNode.test.js → src/lib/models/chapter/ListNode.test.ts} +57 -20
  229. package/{models/chapter/ListNode.js → src/lib/models/chapter/ListNode.ts} +277 -200
  230. package/src/lib/models/chapter/MetadataNode.ts +44 -0
  231. package/{models → src/lib/models}/chapter/Node.test.js +0 -0
  232. package/{models/chapter/Node.js → src/lib/models/chapter/Node.ts} +155 -71
  233. package/src/lib/models/chapter/ParagraphNode.test.ts +54 -0
  234. package/{models/chapter/ParagraphNode.js → src/lib/models/chapter/ParagraphNode.ts} +95 -58
  235. package/{models/chapter/Parser.test.js → src/lib/models/chapter/Parser.test.ts} +7 -0
  236. package/{models/chapter/Parser.js → src/lib/models/chapter/Parser.ts} +369 -184
  237. package/{models/chapter/Position.d.ts → src/lib/models/chapter/Position.ts} +0 -0
  238. package/src/lib/models/chapter/QuoteNode.ts +135 -0
  239. package/{models/chapter/RootNode.d.ts → src/lib/models/chapter/RootNode.ts} +2 -0
  240. package/{models/chapter/RuleNode.js → src/lib/models/chapter/RuleNode.ts} +9 -6
  241. package/{models/chapter/TableNode.test.js → src/lib/models/chapter/TableNode.test.ts} +27 -10
  242. package/{models/chapter/TableNode.js → src/lib/models/chapter/TableNode.ts} +141 -82
  243. package/{models/chapter/TextNode.test.js → src/lib/models/chapter/TextNode.test.ts} +2 -0
  244. package/{models/chapter/TextNode.js → src/lib/models/chapter/TextNode.ts} +117 -65
  245. package/{util/getSubdomain.js → src/lib/util/getSubdomain.ts} +14 -8
  246. package/{util/isMobile.js → src/lib/util/isMobile.ts} +1 -0
  247. package/{util/mineReference.js → src/lib/util/mineReference.ts} +45 -25
  248. package/{util/scrollToEyeLevel.js → src/lib/util/scrollToEyeLevel.ts} +4 -2
  249. package/src/params/edition.ts +3 -0
  250. package/src/routes/+error.svelte +12 -0
  251. package/src/routes/+layout.svelte +241 -0
  252. package/src/routes/+page.svelte +43 -0
  253. package/src/routes/Footer.svelte +0 -0
  254. package/src/routes/Header.svelte +112 -0
  255. package/src/routes/[bookid]/+layout.svelte +5 -0
  256. package/src/routes/[bookid]/[[editionid=edition]]/+error.svelte +14 -0
  257. package/src/routes/[bookid]/[[editionid=edition]]/+layout.svelte +7 -0
  258. package/src/routes/[bookid]/[[editionid=edition]]/+page.svelte +5 -0
  259. package/src/routes/[bookid]/[[editionid=edition]]/[chapterid]/+page.svelte +5 -0
  260. package/src/routes/[bookid]/[[editionid=edition]]/glossary/+page.svelte +5 -0
  261. package/src/routes/[bookid]/[[editionid=edition]]/index/[[letter]]/+page.svelte +5 -0
  262. package/src/routes/[bookid]/[[editionid=edition]]/media/+page.svelte +5 -0
  263. package/src/routes/[bookid]/[[editionid=edition]]/print/+page.svelte +5 -0
  264. package/src/routes/[bookid]/[[editionid=edition]]/references/+page.svelte +5 -0
  265. package/src/routes/[bookid]/[[editionid=edition]]/search/+page.svelte +5 -0
  266. package/src/routes/[bookid]/editions/+page.svelte +20 -0
  267. package/src/routes/about/+page.svelte +102 -0
  268. package/src/routes/confirm/+page.svelte +62 -0
  269. package/src/routes/email/+page.svelte +99 -0
  270. package/src/routes/login/+page.svelte +66 -0
  271. package/src/routes/read/+page.svelte +38 -0
  272. package/src/routes/write/+error.svelte +10 -0
  273. package/src/routes/write/+layout.svelte +11 -0
  274. package/src/routes/write/+page.svelte +114 -0
  275. package/src/routes/write/[bookid]/+layout.svelte +5 -0
  276. package/src/routes/write/[bookid]/[[editionid=edition]]/+layout.svelte +7 -0
  277. package/src/routes/write/[bookid]/[[editionid=edition]]/+page.svelte +5 -0
  278. package/src/routes/write/[bookid]/[[editionid=edition]]/[chapterid]/+page.svelte +5 -0
  279. package/src/routes/write/[bookid]/[[editionid=edition]]/glossary/+page.svelte +5 -0
  280. package/src/routes/write/[bookid]/[[editionid=edition]]/index/[[letter]]/+page.svelte +5 -0
  281. package/src/routes/write/[bookid]/[[editionid=edition]]/media/+page.svelte +5 -0
  282. package/src/routes/write/[bookid]/[[editionid=edition]]/print/+page.svelte +5 -0
  283. package/src/routes/write/[bookid]/[[editionid=edition]]/references/+page.svelte +5 -0
  284. package/src/routes/write/[bookid]/[[editionid=edition]]/search/+page.svelte +5 -0
  285. package/src/routes/write/[bookid]/[[editionid=edition]]/theme/+page.svelte +5 -0
  286. package/src/routes/write/[bookid]/[[editionid=edition]]/unknown/+page.svelte +5 -0
  287. package/src/routes/write/[bookid]/editions/+page.svelte +20 -0
  288. package/src/vite-env.d.ts +1 -0
  289. package/static/icons/favicon.png +0 -0
  290. package/static/icons/icon.png +0 -0
  291. package/static/icons/ios-icon.png +0 -0
  292. package/storage.rules +9 -0
  293. package/svelte.config.js +19 -0
  294. package/tsconfig.json +18 -0
  295. package/tsconfig.node.json +9 -0
  296. package/vite.config.ts +8 -0
  297. package/vite.reader.config.ts +32 -0
  298. package/components/Auth.svelte +0 -55
  299. package/components/Auth.svelte.d.ts +0 -16
  300. package/components/Authentication.js +0 -1
  301. package/components/BookPreview.svelte.d.ts +0 -18
  302. package/components/External.svelte.d.ts +0 -18
  303. package/components/Link.svelte +0 -51
  304. package/components/Link.svelte.d.ts +0 -18
  305. package/components/app/BookList.svelte.d.ts +0 -18
  306. package/components/app/Button.svelte.d.ts +0 -22
  307. package/components/app/Feedback.svelte.d.ts +0 -18
  308. package/components/app/Head.svelte.d.ts +0 -18
  309. package/components/app/Large.svelte.d.ts +0 -27
  310. package/components/app/Lead.svelte.d.ts +0 -27
  311. package/components/app/Link.svelte.d.ts +0 -20
  312. package/components/app/Options.svelte.d.ts +0 -19
  313. package/components/app/Paragraph.svelte.d.ts +0 -18
  314. package/components/app/Section.svelte.d.ts +0 -27
  315. package/components/app/Table.svelte.d.ts +0 -27
  316. package/components/app/TextInput.svelte.d.ts +0 -22
  317. package/components/chapter/Atom.svelte.d.ts +0 -19
  318. package/components/chapter/Block.svelte +0 -37
  319. package/components/chapter/Block.svelte.d.ts +0 -17
  320. package/components/chapter/Callout.svelte.d.ts +0 -17
  321. package/components/chapter/CaptionedCode.svelte.d.ts +0 -17
  322. package/components/chapter/ChapterBody.svelte.d.ts +0 -19
  323. package/components/chapter/Citations.svelte.d.ts +0 -17
  324. package/components/chapter/Code.svelte.d.ts +0 -22
  325. package/components/chapter/Comment.svelte.d.ts +0 -17
  326. package/components/chapter/Definition.svelte.d.ts +0 -17
  327. package/components/chapter/Embed.svelte.d.ts +0 -20
  328. package/components/chapter/ErrorMessage.svelte +0 -9
  329. package/components/chapter/ErrorMessage.svelte.d.ts +0 -17
  330. package/components/chapter/ExtendedPrism.d.ts +0 -2
  331. package/components/chapter/Figure.svelte.d.ts +0 -24
  332. package/components/chapter/Footnote.svelte.d.ts +0 -19
  333. package/components/chapter/Format.svelte.d.ts +0 -19
  334. package/components/chapter/InlineCode.svelte.d.ts +0 -17
  335. package/components/chapter/Label.svelte.d.ts +0 -17
  336. package/components/chapter/Link.svelte.d.ts +0 -17
  337. package/components/chapter/List.svelte.d.ts +0 -17
  338. package/components/chapter/Marginal.svelte.d.ts +0 -22
  339. package/components/chapter/Paragraph.svelte.d.ts +0 -18
  340. package/components/chapter/Positioned.svelte.d.ts +0 -19
  341. package/components/chapter/Problem.svelte.d.ts +0 -27
  342. package/components/chapter/Python.svelte +0 -128
  343. package/components/chapter/Python.svelte.d.ts +0 -18
  344. package/components/chapter/Quote.svelte.d.ts +0 -17
  345. package/components/chapter/Rule.svelte.d.ts +0 -17
  346. package/components/chapter/Table.svelte.d.ts +0 -17
  347. package/components/chapter/Text.svelte +0 -87
  348. package/components/chapter/Text.svelte.d.ts +0 -18
  349. package/components/editor/BookishEditor.svelte +0 -884
  350. package/components/editor/BookishEditor.svelte.d.ts +0 -25
  351. package/components/editor/CalloutEditor.svelte +0 -10
  352. package/components/editor/CalloutEditor.svelte.d.ts +0 -17
  353. package/components/editor/CaptionedCodeEditor.svelte.d.ts +0 -17
  354. package/components/editor/CaretContext.d.ts +0 -50
  355. package/components/editor/CaretContext.js +0 -1
  356. package/components/editor/CaretState.js +0 -1
  357. package/components/editor/CaretUtilities.js +0 -1
  358. package/components/editor/CaretView.svelte.d.ts +0 -25
  359. package/components/editor/CitationsEditor.svelte +0 -53
  360. package/components/editor/CitationsEditor.svelte.d.ts +0 -17
  361. package/components/editor/Clipboard.js +0 -1
  362. package/components/editor/Command.js +0 -1
  363. package/components/editor/Commands.d.ts +0 -3
  364. package/components/editor/ConfirmButton.svelte +0 -49
  365. package/components/editor/ConfirmButton.svelte.d.ts +0 -19
  366. package/components/editor/DefinitionEditor.svelte +0 -36
  367. package/components/editor/DefinitionEditor.svelte.d.ts +0 -17
  368. package/components/editor/EmbedEditor.svelte +0 -137
  369. package/components/editor/EmbedEditor.svelte.d.ts +0 -17
  370. package/components/editor/Icon.svelte.d.ts +0 -16
  371. package/components/editor/ImageChooser.svelte.d.ts +0 -18
  372. package/components/editor/InlineCodeEditor.svelte +0 -12
  373. package/components/editor/InlineCodeEditor.svelte.d.ts +0 -17
  374. package/components/editor/LabelEditor.svelte.d.ts +0 -17
  375. package/components/editor/LanguageEditor.svelte.d.ts +0 -17
  376. package/components/editor/LinkEditor.svelte +0 -100
  377. package/components/editor/LinkEditor.svelte.d.ts +0 -17
  378. package/components/editor/Note.svelte.d.ts +0 -27
  379. package/components/editor/Permissions.svelte.d.ts +0 -20
  380. package/components/editor/PositionEditor.svelte +0 -17
  381. package/components/editor/PositionEditor.svelte.d.ts +0 -18
  382. package/components/editor/QuoteEditor.svelte +0 -10
  383. package/components/editor/QuoteEditor.svelte.d.ts +0 -17
  384. package/components/editor/Switch.svelte.d.ts +0 -20
  385. package/components/editor/TableEditor.svelte +0 -10
  386. package/components/editor/TableEditor.svelte.d.ts +0 -17
  387. package/components/editor/TextEditor.svelte.d.ts +0 -24
  388. package/components/editor/Toggle.svelte +0 -41
  389. package/components/editor/Toggle.svelte.d.ts +0 -19
  390. package/components/editor/Toolbar.svelte +0 -249
  391. package/components/editor/Toolbar.svelte.d.ts +0 -17
  392. package/components/editor/ToolbarGroup.svelte.d.ts +0 -18
  393. package/components/editor/ToolbarSpacer.svelte.d.ts +0 -23
  394. package/components/editor/URLEditor.svelte +0 -13
  395. package/components/editor/URLEditor.svelte.d.ts +0 -18
  396. package/components/editor/UndoState.js +0 -1
  397. package/components/page/Acknowledgements.svelte.d.ts +0 -14
  398. package/components/page/Authors.svelte +0 -85
  399. package/components/page/Authors.svelte.d.ts +0 -21
  400. package/components/page/BookLoader.svelte +0 -59
  401. package/components/page/BookLoader.svelte.d.ts +0 -16
  402. package/components/page/BulkReferenceEditor.svelte +0 -63
  403. package/components/page/BulkReferenceEditor.svelte.d.ts +0 -14
  404. package/components/page/Chapter.svelte +0 -392
  405. package/components/page/Chapter.svelte.d.ts +0 -18
  406. package/components/page/ChapterContext.d.ts +0 -10
  407. package/components/page/ChapterContext.js +0 -1
  408. package/components/page/ChapterNumber.svelte.d.ts +0 -27
  409. package/components/page/ChapterTitle.svelte.d.ts +0 -18
  410. package/components/page/Contexts.d.ts +0 -47
  411. package/components/page/Contexts.js +0 -133
  412. package/components/page/DefinitionView.svelte.d.ts +0 -18
  413. package/components/page/Description.svelte.d.ts +0 -14
  414. package/components/page/Edition.svelte +0 -161
  415. package/components/page/Edition.svelte.d.ts +0 -20
  416. package/components/page/EditionLoader.svelte +0 -99
  417. package/components/page/EditionLoader.svelte.d.ts +0 -18
  418. package/components/page/Editions.svelte.d.ts +0 -14
  419. package/components/page/Glossary.svelte.d.ts +0 -14
  420. package/components/page/Header.svelte.d.ts +0 -29
  421. package/components/page/Index.svelte.d.ts +0 -14
  422. package/components/page/Instructions.svelte.d.ts +0 -18
  423. package/components/page/License.svelte.d.ts +0 -14
  424. package/components/page/Loading.svelte.d.ts +0 -23
  425. package/components/page/Media.svelte.d.ts +0 -14
  426. package/components/page/MediaPreview.svelte.d.ts +0 -19
  427. package/components/page/Muted.svelte.d.ts +0 -27
  428. package/components/page/Outline.svelte.d.ts +0 -19
  429. package/components/page/Page.svelte +0 -84
  430. package/components/page/Page.svelte.d.ts +0 -19
  431. package/components/page/PageHeader.svelte.d.ts +0 -18
  432. package/components/page/PageParagraph.svelte.d.ts +0 -27
  433. package/components/page/PossibleChapter.svelte +0 -14
  434. package/components/page/PossibleChapter.svelte.d.ts +0 -14
  435. package/components/page/PossibleReference.svelte +0 -11
  436. package/components/page/PossibleReference.svelte.d.ts +0 -18
  437. package/components/page/Print.svelte.d.ts +0 -14
  438. package/components/page/Publish.svelte.d.ts +0 -14
  439. package/components/page/Reference.svelte.d.ts +0 -17
  440. package/components/page/References.svelte.d.ts +0 -14
  441. package/components/page/Rows.svelte.d.ts +0 -27
  442. package/components/page/Search.svelte +0 -133
  443. package/components/page/Search.svelte.d.ts +0 -14
  444. package/components/page/Status.svelte.d.ts +0 -14
  445. package/components/page/SubdomainEditor.svelte.d.ts +0 -14
  446. package/components/page/TableOfContents.svelte.d.ts +0 -14
  447. package/components/page/TableOfContentsImage.svelte +0 -18
  448. package/components/page/TableOfContentsImage.svelte.d.ts +0 -16
  449. package/components/page/TableOfContentsRow.svelte.d.ts +0 -24
  450. package/components/page/ThemeEditor.svelte.d.ts +0 -14
  451. package/components/page/ThemeEditorPreview.svelte.d.ts +0 -17
  452. package/components/page/ThemeSetEditor.svelte +0 -19
  453. package/components/page/ThemeSetEditor.svelte.d.ts +0 -18
  454. package/components/page/ThemeVariableEditor.svelte.d.ts +0 -18
  455. package/components/page/Title.svelte.d.ts +0 -27
  456. package/components/page/Unknown.svelte.d.ts +0 -16
  457. package/components/page/margins.d.ts +0 -2
  458. package/index.d.ts +0 -15
  459. package/models/CRUD.d.ts +0 -27
  460. package/models/CRUD.js +0 -262
  461. package/models/Firebase.d.ts +0 -5
  462. package/models/book/Book.d.ts +0 -61
  463. package/models/book/Book.js +0 -135
  464. package/models/book/BookMedia.d.ts +0 -23
  465. package/models/book/BookMedia.js +0 -108
  466. package/models/book/BookSaveStatus.d.ts +0 -7
  467. package/models/book/BookSaveStatus.js +0 -8
  468. package/models/book/Chapter.d.ts +0 -81
  469. package/models/book/Chapter.js +0 -212
  470. package/models/book/ChapterID.d.ts +0 -10
  471. package/models/book/Definition.d.ts +0 -6
  472. package/models/book/Definition.js +0 -1
  473. package/models/book/Edition.d.ts +0 -139
  474. package/models/book/Edition.js +0 -620
  475. package/models/book/Reference.d.ts +0 -24
  476. package/models/book/Reference.js +0 -78
  477. package/models/book/Schema.d.ts +0 -174
  478. package/models/book/Theme.d.ts +0 -113
  479. package/models/book/ThemeColors.js +0 -1
  480. package/models/book/Words.d.ts +0 -2
  481. package/models/chapter/AtomNode.d.ts +0 -18
  482. package/models/chapter/BlockNode.d.ts +0 -20
  483. package/models/chapter/BlocksNode.d.ts +0 -50
  484. package/models/chapter/BlocksNode.test.d.ts +0 -1
  485. package/models/chapter/BlocksNode.test.js +0 -568
  486. package/models/chapter/Bookkeeping.js +0 -1
  487. package/models/chapter/CalloutNode.d.ts +0 -17
  488. package/models/chapter/CalloutNode.js +0 -58
  489. package/models/chapter/Caret.d.ts +0 -23
  490. package/models/chapter/ChapterNode.d.ts +0 -34
  491. package/models/chapter/ChapterNode.js +0 -117
  492. package/models/chapter/CitationsNode.d.ts +0 -16
  493. package/models/chapter/CodeNode.d.ts +0 -35
  494. package/models/chapter/CommentNode.d.ts +0 -18
  495. package/models/chapter/CommentNode.js +0 -48
  496. package/models/chapter/DefinitionNode.d.ts +0 -12
  497. package/models/chapter/Edit.d.ts +0 -7
  498. package/models/chapter/Edit.js +0 -1
  499. package/models/chapter/EmbedNode.d.ts +0 -45
  500. package/models/chapter/EmbedNode.js +0 -168
  501. package/models/chapter/ErrorNode.d.ts +0 -17
  502. package/models/chapter/FootnoteNode.d.ts +0 -18
  503. package/models/chapter/FootnoteNode.js +0 -47
  504. package/models/chapter/FormatNode.d.ts +0 -60
  505. package/models/chapter/FormatNode.test.d.ts +0 -1
  506. package/models/chapter/FormatNode.test.js +0 -96
  507. package/models/chapter/InlineCodeNode.d.ts +0 -12
  508. package/models/chapter/LabelNode.d.ts +0 -17
  509. package/models/chapter/LinkNode.d.ts +0 -12
  510. package/models/chapter/ListNode.d.ts +0 -51
  511. package/models/chapter/ListNode.test.d.ts +0 -1
  512. package/models/chapter/MetadataNode.d.ts +0 -17
  513. package/models/chapter/MetadataNode.js +0 -32
  514. package/models/chapter/Node.d.ts +0 -38
  515. package/models/chapter/Node.test.d.ts +0 -1
  516. package/models/chapter/ParagraphNode.d.ts +0 -33
  517. package/models/chapter/ParagraphNode.test.d.ts +0 -1
  518. package/models/chapter/ParagraphNode.test.js +0 -30
  519. package/models/chapter/Parser.d.ts +0 -75
  520. package/models/chapter/Parser.test.d.ts +0 -1
  521. package/models/chapter/Position.js +0 -1
  522. package/models/chapter/QuoteNode.d.ts +0 -25
  523. package/models/chapter/QuoteNode.js +0 -99
  524. package/models/chapter/RootNode.js +0 -1
  525. package/models/chapter/RuleNode.d.ts +0 -15
  526. package/models/chapter/TableNode.d.ts +0 -37
  527. package/models/chapter/TableNode.test.d.ts +0 -1
  528. package/models/chapter/TextNode.d.ts +0 -36
  529. package/models/chapter/TextNode.test.d.ts +0 -1
  530. package/util/getSubdomain.d.ts +0 -3
  531. package/util/isMobile.d.ts +0 -2
  532. package/util/mineReference.d.ts +0 -4
  533. package/util/scrollToEyeLevel.d.ts +0 -2
@@ -0,0 +1,449 @@
1
+ <script lang="ts">
2
+ import Parser from '$lib/models/chapter/Parser';
3
+ import type ChapterModel from '$lib/models/book/Chapter';
4
+ import Header from '$lib/components/page/Header.svelte';
5
+ import Authors from '$lib/components/page/Authors.svelte';
6
+ import Outline from '$lib/components/page/Outline.svelte';
7
+ import Page from '$lib/components/page/Page.svelte';
8
+ import TextEditor from '$lib/components/editor/TextEditor.svelte';
9
+ import BookishEditor from '$lib/components/editor/BookishEditor.svelte';
10
+ import Toggle from '$lib/components/editor/Toggle.svelte';
11
+ import Instructions from '$lib/components/page/Instructions.svelte';
12
+ import ChapterBody from '$lib/components/chapter/ChapterBody.svelte';
13
+ import PossibleReference from './PossibleReference.svelte';
14
+ import ChapterNumber from './ChapterNumber.svelte';
15
+ import Problem from '../chapter/Problem.svelte';
16
+ import {
17
+ CHAPTER,
18
+ getUser,
19
+ getBook,
20
+ getEdition,
21
+ isBookEditable,
22
+ isChapterEditable,
23
+ isEditionPartiallyEditable,
24
+ getLeasee,
25
+ lease,
26
+ setChapter,
27
+ type ChapterStore,
28
+ isEditionEditable,
29
+ } from './Contexts';
30
+ import { writable } from 'svelte/store';
31
+ import { onMount, setContext } from 'svelte';
32
+ import { hideOutlineIfObscured, layoutMarginals } from './margins';
33
+ import scrollToEyeLevel from '../../util/scrollToEyeLevel';
34
+ import type ChapterContext from '$lib/components/page/ChapterContext';
35
+ import { goto } from '$app/navigation';
36
+ import ChapterNode from '$lib/models/chapter/ChapterNode';
37
+ import Muted from './Muted.svelte';
38
+ import Title from './Title.svelte';
39
+ import PageHeader from './PageHeader.svelte';
40
+ import Permissions from '../editor/Permissions.svelte';
41
+
42
+ export let chapter: ChapterModel;
43
+ export let print: boolean = false;
44
+
45
+ let book = getBook();
46
+ let edition = getEdition();
47
+ let auth = getUser();
48
+
49
+ // Keep track of the scroll position to facilitate reading during reloads.
50
+ function rememberPosition() {
51
+ localStorage.setItem('scrollposition', '' + window.scrollY);
52
+ }
53
+
54
+ // When the window resizes, the responsive layout might cause the marginals to move to the footer.
55
+ // when this happens, we want to immediately remove all of the explicit positioning.
56
+ function handleResize() {
57
+ layoutMarginals();
58
+ }
59
+
60
+ // The currently selected marginal; we only do one at a time.
61
+ let marginal = writable<string | undefined>(undefined);
62
+
63
+ // Keep track of which hash mark is scrolled to
64
+ let highlightedID: string | undefined = undefined;
65
+
66
+ // When this component is mounted...
67
+ // 1) Subscribe and unsubscribe to window listeners
68
+ // 2) Do initial layout of marginals
69
+ // 3) Start observing any elements corresponding to the ID in the URL's hash string
70
+ // 4) Clean up our mess after unmounting.
71
+ onMount(() => {
72
+ // On render or when scrolling, see if the URL hash has changed and update state accordingly.
73
+ // We also track whether we've scrolled to it.
74
+ const observeHash = () => {
75
+ // Get the ID without the hash and the corresponding element
76
+ const elementID = window.location.hash.substring(1);
77
+ const element = elementID
78
+ ? document.getElementById(elementID)
79
+ : null;
80
+
81
+ // If it's not empty, observe it, and remember what we're observing for highlighting
82
+ if (element) {
83
+ highlightedID = elementID;
84
+ // Start watching this a few seconds after we see it, giving the for in-page scrolling.
85
+ setTimeout(() => observer.observe(element), 2500);
86
+ }
87
+ };
88
+
89
+ // Do things to do when scrolling
90
+ const handleScroll = () => {
91
+ // See if the outline is obscured by an image
92
+ hideOutlineIfObscured();
93
+
94
+ // See if there are any new hashes to observe. This is because
95
+ // we're using react-router-hash-link, which doesn't trigger hashchange events for some reason.
96
+ observeHash();
97
+ };
98
+
99
+ // Lay things out when the window or scroll changes.
100
+ window.addEventListener('scroll', handleScroll);
101
+ window.addEventListener('resize', handleResize);
102
+
103
+ // Remember the scroll position before a refresh.
104
+ // We have to do all of these because browser support varies.
105
+ window.addEventListener('beforeunload', rememberPosition);
106
+ window.addEventListener('visibilitychange', rememberPosition);
107
+ window.addEventListener('pagehide', rememberPosition);
108
+
109
+ // Start listening for hash changes, since we want to remove them upon scrolling away from them.
110
+ window.addEventListener('pushstate', observeHash);
111
+ window.addEventListener('popstate', observeHash);
112
+ window.addEventListener('hashchange', observeHash);
113
+
114
+ // Make an intersection observer to monitor the location of elements selected by the URL hash ID.
115
+ const observer = new IntersectionObserver((entries) => {
116
+ // Go through all of the monitored elements
117
+ entries.forEach((entry) => {
118
+ // If the observed element is out of view and in the hash, remove the hash
119
+ if (
120
+ entry.intersectionRatio === 0 &&
121
+ entry.target.id === window.location.hash.substring(1)
122
+ ) {
123
+ history.pushState(
124
+ '',
125
+ document.title,
126
+ window.location.pathname + window.location.search
127
+ );
128
+ observer.unobserve(entry.target);
129
+ highlightedID = undefined;
130
+ }
131
+ });
132
+ });
133
+
134
+ // Do an initial check the hash to see if there's an ID to scroll to
135
+ observeHash();
136
+
137
+ // Position the marginals, since there's new content.
138
+ layoutMarginals();
139
+
140
+ // On cleanup, unsubscribe from everything above.
141
+ return () => {
142
+ window.removeEventListener('scroll', handleScroll);
143
+ window.removeEventListener('resize', handleResize);
144
+
145
+ // Stop listening to page visibility changes.
146
+ window.removeEventListener('beforeunload', rememberPosition);
147
+ window.removeEventListener('visibilitychange', rememberPosition);
148
+ window.removeEventListener('pagehide', rememberPosition);
149
+
150
+ // Delete the remembered position so that the next page scrolls to top.
151
+ localStorage.removeItem('scrollposition');
152
+
153
+ // Stop listening for hash changes
154
+ window.removeEventListener('pushstate', observeHash);
155
+ window.removeEventListener('popstate', observeHash);
156
+ window.removeEventListener('hashchange', observeHash);
157
+
158
+ // Stop observing everything on unmount
159
+ observer.disconnect();
160
+ };
161
+ });
162
+
163
+ // Position the marginals on mount.
164
+ onMount(() => layoutMarginals());
165
+
166
+ // This gets called after the page is done loading. There are various things we scroll to.
167
+ function scrollToLastLocation() {
168
+ // In case loading changed marginal positions
169
+ layoutMarginals();
170
+
171
+ // If there's a word we're trying to highlight in the URL path, scroll to the corresponding match.
172
+ if (location.search) {
173
+ const highlights = document.getElementsByClassName(
174
+ 'bookish-text bookish-content-highlight'
175
+ );
176
+ const num = getHighlightedNumber();
177
+ if (
178
+ num &&
179
+ highlights.length > 0 &&
180
+ num < highlights.length &&
181
+ num >= 0
182
+ ) {
183
+ scrollToEyeLevel(highlights[num]);
184
+ }
185
+ }
186
+ // Otherwise, if there's an ID in the URL, jump to it.
187
+ else if (highlightedID) {
188
+ const el = document.getElementById(highlightedID as string);
189
+ // If we found the element, remove the hash any time after a few seconds. See handleScroll for the removal logic.
190
+ if (el) {
191
+ scrollToEyeLevel(el);
192
+ }
193
+ } else {
194
+ // If we got to this page through a refresh, scroll to
195
+ const entries = performance.getEntriesByType('navigation');
196
+ const position = localStorage.getItem('scrollposition');
197
+ if (
198
+ position !== null &&
199
+ entries.length > 0 &&
200
+ (entries[entries.length - 1] as PerformanceNavigationTiming)
201
+ .type === 'reload'
202
+ ) {
203
+ // Scroll to the previous position, if there was one, so that refresh preserves position.
204
+ window.scrollTo(0, parseInt(position));
205
+ }
206
+ // Otherwise, just scroll to the top.
207
+ else {
208
+ window.scrollTo(0, 0);
209
+ }
210
+ }
211
+ }
212
+
213
+ /** Account for static builds, where location isn't defined */
214
+ function getLocation() {
215
+ return typeof location === 'undefined' ? undefined : location;
216
+ }
217
+
218
+ function getHighlightedWord() {
219
+ return getLocation()?.search.split('&')[0]?.split('=')[1] ?? undefined;
220
+ }
221
+ function getHighlightedNumber() {
222
+ const number = getLocation()?.search.split('&')[1]?.split('=')[1];
223
+ return number === undefined ? undefined : parseInt(number);
224
+ }
225
+
226
+ // Prepare to render the chapter by getting some data from the chapter and book.
227
+ $: chapterID = chapter.getID();
228
+ $: chapterNumber = $edition?.getChapterNumber(chapterID);
229
+ $: chapterSection = $edition?.getChapterSection(chapterID);
230
+ $: chapterAST = $edition ? chapter.getAST($edition) : undefined;
231
+ $: citations = chapterAST ? chapterAST.getCitations() : undefined;
232
+ $: editionNumber = $edition ? $edition.getEditionNumber() : undefined;
233
+
234
+ let chapterStore = writable<ChapterContext>();
235
+ setContext<ChapterStore>(CHAPTER, chapterStore);
236
+ $: chapterStore.set({
237
+ chapter: chapter,
238
+ highlightedWord: getHighlightedWord(),
239
+ highlightedID: highlightedID,
240
+ marginal: marginal,
241
+ layoutMarginals: layoutMarginals,
242
+ });
243
+
244
+ let editable =
245
+ isBookEditable() ||
246
+ isEditionEditable() ||
247
+ isChapterEditable() ||
248
+ ($auth !== undefined &&
249
+ $auth.user !== null &&
250
+ chapter.isEditor($auth.user.uid));
251
+ </script>
252
+
253
+ {#if $edition}
254
+ <Page
255
+ afterLoaded={scrollToLastLocation}
256
+ title={`${$edition.getTitle()} - ${chapter.getTitle()}`}
257
+ >
258
+ <Header
259
+ editable={isChapterEditable()}
260
+ id={chapter.id}
261
+ header={chapter.getTitle()}
262
+ label="Chapter title"
263
+ tags={$edition.getTags()}
264
+ save={(text) =>
265
+ setChapter(edition, chapter, chapter.withTitle(text))}
266
+ getImage={() => chapter.getImage()}
267
+ setImage={(embed) =>
268
+ setChapter(edition, chapter, chapter.withImage(embed))}
269
+ {print}
270
+ >
271
+ <!-- Collapse the outline if a marginal is selected. -->
272
+ <Outline
273
+ slot="outline"
274
+ collapse={$marginal !== undefined}
275
+ previous={$edition.getPreviousChapterID(chapterID)}
276
+ next={$edition.getNextChapterID(chapterID)}
277
+ listener={(expanded) => {
278
+ // If the outline is being expanded, hide the marginal, otherwise leave it alone.
279
+ if (expanded) marginal.set(undefined);
280
+
281
+ // Check if we need to hide the outline after positioning.
282
+ hideOutlineIfObscured();
283
+ }}
284
+ />
285
+ <!-- Add an editable chapter ID if in editor mode -->
286
+ <svelte:fragment slot="before">
287
+ {#if editable && $book}
288
+ <Muted>
289
+ <TextEditor
290
+ text={chapter.getID()}
291
+ label="Chapter URL ID editor"
292
+ save={// After the ID is edited, reload the page with the new URL.
293
+ (newChapterID) => {
294
+ if ($book) {
295
+ chapter.withChapterID(newChapterID);
296
+ // Navigate to the new ID
297
+ goto(
298
+ `/write/${$book.ref.id}/${editionNumber}/${newChapterID}`
299
+ );
300
+ }
301
+ }}
302
+ placeholder="chapter ID"
303
+ valid={(newChapterID) =>
304
+ !/^[a-zA-Z0-9]+$/.test(newChapterID)
305
+ ? 'Chapter IDs must be one or more letters or numbers'
306
+ : chapter.getID() !== newChapterID &&
307
+ $edition?.hasChapter(newChapterID)
308
+ ? "There's already a chapter that has this ID."
309
+ : undefined}
310
+ saveOnExit={true}
311
+ />
312
+ </Muted>
313
+ {/if}
314
+ {#if editable}
315
+ <Toggle
316
+ on={chapter.isNumbered()}
317
+ save={(on) =>
318
+ setChapter(
319
+ edition,
320
+ chapter,
321
+ chapter.asNumbered(on)
322
+ )}
323
+ >
324
+ <ChapterNumber
325
+ >{#if chapterNumber !== undefined}Chapter {chapterNumber}{:else}<Muted
326
+ >Unnumbered</Muted
327
+ >{/if}</ChapterNumber
328
+ >
329
+ </Toggle>
330
+ {:else if chapterNumber !== undefined}
331
+ <ChapterNumber>Chapter {chapterNumber}</ChapterNumber>
332
+ {/if}
333
+ {#if chapterSection !== undefined && chapterSection.length > 0}
334
+ <span class="section-name">{chapterSection}</span>
335
+ {/if}
336
+ </svelte:fragment>
337
+ <!-- If there are chapter authors, render those, otherwise use the book authors -->
338
+ <Authors
339
+ editable={isChapterEditable()}
340
+ slot="after"
341
+ authors={chapter.getAuthors()}
342
+ inheritedAuthors={$edition.getAuthors()}
343
+ add={() => setChapter(edition, chapter, chapter.withAuthor(''))}
344
+ edit={(index, text) =>
345
+ setChapter(
346
+ edition,
347
+ chapter,
348
+ chapter.withRenamedAuthor(index, text)
349
+ )}
350
+ remove={(index) =>
351
+ setChapter(edition, chapter, chapter.withoutAuthor(index))}
352
+ />
353
+ </Header>
354
+
355
+ <Instructions {editable}>
356
+ Edit your chapter's title, authors, and cover image above. You can
357
+ also change the ID of the chapter, which is the text that appears in
358
+ the chapter URL. Write your chapter text below, formatting options
359
+ in the toolbar above to add headers, lists, tables, comments,
360
+ citations, footnotes, and more. It's okay to try things, you can
361
+ always undo. Saves are automatic.
362
+ </Instructions>
363
+
364
+ <!-- Render the chapter body, passing some context -->
365
+ <section class="chapter-content">
366
+ {#if chapterAST}
367
+ {#if editable}
368
+ <BookishEditor
369
+ text={chapterAST.toBookdown()}
370
+ parser={(text) => Parser.parseChapter($edition, text)}
371
+ save={(ast) =>
372
+ ast instanceof ChapterNode
373
+ ? setChapter(
374
+ edition,
375
+ chapter,
376
+ chapter.withAST(ast)
377
+ )
378
+ : undefined}
379
+ chapter={true}
380
+ autofocus
381
+ component={ChapterBody}
382
+ placeholder="write here"
383
+ leasee={getLeasee(auth, edition, chapter.id)}
384
+ lease={(lock) => lease(auth, edition, chapter.id, lock)}
385
+ />
386
+ {:else}
387
+ <ChapterBody node={chapterAST} />
388
+ {/if}
389
+ {:else}
390
+ <span>Loading...</span>
391
+ {/if}
392
+ </section>
393
+
394
+ {#if citations && citations.size > 0}
395
+ {@const refs = $edition.getReferences()}
396
+ <Title>References</Title>
397
+ <ol>
398
+ {#each [...citations].sort() as citationID}
399
+ {#if citationID in refs}
400
+ <li
401
+ class={'bookish-reference'}
402
+ id={'ref-' + citationID}
403
+ >
404
+ <PossibleReference node={refs[citationID]} />
405
+ </li>
406
+ {:else}
407
+ <li
408
+ ><Problem
409
+ >Unknown reference: <code>{citationID}</code
410
+ ></Problem
411
+ ></li
412
+ >
413
+ {/if}
414
+ {/each}
415
+ </ol>
416
+ {/if}
417
+
418
+ {#if editable || isEditionPartiallyEditable()}
419
+ <PageHeader>Editors</PageHeader>
420
+ <Instructions {editable}
421
+ >These authors can edit this chapter. Add an email here to
422
+ provide chapter-level edit permissions.</Instructions
423
+ >
424
+
425
+ <Permissions
426
+ uids={chapter.uids}
427
+ inheriteduids={Array.from(
428
+ new Set([...$edition.uids, ...($book ? $book.uids : [])])
429
+ )}
430
+ atleastone={false}
431
+ writable={isChapterEditable()}
432
+ change={(uids) =>
433
+ setChapter(edition, chapter, chapter.withEditors(uids))}
434
+ />
435
+ {/if}
436
+ </Page>
437
+ {/if}
438
+
439
+ <style>
440
+ .section-name {
441
+ display: inline-block;
442
+ font-family: var(--bookish-paragraph-font-family);
443
+ font-size: var(--bookish-small-font-size);
444
+ font-weight: normal;
445
+ font-style: normal;
446
+ color: var(--bookish-muted-color);
447
+ line-height: 1em;
448
+ }
449
+ </style>
@@ -0,0 +1,13 @@
1
+ import type { Writable } from 'svelte/store';
2
+ import type Chapter from '../../models/book/Chapter';
3
+
4
+ type ChapterContext =
5
+ | {
6
+ chapter: Chapter;
7
+ highlightedWord?: string;
8
+ highlightedID?: string;
9
+ marginal: Writable<string | undefined>;
10
+ layoutMarginals: () => void;
11
+ }
12
+ | undefined;
13
+ export default ChapterContext;
@@ -1,5 +1,7 @@
1
- <script>import Link from '../Link.svelte';
2
- export let link = undefined;
1
+ <script lang="ts">
2
+ import Link from '../Link.svelte';
3
+
4
+ export let link: string | undefined = undefined;
3
5
  </script>
4
6
 
5
7
  {#if link}
@@ -0,0 +1,176 @@
1
+ // We use these unique objects as keys in Svelte context in order
2
+ // to avoid key collisions and prevent typos. This is partly
3
+ // future-proofing, but also because getContext<Type>() isn't type safe,
4
+ // as the resulting value is coerced to Type even if it's not that value.
5
+
6
+ import { getContext } from 'svelte';
7
+ import { get, type Writable } from 'svelte/store';
8
+ import type Book from '../../models/book/Book';
9
+ import type Chapter from '../../models/book/Chapter';
10
+ import type BookSaveStatus from '../../models/book/BookSaveStatus';
11
+ import type Edition from '../../models/book/Edition';
12
+ import type Authentication from '../Authentication';
13
+ import type CaretState from '../editor/CaretState';
14
+ import type ChapterContext from './ChapterContext';
15
+ import { page } from '$app/stores';
16
+ import { updateLock } from '../../models/CRUD';
17
+ import type { DocumentReference } from 'firebase/firestore';
18
+
19
+ export type DarkModeStore = Writable<boolean>;
20
+ export const DARK_MODE = Symbol('dark');
21
+ export function getDarkMode() {
22
+ return getContext<DarkModeStore>(DARK_MODE);
23
+ }
24
+
25
+ export type UserStore = Writable<Authentication | undefined>;
26
+ export const USER = Symbol('user');
27
+ export function getUser() {
28
+ return getContext<UserStore>(USER);
29
+ }
30
+
31
+ export type BookStore = Writable<Book | undefined>;
32
+ export const BOOK = Symbol('book');
33
+ export function getBook() {
34
+ return getContext<BookStore>(BOOK);
35
+ }
36
+
37
+ export type EditionStore = Writable<Edition | undefined>;
38
+ export const EDITION = Symbol('edition');
39
+ export function getEdition() {
40
+ return getContext<EditionStore>(EDITION);
41
+ }
42
+
43
+ export type ChapterText = [DocumentReference, string][];
44
+ export type ChapterTextStore = Writable<ChapterText | undefined>;
45
+ export const CHAPTERTEXT = Symbol('chaptertext');
46
+ export function getChapterText() {
47
+ return getContext<ChapterTextStore>(CHAPTERTEXT);
48
+ }
49
+
50
+ export type ChapterStore = Writable<ChapterContext>;
51
+ export const CHAPTER = Symbol('chapter');
52
+ export function getChapter() {
53
+ return getContext<ChapterStore>(CHAPTER);
54
+ }
55
+
56
+ /**
57
+ * Update the edition that contains the chapter, then update the
58
+ * global edition store with the new edition, propogating the changes everywhere.
59
+ */
60
+ export function setChapter(
61
+ store: EditionStore,
62
+ previous: Chapter,
63
+ chapter: Chapter
64
+ ) {
65
+ const edition = get(store);
66
+ if (edition) store.set(edition.withRevisedChapter(previous, chapter));
67
+ }
68
+
69
+ export function isChapterEditable(): boolean {
70
+ if (!get(page).route.id?.startsWith('/write')) return false;
71
+ const auth = get(getUser());
72
+ const chapter = get(getChapter());
73
+ const edition = get(getEdition());
74
+ const book = get(getBook());
75
+ return (
76
+ chapter !== undefined &&
77
+ edition !== undefined &&
78
+ book !== undefined &&
79
+ auth !== undefined &&
80
+ auth.user !== null &&
81
+ (chapter.chapter.isEditor(auth.user.uid) ||
82
+ edition.isEditor(auth.user.uid) ||
83
+ book.isEditor(auth.user.uid))
84
+ );
85
+ }
86
+
87
+ export function isEditionEditable(): boolean {
88
+ if (!get(page).route.id?.startsWith('/write')) return false;
89
+ const auth = get(getUser());
90
+ const edition = get(getEdition());
91
+ const book = get(getBook());
92
+ return (
93
+ edition !== undefined &&
94
+ book !== undefined &&
95
+ auth !== undefined &&
96
+ auth.user !== null &&
97
+ (edition.isEditor(auth.user.uid) || book.isEditor(auth.user.uid))
98
+ );
99
+ }
100
+
101
+ export function isEditionPartiallyEditable(): boolean {
102
+ if (!get(page).route.id?.startsWith('/write')) return false;
103
+ const auth = get(getUser());
104
+ const edition = get(getEdition());
105
+ return (
106
+ edition !== undefined &&
107
+ auth !== undefined &&
108
+ auth.user !== null &&
109
+ edition.isChapterEditor(auth.user.uid)
110
+ );
111
+ }
112
+
113
+ export function isBookEditable(): boolean {
114
+ if (!get(page).route.id?.startsWith('/write')) return false;
115
+ const auth = get(getUser());
116
+ const book = get(getBook());
117
+ return (
118
+ book !== undefined &&
119
+ auth !== undefined &&
120
+ auth.user !== null &&
121
+ book.isEditor(auth.user.uid)
122
+ );
123
+ }
124
+
125
+ export const BASE = Symbol('base');
126
+ export type BaseStore = Writable<string>;
127
+ export function getBase() {
128
+ return getContext<BaseStore>(BASE);
129
+ }
130
+
131
+ export const CARET = Symbol('caret');
132
+ export function getCaret() {
133
+ return getContext<Writable<CaretState | undefined>>(CARET);
134
+ }
135
+
136
+ export const STATUS = Symbol('status');
137
+ export type StatusStore = Writable<BookSaveStatus>;
138
+ export function getStatus() {
139
+ return getContext<StatusStore>(STATUS);
140
+ }
141
+
142
+ export async function lease(
143
+ authStore: UserStore,
144
+ editionStore: EditionStore,
145
+ contentID: string,
146
+ lock: boolean
147
+ ): Promise<boolean> {
148
+ const edition = get(editionStore);
149
+ const auth = get(authStore);
150
+ if (edition && auth && auth.user) {
151
+ await updateLock(edition, auth.user.uid, contentID, lock);
152
+ const latestEdition = get(editionStore);
153
+ const latestAuth = get(authStore);
154
+ if (latestEdition && latestAuth && latestAuth.user) {
155
+ editionStore.set(
156
+ latestEdition.withLock(latestAuth.user.uid, contentID, lock)
157
+ );
158
+ return true;
159
+ } else return false;
160
+ } else return false;
161
+ }
162
+
163
+ export function getLeasee(
164
+ authStore: UserStore,
165
+ editionStore: EditionStore,
166
+ contentID: string
167
+ ): string | boolean {
168
+ const edition = get(editionStore);
169
+ const auth = get(authStore);
170
+ if (edition !== undefined && auth !== undefined && auth.user !== null) {
171
+ const leasee = edition.getLeasee(contentID);
172
+ if (leasee === undefined) return false;
173
+ else if (leasee === auth.user.uid) return true;
174
+ else return leasee;
175
+ } else return false;
176
+ }