bookish-press 0.4.0 → 0.4.16

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 (394) hide show
  1. package/README.md +3 -1
  2. package/components/Auth.svelte +19 -14
  3. package/components/Auth.svelte.d.ts +4 -4
  4. package/components/Authentication.d.ts +2 -2
  5. package/components/BookPreview.svelte +77 -59
  6. package/components/BookPreview.svelte.d.ts +5 -5
  7. package/components/External.svelte +1 -1
  8. package/components/External.svelte.d.ts +3 -3
  9. package/components/Link.svelte +49 -3
  10. package/components/Link.svelte.d.ts +3 -4
  11. package/components/app/BookList.svelte +19 -0
  12. package/components/app/BookList.svelte.d.ts +18 -0
  13. package/components/app/Button.svelte +49 -0
  14. package/components/app/Button.svelte.d.ts +22 -0
  15. package/components/app/Feedback.svelte +45 -0
  16. package/components/app/Feedback.svelte.d.ts +18 -0
  17. package/components/app/Head.svelte +12 -0
  18. package/components/app/Head.svelte.d.ts +27 -0
  19. package/components/app/Large.svelte +8 -0
  20. package/components/app/Large.svelte.d.ts +27 -0
  21. package/components/app/Lead.svelte +12 -0
  22. package/components/app/Lead.svelte.d.ts +27 -0
  23. package/components/app/Link.svelte +24 -0
  24. package/components/app/Link.svelte.d.ts +20 -0
  25. package/components/app/Options.svelte +24 -0
  26. package/components/app/Options.svelte.d.ts +19 -0
  27. package/components/app/Paragraph.svelte +19 -0
  28. package/components/app/Paragraph.svelte.d.ts +18 -0
  29. package/components/app/Table.svelte +32 -0
  30. package/components/app/Table.svelte.d.ts +27 -0
  31. package/components/app/TextInput.svelte +37 -0
  32. package/components/app/TextInput.svelte.d.ts +22 -0
  33. package/components/app/Writing.svelte +13 -0
  34. package/components/app/Writing.svelte.d.ts +27 -0
  35. package/components/chapter/Atom.svelte +20 -6
  36. package/components/chapter/Atom.svelte.d.ts +3 -3
  37. package/components/chapter/Block.svelte +23 -20
  38. package/components/chapter/Block.svelte.d.ts +4 -4
  39. package/components/chapter/Callout.svelte +38 -7
  40. package/components/chapter/Callout.svelte.d.ts +4 -4
  41. package/components/chapter/CaptionedCode.svelte +66 -23
  42. package/components/chapter/CaptionedCode.svelte.d.ts +4 -4
  43. package/components/chapter/ChapterBody.svelte +61 -9
  44. package/components/chapter/ChapterBody.svelte.d.ts +4 -4
  45. package/components/chapter/Citations.svelte +86 -20
  46. package/components/chapter/Citations.svelte.d.ts +4 -4
  47. package/components/chapter/Code.svelte +152 -21
  48. package/components/chapter/Code.svelte.d.ts +3 -3
  49. package/components/chapter/Comment.svelte +38 -16
  50. package/components/chapter/Comment.svelte.d.ts +3 -3
  51. package/components/chapter/Definition.svelte +52 -18
  52. package/components/chapter/Definition.svelte.d.ts +5 -8
  53. package/components/chapter/Embed.svelte +154 -66
  54. package/components/chapter/Embed.svelte.d.ts +5 -4
  55. package/components/chapter/ErrorMessage.svelte +7 -2
  56. package/components/chapter/ErrorMessage.svelte.d.ts +4 -4
  57. package/components/chapter/ExtendedPrism.d.ts +2 -0
  58. package/components/chapter/ExtendedPrism.js +69 -0
  59. package/components/chapter/Figure.svelte +90 -0
  60. package/components/chapter/Figure.svelte.d.ts +24 -0
  61. package/components/chapter/Footnote.svelte +75 -12
  62. package/components/chapter/Footnote.svelte.d.ts +4 -4
  63. package/components/chapter/Format.svelte +60 -37
  64. package/components/chapter/Format.svelte.d.ts +4 -4
  65. package/components/chapter/InlineCode.svelte +15 -5
  66. package/components/chapter/InlineCode.svelte.d.ts +4 -4
  67. package/components/chapter/Label.svelte +37 -8
  68. package/components/chapter/Label.svelte.d.ts +4 -4
  69. package/components/chapter/Link.svelte +23 -18
  70. package/components/chapter/Link.svelte.d.ts +4 -4
  71. package/components/chapter/List.svelte +75 -8
  72. package/components/chapter/List.svelte.d.ts +4 -4
  73. package/components/chapter/Marginal.svelte +169 -27
  74. package/components/chapter/Marginal.svelte.d.ts +6 -3
  75. package/components/chapter/Paragraph.svelte +74 -6
  76. package/components/chapter/Paragraph.svelte.d.ts +4 -4
  77. package/components/chapter/Positioned.svelte +33 -0
  78. package/components/chapter/Positioned.svelte.d.ts +19 -0
  79. package/components/chapter/Problem.svelte +15 -0
  80. package/components/chapter/Problem.svelte.d.ts +27 -0
  81. package/components/chapter/Python.svelte +68 -21
  82. package/components/chapter/Python.svelte.d.ts +4 -4
  83. package/components/chapter/Quote.svelte +64 -11
  84. package/components/chapter/Quote.svelte.d.ts +4 -4
  85. package/components/chapter/Rule.svelte +12 -1
  86. package/components/chapter/Rule.svelte.d.ts +4 -4
  87. package/components/chapter/Table.svelte +36 -25
  88. package/components/chapter/Table.svelte.d.ts +4 -4
  89. package/components/chapter/Text.svelte +61 -36
  90. package/components/chapter/Text.svelte.d.ts +5 -4
  91. package/components/editor/BookishEditor.svelte +343 -237
  92. package/components/editor/BookishEditor.svelte.d.ts +5 -5
  93. package/components/editor/CalloutEditor.svelte +5 -5
  94. package/components/editor/CalloutEditor.svelte.d.ts +4 -4
  95. package/components/editor/CaptionedCodeEditor.svelte +16 -12
  96. package/components/editor/CaptionedCodeEditor.svelte.d.ts +4 -4
  97. package/components/editor/CaretContext.d.ts +48 -16
  98. package/components/editor/CaretState.d.ts +16 -44
  99. package/components/editor/CaretUtilities.d.ts +2 -2
  100. package/components/editor/CaretView.svelte +80 -0
  101. package/components/editor/CaretView.svelte.d.ts +24 -0
  102. package/components/editor/CitationsEditor.svelte +36 -25
  103. package/components/editor/CitationsEditor.svelte.d.ts +4 -4
  104. package/components/editor/Clipboard.d.ts +2 -2
  105. package/components/editor/Command.d.ts +13 -12
  106. package/components/editor/Commands.d.ts +1 -1
  107. package/components/editor/Commands.js +1114 -571
  108. package/components/editor/ConfirmButton.svelte +18 -12
  109. package/components/editor/ConfirmButton.svelte.d.ts +5 -4
  110. package/components/editor/DefinitionEditor.svelte +29 -21
  111. package/components/editor/DefinitionEditor.svelte.d.ts +4 -4
  112. package/components/editor/EmbedEditor.svelte +93 -43
  113. package/components/editor/EmbedEditor.svelte.d.ts +3 -3
  114. package/components/editor/Icon.svelte +17 -0
  115. package/components/editor/Icon.svelte.d.ts +16 -0
  116. package/components/editor/ImageChooser.svelte +53 -34
  117. package/components/editor/ImageChooser.svelte.d.ts +3 -3
  118. package/components/editor/InlineCodeEditor.svelte +7 -4
  119. package/components/editor/InlineCodeEditor.svelte.d.ts +4 -4
  120. package/components/editor/LabelEditor.svelte +20 -11
  121. package/components/editor/LabelEditor.svelte.d.ts +4 -4
  122. package/components/editor/LanguageEditor.svelte +10 -7
  123. package/components/editor/LanguageEditor.svelte.d.ts +3 -3
  124. package/components/editor/LinkEditor.svelte +64 -39
  125. package/components/editor/LinkEditor.svelte.d.ts +4 -4
  126. package/components/editor/Note.svelte +3 -3
  127. package/components/editor/Note.svelte.d.ts +6 -2
  128. package/components/editor/PositionEditor.svelte +9 -6
  129. package/components/editor/PositionEditor.svelte.d.ts +4 -4
  130. package/components/editor/QuoteEditor.svelte +7 -2
  131. package/components/editor/QuoteEditor.svelte.d.ts +4 -4
  132. package/components/editor/Switch.svelte +55 -28
  133. package/components/editor/Switch.svelte.d.ts +4 -4
  134. package/components/editor/TableEditor.svelte +10 -0
  135. package/components/editor/TableEditor.svelte.d.ts +17 -0
  136. package/components/editor/TextEditor.svelte +83 -45
  137. package/components/editor/TextEditor.svelte.d.ts +5 -4
  138. package/components/editor/Toggle.svelte +11 -8
  139. package/components/editor/Toggle.svelte.d.ts +4 -4
  140. package/components/editor/Toolbar.svelte +192 -144
  141. package/components/editor/Toolbar.svelte.d.ts +5 -8
  142. package/components/editor/ToolbarGroup.svelte +18 -23
  143. package/components/editor/ToolbarGroup.svelte.d.ts +3 -4
  144. package/components/editor/ToolbarSpacer.svelte +8 -1
  145. package/components/editor/ToolbarSpacer.svelte.d.ts +6 -2
  146. package/components/editor/URLEditor.svelte +6 -8
  147. package/components/editor/URLEditor.svelte.d.ts +3 -3
  148. package/components/editor/UndoState.d.ts +3 -3
  149. package/components/editor/icons/annotate.svg +1 -0
  150. package/components/editor/icons/block.svg +1 -0
  151. package/components/editor/icons/bold.svg +1 -0
  152. package/components/editor/icons/bullets.svg +1 -0
  153. package/components/editor/icons/callout.svg +1 -0
  154. package/components/editor/icons/citation.svg +8 -0
  155. package/components/editor/icons/clear.svg +1 -0
  156. package/components/editor/icons/clipboard.svg +1 -0
  157. package/components/editor/icons/code.svg +1 -0
  158. package/components/editor/icons/columnafter.svg +1 -0
  159. package/components/editor/icons/columnbefore.svg +1 -0
  160. package/components/editor/icons/comment.svg +1 -0
  161. package/components/editor/icons/copy.svg +1 -0
  162. package/components/editor/icons/cut.svg +1 -0
  163. package/components/editor/icons/define.svg +7 -0
  164. package/components/editor/icons/deletecolumn.svg +1 -0
  165. package/components/editor/icons/deleterow.svg +1 -0
  166. package/components/editor/icons/footnote.svg +8 -0
  167. package/components/editor/icons/header1.svg +7 -0
  168. package/components/editor/icons/header2.svg +7 -0
  169. package/components/editor/icons/header3.svg +7 -0
  170. package/components/editor/icons/home.svg +1 -0
  171. package/components/editor/icons/indent.svg +1 -0
  172. package/components/editor/icons/italic.svg +1 -0
  173. package/components/editor/icons/label.svg +1 -0
  174. package/components/editor/icons/left.svg +1 -0
  175. package/components/editor/icons/level.svg +1 -0
  176. package/components/editor/icons/link.svg +1 -0
  177. package/components/editor/icons/list.svg +1 -0
  178. package/components/editor/icons/media.svg +1 -0
  179. package/components/editor/icons/middle.svg +1 -0
  180. package/components/editor/icons/numbers.svg +10 -0
  181. package/components/editor/icons/paragraph.svg +1 -0
  182. package/components/editor/icons/paste.svg +10 -0
  183. package/components/editor/icons/quote.svg +1 -0
  184. package/components/editor/icons/redo.svg +1 -0
  185. package/components/editor/icons/right.svg +1 -0
  186. package/components/editor/icons/rowabove.svg +1 -0
  187. package/components/editor/icons/rowbelow.svg +1 -0
  188. package/components/editor/icons/rule.svg +1 -0
  189. package/components/editor/icons/sub.svg +1 -0
  190. package/components/editor/icons/super.svg +1 -0
  191. package/components/editor/icons/table.svg +1 -0
  192. package/components/editor/icons/text.svg +1 -0
  193. package/components/editor/icons/time.svg +1 -0
  194. package/components/editor/icons/undo.svg +1 -0
  195. package/components/editor/icons/unindent.svg +1 -0
  196. package/components/editor/icons/unlink.svg +1 -0
  197. package/components/page/Acknowledgements.svelte +31 -22
  198. package/components/page/Acknowledgements.svelte.d.ts +4 -4
  199. package/components/page/Authors.svelte +34 -14
  200. package/components/page/Authors.svelte.d.ts +6 -6
  201. package/components/page/BulkReferenceEditor.svelte +53 -22
  202. package/components/page/BulkReferenceEditor.svelte.d.ts +4 -4
  203. package/components/page/Chapter.svelte +196 -141
  204. package/components/page/Chapter.svelte.d.ts +3 -3
  205. package/components/page/ChapterContext.d.ts +4 -4
  206. package/components/page/ChapterNumber.svelte +9 -0
  207. package/components/page/ChapterNumber.svelte.d.ts +27 -0
  208. package/components/page/ChapterTitle.svelte +16 -0
  209. package/components/page/ChapterTitle.svelte.d.ts +18 -0
  210. package/components/page/Contexts.d.ts +31 -20
  211. package/components/page/Contexts.js +47 -17
  212. package/components/page/DefinitionView.svelte +115 -86
  213. package/components/page/DefinitionView.svelte.d.ts +3 -3
  214. package/components/page/Description.svelte +27 -18
  215. package/components/page/Description.svelte.d.ts +4 -4
  216. package/components/page/Edition.svelte +127 -74
  217. package/components/page/Edition.svelte.d.ts +4 -4
  218. package/components/page/Editions.svelte +144 -0
  219. package/components/page/Editions.svelte.d.ts +14 -0
  220. package/components/page/Glossary.svelte +57 -48
  221. package/components/page/Glossary.svelte.d.ts +4 -4
  222. package/components/page/Header.svelte +129 -44
  223. package/components/page/Header.svelte.d.ts +6 -6
  224. package/components/page/Index.svelte +114 -80
  225. package/components/page/Index.svelte.d.ts +4 -4
  226. package/components/page/Instructions.svelte +18 -16
  227. package/components/page/Instructions.svelte.d.ts +4 -4
  228. package/components/page/License.svelte +29 -21
  229. package/components/page/License.svelte.d.ts +4 -4
  230. package/components/page/Loading.svelte +102 -12
  231. package/components/page/Loading.svelte.d.ts +6 -2
  232. package/components/page/Media.svelte +77 -51
  233. package/components/page/Media.svelte.d.ts +4 -4
  234. package/components/page/MediaPreview.svelte +26 -8
  235. package/components/page/MediaPreview.svelte.d.ts +3 -3
  236. package/components/page/Muted.svelte +10 -0
  237. package/components/page/Muted.svelte.d.ts +27 -0
  238. package/components/page/Outline.svelte +279 -59
  239. package/components/page/Outline.svelte.d.ts +3 -3
  240. package/components/page/Page.svelte +40 -9
  241. package/components/page/Page.svelte.d.ts +3 -3
  242. package/components/page/PageHeader.svelte +14 -0
  243. package/components/page/PageHeader.svelte.d.ts +18 -0
  244. package/components/page/PageParagraph.svelte +18 -0
  245. package/components/page/PageParagraph.svelte.d.ts +27 -0
  246. package/components/page/PossibleChapter.svelte +7 -7
  247. package/components/page/PossibleChapter.svelte.d.ts +4 -4
  248. package/components/page/PossibleReference.svelte +6 -11
  249. package/components/page/PossibleReference.svelte.d.ts +6 -7
  250. package/components/page/Print.svelte +27 -3
  251. package/components/page/Print.svelte.d.ts +4 -4
  252. package/components/page/Reference.svelte +256 -113
  253. package/components/page/Reference.svelte.d.ts +5 -5
  254. package/components/page/References.svelte +39 -47
  255. package/components/page/References.svelte.d.ts +4 -4
  256. package/components/page/Rows.svelte +54 -0
  257. package/components/page/Rows.svelte.d.ts +27 -0
  258. package/components/page/Search.svelte +86 -63
  259. package/components/page/Search.svelte.d.ts +4 -4
  260. package/components/page/Status.svelte +43 -35
  261. package/components/page/Status.svelte.d.ts +4 -9
  262. package/components/page/SubdomainEditor.svelte +40 -27
  263. package/components/page/SubdomainEditor.svelte.d.ts +4 -4
  264. package/components/page/TableOfContents.svelte +225 -190
  265. package/components/page/TableOfContents.svelte.d.ts +4 -4
  266. package/components/page/TableOfContentsImage.svelte +8 -8
  267. package/components/page/TableOfContentsImage.svelte.d.ts +3 -3
  268. package/components/page/TableOfContentsRow.svelte +96 -33
  269. package/components/page/TableOfContentsRow.svelte.d.ts +4 -4
  270. package/components/page/ThemeEditor.svelte +174 -39
  271. package/components/page/ThemeEditor.svelte.d.ts +4 -4
  272. package/components/page/ThemeEditorPreview.svelte +35 -23
  273. package/components/page/ThemeEditorPreview.svelte.d.ts +5 -5
  274. package/components/page/ThemeSetEditor.svelte +15 -13
  275. package/components/page/ThemeSetEditor.svelte.d.ts +4 -4
  276. package/components/page/ThemeVariableEditor.svelte +24 -15
  277. package/components/page/ThemeVariableEditor.svelte.d.ts +3 -3
  278. package/components/page/Title.svelte +12 -0
  279. package/components/page/Title.svelte.d.ts +27 -0
  280. package/components/page/Unknown.svelte +25 -21
  281. package/components/page/Unknown.svelte.d.ts +4 -4
  282. package/components/page/margins.js +50 -33
  283. package/index.d.ts +14 -0
  284. package/index.js +14 -0
  285. package/models/CRUD.d.ts +17 -0
  286. package/models/CRUD.js +194 -0
  287. package/models/Firebase.js +17 -15
  288. package/models/book/Book.d.ts +24 -28
  289. package/models/book/Book.js +120 -113
  290. package/models/book/BookMedia.d.ts +3 -3
  291. package/models/book/BookMedia.js +22 -16
  292. package/models/book/BookSaveStatus.d.ts +7 -0
  293. package/models/book/BookSaveStatus.js +8 -0
  294. package/models/book/Chapter.d.ts +46 -39
  295. package/models/book/Chapter.js +180 -198
  296. package/models/book/ChapterID.js +7 -7
  297. package/models/book/Definition.d.ts +1 -1
  298. package/models/book/Edition.d.ts +62 -60
  299. package/models/book/Edition.js +385 -303
  300. package/models/book/Reference.d.ts +24 -0
  301. package/models/book/Reference.js +78 -0
  302. package/models/book/Schema.d.ts +169 -0
  303. package/models/book/Schema.js +114 -0
  304. package/models/book/Theme.d.ts +44 -37
  305. package/models/book/Theme.js +452 -52
  306. package/models/book/ThemeColors.d.ts +1 -1
  307. package/models/book/Words.d.ts +2 -0
  308. package/models/book/Words.js +110 -0
  309. package/models/chapter/AtomNode.d.ts +4 -4
  310. package/models/chapter/AtomNode.js +20 -13
  311. package/models/chapter/BlockNode.d.ts +9 -10
  312. package/models/chapter/BlockNode.js +32 -13
  313. package/models/chapter/BlocksNode.d.ts +10 -10
  314. package/models/chapter/BlocksNode.js +315 -120
  315. package/models/chapter/BlocksNode.test.js +494 -228
  316. package/models/chapter/Bookkeeping.d.ts +1 -1
  317. package/models/chapter/CalloutNode.d.ts +3 -3
  318. package/models/chapter/CalloutNode.js +34 -12
  319. package/models/chapter/Caret.d.ts +9 -7
  320. package/models/chapter/Caret.js +11 -6
  321. package/models/chapter/ChapterNode.d.ts +11 -11
  322. package/models/chapter/ChapterNode.js +70 -33
  323. package/models/chapter/CitationsNode.d.ts +3 -3
  324. package/models/chapter/CitationsNode.js +31 -12
  325. package/models/chapter/CodeNode.d.ts +11 -6
  326. package/models/chapter/CodeNode.js +143 -34
  327. package/models/chapter/CommentNode.d.ts +5 -5
  328. package/models/chapter/CommentNode.js +29 -13
  329. package/models/chapter/DefinitionNode.d.ts +2 -2
  330. package/models/chapter/DefinitionNode.js +15 -7
  331. package/models/chapter/Edit.d.ts +3 -3
  332. package/models/chapter/EmbedNode.d.ts +9 -5
  333. package/models/chapter/EmbedNode.js +108 -35
  334. package/models/chapter/ErrorNode.d.ts +2 -2
  335. package/models/chapter/ErrorNode.js +34 -12
  336. package/models/chapter/FootnoteNode.d.ts +5 -5
  337. package/models/chapter/FootnoteNode.js +34 -16
  338. package/models/chapter/FormatNode.d.ts +10 -10
  339. package/models/chapter/FormatNode.js +237 -106
  340. package/models/chapter/FormatNode.test.js +87 -45
  341. package/models/chapter/InlineCodeNode.d.ts +2 -2
  342. package/models/chapter/InlineCodeNode.js +22 -9
  343. package/models/chapter/LabelNode.d.ts +4 -4
  344. package/models/chapter/LabelNode.js +31 -13
  345. package/models/chapter/LinkNode.d.ts +2 -2
  346. package/models/chapter/LinkNode.js +21 -9
  347. package/models/chapter/ListNode.d.ts +8 -8
  348. package/models/chapter/ListNode.js +99 -38
  349. package/models/chapter/ListNode.test.js +29 -24
  350. package/models/chapter/MetadataNode.d.ts +3 -3
  351. package/models/chapter/MetadataNode.js +13 -5
  352. package/models/chapter/Node.d.ts +5 -3
  353. package/models/chapter/Node.js +76 -29
  354. package/models/chapter/Node.test.js +20 -18
  355. package/models/chapter/ParagraphNode.d.ts +6 -6
  356. package/models/chapter/ParagraphNode.js +84 -29
  357. package/models/chapter/ParagraphNode.test.js +22 -13
  358. package/models/chapter/Parser.d.ts +25 -25
  359. package/models/chapter/Parser.js +201 -189
  360. package/models/chapter/Parser.test.js +16 -16
  361. package/models/chapter/Position.d.ts +1 -1
  362. package/models/chapter/QuoteNode.d.ts +6 -6
  363. package/models/chapter/QuoteNode.js +61 -23
  364. package/models/chapter/RootNode.d.ts +4 -4
  365. package/models/chapter/RuleNode.d.ts +2 -2
  366. package/models/chapter/RuleNode.js +31 -11
  367. package/models/chapter/TableNode.d.ts +8 -6
  368. package/models/chapter/TableNode.js +89 -34
  369. package/models/chapter/TableNode.test.js +22 -24
  370. package/models/chapter/TextNode.d.ts +6 -6
  371. package/models/chapter/TextNode.js +72 -32
  372. package/models/chapter/TextNode.test.js +4 -4
  373. package/models/loadEdition.d.ts +1 -1
  374. package/models/loadEdition.js +10 -6
  375. package/package.json +104 -25
  376. package/util/getSubdomain.js +8 -6
  377. package/util/isMobile.js +1 -1
  378. package/util/mineReference.d.ts +3 -2
  379. package/util/mineReference.js +67 -29
  380. package/util/scrollToEyeLevel.js +6 -1
  381. package/components/chapter/renderPosition.d.ts +0 -3
  382. package/components/chapter/renderPosition.js +0 -4
  383. package/components/editor/ToolbarIcon.svelte +0 -22
  384. package/components/editor/ToolbarIcon.svelte.d.ts +0 -16
  385. package/components/page/Alert.svelte +0 -11
  386. package/components/page/Alert.svelte.d.ts +0 -23
  387. package/components/page/Revisions.svelte +0 -124
  388. package/components/page/Revisions.svelte.d.ts +0 -14
  389. package/models/BookLoader.d.ts +0 -2
  390. package/models/BookLoader.js +0 -67
  391. package/models/Firestore.d.ts +0 -22
  392. package/models/Firestore.js +0 -194
  393. package/models/chapter/ReferenceNode.d.ts +0 -29
  394. package/models/chapter/ReferenceNode.js +0 -48
