bookish-press 0.9.4 → 0.10.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 (154) hide show
  1. package/dist/components/Auth.svelte +37 -21
  2. package/dist/components/BookPreview.svelte +4 -4
  3. package/dist/components/BookPreview.svelte.d.ts +1 -1
  4. package/dist/components/Link.svelte +19 -12
  5. package/dist/components/app/Button.svelte +1 -8
  6. package/dist/components/app/Link.svelte +1 -7
  7. package/dist/components/app/Options.svelte +1 -6
  8. package/dist/components/app/TextInput.svelte +2 -8
  9. package/dist/components/chapter/Atom.svelte +2 -1
  10. package/dist/components/chapter/Atom.svelte.d.ts +1 -1
  11. package/dist/components/chapter/Block.svelte +9 -9
  12. package/dist/components/chapter/Block.svelte.d.ts +1 -1
  13. package/dist/components/chapter/Callout.svelte.d.ts +1 -1
  14. package/dist/components/chapter/CaptionedCode.svelte +1 -0
  15. package/dist/components/chapter/CaptionedCode.svelte.d.ts +1 -1
  16. package/dist/components/chapter/ChapterBody.svelte +5 -2
  17. package/dist/components/chapter/ChapterBody.svelte.d.ts +1 -1
  18. package/dist/components/chapter/ChapterBody.test.js +3 -3
  19. package/dist/components/chapter/Citations.svelte +17 -16
  20. package/dist/components/chapter/Citations.svelte.d.ts +1 -1
  21. package/dist/components/chapter/Code.svelte +8 -14
  22. package/dist/components/chapter/Comment.svelte +7 -12
  23. package/dist/components/chapter/Comment.svelte.d.ts +1 -1
  24. package/dist/components/chapter/Definition.svelte +8 -9
  25. package/dist/components/chapter/Definition.svelte.d.ts +1 -1
  26. package/dist/components/chapter/Embed.svelte +41 -61
  27. package/dist/components/chapter/Embed.svelte.d.ts +1 -1
  28. package/dist/components/chapter/ErrorMessage.svelte.d.ts +1 -1
  29. package/dist/components/chapter/Figure.svelte +14 -14
  30. package/dist/components/chapter/Figure.svelte.d.ts +4 -4
  31. package/dist/components/chapter/Footnote.svelte +11 -17
  32. package/dist/components/chapter/Footnote.svelte.d.ts +1 -1
  33. package/dist/components/chapter/Format.svelte +11 -11
  34. package/dist/components/chapter/Format.svelte.d.ts +1 -1
  35. package/dist/components/chapter/InlineCode.svelte.d.ts +1 -1
  36. package/dist/components/chapter/Label.svelte +1 -1
  37. package/dist/components/chapter/Label.svelte.d.ts +1 -1
  38. package/dist/components/chapter/LineBreak.svelte +1 -0
  39. package/dist/components/chapter/LineBreak.svelte.d.ts +1 -1
  40. package/dist/components/chapter/Link.svelte +14 -12
  41. package/dist/components/chapter/Link.svelte.d.ts +1 -1
  42. package/dist/components/chapter/List.svelte +1 -1
  43. package/dist/components/chapter/List.svelte.d.ts +1 -1
  44. package/dist/components/chapter/Marginal.svelte +36 -42
  45. package/dist/components/chapter/Paragraph.svelte +4 -4
  46. package/dist/components/chapter/Paragraph.svelte.d.ts +1 -1
  47. package/dist/components/chapter/Positioned.svelte +1 -0
  48. package/dist/components/chapter/Positioned.svelte.d.ts +1 -1
  49. package/dist/components/chapter/Python.svelte +42 -31
  50. package/dist/components/chapter/Python.svelte.d.ts +1 -1
  51. package/dist/components/chapter/Quote.svelte.d.ts +1 -1
  52. package/dist/components/chapter/Rule.svelte +1 -0
  53. package/dist/components/chapter/Rule.svelte.d.ts +1 -1
  54. package/dist/components/chapter/Table.svelte.d.ts +1 -1
  55. package/dist/components/chapter/Text.svelte +41 -50
  56. package/dist/components/chapter/Text.svelte.d.ts +1 -1
  57. package/dist/components/controls/DarkToggle.svelte +4 -4
  58. package/dist/components/editor/BookishEditor.svelte +605 -569
  59. package/dist/components/editor/BookishEditor.svelte.d.ts +1 -1
  60. package/dist/components/editor/CalloutEditor.svelte +1 -1
  61. package/dist/components/editor/CalloutEditor.svelte.d.ts +1 -1
  62. package/dist/components/editor/CaptionedCodeEditor.svelte +1 -1
  63. package/dist/components/editor/CaptionedCodeEditor.svelte.d.ts +1 -1
  64. package/dist/components/editor/CaretContext.d.ts +14 -14
  65. package/dist/components/editor/CaretState.d.ts +3 -3
  66. package/dist/components/editor/CaretView.svelte +8 -19
  67. package/dist/components/editor/CitationsEditor.svelte +10 -18
  68. package/dist/components/editor/CitationsEditor.svelte.d.ts +1 -1
  69. package/dist/components/editor/Clipboard.d.ts +1 -1
  70. package/dist/components/editor/Command.d.ts +1 -1
  71. package/dist/components/editor/Commands.js +19 -19
  72. package/dist/components/editor/ConfirmButton.svelte +1 -6
  73. package/dist/components/editor/DefinitionEditor.svelte +9 -7
  74. package/dist/components/editor/DefinitionEditor.svelte.d.ts +1 -1
  75. package/dist/components/editor/EmbedEditor.svelte +25 -34
  76. package/dist/components/editor/EmbedEditor.svelte.d.ts +1 -1
  77. package/dist/components/editor/ImageChooser.svelte +8 -7
  78. package/dist/components/editor/ImageChooser.svelte.d.ts +1 -1
  79. package/dist/components/editor/ImageThumbnail.svelte +21 -18
  80. package/dist/components/editor/InlineCodeEditor.svelte +1 -1
  81. package/dist/components/editor/InlineCodeEditor.svelte.d.ts +1 -1
  82. package/dist/components/editor/LabelEditor.svelte +2 -2
  83. package/dist/components/editor/LabelEditor.svelte.d.ts +1 -1
  84. package/dist/components/editor/LanguageEditor.svelte +8 -1
  85. package/dist/components/editor/LinkEditor.svelte +42 -44
  86. package/dist/components/editor/LinkEditor.svelte.d.ts +1 -1
  87. package/dist/components/editor/Permissions.svelte +23 -29
  88. package/dist/components/editor/PositionEditor.svelte +1 -1
  89. package/dist/components/editor/PositionEditor.svelte.d.ts +1 -1
  90. package/dist/components/editor/QuoteEditor.svelte +1 -1
  91. package/dist/components/editor/QuoteEditor.svelte.d.ts +1 -1
  92. package/dist/components/editor/Switch.svelte +5 -11
  93. package/dist/components/editor/TableEditor.svelte +1 -1
  94. package/dist/components/editor/TableEditor.svelte.d.ts +1 -1
  95. package/dist/components/editor/TextEditor.svelte +61 -58
  96. package/dist/components/editor/Toggle.svelte +16 -14
  97. package/dist/components/editor/Toolbar.svelte +81 -94
  98. package/dist/components/editor/UndoState.d.ts +2 -2
  99. package/dist/components/page/Acknowledgements.svelte +2 -8
  100. package/dist/components/page/Authors.svelte +12 -21
  101. package/dist/components/page/BookLoader.svelte +32 -34
  102. package/dist/components/page/BulkReferenceEditor.svelte +21 -41
  103. package/dist/components/page/Chapter.svelte +139 -114
  104. package/dist/components/page/Chapter.svelte.d.ts +1 -1
  105. package/dist/components/page/ChapterTitle.svelte +1 -1
  106. package/dist/components/page/Contexts.js +3 -1
  107. package/dist/components/page/DefinitionView.svelte +30 -42
  108. package/dist/components/page/DefinitionView.svelte.d.ts +1 -1
  109. package/dist/components/page/Description.svelte +2 -8
  110. package/dist/components/page/DownloadEPUB.svelte +83 -41
  111. package/dist/components/page/EditableHeader.svelte.d.ts +1 -1
  112. package/dist/components/page/Edition.svelte +44 -30
  113. package/dist/components/page/Edition.svelte.d.ts +1 -1
  114. package/dist/components/page/EditionLoader.svelte +101 -100
  115. package/dist/components/page/Editions.svelte +13 -13
  116. package/dist/components/page/Glossary.svelte +9 -10
  117. package/dist/components/page/Header.svelte +15 -28
  118. package/dist/components/page/Index.svelte +17 -18
  119. package/dist/components/page/License.svelte +2 -8
  120. package/dist/components/page/Media.svelte +7 -14
  121. package/dist/components/page/MediaPreview.svelte +14 -17
  122. package/dist/components/page/Outline.svelte +74 -66
  123. package/dist/components/page/Page.svelte +23 -17
  124. package/dist/components/page/PossibleChapter.svelte +2 -2
  125. package/dist/components/page/PossibleReference.svelte +1 -1
  126. package/dist/components/page/PossibleReference.svelte.d.ts +2 -2
  127. package/dist/components/page/Print.svelte +5 -8
  128. package/dist/components/page/Publish.svelte +33 -39
  129. package/dist/components/page/Reference.svelte +9 -11
  130. package/dist/components/page/Reference.svelte.d.ts +1 -1
  131. package/dist/components/page/References.svelte +1 -1
  132. package/dist/components/page/Search.svelte +39 -40
  133. package/dist/components/page/SubdomainEditor.svelte +11 -10
  134. package/dist/components/page/TableOfContents.svelte +52 -48
  135. package/dist/components/page/TableOfContentsImage.svelte +2 -2
  136. package/dist/components/page/TableOfContentsRow.svelte +9 -22
  137. package/dist/components/page/TableOfContentsRow.svelte.d.ts +2 -2
  138. package/dist/components/page/ThemeEditor.svelte +10 -17
  139. package/dist/components/page/ThemeEditorPreview.svelte +3 -6
  140. package/dist/components/page/ThemeEditorPreview.svelte.d.ts +1 -1
  141. package/dist/components/page/ThemeVariableEditor.svelte +6 -6
  142. package/dist/components/page/Unknown.svelte +1 -1
  143. package/dist/epub/build.d.ts +6 -0
  144. package/dist/epub/build.js +16 -3
  145. package/dist/epub/build.test.js +65 -0
  146. package/dist/epub/images.d.ts +7 -5
  147. package/dist/epub/images.js +15 -10
  148. package/dist/epub/images.test.js +8 -6
  149. package/dist/epub/package.js +25 -3
  150. package/dist/models/FirebaseAvailable.d.ts +9 -0
  151. package/dist/models/FirebaseAvailable.js +10 -0
  152. package/dist/models/book/BookMedia.d.ts +2 -1
  153. package/dist/models/book/BookMedia.js +33 -9
  154. package/package.json +18 -14
