bookish-press 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (309) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -0
  3. package/components/Auth.svelte +52 -0
  4. package/components/Auth.svelte.d.ts +16 -0
  5. package/components/Authentication.d.ts +8 -0
  6. package/components/Authentication.js +1 -0
  7. package/components/BookPreview.svelte +87 -0
  8. package/components/BookPreview.svelte.d.ts +18 -0
  9. package/components/External.svelte +4 -0
  10. package/components/External.svelte.d.ts +18 -0
  11. package/components/Link.svelte +5 -0
  12. package/components/Link.svelte.d.ts +19 -0
  13. package/components/chapter/Atom.svelte +36 -0
  14. package/components/chapter/Atom.svelte.d.ts +19 -0
  15. package/components/chapter/Block.svelte +32 -0
  16. package/components/chapter/Block.svelte.d.ts +17 -0
  17. package/components/chapter/Callout.svelte +10 -0
  18. package/components/chapter/Callout.svelte.d.ts +17 -0
  19. package/components/chapter/CaptionedCode.svelte +34 -0
  20. package/components/chapter/CaptionedCode.svelte.d.ts +17 -0
  21. package/components/chapter/ChapterBody.svelte +23 -0
  22. package/components/chapter/ChapterBody.svelte.d.ts +18 -0
  23. package/components/chapter/Citations.svelte +66 -0
  24. package/components/chapter/Citations.svelte.d.ts +17 -0
  25. package/components/chapter/Code.svelte +35 -0
  26. package/components/chapter/Code.svelte.d.ts +22 -0
  27. package/components/chapter/Comment.svelte +46 -0
  28. package/components/chapter/Comment.svelte.d.ts +17 -0
  29. package/components/chapter/Definition.svelte +38 -0
  30. package/components/chapter/Definition.svelte.d.ts +20 -0
  31. package/components/chapter/Embed.svelte +122 -0
  32. package/components/chapter/Embed.svelte.d.ts +18 -0
  33. package/components/chapter/ErrorMessage.svelte +4 -0
  34. package/components/chapter/ErrorMessage.svelte.d.ts +17 -0
  35. package/components/chapter/Footnote.svelte +37 -0
  36. package/components/chapter/Footnote.svelte.d.ts +19 -0
  37. package/components/chapter/Format.svelte +57 -0
  38. package/components/chapter/Format.svelte.d.ts +18 -0
  39. package/components/chapter/InlineCode.svelte +12 -0
  40. package/components/chapter/InlineCode.svelte.d.ts +17 -0
  41. package/components/chapter/Label.svelte +20 -0
  42. package/components/chapter/Label.svelte.d.ts +17 -0
  43. package/components/chapter/Link.svelte +51 -0
  44. package/components/chapter/Link.svelte.d.ts +17 -0
  45. package/components/chapter/List.svelte +14 -0
  46. package/components/chapter/List.svelte.d.ts +17 -0
  47. package/components/chapter/Marginal.svelte +48 -0
  48. package/components/chapter/Marginal.svelte.d.ts +19 -0
  49. package/components/chapter/Paragraph.svelte +15 -0
  50. package/components/chapter/Paragraph.svelte.d.ts +18 -0
  51. package/components/chapter/Python.svelte +81 -0
  52. package/components/chapter/Python.svelte.d.ts +18 -0
  53. package/components/chapter/Quote.svelte +16 -0
  54. package/components/chapter/Quote.svelte.d.ts +17 -0
  55. package/components/chapter/Rule.svelte +4 -0
  56. package/components/chapter/Rule.svelte.d.ts +17 -0
  57. package/components/chapter/Table.svelte +29 -0
  58. package/components/chapter/Table.svelte.d.ts +17 -0
  59. package/components/chapter/Text.svelte +62 -0
  60. package/components/chapter/Text.svelte.d.ts +17 -0
  61. package/components/chapter/renderPosition.d.ts +3 -0
  62. package/components/chapter/renderPosition.js +4 -0
  63. package/components/editor/BookishEditor.svelte +755 -0
  64. package/components/editor/BookishEditor.svelte.d.ts +22 -0
  65. package/components/editor/CalloutEditor.svelte +10 -0
  66. package/components/editor/CalloutEditor.svelte.d.ts +17 -0
  67. package/components/editor/CaptionedCodeEditor.svelte +22 -0
  68. package/components/editor/CaptionedCodeEditor.svelte.d.ts +17 -0
  69. package/components/editor/CaretContext.d.ts +18 -0
  70. package/components/editor/CaretContext.js +1 -0
  71. package/components/editor/CaretState.d.ts +47 -0
  72. package/components/editor/CaretState.js +1 -0
  73. package/components/editor/CaretUtilities.d.ts +5 -0
  74. package/components/editor/CaretUtilities.js +1 -0
  75. package/components/editor/CitationsEditor.svelte +42 -0
  76. package/components/editor/CitationsEditor.svelte.d.ts +17 -0
  77. package/components/editor/Clipboard.d.ts +3 -0
  78. package/components/editor/Clipboard.js +1 -0
  79. package/components/editor/Command.d.ts +18 -0
  80. package/components/editor/Command.js +1 -0
  81. package/components/editor/Commands.d.ts +3 -0
  82. package/components/editor/Commands.js +951 -0
  83. package/components/editor/ConfirmButton.svelte +43 -0
  84. package/components/editor/ConfirmButton.svelte.d.ts +18 -0
  85. package/components/editor/DefinitionEditor.svelte +28 -0
  86. package/components/editor/DefinitionEditor.svelte.d.ts +17 -0
  87. package/components/editor/EmbedEditor.svelte +87 -0
  88. package/components/editor/EmbedEditor.svelte.d.ts +17 -0
  89. package/components/editor/ImageChooser.svelte +70 -0
  90. package/components/editor/ImageChooser.svelte.d.ts +18 -0
  91. package/components/editor/InlineCodeEditor.svelte +9 -0
  92. package/components/editor/InlineCodeEditor.svelte.d.ts +17 -0
  93. package/components/editor/LabelEditor.svelte +23 -0
  94. package/components/editor/LabelEditor.svelte.d.ts +17 -0
  95. package/components/editor/LanguageEditor.svelte +11 -0
  96. package/components/editor/LanguageEditor.svelte.d.ts +17 -0
  97. package/components/editor/LinkEditor.svelte +75 -0
  98. package/components/editor/LinkEditor.svelte.d.ts +17 -0
  99. package/components/editor/Note.svelte +9 -0
  100. package/components/editor/Note.svelte.d.ts +23 -0
  101. package/components/editor/PositionEditor.svelte +14 -0
  102. package/components/editor/PositionEditor.svelte.d.ts +18 -0
  103. package/components/editor/QuoteEditor.svelte +5 -0
  104. package/components/editor/QuoteEditor.svelte.d.ts +17 -0
  105. package/components/editor/Switch.svelte +56 -0
  106. package/components/editor/Switch.svelte.d.ts +20 -0
  107. package/components/editor/TextEditor.svelte +193 -0
  108. package/components/editor/TextEditor.svelte.d.ts +23 -0
  109. package/components/editor/Toggle.svelte +38 -0
  110. package/components/editor/Toggle.svelte.d.ts +19 -0
  111. package/components/editor/Toolbar.svelte +202 -0
  112. package/components/editor/Toolbar.svelte.d.ts +20 -0
  113. package/components/editor/ToolbarGroup.svelte +41 -0
  114. package/components/editor/ToolbarGroup.svelte.d.ts +19 -0
  115. package/components/editor/ToolbarIcon.svelte +22 -0
  116. package/components/editor/ToolbarIcon.svelte.d.ts +16 -0
  117. package/components/editor/ToolbarSpacer.svelte +1 -0
  118. package/components/editor/ToolbarSpacer.svelte.d.ts +19 -0
  119. package/components/editor/URLEditor.svelte +15 -0
  120. package/components/editor/URLEditor.svelte.d.ts +18 -0
  121. package/components/editor/UndoState.d.ts +8 -0
  122. package/components/editor/UndoState.js +1 -0
  123. package/components/page/Acknowledgements.svelte +29 -0
  124. package/components/page/Acknowledgements.svelte.d.ts +14 -0
  125. package/components/page/Alert.svelte +11 -0
  126. package/components/page/Alert.svelte.d.ts +23 -0
  127. package/components/page/Authors.svelte +62 -0
  128. package/components/page/Authors.svelte.d.ts +20 -0
  129. package/components/page/BulkReferenceEditor.svelte +32 -0
  130. package/components/page/BulkReferenceEditor.svelte.d.ts +14 -0
  131. package/components/page/Chapter.svelte +301 -0
  132. package/components/page/Chapter.svelte.d.ts +18 -0
  133. package/components/page/ChapterContext.d.ts +10 -0
  134. package/components/page/ChapterContext.js +1 -0
  135. package/components/page/Contexts.d.ts +27 -0
  136. package/components/page/Contexts.js +21 -0
  137. package/components/page/DefinitionView.svelte +129 -0
  138. package/components/page/DefinitionView.svelte.d.ts +18 -0
  139. package/components/page/Description.svelte +22 -0
  140. package/components/page/Description.svelte.d.ts +14 -0
  141. package/components/page/Edition.svelte +106 -0
  142. package/components/page/Edition.svelte.d.ts +21 -0
  143. package/components/page/Glossary.svelte +61 -0
  144. package/components/page/Glossary.svelte.d.ts +14 -0
  145. package/components/page/Header.svelte +105 -0
  146. package/components/page/Header.svelte.d.ts +27 -0
  147. package/components/page/Index.svelte +117 -0
  148. package/components/page/Index.svelte.d.ts +14 -0
  149. package/components/page/Instructions.svelte +30 -0
  150. package/components/page/Instructions.svelte.d.ts +16 -0
  151. package/components/page/License.svelte +29 -0
  152. package/components/page/License.svelte.d.ts +14 -0
  153. package/components/page/Loading.svelte +13 -0
  154. package/components/page/Loading.svelte.d.ts +19 -0
  155. package/components/page/Media.svelte +76 -0
  156. package/components/page/Media.svelte.d.ts +14 -0
  157. package/components/page/MediaPreview.svelte +11 -0
  158. package/components/page/MediaPreview.svelte.d.ts +19 -0
  159. package/components/page/Outline.svelte +173 -0
  160. package/components/page/Outline.svelte.d.ts +19 -0
  161. package/components/page/Page.svelte +53 -0
  162. package/components/page/Page.svelte.d.ts +19 -0
  163. package/components/page/PossibleChapter.svelte +14 -0
  164. package/components/page/PossibleChapter.svelte.d.ts +14 -0
  165. package/components/page/PossibleReference.svelte +16 -0
  166. package/components/page/PossibleReference.svelte.d.ts +19 -0
  167. package/components/page/Print.svelte +8 -0
  168. package/components/page/Print.svelte.d.ts +14 -0
  169. package/components/page/Reference.svelte +145 -0
  170. package/components/page/Reference.svelte.d.ts +17 -0
  171. package/components/page/References.svelte +58 -0
  172. package/components/page/References.svelte.d.ts +14 -0
  173. package/components/page/Revisions.svelte +124 -0
  174. package/components/page/Revisions.svelte.d.ts +14 -0
  175. package/components/page/Search.svelte +108 -0
  176. package/components/page/Search.svelte.d.ts +14 -0
  177. package/components/page/Status.svelte +49 -0
  178. package/components/page/Status.svelte.d.ts +19 -0
  179. package/components/page/SubdomainEditor.svelte +30 -0
  180. package/components/page/SubdomainEditor.svelte.d.ts +14 -0
  181. package/components/page/TableOfContents.svelte +234 -0
  182. package/components/page/TableOfContents.svelte.d.ts +14 -0
  183. package/components/page/TableOfContentsImage.svelte +15 -0
  184. package/components/page/TableOfContentsImage.svelte.d.ts +16 -0
  185. package/components/page/TableOfContentsRow.svelte +57 -0
  186. package/components/page/TableOfContentsRow.svelte.d.ts +24 -0
  187. package/components/page/ThemeEditor.svelte +52 -0
  188. package/components/page/ThemeEditor.svelte.d.ts +14 -0
  189. package/components/page/ThemeEditorPreview.svelte +37 -0
  190. package/components/page/ThemeEditorPreview.svelte.d.ts +17 -0
  191. package/components/page/ThemeSetEditor.svelte +17 -0
  192. package/components/page/ThemeSetEditor.svelte.d.ts +18 -0
  193. package/components/page/ThemeVariableEditor.svelte +28 -0
  194. package/components/page/ThemeVariableEditor.svelte.d.ts +18 -0
  195. package/components/page/Unknown.svelte +29 -0
  196. package/components/page/Unknown.svelte.d.ts +16 -0
  197. package/components/page/margins.d.ts +2 -0
  198. package/components/page/margins.js +132 -0
  199. package/models/BookLoader.d.ts +2 -0
  200. package/models/BookLoader.js +67 -0
  201. package/models/Firebase.d.ts +4 -0
  202. package/models/Firebase.js +26 -0
  203. package/models/Firestore.d.ts +22 -0
  204. package/models/Firestore.js +194 -0
  205. package/models/book/Book.d.ts +60 -0
  206. package/models/book/Book.js +135 -0
  207. package/models/book/BookMedia.d.ts +23 -0
  208. package/models/book/BookMedia.js +102 -0
  209. package/models/book/Chapter.d.ts +70 -0
  210. package/models/book/Chapter.js +221 -0
  211. package/models/book/ChapterID.d.ts +10 -0
  212. package/models/book/ChapterID.js +10 -0
  213. package/models/book/Definition.d.ts +6 -0
  214. package/models/book/Definition.js +1 -0
  215. package/models/book/Edition.d.ts +111 -0
  216. package/models/book/Edition.js +466 -0
  217. package/models/book/Theme.d.ts +106 -0
  218. package/models/book/Theme.js +76 -0
  219. package/models/book/ThemeColors.d.ts +15 -0
  220. package/models/book/ThemeColors.js +1 -0
  221. package/models/chapter/AtomNode.d.ts +18 -0
  222. package/models/chapter/AtomNode.js +31 -0
  223. package/models/chapter/BlockNode.d.ts +21 -0
  224. package/models/chapter/BlockNode.js +117 -0
  225. package/models/chapter/BlocksNode.d.ts +50 -0
  226. package/models/chapter/BlocksNode.js +709 -0
  227. package/models/chapter/BlocksNode.test.d.ts +1 -0
  228. package/models/chapter/BlocksNode.test.js +302 -0
  229. package/models/chapter/Bookkeeping.d.ts +4 -0
  230. package/models/chapter/Bookkeeping.js +1 -0
  231. package/models/chapter/CalloutNode.d.ts +17 -0
  232. package/models/chapter/CalloutNode.js +36 -0
  233. package/models/chapter/Caret.d.ts +21 -0
  234. package/models/chapter/Caret.js +69 -0
  235. package/models/chapter/ChapterNode.d.ts +34 -0
  236. package/models/chapter/ChapterNode.js +80 -0
  237. package/models/chapter/CitationsNode.d.ts +16 -0
  238. package/models/chapter/CitationsNode.js +17 -0
  239. package/models/chapter/CodeNode.d.ts +30 -0
  240. package/models/chapter/CodeNode.js +64 -0
  241. package/models/chapter/CommentNode.d.ts +18 -0
  242. package/models/chapter/CommentNode.js +32 -0
  243. package/models/chapter/DefinitionNode.d.ts +12 -0
  244. package/models/chapter/DefinitionNode.js +20 -0
  245. package/models/chapter/Edit.d.ts +7 -0
  246. package/models/chapter/Edit.js +1 -0
  247. package/models/chapter/EmbedNode.d.ts +40 -0
  248. package/models/chapter/EmbedNode.js +89 -0
  249. package/models/chapter/ErrorNode.d.ts +17 -0
  250. package/models/chapter/ErrorNode.js +21 -0
  251. package/models/chapter/FootnoteNode.d.ts +18 -0
  252. package/models/chapter/FootnoteNode.js +29 -0
  253. package/models/chapter/FormatNode.d.ts +60 -0
  254. package/models/chapter/FormatNode.js +614 -0
  255. package/models/chapter/FormatNode.test.d.ts +1 -0
  256. package/models/chapter/FormatNode.test.js +54 -0
  257. package/models/chapter/InlineCodeNode.d.ts +12 -0
  258. package/models/chapter/InlineCodeNode.js +18 -0
  259. package/models/chapter/LabelNode.d.ts +17 -0
  260. package/models/chapter/LabelNode.js +22 -0
  261. package/models/chapter/LinkNode.d.ts +12 -0
  262. package/models/chapter/LinkNode.js +16 -0
  263. package/models/chapter/ListNode.d.ts +51 -0
  264. package/models/chapter/ListNode.js +370 -0
  265. package/models/chapter/ListNode.test.d.ts +1 -0
  266. package/models/chapter/ListNode.test.js +49 -0
  267. package/models/chapter/MetadataNode.d.ts +17 -0
  268. package/models/chapter/MetadataNode.js +24 -0
  269. package/models/chapter/Node.d.ts +36 -0
  270. package/models/chapter/Node.js +173 -0
  271. package/models/chapter/Node.test.d.ts +1 -0
  272. package/models/chapter/Node.test.js +27 -0
  273. package/models/chapter/ParagraphNode.d.ts +33 -0
  274. package/models/chapter/ParagraphNode.js +93 -0
  275. package/models/chapter/ParagraphNode.test.d.ts +1 -0
  276. package/models/chapter/ParagraphNode.test.js +21 -0
  277. package/models/chapter/Parser.d.ts +75 -0
  278. package/models/chapter/Parser.js +824 -0
  279. package/models/chapter/Parser.test.d.ts +1 -0
  280. package/models/chapter/Parser.test.js +25 -0
  281. package/models/chapter/Position.d.ts +2 -0
  282. package/models/chapter/Position.js +1 -0
  283. package/models/chapter/QuoteNode.d.ts +25 -0
  284. package/models/chapter/QuoteNode.js +61 -0
  285. package/models/chapter/ReferenceNode.d.ts +29 -0
  286. package/models/chapter/ReferenceNode.js +48 -0
  287. package/models/chapter/RootNode.d.ts +5 -0
  288. package/models/chapter/RootNode.js +1 -0
  289. package/models/chapter/RuleNode.d.ts +15 -0
  290. package/models/chapter/RuleNode.js +16 -0
  291. package/models/chapter/TableNode.d.ts +35 -0
  292. package/models/chapter/TableNode.js +176 -0
  293. package/models/chapter/TableNode.test.d.ts +1 -0
  294. package/models/chapter/TableNode.test.js +31 -0
  295. package/models/chapter/TextNode.d.ts +36 -0
  296. package/models/chapter/TextNode.js +136 -0
  297. package/models/chapter/TextNode.test.d.ts +1 -0
  298. package/models/chapter/TextNode.test.js +6 -0
  299. package/models/loadEdition.d.ts +5 -0
  300. package/models/loadEdition.js +16 -0
  301. package/package.json +189 -0
  302. package/util/getSubdomain.d.ts +3 -0
  303. package/util/getSubdomain.js +22 -0
  304. package/util/isMobile.d.ts +2 -0
  305. package/util/isMobile.js +6 -0
  306. package/util/mineReference.d.ts +3 -0
  307. package/util/mineReference.js +62 -0
  308. package/util/scrollToEyeLevel.d.ts +2 -0
  309. package/util/scrollToEyeLevel.js +5 -0
