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
@@ -2,7 +2,7 @@
2
2
  import Outline from "./Outline.svelte";
3
3
  import Page from "./Page.svelte";
4
4
  import Instructions from "./Instructions.svelte";
5
- import ChapterIDs from "../../models/book/ChapterID";
5
+ import ChapterIDs from "../../models/book/ChapterID.js";
6
6
  import Link from "../Link.svelte";
7
7
  import { getBase, getEdition, isEditionEditable } from "./Contexts";
8
8
  import { page } from "$app/state";
@@ -14,28 +14,27 @@ import Rows from "./Rows.svelte";
14
14
  let editable = isEditionEditable();
15
15
  let edition = getEdition();
16
16
  let base = getBase();
17
+ // What letter are we matching?
17
18
  let letter = $derived(page.params.letter);
18
19
  let bookIndex = $derived($edition?.getBookIndex() ?? {});
20
+ // Figure out what letters have words
19
21
  let letters = $derived.by(() => {
20
- const map = {};
21
- for (const word of Object.keys(bookIndex).sort(
22
- (a, b) => a.localeCompare(b)
23
- ))
24
- map[word.charAt(0).toLocaleLowerCase()] = true;
25
- return map;
22
+ const map = {};
23
+ for (const word of Object.keys(bookIndex).sort((a, b) => a.localeCompare(b))) map[word.charAt(0).toLocaleLowerCase()] = true;
24
+ return map;
26
25
  });
27
26
  let words = $derived.by(() => {
28
- const list = [];
29
- let count = 0;
30
- Object.keys(bookIndex).sort((a, b) => a.localeCompare(b)).forEach((word) => {
31
- const firstLetter = word.charAt(0).toLowerCase();
32
- if (letter === firstLetter) {
33
- count++;
34
- if (count % 20 === 0) list.push(true);
35
- list.push(word);
36
- }
37
- });
38
- return list;
27
+ const list = [];
28
+ let count = 0;
29
+ Object.keys(bookIndex).sort((a, b) => a.localeCompare(b)).forEach((word) => {
30
+ const firstLetter = word.charAt(0).toLowerCase();
31
+ if (letter === firstLetter) {
32
+ count++;
33
+ if (count % 20 === 0) list.push(true);
34
+ list.push(word);
35
+ }
36
+ });
37
+ return list;
39
38
  });
40
39
  </script>
41
40
 
@@ -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 BookishEditor from "../editor/BookishEditor.svelte";
3
3
  import Instructions from "./Instructions.svelte";
4
4
  import Format from "../chapter/Format.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 EditableHeader from "./EditableHeader.svelte";
13
7
  let auth = getUser();
14
8
  let edition = getEdition();
@@ -2,17 +2,11 @@
2
2
  import Outline from "./Outline.svelte";
3
3
  import Page from "./Page.svelte";
4
4
  import Instructions from "./Instructions.svelte";
5
- import ChapterIDs from "../../models/book/ChapterID";
5
+ import ChapterIDs from "../../models/book/ChapterID.js";
6
6
  import Format from "../chapter/Format.svelte";
7
7
  import MediaPreview from "./MediaPreview.svelte";
8
8
  import { onMount } from "svelte";
9
- import {
10
- getBase,
11
- getBook,
12
- getEdition,
13
- isBookEditable,
14
- isEditionEditable
15
- } from "./Contexts";
9
+ import { getBase, getBook, getEdition, isBookEditable, isEditionEditable } from "./Contexts";
16
10
  import PageHeader from "./PageHeader.svelte";
17
11
  import ConfirmButton from "../editor/ConfirmButton.svelte";
18
12
  let book = getBook();
@@ -23,15 +17,14 @@ let images = $state([]);
23
17
  let embeds = $derived($edition?.getEmbeds() ?? []);
24
18
  let media = $derived($book?.getMedia());
25
19
  function updateImages(newImages) {
26
- images = newImages;
20
+ images = newImages;
27
21
  }
28
22
  onMount(() => {
29
- media?.notify(updateImages);
30
- return () => media?.stopNotifying(updateImages);
23
+ // Listen to image changes.
24
+ media?.notify(updateImages);
25
+ return () => media?.stopNotifying(updateImages);
31
26
  });