@@ -1,39 +1,31 @@
1
- <script lang="ts">import { createUser } from "../../models/CRUD";
2
- import Button from "../app/Button.svelte";
1
+ <script lang="ts">import Button from "../app/Button.svelte";
3
2
  import TextInput from "../app/TextInput.svelte";
4
3
  import { getEditors } from "../page/Contexts";
5
4
  import Note from "./Note.svelte";
6
- let {
7
- uids,
8
- inheriteduids,
9
- writable,
10
- atleastone,
11
- change
12
- } = $props();
5
+ let { uids, inheriteduids, writable, atleastone, change } = $props();
13
6
  let emails = getEditors();
14
7
  let newEditor = $state("");
15
8
  let newEditorError = $state(null);
16
- let loading = $state(void 0);
9
+ let loading = $state(undefined);
17
10
  async function addEditor() {
18
- const email = newEditor;
19
- newEditor = "";
20
- loading = email;
21
- try {
22
- const uid = await createUser(email);
23
- if (uid === null) newEditorError = "couldn't add editor";
24
- else change([...uids, uid]);
25
- } finally {
26
- loading = void 0;
27
- }
11
+ const email = newEditor;
12
+ newEditor = "";
13
+ loading = email;
14
+ try {
15
+ const { createUser } = await import("../../models/CRUD");
16
+ const uid = await createUser(email);
17
+ if (uid === null) newEditorError = "couldn't add editor";
18
+ else change([...uids, uid]);
19
+ } finally {
20
+ loading = undefined;
21
+ }
28
22
  }
