bookish-press 0.4.46 → 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 -59
  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} +110 -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
@@ -1,24 +1,48 @@
1
1
  import Node from './Node';
2
+ import type ErrorNode from './ErrorNode';
2
3
  import TextNode from './TextNode';
3
- import { caretRangeToIndexRange, caretToIndex, indexToCaret, } from './Caret';
4
+ import type Caret from './Caret';
5
+ import {
6
+ caretRangeToIndexRange,
7
+ caretToIndex,
8
+ indexToCaret,
9
+ type CaretRange,
10
+ } from './Caret';
4
11
  import MetadataNode from './MetadataNode';
5
12
  import AtomNode from './AtomNode';
13
+ import type Edit from './Edit';
14
+
15
+ export type Format = '' | '*' | '_' | '^' | 'v';
16
+ export type FormatNodeSegmentType =
17
+ | FormatNode
18
+ | TextNode
19
+ | ErrorNode
20
+ | MetadataNode<any>
21
+ | AtomNode<any>;
22
+
6
23
  export default class FormatNode extends Node {
7
- #format;
8
- #segments;
9
- constructor(format, segments) {
24
+ readonly #format: Format;
25
+ readonly #segments: FormatNodeSegmentType[];
26
+
27
+ constructor(format: Format, segments: FormatNodeSegmentType[]) {
10
28
  super();
29
+
11
30
  this.#format = format;
12
31
  // Remove consecutive empty text nodes.
13
32
  this.#segments = segments.filter((item, position, list) => {
14
- if (position === 0 ||
33
+ if (
34
+ position === 0 ||
15
35
  !(item instanceof TextNode) ||
16
- item.getLength() > 0)
36
+ item.getLength() > 0
37
+ )
17
38
  return true;
18
39
  const previous = list[position - 1];
19
- return !(previous instanceof TextNode && previous.getLength() === 0);
40
+ return !(
41
+ previous instanceof TextNode && previous.getLength() === 0
42
+ );
20
43
  });
21
44
  }
45
+
22
46
  getType() {
23
47
  return 'formatted';
24
48
  }
@@ -32,100 +56,130 @@ export default class FormatNode extends Node {
32
56
  return this.#segments.length === 0;
33
57
  }
