bookish-press 0.4.1 → 0.4.21
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.
- package/README.md +3 -1
- package/components/Auth.svelte +19 -14
- package/components/Auth.svelte.d.ts +4 -4
- package/components/Authentication.d.ts +2 -2
- package/components/BookPreview.svelte +77 -59
- package/components/BookPreview.svelte.d.ts +5 -5
- package/components/External.svelte +1 -1
- package/components/External.svelte.d.ts +3 -3
- package/components/Link.svelte +49 -3
- package/components/Link.svelte.d.ts +3 -4
- package/components/app/BookList.svelte +19 -0
- package/components/app/BookList.svelte.d.ts +18 -0
- package/components/app/Button.svelte +49 -0
- package/components/app/Button.svelte.d.ts +22 -0
- package/components/app/Feedback.svelte +45 -0
- package/components/app/Feedback.svelte.d.ts +18 -0
- package/components/app/Head.svelte +12 -0
- package/components/app/Head.svelte.d.ts +27 -0
- package/components/app/Large.svelte +8 -0
- package/components/app/Large.svelte.d.ts +27 -0
- package/components/app/Lead.svelte +12 -0
- package/components/app/Lead.svelte.d.ts +27 -0
- package/components/app/Link.svelte +24 -0
- package/components/app/Link.svelte.d.ts +20 -0
- package/components/app/Options.svelte +24 -0
- package/components/app/Options.svelte.d.ts +19 -0
- package/components/app/Paragraph.svelte +19 -0
- package/components/app/Paragraph.svelte.d.ts +18 -0
- package/components/app/Table.svelte +32 -0
- package/components/app/Table.svelte.d.ts +27 -0
- package/components/app/TextInput.svelte +37 -0
- package/components/app/TextInput.svelte.d.ts +22 -0
- package/components/app/Writing.svelte +13 -0
- package/components/app/Writing.svelte.d.ts +27 -0
- package/components/chapter/Atom.svelte +20 -6
- package/components/chapter/Atom.svelte.d.ts +3 -3
- package/components/chapter/Block.svelte +23 -20
- package/components/chapter/Block.svelte.d.ts +4 -4
- package/components/chapter/Callout.svelte +38 -7
- package/components/chapter/Callout.svelte.d.ts +4 -4
- package/components/chapter/CaptionedCode.svelte +66 -23
- package/components/chapter/CaptionedCode.svelte.d.ts +4 -4
- package/components/chapter/ChapterBody.svelte +61 -9
- package/components/chapter/ChapterBody.svelte.d.ts +4 -4
- package/components/chapter/Citations.svelte +86 -20
- package/components/chapter/Citations.svelte.d.ts +4 -4
- package/components/chapter/Code.svelte +152 -21
- package/components/chapter/Code.svelte.d.ts +3 -3
- package/components/chapter/Comment.svelte +38 -16
- package/components/chapter/Comment.svelte.d.ts +3 -3
- package/components/chapter/Definition.svelte +52 -18
- package/components/chapter/Definition.svelte.d.ts +5 -8
- package/components/chapter/Embed.svelte +154 -66
- package/components/chapter/Embed.svelte.d.ts +5 -4
- package/components/chapter/ErrorMessage.svelte +7 -2
- package/components/chapter/ErrorMessage.svelte.d.ts +4 -4
- package/components/chapter/ExtendedPrism.d.ts +2 -0
- package/components/chapter/ExtendedPrism.js +69 -0
- package/components/chapter/Figure.svelte +90 -0
- package/components/chapter/Figure.svelte.d.ts +24 -0
- package/components/chapter/Footnote.svelte +75 -12
- package/components/chapter/Footnote.svelte.d.ts +4 -4
- package/components/chapter/Format.svelte +60 -37
- package/components/chapter/Format.svelte.d.ts +4 -4
- package/components/chapter/InlineCode.svelte +15 -5
- package/components/chapter/InlineCode.svelte.d.ts +4 -4
- package/components/chapter/Label.svelte +37 -8
- package/components/chapter/Label.svelte.d.ts +4 -4
- package/components/chapter/Link.svelte +23 -18
- package/components/chapter/Link.svelte.d.ts +4 -4
- package/components/chapter/List.svelte +75 -8
- package/components/chapter/List.svelte.d.ts +4 -4
- package/components/chapter/Marginal.svelte +169 -27
- package/components/chapter/Marginal.svelte.d.ts +6 -3
- package/components/chapter/Paragraph.svelte +74 -6
- package/components/chapter/Paragraph.svelte.d.ts +4 -4
- package/components/chapter/Positioned.svelte +33 -0
- package/components/chapter/Positioned.svelte.d.ts +19 -0
- package/components/chapter/Problem.svelte +15 -0
- package/components/chapter/Problem.svelte.d.ts +27 -0
- package/components/chapter/Python.svelte +68 -21
- package/components/chapter/Python.svelte.d.ts +4 -4
- package/components/chapter/Quote.svelte +64 -11
- package/components/chapter/Quote.svelte.d.ts +4 -4
- package/components/chapter/Rule.svelte +12 -1
- package/components/chapter/Rule.svelte.d.ts +4 -4
- package/components/chapter/Table.svelte +36 -25
- package/components/chapter/Table.svelte.d.ts +4 -4
- package/components/chapter/Text.svelte +61 -36
- package/components/chapter/Text.svelte.d.ts +5 -4
- package/components/editor/BookishEditor.svelte +343 -237
- package/components/editor/BookishEditor.svelte.d.ts +5 -5
- package/components/editor/CalloutEditor.svelte +5 -5
- package/components/editor/CalloutEditor.svelte.d.ts +4 -4
- package/components/editor/CaptionedCodeEditor.svelte +16 -12
- package/components/editor/CaptionedCodeEditor.svelte.d.ts +4 -4
- package/components/editor/CaretContext.d.ts +48 -16
- package/components/editor/CaretState.d.ts +16 -44
- package/components/editor/CaretUtilities.d.ts +2 -2
- package/components/editor/CaretView.svelte +80 -0
- package/components/editor/CaretView.svelte.d.ts +24 -0
- package/components/editor/CitationsEditor.svelte +36 -25
- package/components/editor/CitationsEditor.svelte.d.ts +4 -4
- package/components/editor/Clipboard.d.ts +2 -2
- package/components/editor/Command.d.ts +13 -12
- package/components/editor/Commands.d.ts +1 -1
- package/components/editor/Commands.js +1114 -571
- package/components/editor/ConfirmButton.svelte +18 -12
- package/components/editor/ConfirmButton.svelte.d.ts +5 -4
- package/components/editor/DefinitionEditor.svelte +29 -21
- package/components/editor/DefinitionEditor.svelte.d.ts +4 -4
- package/components/editor/EmbedEditor.svelte +93 -43
- package/components/editor/EmbedEditor.svelte.d.ts +3 -3
- package/components/editor/Icon.svelte +17 -0
- package/components/editor/Icon.svelte.d.ts +16 -0
- package/components/editor/ImageChooser.svelte +53 -34
- package/components/editor/ImageChooser.svelte.d.ts +3 -3
- package/components/editor/InlineCodeEditor.svelte +7 -4
- package/components/editor/InlineCodeEditor.svelte.d.ts +4 -4
- package/components/editor/LabelEditor.svelte +20 -11
- package/components/editor/LabelEditor.svelte.d.ts +4 -4
- package/components/editor/LanguageEditor.svelte +10 -7
- package/components/editor/LanguageEditor.svelte.d.ts +3 -3
- package/components/editor/LinkEditor.svelte +64 -39
- package/components/editor/LinkEditor.svelte.d.ts +4 -4
- package/components/editor/Note.svelte +3 -3
- package/components/editor/Note.svelte.d.ts +6 -2
- package/components/editor/PositionEditor.svelte +9 -6
- package/components/editor/PositionEditor.svelte.d.ts +4 -4
- package/components/editor/QuoteEditor.svelte +7 -2
- package/components/editor/QuoteEditor.svelte.d.ts +4 -4
- package/components/editor/Switch.svelte +55 -28
- package/components/editor/Switch.svelte.d.ts +4 -4
- package/components/editor/TableEditor.svelte +10 -0
- package/components/editor/TableEditor.svelte.d.ts +17 -0
- package/components/editor/TextEditor.svelte +83 -45
- package/components/editor/TextEditor.svelte.d.ts +5 -4
- package/components/editor/Toggle.svelte +11 -8
- package/components/editor/Toggle.svelte.d.ts +4 -4
- package/components/editor/Toolbar.svelte +192 -144
- package/components/editor/Toolbar.svelte.d.ts +5 -8
- package/components/editor/ToolbarGroup.svelte +18 -23
- package/components/editor/ToolbarGroup.svelte.d.ts +3 -4
- package/components/editor/ToolbarSpacer.svelte +8 -1
- package/components/editor/ToolbarSpacer.svelte.d.ts +6 -2
- package/components/editor/URLEditor.svelte +6 -8
- package/components/editor/URLEditor.svelte.d.ts +3 -3
- package/components/editor/UndoState.d.ts +3 -3
- package/components/editor/icons/annotate.svg +1 -0
- package/components/editor/icons/block.svg +1 -0
- package/components/editor/icons/bold.svg +1 -0
- package/components/editor/icons/bullets.svg +1 -0
- package/components/editor/icons/callout.svg +1 -0
- package/components/editor/icons/citation.svg +8 -0
- package/components/editor/icons/clear.svg +1 -0
- package/components/editor/icons/clipboard.svg +1 -0
- package/components/editor/icons/code.svg +1 -0
- package/components/editor/icons/columnafter.svg +1 -0
- package/components/editor/icons/columnbefore.svg +1 -0
- package/components/editor/icons/comment.svg +1 -0
- package/components/editor/icons/copy.svg +1 -0
- package/components/editor/icons/cut.svg +1 -0
- package/components/editor/icons/define.svg +7 -0
- package/components/editor/icons/deletecolumn.svg +1 -0
- package/components/editor/icons/deleterow.svg +1 -0
- package/components/editor/icons/footnote.svg +8 -0
- package/components/editor/icons/header1.svg +7 -0
- package/components/editor/icons/header2.svg +7 -0
- package/components/editor/icons/header3.svg +7 -0
- package/components/editor/icons/home.svg +1 -0
- package/components/editor/icons/indent.svg +1 -0
- package/components/editor/icons/italic.svg +1 -0
- package/components/editor/icons/label.svg +1 -0
- package/components/editor/icons/left.svg +1 -0
- package/components/editor/icons/level.svg +1 -0
- package/components/editor/icons/link.svg +1 -0
- package/components/editor/icons/list.svg +1 -0
- package/components/editor/icons/media.svg +1 -0
- package/components/editor/icons/middle.svg +1 -0
- package/components/editor/icons/numbers.svg +10 -0
- package/components/editor/icons/paragraph.svg +1 -0
- package/components/editor/icons/paste.svg +10 -0
- package/components/editor/icons/quote.svg +1 -0
- package/components/editor/icons/redo.svg +1 -0
- package/components/editor/icons/right.svg +1 -0
- package/components/editor/icons/rowabove.svg +1 -0
- package/components/editor/icons/rowbelow.svg +1 -0
- package/components/editor/icons/rule.svg +1 -0
- package/components/editor/icons/sub.svg +1 -0
- package/components/editor/icons/super.svg +1 -0
- package/components/editor/icons/table.svg +1 -0
- package/components/editor/icons/text.svg +1 -0
- package/components/editor/icons/time.svg +1 -0
- package/components/editor/icons/undo.svg +1 -0
- package/components/editor/icons/unindent.svg +1 -0
- package/components/editor/icons/unlink.svg +1 -0
- package/components/page/Acknowledgements.svelte +31 -22
- package/components/page/Acknowledgements.svelte.d.ts +4 -4
- package/components/page/Authors.svelte +34 -14
- package/components/page/Authors.svelte.d.ts +6 -6
- package/components/page/BulkReferenceEditor.svelte +53 -22
- package/components/page/BulkReferenceEditor.svelte.d.ts +4 -4
- package/components/page/Chapter.svelte +196 -141
- package/components/page/Chapter.svelte.d.ts +3 -3
- package/components/page/ChapterContext.d.ts +4 -4
- package/components/page/ChapterNumber.svelte +9 -0
- package/components/page/ChapterNumber.svelte.d.ts +27 -0
- package/components/page/ChapterTitle.svelte +16 -0
- package/components/page/ChapterTitle.svelte.d.ts +18 -0
- package/components/page/Contexts.d.ts +31 -20
- package/components/page/Contexts.js +47 -17
- package/components/page/DefinitionView.svelte +115 -86
- package/components/page/DefinitionView.svelte.d.ts +3 -3
- package/components/page/Description.svelte +27 -18
- package/components/page/Description.svelte.d.ts +4 -4
- package/components/page/Edition.svelte +127 -75
- package/components/page/Edition.svelte.d.ts +4 -4
- package/components/page/Editions.svelte +158 -0
- package/components/page/Editions.svelte.d.ts +14 -0
- package/components/page/Glossary.svelte +57 -48
- package/components/page/Glossary.svelte.d.ts +4 -4
- package/components/page/Header.svelte +129 -44
- package/components/page/Header.svelte.d.ts +6 -6
- package/components/page/Index.svelte +114 -80
- package/components/page/Index.svelte.d.ts +4 -4
- package/components/page/Instructions.svelte +18 -16
- package/components/page/Instructions.svelte.d.ts +4 -4
- package/components/page/License.svelte +29 -21
- package/components/page/License.svelte.d.ts +4 -4
- package/components/page/Loading.svelte +102 -12
- package/components/page/Loading.svelte.d.ts +6 -2
- package/components/page/Media.svelte +77 -51
- package/components/page/Media.svelte.d.ts +4 -4
- package/components/page/MediaPreview.svelte +26 -8
- package/components/page/MediaPreview.svelte.d.ts +3 -3
- package/components/page/Muted.svelte +10 -0
- package/components/page/Muted.svelte.d.ts +27 -0
- package/components/page/Outline.svelte +279 -59
- package/components/page/Outline.svelte.d.ts +3 -3
- package/components/page/Page.svelte +40 -9
- package/components/page/Page.svelte.d.ts +3 -3
- package/components/page/PageHeader.svelte +14 -0
- package/components/page/PageHeader.svelte.d.ts +18 -0
- package/components/page/PageParagraph.svelte +18 -0
- package/components/page/PageParagraph.svelte.d.ts +27 -0
- package/components/page/PossibleChapter.svelte +7 -7
- package/components/page/PossibleChapter.svelte.d.ts +4 -4
- package/components/page/PossibleReference.svelte +6 -11
- package/components/page/PossibleReference.svelte.d.ts +6 -7
- package/components/page/Print.svelte +27 -3
- package/components/page/Print.svelte.d.ts +4 -4
- package/components/page/Reference.svelte +256 -113
- package/components/page/Reference.svelte.d.ts +5 -5
- package/components/page/References.svelte +39 -47
- package/components/page/References.svelte.d.ts +4 -4
- package/components/page/Rows.svelte +54 -0
- package/components/page/Rows.svelte.d.ts +27 -0
- package/components/page/Search.svelte +86 -63
- package/components/page/Search.svelte.d.ts +4 -4
- package/components/page/Status.svelte +43 -35
- package/components/page/Status.svelte.d.ts +4 -9
- package/components/page/SubdomainEditor.svelte +40 -27
- package/components/page/SubdomainEditor.svelte.d.ts +4 -4
- package/components/page/TableOfContents.svelte +225 -190
- package/components/page/TableOfContents.svelte.d.ts +4 -4
- package/components/page/TableOfContentsImage.svelte +8 -8
- package/components/page/TableOfContentsImage.svelte.d.ts +3 -3
- package/components/page/TableOfContentsRow.svelte +96 -33
- package/components/page/TableOfContentsRow.svelte.d.ts +4 -4
- package/components/page/ThemeEditor.svelte +174 -39
- package/components/page/ThemeEditor.svelte.d.ts +4 -4
- package/components/page/ThemeEditorPreview.svelte +35 -23
- package/components/page/ThemeEditorPreview.svelte.d.ts +5 -5
- package/components/page/ThemeSetEditor.svelte +15 -13
- package/components/page/ThemeSetEditor.svelte.d.ts +4 -4
- package/components/page/ThemeVariableEditor.svelte +24 -15
- package/components/page/ThemeVariableEditor.svelte.d.ts +3 -3
- package/components/page/Title.svelte +12 -0
- package/components/page/Title.svelte.d.ts +27 -0
- package/components/page/Unknown.svelte +25 -21
- package/components/page/Unknown.svelte.d.ts +4 -4
- package/components/page/margins.js +50 -33
- package/index.d.ts +14 -0
- package/index.js +14 -0
- package/models/CRUD.d.ts +17 -0
- package/models/CRUD.js +207 -0
- package/models/Firebase.d.ts +1 -0
- package/models/Firebase.js +21 -15
- package/models/book/Book.d.ts +26 -30
- package/models/book/Book.js +120 -113
- package/models/book/BookMedia.d.ts +3 -3
- package/models/book/BookMedia.js +22 -16
- package/models/book/BookSaveStatus.d.ts +7 -0
- package/models/book/BookSaveStatus.js +8 -0
- package/models/book/Chapter.d.ts +46 -39
- package/models/book/Chapter.js +180 -198
- package/models/book/ChapterID.js +7 -7
- package/models/book/Definition.d.ts +1 -1
- package/models/book/Edition.d.ts +62 -60
- package/models/book/Edition.js +385 -303
- package/models/book/Reference.d.ts +24 -0
- package/models/book/Reference.js +78 -0
- package/models/book/Schema.d.ts +169 -0
- package/models/book/Schema.js +114 -0
- package/models/book/Theme.d.ts +44 -37
- package/models/book/Theme.js +452 -52
- package/models/book/ThemeColors.d.ts +1 -1
- package/models/book/Words.d.ts +2 -0
- package/models/book/Words.js +110 -0
- package/models/chapter/AtomNode.d.ts +4 -4
- package/models/chapter/AtomNode.js +20 -13
- package/models/chapter/BlockNode.d.ts +9 -10
- package/models/chapter/BlockNode.js +32 -13
- package/models/chapter/BlocksNode.d.ts +10 -10
- package/models/chapter/BlocksNode.js +315 -120
- package/models/chapter/BlocksNode.test.js +494 -228
- package/models/chapter/Bookkeeping.d.ts +1 -1
- package/models/chapter/CalloutNode.d.ts +3 -3
- package/models/chapter/CalloutNode.js +34 -12
- package/models/chapter/Caret.d.ts +9 -7
- package/models/chapter/Caret.js +11 -6
- package/models/chapter/ChapterNode.d.ts +11 -11
- package/models/chapter/ChapterNode.js +70 -33
- package/models/chapter/CitationsNode.d.ts +3 -3
- package/models/chapter/CitationsNode.js +31 -12
- package/models/chapter/CodeNode.d.ts +11 -6
- package/models/chapter/CodeNode.js +143 -34
- package/models/chapter/CommentNode.d.ts +5 -5
- package/models/chapter/CommentNode.js +29 -13
- package/models/chapter/DefinitionNode.d.ts +2 -2
- package/models/chapter/DefinitionNode.js +15 -7
- package/models/chapter/Edit.d.ts +3 -3
- package/models/chapter/EmbedNode.d.ts +9 -5
- package/models/chapter/EmbedNode.js +108 -35
- package/models/chapter/ErrorNode.d.ts +2 -2
- package/models/chapter/ErrorNode.js +34 -12
- package/models/chapter/FootnoteNode.d.ts +5 -5
- package/models/chapter/FootnoteNode.js +34 -16
- package/models/chapter/FormatNode.d.ts +10 -10
- package/models/chapter/FormatNode.js +237 -106
- package/models/chapter/FormatNode.test.js +87 -45
- package/models/chapter/InlineCodeNode.d.ts +2 -2
- package/models/chapter/InlineCodeNode.js +22 -9
- package/models/chapter/LabelNode.d.ts +4 -4
- package/models/chapter/LabelNode.js +31 -13
- package/models/chapter/LinkNode.d.ts +2 -2
- package/models/chapter/LinkNode.js +21 -9
- package/models/chapter/ListNode.d.ts +8 -8
- package/models/chapter/ListNode.js +99 -38
- package/models/chapter/ListNode.test.js +29 -24
- package/models/chapter/MetadataNode.d.ts +3 -3
- package/models/chapter/MetadataNode.js +13 -5
- package/models/chapter/Node.d.ts +5 -3
- package/models/chapter/Node.js +76 -29
- package/models/chapter/Node.test.js +20 -18
- package/models/chapter/ParagraphNode.d.ts +6 -6
- package/models/chapter/ParagraphNode.js +84 -29
- package/models/chapter/ParagraphNode.test.js +22 -13
- package/models/chapter/Parser.d.ts +25 -25
- package/models/chapter/Parser.js +201 -189
- package/models/chapter/Parser.test.js +16 -16
- package/models/chapter/Position.d.ts +1 -1
- package/models/chapter/QuoteNode.d.ts +6 -6
- package/models/chapter/QuoteNode.js +61 -23
- package/models/chapter/RootNode.d.ts +4 -4
- package/models/chapter/RuleNode.d.ts +2 -2
- package/models/chapter/RuleNode.js +31 -11
- package/models/chapter/TableNode.d.ts +8 -6
- package/models/chapter/TableNode.js +89 -34
- package/models/chapter/TableNode.test.js +22 -24
- package/models/chapter/TextNode.d.ts +6 -6
- package/models/chapter/TextNode.js +72 -32
- package/models/chapter/TextNode.test.js +4 -4
- package/models/loadEdition.d.ts +1 -1
- package/models/loadEdition.js +10 -6
- package/package.json +104 -25
- package/util/getSubdomain.js +8 -6
- package/util/isMobile.js +1 -1
- package/util/mineReference.d.ts +3 -2
- package/util/mineReference.js +67 -29
- package/util/scrollToEyeLevel.js +6 -1
- package/components/chapter/renderPosition.d.ts +0 -3
- package/components/chapter/renderPosition.js +0 -4
- package/components/editor/ToolbarIcon.svelte +0 -22
- package/components/editor/ToolbarIcon.svelte.d.ts +0 -16
- package/components/page/Alert.svelte +0 -11
- package/components/page/Alert.svelte.d.ts +0 -23
- package/components/page/Revisions.svelte +0 -124
- package/components/page/Revisions.svelte.d.ts +0 -14
- package/models/BookLoader.d.ts +0 -2
- package/models/BookLoader.js +0 -67
- package/models/Firestore.d.ts +0 -22
- package/models/Firestore.js +0 -194
- package/models/chapter/ReferenceNode.d.ts +0 -29
- package/models/chapter/ReferenceNode.js +0 -48
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} TitleProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} TitleEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} TitleSlots */
|
|
4
|
+
export default class Title extends SvelteComponentTyped<{
|
|
5
|
+
[x: string]: never;
|
|
6
|
+
}, {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
}, {
|
|
9
|
+
default: {};
|
|
10
|
+
}> {
|
|
11
|
+
}
|
|
12
|
+
export type TitleProps = typeof __propDef.props;
|
|
13
|
+
export type TitleEvents = typeof __propDef.events;
|
|
14
|
+
export type TitleSlots = typeof __propDef.slots;
|
|
15
|
+
import { SvelteComponentTyped } from "svelte";
|
|
16
|
+
declare const __propDef: {
|
|
17
|
+
props: {
|
|
18
|
+
[x: string]: never;
|
|
19
|
+
};
|
|
20
|
+
events: {
|
|
21
|
+
[evt: string]: CustomEvent<any>;
|
|
22
|
+
};
|
|
23
|
+
slots: {
|
|
24
|
+
default: {};
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export {};
|
|
@@ -1,29 +1,33 @@
|
|
|
1
|
-
<script>import Header from
|
|
1
|
+
<script>import Header from './Header.svelte';
|
|
2
2
|
import Outline from './Outline.svelte';
|
|
3
3
|
import Page from './Page.svelte';
|
|
4
4
|
import Instructions from './Instructions.svelte';
|
|
5
5
|
import ChapterIDs from '../../models/book/ChapterID';
|
|
6
|
-
import { getEdition } from
|
|
6
|
+
import { getEdition } from './Contexts';
|
|
7
7
|
let edition = getEdition();
|
|
8
8
|
</script>
|
|
9
|
-
<Page title={`${$edition.getTitle()} - Unknown Page`}>
|
|
10
|
-
<Header
|
|
11
|
-
label="Unknown page title"
|
|
12
|
-
getImage={() => $edition.getImage(ChapterIDs.UnknownID)}
|
|
13
|
-
setImage={embed => $edition.setImage(ChapterIDs.UnknownID, embed)}
|
|
14
|
-
header="Oops."
|
|
15
|
-
>
|
|
16
|
-
<Outline
|
|
17
|
-
slot="outline"
|
|
18
|
-
previous={null}
|
|
19
|
-
next={null}
|
|
20
|
-
/>
|
|
21
|
-
</Header>
|
|
22
9
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
10
|
+
{#if $edition}
|
|
11
|
+
<Page title={`${$edition.getTitle()} - Unknown Page`}>
|
|
12
|
+
<Header
|
|
13
|
+
label="Unknown page title"
|
|
14
|
+
getImage={() => $edition?.getImage(ChapterIDs.UnknownID) ?? null}
|
|
15
|
+
setImage={(embed) =>
|
|
16
|
+
$edition
|
|
17
|
+
? edition.set(
|
|
18
|
+
$edition.withImage(ChapterIDs.UnknownID, embed)
|
|
19
|
+
)
|
|
20
|
+
: undefined}
|
|
21
|
+
header="Oops."
|
|
22
|
+
>
|
|
23
|
+
<Outline slot="outline" previous={null} next={null} />
|
|
24
|
+
</Header>
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
<Instructions>
|
|
27
|
+
This page will be shown if the reader somehow ends up on a page that
|
|
28
|
+
doesn't exist. You can customize the image shown.
|
|
29
|
+
</Instructions>
|
|
30
|
+
|
|
31
|
+
<slot />
|
|
32
|
+
</Page>
|
|
33
|
+
{/if}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
2
|
declare const __propDef: {
|
|
3
|
-
props:
|
|
3
|
+
props: Record<string, never>;
|
|
4
4
|
events: {
|
|
5
5
|
[evt: string]: CustomEvent<any>;
|
|
6
6
|
};
|
|
@@ -8,9 +8,9 @@ declare const __propDef: {
|
|
|
8
8
|
default: {};
|
|
9
9
|
};
|
|
10
10
|
};
|
|
11
|
-
export
|
|
12
|
-
export
|
|
13
|
-
export
|
|
11
|
+
export type UnknownProps = typeof __propDef.props;
|
|
12
|
+
export type UnknownEvents = typeof __propDef.events;
|
|
13
|
+
export type UnknownSlots = typeof __propDef.slots;
|
|
14
14
|
export default class Unknown extends SvelteComponentTyped<UnknownProps, UnknownEvents, UnknownSlots> {
|
|
15
15
|
}
|
|
16
16
|
export {};
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
// This operates on the DOM directly, as scroll position isn't easily managed in React.
|
|
3
3
|
export function hideOutlineIfObscured() {
|
|
4
4
|
// Get the outline's bounds.
|
|
5
|
-
let outline = document.getElementsByClassName(
|
|
5
|
+
let outline = document.getElementsByClassName('outline')[0];
|
|
6
6
|
// If there's no outline, don't bother.
|
|
7
7
|
if (!outline)
|
|
8
8
|
return;
|
|
9
9
|
// Set a threshold for hiding
|
|
10
10
|
let threshold = 100;
|
|
11
11
|
// If the outline isn't affixed to the footer
|
|
12
|
-
if (window.getComputedStyle(outline).getPropertyValue(
|
|
12
|
+
if (window.getComputedStyle(outline).getPropertyValue('left') !== '0px') {
|
|
13
13
|
let outlineRect = outline.getBoundingClientRect();
|
|
14
14
|
let overlapRect = undefined;
|
|
15
15
|
// Find the bottom-most left inset marginal within threshold of the outline.
|
|
16
|
-
Array.from(document.getElementsByClassName(
|
|
16
|
+
Array.from(document.getElementsByClassName('inset-left')).forEach((el) => {
|
|
17
17
|
let insetRect = el.getBoundingClientRect();
|
|
18
18
|
if (!(outlineRect.bottom < insetRect.top - threshold ||
|
|
19
19
|
outlineRect.top > insetRect.bottom + threshold))
|
|
@@ -22,24 +22,28 @@ export function hideOutlineIfObscured() {
|
|
|
22
22
|
// If it overlaps, reduce opacity by the proportion of the vertical distance between two rectangles and the height of the marginal.
|
|
23
23
|
if (overlapRect) {
|
|
24
24
|
let overlap = overlapRect;
|
|
25
|
-
let distance = outlineRect.bottom < overlap.top
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
let distance = outlineRect.bottom < overlap.top
|
|
26
|
+
? threshold
|
|
27
|
+
: outlineRect.bottom < overlap.top + threshold
|
|
28
|
+
? threshold - (outlineRect.bottom - overlap.top)
|
|
29
|
+
: outlineRect.top > overlap.bottom - threshold
|
|
30
|
+
? threshold - (overlap.bottom - outlineRect.top)
|
|
31
|
+
: outlineRect.top > overlap.bottom
|
|
32
|
+
? threshold
|
|
33
|
+
: 0;
|
|
30
34
|
let proportion = distance / threshold;
|
|
31
|
-
outline.style.opacity =
|
|
35
|
+
outline.style.opacity = '' + proportion * proportion;
|
|
32
36
|
}
|
|
33
37
|
// Otherwise, remove the dimming.
|
|
34
38
|
else
|
|
35
|
-
outline.style.removeProperty(
|
|
39
|
+
outline.style.removeProperty('opacity');
|
|
36
40
|
}
|
|
37
41
|
// If it is, it's always visible.
|
|
38
42
|
else
|
|
39
|
-
outline.style.removeProperty(
|
|
43
|
+
outline.style.removeProperty('opacity');
|
|
40
44
|
}
|
|
41
45
|
// After each render of the chapter, we need to adjust the layout of marginals, which by default are floating from
|
|
42
|
-
// their little spans within the body of the text.
|
|
46
|
+
// their little spans within the body of the text.
|
|
43
47
|
//
|
|
44
48
|
// We have to do two things:
|
|
45
49
|
//
|
|
@@ -50,53 +54,60 @@ export function hideOutlineIfObscured() {
|
|
|
50
54
|
// fixed in a fixed position.
|
|
51
55
|
export function layoutMarginals() {
|
|
52
56
|
// Get the chapter DOM node, so we can calculate margins.
|
|
53
|
-
let chapter = document.getElementsByClassName(
|
|
57
|
+
let chapter = document.getElementsByClassName('bookish-chapter-body')[0];
|
|
54
58
|
// If there's no chapter rendered yet, stop.
|
|
55
59
|
if (chapter === undefined)
|
|
56
60
|
return;
|
|
57
|
-
let book = document.getElementsByClassName(
|
|
61
|
+
let book = document.getElementsByClassName('bookish')[0];
|
|
58
62
|
// This is the grid line we'll aline all marginals too horizontally.
|
|
59
63
|
let margin = chapter.getBoundingClientRect().width;
|
|
60
64
|
// This will track the current leading bottom edge for laying out marginals.
|
|
61
65
|
let currentBottom = null;
|
|
62
66
|
// Are there any marginal right inset images that might overlap?
|
|
63
|
-
let rightInsets = document.getElementsByClassName(
|
|
64
|
-
const marginals = document.getElementsByClassName(
|
|
67
|
+
let rightInsets = document.getElementsByClassName('inset-right');
|
|
68
|
+
const marginals = document.getElementsByClassName('bookish-marginal');
|
|
65
69
|
// Layout all of the marginals vertically to prevent overlaps.
|
|
66
70
|
Array.from(marginals).forEach((element) => {
|
|
67
71
|
const el = element;
|
|
68
72
|
if (el === null)
|
|
69
73
|
return;
|
|
70
|
-
if (window.getComputedStyle(el).getPropertyValue(
|
|
74
|
+
if (window.getComputedStyle(el).getPropertyValue('position') !== 'fixed') {
|
|
71
75
|
if (el.parentElement) {
|
|
72
|
-
let containingMarginal = el.parentElement.closest(
|
|
76
|
+
let containingMarginal = el.parentElement.closest('.bookish-marginal');
|
|
73
77
|
// Get the bounds of this marginal so we know it's size.
|
|
74
78
|
let elementBounds = el.getBoundingClientRect();
|
|
75
79
|
// Get the bounds of this marginal's parent so we know it's vertical position.
|
|
76
80
|
let parentBounds = el.parentElement.getBoundingClientRect();
|
|
77
|
-
let parentTop = parentBounds.top +
|
|
81
|
+
let parentTop = parentBounds.top +
|
|
82
|
+
window.scrollY -
|
|
83
|
+
(book.getBoundingClientRect().top + window.scrollY);
|
|
78
84
|
// If it's inside a marginal, position it below the marginal.
|
|
79
85
|
if (containingMarginal !== null && currentBottom) {
|
|
80
|
-
el.style.left =
|
|
81
|
-
el.style.top =
|
|
86
|
+
el.style.left = '0';
|
|
87
|
+
el.style.top =
|
|
88
|
+
'' +
|
|
89
|
+
(currentBottom -
|
|
90
|
+
(containingMarginal.getBoundingClientRect().top +
|
|
91
|
+
window.scrollY)) +
|
|
92
|
+
'px';
|
|
82
93
|
currentBottom = currentBottom + elementBounds.height;
|
|
83
94
|
}
|
|
84
95
|
else {
|
|
85
96
|
// If we don't have a bottom yet, or the current above is above the parent's top,
|
|
86
97
|
// then set the current bottom to the bottom of the parent.
|
|
87
98
|
if (currentBottom === null || currentBottom < parentTop) {
|
|
88
|
-
el.style.top = parentTop +
|
|
99
|
+
el.style.top = parentTop + 'px';
|
|
89
100
|
currentBottom = parentTop + elementBounds.height;
|
|
90
101
|
}
|
|
91
102
|
// Otherwise, put the marginal below the last marginal's bottom.
|
|
92
103
|
else {
|
|
93
|
-
el.style.top = currentBottom +
|
|
104
|
+
el.style.top = currentBottom + 'px';
|
|
94
105
|
currentBottom = currentBottom + elementBounds.height;
|
|
95
106
|
}
|
|
96
107
|
// If there are any right insets, do any intersect with this marginal?
|
|
97
108
|
// If so, move the marginal below them.
|
|
98
109
|
if (rightInsets.length > 0) {
|
|
99
|
-
Array.from(rightInsets).forEach(inset => {
|
|
110
|
+
Array.from(rightInsets).forEach((inset) => {
|
|
100
111
|
// Compute the global positions of the marginal and the potential inset.
|
|
101
112
|
let insetBounds = inset.getBoundingClientRect();
|
|
102
113
|
let insetTop = insetBounds.top + window.scrollY;
|
|
@@ -105,28 +116,34 @@ export function layoutMarginals() {
|
|
|
105
116
|
let elementBottom = elementTop + elementBounds.height;
|
|
106
117
|
// If they overlap...
|
|
107
118
|
if (currentBottom !== null) {
|
|
108
|
-
if ((elementTop <= insetTop &&
|
|
109
|
-
|
|
110
|
-
(elementTop
|
|
119
|
+
if ((elementTop <= insetTop &&
|
|
120
|
+
elementBottom >= insetTop) ||
|
|
121
|
+
(elementTop <= insetBottom &&
|
|
122
|
+
elementBottom >= insetBottom) ||
|
|
123
|
+
(elementTop >= insetTop &&
|
|
124
|
+
elementBottom <= insetBottom)) {
|
|
111
125
|
// Calculate the new position based on the preferred position, minus the element's height (which was added above), plus the overlap between the inset and the marginal.
|
|
112
|
-
let newTop = currentBottom -
|
|
126
|
+
let newTop = currentBottom -
|
|
127
|
+
elementBounds.height +
|
|
128
|
+
(insetBottom - elementTop);
|
|
113
129
|
// Reposition the marginal.
|
|
114
|
-
el.style.top = newTop +
|
|
130
|
+
el.style.top = newTop + 'px';
|
|
115
131
|
// Update the new bottom.
|
|
116
|
-
currentBottom =
|
|
132
|
+
currentBottom =
|
|
133
|
+
newTop + elementBounds.height;
|
|
117
134
|
}
|
|
118
135
|
}
|
|
119
136
|
});
|
|
120
137
|
}
|
|
121
138
|
// Reposition the marginal horizontally.
|
|
122
|
-
el.style.left =
|
|
139
|
+
el.style.left = 'calc(2rem + ' + margin + 'px)';
|
|
123
140
|
}
|
|
124
141
|
}
|
|
125
142
|
}
|
|
126
143
|
// If it's fixed, remove any explicitly set inline values.
|
|
127
144
|
else {
|
|
128
|
-
el.style.removeProperty(
|
|
129
|
-
el.style.removeProperty(
|
|
145
|
+
el.style.removeProperty('top');
|
|
146
|
+
el.style.removeProperty('left');
|
|
130
147
|
}
|
|
131
148
|
});
|
|
132
149
|
}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { default as TableOfContents } from "./components/page/TableOfContents.svelte";
|
|
2
|
+
export { default as Search } from "./components/page/Search.svelte";
|
|
3
|
+
export { default as Index } from "./components/page/Index.svelte";
|
|
4
|
+
export { default as References } from "./components/page/References.svelte";
|
|
5
|
+
export { default as PossibleChapter } from "./components/page/PossibleChapter.svelte";
|
|
6
|
+
export { default as Media } from "./components/page/Media.svelte";
|
|
7
|
+
export { default as Print } from "./components/page/Print.svelte";
|
|
8
|
+
export { default as Glossary } from "./components/page/Glossary.svelte";
|
|
9
|
+
export { default as Edition } from "./components/page/Edition.svelte";
|
|
10
|
+
export { default as Feedback } from "./components/app/Feedback.svelte";
|
|
11
|
+
export { default as Loading } from "./components/page/Loading.svelte";
|
|
12
|
+
export { default as EditionModel } from "./models/book/Edition";
|
|
13
|
+
export { EDITION } from "./components/page/Contexts";
|
|
14
|
+
export { Schema } from "./models/book/Schema";
|
package/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { default as TableOfContents } from './components/page/TableOfContents.svelte';
|
|
2
|
+
export { default as Search } from './components/page/Search.svelte';
|
|
3
|
+
export { default as Index } from './components/page/Index.svelte';
|
|
4
|
+
export { default as References } from './components/page/References.svelte';
|
|
5
|
+
export { default as PossibleChapter } from './components/page/PossibleChapter.svelte';
|
|
6
|
+
export { default as Media } from './components/page/Media.svelte';
|
|
7
|
+
export { default as Print } from './components/page/Print.svelte';
|
|
8
|
+
export { default as Glossary } from './components/page/Glossary.svelte';
|
|
9
|
+
export { default as Edition } from './components/page/Edition.svelte';
|
|
10
|
+
export { default as Feedback } from './components/app/Feedback.svelte';
|
|
11
|
+
export { default as Loading } from './components/page/Loading.svelte';
|
|
12
|
+
export { default as EditionModel } from './models/book/Edition';
|
|
13
|
+
export { EDITION } from './components/page/Contexts';
|
|
14
|
+
export { Schema } from './models/book/Schema';
|
package/models/CRUD.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DocumentReference } from 'firebase/firestore';
|
|
2
|
+
import Edition from './book/Edition';
|
|
3
|
+
import Book from './book/Book';
|
|
4
|
+
import type { ChapterContent } from './book/Chapter';
|
|
5
|
+
export declare function getPublishedBooks(): Promise<Book[]>;
|
|
6
|
+
export declare function getUserBooks(userID: string): Promise<Book[] | null>;
|
|
7
|
+
export declare function getBookFromIDOrName(bookIDOrName: string): Promise<Book | null>;
|
|
8
|
+
export declare function readBook(bookID: string): Promise<Book | null>;
|
|
9
|
+
export declare function readEdition(editionID: string): Promise<Edition>;
|
|
10
|
+
export declare const createBook: (userID: string) => Promise<string>;
|
|
11
|
+
export declare function createNewEdition(book: Book): Promise<Book>;
|
|
12
|
+
export declare const updateEdition: (previousEdition: Edition | undefined, newEdition: Edition) => Promise<Edition>;
|
|
13
|
+
export declare function updateBook(book: Book): Promise<void>;
|
|
14
|
+
export declare function readChapterText(chapterRef: DocumentReference): Promise<ChapterContent>;
|
|
15
|
+
export declare function isSubdomainAvailable(subdomain: string, book: Book): Promise<boolean>;
|
|
16
|
+
export declare function getBookIDFromName(subdomain: string): Promise<string | null>;
|
|
17
|
+
export declare function publish(book: Book, index: number): Promise<string | undefined>;
|
package/models/CRUD.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { db, functions } from './Firebase';
|
|
2
|
+
import { collection, getDocs, getDoc, setDoc, doc, addDoc, query, where, deleteDoc, DocumentReference, } from 'firebase/firestore';
|
|
3
|
+
import { getFunctions, httpsCallable } from 'firebase/functions';
|
|
4
|
+
import Edition from './book/Edition';
|
|
5
|
+
import Book from './book/Book';
|
|
6
|
+
export async function getPublishedBooks() {
|
|
7
|
+
if (!db)
|
|
8
|
+
throw Error("Can't retrieve books, not connected to the database.");
|
|
9
|
+
try {
|
|
10
|
+
const data = await getDocs(collection(db, 'books'));
|
|
11
|
+
return data.docs
|
|
12
|
+
.map((doc) => Book.fromJSON(doc.ref, doc.data()))
|
|
13
|
+
.filter((book) => book.hasPublishedEdition());
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
throw Error("Couldn't load books, problem reading from the database.");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function getUserBooks(userID) {
|
|
20
|
+
if (!db)
|
|
21
|
+
throw Error("Can't retrieve user's books, not connected to Firebase.");
|
|
22
|
+
try {
|
|
23
|
+
const books = await getDocs(query(collection(db, 'books'), where('uids', 'array-contains', userID)));
|
|
24
|
+
return books.docs.map((doc) => Book.fromJSON(doc.ref, doc.data()));
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
console.error(err);
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export async function getBookFromIDOrName(bookIDOrName) {
|
|
32
|
+
const book = await readBook(bookIDOrName);
|
|
33
|
+
if (book)
|
|
34
|
+
return book;
|
|
35
|
+
const bookID = await getBookIDFromName(bookIDOrName);
|
|
36
|
+
return bookID !== null ? readBook(bookID) : null;
|
|
37
|
+
}
|
|
38
|
+
export async function readBook(bookID) {
|
|
39
|
+
if (!db)
|
|
40
|
+
return null;
|
|
41
|
+
const bookRef = doc(db, 'books', bookID);
|
|
42
|
+
const book = await getDoc(bookRef);
|
|
43
|
+
return !book.exists()
|
|
44
|
+
? null
|
|
45
|
+
: Book.fromJSON(bookRef, book.data());
|
|
46
|
+
}
|
|
47
|
+
export async function readEdition(editionID) {
|
|
48
|
+
if (!db)
|
|
49
|
+
throw Error("Can't retrieve edition, not connected to Firebase.");
|
|
50
|
+
const editionDoc = await getDoc(doc(db, 'editions', editionID));
|
|
51
|
+
if (!editionDoc.exists())
|
|
52
|
+
throw Error('' + editionID + " doesn't exist");
|
|
53
|
+
// TODO We should really be doing some validation here.
|
|
54
|
+
let edition = editionDoc.data();
|
|
55
|
+
// Go through each of the edition's chapters and get its text.
|
|
56
|
+
for (const chapter of edition.chapters) {
|
|
57
|
+
if (chapter.ref) {
|
|
58
|
+
const { text } = await readChapterText(chapter.ref);
|
|
59
|
+
chapter.text = text;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return Edition.fromJSON(editionDoc.ref, edition);
|
|
63
|
+
}
|
|
64
|
+
export const createBook = async (userID) => {
|
|
65
|
+
if (!db)
|
|
66
|
+
throw Error("Can't create book, not connected to Firebase.");
|
|
67
|
+
// Make a new default edition with a single chapter with this user id.
|
|
68
|
+
let newEdition = new Edition(undefined, undefined, [userID], 'Untitled', [], {}, '', [], 'All rights reserved.', '', [], {}, {}, {}, {}, null).withNewChapter();
|
|
69
|
+
// Add the edition to the editions collection in the database so we can get an edition ref.
|
|
70
|
+
const editionRef = await addDoc(collection(db, 'editions'), newEdition.toObject());
|
|
71
|
+
// Remember the ref.
|
|
72
|
+
newEdition = newEdition.withRef(editionRef);
|
|
73
|
+
// Note that we don't create a sub-collection of chapters here.
|
|
74
|
+
// Firestore creates sub-collections automatically when documents are added.
|
|
75
|
+
// Create a new book with the draft first edition and the user ID.
|
|
76
|
+
const newBook = {
|
|
77
|
+
title: '',
|
|
78
|
+
authors: [],
|
|
79
|
+
description: '',
|
|
80
|
+
cover: null,
|
|
81
|
+
editions: [
|
|
82
|
+
{
|
|
83
|
+
ref: editionRef,
|
|
84
|
+
time: Date.now(),
|
|
85
|
+
summary: '',
|
|
86
|
+
published: false,
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
uids: [userID],
|
|
90
|
+
};
|
|
91
|
+
// Create the book
|
|
92
|
+
const bookRef = await addDoc(collection(db, 'books'), newBook);
|
|
93
|
+
// Update all of the changes to the edition in Firestore, persisting the refs and chapter text.
|
|
94
|
+
await updateEdition(undefined, newEdition);
|
|
95
|
+
// Return the book id
|
|
96
|
+
return bookRef.id;
|
|
97
|
+
};
|
|
98
|
+
export async function createNewEdition(book) {
|
|
99
|
+
if (!db)
|
|
100
|
+
throw Error("Can't publish draft, no Firebase connection.");
|
|
101
|
+
// Get the latest draft.
|
|
102
|
+
const latestDraft = await book.getDraftEdition();
|
|
103
|
+
if (latestDraft === undefined)
|
|
104
|
+
return book;
|
|
105
|
+
// Make a copy without chapter and edition refs, because we want to create new ones.
|
|
106
|
+
const newEdition = latestDraft.withoutRefs();
|
|
107
|
+
// Create a copy of the existing draft as a new edition, but without any chapter refs.
|
|
108
|
+
const newEditionRef = await addDoc(collection(db, 'editions'), newEdition.toObject());
|
|
109
|
+
// Update the edition, creating chapter text as necessary.
|
|
110
|
+
updateEdition(undefined, newEdition.withRef(newEditionRef));
|
|
111
|
+
// Put the new edition in the book.
|
|
112
|
+
const revisions = book.getEditions();
|
|
113
|
+
revisions.unshift({
|
|
114
|
+
ref: newEditionRef,
|
|
115
|
+
time: Date.now(),
|
|
116
|
+
summary: '',
|
|
117
|
+
published: false,
|
|
118
|
+
});
|
|
119
|
+
book = book.withRevisions(revisions);
|
|
120
|
+
// Return the revised Book's revision.'
|
|
121
|
+
updateBook(book);
|
|
122
|
+
return book;
|
|
123
|
+
}
|
|
124
|
+
export const updateEdition = async (previousEdition, newEdition) => {
|
|
125
|
+
if (!db)
|
|
126
|
+
throw Error("Can't update edition, not connected to Firebase.");
|
|
127
|
+
// Get the reference to the edition, fail if we don't have one.
|
|
128
|
+
const editionRef = newEdition.getRef();
|
|
129
|
+
if (!editionRef)
|
|
130
|
+
throw Error('Book given has no ID');
|
|
131
|
+
// Create any new chapters that aren't in the current edition, and update text if it changed.
|
|
132
|
+
for (const newChapter of newEdition.chapters) {
|
|
133
|
+
if (newChapter.ref === undefined) {
|
|
134
|
+
// Make the new chapter's text.
|
|
135
|
+
const newChapterRef = await addDoc(collection(db, `editions/${editionRef.id}/chapters`), { text: newChapter.text });
|
|
136
|
+
// Add the ref of the new chapter to the revised chapter.
|
|
137
|
+
newEdition = newEdition.withRevisedChapter(newChapter, newChapter.withRef(newChapterRef));
|
|
138
|
+
}
|
|
139
|
+
// If we have a previous version, did the text change? If so, update it.
|
|
140
|
+
else if (previousEdition) {
|
|
141
|
+
const previousChapter = previousEdition.getChapterByRef(newChapter.ref);
|
|
142
|
+
if (previousChapter && newChapter.text !== previousChapter.text) {
|
|
143
|
+
await setDoc(doc(db, `editions/${editionRef.id}/chapters`, newChapter.ref.id), { text: newChapter.text });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Remove any chapters from Firebase that are removed.
|
|
148
|
+
if (previousEdition) {
|
|
149
|
+
for (const previousChapter of previousEdition.chapters) {
|
|
150
|
+
if (previousChapter.ref &&
|
|
151
|
+
newEdition.getChapterByRef(previousChapter.ref) === undefined) {
|
|
152
|
+
await deleteDoc(previousChapter.ref);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Finally, update the edition's document.
|
|
157
|
+
await setDoc(doc(db, 'editions', editionRef.id), newEdition.toObject());
|
|
158
|
+
return newEdition;
|
|
159
|
+
};
|
|
160
|
+
export async function updateBook(book) {
|
|
161
|
+
if (!db)
|
|
162
|
+
throw Error("Can't update book, not connected to Firebase.");
|
|
163
|
+
await setDoc(doc(db, 'books', book.getRefID()), book.toJSON());
|
|
164
|
+
}
|
|
165
|
+
export async function readChapterText(chapterRef) {
|
|
166
|
+
if (!db)
|
|
167
|
+
throw Error('Not connected to Firebase.');
|
|
168
|
+
const text = await getDoc(chapterRef);
|
|
169
|
+
if (!text.exists())
|
|
170
|
+
throw Error('Chapter text does not exist.');
|
|
171
|
+
return text.data();
|
|
172
|
+
}
|
|
173
|
+
export async function isSubdomainAvailable(subdomain, book) {
|
|
174
|
+
if (!db)
|
|
175
|
+
throw Error('Not connected to Firebase.');
|
|
176
|
+
const matches = await getDocs(query(collection(db, 'books'), where('domain', '==', subdomain)));
|
|
177
|
+
return matches.empty || matches.docs[0].id === book.getRefID();
|
|
178
|
+
}
|
|
179
|
+
export async function getBookIDFromName(subdomain) {
|
|
180
|
+
if (!db)
|
|
181
|
+
throw Error("Can't find book ID from URL, not connected to Firebase.");
|
|
182
|
+
const matches = await getDocs(query(collection(db, 'books'), where('domain', '==', subdomain)));
|
|
183
|
+
if (!matches.empty)
|
|
184
|
+
return matches.docs[0].id;
|
|
185
|
+
else
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
export async function publish(book, index) {
|
|
189
|
+
if (!db)
|
|
190
|
+
throw Error("Can't publish, no Firebase connection.");
|
|
191
|
+
if (!functions)
|
|
192
|
+
throw Error("Can't publish, no connection to Firebase functions.");
|
|
193
|
+
const edition = await book.getEditionNumber(index + 1);
|
|
194
|
+
if (edition === undefined)
|
|
195
|
+
return `Couldn't find edition ${index} number to publish`;
|
|
196
|
+
const editionRef = edition.getRef();
|
|
197
|
+
if (editionRef === undefined)
|
|
198
|
+
return `Couldn't find edition to publish`;
|
|
199
|
+
const publishEdition = httpsCallable(functions, 'publishEdition');
|
|
200
|
+
const result = await publishEdition({
|
|
201
|
+
book: book.getRef().id,
|
|
202
|
+
edition: editionRef.id,
|
|
203
|
+
});
|
|
204
|
+
return result.data;
|
|
205
|
+
// Update the edition's published status in the book.
|
|
206
|
+
// await updateBook(book.withEditionAsPublished(true, index));
|
|
207
|
+
}
|
package/models/Firebase.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ export declare const app: import("@firebase/app").FirebaseApp | undefined;
|
|
|
2
2
|
export declare const auth: import("@firebase/auth").Auth | undefined;
|
|
3
3
|
export declare const db: import("@firebase/firestore").Firestore | undefined;
|
|
4
4
|
export declare const storage: import("@firebase/storage").FirebaseStorage | undefined;
|
|
5
|
+
export declare const functions: import("@firebase/functions").Functions | undefined;
|
package/models/Firebase.js
CHANGED
|
@@ -1,26 +1,32 @@
|
|
|
1
|
-
import { initializeApp } from
|
|
2
|
-
import { connectAuthEmulator, getAuth } from
|
|
3
|
-
import { connectFirestoreEmulator, getFirestore } from
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
import { initializeApp } from 'firebase/app';
|
|
2
|
+
import { connectAuthEmulator, getAuth } from 'firebase/auth';
|
|
3
|
+
import { connectFirestoreEmulator, getFirestore } from 'firebase/firestore';
|
|
4
|
+
import { connectFunctionsEmulator, getFunctions } from 'firebase/functions';
|
|
5
|
+
import { connectStorageEmulator, getStorage } from 'firebase/storage';
|
|
6
|
+
const isReader = import.meta.env.VITE_READER === 'true';
|
|
6
7
|
// Initialize Firebase using the environment variables provided at build time.
|
|
7
8
|
// Only do this if we have environment variables defined. (We won't in the standalone Reader).
|
|
8
|
-
export const app = isReader
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
export const app = isReader
|
|
10
|
+
? undefined
|
|
11
|
+
: initializeApp({
|
|
12
|
+
apiKey: import.meta.env.VITE_BOOKISH_FIREBASE_API_KEY,
|
|
13
|
+
authDomain: import.meta.env.VITE_BOOKISH_AUTH_DOMAIN,
|
|
14
|
+
projectId: import.meta.env.VITE_BOOKISH_PROJECT_ID,
|
|
15
|
+
storageBucket: import.meta.env.VITE_BOOKISH_STORAGE_BUCKET,
|
|
16
|
+
messagingSenderId: import.meta.env.VITE_BOOKISH_MESSAGING_SENDER_ID,
|
|
17
|
+
appId: import.meta.env.VITE_BOOKISH_APP_ID,
|
|
18
|
+
});
|
|
16
19
|
export const auth = isReader ? undefined : getAuth();
|
|
17
20
|
export const db = isReader ? undefined : getFirestore();
|
|
18
21
|
export const storage = isReader ? undefined : getStorage();
|
|
22
|
+
export const functions = isReader ? undefined : getFunctions();
|
|
19
23
|
if (!isReader && import.meta.env.DEV) {
|
|
20
24
|
if (db)
|
|
21
25
|
connectFirestoreEmulator(db, 'localhost', 8080);
|
|
22
26
|
if (auth)
|
|
23
|
-
connectAuthEmulator(auth,
|
|
27
|
+
connectAuthEmulator(auth, 'http://localhost:9099');
|
|
24
28
|
if (storage)
|
|
25
|
-
connectStorageEmulator(storage,
|
|
29
|
+
connectStorageEmulator(storage, 'localhost', 9199);
|
|
30
|
+
if (functions)
|
|
31
|
+
connectFunctionsEmulator(functions, 'localhost', 5001);
|
|
26
32
|
}
|