@@ -1,38 +1,50 @@
1
- import BlockNode from "./BlockNode";
2
- import ListNode from "./ListNode";
3
- import { caretToIndex, indexToCaret } from "./Caret";
4
- import ParagraphNode from "./ParagraphNode";
5
- import FormatNode from "./FormatNode";
6
- import TextNode from "./TextNode";
7
- import AtomNode from "./AtomNode";
8
- import CodeNode from "./CodeNode";
1
+ import BlockNode from './BlockNode';
2
+ import ListNode from './ListNode';
3
+ import { caretToIndex, indexToCaret } from './Caret';
4
+ import ParagraphNode from './ParagraphNode';
5
+ import FormatNode from './FormatNode';
6
+ import TextNode from './TextNode';
7
+ import AtomNode from './AtomNode';
8
+ import CodeNode from './CodeNode';
9
+ import EmbedNode from './EmbedNode';
9
10
  export default class BlocksNode extends BlockNode {
10
11
  #blocks;
11
12
  constructor(elements) {
12
13
  super();
13
- // Always ensure there's an empty paragraph before and after non-paragraph nodes to allow for insertions.
14
14
  const adjustedElements = [];
15
15
  for (let i = 0; i < elements.length; i++) {
16
16
  const block = elements[i];
17
17
  const previousBlock = i === 0 ? undefined : elements[i - 1];
18
18
  // If this block and the previous one are lists of the same kind, merge them.
19
- if (block instanceof ListNode && previousBlock instanceof ListNode && block.isNumbered() === previousBlock.isNumbered()) {
20
- adjustedElements[adjustedElements.length - 1] = previousBlock.withListAppended(block);
19
+ if (block instanceof ListNode &&
20
+ previousBlock instanceof ListNode &&
21
+ block.isNumbered() === previousBlock.isNumbered()) {
22
+ adjustedElements[adjustedElements.length - 1] =
23
+ previousBlock.withListAppended(block);
21
24
  }
22
- // If the block isn't a paragraph and the last one isn't either or this is the first one., put a paragraph between them to allow for insertion.
23
- else {
24
- if (!(block instanceof ParagraphNode) && (i === 0 || !(previousBlock instanceof ParagraphNode)))
25
- adjustedElements.push(new ParagraphNode());
25
+ // Always ensure there's an empty paragraph before and after non-paragraph nodes to allow for insertions.
26
+ // // If the block isn't a paragraph and the last one isn't either or this is the first one, put a paragraph between them to allow for insertion.
27
+ // else {
28
+ // if(!(block instanceof ParagraphNode) && (i === 0 || !(previousBlock instanceof ParagraphNode)))
29
+ // adjustedElements.push(new ParagraphNode());
30
+ // }
31
+ else
26
32
  adjustedElements.push(block);
27
- }
28
33
  }
29
34
  // Check the last one.
30
- if (!(adjustedElements[adjustedElements.length - 1] instanceof ParagraphNode))
31
- adjustedElements.push(new ParagraphNode());
35
+ // if(!(adjustedElements[adjustedElements.length - 1] instanceof ParagraphNode))
36
+ // adjustedElements.push(new ParagraphNode());
32
37
  this.#blocks = adjustedElements;
38
+ // After all that, always ensure there's at least one empty paragraph block.
39
+ if (this.#blocks.length === 0)
40
+ this.#blocks.push(new ParagraphNode());
41
+ }
42
+ getBlocks() {
43
+ return this.#blocks;
44
+ }
45
+ getFormats() {
46
+ return this.getBlocks().reduce((prev, current) => prev.concat(current.getFormats()), []);
33
47
  }
34
- getBlocks() { return this.#blocks; }
35
- getFormats() { return this.getBlocks().reduce((prev, current) => prev.concat(current.getFormats()), []); }
36
48
  getIndexOf(block) {
37
49
  const index = this.#blocks.indexOf(block);
38
50
  return index < 0 ? undefined : index;
@@ -77,14 +89,18 @@ export default class BlocksNode extends BlockNode {
77
89
  getBlocksInRange(range) {
78
90
  // Find the start and end block the carets reside in. Bail on fail.
79
91
  const startBlock = this.getBlockOfCaret(range.start);
80
- const endBlock = range.end === range.start ? startBlock : this.getBlockOfCaret(range.end);
92
+ const endBlock = range.end === range.start
93
+ ? startBlock
94
+ : this.getBlockOfCaret(range.end);
81
95
  if (startBlock === undefined || endBlock === undefined)
82
96
  return;
83
97
  // Find all of the blocks between the start and end blocks.
84
98
  // Start tracking when we hit the start node. Stop tracking when we hit the end node.
85
99
  const blocksToEdit = [];
86
100
  let insideSelection = false;
87
- this.getNodes().filter(n => n instanceof BlockNode).forEach(node => {
101
+ this.getNodes()
102
+ .filter((n) => n instanceof BlockNode)
103
+ .forEach((node) => {
88
104
  if (node === startBlock)
89
105
  insideSelection = true;
90
106
  if (insideSelection && node instanceof BlockNode)
@@ -98,16 +114,18 @@ export default class BlocksNode extends BlockNode {
98
114
  return caret.node.getClosestParentOfType(this, BlockNode);
99
115
  }
100
116
  getParentOf(node) {
101
- return this.#blocks.map(b => b === node ? this : b.getParentOf(node)).find(b => b !== undefined);
117
+ return this.#blocks
118
+ .map((b) => (b === node ? this : b.getParentOf(node)))
119
+ .find((b) => b !== undefined);
102
120
  }
103
121
  getTextNodes() {
104
- return this.getNodes().filter(node => node instanceof TextNode);
122
+ return this.getNodes().filter((node) => node instanceof TextNode);
105
123
  }
106
124
  getAtomNodes() {
107
- return this.getNodes().filter(node => node instanceof AtomNode);
125
+ return this.getNodes().filter((node) => node instanceof AtomNode);
108
126
  }
109
127
  getTextAndAtomNodes() {
110
- return this.getNodes().filter(node => node instanceof TextNode || node instanceof AtomNode);
128
+ return this.getNodes().filter((node) => node instanceof TextNode || node instanceof AtomNode);
111
129
  }
112
130
  getIndexOfTextNode(node) {
113
131
  const text = this.getTextNodes();
@@ -119,23 +137,30 @@ export default class BlocksNode extends BlockNode {
119
137
  }
120
138
  getLastCaret() {
121
139
  const text = this.getTextNodes();
122
- return text.length === 0 ? undefined : { node: text[text.length - 1], index: text[text.length - 1].getLength() };
140
+ return text.length === 0
141
+ ? undefined
142
+ : {
143
+ node: text[text.length - 1],
144
+ index: text[text.length - 1].getLength(),
145
+ };
123
146
  }
124
147
  getAdjacentCaret(caret, next) {
125
148
  if (!this.contains(caret.node))
126
149
  return;
127
150
  // Navigate from code node.
128
- const code = caret.node.getFarthestParentMatching(this, n => n instanceof CodeNode);
151
+ const code = caret.node.getFarthestParentMatching(this, (n) => n instanceof CodeNode);
129
152
  if (code && caret.node === code.getCodeNode()) {
130
153
  // Get the adjacent text node.
131
- const newCaret = next ? caret.node.getNextCaret(caret.index) : caret.node.getPreviousCaret(caret.index);
154
+ const newCaret = next
155
+ ? caret.node.getNextCaret(caret.index)
156
+ : caret.node.getPreviousCaret(caret.index);
132
157
  if (newCaret !== undefined)
133
158
  return newCaret;
134
159
  // Otherwise, get the adjacent format's first/last caret.
135
160
  if (next)
136
161
  return code.getCaption().getFirstCaret();
137
162
  // If there's no adjacent caret, find the adjacent root format.
138
- const blocks = this.getNodes().filter(n => n instanceof BlockNode);
163
+ const blocks = this.getNodes().filter((n) => n instanceof BlockNode);
139
164
  const codeIndex = blocks.indexOf(code);
140
165
  if (codeIndex <= 0)
141
166
  return;
@@ -144,7 +169,7 @@ export default class BlocksNode extends BlockNode {
144
169
  const adjacentFormat = adjacentFormats[adjacentFormats.length - 1];
145
170
  return adjacentFormat.getLastCaret();
146
171
  }
147
- const format = caret.node.getFarthestParentMatching(this, n => n instanceof FormatNode);
172
+ const format = caret.node.getFarthestParentMatching(this, (n) => n instanceof FormatNode);
148
173
  if (format === undefined)
149
174
  return;
150
175
  // Find the format that contains the caret and return the adjacent caret if there is one.
@@ -152,26 +177,34 @@ export default class BlocksNode extends BlockNode {
152
177
  if (adjacentCaretInFormat !== undefined)
153
178
  return adjacentCaretInFormat;
154
179
  // If there's no adjacent caret in the root format, find the adjacent format or code.
155
- const formats = this.getNodes().filter(n => {
180
+ const formats = this.getNodes().filter((n) => {
156
181
  const parent = n.getParent(this);
157
- return (n instanceof TextNode && parent instanceof CodeNode) || (n instanceof FormatNode && !(parent instanceof AtomNode) && !(parent instanceof FormatNode));
182
+ return ((n instanceof TextNode && parent instanceof CodeNode) ||
183
+ (n instanceof FormatNode &&
184
+ !(parent instanceof AtomNode) &&
185
+ !(parent instanceof FormatNode)));
158
186
  });
159
187
  const index = formats.indexOf(format);
160
- const adjacentFormat = index < 0 || formats.length === 0 ? undefined : formats[index + (next ? 1 : -1)];
188
+ const adjacentFormat = index < 0 || formats.length === 0
189
+ ? undefined
190
+ : formats[index + (next ? 1 : -1)];
161
191
  if (adjacentFormat === undefined)
162
192
  return;
163
- return next ? adjacentFormat.getFirstCaret() : adjacentFormat.getLastCaret();
193
+ return next
194
+ ? adjacentFormat.getFirstCaret()
195
+ : adjacentFormat.getLastCaret();
164
196
  }
165
197
  getSelectedFormatRange(format, range) {
166
198
  // Find all of the formats.
167
- const formats = this.getNodes().filter(n => n instanceof FormatNode && !(this.getParentOf(n) instanceof FormatNode));
199
+ const formats = this.getNodes().filter((n) => n instanceof FormatNode &&
200
+ !(this.getParentOf(n) instanceof FormatNode));
168
201
  // Find the given format index.
169
202
  const formatIndex = formats.indexOf(format);
170
203
  if (formatIndex < 0)
171
204
  return undefined;
172
205
  // Find the range start and end formats.
173
- const startFormat = formats.find(f => f.contains(range.start.node));
174
- const endFormat = formats.find(f => f.contains(range.end.node));
206
+ const startFormat = formats.find((f) => f.contains(range.start.node));
207
+ const endFormat = formats.find((f) => f.contains(range.end.node));
175
208
  if (startFormat === undefined || endFormat === undefined)
176
209
  return undefined;
177
210
  const startIndex = formats.indexOf(startFormat);
@@ -225,7 +258,7 @@ export default class BlocksNode extends BlockNode {
225
258
  return this.create(newBlocks);
226
259
  }
227
260
  withoutBlock(block) {
228
- return this.create(this.#blocks.filter(n => n !== block));
261
+ return this.create(this.#blocks.filter((n) => n !== block));
229
262
  }
230
263
  withBlockInsertedBefore(anchor, block) {
231
264
  return this.withBlockInserted(anchor, block, true);
@@ -237,48 +270,71 @@ export default class BlocksNode extends BlockNode {
237
270
  let caret = range.start;
238
271
  let blocks = this;
239
272
  // If there's a selection, remove it before inserting.
240
- if (range.start.node !== range.end.node || range.start.index !== range.end.index) {
273
+ if (range.start.node !== range.end.node ||
274
+ range.start.index !== range.end.index) {
241
275
  const edit = blocks.withoutRange(range);
242
276
  if (edit === undefined || !(edit.root instanceof BlocksNode))
243
277
  return;
244
278
  blocks = edit.root;
245
279
  caret = edit.range.start;
246
280
  }
247
- // Find what paragraph the caret is in.
248
- // There are some contexts with no paragraphs. Return the start range given.
249
- const paragraph = caret.node.getClosestParentOfType(blocks, ParagraphNode);
250
- if (paragraph === undefined)
251
- return;
252
- // Split the paragraph in two.
253
- const split = paragraph.split(caret);
254
- if (split === undefined)
281
+ // Find what block the caret is in.
282
+ const block = caret.node.getClosestParentOfType(blocks, BlockNode);
283
+ if (block === undefined)
255
284
  return;
256
- const [first, last] = split;
257
- const newCaret = last.getFirstCaret();
258
- if (newCaret === undefined)
259
- return;
260
- // Find the paragraph's blocks node.
261
- const paragraphBlocks = paragraph.getParent(blocks);
262
- if (!(paragraphBlocks instanceof BlocksNode))
263
- return;
264
- const newBlocks = paragraphBlocks
265
- .withBlockInsertedBefore(paragraph, first)
266
- ?.withBlockInsertedAfter(paragraph, last)
267
- ?.withoutBlock(paragraph);
268
- if (newBlocks === undefined)
269
- return;
270
- // Replace the paragraphs blocks in these blocks.
271
- const newRoot = blocks.withNodeReplaced(paragraphBlocks, newBlocks);
272
- if (newRoot === undefined)
273
- return;
274
- return { root: newRoot, range: { start: newCaret, end: newCaret } };
285
+ // If it's a paragraph, split it.
286
+ if (block instanceof ParagraphNode) {
287
+ const paragraph = block;
288
+ // Split the paragraph in two.
289
+ const split = paragraph.split(caret);
290
+ if (split === undefined)
291
+ return;
292
+ const [first, last] = split;
293
+ const newCaret = last.getFirstCaret();
294
+ if (newCaret === undefined)
295
+ return;
296
+ // Find the paragraph's blocks node.
297
+ const paragraphBlocks = paragraph.getParent(blocks);
298
+ if (!(paragraphBlocks instanceof BlocksNode))
299
+ return;
300
+ const newBlocks = paragraphBlocks
301
+ .withBlockInsertedBefore(paragraph, first)
302
+ ?.withBlockInsertedAfter(paragraph, last)
303
+ ?.withoutBlock(paragraph);
304
+ if (newBlocks === undefined)
305
+ return;
306
+ // Replace the paragraphs blocks in these blocks.
307
+ const newRoot = blocks.withNodeReplaced(paragraphBlocks, newBlocks);
308
+ if (newRoot === undefined)
309
+ return;
310
+ return { root: newRoot, range: { start: newCaret, end: newCaret } };
311
+ }
312
+ // If any other kind of block, and an empty paragraph after the block.
313
+ else {
314
+ // Find the paragraph's blocks node.
315
+ const container = block.getParent(blocks);
316
+ if (!(container instanceof BlocksNode))
317
+ return;
318
+ const newParagraph = new ParagraphNode();
319
+ const newCaret = newParagraph.getFirstCaret();
320
+ if (newCaret === undefined)
321
+ return;
322
+ const newBlocks = container.withBlockInsertedAfter(block, newParagraph);
323
+ if (newBlocks === undefined)
324
+ return;
325
+ // Replace the paragraphs blocks in these blocks.
326
+ const newRoot = blocks.withNodeReplaced(container, newBlocks);
327
+ if (newRoot === undefined)
328
+ return;
329
+ return { root: newRoot, range: { start: newCaret, end: newCaret } };
330
+ }
275
331
  }
276
332
  withoutRange(range) {
277
333
  return this.withRangeFormatted(range, undefined);
278
334
  }
279
335
  withoutAtom(atom) {
280
336
  // Find the format that contains the atom.
281
- const format = atom.getFarthestParentMatching(this, p => p instanceof FormatNode);
337
+ const format = atom.getFarthestParentMatching(this, (p) => p instanceof FormatNode);
282
338
  if (format === undefined)
283
339
  return;
284
340
  // Find the text or atom node to the left and right of the atom to determine the new caret position.
@@ -286,11 +342,16 @@ export default class BlocksNode extends BlockNode {
286
342
  const next = format.getNextTextOrAtom(atom);
287
343
  const newText = new TextNode();
288
344
  // If the format is otherwise empty, replace the atom with an empty text node
289
- const newFormat = previous === undefined && next == undefined ?
290
- format.withSegmentReplaced(atom, newText) :
291
- format.withoutSegment(atom);
345
+ const newFormat = previous === undefined && next == undefined
346
+ ? format.withSegmentReplaced(atom, newText)
347
+ : format.withoutSegment(atom);
292
348
  // New caret is left, or right, or empty text.
293
- const newCaret = { node: previous ? previous : next ? next : newText, index: previous && previous instanceof TextNode ? previous.getLength() : 0 };
349
+ const newCaret = {
350
+ node: previous ? previous : next ? next : newText,
351
+ index: previous && previous instanceof TextNode
352
+ ? previous.getLength()
353
+ : 0,
354
+ };
294
355
  // No format? Fail.
295
356
  if (newFormat === undefined)
296
357
  return;
@@ -303,18 +364,27 @@ export default class BlocksNode extends BlockNode {
303
364
  }
304
365
  withRangeFormatted(range, format) {
305
366
  // Only works on text nodes, atom nodes, and metadata nodes.
306
- if (!(range.start.node instanceof TextNode || range.start.node instanceof AtomNode) ||
307
- !(range.end.node instanceof TextNode || range.end.node instanceof AtomNode))
367
+ if (!(range.start.node instanceof TextNode ||
368
+ range.start.node instanceof AtomNode) ||
369
+ !(range.end.node instanceof TextNode ||
370
+ range.end.node instanceof AtomNode))
308
371
  return;
309
372
  // Have we selected a single atom node for removal? Remove it and place the caret in the adjacent word.
310
- if (format === undefined && (range.start.node instanceof AtomNode && range.end.node instanceof AtomNode && range.start.node === range.end.node)) {
373
+ if (format === undefined &&
374
+ range.start.node instanceof AtomNode &&
375
+ range.end.node instanceof AtomNode &&
376
+ range.start.node === range.end.node) {
311
377
  return this.withoutAtom(range.start.node);
312
378
  }
313
379
  // Preserve the original range, since there are a few cases where we adjust it.
314
380
  let adjustedRange = range;
315
381
  // If this a single point in format, and we're clearing formatting, adjust the selection to the whole format.
316
- if (format === "" && range.start.node === range.end.node && range.start.index === range.end.index) {
317
- const selection = range.start.node.getFormatRoot(this)?.getSelection();
382
+ if (format === '' &&
383
+ range.start.node === range.end.node &&
384
+ range.start.index === range.end.index) {
385
+ const selection = range.start.node
386
+ .getFormatRoot(this)
387
+ ?.getSelection();
318
388
  if (selection === undefined)
319
389
  return;
320
390
  adjustedRange = selection;
@@ -337,8 +407,12 @@ export default class BlocksNode extends BlockNode {
337
407
  if (containsStart || containsEnd || inRange) {
338
408
  inRange = true;
339
409
  // Compute a proper range based on containment.
340
- const blockStart = containsStart ? sortedRange.start : block.getFirstCaret();
341
- const blockEnd = containsEnd ? sortedRange.end : block.getLastCaret();
410
+ const blockStart = containsStart
411
+ ? sortedRange.start
412
+ : block.getFirstCaret();
413
+ const blockEnd = containsEnd
414
+ ? sortedRange.end
415
+ : block.getLastCaret();
342
416
  if (blockStart === undefined || blockEnd === undefined)
343
417
  return;
344
418
  // If we're just going to delete it, then don't bother formatting it.
@@ -354,16 +428,40 @@ export default class BlocksNode extends BlockNode {
354
428
  if (edit === undefined)
355
429
  return;
356
430
  // If we succeeded in formatting it, replace it, otherwise skip it.
431
+ let newBlock = edit.root;
432
+ // Finally, if the selection started before a list node, and we were deleting in the middle of some item,
433
+ // convert that item (which should now be the first item in the list) into a paragraph, since it's bullet was deleted, conceptually.
434
+ if (!newBlock.isEmpty() &&
435
+ newBlock instanceof ListNode &&
436
+ !containsStart &&
437
+ containsEnd) {
438
+ const firstItem = newBlock.getItem(0);
439
+ if (firstItem instanceof FormatNode) {
440
+ // Remove the item from the list.
441
+ const newListWithoutItem = newBlock.withoutItem(firstItem);
442
+ if (newListWithoutItem === undefined)
443
+ return;
444
+ newBlock = newListWithoutItem;
445
+ // Replace the revised list
446
+ const blocksWithList = newBlocks
447
+ .withChildReplaced(block, newBlock)
448
+ ?.withBlockInsertedBefore(newBlock, new ParagraphNode(0, firstItem));
449
+ if (blocksWithList === undefined)
450
+ return;
451
+ newBlocks = blocksWithList;
452
+ }
453
+ }
454
+ // Otherwise, just handle the new block in isolation.
357
455
  else {
358
- const newBlock = edit.root;
359
456
  // Remember non-empty revised blocks so we can merge things after.
360
457
  if (!newBlock.isEmpty())
361
458
  formattedBlocks.push(newBlock);
362
459
  // Replace the block, or delete it if it's empty.
363
460
  newBlocks = newBlocks.withChildReplaced(block, newBlock.isEmpty() ? undefined : newBlock);
364
- if (newBlocks === undefined)
365
- return;
366
461
  }
462
+ // If we failed to replace it, bail.
463
+ if (newBlocks === undefined)
464
+ return;
367
465
  }
368
466
  }
369
467
  if (block.contains(sortedRange.end.node))
@@ -373,7 +471,8 @@ export default class BlocksNode extends BlockNode {
373
471
  if (format === undefined && formattedBlocks.length >= 2) {
374
472
  const first = formattedBlocks[0];
375
473
  const last = formattedBlocks[formattedBlocks.length - 1];
376
- if (first instanceof ParagraphNode && last instanceof ParagraphNode) {
474
+ if (first instanceof ParagraphNode &&
475
+ last instanceof ParagraphNode) {
377
476
  // Replace the first paragraph with the second merged.
378
477
  newBlocks = newBlocks.withNodeReplaced(first, first.withContent(first.getFormat().withSegmentsAppended(last.getFormat())));
379
478
  if (newBlocks === undefined)
@@ -386,7 +485,9 @@ export default class BlocksNode extends BlockNode {
386
485
  }
387
486
  const startCaret = indexToCaret(newBlocks, startTextIndex);
388
487
  // If we deleted, then the end caret should be the same as the start.
389
- const endCaret = format === undefined ? startCaret : indexToCaret(newBlocks, endTextIndex);
488
+ const endCaret = format === undefined
489
+ ? startCaret
490
+ : indexToCaret(newBlocks, endTextIndex);
390
491
  if (startCaret === undefined || endCaret === undefined)
391
492
  return;
392
493
  // Return the new root and the start and end of the range.
@@ -417,13 +518,14 @@ export default class BlocksNode extends BlockNode {
417
518
  if (blocksInRange === undefined)
418
519
  return;
419
520
  // Only format if every block selected is a paragraph node. Non-paragraphs can't be in lists.
420
- if (!blocksInRange.every(b => b instanceof ParagraphNode))
521
+ if (!blocksInRange.every((b) => b instanceof ParagraphNode))
421
522
  return;
422
523
  // Split the blocks into groups with shared parents.
423
524
  const sequences = [[]];
424
525
  let previous = undefined;
425
- blocksInRange.forEach(block => {
426
- if (previous === undefined || block.getParent(this) === previous.getParent(this))
526
+ blocksInRange.forEach((block) => {
527
+ if (previous === undefined ||
528
+ block.getParent(this) === previous.getParent(this))
427
529
  sequences[sequences.length - 1].push(block);
428
530
  else {
429
531
  sequences.push([block]);
@@ -435,7 +537,7 @@ export default class BlocksNode extends BlockNode {
435
537
  for (let i = 0; i < sequences.length; i++) {
436
538
  const sequence = sequences[i];
437
539
  // Make the new list
438
- const newList = new ListNode(sequence.map(p => p.getFormat()), numbered);
540
+ const newList = new ListNode(sequence.map((p) => p.getFormat()), numbered);
439
541
  // Insert the new list
440
542
  const blocksParent = sequence[0].getParent(newBlocks);
441
543
  if (blocksParent === undefined)
@@ -462,14 +564,23 @@ export default class BlocksNode extends BlockNode {
462
564
  if (blocksInRange === undefined)
463
565
  return;
464
566
  // Convert all of the lists into their root lists, since we only convert entire lists, not parts of lists.
465
- const listsInRange = blocksInRange.filter(l => l instanceof ListNode);
466
- const listRootsInRange = [...new Set(listsInRange.map(l => l.getParent(this) instanceof ListNode ? l.getFarthestParentMatching(this, m => m instanceof ListNode) : l).filter(n => n !== undefined))];
567
+ const listsInRange = blocksInRange.filter((l) => l instanceof ListNode);
568
+ const listRootsInRange = [
569
+ ...new Set(listsInRange
570
+ .map((l) => l.getParent(this) instanceof ListNode
571
+ ? l.getFarthestParentMatching(this, (m) => m instanceof ListNode)
572
+ : l)
573
+ .filter((n) => n !== undefined)),
574
+ ];
467
575
  if (listRootsInRange.length === 0)
468
576
  return undefined;
469
577
  // For each list in the range, convert all items in range to paragraphs.
470
578
  for (let i = 0; i < listRootsInRange.length; i++) {
471
579
  const list = listRootsInRange[i];
472
- const paragraphs = list.getNodes().filter(n => n instanceof FormatNode).map(f => new ParagraphNode(0, f));
580
+ const paragraphs = list
581
+ .getNodes()
582
+ .filter((n) => n instanceof FormatNode)
583
+ .map((f) => new ParagraphNode(0, f));
473
584
  // Insert in reverse order to keep them in order, since the list is our anchor.
474
585
  for (let j = paragraphs.length - 1; j >= 0; j--) {
475
586
  const paragraph = paragraphs[j];
@@ -490,10 +601,13 @@ export default class BlocksNode extends BlockNode {
490
601
  // Find all of the formats in list nodes in the range and indent them.
491
602
  const ancestor = range.start.node.getCommonAncestor(newBlocks, range.end.node);
492
603
  const nodes = ancestor?.getNodes();
493
- const formats = nodes?.filter(n => n instanceof FormatNode && newBlocks.getParentOf(n) instanceof ListNode);
604
+ const formats = nodes?.filter((n) => n instanceof FormatNode &&
605
+ newBlocks.getParentOf(n) instanceof ListNode);
494
606
  const startIndex = nodes?.indexOf(range.start.node);
495
607
  const endIndex = nodes?.indexOf(range.end.node);
496
- if (formats === undefined || startIndex === undefined || endIndex === undefined)
608
+ if (formats === undefined ||
609
+ startIndex === undefined ||
610
+ endIndex === undefined)
497
611
  return;
498
612
  // Loop through the formats in the range and indent or dedent them, constructing a new root.
499
613
  const first = startIndex < endIndex ? range.start.node : range.end.node;
@@ -506,9 +620,11 @@ export default class BlocksNode extends BlockNode {
506
620
  // If we're in the selection and the format is in a list, restructure it's list to indent/unindent it.
507
621
  if (inside) {
508
622
  // Find the root list node of the format.
509
- const list = format.getFarthestParentMatching(newBlocks, n => n instanceof ListNode);
623
+ const list = format.getFarthestParentMatching(newBlocks, (n) => n instanceof ListNode);
510
624
  if (list instanceof ListNode) {
511
- const newList = indent ? list.withItemIndented(format) : list.withItemUnindented(format);
625
+ const newList = indent
626
+ ? list.withItemIndented(format)
627
+ : list.withItemUnindented(format);
512
628
  if (newList === undefined)
513
629
  return;
514
630
  const blocksWithIndent = newBlocks.withChildReplaced(list, newList);
@@ -534,6 +650,7 @@ export default class BlocksNode extends BlockNode {
534
650
  return;
535
651
  // Find the parents of the node.
536
652
  const parents = this.getParentsOf(caret.node);
653
+ // Iterate through the ancestors, seeing if they'd like to handle the request for a deletion.
537
654
  while (parents && parents.length > 0) {
538
655
  const parent = parents.pop();
539
656
  // Ask the format node it's in to edit it, and return if successful.
@@ -547,6 +664,32 @@ export default class BlocksNode extends BlockNode {
547
664
  return { root: newBlocks, range: editedFormat.range };
548
665
  }
549
666
  }
667
+ // See if the CodeNode would like to handle it.
668
+ else if (parent instanceof CodeNode) {
669
+ const revisedCode = parent.getCodeNode().withoutRange({
670
+ start: caret,
671
+ end: {
672
+ node: caret.node,
673
+ index: caret.index + (next ? 1 : -1),
674
+ },
675
+ });
676
+ if (revisedCode === undefined)
677
+ return;
678
+ const revisedCodeNode = parent.withChildReplaced(parent.getCodeNode(), revisedCode);
679
+ if (revisedCodeNode === undefined)
680
+ return;
681
+ const newBlocks = this.withNodeReplaced(parent, revisedCodeNode);
682
+ const newCaret = {
683
+ node: revisedCode,
684
+ index: Math.max(0, caret.index + (next ? 0 : -1)),
685
+ };
686
+ return newBlocks === undefined
687
+ ? undefined
688
+ : {
689
+ root: newBlocks,
690
+ range: { start: newCaret, end: newCaret },
691
+ };
692
+ }
550
693
  // If it's a format in the list node, merge with the previous list item
551
694
  else if (parent instanceof ListNode) {
552
695
  const index = parent.getItemContaining(caret);
@@ -561,10 +704,14 @@ export default class BlocksNode extends BlockNode {
561
704
  const newBlocks = this.withNodeReplaced(parent, newList);
562
705
  if (newBlocks === undefined)
563
706
  return;
564
- return { root: newBlocks, range: { start: newCaret, end: newCaret } };
707
+ return {
708
+ root: newBlocks,
709
+ range: { start: newCaret, end: newCaret },
710
+ };
565
711
  }
566
712
  // Convert the remaining list item into a paragraph.
567
- else if (parents.length > 0 && parents[parents.length - 1] instanceof BlocksNode) {
713
+ else if (parents.length > 0 &&
714
+ parents[parents.length - 1] instanceof BlocksNode) {
568
715
  const item = parent.getItem(0);
569
716
  if (!(item instanceof FormatNode))
570
717
  return;
@@ -573,36 +720,56 @@ export default class BlocksNode extends BlockNode {
573
720
  const newCaret = newParagraph.getFirstCaret();
574
721
  if (newBlocks === undefined || newCaret === undefined)
575
722
  return;
576
- return { root: newBlocks, range: { start: newCaret, end: newCaret } };
723
+ return {
724
+ root: newBlocks,
725
+ range: { start: newCaret, end: newCaret },
726
+ };
577
727
  }
578
728
  }
579
729
  // If it's at the beginning of the paragraph, and there's a previous paragraph, merge with the previous paragraph.
580
730
  else if (parent instanceof ParagraphNode) {
581
- const firstCaret = next ? parent.getLastCaret() : parent.getFirstCaret();
731
+ const firstCaret = next
732
+ ? parent.getLastCaret()
733
+ : parent.getFirstCaret();
582
734
  if (firstCaret === undefined)
583
735
  return;
584
736
  const blocks = parents[parents.length - 1];
585
- const adjacentBlock = next ? blocks.getBlockAfter(parent) : blocks.getBlockBefore(parent);
737
+ const adjacentBlock = next
738
+ ? blocks.getBlockAfter(parent)
739
+ : blocks.getBlockBefore(parent);
586
740
  // Is this the first/last caret of the paragraph and there's an adjascent block? Try deleting something.
587
- if (firstCaret.node === caret.node && firstCaret.index === caret.index && adjacentBlock !== undefined) {
741
+ if (firstCaret.node === caret.node &&
742
+ firstCaret.index === caret.index &&
743
+ adjacentBlock !== undefined) {
588
744
  // If the block adjacent this paragraph is a paragraph, merge the paragraph into the adjacent paragraph.
589
745
  if (adjacentBlock instanceof ParagraphNode) {
590
- const currentCaret = next ? parent.getLastCaret() : adjacentBlock.getLastCaret();
746
+ const currentCaret = next
747
+ ? parent.getLastCaret()
748
+ : adjacentBlock.getLastCaret();
591
749
  if (currentCaret === undefined)
592
750
  return;
593
- const textIndex = next ? caretToIndex(parent.getFormat(), currentCaret) : caretToIndex(adjacentBlock.getFormat(), currentCaret);
751
+ const textIndex = next
752
+ ? caretToIndex(parent.getFormat(), currentCaret)
753
+ : caretToIndex(adjacentBlock.getFormat(), currentCaret);
594
754
  if (textIndex === undefined)
595
755
  return;
596
- const mergedParagraph = next ? adjacentBlock.withParagraphPrepended(parent) : adjacentBlock.withParagraphAppended(parent);
756
+ const mergedParagraph = next
757
+ ? adjacentBlock.withParagraphPrepended(parent)
758
+ : adjacentBlock.withParagraphAppended(parent);
597
759
  if (mergedParagraph === undefined)
598
760
  return;
599
- const newBlocks = this.withNodeReplaced(blocks, blocks.withChildReplaced(adjacentBlock, mergedParagraph)?.withoutBlock(parent));
761
+ const newBlocks = this.withNodeReplaced(blocks, blocks
762
+ .withChildReplaced(adjacentBlock, mergedParagraph)
763
+ ?.withoutBlock(parent));
600
764
  if (newBlocks === undefined)
601
765
  return;
602
766
  const newCaret = indexToCaret(mergedParagraph.getFormat(), textIndex);
603
767
  if (newCaret === undefined)
604
768
  return;
605
- return { root: newBlocks, range: { start: newCaret, end: newCaret } };
769
+ return {
770
+ root: newBlocks,
771
+ range: { start: newCaret, end: newCaret },
772
+ };
606
773
  }
607
774
  // If the block adjacent is a list node, merge the paragraph to the list's first/last item.
608
775
  else if (adjacentBlock instanceof ListNode) {
@@ -610,11 +777,18 @@ export default class BlocksNode extends BlockNode {
610
777
  if (next) {
611
778
  const format = adjacentBlock.getFirstItem();
612
779
  if (format !== undefined) {
613
- const newParagraph = parent.withContent(parent.getFormat().withSegmentsAppended(format));
614
- const newBlocks = blocks.withNodeReplaced(parent, newParagraph)?.withNodeReplaced(format, undefined);
780
+ const newParagraph = parent.withContent(parent
781
+ .getFormat()
782
+ .withSegmentsAppended(format));
783
+ const newBlocks = blocks
784
+ .withNodeReplaced(parent, newParagraph)
785
+ ?.withNodeReplaced(format, undefined);
615
786
  if (newBlocks === undefined)
616
787
  return;
617
- return { root: newBlocks, range: { start: caret, end: caret } };
788
+ return {
789
+ root: newBlocks,
790
+ range: { start: caret, end: caret },
791
+ };
618
792
  }
619
793
  }
620
794
  // If we're going backwards, get the last format of the list and insert the paragraph's content into it,
@@ -623,18 +797,31 @@ export default class BlocksNode extends BlockNode {
623
797
  const format = adjacentBlock.getLastItem();
624
798
  if (format !== undefined) {
625
799
  const newFormat = format.withSegmentAppended(parent.getFormat());
626
- const newBlocks = blocks.withNodeReplaced(format, newFormat)?.withoutBlock(parent);
627
- const newCaret = parent.getFormat().getFirstCaret();
628
- if (newBlocks === undefined || newCaret === undefined)
800
+ const newBlocks = blocks
801
+ .withNodeReplaced(format, newFormat)
802
+ ?.withoutBlock(parent);
803
+ const newCaret = parent
804
+ .getFormat()
805
+ .getFirstCaret();
806
+ if (newBlocks === undefined ||
807
+ newCaret === undefined)
629
808
  return;
630
- return { root: newBlocks, range: { start: newCaret, end: newCaret } };
809
+ return {
810
+ root: newBlocks,
811
+ range: { start: newCaret, end: newCaret },
812
+ };
631
813
  }
632
814
  }
633
815
  }
634
816
  // Otherwise, return a root without the previous block, deleting it.
635
817
  else {
636
818
  const newBlocks = this.withNodeReplaced(blocks, blocks.withoutBlock(adjacentBlock));
637
- return newBlocks === undefined ? undefined : { root: newBlocks, range: { start: caret, end: caret } };
819
+ return newBlocks === undefined
820
+ ? undefined
821
+ : {
822
+ root: newBlocks,
823
+ range: { start: caret, end: caret },
824
+ };
638
825
  }
639
826
  }
640
827
  }
@@ -646,12 +833,16 @@ export default class BlocksNode extends BlockNode {
646
833
  if (!this.contains(caret.node))
647
834
  return;
648
835
  // Get the blocks to insert.
649
- const blocks = node instanceof BlocksNode ? node.getBlocks() : node instanceof BlockNode ? [node] : [];
836
+ const blocks = node instanceof BlocksNode
837
+ ? node.getBlocks()
838
+ : node instanceof BlockNode
839
+ ? [node]
840
+ : [];
650
841
  // If there are none, do nothing.
651
842
  if (blocks.length === 0)
652
843
  return;
653
844
  // Find the block in this blocks node that contains the caret.
654
- const anchor = this.#blocks.find(b => b.contains(caret.node));
845
+ const anchor = this.#blocks.find((b) => b.contains(caret.node));
655
846
  if (anchor === undefined)
656
847
  return;
657
848
  let lastInsert = anchor;
@@ -662,14 +853,18 @@ export default class BlocksNode extends BlockNode {
662
853
  if (newBlock === undefined)
663
854
  return;
664
855
  // If we're inserting after the anchor and the anchor is a paragraph and the block to insert is a paragraph, merge them.
665
- if (lastInsert === anchor && anchor instanceof ParagraphNode && newBlock instanceof ParagraphNode) {
856
+ if (lastInsert === anchor &&
857
+ anchor instanceof ParagraphNode &&
858
+ newBlock instanceof ParagraphNode) {
666
859
  newBlock = anchor.withParagraphAppended(newBlock);
667
860
  if (newBlock === undefined)
668
861
  return;
669
862
  newBlocks = newBlocks.withChildReplaced(anchor, newBlock);
670
863
  }
671
864
  // If we're inserting after the anchor and the anchor is a list and the block to insert is a list, merge them.
672
- else if (lastInsert === anchor && anchor instanceof ListNode && newBlock instanceof ListNode) {
865
+ else if (lastInsert === anchor &&
866
+ anchor instanceof ListNode &&
867
+ newBlock instanceof ListNode) {
673
868
  const edit = anchor.withNodeInserted(caret, newBlock);
674
869
  if (edit === undefined || !(edit.root instanceof BlockNode))
675
870
  return;
@@ -690,7 +885,7 @@ export default class BlocksNode extends BlockNode {
690
885
  const formats = lastInsert.getFormats();
691
886
  let newCaret = undefined;
692
887
  if (formats.length === 0) {
693
- const newParagraph = new ParagraphNode(0, new FormatNode("", [new TextNode()]));
888
+ const newParagraph = new ParagraphNode(0, new FormatNode('', [new TextNode()]));
694
889
  newCaret = newParagraph.getFirstCaret();
695
890
  newBlocks = newBlocks.withBlockInsertedAfter(lastInsert, newParagraph);
696
891
  if (newCaret === undefined || newBlocks === undefined)
@@ -704,6 +899,6 @@ export default class BlocksNode extends BlockNode {
704
899
  return { root: newBlocks, range: { start: newCaret, end: newCaret } };
705
900
  }
706
901
  toHTML() {
707
- return this.#blocks.map(b => b.toHTML()).join("");
902
+ return this.#blocks.map((b) => b.toHTML()).join('');
708
903
  }
709
904
  }