@@ -0,0 +1,43 @@
1
+ <script>import { onMount } from "svelte";
2
+ export let commandLabel;
3
+ export let confirmLabel;
4
+ export let command;
5
+ let confirming = false;
6
+ let executing = false;
7
+ let timeoutID = undefined;
8
+ let isMounted = false;
9
+ onMount(() => {
10
+ isMounted = true;
11
+ return () => isMounted = false;
12
+ });
13
+ function execute() {
14
+ if (!confirming && !executing) {
15
+ confirming = true;
16
+ timeoutID = setTimeout(() => { if (isMounted)
17
+ confirming = false; }, 2000);
18
+ }
19
+ else if (confirming) {
20
+ command()?.finally(() => {
21
+ if (isMounted) {
22
+ if (timeoutID)
23
+ clearTimeout(timeoutID);
24
+ confirming = false;
25
+ executing = false;
26
+ }
27
+ });
28
+ }
29
+ }
30
+ </script>
31
+
32
+ <button
33
+ disabled={executing}
34
+ on:click={execute}
35
+ class={confirming ? "bookish-editor-confirm" : ""}>
36
+ { confirming ? confirmLabel : commandLabel }
37
+ </button>
38
+
39
+ <style>
40
+ button.bookish-editor-confirm {
41
+ animation: failure 100ms infinite;
42
+ }
43
+ </style>
@@ -0,0 +1,18 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ commandLabel: string;
5
+ confirmLabel: string;
6
+ command: () => Promise<void> | undefined;
7
+ };
8
+ events: {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots: {};
12
+ };
13
+ export declare type ConfirmButtonProps = typeof __propDef.props;
14
+ export declare type ConfirmButtonEvents = typeof __propDef.events;
15
+ export declare type ConfirmButtonSlots = typeof __propDef.slots;
16
+ export default class ConfirmButton extends SvelteComponentTyped<ConfirmButtonProps, ConfirmButtonEvents, ConfirmButtonSlots> {
17
+ }
18
+ export {};
@@ -0,0 +1,28 @@
1
+ <script>import { getCaret, getEdition } from "../page/Contexts";
2
+ export let definition;
3
+ let edition = getEdition();
4
+ let caret = getCaret();
5
+ $: glossary = $edition.getGlossary();
6
+ function handleChange(event) {
7
+ const target = event.target;
8
+ $caret?.edit(definition, definition.withMeta(target.value));
9
+ }
10
+ // Sort the glossary entries by phrase
11
+ $: entries = Object.keys(glossary).map(key => { return { glossaryID: key, phrase: glossary[key].phrase }; }).sort((a, b) => a.phrase.localeCompare(b.phrase));
12
+ $: refID = $edition.getRef()?.id;
13
+ $: glossaryLink = `/write/${refID}/glossary`;
14
+ </script>
15
+
16
+ <span>
17
+ <select
18
+ tabIndex=0
19
+ value={definition.getMeta()}
20
+ on:change={handleChange}
21
+ >
22
+ <option value=""></option>
23
+ {#each entries as entry}<option value={entry.glossaryID}>{entry.phrase}</option>{/each}
24
+ </select>
25
+ {#if !(definition.getMeta() in glossary)}
26
+ <span class="bookish-editor-error">Choose a <a href={glossaryLink}>glossary</a> entry.</span>
27
+ {/if}
28
+ </span>
@@ -0,0 +1,17 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type DefinitionNode from "../../models/chapter/DefinitionNode";
3
+ declare const __propDef: {
4
+ props: {
5
+ definition: DefinitionNode;
6
+ };
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export declare type DefinitionEditorProps = typeof __propDef.props;
13
+ export declare type DefinitionEditorEvents = typeof __propDef.events;
14
+ export declare type DefinitionEditorSlots = typeof __propDef.slots;
15
+ export default class DefinitionEditor extends SvelteComponentTyped<DefinitionEditorProps, DefinitionEditorEvents, DefinitionEditorSlots> {
16
+ }
17
+ export {};
@@ -0,0 +1,87 @@
1
+ <script>import PositionEditor from './PositionEditor.svelte';
2
+ import EmbedNode from '../../models/chapter/EmbedNode';
3
+ import TextEditor from './TextEditor.svelte';
4
+ import { storage } from '../../models/Firebase';
5
+ import { getBook, getCaret } from '../page/Contexts';
6
+ import ToolbarSpacer from './ToolbarSpacer.svelte';
7
+ import ImageChooser from './ImageChooser.svelte';
8
+ import URLEditor from './URLEditor.svelte';
9
+ export let embed;
10
+ let book = getBook();
11
+ let caret = getCaret();
12
+ let upload = undefined;
13
+ $: description = embed.getDescription();
14
+ $: book.getMedia();
15
+ function isValidURL(url) {
16
+ // Is it a valid URL?
17
+ try {
18
+ let test = new URL(url);
19
+ if (test.protocol === "http:" || test.protocol === "https:")
20
+ return;
21
+ }
22
+ catch (_) { }
23
+ return "URL doesn't seem valid";
24
+ }
25
+ function handleImageChange(event) {
26
+ const target = event.target;
27
+ const file = target.files === null ? undefined : target.files[0];
28
+ const media = book.getMedia();
29
+ if (file === undefined)
30
+ return;
31
+ if (storage === undefined)
32
+ return;
33
+ if (media === undefined)
34
+ return;
35
+ media.upload(file, (progress) => upload = `${progress}% done`, (error) => upload = error, (url, thumbnail) => {
36
+ // Upload completed successfully, now we can get the download URL
37
+ $caret?.edit(embed, embed.withURLs(url, thumbnail).withDescription(""));
38
+ upload = undefined;
39
+ });
40
+ }
41
+ function handleImageSelection(image) {
42
+ // Toggle the embed
43
+ $caret?.edit(embed, embed.getURL() === image.url ?
44
+ embed.withURL("").withDescription("") :
45
+ embed.withURL(image.url));
46
+ }
47
+ </script>
48
+
49
+ {#if $caret?.root instanceof EmbedNode}
50
+ <ToolbarSpacer/>
51
+ {:else}
52
+ Position <PositionEditor value={embed.getPosition()} edit={position => $caret?.edit(embed, embed.withPosition(position)) } />
53
+ {/if}
54
+ <label class="bookish-file-upload">
55
+ <input type="file" on:input={handleImageChange} accept=".jpg,.jpeg,.png,.gif,image/jpeg,image/png,image/gif"/>
56
+ Upload
57
+ </label>
58
+ <ToolbarSpacer/>
59
+ <code>
60
+ {#if !embed.isHosted() }
61
+ <URLEditor
62
+ url={embed.getURL()}
63
+ validator={isValidURL}
64
+ edit={url => {
65
+ const revisedEmbed = embed.withURL(url);
66
+ const revisedURL = revisedEmbed.getURL();
67
+ $caret?.edit(embed, revisedEmbed);
68
+ return revisedURL;
69
+ }}
70
+ />
71
+ {/if}
72
+ </code>
73
+ <ToolbarSpacer/>
74
+ <code>
75
+ <TextEditor
76
+ startText={description}
77
+ label={'Image description'}
78
+ placeholder={'description'}
79
+ valid={ alt => alt.length === 0 ? "Image description required" : undefined }
80
+ save={ alt => { $caret?.edit(embed, embed.withDescription(alt)); } }
81
+ width={20}
82
+ clip={true}
83
+ />
84
+ </code>
85
+ <ToolbarSpacer/>
86
+ {upload}
87
+ <ImageChooser select={handleImageSelection} selection={embed.getURL()} />
@@ -0,0 +1,17 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import EmbedNode from '../../models/chapter/EmbedNode';
3
+ declare const __propDef: {
4
+ props: {
5
+ embed: EmbedNode;
6
+ };
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export declare type EmbedEditorProps = typeof __propDef.props;
13
+ export declare type EmbedEditorEvents = typeof __propDef.events;
14
+ export declare type EmbedEditorSlots = typeof __propDef.slots;
15
+ export default class EmbedEditor extends SvelteComponentTyped<EmbedEditorProps, EmbedEditorEvents, EmbedEditorSlots> {
16
+ }
17
+ export {};
@@ -0,0 +1,70 @@
1
+ <script>import { onMount } from 'svelte';
2
+ import { getBook } from '../page/Contexts';
3
+ export let select;
4
+ export let selection;
5
+ let book = getBook();
6
+ let images = undefined;
7
+ let expanded = false;
8
+ function updateImages(newImages) {
9
+ images = newImages;
10
+ }
11
+ // Load the latest images in the book, and keep them updated as they change.
12
+ onMount(() => {
13
+ const media = book.getMedia();
14
+ media.notify(updateImages);
15
+ return () => media.stopNotifying(updateImages);
16
+ });
17
+ </script>
18
+
19
+ <div
20
+ class={`bookish-image-chooser ${expanded ? "expanded" : ""}`}
21
+ tabIndex=0
22
+ on:click={() => expanded = !expanded}
23
+ on:keydown={event => event.key === "Enter" || event.key === " " ? expanded = !expanded : undefined }
24
+ on:mouseenter={() => expanded = true}
25
+ on:mouseleave={() => expanded = false}
26
+ >
27
+ {#if images === undefined}
28
+ Loading images
29
+ {:else}
30
+ <!-- Sort the images by their URL. There's probably a more meaningful sort,
31
+ such as placing unused images at the front of the list. -->
32
+ {#each images.sort((a, b) => a.url.localeCompare(b.url)) as image }
33
+ <img
34
+ class={`bookish-image-chooser-image ${image.url === selection ? "selected" : ""}`}
35
+ src={image.url}
36
+ alt={`Image named ${image.url}`}
37
+ tabIndex=0
38
+ on:click|stopPropagation={() => select(image)}
39
+ on:keydown={event => event.key === "Enter" || event.key === " " ? select(image) : undefined }
40
+ />
41
+ {:else}
42
+ No images uploaded
43
+ {/each}
44
+ {/if}
45
+ </div>
46
+
47
+ <style>
48
+ .bookish-image-chooser {
49
+ margin-top: var(--bookish-app-chrome-padding);
50
+ height: 3em;
51
+ overflow-y: hidden;
52
+ }
53
+
54
+ .bookish-image-chooser.expanded {
55
+ height: auto;
56
+ overflow-y: auto;
57
+ }
58
+
59
+ .bookish-image-chooser-image {
60
+ display: inline-block;
61
+ height: 3em;
62
+ margin-right: var(--bookish-app-chrome-padding);
63
+ cursor: pointer;
64
+ }
65
+
66
+ .bookish-image-chooser-image.selected {
67
+ outline: var(--bookish-app-highlight-width) solid var(--bookish-highlight-color);
68
+ outline-offset: calc(-1 * var(--bookish-app-highlight-width));
69
+ }
70
+ </style>
@@ -0,0 +1,18 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { Image } from '../../models/book/BookMedia';
3
+ declare const __propDef: {
4
+ props: {
5
+ select: (image: Image) => void;
6
+ selection: string;
7
+ };
8
+ events: {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots: {};
12
+ };
13
+ export declare type ImageChooserProps = typeof __propDef.props;
14
+ export declare type ImageChooserEvents = typeof __propDef.events;
15
+ export declare type ImageChooserSlots = typeof __propDef.slots;
16
+ export default class ImageChooser extends SvelteComponentTyped<ImageChooserProps, ImageChooserEvents, ImageChooserSlots> {
17
+ }
18
+ export {};
@@ -0,0 +1,9 @@
1
+ <script>import LanguageEditor from "./LanguageEditor.svelte";
2
+ import { getCaret } from "../page/Contexts";
3
+ export let code;
4
+ let caret = getCaret();
5
+ </script>
6
+
7
+ <span>
8
+ <LanguageEditor language={code.getMeta()} edit={lang => $caret?.edit(code, code.withMeta(lang)) } />
9
+ </span>
@@ -0,0 +1,17 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type InlineCodeNode from "../../models/chapter/InlineCodeNode";
3
+ declare const __propDef: {
4
+ props: {
5
+ code: InlineCodeNode;
6
+ };
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export declare type InlineCodeEditorProps = typeof __propDef.props;
13
+ export declare type InlineCodeEditorEvents = typeof __propDef.events;
14
+ export declare type InlineCodeEditorSlots = typeof __propDef.slots;
15
+ export default class InlineCodeEditor extends SvelteComponentTyped<InlineCodeEditorProps, InlineCodeEditorEvents, InlineCodeEditorSlots> {
16
+ }
17
+ export {};
@@ -0,0 +1,23 @@
1
+ <script>import TextEditor from "./TextEditor.svelte";
2
+ import { getCaret, getChapter } from "../page/Contexts";
3
+ export let label;
4
+ let chapter = getChapter();
5
+ let caret = getCaret();
6
+ $: ast = $chapter?.chapter.getAST();
7
+ </script>
8
+
9
+ <code>
10
+ <TextEditor
11
+ startText={label.getMeta()}
12
+ label="Chapter label ID"
13
+ placeholder="label ID"
14
+ valid={ id => {
15
+ if(id.length === 0) return "Can't be empty";
16
+ if(!/^[a-z]+$/.test(id)) return "Can only be a-z";
17
+ // If it's different than what it is and there's already one, then error.
18
+ if(ast && ast.getLabels().filter(l => l.getMeta() === id).length > (label.getMeta() === id ? 1 : 0)) return "Another label has this ID";
19
+ }}
20
+ save={labelID => $caret?.edit(label, label.withMeta(labelID)) }
21
+ saveOnExit
22
+ />
23
+ </code>
@@ -0,0 +1,17 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type LabelNode from "../../models/chapter/LabelNode";
3
+ declare const __propDef: {
4
+ props: {
5
+ label: LabelNode;
6
+ };
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export declare type LabelEditorProps = typeof __propDef.props;
13
+ export declare type LabelEditorEvents = typeof __propDef.events;
14
+ export declare type LabelEditorSlots = typeof __propDef.slots;
15
+ export default class LabelEditor extends SvelteComponentTyped<LabelEditorProps, LabelEditorEvents, LabelEditorSlots> {
16
+ }
17
+ export {};
@@ -0,0 +1,11 @@
1
+ <script>import Note from "./Note.svelte";
2
+ export let language;
3
+ export let edit;
4
+ let value = language;
5
+ const languages = ["C", "C++", "CSS", "Go", "HTML", "Java", "JavaScript", "Markdown", "Plaintext", "Python", "TypeScript"];
6
+ </script>
7
+
8
+ <select bind:value={value} on:change={() => edit(value)}>
9
+ {#each languages as lang}<option value={lang.toLocaleLowerCase()}>{lang}</option>{/each}
10
+ </select>
11
+ <Note>Choose a programming language to enable syntax highlighting.</Note>
@@ -0,0 +1,17 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ language: string;
5
+ edit: (newValue: string) => void;
6
+ };
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export declare type LanguageEditorProps = typeof __propDef.props;
13
+ export declare type LanguageEditorEvents = typeof __propDef.events;
14
+ export declare type LanguageEditorSlots = typeof __propDef.slots;
15
+ export default class LanguageEditor extends SvelteComponentTyped<LanguageEditorProps, LanguageEditorEvents, LanguageEditorSlots> {
16
+ }
17
+ export {};
@@ -0,0 +1,75 @@
1
+ <script>import URLEditor from "./URLEditor.svelte";
2
+ import { getCaret, getChapter, getEdition } from "../page/Contexts";
3
+ import ToolbarIcon from "./ToolbarIcon.svelte";
4
+ export let link;
5
+ let caret = getCaret();
6
+ let edition = getEdition();
7
+ let chapter = getChapter();
8
+ $: url = link.getMeta();
9
+ function saveEdit(value) {
10
+ $caret?.edit(link, link.withMeta(value));
11
+ }
12
+ function handleChapterChange(e) {
13
+ const target = e.target;
14
+ saveEdit(target.value);
15
+ }
16
+ function isValidURL(url) {
17
+ // Is it a valid URL?
18
+ try {
19
+ let test = new URL(url);
20
+ if (test.protocol === "http:" || test.protocol === "https:")
21
+ return true;
22
+ }
23
+ catch (_) { }
24
+ return false;
25
+ }
26
+ function getURLError(urlOrChapter) {
27
+ if (urlOrChapter.length === 0)
28
+ return "Can't be empty.";
29
+ if (isValidURL(urlOrChapter))
30
+ return;
31
+ // If not, is it a valid chapterID?
32
+ if ($edition.hasChapter(urlOrChapter))
33
+ return;
34
+ // If not, is it a valid chapterID:label?
35
+ const [chapterID, labelID] = urlOrChapter.split(":");
36
+ if (chapterID === undefined || labelID === undefined)
37
+ return;
38
+ // The chapter ID is optional; if it's missing, it refers to this chapter.
39
+ const correspondingChapter = chapterID === "" && $chapter ? $chapter.chapter.getAST() : $edition.getChapter(chapterID)?.getAST();
40
+ if (correspondingChapter === undefined)
41
+ return "Not a valid URL or chapter.";
42
+ if (!correspondingChapter.hasLabel(labelID))
43
+ return "Not a valid chapter label.";
44
+ }
45
+ </script>
46
+
47
+ <span>
48
+ <button
49
+ title="Remove link."
50
+ on:click={() => {
51
+ if($caret?.context?.format) {
52
+ const newFormat = $caret.context.format.withSegmentReplaced(link, link.getText());
53
+ if(newFormat)
54
+ $caret.edit($caret.context.format, newFormat);
55
+ }
56
+ }}
57
+ >
58
+ <ToolbarIcon name="unlink.svg"/>
59
+ </button>
60
+ <select name="chapterID" on:change={handleChapterChange} value={url}>
61
+ <option value="">URL</option>
62
+ {#if $chapter }
63
+ <option value={$chapter.chapter.getChapterID()}>{$chapter.chapter.getTitle()}</option>
64
+ <!-- Build the list of options (chapters and then any of the chapter's labels.) -->
65
+ {#each $edition.getChapters() as chapter }
66
+ {#each chapter.getAST()?.getLabels() ?? [] as label }
67
+ <option value={`${chapter.getChapterID()}:${label.getMeta()}`}>{chapter.getTitle() + ": " + label.getMeta()}</option>
68
+ {/each}
69
+ {/each}
70
+ {/if}
71
+ </select>
72
+ <code>
73
+ <URLEditor url={url} validator={getURLError} edit={ url => { saveEdit(url); return undefined; }} />
74
+ </code>
75
+ </span>
@@ -0,0 +1,17 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type LinkNode from "../../models/chapter/LinkNode";
3
+ declare const __propDef: {
4
+ props: {
5
+ link: LinkNode;
6
+ };
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export declare type LinkEditorProps = typeof __propDef.props;
13
+ export declare type LinkEditorEvents = typeof __propDef.events;
14
+ export declare type LinkEditorSlots = typeof __propDef.slots;
15
+ export default class LinkEditor extends SvelteComponentTyped<LinkEditorProps, LinkEditorEvents, LinkEditorSlots> {
16
+ }
17
+ export {};
@@ -0,0 +1,9 @@
1
+ <span><slot></slot></span>
2
+
3
+ <style>
4
+ span {
5
+ font-size: small;
6
+ font-style: italic;
7
+ color: var(--bookish-app-chrome-muted);
8
+ }
9
+ </style>
@@ -0,0 +1,23 @@
1
+ /** @typedef {typeof __propDef.props} NoteProps */
2
+ /** @typedef {typeof __propDef.events} NoteEvents */
3
+ /** @typedef {typeof __propDef.slots} NoteSlots */
4
+ export default class Note extends SvelteComponentTyped<{}, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {
7
+ default: {};
8
+ }> {
9
+ }
10
+ export type NoteProps = typeof __propDef.props;
11
+ export type NoteEvents = typeof __propDef.events;
12
+ export type NoteSlots = typeof __propDef.slots;
13
+ import { SvelteComponentTyped } from "svelte";
14
+ declare const __propDef: {
15
+ props: {};
16
+ events: {
17
+ [evt: string]: CustomEvent<any>;
18
+ };
19
+ slots: {
20
+ default: {};
21
+ };
22
+ };
23
+ export {};
@@ -0,0 +1,14 @@
1
+ <script>import Switch from "./Switch.svelte";
2
+ export let value;
3
+ export let edit;
4
+ function editAsString(newValue) {
5
+ edit(newValue);
6
+ }
7
+ </script>
8
+
9
+ <Switch
10
+ position={value}
11
+ options={["<", "|", ">"]}
12
+ value={value}
13
+ edit={editAsString}
14
+ />
@@ -0,0 +1,18 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type Position from "../../models/chapter/Position";
3
+ declare const __propDef: {
4
+ props: {
5
+ value: string;
6
+ edit: (newValue: Position) => void;
7
+ };
8
+ events: {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots: {};
12
+ };
13
+ export declare type PositionEditorProps = typeof __propDef.props;
14
+ export declare type PositionEditorEvents = typeof __propDef.events;
15
+ export declare type PositionEditorSlots = typeof __propDef.slots;
16
+ export default class PositionEditor extends SvelteComponentTyped<PositionEditorProps, PositionEditorEvents, PositionEditorSlots> {
17
+ }
18
+ export {};
@@ -0,0 +1,5 @@
1
+ <script>import PositionEditor from "./PositionEditor.svelte";
2
+ export let quote;
3
+ </script>
4
+
5
+ <PositionEditor value={quote.getPosition()} edit={position => quote.withPosition(position)} />
@@ -0,0 +1,17 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type QuoteNode from "../../models/chapter/QuoteNode";
3
+ declare const __propDef: {
4
+ props: {
5
+ quote: QuoteNode;
6
+ };
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export declare type QuoteEditorProps = typeof __propDef.props;
13
+ export declare type QuoteEditorEvents = typeof __propDef.events;
14
+ export declare type QuoteEditorSlots = typeof __propDef.slots;
15
+ export default class QuoteEditor extends SvelteComponentTyped<QuoteEditorProps, QuoteEditorEvents, QuoteEditorSlots> {
16
+ }
17
+ export {};
@@ -0,0 +1,56 @@
1
+ <script>export let options;
2
+ export let value;
3
+ export let position;
4
+ export let enabled = undefined;
5
+ export let edit;
6
+ function handleClick(event) {
7
+ const newValue = event.currentTarget.dataset.value;
8
+ if (newValue && options.includes(newValue)) {
9
+ edit(newValue);
10
+ }
11
+ }
12
+ </script>
13
+
14
+ <span class={`bookish-app-switch bookish-app-${position === "<" ? "left" : position === ">" ? "right" : "middle"}`}>
15
+ {#each options as option }
16
+ <button
17
+ class={`bookish-app-switch-option ${value === option ? "bookish-app-switch-option-selected" : ""}`}
18
+ data-value={option}
19
+ disabled={enabled === false}
20
+ on:click|stopPropagation={handleClick}>
21
+ {option}
22
+ </button>
23
+ {/each}
24
+ </span>
25
+
26
+ <style>
27
+ .bookish-app-switch {
28
+ font-family: var(--bookish-app-chrome-font-family);
29
+ font-size: var(--bookish-app-chrome-font-size);
30
+ }
31
+
32
+ .bookish-app-switch-option {
33
+ display: inline-block;
34
+ background-color: var(--bookish-app-chrome-background);
35
+ cursor: pointer;
36
+ padding-left: var(--bookish-app-chrome-padding);
37
+ padding-right: var(--bookish-app-chrome-padding);
38
+ border: var(--bookish-app-chrome-border-width) solid var(--bookish-app-chrome-border-color);
39
+ }
40
+
41
+ .bookish-app-switch-option:first-child {
42
+ border-top-left-radius: var(--bookish-app-chrome-roundedness);
43
+ border-bottom-left-radius: var(--bookish-app-chrome-roundedness);
44
+ margin-left: var(--bookish-app-chrome-padding);
45
+ }
46
+
47
+ .bookish-app-switch-option:last-child {
48
+ border-top-right-radius: var(--bookish-app-chrome-roundedness);
49
+ border-bottom-right-radius: var(--bookish-app-chrome-roundedness);
50
+ margin-right: var(--bookish-app-chrome-padding);
51
+ }
52
+
53
+ .bookish-app-switch-option-selected {
54
+ background-color: var(--bookish-app-chrome-hover-background);
55
+ }
56
+ </style>