32
- let unused = $derived(images?.filter(
33
- (image) => !embeds.some((embed) => image.url.includes(embed.embed.getURL()))
34
- ));
27
+ let unused = $derived(images?.filter((image) => !embeds.some((embed) => image.url.includes(embed.embed.getURL()))));
35
28
  </script>
36
29
 
37
30
  {#if $edition}
@@ -1,25 +1,22 @@
1
1
  <script lang="ts">import Link from "../Link.svelte";
2
2
  import { getBase } from "./Contexts";
3
- let {
4
- url,
5
- alt,
6
- chapterID,
7
- children
8
- } = $props();
3
+ let { url, alt, chapterID, children } = $props();
9
4
  let base = getBase();
10
5
  let loaded = $state();
11
- let urlChecked = void 0;
6
+ // Not $state: it's only a guard against re-checking the same URL, and
7
+ // making it reactive would make this effect re-run on its own write.
8
+ let urlChecked = undefined;
12
9
  $effect.pre(() => {
13
- if (urlChecked !== url && typeof Image !== "undefined") {
14
- urlChecked = url;
15
- let image = new Image();
16
- image.src = url;
17
- loaded = image.complete;
18
- if (!loaded) {
19
- image.onload = () => loaded = true;
20
- image.onerror = () => loaded = null;
21
- }
22
- }
10
+ if (urlChecked !== url && typeof Image !== "undefined") {
11
+ urlChecked = url;
12
+ let image = new Image();
13
+ image.src = url;
14
+ loaded = image.complete;
15
+ if (!loaded) {
16
+ image.onload = () => loaded = true;
17
+ image.onerror = () => loaded = null;
18
+ }
19
+ }
23
20
  });
24
21
  </script>
25
22
 
@@ -1,14 +1,9 @@
1
- <script lang="ts">import { isMobile } from "../../util/isMobile";
1
+ <script lang="ts">import { isMobile } from "../../util/isMobile.js";
2
2
  import { onMount } from "svelte";
3
3
  import Link from "../Link.svelte";
4
4
  import { getBase, getDarkMode } from "./Contexts";
5
5
  import DarkToggle from "../controls/DarkToggle.svelte";
6
- let {
7
- previous,
8
- next,
9
- collapse = false,
10
- listener = void 0
11
- } = $props();
6
+ let { previous, next, collapse = false, listener = undefined } = $props();
12
7
  let headerString = null;
13
8
  let headerIndex = $state(-1);
14
9
  let expanded = $state(false);
@@ -17,80 +12,93 @@ let base = getBase();
17
12
  let outline = $state(null);
18
13
  let headers = $state([]);
19
14
  function toggleExpanded() {
20
- if (!isMobile()) return;
21
- const newExpanded = !expanded;
22
- expanded = newExpanded;
23
- if (listener) listener(newExpanded, layout);
15
+ // Don't toggle when in margin mode.
16
+ if (!isMobile()) return;
17
+ const newExpanded = !expanded;
18
+ // Toggle expanded state
19
+ expanded = newExpanded;
20
+ if (listener) listener(newExpanded, layout);
24
21
  }
25
22
  function toggleReadingMode() {
26
- dark.set(!$dark);
23
+ dark.set(!$dark);
27
24
  }
28
25
  function layout() {
29
- position();
30
- highlight();
31
- updateHeaders();
26
+ position();
27
+ highlight();
28
+ updateHeaders();
32
29
  }
33
30
  function updateHeaders() {
34
- headers = Array.from(document.getElementsByClassName("page-header"));
35
- let newHeaderString = headers.reduce(
36
- (sum, el) => sum + el.outerHTML,
37
- ""
38
- );
39
- if (headerString !== newHeaderString) headerString = newHeaderString;
31
+ // When the outline updates (due to the page its on updating), generate a unique string for the current header outline.
32
+ // If it's different from the last rendered state, refresh.
33
+ headers = Array.from(document.getElementsByClassName("page-header"));
34
+ let newHeaderString = headers.reduce((sum, el) => sum + el.outerHTML, "");
35
+ // If the headers change, update the outline.
36
+ if (headerString !== newHeaderString) headerString = newHeaderString;
40
37
  }
41
38
  function getHighlightThreshold() {
42
- return window.innerHeight / 3;
39
+ return window.innerHeight / 3;
43
40
  }
44
41
  function position() {
45
- let title = document.getElementsByClassName(
46
- "bookish-chapter-header-text"
47
- )[0];
48
- if (outline && title) {
49
- if (isMobile()) {
50
- outline.style.removeProperty("margin-top");
51
- } else {
52
- let titleY = title.getBoundingClientRect().top + window.scrollY;
53
- if (titleY - 50 < window.scrollY) {
54
- outline.classList.add("outline-fixed-left");
55
- outline.classList.remove("outline-title-left");
56
- } else {
57
- outline.classList.remove("outline-fixed-left");
58
- outline.classList.add("outline-title-left");
59
- }
60
- if (listener) listener(false, layout);
61
- }
62
- }
42
+ // Left align the floating outline with the left margin of the chapter
43
+ // and the top of the title, unless we're past it.
44
+ let title = document.getElementsByClassName("bookish-chapter-header-text")[0];
45
+ // If we found them both...
46
+ if (outline && title) {
47
+ // If so, remove the inline position so the footer CSS applies.
48
+ if (isMobile()) {
49
+ outline.style.removeProperty("margin-top");
50
+ } else {
51
+ let titleY = title.getBoundingClientRect().top + window.scrollY;
52
+ // If the title is off screen, anchor it to the top of the window. (CSS is set to do this).
53
+ if (titleY - 50 < window.scrollY) {
54
+ outline.classList.add("outline-fixed-left");
55
+ outline.classList.remove("outline-title-left");
56
+ } else {
57
+ outline.classList.remove("outline-fixed-left");
58
+ outline.classList.add("outline-title-left");
59
+ }
60
+ // Tell any listeners about the repositioning.
61
+ if (listener) listener(false, layout);
62
+ }
63
+ }
63
64
  }
64
65
  function highlight() {
65
- const top = window.scrollY;
66
- const threshold = getHighlightThreshold();
67
- let indexOfNearestHeaderAbove = -1;
68
- Array.from(document.getElementsByClassName("page-header")).forEach(
69
- (header, index) => {
70
- if (header.tagName === "H1" || header.tagName === "H2" || header.tagName === "H3") {
71
- let rect = header.getBoundingClientRect();
72
- let headerTop = rect.y + top - rect.height;
73
- if (top > headerTop - threshold)
74
- indexOfNearestHeaderAbove = index;
75
- }
76
- }
77
- );
78
- headerIndex = indexOfNearestHeaderAbove;
66
+ const top = window.scrollY;
67
+ const threshold = getHighlightThreshold();
68
+ // Find the header that we're past so we can update the outline.
69
+ let indexOfNearestHeaderAbove = -1;
70
+ Array.from(document.getElementsByClassName("page-header")).forEach((header, index) => {
71
+ // Is this a header we care about?
72
+ if (header.tagName === "H1" || header.tagName === "H2" || header.tagName === "H3") {
73
+ let rect = header.getBoundingClientRect();
74
+ let headerTop = rect.y + top - rect.height;
75
+ // Are we past this header?
76
+ if (top > headerTop - threshold) indexOfNearestHeaderAbove = index;
77
+ }
78
+ });
79
+ // Update the outline and progress bar.
80
+ headerIndex = indexOfNearestHeaderAbove;
79
81
  }
80
82
  onMount(() => {
81
- window.addEventListener("resize", layout);
82
- window.addEventListener("scroll", layout);
83
- document.addEventListener("selectionchange", updateHeaders);
84
- layout();
85
- return () => {
86
- window.removeEventListener("scroll", layout);
87
- window.removeEventListener("resize", layout);
88
- document.removeEventListener("selectionchange", updateHeaders);
89
- };
83
+ window.addEventListener("resize", layout);
84
+ window.addEventListener("scroll", layout);
85
+ // This is a bit hacky: we update the headers on every selection change so we
86
+ // can detect any header changes during editing. This isn't necessary during
87
+ // reading, and is only necessary when a header is created, updated, or removed,
88
+ // but we don't have a precise mechanism to listen to chapter changes, so we do this instead.
89
+ document.addEventListener("selectionchange", updateHeaders);
90
+ // Position outline after first render.
91
+ layout();
92
+ // Stop listening!
93
+ return () => {
94
+ window.removeEventListener("scroll", layout);
95
+ window.removeEventListener("resize", layout);
96
+ document.removeEventListener("selectionchange", updateHeaders);
97
+ };
90
98
  });
91
- let previousLabel = "\u25C0\uFE0E";
92
- let nextLabel = "\u25B6\uFE0E";
93
- let expandLabel = "\u2630";
99
+ let previousLabel = "◀︎";
100
+ let nextLabel = "▶︎";
101
+ let expandLabel = "☰";
94
102
  </script>
95
103
 
96
104
  <nav
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">import { onMount } from "svelte";
2
2
  import Loading from "./Loading.svelte";
3
- let { title = void 0, afterLoaded = void 0, children } = $props();
3
+ let { title = undefined, afterLoaded = undefined, children } = $props();
4
4
  let fontsLoaded = $state(false);
5
5
  let imagesLoaded = $state(false);
6
6
  let lastHeight = 0;
@@ -8,28 +8,34 @@ let intervalID = null;
8
8
  let mountTime = Date.now();
9
9
  let loaded = $derived(fontsLoaded && imagesLoaded);
10
10
  function watchLoading() {
11
- const bodyHeight = document.body.clientHeight;
12
- if (lastHeight === bodyHeight && imagesAreLoaded() || Date.now() - mountTime > 2e3) {
13
- stopWatching();
14
- imagesLoaded = true;
15
- if (afterLoaded) afterLoaded();
16
- }
17
- lastHeight = bodyHeight;
11
+ const bodyHeight = document.body.clientHeight;
12
+ // If the height hasn't changed and images are loaded OR it's been 2 seconds, load.
13
+ if (lastHeight === bodyHeight && imagesAreLoaded() || Date.now() - mountTime > 2e3) {
14
+ // Stop watching the images
15
+ stopWatching();
16
+ // Set to loaded to hide the overlay and notify callback if there is one.
17
+ imagesLoaded = true;
18
+ if (afterLoaded) afterLoaded();
19
+ }
20
+ // Remember the last height
21
+ lastHeight = bodyHeight;
18
22
  }
19
23
  function stopWatching() {
20
- if (intervalID) clearInterval(intervalID);
24
+ if (intervalID) clearInterval(intervalID);
21
25
  }
22
26
  onMount(() => {
23
- intervalID = setInterval(() => watchLoading(), 50);
24
- document.fonts.ready.then(() => fontsLoaded = true);
25
- return () => stopWatching();
27
+ // Watch the height of the document and wait until it's been stable for a while before scrolling
28
+ // to any targets. We use the data below to monitor the document height over time.
29
+ intervalID = setInterval(() => watchLoading(), 50);
30
+ document.fonts.ready.then(() => fontsLoaded = true);
31
+ return () => stopWatching();
26
32
  });
27
33
  function imagesAreLoaded() {
28
- let done = true;
29
- Array.from(document.getElementsByTagName("img")).forEach((el) => {
30
- done = done && el.complete;
31
- });
32
- return done;
34
+ let done = true;
35
+ Array.from(document.getElementsByTagName("img")).forEach((el) => {
36
+ done = done && el.complete;
37
+ });
38
+ return done;
33
39
  }
34
40
  </script>
35
41
 
@@ -1,10 +1,10 @@
1
1
  <script lang="ts">import Chapter from "./Chapter.svelte";
2
2
  import { page } from "$app/state";
3
- import { getEdition } from "./Contexts";
3
+ import { getEdition } from "./Contexts.js";
4
4
  import Unknown from "./Unknown.svelte";
5
5
  let edition = $derived(getEdition());
6
6
  let chapterID = $derived(page.params.chapterid);
7
- let chapter = $derived(chapterID === void 0 ? void 0 : $edition?.getChapter(chapterID));
7
+ let chapter = $derived(chapterID === undefined ? undefined : $edition?.getChapter(chapterID));
8
8
  </script>
9
9
 
10
10
  {#if chapter}
@@ -1,4 +1,4 @@
1
- <script lang="ts">import FormatNode from "../../models/chapter/FormatNode";
1
+ <script lang="ts">import FormatNode from "../../models/chapter/FormatNode.js";
2
2
  import Format from "../chapter/Format.svelte";
3
3
  import Reference from "./Reference.svelte";
4
4
  let { node, edit } = $props();
@@ -1,5 +1,5 @@
1
- import FormatNode from '../../models/chapter/FormatNode';
2
- import type Ref from '../../models/book/Reference';
1
+ import FormatNode from '../../models/chapter/FormatNode.js';
2
+ import type Ref from '../../models/book/Reference.js';
3
3
  interface Props {
4
4
  node: FormatNode | Ref;
5
5
  edit: boolean;
@@ -1,15 +1,12 @@
1
1
  <script lang="ts">import Chapter from "./Chapter.svelte";
2
2
  import { getEdition } from "./Contexts";
3
- import Parser from "../../models/chapter/Parser";
3
+ import Parser from "../../models/chapter/Parser.js";
4
4
  let edition = getEdition();
5
5
  let title = $derived($edition ? [
6
- $edition.getTitle(),
7
- `${$edition.getEditionLabel()} Edition`,
8
- Parser.parseFormat(
9
- $edition,
10
- $edition.getAuthors().at(0) ?? ""
11
- ).toText() + ($edition.getAuthors().length > 1 ? " et al." : "")
12
- ].filter(Boolean).join(" - ") : void 0);
6
+ $edition.getTitle(),
7
+ `${$edition.getEditionLabel()} Edition`,
8
+ Parser.parseFormat($edition, $edition.getAuthors().at(0) ?? "").toText() + ($edition.getAuthors().length > 1 ? " et al." : "")
9
+ ].filter(Boolean).join(" - ") : undefined);
13
10
  </script>
14
11
 
15
12
  <svelte:head>
@@ -1,58 +1,52 @@
1
1
  <script lang="ts">import Parser from "../../models/chapter/Parser";
2
2
  import BookishEditor from "../editor/BookishEditor.svelte";
3
3
  import Switch from "../editor/Switch.svelte";
4
- import {
5
- getUser,
6
- getEdition,
7
- getLeasee,
8
- isEditionEditable,
9
- lease
10
- } from "./Contexts";
4
+ import { getUser, getEdition, getLeasee, isEditionEditable, lease } from "./Contexts";
11
5
  import Format from "../chapter/Format.svelte";
12
6
  import Note from "../editor/Note.svelte";
13
7
  import Instructions from "./Instructions.svelte";
14
8
  import Link from "../Link.svelte";
15
9
  import { PUBLIC_CONTEXT } from "$env/static/public";
16
10
  import Button from "../app/Button.svelte";
17
- import { publish } from "../../models/CRUD";
18
11
  import Feedback from "../app/Feedback.svelte";
19
12
  let auth = getUser();
20
13
  let edition = getEdition();
21
14
  let editable = isEditionEditable();
22
15
  let publishing = false;
23
- let feedback = $state(void 0);
24
- let error = $state(void 0);
25
- let url = $state(void 0);
16
+ let feedback = $state(undefined);
17
+ let error = $state(undefined);
18
+ let url = $state(undefined);
26
19
  async function requestPublish() {
27
- if ($edition) {
28
- publishing = true;
29
- error = void 0;
30
- feedback = "Binding the book, this could take a minute...";
31
- try {
32
- const result = await publish($edition);
33
- if (typeof result === "string") {
34
- error = result;
35
- feedback = void 0;
36
- } else {
37
- url = result.url;
38
- }
39
- } catch (err) {
40
- console.log(err);
41
- feedback = void 0;
42
- error = "Unable to bundle the book for download :(";
43
- } finally {
44
- publishing = false;
45
- }
46
- }
20
+ if ($edition) {
21
+ publishing = true;
22
+ error = undefined;
23
+ feedback = "Binding the book, this could take a minute...";
24
+ try {
25
+ const { publish } = await import("../../models/CRUD");
26
+ const result = await publish($edition);
27
+ if (typeof result === "string") {
28
+ error = result;
29
+ feedback = undefined;
30
+ } else {
31
+ url = result.url;
32
+ }
33
+ } catch (err) {
34
+ console.log(err);
35
+ feedback = undefined;
36
+ error = "Unable to bundle the book for download :(";
37
+ } finally {
38
+ publishing = false;
39
+ }
40
+ }
47
41
  }
48
- let publisher = $state(void 0);
42
+ let publisher = $state(undefined);
49
43
  async function updateUserClaims() {
50
- if ($auth === void 0 || $auth.user === null) return;
51
- const token = await $auth.user.getIdTokenResult();
52
- publisher = "publisher" in token.claims && token.claims.publisher === true;
44
+ if ($auth === undefined || $auth.user === null) return;
45
+ const token = await $auth.user.getIdTokenResult();
46
+ publisher = "publisher" in token.claims && token.claims.publisher === true;
53
47
  }
54
48
  $effect(() => {
55
- if ($auth && $auth.user) updateUserClaims();
49
+ if ($auth && $auth.user) updateUserClaims();
56
50
  });
57
51
  </script>
58
52
 
@@ -70,7 +64,7 @@ $effect(() => {
70
64
  save={(newSummary) =>
71
65
  $edition
72
66
  ? edition.set(
73
- $edition.withSummary(newSummary.toBookdown())
67
+ $edition.withSummary(newSummary.toBookdown()),
74
68
  )
75
69
  : undefined}
76
70
  chapter={false}
@@ -87,7 +81,7 @@ $effect(() => {
87
81
  edit={(published) =>
88
82
  $edition
89
83
  ? edition.set(
90
- $edition.asPublished(published === 'published')
84
+ $edition.asPublished(published === 'published'),
91
85
  )
92
86
  : undefined}
93
87
  />
@@ -108,7 +102,7 @@ $effect(() => {
108
102
  <div>
109
103
  <Note
110
104
  >{#if $edition.published}Last published {new Date(
111
- $edition.published
105
+ $edition.published,
112
106
  ).toLocaleDateString('en-us')}{/if}</Note
113
107
  >
114
108
  </div>
@@ -1,4 +1,4 @@
1
- <script lang="ts">import Reference from "../../models/book/Reference";
1
+ <script lang="ts">import Reference from "../../models/book/Reference.js";
2
2
  import Button from "../app/Button.svelte";
3
3
  import Table from "../app/Table.svelte";
4
4
  import ConfirmButton from "../editor/ConfirmButton.svelte";
@@ -11,20 +11,18 @@ let editable = isEditionEditable();
11
11
  let edition = getEdition();
12
12
  let editing = $state(false);
13
13
  function startEditing() {
14
- editing = true;
14
+ editing = true;
15
15
  }
16
16
  function stopEditing() {
17
- editing = false;
17
+ editing = false;
18
18
  }
19
19
  function move(field, direction) {
20
- let fields = Array.from(
21
- document.querySelectorAll('input[type="text"]')
22
- );
23
- let index = fields.indexOf(field);
24
- if (index >= 0) {
25
- const newInput = direction < 0 && index > 0 ? fields[index - 1] : direction > 0 && index < fields.length - 1 ? fields[index + 1] : void 0;
26
- if (newInput) newInput.focus();
27
- }
20
+ let fields = Array.from(document.querySelectorAll("input[type=\"text\"]"));
21
+ let index = fields.indexOf(field);
22
+ if (index >= 0) {
23
+ const newInput = direction < 0 && index > 0 ? fields[index - 1] : direction > 0 && index < fields.length - 1 ? fields[index + 1] : undefined;
24
+ if (newInput) newInput.focus();
25
+ }
28
26
  }
29
27
  </script>
30
28
 
@@ -1,4 +1,4 @@
1
- import Reference from '../../models/book/Reference';
1
+ import Reference from '../../models/book/Reference.js';
2
2
  interface Props {
3
3
  reference: Reference;
4
4
  edit?: boolean;
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">import Header from "./Header.svelte";
2
2
  import Outline from "./Outline.svelte";
3
3
  import Page from "./Page.svelte";
4
- import ChapterIDs from "../../models/book/ChapterID";
4
+ import ChapterIDs from "../../models/book/ChapterID.js";
5
5
  import BulkReferenceEditor from "./BulkReferenceEditor.svelte";
6
6
  import PossibleReference from "./PossibleReference.svelte";
7
7
  import { getUser, getEdition, isEditionEditable } from "./Contexts";