34
58
  isEmptyText() {
35
- return (this.#segments.length === 1 &&
59
+ return (
60
+ this.#segments.length === 1 &&
36
61
  this.#segments[0] instanceof TextNode &&
37
- this.#segments[0].getText() === '');
62
+ this.#segments[0].getText() === ''
63
+ );
38
64
  }
39
65
  getLength() {
40
66
  return this.#segments.length;
41
67
  }
42
- getParentOf(node) {
68
+ getParentOf(node: Node): Node | undefined {
43
69
  return this.#segments
44
70
  .map((b) => (b === node ? this : b.getParentOf(node)))
45
71
  .find((b) => b !== undefined);
46
72
  }
47
- toText() {
73
+
74
+ toText(): string {
48
75
  return this.#segments.map((segment) => segment.toText()).join(' ');
49
76
  }
50
- toHTML() {
77
+ toHTML(): string {
51
78
  const format = this.#format;
52
79
  const segments = this.#segments.map((s) => s.toHTML()).join('');
53
- if (format === '*')
54
- return `<strong>${segments}</strong>`;
55
- else if (format === '_')
56
- return `<em>${segments}</em>`;
57
- else if (format === '^')
58
- return `<sup>${segments}</sup>`;
59
- else if (format === 'v')
60
- return `<sub>${segments}</sub>`;
61
- else
62
- return segments;
63
- }
64
- toBookdown() {
65
- return ((this.#format === 'v' ? '^v' : this.#format) +
80
+ if (format === '*') return `<strong>${segments}</strong>`;
81
+ else if (format === '_') return `<em>${segments}</em>`;
82
+ else if (format === '^') return `<sup>${segments}</sup>`;
83
+ else if (format === 'v') return `<sub>${segments}</sub>`;
84
+ else return segments;
85
+ }
86
+
87
+ toBookdown(): string {
88
+ return (
89
+ (this.#format === 'v' ? '^v' : this.#format) +
66
90
  this.#segments
67
- .map((s) => s instanceof AtomNode ? s.toBookdown(this) : s.toBookdown())
91
+ .map((s) =>
92
+ s instanceof AtomNode ? s.toBookdown(this) : s.toBookdown()
93
+ )
68
94
  .join('') +
69
- (this.#format === 'v' ? '^' : this.#format));
95
+ (this.#format === 'v' ? '^' : this.#format)
96
+ );
70
97
  }
98
+
71
99
  getChildren() {
72
100
  return this.#segments;
73
101
  }
74
- getFirstTextNode() {
102
+
103
+ getFirstTextNode(): TextNode {
75
104
  const text = this.getTextNodes();
76
105
  return text[0];
77
106
  }
78
- getLastTextNode() {
107
+
108
+ getLastTextNode(): TextNode {
79
109
  const text = this.getTextNodes();
80
110
  return text[text.length - 1];
81
111
  }
82
- copy() {
83
- return new FormatNode(this.#format, this.#segments.map((s) => s.copy()));
112
+
113
+ copy(): this {
114
+ return new FormatNode(
115
+ this.#format,
116
+ this.#segments.map((s) => s.copy())
117
+ ) as this;
84
118
  }
85
- getTextNodes() {
86
- return this.getNodes().filter((n) => n instanceof TextNode);
119
+
120
+ getTextNodes(): TextNode[] {
121
+ return this.getNodes().filter(
122
+ (n) => n instanceof TextNode
123
+ ) as TextNode[];
87
124
  }
125
+
88
126
  // Get all text or atom nodes in this format, except for any inside an atom node,
89
127
  // as this is used for navigation and editing, and they should be isolated from that.
90
- getTextAndAtomNodes() {
91
- return this.getNodes().filter((n) => n instanceof TextNode || n instanceof AtomNode);
92
- }
93
- getAdjacentTextOrAtom(node, next) {
128
+ getTextAndAtomNodes(): (TextNode | AtomNode<any>)[] {
129
+ return this.getNodes().filter(
130
+ (n) => n instanceof TextNode || n instanceof AtomNode
131
+ ) as (TextNode | AtomNode<any>)[];
132
+ }
133
+
134
+ getAdjacentTextOrAtom(
135
+ node: TextNode | AtomNode<any>,
136
+ next: boolean
137
+ ): TextNode | AtomNode<any> | undefined {
94
138
  // Find all of the text and atom nodes not in atom nodes in this node.
95
139
  const text = this.getTextAndAtomNodes().filter((n) => {
96
140
  const atomAncestor = n.getClosestParentOfType(this, AtomNode);
97
- return (atomAncestor === undefined ||
141
+ return (
142
+ atomAncestor === undefined ||
98
143
  (atomAncestor instanceof AtomNode &&
99
- atomAncestor.getMeta() === this));
144
+ atomAncestor.getMeta() === this)
145
+ );
100
146
  });
101
147
  const index = text.indexOf(node);
102
148
  return index === undefined
103
149
  ? undefined
104
150
  : next
105
- ? index >= 0 && index < text.length - 1
106
- ? text[index + 1]
107
- : undefined
108
- : index > 0 && index <= text.length
109
- ? text[index - 1]
110
- : undefined;
111
- }
112
- getNextTextOrAtom(node) {
151
+ ? index >= 0 && index < text.length - 1
152
+ ? text[index + 1]
153
+ : undefined
154
+ : index > 0 && index <= text.length
155
+ ? text[index - 1]
156
+ : undefined;
157
+ }
158
+
159
+ getNextTextOrAtom(
160
+ node: TextNode | AtomNode<any>
161
+ ): TextNode | AtomNode<any> | undefined {
113
162
  return this.getAdjacentTextOrAtom(node, true);
114
163
  }
115
- getPreviousTextOrAtom(node) {
164
+
165
+ getPreviousTextOrAtom(
166
+ node: TextNode | AtomNode<any>
167
+ ): TextNode | AtomNode<any> | undefined {
116
168
  return this.getAdjacentTextOrAtom(node, false);
117
169
  }
118
- getAdjacentCaret(caret, next) {
119
- if (!(caret.node instanceof TextNode) &&
120
- !(caret.node instanceof AtomNode))
170
+
171
+ getAdjacentCaret(caret: Caret, next: boolean): Caret | undefined {
172
+ if (
173
+ !(caret.node instanceof TextNode) &&
174
+ !(caret.node instanceof AtomNode)
175
+ )
121
176
  return;
122
177
  // Is there an adjascent caret in the current text node? If so, return it.
123
178
  if (caret.node instanceof TextNode) {
124
179
  const adjacentText = next
125
180
  ? caret.node.getNextCaret(caret.index)
126
181
  : caret.node.getPreviousCaret(caret.index);
127
- if (adjacentText !== undefined)
128
- return adjacentText;
182
+ if (adjacentText !== undefined) return adjacentText;
129
183
  }
130
184
  // If there's not, is there an adjacent caret in the sequence of text and atom nodes?
131
185
  const adjacentNode = this.getAdjacentTextOrAtom(caret.node, next);
@@ -141,29 +195,30 @@ export default class FormatNode extends Node {
141
195
  : 1
142
196
  : 0
143
197
  : adjacentNode instanceof TextNode
144
- ? adjacentNode.isEmpty()
145
- ? 0
146
- : adjacentNode.getLength() - 1
147
- : 0,
198
+ ? adjacentNode.isEmpty()
199
+ ? 0
200
+ : adjacentNode.getLength() - 1
201
+ : 0,
148
202
  };
149
203
  }
150
204
  // Otherwise, there is no adjascent caret.
151
205
  return undefined;
152
206
  }
153
- getFirstCaret() {
207
+
208
+ getFirstCaret(): Caret | undefined {
154
209
  const text = this.getTextNodes();
155
- if (text.length === 0)
156
- return undefined;
210
+ if (text.length === 0) return undefined;
157
211
  return { node: this.getTextNodes()[0], index: 0 };
158
212
  }
159
- getLastCaret() {
213
+
214
+ getLastCaret(): Caret | undefined {
160
215
  const text = this.getTextNodes();
161
- if (text.length === 0)
162
- return undefined;
216
+ if (text.length === 0) return undefined;
163
217
  const last = text[text.length - 1];
164
218
  return { node: last, index: last.getLength() };
165
219
  }
166
- getSelection() {
220
+
221
+ getSelection(): CaretRange {
167
222
  const first = this.getFirstTextNode();
168
223
  const last = this.getLastTextNode();
169
224
  return {
@@ -171,117 +226,159 @@ export default class FormatNode extends Node {
171
226
  end: { node: last, index: last.getLength() },
172
227
  };
173
228
  }
174
- getIndexOfTextNode(node) {
229
+
230
+ getIndexOfTextNode(node: TextNode): number | undefined {
175
231
  const text = this.getTextNodes();
176
232
  return text.indexOf(node);
177
233
  }
178
- getSelectedText(range) {
179
- if (!(range.start.node instanceof TextNode) ||
180
- !(range.end.node instanceof TextNode))
234
+
235
+ getSelectedText(range: CaretRange): string | undefined {
236
+ if (
237
+ !(range.start.node instanceof TextNode) ||
238
+ !(range.end.node instanceof TextNode)
239
+ )
181
240
  return undefined;
241
+
182
242
  const start = this.getIndexOfTextNode(range.start.node);
183
243
  const end = this.getIndexOfTextNode(range.end.node);
184
- if (start === undefined || end === undefined)
185
- return undefined;
244
+
245
+ if (start === undefined || end === undefined) return undefined;
246
+
186
247
  return this.getTextNodes()
187
248
  .map((current, index) => {
188
- return current === range.start.node
189
- ? current === range.end.node
190
- ? current
191
- .getText()
192
- .substring(range.start.index, range.end.index)
193
- : current.getText().substring(range.start.index)
194
- : index > start && index < end
249
+ return current === range.start.node
250
+ ? current === range.end.node
251
+ ? current
252
+ .getText()
253
+ .substring(range.start.index, range.end.index)
254
+ : current.getText().substring(range.start.index)
255
+ : index > start && index < end
195
256
  ? current.getText()
196
257
  : current === range.end.node
197
- ? current.getText().substring(0, range.end.index)
198
- : '';
199
- })
258
+ ? current.getText().substring(0, range.end.index)
259
+ : '';
260
+ })
200
261
  .join('');
201
262
  }
263
+
202
264
  withTextIfEmpty() {
203
265
  return this.isEmpty() ? this.withSegmentAppended(new TextNode()) : this;
204
266
  }
205
- withSegmentPrepended(segment) {
267
+
268
+ withSegmentPrepended(segment: FormatNodeSegmentType): FormatNode {
206
269
  return new FormatNode(this.#format, [segment, ...this.#segments]);
207
270
  }
208
- withSegmentAppended(segment) {
271
+
272
+ withSegmentAppended(segment: FormatNodeSegmentType): FormatNode {
209
273
  return new FormatNode(this.#format, [...this.#segments, segment]);
210
274
  }
211
- withSegmentReplaced(segment, replacement) {
275
+
276
+ withSegmentReplaced(
277
+ segment: FormatNodeSegmentType,
278
+ replacement: FormatNodeSegmentType
279
+ ): this | undefined {
212
280
  const index = this.#segments.indexOf(segment);
213
- if (index < 0)
214
- return undefined;
281
+ if (index < 0) return undefined;
282
+
215
283
  const segments = this.#segments.slice();
216
284
  segments[index] = replacement;
217
- return new FormatNode(this.#format, segments);
285
+
286
+ return new FormatNode(this.#format, segments) as this;
218
287
  }
219
- withoutSegment(segment) {
288
+
289
+ withoutSegment(segment: FormatNodeSegmentType): this | undefined {
220
290
  const index = this.#segments.indexOf(segment);
221
- if (index < 0)
222
- return undefined;
291
+ if (index < 0) return undefined;
223
292
  const newSegments = this.#segments.slice();
224
293
  newSegments.splice(index, 1);
225
- return new FormatNode(this.#format, newSegments);
294
+ return new FormatNode(this.#format, newSegments) as this;
226
295
  }
227
- withChildReplaced(node, replacement) {
296
+
297
+ withChildReplaced(
298
+ node: FormatNodeSegmentType,
299
+ replacement: FormatNodeSegmentType | undefined
300
+ ) {
228
301
  return replacement === undefined
229
- ? this.withoutSegment(node)
230
- : this.withSegmentReplaced(node, replacement);
302
+ ? (this.withoutSegment(node) as this)
303
+ : (this.withSegmentReplaced(node, replacement) as this);
231
304
  }
305
+
232
306
  // Creates two formatted nodes that split this node at the given caret location.
233
- split(caret) {
307
+ split(caret: Caret): [FormatNode, FormatNode] | undefined {
234
308
  // We can only copy if
235
309
  // ... this has a parent.
236
310
  // ... the given caret is in this formatted node.
237
311
  // ... the caret is on a text node.
238
312
  if (!(caret.node instanceof TextNode) || !this.contains(caret.node))
239
313
  return undefined;
314
+
240
315
  const firstCaret = this.getFirstCaret();
241
316
  const lastCaret = this.getLastCaret();
242
317
  if (firstCaret === undefined || lastCaret === undefined)
243
318
  return undefined;
319
+
244
320
  // Delete everything after in the first, everything before in the second.
245
321
  const first = this.withoutRange({ start: caret, end: lastCaret });
246
322
  const second = this.withoutRange({ start: firstCaret, end: caret });
247
- if (first !== undefined && second !== undefined)
248
- return [first, second];
323
+
324
+ if (first !== undefined && second !== undefined) return [first, second];
249
325
  }
250
- withoutRange(range) {
326
+
327
+ withoutRange(range: CaretRange): FormatNode | undefined {
251
328
  return this.withFormat(range, undefined);
252
329
  }
330
+
253
331
  // This function takes the given range, and if it's within the bounds of this FormatNode,
254
332
  // produces a new FormatNode that either formats the given range with the given format or deletes the range if the format is undefined.
255
333
  // It's approach is to scan through every text, meta, and atom node build a new format based on the requested format.
256
- withFormat(range, format) {
334
+ withFormat(
335
+ range: CaretRange,
336
+ format: Format | undefined
337
+ ): FormatNode | undefined {
257
338
  // This only transforms ranges that start and end with text/atom nodes in this format node.
258
- if (!(range.start.node instanceof TextNode ||
259
- range.start.node instanceof AtomNode) ||
260
- !(range.end.node instanceof TextNode ||
261
- range.end.node instanceof AtomNode) ||
262
- !(this.contains(range.start.node) && this.contains(range.end.node)))
339
+ if (
340
+ !(
341
+ range.start.node instanceof TextNode ||
342
+ range.start.node instanceof AtomNode
343
+ ) ||
344
+ !(
345
+ range.end.node instanceof TextNode ||
346
+ range.end.node instanceof AtomNode
347
+ ) ||
348
+ !(this.contains(range.start.node) && this.contains(range.end.node))
349
+ )
263
350
  return;
351
+
264
352
  const sortedRange = this.sortRange(range);
353
+
265
354
  // Remember the text positions so we can return a new range in the new tree.
266
355
  const selectionStartIndex = caretToIndex(this, sortedRange.start);
267
356
  const selectionEndIndex = caretToIndex(this, sortedRange.end);
268
- if (selectionStartIndex === undefined ||
269
- selectionEndIndex === undefined)
357
+
358
+ if (
359
+ selectionStartIndex === undefined ||
360
+ selectionEndIndex === undefined
361
+ )
270
362
  return;
363
+
271
364
  // Remember if the selection is zero width.
272
365
  let zeroWidthSelection = selectionStartIndex === selectionEndIndex;
366
+
273
367
  // Find all of the content in the node, except for format nodes and decendants of atom nodes that have format nodes,
274
368
  // to construct a new format tree with the old content.
275
- const everythingButFormats = this.getNodes().filter((n) => !(n instanceof FormatNode));
369
+ const everythingButFormats = this.getNodes().filter(
370
+ (n) => !(n instanceof FormatNode)
371
+ );
372
+
276
373
  // Check if all of the selected content has the requested format so we can toggle it if so.
277
374
  let checkIndex = 0; // This tracks the current location in our scan.
278
375
  let editingEmptyNode = false; // This remembers the special case of the caret being inside an empty text node.
279
376
  let alreadyApplied = false; // We assume it's not applied until proven otherwise.
280
377
  let nodeCount = 0;
281
378
  let nodesWithFormat = 0;
379
+
282
380
  // It's already applied if we're deleting (in which case this doesn't apply).
283
- if (format === undefined)
284
- alreadyApplied = true;
381
+ if (format === undefined) alreadyApplied = true;
285
382
  // Otherwise, formatting is already applied if all of the non-format nodes already have this format.
286
383
  // We need to know this so we can toggle the format off.
287
384
  else {
@@ -294,8 +391,10 @@ export default class FormatNode extends Node {
294
391
  }
295
392
  // If this node is empty but contains a zero-width selection, remember it, since this is the only node for which formats are relevant.
296
393
  else if (node.getText().length === 0) {
297
- if (checkIndex === selectionStartIndex &&
298
- zeroWidthSelection) {
394
+ if (
395
+ checkIndex === selectionStartIndex &&
396
+ zeroWidthSelection
397
+ ) {
299
398
  editingEmptyNode = true;
300
399
  alreadyApplied = parent
301
400
  .getFormats(this)
@@ -308,41 +407,46 @@ export default class FormatNode extends Node {
308
407
  const parentIsFormatted = parent
309
408
  .getFormats(this)
310
409
  .includes(format);
311
- const selectionContainsNode = (selectionStartIndex > checkIndex &&
312
- selectionStartIndex <
313
- checkIndex +
314
- node.getCaretPositionCount() -
315
- 1) ||
410
+ const selectionContainsNode =
411
+ (selectionStartIndex > checkIndex &&
412
+ selectionStartIndex <
413
+ checkIndex +
414
+ node.getCaretPositionCount() -
415
+ 1) ||
316
416
  (selectionEndIndex > checkIndex &&
317
417
  selectionEndIndex <
318
418
  checkIndex +
319
419
  node.getCaretPositionCount() -
320
420
  1);
321
- const nodeContainsSelection = selectionStartIndex >= checkIndex &&
421
+ const nodeContainsSelection =
422
+ selectionStartIndex >= checkIndex &&
322
423
  selectionEndIndex <=
323
424
  checkIndex + node.getCaretPositionCount();
324
425
  checkIndex += node.getCaretPositionCount();
325
426
  if (nodeContainsSelection || selectionContainsNode) {
326
427
  nodeCount++;
327
- if (parentIsFormatted)
328
- nodesWithFormat++;
428
+ if (parentIsFormatted) nodesWithFormat++;
329
429
  }
330
430
  }
331
431
  }
332
432
  // Treat all non-text as containing the requested format.
333
- else
334
- return true;
433
+ else return true;
335
434
  });
336
435
  if (nodeCount > 0 && nodesWithFormat === nodeCount)
337
436
  alreadyApplied = true;
338
437
  }
438
+
339
439
  // Reformat everything. The strategy is to step through each character, atom node, and metadata node in this format node
340
440
  // and create a new series of formats that preserve existing formatting while applying new formatting to the selection.
341
- let newFormats = [{ format: '', segments: [] }]; // A stack of formats we're constructing.
441
+ let newFormats: {
442
+ format: Format;
443
+ segments: FormatNodeSegmentType[];
444
+ }[] = [{ format: '', segments: [] }]; // A stack of formats we're constructing.
342
445
  let textIndex = 0;
343
446
  let currentText = ''; // The current text we've accumulated, inserted before each format change and at the end.
344
447
  let formattingEmptyNode = false;
345
448
  let emptyNode = undefined;
449
+
346
450
  function saveText() {
347
451
  // If there's some text, update the current format with the current text, then reset it.
348
452
  if (currentText.length > 0) {
@@ -350,45 +454,60 @@ export default class FormatNode extends Node {
350
454
  currentText = '';
351
455
  }
352
456
  }
457
+
353
458
  function inRange() {
354
- return (selectionStartIndex !== undefined &&
459
+ return (
460
+ selectionStartIndex !== undefined &&
355
461
  selectionEndIndex !== undefined &&
356
462
  textIndex >= selectionStartIndex &&
357
- textIndex < selectionEndIndex);
463
+ textIndex < selectionEndIndex
464
+ );
358
465
  }
466
+
359
467
  function getFormats() {
360
468
  // We don't include non-formatted text in the list of formats applied.
361
469
  return newFormats.map((f) => f.format).filter((f) => f !== '');
362
470
  }
471
+
363
472
  function finishFormat() {
364
473
  const formatSpec = newFormats[0];
365
474
  newFormats.shift();
366
475
  // Keep the new format clean by only adding the format node if it's not empty, or if it's a zero width selection.
367
- if (formatSpec.segments.length > 0 ||
368
- (zeroWidthSelection && textIndex === selectionStartIndex))
369
- newFormats[0].segments.push(new FormatNode(formatSpec.format, formatSpec.segments));
476
+ if (
477
+ formatSpec.segments.length > 0 ||
478
+ (zeroWidthSelection && textIndex === selectionStartIndex)
479
+ )
480
+ newFormats[0].segments.push(
481
+ new FormatNode(formatSpec.format, formatSpec.segments)
482
+ );
370
483
  }
484
+
371
485
  everythingButFormats.forEach((node) => {
372
486
  const parent = this.getParentOf(node);
373
487
  if (node instanceof TextNode) {
374
488
  // If this is a text node in an atom node we're not formatting the atom node's format, then just
375
489
  // account for it's length, but do nothing else.
376
- const atomAncestor = node.getClosestParentOfType(this, AtomNode);
377
- if (atomAncestor instanceof AtomNode &&
490
+ const atomAncestor = node.getClosestParentOfType(
491
+ this,
492
+ AtomNode
493
+ );
494
+ if (
495
+ atomAncestor instanceof AtomNode &&
378
496
  atomAncestor.getMeta() !== this &&
379
- atomAncestor.getMeta() instanceof FormatNode) {
497
+ atomAncestor.getMeta() instanceof FormatNode
498
+ ) {
380
499
  textIndex += node.getCaretPositionCount();
381
- }
382
- else if (parent instanceof FormatNode) {
500
+ } else if (parent instanceof FormatNode) {
383
501
  // Remember we found an empty node so that we don't insert an extra one later.
384
502
  if (node.getText().length === 0) {
385
- if (textIndex === selectionStartIndex &&
386
- zeroWidthSelection) {
503
+ if (
504
+ textIndex === selectionStartIndex &&
505
+ zeroWidthSelection
506
+ ) {
387
507
  formattingEmptyNode = true;
388
508
  textIndex++;
389
509
  }
390
- }
391
- else {
510
+ } else {
392
511
  // Process each character in the node, including the very last position.
393
512
  for (let i = 0; i <= node.getText().length; i++) {
394
513
  // Determine the desired format for this character. Start with the current formats
@@ -398,22 +517,31 @@ export default class FormatNode extends Node {
398
517
  let desiredFormats = formatter
399
518
  ? formatter.getFormats(this)
400
519
  : [];
401
- if (format !== undefined &&
520
+ if (
521
+ format !== undefined &&
402
522
  ((textIndex === selectionStartIndex &&
403
523
  zeroWidthSelection) ||
404
- inRange())) {
524
+ inRange())
525
+ ) {
405
526
  // Remove all formatting if we were asked to.
406
- if (format === '')
407
- desiredFormats = [];
527
+ if (format === '') desiredFormats = [];
408
528
  // Apply the formatting if it's not already applied.
409
- else if (!alreadyApplied &&
410
- !desiredFormats.includes(format))
529
+ else if (
530
+ !alreadyApplied &&
531
+ !desiredFormats.includes(format)
532
+ )
411
533
  desiredFormats.push(format);
412
534
  // Remove the formatting if it's already applied in the selection.
413
- else if (alreadyApplied &&
414
- desiredFormats.includes(format))
415
- desiredFormats.splice(desiredFormats.indexOf(format), 1);
535
+ else if (
536
+ alreadyApplied &&
537
+ desiredFormats.includes(format)
538
+ )
539
+ desiredFormats.splice(
540
+ desiredFormats.indexOf(format),
541
+ 1
542
+ );
416
543
  }
544
+
417
545
  // Remove undesired formats.
418
546
  getFormats().forEach((activeFormat) => {
419
547
  // If the current format is not in the desired list, close the text
@@ -421,16 +549,22 @@ export default class FormatNode extends Node {
421
549
  if (!desiredFormats.includes(activeFormat)) {
422
550
  // Save any text that we've accumulated.
423
551
  saveText();
552
+
424
553
  // Not sure this loop is necessary; we should always remove in the order we added.
425
- while (newFormats[0].format !== activeFormat)
554
+ while (
555
+ newFormats[0].format !== activeFormat
556
+ )
426
557
  finishFormat();
427
558
  // Do it one more time to close out the undesired format.
428
559
  finishFormat();
560
+
429
561
  // If we have unformatted something at a zero-width range, create empty format node, add a text node in it and remember it so
430
562
  // we can place the caret in it.
431
- if (!formattingEmptyNode &&
563
+ if (
564
+ !formattingEmptyNode &&
432
565
  textIndex === selectionStartIndex &&
433
- zeroWidthSelection) {
566
+ zeroWidthSelection
567
+ ) {
434
568
  // Remember the node for later, so we can place the caret in it.
435
569
  emptyNode = new TextNode();
436
570
  // Append the empty node to the current format.
@@ -443,6 +577,7 @@ export default class FormatNode extends Node {
443
577
  }
444
578
  }
445
579
  });
580
+
446
581
  // Ensure the desired formats.
447
582
  desiredFormats.forEach((desiredFormat) => {
448
583
  // If the current format does not yet include the desired format,
@@ -450,22 +585,27 @@ export default class FormatNode extends Node {
450
585
  if (!getFormats().includes(desiredFormat)) {
451
586
  // Save any text that we've accumulated in the curent format.
452
587
  saveText();
588
+
453
589
  // Add a new format onto the stack to start adding to.
454
590
  newFormats.unshift({
455
591
  format: desiredFormat,
456
592
  segments: [],
457
593
  });
594
+
458
595
  // If we inserted an empty format node, add a text node in it and remember it so
459
596
  // we can place the caret in it.
460
- if (!formattingEmptyNode &&
597
+ if (
598
+ !formattingEmptyNode &&
461
599
  textIndex === selectionStartIndex &&
462
- zeroWidthSelection) {
600
+ zeroWidthSelection
601
+ ) {
463
602
  emptyNode = new TextNode();
464
603
  newFormats[0].segments.push(emptyNode);
465
604
  finishFormat();
466
605
  }
467
606
  }
468
607
  });
608
+
469
609
  // If there's a format we're applying, or we're outside the deletion range, append the current character.
470
610
  // We don't do this if we're checking the very last index of the node, since there is no character after it.
471
611
  if (i < node.getLength()) {
@@ -481,16 +621,20 @@ export default class FormatNode extends Node {
481
621
  else if (parent instanceof MetadataNode) {
482
622
  // Save whatever text came before it.
483
623
  saveText();
624
+
484
625
  // Process each character in the node if we're formatting, and if we're deleting, skip anything in range of deletion.
485
626
  for (let i = 0; i < node.getText().length; i++) {
486
627
  if (format !== undefined || !inRange())
487
628
  currentText += node.getText().charAt(i);
488
629
  textIndex++;
489
630
  }
631
+
490
632
  // Duplicate the MetadataNode but with new text. Erase the MetadataNode if the text is empty
491
633
  // by simply not adding one to this new format. Then, erase the text, since it was added in the metadata node.
492
634
  if (currentText.length > 0) {
493
- newFormats[0].segments.push(parent.withText(new TextNode(currentText)));
635
+ newFormats[0].segments.push(
636
+ parent.withText(new TextNode(currentText))
637
+ );
494
638
  currentText = '';
495
639
  }
496
640
  }
@@ -500,35 +644,52 @@ export default class FormatNode extends Node {
500
644
  else if (node instanceof AtomNode) {
501
645
  // Before adding the atom, create a text node and reset the accumulator.
502
646
  saveText();
647
+
503
648
  // Add the atom immediately after, unless it's in the deletion range.
504
649
  // We include the start index since AtomNode's text index is on the left.
505
- if (format !== undefined ||
650
+ if (
651
+ format !== undefined ||
506
652
  textIndex < selectionStartIndex ||
507
- textIndex > selectionEndIndex) {
653
+ textIndex > selectionEndIndex
654
+ ) {
508
655
  // Does the atom node have a format? Format it!
509
656
  let newAtom = node;
510
657
  const atomMeta = node.getMeta();
511
658
  if (atomMeta instanceof FormatNode) {
512
- if (atomMeta.contains(range.start.node) &&
513
- atomMeta.contains(range.end.node)) {
514
- const newFormat = atomMeta.withFormat(range, format);
659
+ if (
660
+ atomMeta.contains(range.start.node) &&
661
+ atomMeta.contains(range.end.node)
662
+ ) {
663
+ const newFormat = atomMeta.withFormat(
664
+ range,
665
+ format
666
+ );
515
667
  newAtom = node.withMeta(newFormat);
516
668
  }
517
669
  }
518
670
  // Add the formatted atom if there is one.
519
- newFormats[0].segments.push(newAtom !== undefined ? newAtom : node);
671
+ newFormats[0].segments.push(
672
+ newAtom !== undefined ? newAtom : node
673
+ );
520
674
  }
675
+
521
676
  // Increment the text index; atoms count for one character.
522
677
  textIndex++;
523
678
  }
524
679
  });
680
+
525
681
  // Save any remaining text that we've accumulated.
526
682
  saveText();
683
+
527
684
  // Keep finishing formats until we get to the original we created.
528
- while (newFormats.length > 1)
529
- finishFormat();
685
+ while (newFormats.length > 1) finishFormat();
686
+
530
687
  // Create the final format.
531
- let newFormat = new FormatNode(newFormats[0].format, newFormats[0].segments);
688
+ let newFormat = new FormatNode(
689
+ newFormats[0].format,
690
+ newFormats[0].segments
691
+ );
692
+
532
693
  // If after all that, it's empty, make sure there's one empty text node to type in.
533
694
  if (newFormat.getTextAndAtomNodes().length === 0)
534
695
  newFormat = new FormatNode('', [new TextNode()]);
@@ -536,210 +697,230 @@ export default class FormatNode extends Node {
536
697
  else {
537
698
  if (newFormat.#segments[0] instanceof AtomNode)
538
699
  newFormat = newFormat.withSegmentPrepended(new TextNode());
539
- if (newFormat.#segments[newFormat.getLength() - 1] instanceof
540
- AtomNode)
700
+ if (
701
+ newFormat.#segments[newFormat.getLength() - 1] instanceof
702
+ AtomNode
703
+ )
541
704
  newFormat = newFormat.withSegmentAppended(new TextNode());
542
705
  }
706
+
543
707
  return newFormat;
544
708
  }
545
- withRangeFormatted(range, format) {
709
+
710
+ withRangeFormatted(range: CaretRange, format: Format | undefined): Edit {
546
711
  // Convert the range to text indices.
547
712
  const text = caretRangeToIndexRange(this, range);
548
- if (text === undefined)
549
- return;
713
+ if (text === undefined) return;
550
714
  const newFormat = this.withFormat(range, format);
551
- if (newFormat === undefined)
552
- return;
715
+ if (newFormat === undefined) return;
553
716
  const newStart = indexToCaret(newFormat, text.start);
554
- const newEnd = format === undefined ? newStart : indexToCaret(newFormat, text.end);
555
- if (newStart === undefined || newEnd === undefined)
556
- return;
717
+ const newEnd =
718
+ format === undefined ? newStart : indexToCaret(newFormat, text.end);
719
+ if (newStart === undefined || newEnd === undefined) return;
557
720
  return { root: newFormat, range: { start: newStart, end: newEnd } };
558
721
  }
559
- getFormats(root) {
560
- let format = this;
561
- const formats = [];
722
+
723
+ getFormats(root: Node): Format[] {
724
+ let format: Node | undefined = this;
725
+ const formats: Format[] = [];
562
726
  while (format instanceof FormatNode) {
563
- if (format.#format !== '')
564
- formats.push(format.#format);
727
+ if (format.#format !== '') formats.push(format.#format);
565
728
  format = format.getParent(root);
566
729
  }
567
730
  return formats;
568
731
  }
569
- withSegmentAt(segment, caret) {
570
- if (!(caret.node instanceof TextNode))
571
- return;
732
+
733
+ withSegmentAt(
734
+ segment: FormatNodeSegmentType,
735
+ caret: Caret
736
+ ): FormatNode | undefined {
737
+ if (!(caret.node instanceof TextNode)) return;
738
+
572
739
  // Verify that the caret's node is a segment in this node.
573
740
  const index = this.#segments.indexOf(caret.node);
574
- if (index < 0)
575
- return;
741
+ if (index < 0) return;
742
+
576
743
  // Splice the text node.
577
- const left = new TextNode(caret.node.getText().substring(0, caret.index));
744
+ const left = new TextNode(
745
+ caret.node.getText().substring(0, caret.index)
746
+ );
578
747
  const right = new TextNode(caret.node.getText().substring(caret.index));
748
+
579
749
  // Insert the new left, right and middle
580
750
  const newSegments = this.#segments.slice();
581
751
  newSegments.splice(index, 1, left, segment, right);
582
752
  return new FormatNode(this.#format, newSegments);
583
753
  }
584
- withSegmentAtSelection(range, nodeCreator) {
754
+
755
+ withSegmentAtSelection(
756
+ range: CaretRange,
757
+ nodeCreator: (text: string) => FormatNodeSegmentType
758
+ ): Edit {
585
759
  // If there's a selection, grab it's text and then remove the text and update the root and text being edited.
586
760
  let selectedText = this.getSelectedText(range);
587
- let newFormat = this;
761
+ let newFormat: FormatNode | undefined = this;
588
762
  const sortedRange = this.sortRange(range);
589
763
  let caret = sortedRange.start;
590
- if (sortedRange.start.node !== sortedRange.end.node ||
591
- sortedRange.start.index !== sortedRange.end.index) {
764
+ if (
765
+ sortedRange.start.node !== sortedRange.end.node ||
766
+ sortedRange.start.index !== sortedRange.end.index
767
+ ) {
592
768
  // Try to remove the selected text. Bail on fail.
593
769
  const textIndex = caretToIndex(this, sortedRange.start);
594
- if (textIndex === undefined)
595
- return;
770
+ if (textIndex === undefined) return;
596
771
  newFormat = this.withoutRange(sortedRange);
597
- if (newFormat === undefined)
598
- return;
772
+ if (newFormat === undefined) return;
599
773
  const newCaret = indexToCaret(newFormat, textIndex);
600
- if (newCaret === undefined)
601
- return;
774
+ if (newCaret === undefined) return;
602
775
  caret = newCaret;
603
776
  }
777
+
604
778
  // Create and insert the into the formatted node.
605
- const newNode = nodeCreator.call(undefined, selectedText ? selectedText : '');
779
+ const newNode = nodeCreator.call(
780
+ undefined,
781
+ selectedText ? selectedText : ''
782
+ );
606
783
  const revisedFormat = newFormat.withSegmentAt(newNode, caret);
607
- if (revisedFormat === undefined)
608
- return;
609
- const newCaret = newNode instanceof AtomNode
610
- ? newNode.getDefaultCaret()
611
- : newNode instanceof FormatNode
784
+ if (revisedFormat === undefined) return;
785
+ const newCaret =
786
+ newNode instanceof AtomNode
787
+ ? newNode.getDefaultCaret()
788
+ : newNode instanceof FormatNode
612
789
  ? newNode.getFirstCaret()
613
790
  : newNode instanceof MetadataNode
614
- ? { node: newNode.getText(), index: 0 }
615
- : newNode instanceof TextNode
616
- ? { node: newNode, index: 0 }
617
- : undefined;
618
- if (newCaret === undefined)
619
- return;
791
+ ? { node: newNode.getText(), index: 0 }
792
+ : newNode instanceof TextNode
793
+ ? { node: newNode, index: 0 }
794
+ : undefined;
795
+
796
+ if (newCaret === undefined) return;
620
797
  return {
621
798
  root: revisedFormat,
622
799
  range: { start: newCaret, end: newCaret },
623
800
  };
624
801
  }
625
- withoutContentBefore(caret) {
802
+
803
+ withoutContentBefore(caret: Caret): FormatNode | undefined {
626
804
  return this.withContentAt(caret, false);
627
805
  }
628
- withoutContentAfter(caret) {
806
+
807
+ withoutContentAfter(caret: Caret): FormatNode | undefined {
629
808
  return this.withContentAt(caret, true);
630
809
  }
631
- withContentAt(caret, before) {
810
+
811
+ withContentAt(caret: Caret, before: boolean): FormatNode | undefined {
632
812
  let range = undefined;
633
813
  if (before) {
634
814
  const lastCaret = this.getLastCaret();
635
- if (lastCaret === undefined)
636
- return;
815
+ if (lastCaret === undefined) return;
637
816
  range = { start: caret, end: lastCaret };
638
- }
639
- else {
817
+ } else {
640
818
  const firstCaret = this.getFirstCaret();
641
- if (firstCaret === undefined)
642
- return;
819
+ if (firstCaret === undefined) return;
643
820
  range = { start: firstCaret, end: caret };
644
821
  }
645
822
  return this.withoutRange(range);
646
823
  }
647
- withContentInRange(range) {
824
+
825
+ withContentInRange(range: CaretRange): this | undefined {
648
826
  const containsStart = this.contains(range.start.node);
649
827
  const containsEnd = this.contains(range.end.node);
650
- if (!containsStart && !containsEnd)
651
- return this.copy();
828
+ if (!containsStart && !containsEnd) return this.copy();
652
829
  const startCaret = containsStart ? range.start : this.getFirstCaret();
653
830
  const endCaret = containsEnd ? range.end : this.getLastCaret();
654
- if (startCaret === undefined || endCaret === undefined)
655
- return;
831
+ if (startCaret === undefined || endCaret === undefined) return;
656
832
  const startIndex = caretToIndex(this, startCaret);
657
833
  const endIndex = caretToIndex(this, endCaret);
658
- if (startIndex === undefined || endIndex === undefined)
659
- return;
834
+ if (startIndex === undefined || endIndex === undefined) return;
660
835
  const withoutBefore = this.withoutContentBefore(startCaret);
661
- if (withoutBefore === undefined)
662
- return;
663
- const revisedEndCaret = indexToCaret(withoutBefore, endIndex - startIndex);
664
- if (revisedEndCaret === undefined)
665
- return;
666
- return withoutBefore.withoutContentAfter(revisedEndCaret);
667
- }
668
- withSegmentsAppended(format) {
836
+ if (withoutBefore === undefined) return;
837
+ const revisedEndCaret = indexToCaret(
838
+ withoutBefore,
839
+ endIndex - startIndex
840
+ );
841
+ if (revisedEndCaret === undefined) return;
842
+ return withoutBefore.withoutContentAfter(revisedEndCaret) as this;
843
+ }
844
+
845
+ withSegmentsAppended(format: FormatNode): FormatNode {
669
846
  return new FormatNode(this.#format, [
670
847
  ...this.#segments,
671
848
  ...format.getSegments(),
672
849
  ]);
673
850
  }
674
- withoutAdjacentContent(caret, next) {
851
+
852
+ withoutAdjacentContent(caret: Caret, next: boolean): Edit | undefined {
675
853
  return this.withoutCharacter(caret, next);
676
854
  }
677
- withoutCharacter(caret, next) {
855
+
856
+ withoutCharacter(caret: Caret, next: boolean): Edit | undefined {
678
857
  // Confirm that this caret is in this format.
679
- if (!this.contains(caret.node))
680
- return;
858
+ if (!this.contains(caret.node)) return;
681
859
  // Is there an adjascent caret? Return nothing if not.
682
860
  const adjacentCaret = this.getAdjacentCaret(caret, next);
683
- if (adjacentCaret === undefined)
684
- return;
861
+ if (adjacentCaret === undefined) return;
862
+
685
863
  // Handle each case differently
686
864
  if (caret.node instanceof AtomNode) {
687
865
  const newFormat = this.withNodeReplaced(caret.node, undefined);
688
- if (newFormat === undefined)
689
- return;
866
+ if (newFormat === undefined) return;
690
867
  return {
691
868
  root: newFormat,
692
869
  range: { start: adjacentCaret, end: adjacentCaret },
693
870
  };
694
- }
695
- else if (adjacentCaret.node instanceof AtomNode) {
696
- const newFormat = this.withNodeReplaced(adjacentCaret.node, undefined);
697
- if (newFormat === undefined)
698
- return;
871
+ } else if (adjacentCaret.node instanceof AtomNode) {
872
+ const newFormat = this.withNodeReplaced(
873
+ adjacentCaret.node,
874
+ undefined
875
+ );
876
+ if (newFormat === undefined) return;
699
877
  return { root: newFormat, range: { start: caret, end: caret } };
700
- }
701
- else {
878
+ } else {
702
879
  // If next, keep the caret in place, otherwise go to the adjacent caret position.
703
880
  const textIndex = caretToIndex(this, next ? caret : adjacentCaret);
704
- if (textIndex === undefined)
705
- return;
881
+ if (textIndex === undefined) return;
706
882
  // If there is one, try removing everything between this and the adjascent caret.
707
883
  const newFormat = this.withoutRange({
708
884
  start: caret,
709
885
  end: adjacentCaret,
710
886
  });
711
- if (newFormat === undefined)
712
- return;
887
+ if (newFormat === undefined) return;
713
888
  const newCaret = indexToCaret(newFormat, textIndex);
714
- if (newCaret === undefined)
715
- return;
889
+ if (newCaret === undefined) return;
716
890
  return {
717
891
  root: newFormat,
718
892
  range: { start: newCaret, end: newCaret },
719
893
  };
720
894
  }
721
895
  }
722
- withNodeInserted(caret, node) {
896
+
897
+ withNodeInserted(caret: Caret, node: Node): Edit {
723
898
  // The caret node has to be one of the nodes in this format to insert.
724
- const index = this.#segments.indexOf(caret.node);
725
- if (index < 0)
726
- return;
899
+ const index = this.#segments.indexOf(
900
+ caret.node as FormatNodeSegmentType
901
+ );
902
+ if (index < 0) return;
727
903
  // The inserted node has to be a segment type.
728
- if (!(node instanceof FormatNode ||
729
- node instanceof TextNode ||
730
- node instanceof MetadataNode ||
731
- node instanceof AtomNode))
904
+ if (
905
+ !(
906
+ node instanceof FormatNode ||
907
+ node instanceof TextNode ||
908
+ node instanceof MetadataNode ||
909
+ node instanceof AtomNode
910
+ )
911
+ )
732
912
  return;
913
+
733
914
  const newFormat = this.withSegmentAt(node, caret);
734
- const newCaret = node instanceof AtomNode
735
- ? node.getDefaultCaret()
736
- : node instanceof FormatNode
915
+ const newCaret =
916
+ node instanceof AtomNode
917
+ ? node.getDefaultCaret()
918
+ : node instanceof FormatNode
737
919
  ? node.getLastCaret()
738
920
  : node instanceof MetadataNode
739
- ? { node: node.getText(), index: node.getText().getLength() }
740
- : { node: node, index: node.getLength() };
741
- if (newFormat === undefined || newCaret === undefined)
742
- return;
921
+ ? { node: node.getText(), index: node.getText().getLength() }
922
+ : { node: node, index: node.getLength() };
923
+ if (newFormat === undefined || newCaret === undefined) return;
743
924
  return { root: newFormat, range: { start: newCaret, end: newCaret } };
744
925
  }
745
926
  }