@lapis-notes/lapis-plugin-docs 0.0.0-stage → 0.1.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.
- package/README.md +188 -2
- package/dist/docs/DocsBlockMarkdownEditor.svelte +37 -0
- package/dist/docs/DocsBlockMarkdownEditor.svelte.d.ts +13 -0
- package/dist/docs/DocsBlockRefPicker.svelte +75 -0
- package/dist/docs/DocsBlockRefPicker.svelte.d.ts +11 -0
- package/dist/docs/DocsBookEditor.svelte +141 -0
- package/dist/docs/DocsBookEditor.svelte.d.ts +10 -0
- package/dist/docs/DocsBookNavigation.svelte +838 -0
- package/dist/docs/DocsBookNavigation.svelte.d.ts +11 -0
- package/dist/docs/DocsBooksColumn.svelte +82 -0
- package/dist/docs/DocsBooksColumn.svelte.d.ts +10 -0
- package/dist/docs/DocsCardBackMatter.svelte +32 -0
- package/dist/docs/DocsCardBackMatter.svelte.d.ts +10 -0
- package/dist/docs/DocsCardBlockExtra.svelte +43 -0
- package/dist/docs/DocsCardBlockExtra.svelte.d.ts +9 -0
- package/dist/docs/DocsCardPreviewFlip.svelte +143 -0
- package/dist/docs/DocsCardPreviewFlip.svelte.d.ts +17 -0
- package/dist/docs/DocsCardPreviewStack.svelte +135 -0
- package/dist/docs/DocsCardPreviewStack.svelte.d.ts +13 -0
- package/dist/docs/DocsCardPrompt.svelte +33 -0
- package/dist/docs/DocsCardPrompt.svelte.d.ts +8 -0
- package/dist/docs/DocsCardReviewAnswer.svelte +45 -0
- package/dist/docs/DocsCardReviewAnswer.svelte.d.ts +8 -0
- package/dist/docs/DocsCardTagChips.svelte +19 -0
- package/dist/docs/DocsCardTagChips.svelte.d.ts +7 -0
- package/dist/docs/DocsCardsPanel.svelte +232 -0
- package/dist/docs/DocsCardsPanel.svelte.d.ts +17 -0
- package/dist/docs/DocsCardsReview.css +1050 -0
- package/dist/docs/DocsChapterFooter.svelte +248 -0
- package/dist/docs/DocsChapterFooter.svelte.d.ts +11 -0
- package/dist/docs/DocsChapterScrollRing.svelte +101 -0
- package/dist/docs/DocsChapterScrollRing.svelte.d.ts +6 -0
- package/dist/docs/DocsDisplayPanel.css +627 -0
- package/dist/docs/DocsDisplayPanel.svelte +78 -0
- package/dist/docs/DocsDisplayPanel.svelte.d.ts +16 -0
- package/dist/docs/DocsEditorPanel.css +325 -0
- package/dist/docs/DocsEditorPanel.svelte +570 -0
- package/dist/docs/DocsEditorPanel.svelte.d.ts +22 -0
- package/dist/docs/DocsFlipCard.svelte +68 -0
- package/dist/docs/DocsFlipCard.svelte.d.ts +8 -0
- package/dist/docs/DocsFolderDirectoryList.svelte +206 -0
- package/dist/docs/DocsFolderDirectoryList.svelte.d.ts +14 -0
- package/dist/docs/DocsFolderPanel.css +357 -0
- package/dist/docs/DocsFolderPanel.svelte +102 -0
- package/dist/docs/DocsFolderPanel.svelte.d.ts +17 -0
- package/dist/docs/DocsLinksPanel.css +61 -0
- package/dist/docs/DocsLinksPanel.svelte +55 -0
- package/dist/docs/DocsLinksPanel.svelte.d.ts +11 -0
- package/dist/docs/DocsMarkdownField.svelte +93 -0
- package/dist/docs/DocsMarkdownField.svelte.d.ts +11 -0
- package/dist/docs/DocsMarkdownPreview.svelte +278 -0
- package/dist/docs/DocsMarkdownPreview.svelte.d.ts +17 -0
- package/dist/docs/DocsReviewPanel.svelte +63 -0
- package/dist/docs/DocsReviewPanel.svelte.d.ts +11 -0
- package/dist/docs/DocsRichBlock.svelte +291 -0
- package/dist/docs/DocsRichBlock.svelte.d.ts +13 -0
- package/dist/docs/DocsRichDisplay.svelte +316 -0
- package/dist/docs/DocsRichDisplay.svelte.d.ts +14 -0
- package/dist/docs/DocsSlidesPreview.css +243 -0
- package/dist/docs/DocsSlidesPreview.svelte +206 -0
- package/dist/docs/DocsSlidesPreview.svelte.d.ts +10 -0
- package/dist/docs/DocsWorkspace.css +570 -0
- package/dist/docs/DocsWorkspace.svelte +831 -0
- package/dist/docs/DocsWorkspace.svelte.d.ts +48 -0
- package/dist/docs/DocsWorkspaceToolbar.svelte +211 -0
- package/dist/docs/DocsWorkspaceToolbar.svelte.d.ts +27 -0
- package/dist/docs/candidates/ChoiceMenu.svelte +114 -0
- package/dist/docs/candidates/ChoiceMenu.svelte.d.ts +10 -0
- package/dist/docs/candidates/FlipCardDeck.svelte +800 -0
- package/dist/docs/candidates/FlipCardDeck.svelte.d.ts +36 -0
- package/dist/docs/candidates/MarkdownFloatingToc.svelte +313 -0
- package/dist/docs/candidates/MarkdownFloatingToc.svelte.d.ts +14 -0
- package/dist/docs/candidates/SearchableChoicePicker.css +161 -0
- package/dist/docs/candidates/SearchableChoicePicker.svelte +208 -0
- package/dist/docs/candidates/SearchableChoicePicker.svelte.d.ts +19 -0
- package/dist/docs/candidates/StructuredTable.svelte +98 -0
- package/dist/docs/candidates/StructuredTable.svelte.d.ts +8 -0
- package/dist/docs/candidates/StructuredTableEditor.svelte +374 -0
- package/dist/docs/candidates/StructuredTableEditor.svelte.d.ts +12 -0
- package/dist/docs/candidates/TagEditor.svelte +31 -0
- package/dist/docs/candidates/TagEditor.svelte.d.ts +14 -0
- package/dist/docs/candidates/WorkspaceHistoryControls.svelte +112 -0
- package/dist/docs/candidates/WorkspaceHistoryControls.svelte.d.ts +8 -0
- package/dist/docs/candidates/markdown-floating-toc.css +151 -0
- package/dist/docs/candidates/markdown-floating-toc.d.ts +1 -0
- package/dist/docs/candidates/markdown-floating-toc.js +1 -0
- package/dist/docs/docs-anki-import.d.ts +34 -0
- package/dist/docs/docs-anki-import.js +516 -0
- package/dist/docs/docs-book-view-model.d.ts +9 -0
- package/dist/docs/docs-book-view-model.js +71 -0
- package/dist/docs/docs-card-answer-markdown.d.ts +1 -0
- package/dist/docs/docs-card-answer-markdown.js +63 -0
- package/dist/docs/docs-card-display.d.ts +10 -0
- package/dist/docs/docs-card-display.js +18 -0
- package/dist/docs/docs-display-focus.d.ts +7 -0
- package/dist/docs/docs-display-focus.js +42 -0
- package/dist/docs/docs-document-surface.d.ts +7 -0
- package/dist/docs/docs-document-surface.js +25 -0
- package/dist/docs/docs-folder-directory.d.ts +21 -0
- package/dist/docs/docs-folder-directory.js +56 -0
- package/dist/docs/docs-link-mode.d.ts +16 -0
- package/dist/docs/docs-link-mode.js +94 -0
- package/dist/docs/docs-workspace-helpers.d.ts +25 -0
- package/dist/docs/docs-workspace-helpers.js +195 -0
- package/dist/docs/docs.tokens.css +13 -0
- package/dist/docs/import-anki-package.d.ts +10 -0
- package/dist/docs/import-anki-package.js +30 -0
- package/dist/docs/lapis-markdown-extensions.d.ts +9 -0
- package/dist/docs/lapis-markdown-extensions.js +128 -0
- package/dist/docs/pin-reading-chrome.d.ts +4 -0
- package/dist/docs/pin-reading-chrome.js +32 -0
- package/dist/docs/sidebar/DocsFoldersSidebar.svelte +134 -0
- package/dist/docs/sidebar/DocsFoldersSidebar.svelte.d.ts +15 -0
- package/dist/docs/sidebar/DocsLinksSidebar.svelte +105 -0
- package/dist/docs/sidebar/DocsLinksSidebar.svelte.d.ts +11 -0
- package/dist/docs/sidebar/DocsSidebar.css +346 -0
- package/dist/docs/sidebar/DocsSidebar.svelte +430 -0
- package/dist/docs/sidebar/DocsSidebar.svelte.d.ts +18 -0
- package/dist/docs/sidebar/DocsSidebarHost.svelte +139 -0
- package/dist/docs/sidebar/DocsSidebarHost.svelte.d.ts +12 -0
- package/dist/docs/sidebar/DocsTagsSidebar.svelte +176 -0
- package/dist/docs/sidebar/DocsTagsSidebar.svelte.d.ts +12 -0
- package/dist/docs/sidebar/docs-book-note-tree.d.ts +23 -0
- package/dist/docs/sidebar/docs-book-note-tree.js +88 -0
- package/dist/docs/sidebar/docs-note-sort.d.ts +26 -0
- package/dist/docs/sidebar/docs-note-sort.js +54 -0
- package/dist/docs/sidebar/docs-sidebar-filters.d.ts +17 -0
- package/dist/docs/sidebar/docs-sidebar-filters.js +74 -0
- package/dist/docs/sidebar/docs-sidebar-ui-storage.d.ts +24 -0
- package/dist/docs/sidebar/docs-sidebar-ui-storage.js +87 -0
- package/dist/docs/sidebar/docs-source-folder-tree.d.ts +16 -0
- package/dist/docs/sidebar/docs-source-folder-tree.js +143 -0
- package/dist/docs/sidebar/docs-tag-tree.d.ts +17 -0
- package/dist/docs/sidebar/docs-tag-tree.js +84 -0
- package/dist/docs-cards-view.d.ts +18 -0
- package/dist/docs-cards-view.js +52 -0
- package/dist/docs-document-view.d.ts +24 -0
- package/dist/docs-document-view.js +127 -0
- package/dist/docs-document-workspace.svelte +215 -0
- package/dist/docs-document-workspace.svelte.d.ts +16 -0
- package/dist/docs-index.d.ts +5 -0
- package/dist/docs-index.js +49 -0
- package/dist/docs-path.d.ts +6 -0
- package/dist/docs-path.js +10 -0
- package/dist/docs-plugin.d.ts +21 -0
- package/dist/docs-plugin.js +140 -0
- package/dist/docs-repository.d.ts +15 -0
- package/dist/docs-repository.js +75 -0
- package/dist/docs-review-view.d.ts +18 -0
- package/dist/docs-review-view.js +52 -0
- package/dist/docs-settings-tab.d.ts +8 -0
- package/dist/docs-settings-tab.js +25 -0
- package/dist/docs-settings.d.ts +17 -0
- package/dist/docs-settings.js +38 -0
- package/dist/docs-view.d.ts +22 -0
- package/dist/docs-view.js +51 -0
- package/dist/docs-workspace.svelte +394 -0
- package/dist/docs-workspace.svelte.d.ts +15 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +12 -0
- package/dist/model/book.d.ts +6 -0
- package/dist/model/book.js +101 -0
- package/dist/model/coding-runtime.d.ts +4 -0
- package/dist/model/coding-runtime.js +9 -0
- package/dist/model/docs-card-context.d.ts +32 -0
- package/dist/model/docs-card-context.js +89 -0
- package/dist/model/docs-card-preview-stack-motion.d.ts +51 -0
- package/dist/model/docs-card-preview-stack-motion.js +94 -0
- package/dist/model/docs-media-context.d.ts +9 -0
- package/dist/model/docs-media-context.js +18 -0
- package/dist/model/docs-note-list.d.ts +8 -0
- package/dist/model/docs-note-list.js +25 -0
- package/dist/model/docs-relative-media.d.ts +30 -0
- package/dist/model/docs-relative-media.js +116 -0
- package/dist/model/docs-review-constants.d.ts +4 -0
- package/dist/model/docs-review-constants.js +13 -0
- package/dist/model/fsrs.d.ts +14 -0
- package/dist/model/fsrs.js +153 -0
- package/dist/model/graph.d.ts +12 -0
- package/dist/model/graph.js +169 -0
- package/dist/model/index.d.ts +14 -0
- package/dist/model/index.js +14 -0
- package/dist/model/markdown-normalize.d.ts +11 -0
- package/dist/model/markdown-normalize.js +755 -0
- package/dist/model/markdown.d.ts +167 -0
- package/dist/model/markdown.js +365 -0
- package/dist/model/sample.d.ts +7 -0
- package/dist/model/sample.js +524 -0
- package/dist/model/types.d.ts +328 -0
- package/dist/model/types.js +1 -0
- package/dist/model/workspace.d.ts +6 -0
- package/dist/model/workspace.js +81 -0
- package/dist/storybook.css +52 -0
- package/dist/styles.css +1 -0
- package/manifest.json +11 -0
- package/package.json +147 -4
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { DEFAULT_DOCS_NOTE_SORT, sortDocsNotes } from './docs-note-sort';
|
|
2
|
+
export const DOCS_SOURCE_ROOT_ID = '__docs-root__';
|
|
3
|
+
function sourceRelativePath(note) {
|
|
4
|
+
const sourcePath = note.sourcePath?.replace(/^\/+/, '').replaceAll('\\', '/') ?? '';
|
|
5
|
+
for (const prefix of ['data/docs/', 'docs/']) {
|
|
6
|
+
if (sourcePath.startsWith(prefix))
|
|
7
|
+
return sourcePath.slice(prefix.length);
|
|
8
|
+
}
|
|
9
|
+
return sourcePath || `${note.id}.doc.md`;
|
|
10
|
+
}
|
|
11
|
+
function sourceFolderPath(note) {
|
|
12
|
+
const segments = sourceRelativePath(note).split('/').filter(Boolean);
|
|
13
|
+
segments.pop();
|
|
14
|
+
return segments.join('/');
|
|
15
|
+
}
|
|
16
|
+
function folderId(path) {
|
|
17
|
+
return path || DOCS_SOURCE_ROOT_ID;
|
|
18
|
+
}
|
|
19
|
+
function ensureChild(parent, path, label) {
|
|
20
|
+
let child = parent.children.find((item) => item.path === path);
|
|
21
|
+
if (!child) {
|
|
22
|
+
child = {
|
|
23
|
+
id: folderId(path),
|
|
24
|
+
path,
|
|
25
|
+
label,
|
|
26
|
+
count: 0,
|
|
27
|
+
isBook: false,
|
|
28
|
+
notes: [],
|
|
29
|
+
children: []
|
|
30
|
+
};
|
|
31
|
+
parent.children.push(child);
|
|
32
|
+
}
|
|
33
|
+
return child;
|
|
34
|
+
}
|
|
35
|
+
function bookIndexNote(notes) {
|
|
36
|
+
const bookNotes = notes.filter((note) => (note.book?.chapters?.length ?? 0) > 0);
|
|
37
|
+
if (!bookNotes.length)
|
|
38
|
+
return null;
|
|
39
|
+
return (bookNotes.find((note) => {
|
|
40
|
+
const file = sourceRelativePath(note).split('/').at(-1);
|
|
41
|
+
return file === 'index.md' || file === 'index.doc.md';
|
|
42
|
+
}) ??
|
|
43
|
+
bookNotes[0] ??
|
|
44
|
+
null);
|
|
45
|
+
}
|
|
46
|
+
function applyBookFolderLabel(node) {
|
|
47
|
+
if (node.id === DOCS_SOURCE_ROOT_ID) {
|
|
48
|
+
node.isBook = false;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const indexNote = bookIndexNote(node.notes);
|
|
52
|
+
if (!indexNote) {
|
|
53
|
+
node.isBook = false;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const title = indexNote.title.trim();
|
|
57
|
+
node.label = title || node.label;
|
|
58
|
+
node.isBook = true;
|
|
59
|
+
}
|
|
60
|
+
function finalizeNode(node, sortMode) {
|
|
61
|
+
node.notes = sortDocsNotes(node.notes, sortMode);
|
|
62
|
+
applyBookFolderLabel(node);
|
|
63
|
+
node.children = node.children
|
|
64
|
+
.map((child) => finalizeNode(child, sortMode))
|
|
65
|
+
.sort((left, right) => left.label.localeCompare(right.label));
|
|
66
|
+
node.count = node.notes.length + node.children.reduce((total, child) => total + child.count, 0);
|
|
67
|
+
return node;
|
|
68
|
+
}
|
|
69
|
+
export function createDocsSourceFolderTree(notes, sortMode = DEFAULT_DOCS_NOTE_SORT) {
|
|
70
|
+
const root = {
|
|
71
|
+
id: DOCS_SOURCE_ROOT_ID,
|
|
72
|
+
path: '',
|
|
73
|
+
label: 'Docs',
|
|
74
|
+
count: 0,
|
|
75
|
+
isBook: false,
|
|
76
|
+
notes: [],
|
|
77
|
+
children: []
|
|
78
|
+
};
|
|
79
|
+
for (const note of notes) {
|
|
80
|
+
const segments = sourceFolderPath(note).split('/').filter(Boolean);
|
|
81
|
+
let current = root;
|
|
82
|
+
for (let index = 0; index < segments.length; index += 1) {
|
|
83
|
+
const path = segments.slice(0, index + 1).join('/');
|
|
84
|
+
current = ensureChild(current, path, segments[index]);
|
|
85
|
+
}
|
|
86
|
+
current.notes.push(note);
|
|
87
|
+
}
|
|
88
|
+
return finalizeNode(root, sortMode);
|
|
89
|
+
}
|
|
90
|
+
function normalizeQuery(query) {
|
|
91
|
+
return query.trim().toLowerCase();
|
|
92
|
+
}
|
|
93
|
+
function noteMatchesQuery(note, query) {
|
|
94
|
+
const haystack = [note.title, note.id, note.sourcePath].join(' ').toLowerCase();
|
|
95
|
+
return haystack.includes(query);
|
|
96
|
+
}
|
|
97
|
+
function cloneNode(node) {
|
|
98
|
+
return {
|
|
99
|
+
...node,
|
|
100
|
+
notes: [...node.notes],
|
|
101
|
+
children: node.children.map(cloneNode)
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function filterNode(node, query, sortMode) {
|
|
105
|
+
const folderHaystack = [node.label, node.path || 'Docs', node.isBook ? 'book' : '']
|
|
106
|
+
.join(' ')
|
|
107
|
+
.toLowerCase();
|
|
108
|
+
if (folderHaystack.includes(query))
|
|
109
|
+
return finalizeNode(cloneNode(node), sortMode);
|
|
110
|
+
const notes = sortDocsNotes(node.notes.filter((note) => noteMatchesQuery(note, query)), sortMode);
|
|
111
|
+
const children = node.children
|
|
112
|
+
.map((child) => filterNode(child, query, sortMode))
|
|
113
|
+
.filter((child) => child !== null)
|
|
114
|
+
.sort((left, right) => left.label.localeCompare(right.label));
|
|
115
|
+
const count = notes.length + children.reduce((total, child) => total + child.count, 0);
|
|
116
|
+
if (count === 0)
|
|
117
|
+
return null;
|
|
118
|
+
const next = { ...node, notes, children, count };
|
|
119
|
+
applyBookFolderLabel(next);
|
|
120
|
+
return next;
|
|
121
|
+
}
|
|
122
|
+
export function filterDocsSourceFolderTree(tree, query, sortMode = DEFAULT_DOCS_NOTE_SORT) {
|
|
123
|
+
const normalized = normalizeQuery(query);
|
|
124
|
+
if (!normalized)
|
|
125
|
+
return finalizeNode(cloneNode(tree), sortMode);
|
|
126
|
+
return filterNode(tree, normalized, sortMode);
|
|
127
|
+
}
|
|
128
|
+
export function collectExpandableSourceFolderIds(node) {
|
|
129
|
+
const ids = [];
|
|
130
|
+
if (node.notes.length || node.children.length)
|
|
131
|
+
ids.push(node.id);
|
|
132
|
+
for (const child of node.children)
|
|
133
|
+
ids.push(...collectExpandableSourceFolderIds(child));
|
|
134
|
+
return ids;
|
|
135
|
+
}
|
|
136
|
+
export function sourceFolderAncestorIds(note) {
|
|
137
|
+
const segments = sourceFolderPath(note).split('/').filter(Boolean);
|
|
138
|
+
const ids = [DOCS_SOURCE_ROOT_ID];
|
|
139
|
+
for (let index = 0; index < segments.length; index += 1) {
|
|
140
|
+
ids.push(segments.slice(0, index + 1).join('/'));
|
|
141
|
+
}
|
|
142
|
+
return ids;
|
|
143
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { docsNoteMatchesTagFolder, docsTagMatchesFolder, normalizeDocsTag, type DocsNoteSummary, type DocsTagSummary } from '../../model';
|
|
2
|
+
export type DocsTagSortMode = 'count' | 'name';
|
|
3
|
+
export type DocsTagTreeNode = {
|
|
4
|
+
name: string;
|
|
5
|
+
tag: string;
|
|
6
|
+
count: number;
|
|
7
|
+
exactCount: number;
|
|
8
|
+
summary: DocsTagSummary | null;
|
|
9
|
+
children: DocsTagTreeNode[];
|
|
10
|
+
};
|
|
11
|
+
export { docsNoteMatchesTagFolder, docsTagMatchesFolder, normalizeDocsTag };
|
|
12
|
+
/** Folder badges count notes/files, not notes+cards. */
|
|
13
|
+
export declare function docsTagCount(tag: DocsTagSummary): number;
|
|
14
|
+
export declare function sortDocsTagSummaries(tags: DocsTagSummary[], sortMode: DocsTagSortMode): DocsTagSummary[];
|
|
15
|
+
export declare function filterDocsTagsByPathMatch(tags: DocsTagSummary[], query: string): DocsTagSummary[];
|
|
16
|
+
export declare function createDocsTagTree(tagSummaries: DocsTagSummary[], sortMode?: DocsTagSortMode): DocsTagTreeNode[];
|
|
17
|
+
export declare function filterDocsNotesByTagFolder(notes: DocsNoteSummary[], folder: string): DocsNoteSummary[];
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { docsNoteMatchesTagFolder, docsTagMatchesFolder, normalizeDocsTag } from '../../model';
|
|
2
|
+
export { docsNoteMatchesTagFolder, docsTagMatchesFolder, normalizeDocsTag };
|
|
3
|
+
/** Folder badges count notes/files, not notes+cards. */
|
|
4
|
+
export function docsTagCount(tag) {
|
|
5
|
+
return tag.noteCount;
|
|
6
|
+
}
|
|
7
|
+
export function sortDocsTagSummaries(tags, sortMode) {
|
|
8
|
+
return [...tags].sort((left, right) => {
|
|
9
|
+
if (sortMode === 'name')
|
|
10
|
+
return left.tag.localeCompare(right.tag);
|
|
11
|
+
return docsTagCount(right) - docsTagCount(left) || left.tag.localeCompare(right.tag);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
export function filterDocsTagsByPathMatch(tags, query) {
|
|
15
|
+
const needle = normalizeDocsTag(query).toLowerCase();
|
|
16
|
+
if (!needle)
|
|
17
|
+
return tags;
|
|
18
|
+
return tags.filter((tag) => {
|
|
19
|
+
const path = normalizeDocsTag(tag.tag).toLowerCase();
|
|
20
|
+
return (path === needle ||
|
|
21
|
+
path.startsWith(`${needle}/`) ||
|
|
22
|
+
path.includes(`/${needle}/`) ||
|
|
23
|
+
path.endsWith(`/${needle}`) ||
|
|
24
|
+
path.includes(needle));
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export function createDocsTagTree(tagSummaries, sortMode = 'count') {
|
|
28
|
+
const nodeByPath = new Map();
|
|
29
|
+
const roots = [];
|
|
30
|
+
for (const summary of tagSummaries) {
|
|
31
|
+
const parts = summary.tag
|
|
32
|
+
.split('/')
|
|
33
|
+
.map((part) => part.trim())
|
|
34
|
+
.filter(Boolean);
|
|
35
|
+
if (!parts.length)
|
|
36
|
+
continue;
|
|
37
|
+
let parent = null;
|
|
38
|
+
for (let index = 0; index < parts.length; index += 1) {
|
|
39
|
+
const path = parts.slice(0, index + 1).join('/');
|
|
40
|
+
let node = nodeByPath.get(path);
|
|
41
|
+
if (!node) {
|
|
42
|
+
node = {
|
|
43
|
+
name: parts[index],
|
|
44
|
+
tag: path,
|
|
45
|
+
count: 0,
|
|
46
|
+
exactCount: 0,
|
|
47
|
+
summary: null,
|
|
48
|
+
children: []
|
|
49
|
+
};
|
|
50
|
+
nodeByPath.set(path, node);
|
|
51
|
+
if (parent)
|
|
52
|
+
parent.children.push(node);
|
|
53
|
+
else
|
|
54
|
+
roots.push(node);
|
|
55
|
+
}
|
|
56
|
+
if (index === parts.length - 1) {
|
|
57
|
+
node.summary = summary;
|
|
58
|
+
node.exactCount = docsTagCount(summary);
|
|
59
|
+
}
|
|
60
|
+
parent = node;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function assignCounts(node) {
|
|
64
|
+
const childrenCount = node.children.reduce((total, child) => total + assignCounts(child), 0);
|
|
65
|
+
node.count = node.summary ? node.exactCount : childrenCount;
|
|
66
|
+
return node.count;
|
|
67
|
+
}
|
|
68
|
+
function sortNodes(nodes) {
|
|
69
|
+
nodes.sort((left, right) => {
|
|
70
|
+
if (sortMode === 'name')
|
|
71
|
+
return left.name.localeCompare(right.name);
|
|
72
|
+
return right.count - left.count || left.name.localeCompare(right.name);
|
|
73
|
+
});
|
|
74
|
+
for (const node of nodes)
|
|
75
|
+
sortNodes(node.children);
|
|
76
|
+
return nodes;
|
|
77
|
+
}
|
|
78
|
+
for (const node of roots)
|
|
79
|
+
assignCounts(node);
|
|
80
|
+
return sortNodes(roots);
|
|
81
|
+
}
|
|
82
|
+
export function filterDocsNotesByTagFolder(notes, folder) {
|
|
83
|
+
return notes.filter((note) => docsNoteMatchesTagFolder(note, folder));
|
|
84
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { View, type WorkspaceLeaf } from "@lapis-notes/api";
|
|
2
|
+
import type { DocsRepository } from "./docs-repository";
|
|
3
|
+
import type { DocsSettingsSource } from "./docs-view";
|
|
4
|
+
export declare const DOCS_CARDS_VIEW_TYPE = "docs-cards";
|
|
5
|
+
export declare class DocsCardsView extends View {
|
|
6
|
+
private readonly repository;
|
|
7
|
+
private readonly clock;
|
|
8
|
+
private readonly settings?;
|
|
9
|
+
private component;
|
|
10
|
+
constructor(leaf: WorkspaceLeaf, repository: DocsRepository, clock?: () => Date, settings?: DocsSettingsSource | undefined);
|
|
11
|
+
getViewType(): string;
|
|
12
|
+
getDisplayText(): string;
|
|
13
|
+
getIcon(): string;
|
|
14
|
+
protected onOpen(): Promise<void>;
|
|
15
|
+
protected onClose(): Promise<void>;
|
|
16
|
+
onload(): void;
|
|
17
|
+
onunload(): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { View } from "@lapis-notes/api";
|
|
2
|
+
import { mount, unmount } from "svelte";
|
|
3
|
+
import DocsWorkspace from "./docs-workspace.svelte";
|
|
4
|
+
export const DOCS_CARDS_VIEW_TYPE = "docs-cards";
|
|
5
|
+
export class DocsCardsView extends View {
|
|
6
|
+
repository;
|
|
7
|
+
clock;
|
|
8
|
+
settings;
|
|
9
|
+
component = null;
|
|
10
|
+
constructor(leaf, repository, clock = () => new Date(), settings) {
|
|
11
|
+
super(leaf);
|
|
12
|
+
this.repository = repository;
|
|
13
|
+
this.clock = clock;
|
|
14
|
+
this.settings = settings;
|
|
15
|
+
}
|
|
16
|
+
getViewType() {
|
|
17
|
+
return DOCS_CARDS_VIEW_TYPE;
|
|
18
|
+
}
|
|
19
|
+
getDisplayText() {
|
|
20
|
+
return "Docs Cards";
|
|
21
|
+
}
|
|
22
|
+
getIcon() {
|
|
23
|
+
return "layers";
|
|
24
|
+
}
|
|
25
|
+
onOpen() {
|
|
26
|
+
return Promise.resolve();
|
|
27
|
+
}
|
|
28
|
+
onClose() {
|
|
29
|
+
return Promise.resolve();
|
|
30
|
+
}
|
|
31
|
+
onload() {
|
|
32
|
+
this.containerEl.style.width = "100%";
|
|
33
|
+
this.containerEl.style.height = "100%";
|
|
34
|
+
this.containerEl.style.minHeight = "0";
|
|
35
|
+
this.containerEl.style.overflow = "hidden";
|
|
36
|
+
this.component = mount(DocsWorkspace, {
|
|
37
|
+
target: this.containerEl,
|
|
38
|
+
props: {
|
|
39
|
+
app: this.app,
|
|
40
|
+
repository: this.repository,
|
|
41
|
+
clock: this.clock,
|
|
42
|
+
settingsSource: this.settings,
|
|
43
|
+
mode: "cards",
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
onunload() {
|
|
48
|
+
if (this.component)
|
|
49
|
+
void unmount(this.component);
|
|
50
|
+
this.component = null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { TextFileView, type TFile, type WorkspaceLeaf } from "@lapis-notes/api";
|
|
2
|
+
import type { DocsRepository } from "./docs-repository";
|
|
3
|
+
export declare class DocsDocumentView extends TextFileView {
|
|
4
|
+
private readonly repository?;
|
|
5
|
+
private readonly clock;
|
|
6
|
+
private component;
|
|
7
|
+
private readonly saves;
|
|
8
|
+
constructor(leaf?: WorkspaceLeaf, repository?: DocsRepository | undefined, clock?: () => Date);
|
|
9
|
+
getViewType(): string;
|
|
10
|
+
getDisplayText(): string;
|
|
11
|
+
getIcon(): string;
|
|
12
|
+
canAcceptExtension(extension: string): boolean;
|
|
13
|
+
getViewData(): string;
|
|
14
|
+
setViewData(data: string, _clear?: boolean): void;
|
|
15
|
+
clear(): void;
|
|
16
|
+
onload(): void;
|
|
17
|
+
onunload(): Promise<void>;
|
|
18
|
+
onUnloadFile(file: TFile): Promise<void>;
|
|
19
|
+
protected onClose(): Promise<void>;
|
|
20
|
+
private persistMarkdown;
|
|
21
|
+
private unmountWorkspace;
|
|
22
|
+
private fillLeafSurface;
|
|
23
|
+
private reload;
|
|
24
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { TextFileView, } from "@lapis-notes/api";
|
|
2
|
+
import { mount, unmount } from "svelte";
|
|
3
|
+
import { DOCS_DOCUMENT_VIEW_TYPE, isDocsDocumentPath, } from "./docs-path";
|
|
4
|
+
import DocsDocumentWorkspace from "./docs-document-workspace.svelte";
|
|
5
|
+
class DocsSaveCoordinator {
|
|
6
|
+
write;
|
|
7
|
+
chain = Promise.resolve();
|
|
8
|
+
pending = null;
|
|
9
|
+
constructor(write) {
|
|
10
|
+
this.write = write;
|
|
11
|
+
}
|
|
12
|
+
queue(request) {
|
|
13
|
+
this.pending = request;
|
|
14
|
+
this.chain = this.chain
|
|
15
|
+
.catch(() => undefined)
|
|
16
|
+
.then(async () => {
|
|
17
|
+
const next = this.pending;
|
|
18
|
+
this.pending = null;
|
|
19
|
+
if (!next)
|
|
20
|
+
return;
|
|
21
|
+
await this.write(next);
|
|
22
|
+
});
|
|
23
|
+
return this.chain;
|
|
24
|
+
}
|
|
25
|
+
flush() {
|
|
26
|
+
return this.chain;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export class DocsDocumentView extends TextFileView {
|
|
30
|
+
repository;
|
|
31
|
+
clock;
|
|
32
|
+
component = null;
|
|
33
|
+
saves = new DocsSaveCoordinator(async ({ file, value }) => this.app.vault.modify(file, value));
|
|
34
|
+
constructor(leaf, repository, clock = () => new Date()) {
|
|
35
|
+
super(leaf);
|
|
36
|
+
this.repository = repository;
|
|
37
|
+
this.clock = clock;
|
|
38
|
+
}
|
|
39
|
+
getViewType() {
|
|
40
|
+
return DOCS_DOCUMENT_VIEW_TYPE;
|
|
41
|
+
}
|
|
42
|
+
getDisplayText() {
|
|
43
|
+
return this.file?.baseName ?? "Docs";
|
|
44
|
+
}
|
|
45
|
+
getIcon() {
|
|
46
|
+
return "book-open";
|
|
47
|
+
}
|
|
48
|
+
canAcceptExtension(extension) {
|
|
49
|
+
const normalized = extension.toLowerCase().replace(/^\./, "");
|
|
50
|
+
if (normalized === "doc.md")
|
|
51
|
+
return true;
|
|
52
|
+
return isDocsDocumentPath(this.file?.path ?? "");
|
|
53
|
+
}
|
|
54
|
+
getViewData() {
|
|
55
|
+
return this.data;
|
|
56
|
+
}
|
|
57
|
+
setViewData(data, _clear) {
|
|
58
|
+
this.data = data;
|
|
59
|
+
this.editor.setValue(data);
|
|
60
|
+
this.reload();
|
|
61
|
+
}
|
|
62
|
+
clear() {
|
|
63
|
+
this.data = "";
|
|
64
|
+
this.editor.setValue("");
|
|
65
|
+
this.reload();
|
|
66
|
+
}
|
|
67
|
+
onload() {
|
|
68
|
+
this.reload();
|
|
69
|
+
}
|
|
70
|
+
async onunload() {
|
|
71
|
+
await this.saves.flush();
|
|
72
|
+
this.unmountWorkspace();
|
|
73
|
+
}
|
|
74
|
+
async onUnloadFile(file) {
|
|
75
|
+
await this.saves.flush();
|
|
76
|
+
await super.onUnloadFile(file);
|
|
77
|
+
}
|
|
78
|
+
async onClose() {
|
|
79
|
+
await this.saves.flush();
|
|
80
|
+
this.unmountWorkspace();
|
|
81
|
+
}
|
|
82
|
+
persistMarkdown(next) {
|
|
83
|
+
if (next === this.data)
|
|
84
|
+
return Promise.resolve();
|
|
85
|
+
this.data = next;
|
|
86
|
+
this.editor.setValue(next);
|
|
87
|
+
if (!this.file)
|
|
88
|
+
return Promise.resolve();
|
|
89
|
+
return this.saves.queue({ file: this.file.copy(), value: next });
|
|
90
|
+
}
|
|
91
|
+
unmountWorkspace() {
|
|
92
|
+
if (!this.component)
|
|
93
|
+
return;
|
|
94
|
+
unmount(this.component);
|
|
95
|
+
this.component = null;
|
|
96
|
+
}
|
|
97
|
+
fillLeafSurface(element) {
|
|
98
|
+
if (!element)
|
|
99
|
+
return;
|
|
100
|
+
element.style.display = "flex";
|
|
101
|
+
element.style.flexDirection = "column";
|
|
102
|
+
element.style.width = "100%";
|
|
103
|
+
element.style.height = "100%";
|
|
104
|
+
element.style.minHeight = "0";
|
|
105
|
+
element.style.overflow = "hidden";
|
|
106
|
+
}
|
|
107
|
+
reload() {
|
|
108
|
+
const target = this.contentEl ?? this.containerEl;
|
|
109
|
+
if (!target)
|
|
110
|
+
return;
|
|
111
|
+
this.unmountWorkspace();
|
|
112
|
+
target.empty();
|
|
113
|
+
this.fillLeafSurface(this.containerEl);
|
|
114
|
+
this.fillLeafSurface(target);
|
|
115
|
+
this.component = mount(DocsDocumentWorkspace, {
|
|
116
|
+
target,
|
|
117
|
+
props: {
|
|
118
|
+
app: this.app,
|
|
119
|
+
markdownText: this.data,
|
|
120
|
+
filePath: this.file?.path ?? "",
|
|
121
|
+
repository: this.repository,
|
|
122
|
+
clock: this.clock,
|
|
123
|
+
onMarkdownChange: (next) => this.persistMarkdown(next),
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* File-leaf adapter: vault markdown ↔ ported DocsWorkspace for a single *.doc.md.
|
|
4
|
+
*/
|
|
5
|
+
import type { App } from "@lapis-notes/api";
|
|
6
|
+
import { onDestroy } from "svelte";
|
|
7
|
+
import { docsPanelAfterPreviewToggle } from "./docs/docs-folder-directory";
|
|
8
|
+
import {
|
|
9
|
+
requestDocsDocumentSurface,
|
|
10
|
+
subscribeDocsDocumentSurface,
|
|
11
|
+
} from "./docs/docs-document-surface";
|
|
12
|
+
import DocsWorkspace from "./docs/DocsWorkspace.svelte";
|
|
13
|
+
import type { DocsRepository } from "./docs-repository";
|
|
14
|
+
import {
|
|
15
|
+
buildDocsWorkspace,
|
|
16
|
+
docsNoteToMarkdown,
|
|
17
|
+
parseDocsNoteMarkdownFile,
|
|
18
|
+
reviewDocsCard,
|
|
19
|
+
type DocsNote,
|
|
20
|
+
type DocsNotePanel,
|
|
21
|
+
type DocsReviewRating,
|
|
22
|
+
type DocsReviewScope,
|
|
23
|
+
} from "./model";
|
|
24
|
+
|
|
25
|
+
let {
|
|
26
|
+
app,
|
|
27
|
+
markdownText = "",
|
|
28
|
+
filePath = "",
|
|
29
|
+
repository,
|
|
30
|
+
clock = () => new Date(),
|
|
31
|
+
onMarkdownChange = async () => {},
|
|
32
|
+
}: {
|
|
33
|
+
app: App;
|
|
34
|
+
markdownText?: string;
|
|
35
|
+
filePath?: string;
|
|
36
|
+
repository?: DocsRepository;
|
|
37
|
+
clock?: () => Date;
|
|
38
|
+
onMarkdownChange?: (next: string) => void | Promise<void>;
|
|
39
|
+
} = $props();
|
|
40
|
+
|
|
41
|
+
let notes = $state<DocsNote[]>([]);
|
|
42
|
+
let activePanel = $state<DocsNotePanel>("display");
|
|
43
|
+
let reviewScope = $state<DocsReviewScope>("note");
|
|
44
|
+
let previewMode = $state(true);
|
|
45
|
+
let sidebarOpen = $state(true);
|
|
46
|
+
let loading = $state(false);
|
|
47
|
+
let saving = $state(false);
|
|
48
|
+
let error = $state<string | null>(null);
|
|
49
|
+
|
|
50
|
+
const activeNote = $derived.by(() => {
|
|
51
|
+
const parsed = parseDocsNoteMarkdownFile({
|
|
52
|
+
path: filePath || "untitled.doc.md",
|
|
53
|
+
content: markdownText,
|
|
54
|
+
});
|
|
55
|
+
return parsed;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const workspace = $derived.by(() => {
|
|
59
|
+
const catalog = notes.length
|
|
60
|
+
? notes.map((note) =>
|
|
61
|
+
note.id === activeNote?.id && activeNote ? activeNote : note,
|
|
62
|
+
)
|
|
63
|
+
: activeNote
|
|
64
|
+
? [activeNote]
|
|
65
|
+
: [];
|
|
66
|
+
return buildDocsWorkspace(catalog, clock());
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
async function refreshCatalog() {
|
|
70
|
+
if (!repository) {
|
|
71
|
+
notes = activeNote ? [activeNote] : [];
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
loading = true;
|
|
75
|
+
try {
|
|
76
|
+
const listed = await repository.listNotes("docs");
|
|
77
|
+
notes = listed.length ? listed : activeNote ? [activeNote] : [];
|
|
78
|
+
error = null;
|
|
79
|
+
} catch (err) {
|
|
80
|
+
error = err instanceof Error ? err.message : String(err);
|
|
81
|
+
notes = activeNote ? [activeNote] : [];
|
|
82
|
+
} finally {
|
|
83
|
+
loading = false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
$effect(() => {
|
|
88
|
+
void filePath;
|
|
89
|
+
void markdownText;
|
|
90
|
+
void refreshCatalog();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
$effect(() => {
|
|
94
|
+
if (!filePath) return;
|
|
95
|
+
return subscribeDocsDocumentSurface(filePath, (surface) => {
|
|
96
|
+
activePanel = surface.panel;
|
|
97
|
+
if (surface.reviewScope) reviewScope = surface.reviewScope;
|
|
98
|
+
if (surface.panel === "display" || surface.panel === "note") {
|
|
99
|
+
previewMode = surface.panel !== "note";
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
async function persistNote(note: DocsNote) {
|
|
105
|
+
saving = true;
|
|
106
|
+
try {
|
|
107
|
+
const next = docsNoteToMarkdown(note);
|
|
108
|
+
await onMarkdownChange(next);
|
|
109
|
+
if (repository) await repository.writeNote(note);
|
|
110
|
+
error = null;
|
|
111
|
+
} catch (err) {
|
|
112
|
+
error = err instanceof Error ? err.message : String(err);
|
|
113
|
+
} finally {
|
|
114
|
+
saving = false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function handleReview(
|
|
119
|
+
noteId: string,
|
|
120
|
+
cardId: string,
|
|
121
|
+
rating: DocsReviewRating,
|
|
122
|
+
) {
|
|
123
|
+
const note =
|
|
124
|
+
notes.find((entry) => entry.id === noteId) ??
|
|
125
|
+
(activeNote?.id === noteId ? activeNote : null);
|
|
126
|
+
if (!note) return;
|
|
127
|
+
const card = note.cards.find((entry) => entry.id === cardId);
|
|
128
|
+
if (!card) return;
|
|
129
|
+
const nextCard = reviewDocsCard(card, rating, clock());
|
|
130
|
+
const nextNote: DocsNote = {
|
|
131
|
+
...note,
|
|
132
|
+
cards: note.cards.map((entry) =>
|
|
133
|
+
entry.id === cardId ? nextCard : entry,
|
|
134
|
+
),
|
|
135
|
+
updatedAt: clock().toISOString(),
|
|
136
|
+
};
|
|
137
|
+
await persistNote(nextNote);
|
|
138
|
+
await refreshCatalog();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
onDestroy(() => {
|
|
142
|
+
// Flush is owned by DocsDocumentView save coordinator.
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// app used in openLinkText callback
|
|
146
|
+
</script>
|
|
147
|
+
|
|
148
|
+
<div
|
|
149
|
+
class="docs-document-workspace"
|
|
150
|
+
data-ui-component="docs-document"
|
|
151
|
+
data-docs-ready={activeNote ? "true" : "false"}
|
|
152
|
+
>
|
|
153
|
+
<DocsWorkspace
|
|
154
|
+
{workspace}
|
|
155
|
+
activeNote={activeNote}
|
|
156
|
+
activeNoteId={activeNote?.id ?? null}
|
|
157
|
+
{activePanel}
|
|
158
|
+
{reviewScope}
|
|
159
|
+
{previewMode}
|
|
160
|
+
{sidebarOpen}
|
|
161
|
+
{loading}
|
|
162
|
+
{saving}
|
|
163
|
+
{error}
|
|
164
|
+
onToggleSidebar={() => {
|
|
165
|
+
sidebarOpen = !sidebarOpen;
|
|
166
|
+
}}
|
|
167
|
+
onActiveNoteChange={(noteId) => {
|
|
168
|
+
if (!noteId || !repository) return;
|
|
169
|
+
const target = notes.find((note) => note.id === noteId);
|
|
170
|
+
if (!target?.sourcePath) return;
|
|
171
|
+
const file = app.vault.getFileByPath(target.sourcePath);
|
|
172
|
+
if (!file) return;
|
|
173
|
+
requestDocsDocumentSurface(target.sourcePath, { panel: "display" });
|
|
174
|
+
void app.workspace.openLinkText(target.sourcePath, "", false);
|
|
175
|
+
}}
|
|
176
|
+
onActivePanelChange={(panel) => {
|
|
177
|
+
activePanel = panel;
|
|
178
|
+
if (panel === "display" || panel === "note") {
|
|
179
|
+
previewMode = panel === "display";
|
|
180
|
+
}
|
|
181
|
+
}}
|
|
182
|
+
onReviewScopeChange={(scope) => {
|
|
183
|
+
reviewScope = scope;
|
|
184
|
+
}}
|
|
185
|
+
onPreviewModeChange={(enabled) => {
|
|
186
|
+
previewMode = enabled;
|
|
187
|
+
activePanel = docsPanelAfterPreviewToggle(activePanel, enabled);
|
|
188
|
+
}}
|
|
189
|
+
onSaveNote={persistNote}
|
|
190
|
+
onReviewCard={handleReview}
|
|
191
|
+
onImportAnkiPackage={async (file) => {
|
|
192
|
+
if (!repository) return;
|
|
193
|
+
const { importAnkiPackageFile } = await import("./docs/import-anki-package");
|
|
194
|
+
await importAnkiPackageFile({
|
|
195
|
+
app,
|
|
196
|
+
repository,
|
|
197
|
+
docsRoot: "docs",
|
|
198
|
+
file,
|
|
199
|
+
now: clock(),
|
|
200
|
+
});
|
|
201
|
+
await refreshCatalog();
|
|
202
|
+
}}
|
|
203
|
+
/>
|
|
204
|
+
</div>
|
|
205
|
+
|
|
206
|
+
<style>
|
|
207
|
+
.docs-document-workspace {
|
|
208
|
+
display: flex;
|
|
209
|
+
flex-direction: column;
|
|
210
|
+
width: 100%;
|
|
211
|
+
height: 100%;
|
|
212
|
+
min-height: 0;
|
|
213
|
+
overflow: hidden;
|
|
214
|
+
}
|
|
215
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-leaf adapter: vault markdown ↔ ported DocsWorkspace for a single *.doc.md.
|
|
3
|
+
*/
|
|
4
|
+
import type { App } from "@lapis-notes/api";
|
|
5
|
+
import type { DocsRepository } from "./docs-repository";
|
|
6
|
+
type $$ComponentProps = {
|
|
7
|
+
app: App;
|
|
8
|
+
markdownText?: string;
|
|
9
|
+
filePath?: string;
|
|
10
|
+
repository?: DocsRepository;
|
|
11
|
+
clock?: () => Date;
|
|
12
|
+
onMarkdownChange?: (next: string) => void | Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
declare const DocsDocumentWorkspace: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
15
|
+
type DocsDocumentWorkspace = ReturnType<typeof DocsDocumentWorkspace>;
|
|
16
|
+
export default DocsDocumentWorkspace;
|