29
23
  function hasEditor(email) {
30
- if (email.length === 0) return false;
31
- const match = Array.from($emails.entries()).find(
32
- ([, e]) => e === email
33
- );
34
- if (match === void 0) return false;
35
- const uid = match[0];
36
- return uids.includes(uid) || inheriteduids.includes(uid);
24
+ if (email.length === 0) return false;
25
+ const match = Array.from($emails.entries()).find(([, e]) => e === email);
26
+ if (match === undefined) return false;
27
+ const uid = match[0];
28
+ return uids.includes(uid) || inheriteduids.includes(uid);
37
29
  }
38
30
  </script>
39
31
 
@@ -42,10 +34,12 @@ function hasEditor(email) {
42
34
  {:else}
43
35
  <section class="emails">
44
36
  {#if writable}
45
- <form onsubmit={(event) => {
37
+ <form
38
+ onsubmit={(event) => {
46
39
  event.preventDefault();
47
40
  addEditor();
48
- }}>
41
+ }}
42
+ >
49
43
  <TextInput
50
44
  type="email"
51
45
  placeholder="email"
@@ -4,7 +4,7 @@ import MiddleIcon from "./icons/middle.svg?raw";
4
4
  import RightIcon from "./icons/right.svg?raw";
5
5
  let { value, edit } = $props();
6
6
  function editAsString(newValue) {
7
- edit(newValue);
7
+ edit(newValue);
8
8
  }
9
9
  </script>
10
10
 
@@ -1,4 +1,4 @@
1
- import type Position from '../../models/chapter/Position';
1
+ import type Position from '../../models/chapter/Position.js';
2
2
  interface Props {
3
3
  value: string;
4
4
  edit: (newValue: Position) => void;
@@ -1,4 +1,4 @@
1
- <script lang="ts">import { getCaret } from "../page/Contexts";
1
+ <script lang="ts">import { getCaret } from "../page/Contexts.js";
2
2
  import PositionEditor from "./PositionEditor.svelte";
3
3
  let { quote } = $props();
4
4
  let caret = getCaret();
@@ -1,4 +1,4 @@
1
- import type QuoteNode from '../../models/chapter/QuoteNode';
1
+ import type QuoteNode from '../../models/chapter/QuoteNode.js';
2
2
  interface Props {
3
3
  quote: QuoteNode;
4
4
  }
@@ -1,16 +1,10 @@
1
1
  <script lang="ts">import Icon from "./Icon.svelte";
2
- let {
3
- options,
4
- icons = void 0,
5
- value,
6
- enabled = void 0,
7
- edit
8
- } = $props();
2
+ let { options, icons = undefined, value, enabled = undefined, edit } = $props();
9
3
  function handleClick(event) {
10
- const newValue = event.currentTarget.dataset.value;
11
- if (newValue && options.includes(newValue)) {
12
- edit(newValue);
13
- }
4
+ const newValue = event.currentTarget.dataset.value;
5
+ if (newValue && options.includes(newValue)) {
6
+ edit(newValue);
7
+ }
14
8
  }
15
9
  </script>
16
10
 
@@ -1,4 +1,4 @@
1
- <script lang="ts">import { getCaret } from "../page/Contexts";
1
+ <script lang="ts">import { getCaret } from "../page/Contexts.js";
2
2
  import PositionEditor from "./PositionEditor.svelte";
3
3
  let { table } = $props();
4
4
  let caret = getCaret();
@@ -1,4 +1,4 @@
1
- import type TableNode from '../../models/chapter/TableNode';
1
+ import type TableNode from '../../models/chapter/TableNode.js';
2
2
  interface Props {
3
3
  table: TableNode;
4
4
  }
@@ -1,84 +1,87 @@
1
1
  <script lang="ts">import { untrack } from "svelte";
2
- var Status = /* @__PURE__ */ ((Status2) => {
3
- Status2[Status2["Viewing"] = 0] = "Viewing";
4
- Status2[Status2["Editing"] = 1] = "Editing";
5
- return Status2;
6
- })(Status || {});
7
- let {
8
- text = $bindable(),
9
- label,
10
- placeholder,
11
- valid,
12
- save,
13
- saveOnExit = false,
14
- width = void 0,
15
- clip = false,
16
- move = void 0
17
- } = $props();
18
- let status = $state(0 /* Viewing */);
2
+ // A plain object rather than a TypeScript enum: Vite 8's TS transform
3
+ // inlines enum members in the script and then drops the declaration as
4
+ // unused, though the markup below still reads it.
5
+ const Status = {
6
+ Viewing: 0,
7
+ Editing: 1
8
+ };
9
+ let { text = $bindable(), label, placeholder, valid, save, saveOnExit = false, width = undefined, clip = false, move = undefined } = $props();
10
+ let status = $state(Status.Viewing);
19
11
  let field = $state(null);
20
12
  let sizer = $state(null);
21
13
  function showPlaceholder() {
22
- return text === "";
14
+ return text === "";
23
15
  }
24
16
  function startEditing() {
25
- status = 1 /* Editing */;
17
+ status = Status.Editing;
26
18
  }
27
19
  function stopEditing() {
28
- status = 0 /* Viewing */;
29
- if (saveOnExit) saveText(text);
20
+ status = Status.Viewing;
21
+ if (saveOnExit) saveText(text);
30
22
  }
31
23
  function edit() {
32
- if (field) {
33
- text = field.value;
34
- if (saveOnExit === false) saveText(text);
35
- }
24
+ if (field) {
25
+ text = field.value;
26
+ if (saveOnExit === false) saveText(text);
27
+ }
36
28
  }
37
29
  function saveText(newText) {
38
- if (validate(newText) === void 0) {
39
- const revisedText = save(newText);
40
- if (typeof revisedText === "string") {
41
- text = revisedText;
42
- }
43
- if (revisedText instanceof Promise)
44
- revisedText.catch((err) => error = err.message);
45
- }
30
+ if (validate(newText) === undefined) {
31
+ const revisedText = save(newText);
32
+ if (typeof revisedText === "string") {
33
+ text = revisedText;
34
+ }
35
+ if (revisedText instanceof Promise) revisedText.catch((err) => error = err.message);
36
+ }
46
37
  }
47
38
  function validate(value) {
48
- return valid(value);
39
+ return valid(value);
49
40
  }
50
41
  function handleKeyPress(event) {
51
- if (event.key === "Enter") status = 0 /* Viewing */;
52
- else if (event.key === "ArrowUp" && move && field) {
53
- event.preventDefault();
54
- move(field, -1);
55
- } else if (event.key === "ArrowDown" && move && field) {
56
- event.preventDefault();
57
- move(field, 1);
58
- }
42
+ if (event.key === "Enter") status = Status.Viewing;
43
+ else if (event.key === "ArrowUp" && move && field) {
44
+ event.preventDefault();
45
+ move(field, -1);
46
+ } else if (event.key === "ArrowDown" && move && field) {
47
+ event.preventDefault();
48
+ move(field, 1);
49
+ }
59
50
  }
60
51
  let error = $derived(valid(text));
52
+ // Grow the sizer when text or status changes.
61
53
  $effect(() => {
62
- if (sizer) {
63
- const sizedText = showPlaceholder() ? placeholder : text.replace(/\s$/g, "\xA0");
64
- const trimmedText = width !== void 0 && (clip === true || status === 1 /* Editing */) ? sizedText.substring(0, width) + "\u2026" : sizedText;
65
- sizer.innerHTML = trimmedText;
66
- }
54
+ if (sizer) {
55
+ // Set the invisible sizer to the text to set the container's width.
56
+ // The browser strips trailing spaces, causing jitter after a space, so we replace
57
+ // them with non-breaking spaces.
58
+ const sizedText = showPlaceholder() ? placeholder : text.replace(/\s$/g, "\xA0");
59
+ // Clip the text to prevent this editor from getting too long when editing. If it goes past one line,
60
+ // the measurements and layout are way off.
61
+ const trimmedText = width !== undefined && (clip === true || status === Status.Editing) ? sizedText.substring(0, width) + "…" : sizedText;
62
+ sizer.innerHTML = trimmedText;
63
+ }
67
64
  });
65
+ // When status changes, focus or blur.
68
66
  $effect(() => {
69
- if (field) {
70
- if (status === 1 /* Editing */) {
71
- field.focus();
72
- } else {
73
- field.blur();
74
- }
75
- }
67
+ if (field) {
68
+ if (status === Status.Editing) {
69
+ field.focus();
70
+ } else {
71
+ field.blur();
72
+ }
73
+ }
76
74
  });
75
+ // When text changes, save, unless we only save on exit. Only the text is
76
+ // tracked: the save/valid props are often inline closures recreated on
77
+ // every parent render, and saving usually triggers a parent re-render, so
78
+ // tracking them (as calling saveText inside the effect otherwise would)
79
+ // makes this effect loop forever.
77
80
  $effect(() => {
78
- void text;
79
- untrack(() => {
80
- if (!saveOnExit) saveText(text);
81
- });
81
+ void text;
82
+ untrack(() => {
83
+ if (!saveOnExit) saveText(text);
84
+ });
82
85
  });
83
86
  </script>
84
87
 
@@ -1,19 +1,21 @@
1
- <script lang="ts">var Status = /* @__PURE__ */ ((Status2) => {
2
- Status2[Status2["Viewing"] = 0] = "Viewing";
3
- Status2[Status2["Saving"] = 1] = "Saving";
4
- Status2[Status2["Error"] = 2] = "Error";
5
- return Status2;
6
- })(Status || {});
1
+ <script lang="ts">// A plain object rather than a TypeScript enum: Vite 8's TS transform
2
+ // inlines enum members in the script and then drops the declaration as
3
+ // unused, though the markup below still reads it.
4
+ const Status = {
5
+ Viewing: 0,
6
+ Saving: 1,
7
+ Error: 2
8
+ };
7
9
  let { on, save, children } = $props();
8
- let saving = $state(0 /* Viewing */);
10
+ let saving = $state(Status.Viewing);
9
11
  function toggle() {
10
- saving = 1 /* Saving */;
11
- const promise = save(!on);
12
- if (promise === void 0) {
13
- saving = 0 /* Viewing */;
14
- return;
15
- }
16
- promise.then(() => saving = 0 /* Viewing */).catch(() => saving = 2 /* Error */);
12
+ saving = Status.Saving;
13
+ const promise = save(!on);
14
+ if (promise === undefined) {
15
+ saving = Status.Viewing;
16
+ return;
17
+ }
18
+ promise.then(() => saving = Status.Viewing).catch(() => saving = Status.Error);
17
19
  }
18
20
  </script>
19
21
 
@@ -1,15 +1,15 @@
1
1
  <script lang="ts">import commands from "./Commands";
2
- import TextNode from "../../models/chapter/TextNode";
3
- import AtomNode from "../../models/chapter/AtomNode";
4
- import LinkNode from "../../models/chapter/LinkNode";
5
- import LabelNode from "../../models/chapter/LabelNode";
6
- import InlineCodeNode from "../../models/chapter/InlineCodeNode";
7
- import CitationsNode from "../../models/chapter/CitationsNode";
8
- import DefinitionNode from "../../models/chapter/DefinitionNode";
9
- import CodeNode from "../../models/chapter/CodeNode";
10
- import CalloutNode from "../../models/chapter/CalloutNode";
11
- import EmbedNode from "../../models/chapter/EmbedNode";
12
- import QuoteNode from "../../models/chapter/QuoteNode";
2
+ import TextNode from "../../models/chapter/TextNode.js";
3
+ import AtomNode from "../../models/chapter/AtomNode.js";
4
+ import LinkNode from "../../models/chapter/LinkNode.js";
5
+ import LabelNode from "../../models/chapter/LabelNode.js";
6
+ import InlineCodeNode from "../../models/chapter/InlineCodeNode.js";
7
+ import CitationsNode from "../../models/chapter/CitationsNode.js";
8
+ import DefinitionNode from "../../models/chapter/DefinitionNode.js";
9
+ import CodeNode from "../../models/chapter/CodeNode.js";
10
+ import CalloutNode from "../../models/chapter/CalloutNode.js";
11
+ import EmbedNode from "../../models/chapter/EmbedNode.js";
12
+ import QuoteNode from "../../models/chapter/QuoteNode.js";
13
13
  import LabelEditor from "./LabelEditor.svelte";
14
14
  import InlineCodeEditor from "./InlineCodeEditor.svelte";
15
15
  import CitationsEditor from "./CitationsEditor.svelte";
@@ -43,104 +43,91 @@ import TableNode from "../../models/chapter/TableNode";
43
43
  import { slide } from "svelte/transition";
44
44
  import Note from "./Note.svelte";
45
45
  const keyLabels = {
46
- Digit0: "0",
47
- Digit1: "1",
48
- Digit2: "2",
49
- Digit3: "3",
50
- ArrowDown: "\u2193",
51
- ArrowUp: "\u2191",
52
- ArrowLeft: "\u2190",
53
- ArrowRight: "\u2192",
54
- Backspace: "\u232B"
46
+ Digit0: "0",
47
+ Digit1: "1",
48
+ Digit2: "2",
49
+ Digit3: "3",
50
+ ArrowDown: "↓",
51
+ ArrowUp: "↑",
52
+ ArrowLeft: "←",
53
+ ArrowRight: "→",
54
+ Backspace: "⌫"
55
55
  };
56
56
  const categoryOrder = {
57
- navigation: 1,
58
- selection: 2,
59
- text: 3,
60
- history: 4,
61
- clipboard: 5,
62
- annotation: 6,
63
- level: 8,
64
- list: 9,
65
- table: 10,
66
- block: 11
57
+ navigation: 1,
58
+ selection: 2,
59
+ text: 3,
60
+ history: 4,
61
+ clipboard: 5,
62
+ annotation: 6,
63
+ level: 8,
64
+ list: 9,
65
+ table: 10,
66
+ block: 11
67
67
  };
68
68
  const categoryIcons = {
69
- text: TextIcon,
70
- clipboard: ClipboardIcon,
71
- annotation: AnnotateIcon,
72
- level: LevelIcon,
73
- block: BlockIcon,
74
- list: ListIcon,
75
- table: TableIcon,
76
- history: TimeIcon
69
+ text: TextIcon,
70
+ clipboard: ClipboardIcon,
71
+ annotation: AnnotateIcon,
72
+ level: LevelIcon,
73
+ block: BlockIcon,
74
+ list: ListIcon,
75
+ table: TableIcon,
76
+ history: TimeIcon
77
77
  };
78
78
  let { caret } = $props();
79
79
  let context = $derived(caret?.context);
80
80
  let root = $derived(context?.root);
81
81
  let element = $state(null);
82
- let categories = $state(void 0);
82
+ let categories = $state(undefined);
83
83
  let commandsByCategory = $state({});
84
- let metaNode = $state(void 0);
85
- let calloutNode = $state(void 0);
86
- let quoteNode = $state(void 0);
87
- let embedNode = $state(void 0);
88
- let tableNode = $state(void 0);
84
+ let metaNode = $state(undefined);
85
+ let calloutNode = $state(undefined);
86
+ let quoteNode = $state(undefined);
87
+ let embedNode = $state(undefined);
88
+ let tableNode = $state(undefined);
89
89
  function getShortcutDescription(command) {
90
- const macOS = navigator.userAgent.indexOf("Mac") >= 0;
91
- const controlSymbol = macOS ? "\u2318" : "Ctrl+";
92
- const altSymbol = macOS ? "\u2325" : "Alt+";
93
- const key = command.key ? Array.isArray(command.key) ? command.key.join("/") : command.key : command.code ? command.code : "any";
94
- const keyLabel = (typeof key === "string" ? key in keyLabels ? keyLabels[key] : key : "\u2014").toLocaleUpperCase();
95
- return `${command.control ? controlSymbol : ""}${command.alt ? altSymbol : ""}${command.shift ? "\u21E7" : ""}${keyLabel}`;
90
+ const macOS = navigator.userAgent.indexOf("Mac") >= 0;
91
+ const controlSymbol = macOS ? "⌘" : "Ctrl+";
92
+ const altSymbol = macOS ? "⌥" : "Alt+";
93
+ const key = command.key ? Array.isArray(command.key) ? command.key.join("/") : command.key : command.code ? command.code : "any";
94
+ const keyLabel = (typeof key === "string" ? key in keyLabels ? keyLabels[key] : key : "—").toLocaleUpperCase();
95
+ return `${command.control ? controlSymbol : ""}${command.alt ? altSymbol : ""}${command.shift ? "⇧" : ""}${keyLabel}`;
96
96
  }
97
+ // Update the above when the dependencies below change. Everything is
98
+ // computed into locals and assigned once so the effect never reads
99
+ // the state it writes.
97
100
  $effect.pre(() => {
98
- if (context !== void 0 && root) {
99
- const visible = commands.filter(
100
- (command) => command.visible === true || context && command.visible instanceof Function && command.visible(context)
101
- );
102
- const newCategories = Array.from(
103
- new Set(commands.map((command) => command.category))
104
- ).sort(
105
- (a, b) => a in categoryOrder && b in categoryOrder ? categoryOrder[a] - categoryOrder[b] : 0
106
- );
107
- const byCategory = {};
108
- newCategories.forEach((cat) => {
109
- byCategory[cat] = visible.filter(
110
- (command) => command.category === cat
111
- );
112
- });
113
- const caretNode = context.start.node;
114
- categories = newCategories;
115
- commandsByCategory = byCategory;
116
- metaNode = caretNode instanceof AtomNode ? caretNode : caretNode instanceof TextNode ? caretNode.getParent(root) : void 0;
117
- calloutNode = caretNode.getClosestParentMatching(
118
- root,
119
- (p) => p instanceof CalloutNode
120
- );
121
- quoteNode = caretNode.getClosestParentMatching(
122
- root,
123
- (p) => p instanceof QuoteNode
124
- );
125
- embedNode = caretNode instanceof EmbedNode ? caretNode : caretNode.getClosestParentMatching(
126
- root,
127
- (p) => p instanceof EmbedNode
128
- );
129
- tableNode = caretNode.getClosestParentMatching(
130
- root,
131
- (p) => p instanceof TableNode
132
- );
133
- }
101
+ if (context !== undefined && root) {
102
+ // Filter the commands by those interactive with a mouse and active.
103
+ const visible = commands.filter((command) => command.visible === true || context && command.visible instanceof Function && command.visible(context));
104
+ // Extract the active categories and sort them
105
+ const newCategories = Array.from(new Set(commands.map((command) => command.category))).sort((a, b) => a in categoryOrder && b in categoryOrder ? categoryOrder[a] - categoryOrder[b] : 0);
106
+ // Make a list for each category of commands
107
+ const byCategory = {};
108
+ newCategories.forEach((cat) => {
109
+ byCategory[cat] = visible.filter((command) => command.category === cat);
110
+ });
111
+ const caretNode = context.start.node;
112
+ categories = newCategories;
113
+ commandsByCategory = byCategory;
114
+ metaNode = caretNode instanceof AtomNode ? caretNode : caretNode instanceof TextNode ? caretNode.getParent(root) : undefined;
115
+ calloutNode = caretNode.getClosestParentMatching(root, (p) => p instanceof CalloutNode);
116
+ quoteNode = caretNode.getClosestParentMatching(root, (p) => p instanceof QuoteNode);
117
+ embedNode = caretNode instanceof EmbedNode ? caretNode : caretNode.getClosestParentMatching(root, (p) => p instanceof EmbedNode);
118
+ tableNode = caretNode.getClosestParentMatching(root, (p) => p instanceof TableNode);
119
+ }
134
120
  });
135
121
  function handleKeyPress(event) {
136
- if ((event.key === "Escape" || event.key === "Enter") && element) {
137
- const editor = element.closest(".bookish-editor");
138
- if (editor instanceof HTMLElement) {
139
- event.stopPropagation();
140
- editor.focus();
141
- }
142
- return true;
143
- }
122
+ // Return focus to the editor if someone presses an unhandled enter
123
+ if ((event.key === "Escape" || event.key === "Enter") && element) {
124
+ const editor = element.closest(".bookish-editor");
125
+ if (editor instanceof HTMLElement) {
126
+ event.stopPropagation();
127
+ editor.focus();
128
+ }
129
+ return true;
130
+ }
144
131
  }
145
132
  </script>
146
133
 
@@ -1,5 +1,5 @@
1
- import type { IndexRange } from '../../models/chapter/Caret';
2
- import type Command from './Command';
1
+ import type { IndexRange } from '../../models/chapter/Caret.js';
2
+ import type Command from './Command.js';
3
3
  type UndoState = {
4
4
  command: Command | undefined;
5
5
  bookdown: string;
@@ -1,14 +1,8 @@
1
- <script lang="ts">import Parser from "../../models/chapter/Parser";
1
+ <script lang="ts">import Parser from "../../models/chapter/Parser.js";
2
2
  import ChapterBody from "../chapter/ChapterBody.svelte";
3
3
  import BookishEditor from "../editor/BookishEditor.svelte";
4
4
  import Instructions from "./Instructions.svelte";
5
- import {
6
- getUser,
7
- getEdition,
8
- getLeasee,
9
- isEditionEditable,
10
- lease
11
- } from "./Contexts";
5
+ import { getUser, getEdition, getLeasee, isEditionEditable, lease } from "./Contexts";
12
6
  import PageHeader from "./PageHeader.svelte";
13
7
  import EditableHeader from "./EditableHeader.svelte";
14
8
  let auth = getUser();
@@ -1,4 +1,4 @@
1
- <script lang="ts">import Parser from "../../models/chapter/Parser";
1
+ <script lang="ts">import Parser from "../../models/chapter/Parser.js";
2
2
  import TextEditor from "../editor/TextEditor.svelte";
3
3
  import Format from "../chapter/Format.svelte";
4
4
  import { getEdition, getLeasee, getUser, lease } from "./Contexts";
@@ -6,30 +6,21 @@ import Note from "../editor/Note.svelte";
6
6
  import Button from "../app/Button.svelte";
7
7
  import { tick } from "svelte";
8
8
  import BookishEditor from "../editor/BookishEditor.svelte";
9
- import { auth } from "../../models/Firebase";
10
- let {
11
- editable,
12
- authors,
13
- inheritedAuthors = void 0,
14
- add,
15
- edit,
16
- remove,
17
- editors = false
18
- } = $props();
9
+ let { editable, authors, inheritedAuthors = undefined, add, edit, remove, editors = false } = $props();
19
10
  let edition = getEdition();
20
11
  let authorList = $state(null);
21
- let showInherited = $derived(authors.length === 0 && inheritedAuthors !== void 0);
12
+ let showInherited = $derived(authors.length === 0 && inheritedAuthors !== undefined);
22
13
  let authorsToShow = $derived(showInherited ? inheritedAuthors : authors);
23
14
  async function addAuthor() {
24
- add();
25
- await tick();
26
- if (authors.length > 0 && authorList) {
27
- const editors2 = authorList.querySelectorAll("input");
28
- if (editors2.length > 0) {
29
- const lastAuthor = editors2[editors2.length - 1];
30
- if (lastAuthor instanceof HTMLElement) lastAuthor.focus();
31
- }
32
- }
15
+ add();
16
+ await tick();
17
+ if (authors.length > 0 && authorList) {
18
+ const editors = authorList.querySelectorAll("input");
19
+ if (editors.length > 0) {
20
+ const lastAuthor = editors[editors.length - 1];
21
+ if (lastAuthor instanceof HTMLElement) lastAuthor.focus();
22
+ }
23
+ }
33
24
  }
34
25
  </script>
35
26