@bendyline/docblocks-react 2.7.2 → 2.7.4
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/THIRD_PARTY_NOTICES.txt +215 -23
- package/dist/{AiDiagrams-LFV4YU6W.js → AiDiagrams-QZMJNGDT.js} +3 -3
- package/dist/{AiEditorAssistant-GN2KXKZD.js → AiEditorAssistant-4HFFGVU4.js} +205 -166
- package/dist/AiStudyDialog-P3E7PJV5.js +1150 -0
- package/dist/{AudioExportDialog-F23QXNPB.js → AudioExportDialog-IOYIEAER.js} +1 -1
- package/dist/{DocumentConflictDialog-5LRVIGXS.js → DocumentConflictDialog-DZ2BV2IH.js} +1 -1
- package/dist/ExportDialog-LGWBXIWN.js +9 -0
- package/dist/{ExportToolbarControls-2FEIHNMW.js → ExportToolbarControls-HOV424TO.js} +114 -14
- package/dist/{GitUI-RCWUZVS6.js → GitUI-F3CNBURE.js} +1 -1
- package/dist/{KeyboardShortcutsDialog-NOD4P25G.js → KeyboardShortcutsDialog-HVKDFP5Z.js} +2 -2
- package/dist/{PresentationMaker-ITNP5SDO.js → PresentationMaker-MUMFAXEI.js} +3 -3
- package/dist/{QuickOpenDialog-2KK4SEBU.js → QuickOpenDialog-ENVFGIHS.js} +1 -1
- package/dist/{Settings-RDYvDDI0.d.ts → Settings-CfhY489G.d.ts} +3 -5
- package/dist/{ShareDialog-XUA2OVGI.js → ShareDialog-PF7D7ORP.js} +1 -1
- package/dist/{SpeechToolbarControl-CLU7RB2G.js → SpeechToolbarControl-KNI2C4JJ.js} +1 -1
- package/dist/{TextFromNarration-NITJQ4IB.js → TextFromNarration-EYOMW2IW.js} +1 -1
- package/dist/{chunk-HRWEGPTY.js → chunk-7CSBRAMT.js} +109 -24
- package/dist/{chunk-NAH52736.js → chunk-7V34VUK6.js} +969 -98
- package/dist/{chunk-K7XJDJUJ.js → chunk-ACQF63SB.js} +14 -4
- package/dist/{chunk-X3DDTJKR.js → chunk-D4HIOS7E.js} +256 -18
- package/dist/{chunk-BLUEZG7T.js → chunk-FBPCURCS.js} +9 -2
- package/dist/{chunk-Y5OE3HJC.js → chunk-GFK4TCKN.js} +11 -5
- package/dist/chunk-H3BK5MK6.js +34 -0
- package/dist/{chunk-6B7G33D5.js → chunk-KBUHWZCF.js} +1 -1
- package/dist/{chunk-SSB43524.js → chunk-PNZFIIWW.js} +91 -12
- package/dist/{chunk-56KO2LYN.js → chunk-VJPGZCFS.js} +4 -0
- package/dist/chunk-XNT66JC2.js +168 -0
- package/dist/editor.js +4 -4
- package/dist/export/index.d.ts +19 -4
- package/dist/export/index.js +4 -4
- package/dist/index.d.ts +19 -5
- package/dist/index.js +858 -557
- package/dist/{run-export-CS3HRNAZ.js → run-export-SPNNH32M.js} +1 -1
- package/dist/settings/index.d.ts +1 -1
- package/dist/settings/index.js +2 -2
- package/package.json +8 -8
- package/src/styles/docblocks.css +526 -63
- package/dist/ExportDialog-JRVZCG3J.js +0 -9
- package/dist/chunk-YBEYTVU2.js +0 -12
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ProgressivePlayer
|
|
3
|
+
} from "./chunk-2IYBBFQX.js";
|
|
1
4
|
import {
|
|
2
5
|
BackupIcon,
|
|
3
6
|
FolderIcon,
|
|
@@ -14,13 +17,10 @@ import {
|
|
|
14
17
|
} from "./chunk-DICE7VBJ.js";
|
|
15
18
|
import {
|
|
16
19
|
useConfirmDialog
|
|
17
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-KBUHWZCF.js";
|
|
18
21
|
import {
|
|
19
22
|
createSpeechInputProvider
|
|
20
23
|
} from "./chunk-KBDZDFPU.js";
|
|
21
|
-
import {
|
|
22
|
-
ProgressivePlayer
|
|
23
|
-
} from "./chunk-2IYBBFQX.js";
|
|
24
24
|
import {
|
|
25
25
|
sharedDocumentFilename
|
|
26
26
|
} from "./chunk-SPUPWCSI.js";
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
} from "./chunk-KWG6UP5O.js";
|
|
52
52
|
import {
|
|
53
53
|
runExport
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-7CSBRAMT.js";
|
|
55
55
|
import {
|
|
56
56
|
createImageSaveOutput
|
|
57
57
|
} from "./chunk-UONFWKJ7.js";
|
|
@@ -87,7 +87,7 @@ import {
|
|
|
87
87
|
saveProofingPreferences,
|
|
88
88
|
saveThemePreference,
|
|
89
89
|
saveWriteCanvasPreferences
|
|
90
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-FBPCURCS.js";
|
|
91
91
|
import {
|
|
92
92
|
FindButton,
|
|
93
93
|
focusFindInput,
|
|
@@ -99,14 +99,19 @@ import {
|
|
|
99
99
|
isApplePlatform,
|
|
100
100
|
matchShortcut,
|
|
101
101
|
shortcutLabel
|
|
102
|
-
} from "./chunk-
|
|
103
|
-
import "./chunk-
|
|
104
|
-
import
|
|
102
|
+
} from "./chunk-ACQF63SB.js";
|
|
103
|
+
import "./chunk-PNZFIIWW.js";
|
|
104
|
+
import {
|
|
105
|
+
buildIssueReportUrl,
|
|
106
|
+
displayBuildDate,
|
|
107
|
+
localDateStamp,
|
|
108
|
+
openExternalUrl
|
|
109
|
+
} from "./chunk-7V34VUK6.js";
|
|
105
110
|
import "./chunk-K4I3NJFL.js";
|
|
106
111
|
import {
|
|
107
112
|
ExportDialog
|
|
108
|
-
} from "./chunk-
|
|
109
|
-
import "./chunk-
|
|
113
|
+
} from "./chunk-GFK4TCKN.js";
|
|
114
|
+
import "./chunk-H3BK5MK6.js";
|
|
110
115
|
import {
|
|
111
116
|
DEFAULT_OPTIONS,
|
|
112
117
|
loadLastExportOptions
|
|
@@ -114,13 +119,14 @@ import {
|
|
|
114
119
|
import {
|
|
115
120
|
Dialog,
|
|
116
121
|
dismissTopmostDialog
|
|
117
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-VJPGZCFS.js";
|
|
118
123
|
|
|
119
124
|
// src/FileExplorer/FileExplorer.tsx
|
|
120
125
|
import { useCallback as useCallback5, useEffect as useEffect5, useMemo, useRef as useRef5, useState as useState4 } from "react";
|
|
121
126
|
import {
|
|
122
127
|
isFileSystemMoveStateError,
|
|
123
|
-
parseWorkspacePath as parseWorkspacePath4
|
|
128
|
+
parseWorkspacePath as parseWorkspacePath4,
|
|
129
|
+
tryParseWorkspacePath as tryParseWorkspacePath2
|
|
124
130
|
} from "@bendyline/docblocks/filesystem";
|
|
125
131
|
|
|
126
132
|
// src/FileExplorer/useFileTree.ts
|
|
@@ -134,6 +140,7 @@ import {
|
|
|
134
140
|
workspacePathDirname
|
|
135
141
|
} from "@bendyline/docblocks/filesystem";
|
|
136
142
|
var DIRECTORY_NOT_FOUND_RETRY_DELAYS_MS = Object.freeze([40, 120]);
|
|
143
|
+
var AUTO_RETRY_DELAYS_MS = Object.freeze([1e3, 4e3, 15e3]);
|
|
137
144
|
function normalisePath(path) {
|
|
138
145
|
return parseWorkspacePath(path);
|
|
139
146
|
}
|
|
@@ -162,10 +169,13 @@ function sameEntry(left, right) {
|
|
|
162
169
|
if (left.kind !== right.kind || left.name !== right.name || left.path !== right.path)
|
|
163
170
|
return false;
|
|
164
171
|
if (left.kind === "file" && right.kind === "file") {
|
|
165
|
-
return left.lastModified === right.lastModified;
|
|
172
|
+
return left.lastModified === right.lastModified && left.readIssue?.code === right.readIssue?.code && left.readIssue?.message === right.readIssue?.message;
|
|
166
173
|
}
|
|
167
174
|
return true;
|
|
168
175
|
}
|
|
176
|
+
function hasUnreadableFile(entries) {
|
|
177
|
+
return entries.some((entry) => entry.kind === "file" && entry.readIssue !== void 0);
|
|
178
|
+
}
|
|
169
179
|
function reconcileEntries(current, incoming) {
|
|
170
180
|
const currentByPath = new Map(current.map((entry) => [entry.path, entry]));
|
|
171
181
|
const reconciled = incoming.map((entry) => {
|
|
@@ -184,7 +194,8 @@ async function readProviderDirectory(provider, path) {
|
|
|
184
194
|
kind: entry.kind,
|
|
185
195
|
name: entry.name,
|
|
186
196
|
path: entry.path,
|
|
187
|
-
...entry.kind === "file" ? { lastModified: entry.lastModified } : {}
|
|
197
|
+
...entry.kind === "file" ? { lastModified: entry.lastModified } : {},
|
|
198
|
+
...entry.kind === "file" && entry.readIssue ? { readIssue: entry.readIssue } : {}
|
|
188
199
|
}));
|
|
189
200
|
};
|
|
190
201
|
for (let attempt = 0; ; attempt += 1) {
|
|
@@ -232,64 +243,111 @@ function useFileTree(provider, metadataRefreshKey, metadataRefreshPath) {
|
|
|
232
243
|
providerRef.current = provider;
|
|
233
244
|
const directoryRequestSequenceRef = useRef(0);
|
|
234
245
|
const directoryRequestsRef = useRef(/* @__PURE__ */ new Map());
|
|
246
|
+
const autoRetriesRef = useRef(/* @__PURE__ */ new Map());
|
|
247
|
+
const autoRetryLoadRef = useRef(async () => void 0);
|
|
235
248
|
const reportRootIssue = useCallback((caught) => {
|
|
236
249
|
setRootIssue(readIssue(caught, ""));
|
|
237
250
|
}, []);
|
|
238
|
-
const
|
|
239
|
-
const
|
|
240
|
-
if (
|
|
241
|
-
|
|
242
|
-
setLoading(false);
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
const requestId = ++directoryRequestSequenceRef.current;
|
|
246
|
-
directoryRequestsRef.current.set("", requestId);
|
|
247
|
-
const isCurrent = () => providerRef.current === sourceProvider && directoryRequestsRef.current.get("") === requestId;
|
|
248
|
-
if (showLoading) setLoading(true);
|
|
249
|
-
try {
|
|
250
|
-
const root = await readProviderDirectory(sourceProvider, "");
|
|
251
|
-
if (!isCurrent()) return;
|
|
252
|
-
setEntries((current) => reconcileEntries(current, root));
|
|
253
|
-
setRootIssue(null);
|
|
254
|
-
} catch (caught) {
|
|
255
|
-
if (isCurrent()) setRootIssue(readIssue(caught, ""));
|
|
256
|
-
} finally {
|
|
257
|
-
if (isCurrent()) setLoading(false);
|
|
258
|
-
}
|
|
251
|
+
const cancelAutoRetry = useCallback((directoryPath) => {
|
|
252
|
+
const state = autoRetriesRef.current.get(directoryPath);
|
|
253
|
+
if (state?.timer) clearTimeout(state.timer);
|
|
254
|
+
autoRetriesRef.current.delete(directoryPath);
|
|
259
255
|
}, []);
|
|
260
|
-
const
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
const canonical = normalisePath(dirPath);
|
|
264
|
-
const requestId = ++directoryRequestSequenceRef.current;
|
|
265
|
-
directoryRequestsRef.current.set(canonical, requestId);
|
|
266
|
-
const isCurrent = () => providerRef.current === sourceProvider && directoryRequestsRef.current.get(canonical) === requestId;
|
|
267
|
-
try {
|
|
268
|
-
const children = await readProviderDirectory(sourceProvider, dirPath);
|
|
269
|
-
if (!isCurrent()) return;
|
|
270
|
-
setChildEntries((prev) => {
|
|
271
|
-
const current = prev.get(canonical) ?? [];
|
|
272
|
-
const reconciled = reconcileEntries(current, children);
|
|
273
|
-
if (prev.has(canonical) && reconciled === current) return prev;
|
|
274
|
-
const next = new Map(prev);
|
|
275
|
-
next.set(canonical, reconciled);
|
|
276
|
-
return next;
|
|
277
|
-
});
|
|
278
|
-
setChildIssues((prev) => {
|
|
279
|
-
if (!prev.has(canonical)) return prev;
|
|
280
|
-
const next = new Map(prev);
|
|
281
|
-
next.delete(canonical);
|
|
282
|
-
return next;
|
|
283
|
-
});
|
|
284
|
-
} catch (caught) {
|
|
285
|
-
if (!isCurrent()) return;
|
|
286
|
-
setChildIssues((prev) => {
|
|
287
|
-
const next = new Map(prev);
|
|
288
|
-
next.set(canonical, readIssue(caught, dirPath));
|
|
289
|
-
return next;
|
|
290
|
-
});
|
|
256
|
+
const cancelAllAutoRetries = useCallback(() => {
|
|
257
|
+
for (const state of autoRetriesRef.current.values()) {
|
|
258
|
+
if (state.timer) clearTimeout(state.timer);
|
|
291
259
|
}
|
|
260
|
+
autoRetriesRef.current.clear();
|
|
292
261
|
}, []);
|
|
262
|
+
const settleAutoRetry = useCallback(
|
|
263
|
+
(directoryPath, needsRetry) => {
|
|
264
|
+
if (!needsRetry) {
|
|
265
|
+
cancelAutoRetry(directoryPath);
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const current = autoRetriesRef.current.get(directoryPath);
|
|
269
|
+
if (current?.timer) return;
|
|
270
|
+
const attempts = current?.attempts ?? 0;
|
|
271
|
+
const delay = AUTO_RETRY_DELAYS_MS[attempts];
|
|
272
|
+
if (delay === void 0) return;
|
|
273
|
+
const next = { attempts: attempts + 1, timer: null };
|
|
274
|
+
next.timer = setTimeout(() => {
|
|
275
|
+
next.timer = null;
|
|
276
|
+
void autoRetryLoadRef.current(directoryPath);
|
|
277
|
+
}, delay);
|
|
278
|
+
autoRetriesRef.current.set(directoryPath, next);
|
|
279
|
+
},
|
|
280
|
+
[cancelAutoRetry]
|
|
281
|
+
);
|
|
282
|
+
const loadRoot = useCallback(
|
|
283
|
+
async (showLoading = true) => {
|
|
284
|
+
const sourceProvider = providerRef.current;
|
|
285
|
+
if (!sourceProvider) {
|
|
286
|
+
setEntries([]);
|
|
287
|
+
setLoading(false);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const requestId = ++directoryRequestSequenceRef.current;
|
|
291
|
+
directoryRequestsRef.current.set("", requestId);
|
|
292
|
+
const isCurrent = () => providerRef.current === sourceProvider && directoryRequestsRef.current.get("") === requestId;
|
|
293
|
+
if (showLoading) setLoading(true);
|
|
294
|
+
try {
|
|
295
|
+
const root = await readProviderDirectory(sourceProvider, "");
|
|
296
|
+
if (!isCurrent()) return;
|
|
297
|
+
setEntries((current) => reconcileEntries(current, root));
|
|
298
|
+
setRootIssue(null);
|
|
299
|
+
settleAutoRetry("", hasUnreadableFile(root));
|
|
300
|
+
} catch (caught) {
|
|
301
|
+
if (isCurrent()) {
|
|
302
|
+
const issue = readIssue(caught, "");
|
|
303
|
+
setRootIssue(issue);
|
|
304
|
+
settleAutoRetry("", issue.retryable);
|
|
305
|
+
}
|
|
306
|
+
} finally {
|
|
307
|
+
if (isCurrent()) setLoading(false);
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
[settleAutoRetry]
|
|
311
|
+
);
|
|
312
|
+
const loadChildren = useCallback(
|
|
313
|
+
async (dirPath) => {
|
|
314
|
+
const sourceProvider = providerRef.current;
|
|
315
|
+
if (!sourceProvider) return;
|
|
316
|
+
const canonical = normalisePath(dirPath);
|
|
317
|
+
const requestId = ++directoryRequestSequenceRef.current;
|
|
318
|
+
directoryRequestsRef.current.set(canonical, requestId);
|
|
319
|
+
const isCurrent = () => providerRef.current === sourceProvider && directoryRequestsRef.current.get(canonical) === requestId;
|
|
320
|
+
try {
|
|
321
|
+
const children = await readProviderDirectory(sourceProvider, dirPath);
|
|
322
|
+
if (!isCurrent()) return;
|
|
323
|
+
setChildEntries((prev) => {
|
|
324
|
+
const current = prev.get(canonical) ?? [];
|
|
325
|
+
const reconciled = reconcileEntries(current, children);
|
|
326
|
+
if (prev.has(canonical) && reconciled === current) return prev;
|
|
327
|
+
const next = new Map(prev);
|
|
328
|
+
next.set(canonical, reconciled);
|
|
329
|
+
return next;
|
|
330
|
+
});
|
|
331
|
+
setChildIssues((prev) => {
|
|
332
|
+
if (!prev.has(canonical)) return prev;
|
|
333
|
+
const next = new Map(prev);
|
|
334
|
+
next.delete(canonical);
|
|
335
|
+
return next;
|
|
336
|
+
});
|
|
337
|
+
settleAutoRetry(canonical, hasUnreadableFile(children));
|
|
338
|
+
} catch (caught) {
|
|
339
|
+
if (!isCurrent()) return;
|
|
340
|
+
const issue = readIssue(caught, dirPath);
|
|
341
|
+
setChildIssues((prev) => {
|
|
342
|
+
const next = new Map(prev);
|
|
343
|
+
next.set(canonical, issue);
|
|
344
|
+
return next;
|
|
345
|
+
});
|
|
346
|
+
settleAutoRetry(canonical, issue.retryable);
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
[settleAutoRetry]
|
|
350
|
+
);
|
|
293
351
|
useEffect(() => {
|
|
294
352
|
setEntries([]);
|
|
295
353
|
setExpanded(/* @__PURE__ */ new Set());
|
|
@@ -299,8 +357,10 @@ function useFileTree(provider, metadataRefreshKey, metadataRefreshPath) {
|
|
|
299
357
|
setSelectedKind(null);
|
|
300
358
|
setRootIssue(null);
|
|
301
359
|
directoryRequestsRef.current.clear();
|
|
360
|
+
cancelAllAutoRetries();
|
|
302
361
|
void loadRoot();
|
|
303
|
-
|
|
362
|
+
return cancelAllAutoRetries;
|
|
363
|
+
}, [provider, loadRoot, cancelAllAutoRetries]);
|
|
304
364
|
const toggleExpand = useCallback(
|
|
305
365
|
(path) => {
|
|
306
366
|
setExpanded((prev) => {
|
|
@@ -347,10 +407,12 @@ function useFileTree(provider, metadataRefreshKey, metadataRefreshPath) {
|
|
|
347
407
|
}, [loadRoot, loadChildren, expanded]);
|
|
348
408
|
const retryDirectory = useCallback(
|
|
349
409
|
async (path) => {
|
|
350
|
-
|
|
410
|
+
const canonical = normalisePath(path);
|
|
411
|
+
cancelAutoRetry(canonical);
|
|
412
|
+
if (canonical === "") await loadRoot();
|
|
351
413
|
else await loadChildren(path);
|
|
352
414
|
},
|
|
353
|
-
[loadRoot, loadChildren]
|
|
415
|
+
[loadRoot, loadChildren, cancelAutoRetry]
|
|
354
416
|
);
|
|
355
417
|
const refreshRef = useRef(refresh);
|
|
356
418
|
refreshRef.current = refresh;
|
|
@@ -361,6 +423,7 @@ function useFileTree(provider, metadataRefreshKey, metadataRefreshPath) {
|
|
|
361
423
|
},
|
|
362
424
|
[loadChildren, loadRoot]
|
|
363
425
|
);
|
|
426
|
+
autoRetryLoadRef.current = refreshDirectory;
|
|
364
427
|
const previousMetadataRefreshKeyRef = useRef(metadataRefreshKey);
|
|
365
428
|
useEffect(() => {
|
|
366
429
|
if (Object.is(previousMetadataRefreshKeyRef.current, metadataRefreshKey)) return;
|
|
@@ -537,12 +600,13 @@ function useFileTree(provider, metadataRefreshKey, metadataRefreshPath) {
|
|
|
537
600
|
setExpanded(nextExpanded);
|
|
538
601
|
setChildEntries(/* @__PURE__ */ new Map());
|
|
539
602
|
setChildIssues(/* @__PURE__ */ new Map());
|
|
603
|
+
cancelAllAutoRetries();
|
|
540
604
|
await loadRoot();
|
|
541
605
|
for (const dirPath of nextExpanded) {
|
|
542
606
|
await loadChildren(dirPath);
|
|
543
607
|
}
|
|
544
608
|
},
|
|
545
|
-
[selectedPath, entries, childEntries, expanded, loadRoot, loadChildren]
|
|
609
|
+
[selectedPath, entries, childEntries, expanded, loadRoot, loadChildren, cancelAllAutoRetries]
|
|
546
610
|
);
|
|
547
611
|
return {
|
|
548
612
|
entries,
|
|
@@ -783,6 +847,11 @@ function FileTreeNode({
|
|
|
783
847
|
}) {
|
|
784
848
|
const [renaming, setRenaming] = useState2(false);
|
|
785
849
|
const [renameValue, setRenameValue] = useState2(entry.name);
|
|
850
|
+
const readIssue2 = entry.kind === "file" ? entry.readIssue : void 0;
|
|
851
|
+
const rowStatus = [
|
|
852
|
+
badge?.label,
|
|
853
|
+
readIssue2 ? `could not be read: ${readIssue2.message}` : void 0
|
|
854
|
+
].filter((part) => part !== void 0);
|
|
786
855
|
const [showContext, setShowContext] = useState2(false);
|
|
787
856
|
const [contextPos, setContextPos] = useState2({ x: 0, y: 0 });
|
|
788
857
|
const [actionError, setActionError] = useState2(null);
|
|
@@ -1029,7 +1098,7 @@ function FileTreeNode({
|
|
|
1029
1098
|
"data-path": entry.path,
|
|
1030
1099
|
"aria-expanded": isDir ? expanded : void 0,
|
|
1031
1100
|
"aria-selected": selected,
|
|
1032
|
-
"aria-label":
|
|
1101
|
+
"aria-label": rowStatus.length > 0 ? `${entry.name}, ${rowStatus.join(", ")}` : void 0,
|
|
1033
1102
|
"aria-level": depth + 1,
|
|
1034
1103
|
"aria-posinset": posInSet,
|
|
1035
1104
|
"aria-setsize": setSize,
|
|
@@ -1081,6 +1150,15 @@ function FileTreeNode({
|
|
|
1081
1150
|
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1082
1151
|
/* @__PURE__ */ jsx2("span", { className: "db-tree-label", children: displayFileName(entry.name) }),
|
|
1083
1152
|
badge && /* @__PURE__ */ jsx2("span", { className: `db-git-badge db-git-badge--${badge.kind}`, "aria-hidden": "true", children: badge.glyph }),
|
|
1153
|
+
readIssue2 && /* @__PURE__ */ jsx2(
|
|
1154
|
+
"span",
|
|
1155
|
+
{
|
|
1156
|
+
className: "db-tree-read-issue",
|
|
1157
|
+
title: `Could not read this file: ${readIssue2.message}`,
|
|
1158
|
+
"aria-hidden": "true",
|
|
1159
|
+
children: "!"
|
|
1160
|
+
}
|
|
1161
|
+
),
|
|
1084
1162
|
entry.kind === "file" && entry.lastModified && /* @__PURE__ */ jsx2(LastModifiedTime, { value: entry.lastModified }),
|
|
1085
1163
|
/* @__PURE__ */ jsx2(
|
|
1086
1164
|
"button",
|
|
@@ -1712,6 +1790,7 @@ import {
|
|
|
1712
1790
|
FsError as FsError3,
|
|
1713
1791
|
SQUISQ_RUNTIME_DIRECTORY_NAME,
|
|
1714
1792
|
getFileSystemProviderV2 as getFileSystemProviderV23,
|
|
1793
|
+
findWikiArticle,
|
|
1715
1794
|
parseWorkspacePath as parseWorkspacePath3
|
|
1716
1795
|
} from "@bendyline/docblocks/filesystem";
|
|
1717
1796
|
import {
|
|
@@ -2144,10 +2223,7 @@ async function writeRuntimeIfNeeded(provider, runtimePath) {
|
|
|
2144
2223
|
if (current !== PLAYER_BUNDLE) await writeProviderText(provider, runtimePath, PLAYER_BUNDLE);
|
|
2145
2224
|
}
|
|
2146
2225
|
async function renderPlainOutsideInHtml(provider, layout, markdown, themeId) {
|
|
2147
|
-
const
|
|
2148
|
-
import("@bendyline/squisq/markdown"),
|
|
2149
|
-
import("@bendyline/squisq-formats/html")
|
|
2150
|
-
]);
|
|
2226
|
+
const { markdownDocToPlainHtml } = await import("@bendyline/squisq-formats/html");
|
|
2151
2227
|
const container = new FileSystemContentContainer(provider, layout.companionDirectory);
|
|
2152
2228
|
const images = /* @__PURE__ */ new Map();
|
|
2153
2229
|
for (const entry of await container.listFiles()) {
|
|
@@ -2156,7 +2232,7 @@ async function renderPlainOutsideInHtml(provider, layout, markdown, themeId) {
|
|
|
2156
2232
|
images.set(`./${entry.path}`, outputPath);
|
|
2157
2233
|
}
|
|
2158
2234
|
return new TextEncoder().encode(
|
|
2159
|
-
markdownDocToPlainHtml(
|
|
2235
|
+
markdownDocToPlainHtml(markdown, {
|
|
2160
2236
|
title: layout.stem,
|
|
2161
2237
|
images: images.size > 0 ? images : void 0,
|
|
2162
2238
|
...themeId ? { themeId } : {}
|
|
@@ -2166,9 +2242,22 @@ async function renderPlainOutsideInHtml(provider, layout, markdown, themeId) {
|
|
|
2166
2242
|
async function prepareOutsideInRender(provider, layout, markdown, render) {
|
|
2167
2243
|
const themeId = await resolveFallbackRenderTheme(markdown, render);
|
|
2168
2244
|
const htmlOutput = layout.format === "html" ? await readOutsideInHtmlOutput(markdown) : null;
|
|
2245
|
+
let renderedSource = markdown;
|
|
2246
|
+
if (layout.format === "html") {
|
|
2247
|
+
const { parseMarkdown, resolveWikiLinks } = await import("@bendyline/squisq/markdown");
|
|
2248
|
+
renderedSource = await resolveWikiLinks(parseMarkdown(markdown), async (target) => {
|
|
2249
|
+
const article = await findWikiArticle(provider, layout.targetPath, target, ".html");
|
|
2250
|
+
return article.exists ? article.relativePath.split("/").map(encodeURIComponent).join("/") : null;
|
|
2251
|
+
});
|
|
2252
|
+
}
|
|
2169
2253
|
if (htmlOutput === "static") {
|
|
2170
2254
|
return {
|
|
2171
|
-
bytes: await renderPlainOutsideInHtml(
|
|
2255
|
+
bytes: await renderPlainOutsideInHtml(
|
|
2256
|
+
provider,
|
|
2257
|
+
layout,
|
|
2258
|
+
renderedSource,
|
|
2259
|
+
themeId
|
|
2260
|
+
),
|
|
2172
2261
|
runtimePath: null
|
|
2173
2262
|
};
|
|
2174
2263
|
}
|
|
@@ -2176,7 +2265,7 @@ async function prepareOutsideInRender(provider, layout, markdown, render) {
|
|
|
2176
2265
|
const outputDirectory = dirname(layout.targetPath);
|
|
2177
2266
|
const rendered = await renderOutsideInDocument(
|
|
2178
2267
|
{
|
|
2179
|
-
markdown,
|
|
2268
|
+
markdown: renderedSource,
|
|
2180
2269
|
targetPath: layout.targetPath,
|
|
2181
2270
|
container: new FileSystemContentContainer(provider, layout.companionDirectory)
|
|
2182
2271
|
},
|
|
@@ -2411,6 +2500,10 @@ var NEW_ITEM_HINT_ID = "db-new-item-hint";
|
|
|
2411
2500
|
function normalisePath2(path) {
|
|
2412
2501
|
return parseWorkspacePath4(path);
|
|
2413
2502
|
}
|
|
2503
|
+
function readIssueText(issue) {
|
|
2504
|
+
const failingPath = tryParseWorkspacePath2(issue.path);
|
|
2505
|
+
return failingPath && failingPath !== issue.directoryPath ? `${failingPath}: ${issue.message}` : issue.message;
|
|
2506
|
+
}
|
|
2414
2507
|
function hasEquivalentPath2(paths, path) {
|
|
2415
2508
|
const canonical = normalisePath2(path);
|
|
2416
2509
|
return paths.has(path) || paths.has(canonical) || canonical !== "" && paths.has(`/${canonical}`);
|
|
@@ -2443,6 +2536,7 @@ function isInternalDrag(dataTransfer) {
|
|
|
2443
2536
|
}
|
|
2444
2537
|
function FileExplorer({
|
|
2445
2538
|
provider,
|
|
2539
|
+
loading = false,
|
|
2446
2540
|
metadataRefreshKey,
|
|
2447
2541
|
activeFilePath,
|
|
2448
2542
|
sortMode,
|
|
@@ -2874,7 +2968,7 @@ function FileExplorer({
|
|
|
2874
2968
|
role: "alert",
|
|
2875
2969
|
"data-directory-path": childIssue.directoryPath,
|
|
2876
2970
|
children: [
|
|
2877
|
-
/* @__PURE__ */ jsx5("span", { children: childIssue
|
|
2971
|
+
/* @__PURE__ */ jsx5("span", { children: readIssueText(childIssue) }),
|
|
2878
2972
|
" ",
|
|
2879
2973
|
/* @__PURE__ */ jsx5(
|
|
2880
2974
|
"button",
|
|
@@ -3155,7 +3249,7 @@ function FileExplorer({
|
|
|
3155
3249
|
role: "alert",
|
|
3156
3250
|
"data-directory-path": tree.rootIssue.directoryPath,
|
|
3157
3251
|
children: [
|
|
3158
|
-
/* @__PURE__ */ jsx5("span", { children: tree.rootIssue
|
|
3252
|
+
/* @__PURE__ */ jsx5("span", { children: readIssueText(tree.rootIssue) }),
|
|
3159
3253
|
" ",
|
|
3160
3254
|
/* @__PURE__ */ jsx5(
|
|
3161
3255
|
"button",
|
|
@@ -3169,7 +3263,7 @@ function FileExplorer({
|
|
|
3169
3263
|
]
|
|
3170
3264
|
}
|
|
3171
3265
|
),
|
|
3172
|
-
tree.loading ? /* @__PURE__ */ jsx5("div", { className: "db-tree", role: "status", "aria-live": "polite", children: /* @__PURE__ */ jsx5("div", { className: "db-tree-loading", children: "Loading..." }) }) : filterVisibleFileEntries(tree.entries).length === 0 ? /* @__PURE__ */ jsx5("div", { className: "db-tree", children: /* @__PURE__ */ jsx5("div", { className: "db-tree-empty", children: "No files yet" }) }) : /* @__PURE__ */ jsx5(
|
|
3266
|
+
tree.loading || loading ? /* @__PURE__ */ jsx5("div", { className: "db-tree", role: "status", "aria-live": "polite", children: /* @__PURE__ */ jsx5("div", { className: "db-tree-loading", children: "Loading..." }) }) : filterVisibleFileEntries(tree.entries).length === 0 ? /* @__PURE__ */ jsx5("div", { className: "db-tree", children: /* @__PURE__ */ jsx5("div", { className: "db-tree-empty", children: "No files yet" }) }) : /* @__PURE__ */ jsx5(
|
|
3173
3267
|
"div",
|
|
3174
3268
|
{
|
|
3175
3269
|
ref: treeRef,
|
|
@@ -3236,6 +3330,7 @@ function WorkspacePicker({
|
|
|
3236
3330
|
onCloneRepository,
|
|
3237
3331
|
onRemoveWorkspace,
|
|
3238
3332
|
refreshKey,
|
|
3333
|
+
loading = false,
|
|
3239
3334
|
className
|
|
3240
3335
|
}) {
|
|
3241
3336
|
const [workspaces, setWorkspaces] = useState5([]);
|
|
@@ -3392,7 +3487,7 @@ function WorkspacePicker({
|
|
|
3392
3487
|
}
|
|
3393
3488
|
}, [newWorkspaceName, newWorkspacePending, onSelect, refresh, workspaces]);
|
|
3394
3489
|
const activeWs = workspaces.find((w) => w.id === activeWorkspaceId);
|
|
3395
|
-
const activeWorkspaceName = activeWs?.name ?? "No workspace";
|
|
3490
|
+
const activeWorkspaceName = activeWs?.name ?? (loading ? "Loading\u2026" : "No workspace");
|
|
3396
3491
|
return /* @__PURE__ */ jsxs5("div", { ref: pickerRef, className: `db-workspace-picker ${className ?? ""}`, children: [
|
|
3397
3492
|
/* @__PURE__ */ jsxs5(
|
|
3398
3493
|
"button",
|
|
@@ -3679,13 +3774,15 @@ import {
|
|
|
3679
3774
|
FileSystemContentContainer as FileSystemContentContainer2,
|
|
3680
3775
|
createFileMediaProvider,
|
|
3681
3776
|
decodeUtf8Text,
|
|
3682
|
-
FsError as
|
|
3683
|
-
getFileSystemProviderV2 as
|
|
3777
|
+
FsError as FsError6,
|
|
3778
|
+
getFileSystemProviderV2 as getFileSystemProviderV211,
|
|
3684
3779
|
isQuotaExceededError,
|
|
3685
3780
|
moveFileSystemEntry as moveFileSystemEntry2,
|
|
3686
3781
|
rewriteCompanionReferences,
|
|
3687
3782
|
parseWorkspacePath as parseWorkspacePath8,
|
|
3688
|
-
workspacePathContains
|
|
3783
|
+
workspacePathContains,
|
|
3784
|
+
findWikiArticle as findWikiArticle2,
|
|
3785
|
+
suggestWikiArticles
|
|
3689
3786
|
} from "@bendyline/docblocks/filesystem";
|
|
3690
3787
|
import {
|
|
3691
3788
|
createFileSystemDocumentTarget as createFileSystemDocumentTarget2,
|
|
@@ -3708,12 +3805,14 @@ import {
|
|
|
3708
3805
|
getWorkspace,
|
|
3709
3806
|
listWorkspaces as listWorkspaces2,
|
|
3710
3807
|
reconcileElectronWorkspaceDescriptors,
|
|
3711
|
-
removeWorkspace,
|
|
3712
|
-
saveWorkspace as
|
|
3808
|
+
removeWorkspace as removeWorkspace2,
|
|
3809
|
+
saveWorkspace as saveWorkspace3,
|
|
3713
3810
|
touchWorkspace as touchWorkspace2,
|
|
3714
3811
|
registerTransientWorkspace,
|
|
3715
3812
|
getTransientWorkspace,
|
|
3716
|
-
unregisterTransientWorkspace
|
|
3813
|
+
unregisterTransientWorkspace,
|
|
3814
|
+
appendWorkspaceBackup,
|
|
3815
|
+
finishWorkspaceBackup
|
|
3717
3816
|
} from "@bendyline/docblocks/workspace";
|
|
3718
3817
|
|
|
3719
3818
|
// src/AppMenu/AppMenu.tsx
|
|
@@ -4034,17 +4133,6 @@ function SpeechSettingsControls({ speech }) {
|
|
|
4034
4133
|
] });
|
|
4035
4134
|
}
|
|
4036
4135
|
|
|
4037
|
-
// src/local-date.ts
|
|
4038
|
-
function localDateStamp(date) {
|
|
4039
|
-
const pad = (value) => String(value).padStart(2, "0");
|
|
4040
|
-
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
|
4041
|
-
}
|
|
4042
|
-
function displayBuildDate(value) {
|
|
4043
|
-
if (/^\d{4}-\d{2}-\d{2}$/.test(value)) return value;
|
|
4044
|
-
const instant = new Date(value);
|
|
4045
|
-
return Number.isNaN(instant.getTime()) ? value : localDateStamp(instant);
|
|
4046
|
-
}
|
|
4047
|
-
|
|
4048
4136
|
// src/AppMenu/AppMenu.tsx
|
|
4049
4137
|
import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
4050
4138
|
function formatBytes(bytes) {
|
|
@@ -4081,6 +4169,7 @@ function AppMenu({
|
|
|
4081
4169
|
onVersioningPreferenceChange,
|
|
4082
4170
|
onOpenWorkspaceSettings,
|
|
4083
4171
|
onDownloadAllWorkspaces,
|
|
4172
|
+
onRestoreBackup,
|
|
4084
4173
|
onShowKeyboardShortcuts,
|
|
4085
4174
|
onKeepBrowserData,
|
|
4086
4175
|
onInstallApp,
|
|
@@ -4099,7 +4188,8 @@ function AppMenu({
|
|
|
4099
4188
|
if (settingsRequest > 0) setShowSettings(true);
|
|
4100
4189
|
}, [settingsRequest]);
|
|
4101
4190
|
const [requestingPersistentStorage, setRequestingPersistentStorage] = useState7(false);
|
|
4102
|
-
const
|
|
4191
|
+
const surface = getHostEnvironment()?.surface ?? "web";
|
|
4192
|
+
const moreInformationUrl = MORE_INFORMATION_URLS[surface] ?? MORE_INFORMATION_URLS.web;
|
|
4103
4193
|
const containerRef = useRef8(null);
|
|
4104
4194
|
const { menuRef, triggerRef, handleMenuKeyDown, handleTriggerKeyDown, closeMenu } = useMenuKeyboard(isOpen, setIsOpen);
|
|
4105
4195
|
const [storageEstimate, setStorageEstimate] = useState7(null);
|
|
@@ -4214,7 +4304,7 @@ function AppMenu({
|
|
|
4214
4304
|
children: "Install DocBlocks\u2026"
|
|
4215
4305
|
}
|
|
4216
4306
|
),
|
|
4217
|
-
(onDownloadAllWorkspaces || onKeepBrowserData) && /* @__PURE__ */ jsx8("div", { className: "db-app-menu-divider" }),
|
|
4307
|
+
(onDownloadAllWorkspaces || onRestoreBackup || onKeepBrowserData) && /* @__PURE__ */ jsx8("div", { className: "db-app-menu-divider" }),
|
|
4218
4308
|
onDownloadAllWorkspaces && /* @__PURE__ */ jsx8(
|
|
4219
4309
|
"button",
|
|
4220
4310
|
{
|
|
@@ -4225,6 +4315,16 @@ function AppMenu({
|
|
|
4225
4315
|
children: "Back up all workspaces"
|
|
4226
4316
|
}
|
|
4227
4317
|
),
|
|
4318
|
+
onRestoreBackup && /* @__PURE__ */ jsx8(
|
|
4319
|
+
"button",
|
|
4320
|
+
{
|
|
4321
|
+
className: "db-app-menu-item",
|
|
4322
|
+
role: "menuitem",
|
|
4323
|
+
tabIndex: -1,
|
|
4324
|
+
onClick: () => handleAction(onRestoreBackup),
|
|
4325
|
+
children: "Restore backup\u2026"
|
|
4326
|
+
}
|
|
4327
|
+
),
|
|
4228
4328
|
onKeepBrowserData && /* @__PURE__ */ jsx8(
|
|
4229
4329
|
"button",
|
|
4230
4330
|
{
|
|
@@ -4400,22 +4500,6 @@ function AppMenu({
|
|
|
4400
4500
|
/* @__PURE__ */ jsx8("strong", { children: "DocBlocks" }),
|
|
4401
4501
|
" is a local-first Markdown document editor. Your files stay under your control."
|
|
4402
4502
|
] }),
|
|
4403
|
-
/* @__PURE__ */ jsxs7("aside", { className: "db-about-beta", children: [
|
|
4404
|
-
/* @__PURE__ */ jsx8("strong", { children: "Beta Software." }),
|
|
4405
|
-
" We're still working through initial hiccups and issues. Please bear with us, make sure you keep backups, and",
|
|
4406
|
-
" ",
|
|
4407
|
-
/* @__PURE__ */ jsx8(
|
|
4408
|
-
"a",
|
|
4409
|
-
{
|
|
4410
|
-
href: "https://github.com/bendyline/docblocks/issues/new",
|
|
4411
|
-
target: "_blank",
|
|
4412
|
-
rel: "noopener noreferrer",
|
|
4413
|
-
children: "open issues"
|
|
4414
|
-
}
|
|
4415
|
-
),
|
|
4416
|
-
" ",
|
|
4417
|
-
"where you find them. Thanks!"
|
|
4418
|
-
] }),
|
|
4419
4503
|
appVersion && /* @__PURE__ */ jsxs7("p", { className: "db-about-version", children: [
|
|
4420
4504
|
/* @__PURE__ */ jsx8("span", { children: "Version" }),
|
|
4421
4505
|
/* @__PURE__ */ jsx8("code", { "aria-label": `DocBlocks version ${appVersion}`, children: appVersion })
|
|
@@ -4434,6 +4518,12 @@ function AppMenu({
|
|
|
4434
4518
|
/* @__PURE__ */ jsx8("a", { href: "https://bendyline.com", target: "_blank", rel: "noopener noreferrer", children: "Bendyline" }),
|
|
4435
4519
|
"."
|
|
4436
4520
|
] }),
|
|
4521
|
+
surface === "web" && /* @__PURE__ */ jsxs7("p", { children: [
|
|
4522
|
+
"See our free desktop apps at",
|
|
4523
|
+
" ",
|
|
4524
|
+
/* @__PURE__ */ jsx8("a", { href: MORE_INFORMATION_URLS.electron, target: "_blank", rel: "noopener noreferrer", children: "docblocks.com/desktop" }),
|
|
4525
|
+
"."
|
|
4526
|
+
] }),
|
|
4437
4527
|
/* @__PURE__ */ jsxs7("p", { className: "db-dialog-links", children: [
|
|
4438
4528
|
/* @__PURE__ */ jsx8("a", { href: moreInformationUrl, target: "_blank", rel: "noopener noreferrer", children: "More information..." }),
|
|
4439
4529
|
/* @__PURE__ */ jsx8(
|
|
@@ -4486,6 +4576,59 @@ function AppMenu({
|
|
|
4486
4576
|
] });
|
|
4487
4577
|
}
|
|
4488
4578
|
|
|
4579
|
+
// src/DocBlocksShell/restore-backup.ts
|
|
4580
|
+
import {
|
|
4581
|
+
readWorkspaceBackup,
|
|
4582
|
+
restoreWorkspaceBackup,
|
|
4583
|
+
WORKSPACE_BACKUP_LIMITS,
|
|
4584
|
+
saveWorkspace as saveWorkspace2,
|
|
4585
|
+
removeWorkspace
|
|
4586
|
+
} from "@bendyline/docblocks/workspace";
|
|
4587
|
+
async function restoreBrowserBackup(file) {
|
|
4588
|
+
if (file.size > 256 * 1024 * 1024) throw new Error("Backup ZIPs must be smaller than 256 MiB.");
|
|
4589
|
+
const { zipToContainer } = await import("@bendyline/squisq-formats/container");
|
|
4590
|
+
const container = await zipToContainer(await file.arrayBuffer(), WORKSPACE_BACKUP_LIMITS);
|
|
4591
|
+
const workspaces = await readWorkspaceBackup(
|
|
4592
|
+
container,
|
|
4593
|
+
file.name.replace(/\.zip$/i, "") || "Workspace"
|
|
4594
|
+
);
|
|
4595
|
+
const { IndexedDBFileSystemProvider, deleteIndexedDBWorkspaceData } = await import("@bendyline/docblocks/filesystem/indexeddb");
|
|
4596
|
+
const staged = [];
|
|
4597
|
+
try {
|
|
4598
|
+
for (const workspace of workspaces) {
|
|
4599
|
+
const descriptor = {
|
|
4600
|
+
id: `restored-${crypto.randomUUID()}`,
|
|
4601
|
+
name: `${workspace.name.slice(0, 1013)} (restored)`,
|
|
4602
|
+
type: "indexeddb",
|
|
4603
|
+
lastOpened: (/* @__PURE__ */ new Date()).toISOString()
|
|
4604
|
+
};
|
|
4605
|
+
const provider = new IndexedDBFileSystemProvider(descriptor.id, descriptor.name).v2;
|
|
4606
|
+
staged.push({ descriptor, provider });
|
|
4607
|
+
await restoreWorkspaceBackup(workspace, provider);
|
|
4608
|
+
}
|
|
4609
|
+
for (const { descriptor } of staged) await saveWorkspace2(descriptor);
|
|
4610
|
+
return staged.map(({ descriptor }) => descriptor);
|
|
4611
|
+
} catch (error) {
|
|
4612
|
+
const failures = [error];
|
|
4613
|
+
for (const { descriptor, provider } of staged) {
|
|
4614
|
+
try {
|
|
4615
|
+
await provider.dispose();
|
|
4616
|
+
await removeWorkspace(descriptor.id);
|
|
4617
|
+
await deleteIndexedDBWorkspaceData(descriptor.id);
|
|
4618
|
+
} catch (cleanupError) {
|
|
4619
|
+
failures.push(cleanupError);
|
|
4620
|
+
}
|
|
4621
|
+
}
|
|
4622
|
+
if (failures.length > 1)
|
|
4623
|
+
throw new Error(
|
|
4624
|
+
`Restore failed; temporary workspace cleanup also failed. ${failures.map((failure) => failure instanceof Error ? failure.message : String(failure)).join("; ")}`
|
|
4625
|
+
);
|
|
4626
|
+
throw error;
|
|
4627
|
+
} finally {
|
|
4628
|
+
for (const { provider } of staged) await provider.dispose();
|
|
4629
|
+
}
|
|
4630
|
+
}
|
|
4631
|
+
|
|
4489
4632
|
// src/WorkspacePicker/WorkspaceSettingsButton.tsx
|
|
4490
4633
|
import { useState as useState8, useCallback as useCallback9, useRef as useRef9, useEffect as useEffect9 } from "react";
|
|
4491
4634
|
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
@@ -5008,7 +5151,7 @@ function useDocumentSession(autoSaveDelayMs = 500) {
|
|
|
5008
5151
|
import { lazy, Suspense } from "react";
|
|
5009
5152
|
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
5010
5153
|
var ExportToolbarControlsImplementation = lazy(
|
|
5011
|
-
() => import("./ExportToolbarControls-
|
|
5154
|
+
() => import("./ExportToolbarControls-HOV424TO.js").then((module) => ({
|
|
5012
5155
|
default: module.ExportToolbarControls
|
|
5013
5156
|
}))
|
|
5014
5157
|
);
|
|
@@ -5578,7 +5721,7 @@ function resolveShellEditorLinkTarget(href, documentPath) {
|
|
|
5578
5721
|
targetSegments.push(segment);
|
|
5579
5722
|
}
|
|
5580
5723
|
const path = targetSegments.join("/");
|
|
5581
|
-
if (!path || path.length > HOST_WIRE_LIMITS2.pathCharacters || !isMarkdownFileName(path)) {
|
|
5724
|
+
if (!path || path.length > HOST_WIRE_LIMITS2.pathCharacters || !isMarkdownFileName(path) && !/\.html?$/i.test(path)) {
|
|
5582
5725
|
return null;
|
|
5583
5726
|
}
|
|
5584
5727
|
return { kind: "workspace", path };
|
|
@@ -5601,10 +5744,36 @@ function hasControlCharacter(value) {
|
|
|
5601
5744
|
return false;
|
|
5602
5745
|
}
|
|
5603
5746
|
|
|
5604
|
-
// src/DocBlocksShell/
|
|
5747
|
+
// src/DocBlocksShell/wiki-articles.ts
|
|
5605
5748
|
import {
|
|
5749
|
+
ensureWikiArticle,
|
|
5750
|
+
wikiArticleExists,
|
|
5606
5751
|
FsError as FsError4,
|
|
5607
|
-
getFileSystemProviderV2 as getFileSystemProviderV27
|
|
5752
|
+
getFileSystemProviderV2 as getFileSystemProviderV27
|
|
5753
|
+
} from "@bendyline/docblocks/filesystem";
|
|
5754
|
+
function wikiArticleExtension(format) {
|
|
5755
|
+
return newFileHtmlOutput(format) ? ".html" : ".md";
|
|
5756
|
+
}
|
|
5757
|
+
async function ensureShellWikiArticle(provider, path, format, render) {
|
|
5758
|
+
if (!/\.html?$/i.test(path)) return ensureWikiArticle(provider, path);
|
|
5759
|
+
if (await wikiArticleExists(provider, path)) return false;
|
|
5760
|
+
if (!getFileSystemProviderV27(provider)) {
|
|
5761
|
+
throw new FsError4("not-supported", "This workspace cannot create articles safely.");
|
|
5762
|
+
}
|
|
5763
|
+
try {
|
|
5764
|
+
await createNewOutsideInDocument(provider, path, newFileHtmlOutput(format), render);
|
|
5765
|
+
return true;
|
|
5766
|
+
} catch (error) {
|
|
5767
|
+
if (error instanceof FsError4 && (error.code === "already-exists" || error.code === "conflict") && await wikiArticleExists(provider, path))
|
|
5768
|
+
return false;
|
|
5769
|
+
throw error;
|
|
5770
|
+
}
|
|
5771
|
+
}
|
|
5772
|
+
|
|
5773
|
+
// src/DocBlocksShell/import-files.ts
|
|
5774
|
+
import {
|
|
5775
|
+
FsError as FsError5,
|
|
5776
|
+
getFileSystemProviderV2 as getFileSystemProviderV28,
|
|
5608
5777
|
parseWorkspacePath as parseWorkspacePath6
|
|
5609
5778
|
} from "@bendyline/docblocks/filesystem";
|
|
5610
5779
|
var MAX_NAME_ATTEMPTS = 100;
|
|
@@ -5615,7 +5784,7 @@ function withCopySuffix(path, n) {
|
|
|
5615
5784
|
return `${path.slice(0, dot)} (${n})${path.slice(dot)}`;
|
|
5616
5785
|
}
|
|
5617
5786
|
function isAlreadyExists(error) {
|
|
5618
|
-
return error instanceof
|
|
5787
|
+
return error instanceof FsError5 && error.code === "already-exists";
|
|
5619
5788
|
}
|
|
5620
5789
|
async function claimAvailablePath(provider, desiredPath) {
|
|
5621
5790
|
for (let attempt = 1; attempt <= MAX_NAME_ATTEMPTS; attempt++) {
|
|
@@ -5630,7 +5799,7 @@ async function claimAvailablePath(provider, desiredPath) {
|
|
|
5630
5799
|
throw new Error(`Too many documents are already named like \u201C${desiredPath}\u201D.`);
|
|
5631
5800
|
}
|
|
5632
5801
|
async function writeProviderBytes(provider, path, data, mode) {
|
|
5633
|
-
const providerV2 =
|
|
5802
|
+
const providerV2 = getFileSystemProviderV28(provider);
|
|
5634
5803
|
if (providerV2) {
|
|
5635
5804
|
await providerV2.writeFile(parseWorkspacePath6(path), data, {
|
|
5636
5805
|
mode,
|
|
@@ -5640,7 +5809,7 @@ async function writeProviderBytes(provider, path, data, mode) {
|
|
|
5640
5809
|
return;
|
|
5641
5810
|
}
|
|
5642
5811
|
if (mode === "create" && await providerEntryExists(provider, path)) {
|
|
5643
|
-
throw new
|
|
5812
|
+
throw new FsError5("already-exists", "File already exists.", { operation: "write", path });
|
|
5644
5813
|
}
|
|
5645
5814
|
await provider.writeBinary(path, data);
|
|
5646
5815
|
}
|
|
@@ -5673,7 +5842,7 @@ function directoriesUnder(files, root) {
|
|
|
5673
5842
|
return [...directories].sort((a, b) => b.split("/").length - a.split("/").length);
|
|
5674
5843
|
}
|
|
5675
5844
|
async function removeIfEmptyDirectory(provider, path) {
|
|
5676
|
-
const providerV2 =
|
|
5845
|
+
const providerV2 = getFileSystemProviderV28(provider);
|
|
5677
5846
|
if (!providerV2) return;
|
|
5678
5847
|
await providerV2.remove(parseWorkspacePath6(path), { recursive: false, missing: "ignore" }).catch(() => void 0);
|
|
5679
5848
|
}
|
|
@@ -6050,37 +6219,8 @@ function resolveShellTheme({
|
|
|
6050
6219
|
return osTheme;
|
|
6051
6220
|
}
|
|
6052
6221
|
|
|
6053
|
-
// src/DocBlocksShell/issue-report.ts
|
|
6054
|
-
var NEW_ISSUE_URL = "https://github.com/bendyline/docblocks/issues/new";
|
|
6055
|
-
var VERSION_VALUE_LIMIT = 128;
|
|
6056
|
-
var USER_AGENT_VALUE_LIMIT = 512;
|
|
6057
|
-
function normalizeEnvironmentValue(value, fallback, limit) {
|
|
6058
|
-
const normalized = value.replace(/[\r\n]+/g, " ").trim().slice(0, limit);
|
|
6059
|
-
return normalized || fallback;
|
|
6060
|
-
}
|
|
6061
|
-
function buildIssueReportUrl(environment) {
|
|
6062
|
-
const body = [
|
|
6063
|
-
"## Description",
|
|
6064
|
-
"",
|
|
6065
|
-
"<!-- What happened, and what did you expect? -->",
|
|
6066
|
-
"",
|
|
6067
|
-
"## Environment",
|
|
6068
|
-
"",
|
|
6069
|
-
`- Date: ${localDateStamp(environment.reportedAt)}`,
|
|
6070
|
-
`- DocBlocks: ${normalizeEnvironmentValue(environment.version, "unknown", VERSION_VALUE_LIMIT)}`,
|
|
6071
|
-
`- User agent: ${normalizeEnvironmentValue(
|
|
6072
|
-
environment.userAgent,
|
|
6073
|
-
"unavailable",
|
|
6074
|
-
USER_AGENT_VALUE_LIMIT
|
|
6075
|
-
)}`
|
|
6076
|
-
].join("\n");
|
|
6077
|
-
const url = new URL(NEW_ISSUE_URL);
|
|
6078
|
-
url.searchParams.set("body", body);
|
|
6079
|
-
return url.href;
|
|
6080
|
-
}
|
|
6081
|
-
|
|
6082
6222
|
// src/DocBlocksShell/last-state.ts
|
|
6083
|
-
import { tryParseWorkspacePath as
|
|
6223
|
+
import { tryParseWorkspacePath as tryParseWorkspacePath3 } from "@bendyline/docblocks/filesystem";
|
|
6084
6224
|
var LAST_STATE_KEY = "docblocks:lastState";
|
|
6085
6225
|
var MAX_WORKSPACE_ID_CHARACTERS = 256;
|
|
6086
6226
|
var MAX_WORKSPACE_PATH_CHARACTERS = 4096;
|
|
@@ -6101,7 +6241,7 @@ function parseLastState(value) {
|
|
|
6101
6241
|
if (!hasExactKeys(record, ["workspaceId", "filePath", "view"])) return null;
|
|
6102
6242
|
if (!isBoundedText(record.workspaceId, MAX_WORKSPACE_ID_CHARACTERS)) return null;
|
|
6103
6243
|
if (!isBoundedText(record.filePath, MAX_WORKSPACE_PATH_CHARACTERS)) return null;
|
|
6104
|
-
const parsedPath =
|
|
6244
|
+
const parsedPath = tryParseWorkspacePath3(record.filePath);
|
|
6105
6245
|
if (!parsedPath) return null;
|
|
6106
6246
|
if (typeof record.view !== "string" || !EDITOR_VIEWS.has(record.view)) return null;
|
|
6107
6247
|
return {
|
|
@@ -6733,6 +6873,104 @@ function UpdateAvailableNotice({
|
|
|
6733
6873
|
] });
|
|
6734
6874
|
}
|
|
6735
6875
|
|
|
6876
|
+
// src/DocBlocksShell/WelcomeScreen.tsx
|
|
6877
|
+
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
6878
|
+
var WELCOME_HEADLINE = "The Markdown editor that turns one file into anything.";
|
|
6879
|
+
var WELCOME_SUMMARY = "Write the way you normally would, then share the same file as a PDF, a Word document, a slide deck, or a video.";
|
|
6880
|
+
var WELCOME_PRIVACY_NOTE = "No account, and your documents stay on this device.";
|
|
6881
|
+
var DOCBLOCKS_APPS_URL = "https://docblocks.com/desktop/";
|
|
6882
|
+
function WelcomeScreen({
|
|
6883
|
+
onCreateDocument,
|
|
6884
|
+
onTour,
|
|
6885
|
+
onDismiss,
|
|
6886
|
+
offerApps = false
|
|
6887
|
+
}) {
|
|
6888
|
+
return /* @__PURE__ */ jsxs15("section", { className: "db-welcome-gateway", "aria-labelledby": "db-welcome-gateway-title", children: [
|
|
6889
|
+
/* @__PURE__ */ jsx17(
|
|
6890
|
+
"button",
|
|
6891
|
+
{
|
|
6892
|
+
type: "button",
|
|
6893
|
+
className: "db-welcome-gateway-dismiss",
|
|
6894
|
+
onClick: onDismiss,
|
|
6895
|
+
"aria-label": "Dismiss welcome",
|
|
6896
|
+
title: "Dismiss",
|
|
6897
|
+
children: "\xD7"
|
|
6898
|
+
}
|
|
6899
|
+
),
|
|
6900
|
+
/* @__PURE__ */ jsxs15("div", { className: "db-welcome-gateway-body", children: [
|
|
6901
|
+
/* @__PURE__ */ jsxs15("div", { className: "db-welcome-gateway-copy", children: [
|
|
6902
|
+
/* @__PURE__ */ jsx17("p", { className: "db-welcome-gateway-eyebrow", children: "Welcome to DocBlocks" }),
|
|
6903
|
+
/* @__PURE__ */ jsx17("h1", { id: "db-welcome-gateway-title", children: WELCOME_HEADLINE }),
|
|
6904
|
+
/* @__PURE__ */ jsx17("p", { children: WELCOME_SUMMARY }),
|
|
6905
|
+
/* @__PURE__ */ jsx17("p", { className: "db-welcome-gateway-note", children: WELCOME_PRIVACY_NOTE }),
|
|
6906
|
+
/* @__PURE__ */ jsxs15("div", { className: "db-welcome-gateway-actions", children: [
|
|
6907
|
+
/* @__PURE__ */ jsx17("button", { type: "button", className: "db-welcome-gateway-primary", onClick: onCreateDocument, children: "Create a document" }),
|
|
6908
|
+
/* @__PURE__ */ jsx17("button", { type: "button", className: "db-welcome-gateway-cta", onClick: onTour, children: "Tour the welcome document" }),
|
|
6909
|
+
offerApps && /* @__PURE__ */ jsx17(
|
|
6910
|
+
"a",
|
|
6911
|
+
{
|
|
6912
|
+
className: "db-welcome-gateway-apps",
|
|
6913
|
+
href: DOCBLOCKS_APPS_URL,
|
|
6914
|
+
target: "_blank",
|
|
6915
|
+
rel: "noopener noreferrer",
|
|
6916
|
+
children: "Check out the DocBlocks apps"
|
|
6917
|
+
}
|
|
6918
|
+
)
|
|
6919
|
+
] })
|
|
6920
|
+
] }),
|
|
6921
|
+
/* @__PURE__ */ jsx17(WelcomeLoop, {})
|
|
6922
|
+
] })
|
|
6923
|
+
] });
|
|
6924
|
+
}
|
|
6925
|
+
function WelcomeLoop() {
|
|
6926
|
+
return /* @__PURE__ */ jsxs15("div", { className: "db-welcome-loop", "aria-hidden": "true", children: [
|
|
6927
|
+
/* @__PURE__ */ jsxs15("div", { className: "db-welcome-loop-source", children: [
|
|
6928
|
+
/* @__PURE__ */ jsx17("span", { className: "db-welcome-loop-file", children: "Lisbon.md" }),
|
|
6929
|
+
/* @__PURE__ */ jsxs15("code", { children: [
|
|
6930
|
+
/* @__PURE__ */ jsx17("span", { className: "db-welcome-loop-mark", children: "# " }),
|
|
6931
|
+
"Lisbon in three days",
|
|
6932
|
+
"\n",
|
|
6933
|
+
"Trams, tiles, and pastries.",
|
|
6934
|
+
"\n\n",
|
|
6935
|
+
/* @__PURE__ */ jsx17("span", { className: "db-welcome-loop-mark", children: "## " }),
|
|
6936
|
+
"Day one",
|
|
6937
|
+
"\n",
|
|
6938
|
+
/* @__PURE__ */ jsx17("span", { className: "db-welcome-loop-mark", children: "- " }),
|
|
6939
|
+
"Ride Tram 28",
|
|
6940
|
+
"\n",
|
|
6941
|
+
/* @__PURE__ */ jsx17("span", { className: "db-welcome-loop-mark", children: "- " }),
|
|
6942
|
+
"Sunset at Gra\xE7a"
|
|
6943
|
+
] })
|
|
6944
|
+
] }),
|
|
6945
|
+
/* @__PURE__ */ jsx17("div", { className: "db-welcome-loop-arrow", children: "\u2192" }),
|
|
6946
|
+
/* @__PURE__ */ jsxs15("div", { className: "db-welcome-loop-stage", children: [
|
|
6947
|
+
/* @__PURE__ */ jsxs15("div", { className: "db-welcome-loop-frame db-welcome-loop-frame--page", children: [
|
|
6948
|
+
/* @__PURE__ */ jsx17("strong", { children: "Lisbon in three days" }),
|
|
6949
|
+
/* @__PURE__ */ jsx17("span", { children: "Trams, tiles, and pastries." }),
|
|
6950
|
+
/* @__PURE__ */ jsx17("em", { children: "Day one" }),
|
|
6951
|
+
/* @__PURE__ */ jsx17("span", { children: "\u2022 Ride Tram 28" }),
|
|
6952
|
+
/* @__PURE__ */ jsx17("span", { children: "\u2022 Sunset at Gra\xE7a" })
|
|
6953
|
+
] }),
|
|
6954
|
+
/* @__PURE__ */ jsxs15("div", { className: "db-welcome-loop-frame db-welcome-loop-frame--slide", children: [
|
|
6955
|
+
/* @__PURE__ */ jsx17("strong", { children: "Lisbon in three days" }),
|
|
6956
|
+
/* @__PURE__ */ jsx17("span", { children: "Trams, tiles, and pastries." })
|
|
6957
|
+
] }),
|
|
6958
|
+
/* @__PURE__ */ jsxs15("div", { className: "db-welcome-loop-frame db-welcome-loop-frame--video", children: [
|
|
6959
|
+
/* @__PURE__ */ jsx17("em", { children: "Day one" }),
|
|
6960
|
+
/* @__PURE__ */ jsx17("span", { children: "\u2022 Ride Tram 28" }),
|
|
6961
|
+
/* @__PURE__ */ jsx17("span", { children: "\u2022 Sunset at Gra\xE7a" }),
|
|
6962
|
+
/* @__PURE__ */ jsx17("i", { className: "db-welcome-loop-play", children: "\u25B6" }),
|
|
6963
|
+
/* @__PURE__ */ jsx17("i", { className: "db-welcome-loop-progress" })
|
|
6964
|
+
] })
|
|
6965
|
+
] }),
|
|
6966
|
+
/* @__PURE__ */ jsxs15("ol", { className: "db-welcome-loop-labels", children: [
|
|
6967
|
+
/* @__PURE__ */ jsx17("li", { children: "PDF" }),
|
|
6968
|
+
/* @__PURE__ */ jsx17("li", { children: "Slides" }),
|
|
6969
|
+
/* @__PURE__ */ jsx17("li", { children: "Video" })
|
|
6970
|
+
] })
|
|
6971
|
+
] });
|
|
6972
|
+
}
|
|
6973
|
+
|
|
6736
6974
|
// src/DocBlocksShell/useDocumentLinkProvider.ts
|
|
6737
6975
|
import { useCallback as useCallback16 } from "react";
|
|
6738
6976
|
|
|
@@ -6797,7 +7035,7 @@ function useDocumentLinkProvider(index, selectedFile, ensureIndex) {
|
|
|
6797
7035
|
|
|
6798
7036
|
// src/WorkspaceIndex/useWorkspaceIndex.ts
|
|
6799
7037
|
import { useCallback as useCallback17, useEffect as useEffect28, useMemo as useMemo5, useRef as useRef18, useState as useState22, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
6800
|
-
import { getFileSystemProviderV2 as
|
|
7038
|
+
import { getFileSystemProviderV2 as getFileSystemProviderV29 } from "@bendyline/docblocks/filesystem";
|
|
6801
7039
|
import { maybeGetDocBlocksHost as maybeGetDocBlocksHost3 } from "@bendyline/docblocks/host";
|
|
6802
7040
|
var IDLE_WORKSPACE_INDEX_STATUS = Object.freeze({
|
|
6803
7041
|
phase: "idle",
|
|
@@ -6827,7 +7065,7 @@ function whenIdle(callback) {
|
|
|
6827
7065
|
return () => clearTimeout(handle);
|
|
6828
7066
|
}
|
|
6829
7067
|
function useWorkspaceIndex(provider, workspaceId, mode = "eager") {
|
|
6830
|
-
const providerV2 = provider && mode !== "off" ?
|
|
7068
|
+
const providerV2 = provider && mode !== "off" ? getFileSystemProviderV29(provider) : null;
|
|
6831
7069
|
const [index, setIndex] = useState22(null);
|
|
6832
7070
|
const startRequestedRef = useRef18(false);
|
|
6833
7071
|
useEffect28(() => {
|
|
@@ -6890,7 +7128,7 @@ function useWorkspaceIndex(provider, workspaceId, mode = "eager") {
|
|
|
6890
7128
|
}
|
|
6891
7129
|
|
|
6892
7130
|
// src/WorkspaceIndex/recent-documents.ts
|
|
6893
|
-
import { tryParseWorkspacePath as
|
|
7131
|
+
import { tryParseWorkspacePath as tryParseWorkspacePath4 } from "@bendyline/docblocks/filesystem";
|
|
6894
7132
|
var RECENT_DOCUMENTS_STORAGE_KEY = "docblocks:recentDocuments:v1";
|
|
6895
7133
|
var MAX_PATHS_PER_WORKSPACE = 50;
|
|
6896
7134
|
var MAX_WORKSPACES = 50;
|
|
@@ -6909,7 +7147,7 @@ function defaultStorage() {
|
|
|
6909
7147
|
}
|
|
6910
7148
|
function canonicalPath(path) {
|
|
6911
7149
|
if (path.length === 0 || path.length > MAX_PATH_LENGTH) return null;
|
|
6912
|
-
return
|
|
7150
|
+
return tryParseWorkspacePath4(path) || null;
|
|
6913
7151
|
}
|
|
6914
7152
|
function parseRecentDocuments(value) {
|
|
6915
7153
|
const parsed = /* @__PURE__ */ new Map();
|
|
@@ -7015,14 +7253,14 @@ var WorkspaceAuthorityBarrier = class {
|
|
|
7015
7253
|
|
|
7016
7254
|
// src/DocBlocksShell/transient-workspace-move.ts
|
|
7017
7255
|
import {
|
|
7018
|
-
getFileSystemProviderV2 as
|
|
7256
|
+
getFileSystemProviderV2 as getFileSystemProviderV210
|
|
7019
7257
|
} from "@bendyline/docblocks/filesystem";
|
|
7020
7258
|
function pathDepth(path) {
|
|
7021
7259
|
return path ? path.split("/").length : 0;
|
|
7022
7260
|
}
|
|
7023
7261
|
async function copyTransientWorkspaceContents(source, destination) {
|
|
7024
|
-
const sourceV2 =
|
|
7025
|
-
const destinationV2 =
|
|
7262
|
+
const sourceV2 = getFileSystemProviderV210(source);
|
|
7263
|
+
const destinationV2 = getFileSystemProviderV210(destination);
|
|
7026
7264
|
if (!sourceV2 || !destinationV2) {
|
|
7027
7265
|
throw new Error("Moving a temporary document requires a current workspace provider.");
|
|
7028
7266
|
}
|
|
@@ -7107,7 +7345,15 @@ function createNativeFileActions(entry, workspaceId, host) {
|
|
|
7107
7345
|
|
|
7108
7346
|
// src/DocBlocksShell/welcome-document.ts
|
|
7109
7347
|
import { DEFAULT_WORKSPACE_ID } from "@bendyline/docblocks/workspace";
|
|
7110
|
-
var WELCOME_DOCUMENT_PATH = "/
|
|
7348
|
+
var WELCOME_DOCUMENT_PATH = "/Welcome.md";
|
|
7349
|
+
var WELCOME_DOCUMENT_NAMES = /* @__PURE__ */ new Set([
|
|
7350
|
+
"welcome.md",
|
|
7351
|
+
// Seeded as `aboutDocBlocks.md` through 2.7 (`aboutDocblocks.md` before that).
|
|
7352
|
+
"aboutdocblocks.md"
|
|
7353
|
+
]);
|
|
7354
|
+
function isWelcomeDocumentPath(path) {
|
|
7355
|
+
return WELCOME_DOCUMENT_NAMES.has(path.replace(/^\//, "").toLowerCase());
|
|
7356
|
+
}
|
|
7111
7357
|
function isAppDefaultWorkspace(workspaceId, hostDefaultWorkspaceIds) {
|
|
7112
7358
|
return hostDefaultWorkspaceIds ? hostDefaultWorkspaceIds.has(workspaceId) : workspaceId === DEFAULT_WORKSPACE_ID;
|
|
7113
7359
|
}
|
|
@@ -7117,126 +7363,57 @@ var WELCOME_DOCUMENT_CONTENT = [
|
|
|
7117
7363
|
"squisq-cover-slide: false",
|
|
7118
7364
|
"---",
|
|
7119
7365
|
"",
|
|
7120
|
-
'# DocBlocks {[title subtitle="
|
|
7121
|
-
"",
|
|
7122
|
-
"Write in plain Markdown. Shape it visually. Keep it portable.",
|
|
7123
|
-
"",
|
|
7124
|
-
"## A document editor that never asks you to stop owning the document {[factCard]}",
|
|
7125
|
-
"",
|
|
7126
|
-
"DocBlocks pairs a friendly visual writing surface with the durable source format you already know. There is no account to create, no proprietary document to rescue later, and no requirement to send your work to a hosted editor.",
|
|
7127
|
-
"",
|
|
7128
|
-
"## Start with three small moves {[list]}",
|
|
7129
|
-
"",
|
|
7130
|
-
"1. Choose **New file** in the file pane and give your document a name, such as `my-first-document.md`. On a small screen, open the file pane first.",
|
|
7131
|
-
"2. Add a heading and a few sentences in **Write**, then switch to **Source** to see the Markdown behind them. Both views edit the same document.",
|
|
7132
|
-
"3. Try a Document, Page, Slideshow, or Video preview, then open **Export and share** to make a PDF, Word document, or another supported file.",
|
|
7133
|
-
"",
|
|
7134
|
-
'## Choose your DocBlocks app {[twoColumn header="The same Markdown, wherever you work" left="Web|Start in a browser, with no account. Install the web app when your browser offers it." right="Desktop|Download for macOS (Apple silicon), Windows, or Linux. Work directly in your folders."]}',
|
|
7366
|
+
'# Welcome to DocBlocks {[title subtitle="Write once. Share it as a document, a deck, or a video."]}',
|
|
7135
7367
|
"",
|
|
7136
|
-
"
|
|
7368
|
+
"This is an ordinary document, so go ahead and change it. Click anywhere and type; DocBlocks saves as you go.",
|
|
7137
7369
|
"",
|
|
7138
|
-
"##
|
|
7370
|
+
"## Write the way you already do {[list]}",
|
|
7139
7371
|
"",
|
|
7140
|
-
"-
|
|
7141
|
-
"-
|
|
7142
|
-
"-
|
|
7143
|
-
"- Use the same Write, Source, preview, and export workflow as the web app, with native menus and file opening.",
|
|
7372
|
+
"- Type to add text, and use the toolbar for headings, lists, and bold or italic text.",
|
|
7373
|
+
"- Choose **Insert** in the toolbar to add a table, a checklist, a chart, a diagram, or a picture.",
|
|
7374
|
+
"- Choose **Source** to see the Markdown text behind this page. Both views edit the same document.",
|
|
7144
7375
|
"",
|
|
7145
|
-
"##
|
|
7146
|
-
"",
|
|
7147
|
-
"- Open DocBlocks in your browser and start in a browser workspace. In supported browsers, you can also open a local folder.",
|
|
7148
|
-
"- Choose **Install DocBlocks\u2026** in the app menu when offered. The installed web app keeps using the same browser storage.",
|
|
7149
|
-
"- Once the app has finished downloading for offline use, you can keep editing without a connection.",
|
|
7150
|
-
"- Use **Back up all workspaces** in the app menu to keep a backup before clearing browser data or moving to a new device.",
|
|
7151
|
-
"",
|
|
7152
|
-
"## Work inside VS Code {[content]}",
|
|
7153
|
-
"",
|
|
7154
|
-
"Install the DocBlocks extension, then open a `.md` file in your project. If it opens as plain text, right-click it and choose **Open in DocBlocks**. VS Code supplies the file explorer, tabs, saving, and source control; DocBlocks supplies the visual editor, Markdown source, previews, and export. Follow the extension guide below to get started.",
|
|
7155
|
-
"",
|
|
7156
|
-
"## On a phone or tablet {[content]}",
|
|
7157
|
-
"",
|
|
7158
|
-
"Use the web app on your phone or tablet today. Native apps for iPhone, iPad, and Android are in preview, with store distribution pending. Preview builds offer an **On this device** workspace, picked folders, and system sharing. Keep an exported copy of important work: uninstalling a native app removes its private device workspace.",
|
|
7159
|
-
"",
|
|
7160
|
-
'## Automate with the CLI and MCP {[twoColumn header="For repeatable document work" left="CLI|Install @bendyline/docblocks-cli with npm, then run docblocks --help. Build, preview, and convert files from your terminal." right="MCP|Connect the local server to an agent. Convert and preview documents, then deliberately save the resulting artifacts."]}',
|
|
7161
|
-
"",
|
|
7162
|
-
"With a supported version of `Node.js` installed, run `npm install -g @bendyline/docblocks-cli`, then `docblocks --help`. The CLI builds, previews, and converts files from your terminal. Its local MCP server gives agents document tools with explicitly allowed file access. Follow the CLI and MCP guide below for requirements and configuration.",
|
|
7163
|
-
"",
|
|
7164
|
-
"## One source, four ways to publish {[diagram]}",
|
|
7376
|
+
"## One document, many ways to share it {[diagram]}",
|
|
7165
7377
|
"",
|
|
7166
7378
|
"```diagram",
|
|
7167
|
-
"
|
|
7168
|
-
"|
|
|
7169
|
-
"
|
|
7170
|
-
"
|
|
7171
|
-
"
|
|
7172
|
-
"
|
|
7173
|
-
"
|
|
7174
|
-
"+-------+
|
|
7175
|
-
"|
|
|
7176
|
-
"+-------+
|
|
7379
|
+
" +-----------------+",
|
|
7380
|
+
" | Your document |",
|
|
7381
|
+
" +--------+--------+",
|
|
7382
|
+
" |",
|
|
7383
|
+
" +-----------+------+-----+------------+",
|
|
7384
|
+
" | | | |",
|
|
7385
|
+
" v v v v",
|
|
7386
|
+
"+-------+ +--------+ +----------+ +---------+",
|
|
7387
|
+
"| PDF | | Word | | Slides | | Video |",
|
|
7388
|
+
"+-------+ +--------+ +----------+ +---------+",
|
|
7177
7389
|
"```",
|
|
7178
7390
|
"",
|
|
7179
|
-
"##
|
|
7180
|
-
"",
|
|
7181
|
-
"Use the rich editor for headings, lists, tables, links, images, media, and everyday formatting. Switch to raw Markdown for exact control. Add themes, transform styles, and squiggly-square section annotations when a passage deserves its own visual treatment. The readable `.md` source stays at the center of the workflow.",
|
|
7182
|
-
"",
|
|
7183
|
-
"## Preview the finished idea before you export it {[list]}",
|
|
7184
|
-
"",
|
|
7185
|
-
"- **Document** \u2014 Read the work as a polished, continuous document.",
|
|
7186
|
-
"- **Page** \u2014 See how it behaves as a web page.",
|
|
7187
|
-
"- **Slideshow** \u2014 Step through headings as designed presentation blocks.",
|
|
7188
|
-
"- **Video** \u2014 Rehearse timing, motion, narration, and media in a player-ready view.",
|
|
7189
|
-
"",
|
|
7190
|
-
"## Try the optional desktop tools {[list]}",
|
|
7191
|
-
"",
|
|
7192
|
-
"- **AI assistance** can help rewrite, review, and illustrate a document. In **Settings \u2192 AI assistance**, turn on **Use AI features** and choose an available model. AI is off by default; model downloads start only when you request them.",
|
|
7193
|
-
"- **Dictation and read aloud** run on your computer. Where available, open **Settings \u2192 Speech** to download a dictation model or narration voices, then use the microphone or read-aloud controls.",
|
|
7194
|
-
"- These tools depend on the app, device, and installed models. Writing, previewing, and exporting work without setting them up.",
|
|
7195
|
-
"",
|
|
7196
|
-
"## The quiet conveniences are there, too {[list]}",
|
|
7197
|
-
"",
|
|
7198
|
-
"- **Workspaces and file navigation** keep related documents organized without hiding their source.",
|
|
7199
|
-
"- **Automatic saving** protects the active revision while still surfacing conflicts or save errors.",
|
|
7200
|
-
"- **Optional version history** keeps plain sibling revisions when you want a trail of changes.",
|
|
7201
|
-
"- **Copy-by-link sharing** puts a Markdown copy in a link that opens straight into a Document, Page, Slideshow, or Video view.",
|
|
7202
|
-
"- **Offline-ready, local-first storage** keeps browser work on this device and native work inside folders you choose.",
|
|
7203
|
-
"",
|
|
7204
|
-
"## Export without rebuilding the document {[list]}",
|
|
7205
|
-
"",
|
|
7206
|
-
"- Create **Word documents and PDFs** for review, printing, and sharing with a fixed page layout.",
|
|
7207
|
-
"- Create **PowerPoint decks** from the same annotated sections you preview as a slideshow.",
|
|
7208
|
-
"- Publish **HTML pages, packaged HTML, and EPUB e-books**.",
|
|
7209
|
-
"- Keep portable **Markdown or DBK bundles** with their media assets.",
|
|
7210
|
-
"- Use the linked CLI registry for **spreadsheets, MP4 video, animated GIF, batch conversion, and more**.",
|
|
7391
|
+
"## Present it or send it {[content]}",
|
|
7211
7392
|
"",
|
|
7212
|
-
"
|
|
7393
|
+
"Each heading starts a new slide, so this document is already a slideshow. Choose **Slideshow** at the top to see it, or **Export** to save it as a PDF, a Word document, a PowerPoint deck, an e-book, a web page, or a video.",
|
|
7213
7394
|
"",
|
|
7214
|
-
"
|
|
7395
|
+
"## Your documents stay yours {[factCard]}",
|
|
7215
7396
|
"",
|
|
7216
|
-
"
|
|
7397
|
+
"There is no account to create. Your documents stay on this device as plain text files that other apps can open too. Choose **Back up** at the bottom of the file list to keep a copy somewhere safe.",
|
|
7217
7398
|
"",
|
|
7218
|
-
"
|
|
7399
|
+
"## Make your own {[list]}",
|
|
7219
7400
|
"",
|
|
7220
|
-
"
|
|
7401
|
+
"1. Choose **New File** above the file list and give it a name.",
|
|
7402
|
+
"2. Write a heading and a few sentences.",
|
|
7403
|
+
"3. Choose **Slideshow** to present it, or **Export** to share it.",
|
|
7221
7404
|
"",
|
|
7222
|
-
"
|
|
7405
|
+
"## Go further {[list]}",
|
|
7223
7406
|
"",
|
|
7224
|
-
"
|
|
7225
|
-
"",
|
|
7226
|
-
"- [
|
|
7227
|
-
"- [Web app](https://docblocks.com/web/) \u2014 browser storage, installation, and offline use.",
|
|
7228
|
-
"- [Mobile preview](https://docblocks.com/docs/#mobile-preview) \u2014 iPhone, iPad, and Android status and build guide.",
|
|
7229
|
-
"- [VS Code extension](https://docblocks.com/vscode/) \u2014 rich Markdown editing inside a workspace.",
|
|
7230
|
-
"- [CLI and MCP server](https://docblocks.com/cli/) \u2014 conversion, rendering, and agent workflows.",
|
|
7231
|
-
"- [Supported formats](https://docblocks.com/formats/) \u2014 current import and export directions.",
|
|
7232
|
-
"- [Documentation](https://docblocks.com/docs/) \u2014 compare the apps and follow the getting-started guides.",
|
|
7407
|
+
"- [Get the desktop app](https://docblocks.com/desktop/) to work in folders on your computer.",
|
|
7408
|
+
"- [Add DocBlocks to VS Code](https://docblocks.com/vscode/) to edit documents beside your code.",
|
|
7409
|
+
"- [Read the guides](https://docblocks.com/docs/) for everything else.",
|
|
7233
7410
|
// End with a newline, as the Write view saves every document. Without it,
|
|
7234
7411
|
// merely opening the welcome document in Write rewrote the file.
|
|
7235
7412
|
""
|
|
7236
7413
|
].join("\n");
|
|
7237
7414
|
|
|
7238
7415
|
// src/DocBlocksShell/DocBlocksShell.tsx
|
|
7239
|
-
import { Fragment as Fragment11, jsx as
|
|
7416
|
+
import { Fragment as Fragment11, jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
7240
7417
|
var editorShellModulePromise = null;
|
|
7241
7418
|
function loadEditorShell() {
|
|
7242
7419
|
editorShellModulePromise ?? (editorShellModulePromise = (async () => {
|
|
@@ -7248,13 +7425,13 @@ function loadEditorShell() {
|
|
|
7248
7425
|
return editorShellModulePromise;
|
|
7249
7426
|
}
|
|
7250
7427
|
var EditorShell = lazy2(loadEditorShell);
|
|
7251
|
-
var DocumentConflictDialog = lazy2(() => import("./DocumentConflictDialog-
|
|
7252
|
-
var GitUI = lazy2(() => import("./GitUI-
|
|
7428
|
+
var DocumentConflictDialog = lazy2(() => import("./DocumentConflictDialog-DZ2BV2IH.js"));
|
|
7429
|
+
var GitUI = lazy2(() => import("./GitUI-F3CNBURE.js").then((m) => ({ default: m.GitUI })));
|
|
7253
7430
|
var QuickOpenDialog = lazy2(
|
|
7254
|
-
() => import("./QuickOpenDialog-
|
|
7431
|
+
() => import("./QuickOpenDialog-ENVFGIHS.js").then((m) => ({ default: m.QuickOpenDialog }))
|
|
7255
7432
|
);
|
|
7256
7433
|
var KeyboardShortcutsDialog = lazy2(
|
|
7257
|
-
() => import("./KeyboardShortcutsDialog-
|
|
7434
|
+
() => import("./KeyboardShortcutsDialog-HVKDFP5Z.js").then((m) => ({ default: m.KeyboardShortcutsDialog }))
|
|
7258
7435
|
);
|
|
7259
7436
|
var WorkspaceSearchPanel = lazy2(
|
|
7260
7437
|
() => import("./WorkspaceSearchPanel-J6BKEZQJ.js").then((m) => ({
|
|
@@ -7268,37 +7445,37 @@ var GitToolbarControl = lazy2(
|
|
|
7268
7445
|
() => import("./GitToolbarControl-B7KG4MFP.js").then((m) => ({ default: m.GitToolbarControl }))
|
|
7269
7446
|
);
|
|
7270
7447
|
var AiToolbarControl = lazy2(
|
|
7271
|
-
() => import("./AiEditorAssistant-
|
|
7448
|
+
() => import("./AiEditorAssistant-4HFFGVU4.js").then((module) => ({
|
|
7272
7449
|
default: module.AiToolbarControl
|
|
7273
7450
|
}))
|
|
7274
7451
|
);
|
|
7275
7452
|
var PresentationMaker = lazy2(
|
|
7276
|
-
() => import("./PresentationMaker-
|
|
7453
|
+
() => import("./PresentationMaker-MUMFAXEI.js").then((module) => ({
|
|
7277
7454
|
default: module.PresentationMaker
|
|
7278
7455
|
}))
|
|
7279
7456
|
);
|
|
7280
7457
|
var AiReviewPanel = lazy2(
|
|
7281
|
-
() => import("./AiEditorAssistant-
|
|
7458
|
+
() => import("./AiEditorAssistant-4HFFGVU4.js").then((module) => ({
|
|
7282
7459
|
default: module.AiReviewPanel
|
|
7283
7460
|
}))
|
|
7284
7461
|
);
|
|
7285
7462
|
var AiIllustratePanel = lazy2(
|
|
7286
|
-
() => import("./AiDiagrams-
|
|
7463
|
+
() => import("./AiDiagrams-QZMJNGDT.js").then((module) => ({
|
|
7287
7464
|
default: module.AiIllustratePanel
|
|
7288
7465
|
}))
|
|
7289
7466
|
);
|
|
7290
7467
|
var TextFromNarration = lazy2(
|
|
7291
|
-
() => import("./TextFromNarration-
|
|
7468
|
+
() => import("./TextFromNarration-EYOMW2IW.js").then((module) => ({
|
|
7292
7469
|
default: module.TextFromNarration
|
|
7293
7470
|
}))
|
|
7294
7471
|
);
|
|
7295
7472
|
var SpeechToolbarControl = lazy2(
|
|
7296
|
-
() => import("./SpeechToolbarControl-
|
|
7473
|
+
() => import("./SpeechToolbarControl-KNI2C4JJ.js").then((module) => ({
|
|
7297
7474
|
default: module.SpeechToolbarControl
|
|
7298
7475
|
}))
|
|
7299
7476
|
);
|
|
7300
7477
|
var SpeechMenuBridge = lazy2(
|
|
7301
|
-
() => import("./SpeechToolbarControl-
|
|
7478
|
+
() => import("./SpeechToolbarControl-KNI2C4JJ.js").then((module) => ({
|
|
7302
7479
|
default: module.SpeechMenuBridge
|
|
7303
7480
|
}))
|
|
7304
7481
|
);
|
|
@@ -7439,19 +7616,19 @@ function pathContains(parentPath2, candidatePath) {
|
|
|
7439
7616
|
return workspacePathContains(parseWorkspacePath8(parentPath2), parseWorkspacePath8(candidatePath));
|
|
7440
7617
|
}
|
|
7441
7618
|
async function readProviderDirectory2(provider, path) {
|
|
7442
|
-
const providerV2 =
|
|
7619
|
+
const providerV2 = getFileSystemProviderV211(provider);
|
|
7443
7620
|
if (!providerV2) return provider.readDirectory(path);
|
|
7444
7621
|
const entries = await providerV2.readDirectory(parseWorkspacePath8(path));
|
|
7445
7622
|
return entries.map((entry) => ({ kind: entry.kind, name: entry.name, path: entry.path }));
|
|
7446
7623
|
}
|
|
7447
7624
|
async function readProviderText(provider, path) {
|
|
7448
|
-
const providerV2 =
|
|
7625
|
+
const providerV2 = getFileSystemProviderV211(provider);
|
|
7449
7626
|
if (!providerV2) return provider.readFile(path);
|
|
7450
7627
|
const file = await providerV2.readFile(parseWorkspacePath8(path));
|
|
7451
7628
|
return file ? decodeUtf8Text(file.data, { label: "The document", path: parseWorkspacePath8(path) }) : null;
|
|
7452
7629
|
}
|
|
7453
7630
|
async function pinnedProviderFileExists(provider, path) {
|
|
7454
|
-
const providerV2 =
|
|
7631
|
+
const providerV2 = getFileSystemProviderV211(provider);
|
|
7455
7632
|
if (!providerV2) return provider.exists(path);
|
|
7456
7633
|
const entry = await providerV2.stat(parseWorkspacePath8(path));
|
|
7457
7634
|
if (!entry) return false;
|
|
@@ -7459,7 +7636,7 @@ async function pinnedProviderFileExists(provider, path) {
|
|
|
7459
7636
|
return true;
|
|
7460
7637
|
}
|
|
7461
7638
|
async function removePinnedProviderFile(provider, path) {
|
|
7462
|
-
const providerV2 =
|
|
7639
|
+
const providerV2 = getFileSystemProviderV211(provider);
|
|
7463
7640
|
if (providerV2) {
|
|
7464
7641
|
const canonical = parseWorkspacePath8(path);
|
|
7465
7642
|
const entry = await providerV2.stat(canonical);
|
|
@@ -7477,7 +7654,7 @@ async function removePinnedProviderFile(provider, path) {
|
|
|
7477
7654
|
return true;
|
|
7478
7655
|
}
|
|
7479
7656
|
async function readStableFileSnapshot(provider, path) {
|
|
7480
|
-
const providerV2 =
|
|
7657
|
+
const providerV2 = getFileSystemProviderV211(provider);
|
|
7481
7658
|
if (providerV2) {
|
|
7482
7659
|
const read2 = await providerV2.readFile(parseWorkspacePath8(path));
|
|
7483
7660
|
return {
|
|
@@ -7521,7 +7698,7 @@ async function ensureHandleWritePermission(handle) {
|
|
|
7521
7698
|
}
|
|
7522
7699
|
}
|
|
7523
7700
|
async function copyProviderToContainer(src, container, pathPrefix) {
|
|
7524
|
-
const providerV2 =
|
|
7701
|
+
const providerV2 = getFileSystemProviderV211(src);
|
|
7525
7702
|
if (providerV2) {
|
|
7526
7703
|
const snapshot = await providerV2.snapshot();
|
|
7527
7704
|
for (const entry of snapshot.entries) {
|
|
@@ -7565,7 +7742,7 @@ async function createHostProviderFromWorkspace(ws) {
|
|
|
7565
7742
|
var DESKTOP_TOOLBAR_WRAP_WIDTH = 900;
|
|
7566
7743
|
var WEB_TOOLBAR_WRAP_WIDTH = 700;
|
|
7567
7744
|
function FolderGlyph() {
|
|
7568
|
-
return /* @__PURE__ */
|
|
7745
|
+
return /* @__PURE__ */ jsx18(
|
|
7569
7746
|
"svg",
|
|
7570
7747
|
{
|
|
7571
7748
|
viewBox: "0 0 24 24",
|
|
@@ -7574,12 +7751,12 @@ function FolderGlyph() {
|
|
|
7574
7751
|
strokeWidth: "1.5",
|
|
7575
7752
|
strokeLinejoin: "round",
|
|
7576
7753
|
"aria-hidden": "true",
|
|
7577
|
-
children: /* @__PURE__ */
|
|
7754
|
+
children: /* @__PURE__ */ jsx18("path", { d: "M3 7a1 1 0 0 1 1-1h5l2 2h9a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7z" })
|
|
7578
7755
|
}
|
|
7579
7756
|
);
|
|
7580
7757
|
}
|
|
7581
7758
|
function FileGlyph() {
|
|
7582
|
-
return /* @__PURE__ */
|
|
7759
|
+
return /* @__PURE__ */ jsxs16(
|
|
7583
7760
|
"svg",
|
|
7584
7761
|
{
|
|
7585
7762
|
viewBox: "0 0 24 24",
|
|
@@ -7589,14 +7766,14 @@ function FileGlyph() {
|
|
|
7589
7766
|
strokeLinejoin: "round",
|
|
7590
7767
|
"aria-hidden": "true",
|
|
7591
7768
|
children: [
|
|
7592
|
-
/* @__PURE__ */
|
|
7593
|
-
/* @__PURE__ */
|
|
7769
|
+
/* @__PURE__ */ jsx18("path", { d: "M6 3h8l5 5v12a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z" }),
|
|
7770
|
+
/* @__PURE__ */ jsx18("path", { d: "M14 3v5h5" })
|
|
7594
7771
|
]
|
|
7595
7772
|
}
|
|
7596
7773
|
);
|
|
7597
7774
|
}
|
|
7598
7775
|
function CollapseSidebarGlyph() {
|
|
7599
|
-
return /* @__PURE__ */
|
|
7776
|
+
return /* @__PURE__ */ jsxs16(
|
|
7600
7777
|
"svg",
|
|
7601
7778
|
{
|
|
7602
7779
|
viewBox: "0 0 64 64",
|
|
@@ -7607,9 +7784,9 @@ function CollapseSidebarGlyph() {
|
|
|
7607
7784
|
strokeLinejoin: "round",
|
|
7608
7785
|
"aria-hidden": "true",
|
|
7609
7786
|
children: [
|
|
7610
|
-
/* @__PURE__ */
|
|
7611
|
-
/* @__PURE__ */
|
|
7612
|
-
/* @__PURE__ */
|
|
7787
|
+
/* @__PURE__ */ jsx18("rect", { x: "7", y: "10", width: "50", height: "44", rx: "6" }),
|
|
7788
|
+
/* @__PURE__ */ jsx18("path", { d: "M24 10v44" }),
|
|
7789
|
+
/* @__PURE__ */ jsx18("path", { d: "m17 25-7 7 7 7" })
|
|
7613
7790
|
]
|
|
7614
7791
|
}
|
|
7615
7792
|
);
|
|
@@ -7841,6 +8018,7 @@ function DocBlocksShell({
|
|
|
7841
8018
|
);
|
|
7842
8019
|
const [provider, setProvider] = useState23(null);
|
|
7843
8020
|
const [workspaceStartupError, setWorkspaceStartupError] = useState23(null);
|
|
8021
|
+
const workspaceStarting = provider === null && workspaceStartupError === null;
|
|
7844
8022
|
const [activeWorkspaceId, setActiveWorkspaceId] = useState23(null);
|
|
7845
8023
|
const [defaultNewFileFormat, setDefaultNewFileFormat] = useState23(DEFAULT_NEW_FILE_FORMAT);
|
|
7846
8024
|
useEffect29(() => {
|
|
@@ -7863,7 +8041,7 @@ function DocBlocksShell({
|
|
|
7863
8041
|
const effectiveProofingIgnoreStore = proofingIgnoreStore === void 0 ? defaultProofingIgnoreStore : proofingIgnoreStore;
|
|
7864
8042
|
useEffect29(() => {
|
|
7865
8043
|
if (!provider || getTransientWorkspace(provider.id)) return;
|
|
7866
|
-
const providerV2 =
|
|
8044
|
+
const providerV2 = getFileSystemProviderV211(provider);
|
|
7867
8045
|
return providerV2 ? retainFileSystemProvider(providerV2) : void 0;
|
|
7868
8046
|
}, [provider]);
|
|
7869
8047
|
const [descriptorRefreshKey, setDescriptorRefreshKey] = useState23(0);
|
|
@@ -7951,7 +8129,7 @@ function DocBlocksShell({
|
|
|
7951
8129
|
void scan();
|
|
7952
8130
|
const scanOnFocus = () => void scan();
|
|
7953
8131
|
window.addEventListener("focus", scanOnFocus);
|
|
7954
|
-
const providerV2 =
|
|
8132
|
+
const providerV2 = getFileSystemProviderV211(provider);
|
|
7955
8133
|
const subscription = providerV2?.capabilities.watch ? providerV2.watch(
|
|
7956
8134
|
(event) => {
|
|
7957
8135
|
if (event.type !== "modified") void scan();
|
|
@@ -8060,7 +8238,7 @@ function DocBlocksShell({
|
|
|
8060
8238
|
if (descriptor && descriptor.versioningOverride !== void 0) {
|
|
8061
8239
|
const moved = { ...descriptor };
|
|
8062
8240
|
delete moved.versioningOverride;
|
|
8063
|
-
await
|
|
8241
|
+
await saveWorkspace3(moved);
|
|
8064
8242
|
setDescriptorRefreshKey((k) => k + 1);
|
|
8065
8243
|
}
|
|
8066
8244
|
},
|
|
@@ -8157,7 +8335,13 @@ function DocBlocksShell({
|
|
|
8157
8335
|
return {
|
|
8158
8336
|
resolveTarget: (filename) => resolveTarget(documentId, filename),
|
|
8159
8337
|
pickTarget: (filename, currentTarget) => pickTarget(documentId, filename, currentTarget?.grantId ?? null),
|
|
8160
|
-
saveBlob: (blob, filename, target) => saveBlobToHost(exports, documentId, blob, filename, target?.grantId ?? null)
|
|
8338
|
+
saveBlob: (blob, filename, target) => saveBlobToHost(exports, documentId, blob, filename, target?.grantId ?? null),
|
|
8339
|
+
...hostSupports2("openSavedExports") && exports.openSaved ? {
|
|
8340
|
+
openSaved: async (target) => {
|
|
8341
|
+
if (!target.grantId) throw new Error("The saved export has no native target.");
|
|
8342
|
+
await exports.openSaved(documentId, target.grantId);
|
|
8343
|
+
}
|
|
8344
|
+
} : {}
|
|
8161
8345
|
};
|
|
8162
8346
|
}
|
|
8163
8347
|
}
|
|
@@ -8194,7 +8378,6 @@ function DocBlocksShell({
|
|
|
8194
8378
|
} : null,
|
|
8195
8379
|
[documentSnapshot.frozen, documentSnapshot.generation, documentSnapshot.targetKey]
|
|
8196
8380
|
);
|
|
8197
|
-
const [editorPresentationEpoch, setEditorPresentationEpoch] = useState23(0);
|
|
8198
8381
|
const [editorGeneration, setEditorGeneration] = useState23(documentSnapshot.generation);
|
|
8199
8382
|
useEffect29(() => {
|
|
8200
8383
|
const sync = () => setEditorGeneration(documentSession.getSnapshot().generation);
|
|
@@ -8208,7 +8391,7 @@ function DocBlocksShell({
|
|
|
8208
8391
|
useEffect29(() => {
|
|
8209
8392
|
setOutsideInPdfWorker(pdfWorkerSrc2);
|
|
8210
8393
|
}, [pdfWorkerSrc2]);
|
|
8211
|
-
const editorKey =
|
|
8394
|
+
const editorKey = String(editorGeneration);
|
|
8212
8395
|
const editorPlaceholder = useMemo6(() => {
|
|
8213
8396
|
void editorKey;
|
|
8214
8397
|
return pickEmptyDocumentPrompt();
|
|
@@ -8217,7 +8400,7 @@ function DocBlocksShell({
|
|
|
8217
8400
|
const workspaceOutputsResult = workspaceOutputs.status.result;
|
|
8218
8401
|
useEffect29(() => {
|
|
8219
8402
|
if (!workspaceOutputsResult?.outputs.some((output) => output.created)) return;
|
|
8220
|
-
if (provider &&
|
|
8403
|
+
if (provider && getFileSystemProviderV211(provider)?.capabilities.watch) return;
|
|
8221
8404
|
setExplorerKey((key) => key + 1);
|
|
8222
8405
|
}, [provider, workspaceOutputsResult]);
|
|
8223
8406
|
const [fileExplorerSortMode, setFileExplorerSortMode] = useState23(loadFileExplorerSortMode);
|
|
@@ -8228,6 +8411,15 @@ function DocBlocksShell({
|
|
|
8228
8411
|
const [initialView, setInitialView] = useState23("wysiwyg");
|
|
8229
8412
|
const [initialSharedMode, setInitialSharedMode] = useState23(null);
|
|
8230
8413
|
const [showWelcomeGateway, setShowWelcomeGateway] = useState23(false);
|
|
8414
|
+
const welcomeScreenShown = showWelcomeGateway && !singlePane;
|
|
8415
|
+
const welcomeCoveredRef = useRef19(null);
|
|
8416
|
+
useInert(welcomeCoveredRef, welcomeScreenShown);
|
|
8417
|
+
const closeWelcomeGateway = useCallback18(() => {
|
|
8418
|
+
setShowWelcomeGateway((showing) => {
|
|
8419
|
+
if (showing) markWelcomeGatewayDismissed();
|
|
8420
|
+
return false;
|
|
8421
|
+
});
|
|
8422
|
+
}, []);
|
|
8231
8423
|
const [aiPanel, setAiPanel] = useState23(null);
|
|
8232
8424
|
const navigationRequestRef = useRef19(0);
|
|
8233
8425
|
const workspaceAuthorityBarrier = useMemo6(() => new WorkspaceAuthorityBarrier(), []);
|
|
@@ -8511,7 +8703,7 @@ function DocBlocksShell({
|
|
|
8511
8703
|
}
|
|
8512
8704
|
return fsProvider;
|
|
8513
8705
|
} finally {
|
|
8514
|
-
if (!transient && !adopted) await
|
|
8706
|
+
if (!transient && !adopted) await getFileSystemProviderV211(fsProvider)?.dispose();
|
|
8515
8707
|
}
|
|
8516
8708
|
},
|
|
8517
8709
|
[adoptSelectedDocument, createDocumentTarget, documentSession, pushHash]
|
|
@@ -8536,6 +8728,7 @@ function DocBlocksShell({
|
|
|
8536
8728
|
options.navigationRequestId,
|
|
8537
8729
|
options.sharedMode ?? null
|
|
8538
8730
|
) !== null;
|
|
8731
|
+
if (opened) closeWelcomeGateway();
|
|
8539
8732
|
return opened;
|
|
8540
8733
|
} finally {
|
|
8541
8734
|
if (!opened && getTransientWorkspace(options.id)?.provider === options.provider) {
|
|
@@ -8543,7 +8736,7 @@ function DocBlocksShell({
|
|
|
8543
8736
|
}
|
|
8544
8737
|
}
|
|
8545
8738
|
},
|
|
8546
|
-
[openFromIds]
|
|
8739
|
+
[openFromIds, closeWelcomeGateway]
|
|
8547
8740
|
);
|
|
8548
8741
|
const openSharedDocument = useCallback18(
|
|
8549
8742
|
async (payload, navigationRequestId) => {
|
|
@@ -8562,7 +8755,7 @@ function DocBlocksShell({
|
|
|
8562
8755
|
)
|
|
8563
8756
|
});
|
|
8564
8757
|
} catch (error) {
|
|
8565
|
-
await
|
|
8758
|
+
await getFileSystemProviderV211(mem)?.dispose();
|
|
8566
8759
|
throw error;
|
|
8567
8760
|
}
|
|
8568
8761
|
return adoptTransientWorkspace({
|
|
@@ -8585,18 +8778,18 @@ function DocBlocksShell({
|
|
|
8585
8778
|
const entries = await readProviderDirectory2(fs, "/");
|
|
8586
8779
|
if (!isCurrent()) return;
|
|
8587
8780
|
const visibleEntries = filterVisibleFileEntries(entries);
|
|
8588
|
-
if (visibleEntries.length === 1 && visibleEntries[0].kind === "file" && visibleEntries[0].path
|
|
8781
|
+
if (visibleEntries.length === 1 && visibleEntries[0].kind === "file" && isWelcomeDocumentPath(visibleEntries[0].path)) {
|
|
8589
8782
|
const aboutPath = visibleEntries[0].path;
|
|
8590
8783
|
const content = await readProviderText(fs, aboutPath);
|
|
8591
8784
|
if (content !== null && isCurrent()) {
|
|
8592
8785
|
await documentSession.transitionTo(createDocumentTarget(fs, fs.id, aboutPath), content);
|
|
8593
8786
|
if (!isCurrent()) return;
|
|
8594
8787
|
adoptRegularDocument(aboutPath);
|
|
8595
|
-
setInitialView("
|
|
8788
|
+
setInitialView("wysiwyg");
|
|
8596
8789
|
setInitialSharedMode(null);
|
|
8597
8790
|
setExplorerKey((k) => k + 1);
|
|
8598
8791
|
pushHash(fs.id, aboutPath);
|
|
8599
|
-
saveLastState({ workspaceId: fs.id, filePath: aboutPath, view: "
|
|
8792
|
+
saveLastState({ workspaceId: fs.id, filePath: aboutPath, view: "wysiwyg" });
|
|
8600
8793
|
if (!isWelcomeGatewayDismissed()) setShowWelcomeGateway(true);
|
|
8601
8794
|
}
|
|
8602
8795
|
return;
|
|
@@ -8608,7 +8801,7 @@ function DocBlocksShell({
|
|
|
8608
8801
|
try {
|
|
8609
8802
|
await writeProviderText(fs, welcomePath, welcomeContent, "create");
|
|
8610
8803
|
} catch (error) {
|
|
8611
|
-
if (!(error instanceof
|
|
8804
|
+
if (!(error instanceof FsError6 && error.code === "already-exists")) throw error;
|
|
8612
8805
|
const existing = await readProviderText(fs, welcomePath);
|
|
8613
8806
|
if (existing === null) throw error;
|
|
8614
8807
|
seededContent = existing;
|
|
@@ -8620,11 +8813,11 @@ function DocBlocksShell({
|
|
|
8620
8813
|
);
|
|
8621
8814
|
if (!isCurrent()) return;
|
|
8622
8815
|
adoptRegularDocument(welcomePath);
|
|
8623
|
-
setInitialView("
|
|
8816
|
+
setInitialView("wysiwyg");
|
|
8624
8817
|
setInitialSharedMode(null);
|
|
8625
8818
|
setExplorerKey((k) => k + 1);
|
|
8626
8819
|
pushHash(fs.id, welcomePath);
|
|
8627
|
-
saveLastState({ workspaceId: fs.id, filePath: welcomePath, view: "
|
|
8820
|
+
saveLastState({ workspaceId: fs.id, filePath: welcomePath, view: "wysiwyg" });
|
|
8628
8821
|
if (!isWelcomeGatewayDismissed()) setShowWelcomeGateway(true);
|
|
8629
8822
|
},
|
|
8630
8823
|
[adoptRegularDocument, createDocumentTarget, documentSession, pushHash]
|
|
@@ -8635,21 +8828,16 @@ function DocBlocksShell({
|
|
|
8635
8828
|
startupOpenSharedDocumentRef.current = openSharedDocument;
|
|
8636
8829
|
const startupSeedWelcomeFileRef = useRef19(seedWelcomeFile);
|
|
8637
8830
|
startupSeedWelcomeFileRef.current = seedWelcomeFile;
|
|
8638
|
-
const
|
|
8639
|
-
|
|
8640
|
-
if (showing) markWelcomeGatewayDismissed();
|
|
8641
|
-
return false;
|
|
8642
|
-
});
|
|
8643
|
-
}, []);
|
|
8644
|
-
const handleStartWriting = useCallback18(() => {
|
|
8831
|
+
const [focusAfterWelcome, setFocusAfterWelcome] = useState23(false);
|
|
8832
|
+
const handleTourWelcome = useCallback18(() => {
|
|
8645
8833
|
closeWelcomeGateway();
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
if (
|
|
8650
|
-
|
|
8651
|
-
}
|
|
8652
|
-
}, [
|
|
8834
|
+
setFocusAfterWelcome(true);
|
|
8835
|
+
}, [closeWelcomeGateway]);
|
|
8836
|
+
useEffect29(() => {
|
|
8837
|
+
if (!focusAfterWelcome || welcomeScreenShown) return;
|
|
8838
|
+
setFocusAfterWelcome(false);
|
|
8839
|
+
editorAreaRef.current?.querySelector('[contenteditable="true"]')?.focus({ preventScroll: true });
|
|
8840
|
+
}, [focusAfterWelcome, welcomeScreenShown]);
|
|
8653
8841
|
useEffect29(() => {
|
|
8654
8842
|
const requestId = ++navigationRequestRef.current;
|
|
8655
8843
|
let cancelled = false;
|
|
@@ -8669,8 +8857,8 @@ function DocBlocksShell({
|
|
|
8669
8857
|
getDocBlocksHost().env.platform,
|
|
8670
8858
|
(/* @__PURE__ */ new Date()).toISOString()
|
|
8671
8859
|
);
|
|
8672
|
-
for (const id of reconciliation.removeIds) await
|
|
8673
|
-
for (const workspace of reconciliation.upsert) await
|
|
8860
|
+
for (const id of reconciliation.removeIds) await removeWorkspace2(id);
|
|
8861
|
+
for (const workspace of reconciliation.upsert) await saveWorkspace3(workspace);
|
|
8674
8862
|
workspaceIdRemap = reconciliation.idRemap;
|
|
8675
8863
|
for (const workspace of hostWorkspaces) {
|
|
8676
8864
|
if (workspace.isDefault === true) defaultHostWorkspaceIds.add(workspace.id);
|
|
@@ -8763,12 +8951,12 @@ function DocBlocksShell({
|
|
|
8763
8951
|
const p = await createHostProviderFromWorkspace(ws);
|
|
8764
8952
|
if (!p) continue;
|
|
8765
8953
|
if (!isCurrent()) {
|
|
8766
|
-
await
|
|
8954
|
+
await getFileSystemProviderV211(p)?.dispose();
|
|
8767
8955
|
return;
|
|
8768
8956
|
}
|
|
8769
8957
|
await touchWorkspace2(ws.id);
|
|
8770
8958
|
if (!isCurrent()) {
|
|
8771
|
-
await
|
|
8959
|
+
await getFileSystemProviderV211(p)?.dispose();
|
|
8772
8960
|
return;
|
|
8773
8961
|
}
|
|
8774
8962
|
fsProvider = p;
|
|
@@ -8777,12 +8965,12 @@ function DocBlocksShell({
|
|
|
8777
8965
|
const restored = await (await loadNativeFileSystem()).restoreNativeFolder(ws.id);
|
|
8778
8966
|
if (restored) {
|
|
8779
8967
|
if (!isCurrent()) {
|
|
8780
|
-
await
|
|
8968
|
+
await getFileSystemProviderV211(restored)?.dispose();
|
|
8781
8969
|
return;
|
|
8782
8970
|
}
|
|
8783
8971
|
await touchWorkspace2(ws.id);
|
|
8784
8972
|
if (!isCurrent()) {
|
|
8785
|
-
await
|
|
8973
|
+
await getFileSystemProviderV211(restored)?.dispose();
|
|
8786
8974
|
return;
|
|
8787
8975
|
}
|
|
8788
8976
|
fsProvider = restored;
|
|
@@ -8791,12 +8979,12 @@ function DocBlocksShell({
|
|
|
8791
8979
|
} else {
|
|
8792
8980
|
const p = await createIndexedDbFileSystemProvider(ws.id, ws.name);
|
|
8793
8981
|
if (!isCurrent()) {
|
|
8794
|
-
await
|
|
8982
|
+
await getFileSystemProviderV211(p)?.dispose();
|
|
8795
8983
|
return;
|
|
8796
8984
|
}
|
|
8797
8985
|
await touchWorkspace2(ws.id);
|
|
8798
8986
|
if (!isCurrent()) {
|
|
8799
|
-
await
|
|
8987
|
+
await getFileSystemProviderV211(p)?.dispose();
|
|
8800
8988
|
return;
|
|
8801
8989
|
}
|
|
8802
8990
|
fsProvider = p;
|
|
@@ -8814,11 +9002,11 @@ function DocBlocksShell({
|
|
|
8814
9002
|
rootPath: info.rootPath,
|
|
8815
9003
|
lastOpened: (/* @__PURE__ */ new Date()).toISOString()
|
|
8816
9004
|
};
|
|
8817
|
-
await
|
|
9005
|
+
await saveWorkspace3(descriptor);
|
|
8818
9006
|
if (!isCurrent()) return;
|
|
8819
9007
|
const p = await createHostFileSystemProvider(info.id, info.name, info.rootPath);
|
|
8820
9008
|
if (!isCurrent()) {
|
|
8821
|
-
await
|
|
9009
|
+
await getFileSystemProviderV211(p)?.dispose();
|
|
8822
9010
|
return;
|
|
8823
9011
|
}
|
|
8824
9012
|
fsProvider = p;
|
|
@@ -8827,7 +9015,7 @@ function DocBlocksShell({
|
|
|
8827
9015
|
if (!isCurrent()) return;
|
|
8828
9016
|
const p = await createIndexedDbFileSystemProvider(defaultWs.id, defaultWs.name);
|
|
8829
9017
|
if (!isCurrent()) {
|
|
8830
|
-
await
|
|
9018
|
+
await getFileSystemProviderV211(p)?.dispose();
|
|
8831
9019
|
return;
|
|
8832
9020
|
}
|
|
8833
9021
|
fsProvider = p;
|
|
@@ -8848,7 +9036,7 @@ function DocBlocksShell({
|
|
|
8848
9036
|
setActiveWorkspaceId(fsProvider.id);
|
|
8849
9037
|
adopted = true;
|
|
8850
9038
|
} finally {
|
|
8851
|
-
if (!adopted) await
|
|
9039
|
+
if (!adopted) await getFileSystemProviderV211(fsProvider)?.dispose();
|
|
8852
9040
|
}
|
|
8853
9041
|
})().catch(() => {
|
|
8854
9042
|
if (isCurrent()) {
|
|
@@ -9101,7 +9289,7 @@ function DocBlocksShell({
|
|
|
9101
9289
|
}, [selectedFile, selectedManagedOutput, workspaceOutputsResult]);
|
|
9102
9290
|
useEffect29(() => {
|
|
9103
9291
|
if (!provider) return;
|
|
9104
|
-
const providerV2 =
|
|
9292
|
+
const providerV2 = getFileSystemProviderV211(provider);
|
|
9105
9293
|
const lifecycle = maybeGetDocBlocksHost4()?.lifecycle;
|
|
9106
9294
|
if (!providerV2 || !providerV2.capabilities.watch && !lifecycle?.onResume && !managedOutputRefreshToken)
|
|
9107
9295
|
return;
|
|
@@ -9499,7 +9687,7 @@ function DocBlocksShell({
|
|
|
9499
9687
|
} finally {
|
|
9500
9688
|
if (nextProvider && ownsNextProvider && !adoptedNextProvider) {
|
|
9501
9689
|
try {
|
|
9502
|
-
await
|
|
9690
|
+
await getFileSystemProviderV211(nextProvider)?.dispose();
|
|
9503
9691
|
} catch {
|
|
9504
9692
|
}
|
|
9505
9693
|
}
|
|
@@ -9605,14 +9793,14 @@ function DocBlocksShell({
|
|
|
9605
9793
|
}
|
|
9606
9794
|
}
|
|
9607
9795
|
try {
|
|
9608
|
-
await
|
|
9796
|
+
await removeWorkspace2(activeWorkspaceId);
|
|
9609
9797
|
} catch {
|
|
9610
9798
|
}
|
|
9611
9799
|
setDescriptorRefreshKey((key) => key + 1);
|
|
9612
9800
|
} catch (error) {
|
|
9613
9801
|
if (destinationProvider && !adoptedDestination) {
|
|
9614
9802
|
try {
|
|
9615
|
-
await
|
|
9803
|
+
await getFileSystemProviderV211(destinationProvider)?.dispose();
|
|
9616
9804
|
} catch {
|
|
9617
9805
|
}
|
|
9618
9806
|
}
|
|
@@ -9647,7 +9835,7 @@ function DocBlocksShell({
|
|
|
9647
9835
|
rootPath: info.rootPath,
|
|
9648
9836
|
lastOpened: (/* @__PURE__ */ new Date()).toISOString()
|
|
9649
9837
|
};
|
|
9650
|
-
await
|
|
9838
|
+
await saveWorkspace3(descriptor2);
|
|
9651
9839
|
if (requestId !== navigationRequestRef.current) return;
|
|
9652
9840
|
const provider2 = await createHostFileSystemProvider(info.id, info.name, info.rootPath);
|
|
9653
9841
|
if (!await transitionAwayFromDocument(requestId)) return;
|
|
@@ -9667,7 +9855,7 @@ function DocBlocksShell({
|
|
|
9667
9855
|
type: "native",
|
|
9668
9856
|
lastOpened: (/* @__PURE__ */ new Date()).toISOString()
|
|
9669
9857
|
};
|
|
9670
|
-
await
|
|
9858
|
+
await saveWorkspace3(descriptor);
|
|
9671
9859
|
if (requestId !== navigationRequestRef.current) return;
|
|
9672
9860
|
if (!await transitionAwayFromDocument(requestId)) return;
|
|
9673
9861
|
setProvider(nativeProvider);
|
|
@@ -9690,7 +9878,7 @@ function DocBlocksShell({
|
|
|
9690
9878
|
rootPath: info.rootPath,
|
|
9691
9879
|
lastOpened: (/* @__PURE__ */ new Date()).toISOString()
|
|
9692
9880
|
};
|
|
9693
|
-
await
|
|
9881
|
+
await saveWorkspace3(descriptor);
|
|
9694
9882
|
if (requestId !== navigationRequestRef.current) return;
|
|
9695
9883
|
const cloneProvider = await createHostFileSystemProvider(info.id, info.name, info.rootPath);
|
|
9696
9884
|
if (!await transitionAwayFromDocument(requestId)) return;
|
|
@@ -9718,12 +9906,12 @@ function DocBlocksShell({
|
|
|
9718
9906
|
if (requestId !== navigationRequestRef.current) return null;
|
|
9719
9907
|
if (format === "markdown") {
|
|
9720
9908
|
const content = "# " + filename.replace(/\.[^.]+$/, "") + "\n";
|
|
9721
|
-
const providerV2 =
|
|
9909
|
+
const providerV2 = getFileSystemProviderV211(provider);
|
|
9722
9910
|
if (providerV2) {
|
|
9723
9911
|
try {
|
|
9724
9912
|
await writeProviderText(provider, path, content, "create");
|
|
9725
9913
|
} catch (error) {
|
|
9726
|
-
if (error instanceof
|
|
9914
|
+
if (error instanceof FsError6 && error.code === "already-exists") {
|
|
9727
9915
|
throw new Error("A document with that name already exists.");
|
|
9728
9916
|
}
|
|
9729
9917
|
throw error;
|
|
@@ -9822,7 +10010,7 @@ function DocBlocksShell({
|
|
|
9822
10010
|
}
|
|
9823
10011
|
const path = `/${folderName}`;
|
|
9824
10012
|
try {
|
|
9825
|
-
const providerV2 =
|
|
10013
|
+
const providerV2 = getFileSystemProviderV211(provider);
|
|
9826
10014
|
if (providerV2) {
|
|
9827
10015
|
await providerV2.createDirectory(parseWorkspacePath8(path), { mode: "create" });
|
|
9828
10016
|
} else {
|
|
@@ -9832,7 +10020,7 @@ function DocBlocksShell({
|
|
|
9832
10020
|
await provider.createDirectory(path);
|
|
9833
10021
|
}
|
|
9834
10022
|
} catch (error) {
|
|
9835
|
-
const message = error instanceof
|
|
10023
|
+
const message = error instanceof FsError6 && error.code === "already-exists" ? "A file or folder with that name already exists." : error instanceof Error ? error.message : "Could not create the folder.";
|
|
9836
10024
|
showToast("error", message);
|
|
9837
10025
|
return;
|
|
9838
10026
|
}
|
|
@@ -9882,14 +10070,20 @@ function DocBlocksShell({
|
|
|
9882
10070
|
"new-folder": () => void handleNewFolder(),
|
|
9883
10071
|
shortcuts: openKeyboardShortcuts,
|
|
9884
10072
|
"toggle-sidebar": () => {
|
|
10073
|
+
if (canRestoreSplitView) {
|
|
10074
|
+
updateSidebarPreference("pinned");
|
|
10075
|
+
return;
|
|
10076
|
+
}
|
|
9885
10077
|
if (singlePane) {
|
|
9886
10078
|
setMobileShowEditor((showingEditor) => !showingEditor);
|
|
9887
10079
|
return;
|
|
9888
10080
|
}
|
|
9889
|
-
updateSidebarPreference(
|
|
10081
|
+
updateSidebarPreference("collapsed");
|
|
10082
|
+
setMobileShowEditor(true);
|
|
9890
10083
|
},
|
|
9891
10084
|
"focus-files": () => {
|
|
9892
10085
|
if (singlePane) setMobileShowEditor(false);
|
|
10086
|
+
setSidebarView("files");
|
|
9893
10087
|
window.requestAnimationFrame(() => {
|
|
9894
10088
|
const tree = document.querySelector(".db-tree");
|
|
9895
10089
|
const target = tree?.querySelector('.db-tree-row[tabindex="0"]') ?? tree?.querySelector(".db-tree-row");
|
|
@@ -9919,7 +10113,7 @@ function DocBlocksShell({
|
|
|
9919
10113
|
openKeyboardShortcuts,
|
|
9920
10114
|
singlePane,
|
|
9921
10115
|
mobileShowEditor,
|
|
9922
|
-
|
|
10116
|
+
canRestoreSplitView,
|
|
9923
10117
|
updateSidebarPreference
|
|
9924
10118
|
]
|
|
9925
10119
|
);
|
|
@@ -10052,7 +10246,7 @@ function DocBlocksShell({
|
|
|
10052
10246
|
});
|
|
10053
10247
|
}, [handleNewFile, handleOpenFolder, handleRevealWorkspace, acknowledge, openFind]);
|
|
10054
10248
|
const handleSelect = useCallback18(
|
|
10055
|
-
async (path, kind) => {
|
|
10249
|
+
async (path, kind, createWikiArticle = false) => {
|
|
10056
10250
|
if (!provider || !activeWorkspaceId) return;
|
|
10057
10251
|
const requestId = ++navigationRequestRef.current;
|
|
10058
10252
|
if (kind === "directory") {
|
|
@@ -10069,6 +10263,17 @@ function DocBlocksShell({
|
|
|
10069
10263
|
try {
|
|
10070
10264
|
const transitioned = await documentSession.transitionWithLoad(async () => {
|
|
10071
10265
|
if (requestId !== navigationRequestRef.current) return null;
|
|
10266
|
+
if (createWikiArticle) {
|
|
10267
|
+
if (await ensureShellWikiArticle(
|
|
10268
|
+
provider,
|
|
10269
|
+
parseWorkspacePath8(path),
|
|
10270
|
+
defaultNewFileFormat,
|
|
10271
|
+
outsideInRenderRef.current
|
|
10272
|
+
)) {
|
|
10273
|
+
notifyWorkspaceChanged(activeWorkspaceId, path);
|
|
10274
|
+
}
|
|
10275
|
+
if (requestId !== navigationRequestRef.current) return null;
|
|
10276
|
+
}
|
|
10072
10277
|
openedDocument = await loadEditableShellDocument(
|
|
10073
10278
|
provider,
|
|
10074
10279
|
path,
|
|
@@ -10120,9 +10325,72 @@ function DocBlocksShell({
|
|
|
10120
10325
|
documentSession,
|
|
10121
10326
|
notifyWorkspaceChanged,
|
|
10122
10327
|
transitionAwayFromDocument,
|
|
10123
|
-
showToast
|
|
10328
|
+
showToast,
|
|
10329
|
+
defaultNewFileFormat
|
|
10124
10330
|
]
|
|
10125
10331
|
);
|
|
10332
|
+
const wikiNavigationRef = useRef19(handleSelect);
|
|
10333
|
+
wikiNavigationRef.current = handleSelect;
|
|
10334
|
+
const wikiLinks = useMemo6(() => {
|
|
10335
|
+
if (!provider || !selectedFile || !activeWorkspaceId) return null;
|
|
10336
|
+
const source = selectedFile;
|
|
10337
|
+
const extension = wikiArticleExtension(defaultNewFileFormat);
|
|
10338
|
+
const lookups = /* @__PURE__ */ new Map();
|
|
10339
|
+
let queue = Promise.resolve();
|
|
10340
|
+
const lookup = (target) => {
|
|
10341
|
+
let result = lookups.get(target);
|
|
10342
|
+
if (!result) {
|
|
10343
|
+
result = queue.then(() => findWikiArticle2(provider, source, target, extension));
|
|
10344
|
+
queue = result.then(
|
|
10345
|
+
() => void 0,
|
|
10346
|
+
() => void 0
|
|
10347
|
+
);
|
|
10348
|
+
lookups.set(target, result);
|
|
10349
|
+
}
|
|
10350
|
+
return result;
|
|
10351
|
+
};
|
|
10352
|
+
return {
|
|
10353
|
+
async suggest(query) {
|
|
10354
|
+
const index = workspaceIndex.index;
|
|
10355
|
+
if (!index) return [];
|
|
10356
|
+
workspaceIndex.ensure();
|
|
10357
|
+
await index.whenListed({ timeoutMs: 5e3 });
|
|
10358
|
+
return suggestWikiArticles(
|
|
10359
|
+
index.getFiles(),
|
|
10360
|
+
index.getDirectories(),
|
|
10361
|
+
source,
|
|
10362
|
+
query,
|
|
10363
|
+
extension
|
|
10364
|
+
);
|
|
10365
|
+
},
|
|
10366
|
+
async exists(target) {
|
|
10367
|
+
return (await lookup(target)).exists;
|
|
10368
|
+
},
|
|
10369
|
+
async resolve(target) {
|
|
10370
|
+
const article = await lookup(target);
|
|
10371
|
+
if (!article.exists) return null;
|
|
10372
|
+
const href = selectedSourceFile !== selectedFile ? `/${article.path}` : article.relativePath;
|
|
10373
|
+
return href.split("/").map(encodeURIComponent).join("/");
|
|
10374
|
+
},
|
|
10375
|
+
async open(target, { create }) {
|
|
10376
|
+
const requestId = navigationRequestRef.current;
|
|
10377
|
+
const navigate = wikiNavigationRef.current;
|
|
10378
|
+
const { path } = await lookup(target);
|
|
10379
|
+
if (requestId !== navigationRequestRef.current || navigate !== wikiNavigationRef.current)
|
|
10380
|
+
return;
|
|
10381
|
+
await navigate(path, "file", create);
|
|
10382
|
+
}
|
|
10383
|
+
};
|
|
10384
|
+
}, [
|
|
10385
|
+
provider,
|
|
10386
|
+
selectedFile,
|
|
10387
|
+
selectedSourceFile,
|
|
10388
|
+
activeWorkspaceId,
|
|
10389
|
+
defaultNewFileFormat,
|
|
10390
|
+
workspaceIndex.index,
|
|
10391
|
+
workspaceIndex.ensure,
|
|
10392
|
+
workspaceIndex.status.generation
|
|
10393
|
+
]);
|
|
10126
10394
|
const handleEnableOutsideInEditing = useCallback18(
|
|
10127
10395
|
async (path) => {
|
|
10128
10396
|
if (!provider || !activeWorkspaceId) {
|
|
@@ -10250,44 +10518,32 @@ function DocBlocksShell({
|
|
|
10250
10518
|
if (!target) {
|
|
10251
10519
|
showToast(
|
|
10252
10520
|
"error",
|
|
10253
|
-
"DocBlocks only opens HTTP(S) links or Markdown files inside this workspace."
|
|
10521
|
+
"DocBlocks only opens HTTP(S) links or Markdown and HTML files inside this workspace."
|
|
10254
10522
|
);
|
|
10255
10523
|
return true;
|
|
10256
10524
|
}
|
|
10257
10525
|
if (target.kind === "fragment") return false;
|
|
10258
10526
|
if (target.kind === "external") {
|
|
10259
|
-
|
|
10260
|
-
|
|
10261
|
-
|
|
10262
|
-
|
|
10263
|
-
|
|
10264
|
-
|
|
10265
|
-
);
|
|
10266
|
-
});
|
|
10267
|
-
} else if (typeof window !== "undefined") {
|
|
10268
|
-
try {
|
|
10269
|
-
window.open(target.url, "_blank", "noopener,noreferrer");
|
|
10270
|
-
} catch (error) {
|
|
10271
|
-
showToast(
|
|
10272
|
-
"error",
|
|
10273
|
-
error instanceof Error ? error.message : "Could not open the external link."
|
|
10274
|
-
);
|
|
10275
|
-
}
|
|
10276
|
-
}
|
|
10527
|
+
void openExternalUrl(target.url).catch((error) => {
|
|
10528
|
+
showToast(
|
|
10529
|
+
"error",
|
|
10530
|
+
error instanceof Error ? error.message : "Could not open the external link."
|
|
10531
|
+
);
|
|
10532
|
+
});
|
|
10277
10533
|
return true;
|
|
10278
10534
|
}
|
|
10279
10535
|
void (async () => {
|
|
10280
10536
|
if (!provider) return;
|
|
10281
10537
|
try {
|
|
10282
10538
|
if (!await providerEntryExists(provider, target.path)) {
|
|
10283
|
-
showToast("error", "The linked
|
|
10539
|
+
showToast("error", "The linked document was not found in this workspace.");
|
|
10284
10540
|
return;
|
|
10285
10541
|
}
|
|
10286
10542
|
await handleSelect(target.path, "file");
|
|
10287
10543
|
} catch (error) {
|
|
10288
10544
|
showToast(
|
|
10289
10545
|
"error",
|
|
10290
|
-
error instanceof Error ? error.message : "Could not open the linked
|
|
10546
|
+
error instanceof Error ? error.message : "Could not open the linked document."
|
|
10291
10547
|
);
|
|
10292
10548
|
}
|
|
10293
10549
|
})();
|
|
@@ -10561,7 +10817,7 @@ function DocBlocksShell({
|
|
|
10561
10817
|
} finally {
|
|
10562
10818
|
if (access.owned) {
|
|
10563
10819
|
try {
|
|
10564
|
-
await
|
|
10820
|
+
await getFileSystemProviderV211(access.provider)?.dispose();
|
|
10565
10821
|
} catch {
|
|
10566
10822
|
}
|
|
10567
10823
|
}
|
|
@@ -10630,7 +10886,7 @@ function DocBlocksShell({
|
|
|
10630
10886
|
} finally {
|
|
10631
10887
|
if (access.owned) {
|
|
10632
10888
|
try {
|
|
10633
|
-
await
|
|
10889
|
+
await getFileSystemProviderV211(access.provider)?.dispose();
|
|
10634
10890
|
} catch {
|
|
10635
10891
|
}
|
|
10636
10892
|
}
|
|
@@ -10648,32 +10904,73 @@ function DocBlocksShell({
|
|
|
10648
10904
|
showToast
|
|
10649
10905
|
]
|
|
10650
10906
|
);
|
|
10907
|
+
const restoreInputRef = useRef19(null);
|
|
10908
|
+
const restoreInProgress = useRef19(false);
|
|
10909
|
+
const handleRestoreBackup = useCallback18(
|
|
10910
|
+
async (file) => {
|
|
10911
|
+
if (restoreInProgress.current) {
|
|
10912
|
+
showToast("error", "A backup is already being restored. Please wait.");
|
|
10913
|
+
return;
|
|
10914
|
+
}
|
|
10915
|
+
restoreInProgress.current = true;
|
|
10916
|
+
try {
|
|
10917
|
+
await documentSession.flush("backup");
|
|
10918
|
+
const restored = await restoreBrowserBackup(file);
|
|
10919
|
+
setDescriptorRefreshKey((key) => key + 1);
|
|
10920
|
+
if (restored[0]) await handleWorkspaceSelect(restored[0]);
|
|
10921
|
+
showToast(
|
|
10922
|
+
"success",
|
|
10923
|
+
`Restored ${restored.length} workspace(s) as new copies. Your existing workspaces are unchanged.`
|
|
10924
|
+
);
|
|
10925
|
+
} catch (error) {
|
|
10926
|
+
showToast(
|
|
10927
|
+
"error",
|
|
10928
|
+
`Could not restore ${file.name}: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
10929
|
+
);
|
|
10930
|
+
} finally {
|
|
10931
|
+
restoreInProgress.current = false;
|
|
10932
|
+
}
|
|
10933
|
+
},
|
|
10934
|
+
[documentSession, handleWorkspaceSelect, showToast]
|
|
10935
|
+
);
|
|
10936
|
+
const importOrRestore = useCallback18(
|
|
10937
|
+
async (files) => {
|
|
10938
|
+
const backups = hostSupports2("nativeWorkspaces") ? [] : files.filter((file) => /\.zip$/i.test(file.name));
|
|
10939
|
+
const documents = files.filter((file) => !backups.includes(file));
|
|
10940
|
+
const result = provider ? await importDroppedFiles(documents, provider) : null;
|
|
10941
|
+
for (const file of backups) await handleRestoreBackup(file);
|
|
10942
|
+
return result;
|
|
10943
|
+
},
|
|
10944
|
+
[handleRestoreBackup, provider]
|
|
10945
|
+
);
|
|
10651
10946
|
const handleImportFiles = useCallback18(
|
|
10652
10947
|
async (files) => {
|
|
10653
10948
|
if (!provider) return;
|
|
10654
|
-
const result = await
|
|
10949
|
+
const result = await importOrRestore(files);
|
|
10950
|
+
if (!result) return;
|
|
10655
10951
|
notifyWorkspaceChanged(activeWorkspaceId);
|
|
10656
10952
|
setExplorerKey((k) => k + 1);
|
|
10657
10953
|
const summary = summariseImport(result);
|
|
10658
10954
|
if (summary) showToast(summary.kind, summary.message);
|
|
10659
10955
|
},
|
|
10660
|
-
[activeWorkspaceId, notifyWorkspaceChanged, provider, showToast]
|
|
10956
|
+
[activeWorkspaceId, notifyWorkspaceChanged, provider, showToast, importOrRestore]
|
|
10661
10957
|
);
|
|
10662
10958
|
const handleImportFilesToEditor = useCallback18(
|
|
10663
10959
|
async (files) => {
|
|
10664
10960
|
if (!provider) return;
|
|
10665
|
-
const result = await
|
|
10961
|
+
const result = await importOrRestore(files);
|
|
10962
|
+
if (!result) return;
|
|
10666
10963
|
notifyWorkspaceChanged(activeWorkspaceId);
|
|
10667
10964
|
setExplorerKey((k) => k + 1);
|
|
10668
10965
|
const summary = summariseImport(result);
|
|
10669
10966
|
if (summary) showToast(summary.kind, summary.message);
|
|
10670
10967
|
const imported = result.imported;
|
|
10671
|
-
if (imported.length === 1 && result.failed.length === 0) {
|
|
10968
|
+
if (imported.length === 1 && result.failed.length === 0 && !files.some((file) => /\.zip$/i.test(file.name))) {
|
|
10672
10969
|
const only = imported[0];
|
|
10673
10970
|
if (only) void handleSelect(only.path, "file");
|
|
10674
10971
|
}
|
|
10675
10972
|
},
|
|
10676
|
-
[activeWorkspaceId, notifyWorkspaceChanged, provider, showToast, handleSelect]
|
|
10973
|
+
[activeWorkspaceId, notifyWorkspaceChanged, provider, showToast, handleSelect, importOrRestore]
|
|
10677
10974
|
);
|
|
10678
10975
|
const editorDropActive = useEditorFileDrop(
|
|
10679
10976
|
editorAreaRef,
|
|
@@ -10701,7 +10998,7 @@ function DocBlocksShell({
|
|
|
10701
10998
|
confirmLabel: "Rename"
|
|
10702
10999
|
});
|
|
10703
11000
|
if (!newName || newName === ws.name) return;
|
|
10704
|
-
await
|
|
11001
|
+
await saveWorkspace3({ ...ws, name: newName });
|
|
10705
11002
|
setPinnedDocuments(
|
|
10706
11003
|
(current) => renamePinnedDocumentWorkspace(current, activeWorkspaceId, newName)
|
|
10707
11004
|
);
|
|
@@ -10727,7 +11024,7 @@ function DocBlocksShell({
|
|
|
10727
11024
|
throw error;
|
|
10728
11025
|
}
|
|
10729
11026
|
if (!isCurrent()) {
|
|
10730
|
-
await
|
|
11027
|
+
await getFileSystemProviderV211(mem)?.dispose();
|
|
10731
11028
|
await revokeAbandonedResource();
|
|
10732
11029
|
return;
|
|
10733
11030
|
}
|
|
@@ -10775,7 +11072,7 @@ function DocBlocksShell({
|
|
|
10775
11072
|
} finally {
|
|
10776
11073
|
try {
|
|
10777
11074
|
if (!adoptionStarted) {
|
|
10778
|
-
await
|
|
11075
|
+
await getFileSystemProviderV211(mem)?.dispose();
|
|
10779
11076
|
}
|
|
10780
11077
|
} finally {
|
|
10781
11078
|
if (!opened) await revokeAbandonedResource();
|
|
@@ -10796,6 +11093,7 @@ function DocBlocksShell({
|
|
|
10796
11093
|
if (!opened && requestId === navigationRequestRef.current) {
|
|
10797
11094
|
throw new Error("The requested workspace file is no longer available.");
|
|
10798
11095
|
}
|
|
11096
|
+
if (opened) closeWelcomeGateway();
|
|
10799
11097
|
return opened;
|
|
10800
11098
|
}
|
|
10801
11099
|
);
|
|
@@ -10807,7 +11105,7 @@ function DocBlocksShell({
|
|
|
10807
11105
|
);
|
|
10808
11106
|
});
|
|
10809
11107
|
});
|
|
10810
|
-
}, [openFromIds, openTransient, workspaceAuthorityBarrier, showToast]);
|
|
11108
|
+
}, [openFromIds, openTransient, workspaceAuthorityBarrier, showToast, closeWelcomeGateway]);
|
|
10811
11109
|
const openTransientFromHandle = useCallback18(
|
|
10812
11110
|
async (handle) => {
|
|
10813
11111
|
const name = handle.name;
|
|
@@ -10845,7 +11143,7 @@ function DocBlocksShell({
|
|
|
10845
11143
|
push: true
|
|
10846
11144
|
});
|
|
10847
11145
|
} finally {
|
|
10848
|
-
if (!adoptionStarted) await
|
|
11146
|
+
if (!adoptionStarted) await getFileSystemProviderV211(mem)?.dispose();
|
|
10849
11147
|
}
|
|
10850
11148
|
},
|
|
10851
11149
|
[adoptTransientWorkspace]
|
|
@@ -10875,8 +11173,11 @@ function DocBlocksShell({
|
|
|
10875
11173
|
import("@bendyline/squisq-formats/container")
|
|
10876
11174
|
]);
|
|
10877
11175
|
const container = new MemoryContentContainer();
|
|
10878
|
-
|
|
10879
|
-
|
|
11176
|
+
const source = getFileSystemProviderV211(provider);
|
|
11177
|
+
if (!source) throw new Error("This workspace does not support complete backups.");
|
|
11178
|
+
const workspaces = await appendWorkspaceBackup(container, source, []);
|
|
11179
|
+
await finishWorkspaceBackup(container, workspaces);
|
|
11180
|
+
const blob = await containerToZip(container, { compression: "STORE" });
|
|
10880
11181
|
const url = URL.createObjectURL(blob);
|
|
10881
11182
|
const a = document.createElement("a");
|
|
10882
11183
|
a.href = url;
|
|
@@ -10885,8 +11186,7 @@ function DocBlocksShell({
|
|
|
10885
11186
|
a.click();
|
|
10886
11187
|
URL.revokeObjectURL(url);
|
|
10887
11188
|
} catch (err) {
|
|
10888
|
-
|
|
10889
|
-
showToast("error", "Failed to download workspace. See console for details.");
|
|
11189
|
+
showToast("error", err instanceof Error ? err.message : "Failed to download workspace.");
|
|
10890
11190
|
}
|
|
10891
11191
|
}, [provider, documentSession, showToast]);
|
|
10892
11192
|
const handleDownloadAllWorkspaces = useCallback18(async () => {
|
|
@@ -10906,7 +11206,7 @@ function DocBlocksShell({
|
|
|
10906
11206
|
return;
|
|
10907
11207
|
}
|
|
10908
11208
|
const container = new MemoryContentContainer();
|
|
10909
|
-
|
|
11209
|
+
let backupWorkspaces = [];
|
|
10910
11210
|
const skipped = [];
|
|
10911
11211
|
for (const ws of candidates) {
|
|
10912
11212
|
let p = null;
|
|
@@ -10932,24 +11232,20 @@ function DocBlocksShell({
|
|
|
10932
11232
|
skipped.push(ws.name);
|
|
10933
11233
|
continue;
|
|
10934
11234
|
}
|
|
10935
|
-
const base = (ws.name || "workspace").replace(/[^a-z0-9_\- ]/gi, "_").trim() || "workspace";
|
|
10936
|
-
let folder = base;
|
|
10937
|
-
let suffix = 2;
|
|
10938
|
-
while (usedFolders.has(folder)) {
|
|
10939
|
-
folder = `${base} (${suffix++})`;
|
|
10940
|
-
}
|
|
10941
|
-
usedFolders.add(folder);
|
|
10942
11235
|
try {
|
|
10943
|
-
|
|
11236
|
+
const source = getFileSystemProviderV211(p);
|
|
11237
|
+
if (!source) throw new Error("This workspace does not support complete backups.");
|
|
11238
|
+
backupWorkspaces = await appendWorkspaceBackup(container, source, backupWorkspaces);
|
|
10944
11239
|
} finally {
|
|
10945
|
-
if (ownsProvider) await
|
|
11240
|
+
if (ownsProvider) await getFileSystemProviderV211(p)?.dispose();
|
|
10946
11241
|
}
|
|
10947
11242
|
}
|
|
10948
|
-
if (
|
|
11243
|
+
if (backupWorkspaces.length === 0) {
|
|
10949
11244
|
showToast("error", "No workspaces could be opened for download.");
|
|
10950
11245
|
return;
|
|
10951
11246
|
}
|
|
10952
|
-
|
|
11247
|
+
await finishWorkspaceBackup(container, backupWorkspaces);
|
|
11248
|
+
const blob = await containerToZip(container, { compression: "STORE" });
|
|
10953
11249
|
const url = URL.createObjectURL(blob);
|
|
10954
11250
|
const a = document.createElement("a");
|
|
10955
11251
|
a.href = url;
|
|
@@ -10959,12 +11255,11 @@ function DocBlocksShell({
|
|
|
10959
11255
|
if (skipped.length > 0) {
|
|
10960
11256
|
await acknowledge({
|
|
10961
11257
|
title: "Some workspaces were skipped",
|
|
10962
|
-
message: `Downloaded ${
|
|
11258
|
+
message: `Downloaded ${backupWorkspaces.length} workspace(s). Skipped ${skipped.length} that require re-granting access: ${skipped.join(", ")}.`
|
|
10963
11259
|
});
|
|
10964
11260
|
}
|
|
10965
11261
|
} catch (err) {
|
|
10966
|
-
|
|
10967
|
-
showToast("error", "Failed to download all workspaces. See console for details.");
|
|
11262
|
+
showToast("error", err instanceof Error ? err.message : "Failed to download all workspaces.");
|
|
10968
11263
|
}
|
|
10969
11264
|
}, [documentSession, acknowledge, showToast]);
|
|
10970
11265
|
const handleKeepBrowserData = useCallback18(async () => {
|
|
@@ -11055,7 +11350,7 @@ function DocBlocksShell({
|
|
|
11055
11350
|
} else if (ws?.type === "indexeddb") {
|
|
11056
11351
|
await (await loadIndexedDbFileSystem()).deleteIndexedDBWorkspaceData(workspaceId);
|
|
11057
11352
|
}
|
|
11058
|
-
await
|
|
11353
|
+
await removeWorkspace2(workspaceId);
|
|
11059
11354
|
forgetRecentDocuments(workspaceId);
|
|
11060
11355
|
for (const document2 of pinnedDocuments) {
|
|
11061
11356
|
if (document2.workspaceId === workspaceId) {
|
|
@@ -11083,7 +11378,7 @@ function DocBlocksShell({
|
|
|
11083
11378
|
rootPath: info.rootPath,
|
|
11084
11379
|
lastOpened: (/* @__PURE__ */ new Date()).toISOString()
|
|
11085
11380
|
};
|
|
11086
|
-
await
|
|
11381
|
+
await saveWorkspace3(descriptor);
|
|
11087
11382
|
const p = await createHostFileSystemProvider(info.id, info.name, info.rootPath);
|
|
11088
11383
|
setProvider(p);
|
|
11089
11384
|
setActiveWorkspaceId(info.id);
|
|
@@ -11110,7 +11405,7 @@ function DocBlocksShell({
|
|
|
11110
11405
|
transitionAwayFromDocument
|
|
11111
11406
|
]
|
|
11112
11407
|
);
|
|
11113
|
-
return /* @__PURE__ */
|
|
11408
|
+
return /* @__PURE__ */ jsx18(
|
|
11114
11409
|
"div",
|
|
11115
11410
|
{
|
|
11116
11411
|
ref: shellRef,
|
|
@@ -11119,10 +11414,10 @@ function DocBlocksShell({
|
|
|
11119
11414
|
"data-accent": accentColor,
|
|
11120
11415
|
"data-interface-font": interfaceFont === "fixed" ? "fixed" : void 0,
|
|
11121
11416
|
"data-document-status": documentSnapshot.status,
|
|
11122
|
-
children: /* @__PURE__ */
|
|
11417
|
+
children: /* @__PURE__ */ jsxs16(GitContext.Provider, { value: git, children: [
|
|
11123
11418
|
promptDialog,
|
|
11124
11419
|
confirmDialog,
|
|
11125
|
-
quickOpenOpen && activeWorkspaceId && /* @__PURE__ */
|
|
11420
|
+
quickOpenOpen && activeWorkspaceId && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(
|
|
11126
11421
|
QuickOpenDialog,
|
|
11127
11422
|
{
|
|
11128
11423
|
index: workspaceIndex.index,
|
|
@@ -11136,8 +11431,8 @@ function DocBlocksShell({
|
|
|
11136
11431
|
onClose: () => setQuickOpenOpen(false)
|
|
11137
11432
|
}
|
|
11138
11433
|
) }),
|
|
11139
|
-
shortcutsOpen && /* @__PURE__ */
|
|
11140
|
-
newDocumentDialogOpen && /* @__PURE__ */
|
|
11434
|
+
shortcutsOpen && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(KeyboardShortcutsDialog, { onClose: () => setShortcutsOpen(false) }) }),
|
|
11435
|
+
newDocumentDialogOpen && /* @__PURE__ */ jsx18(
|
|
11141
11436
|
NewDocumentDialog,
|
|
11142
11437
|
{
|
|
11143
11438
|
initialFormat: defaultNewFileFormat,
|
|
@@ -11147,8 +11442,8 @@ function DocBlocksShell({
|
|
|
11147
11442
|
}
|
|
11148
11443
|
}
|
|
11149
11444
|
),
|
|
11150
|
-
workspaceStartupError && /* @__PURE__ */
|
|
11151
|
-
saveToast && /* @__PURE__ */
|
|
11445
|
+
workspaceStartupError && /* @__PURE__ */ jsx18("div", { className: "db-save-toast db-save-toast--error", role: "alert", "aria-live": "assertive", children: workspaceStartupError }),
|
|
11446
|
+
saveToast && /* @__PURE__ */ jsx18(
|
|
11152
11447
|
"div",
|
|
11153
11448
|
{
|
|
11154
11449
|
className: "db-save-toast db-save-toast--" + saveToast.kind,
|
|
@@ -11157,12 +11452,12 @@ function DocBlocksShell({
|
|
|
11157
11452
|
children: saveToast.message
|
|
11158
11453
|
}
|
|
11159
11454
|
),
|
|
11160
|
-
offlineReadyToast && !saveToast && /* @__PURE__ */
|
|
11161
|
-
documentSnapshot.conflict && /* @__PURE__ */
|
|
11162
|
-
/* @__PURE__ */
|
|
11163
|
-
/* @__PURE__ */
|
|
11455
|
+
offlineReadyToast && !saveToast && /* @__PURE__ */ jsx18("div", { className: "db-save-toast db-save-toast--success", role: "status", "aria-live": "polite", children: "DocBlocks is ready to work offline." }),
|
|
11456
|
+
documentSnapshot.conflict && /* @__PURE__ */ jsxs16("div", { className: "db-document-conflict", role: "alert", children: [
|
|
11457
|
+
/* @__PURE__ */ jsx18("span", { children: documentSnapshot.conflict.recoveredDraft ? "A recovery draft from a previous session differs from the saved file. The saved file may be newer. Choose which version to use." : "This document changed outside DocBlocks. Your unsaved version is still intact." }),
|
|
11458
|
+
/* @__PURE__ */ jsx18("div", { className: "db-document-conflict-actions", children: /* @__PURE__ */ jsx18("button", { type: "button", onClick: () => setShowConflictComparison(true), children: "Compare versions" }) })
|
|
11164
11459
|
] }),
|
|
11165
|
-
documentSnapshot.conflict && showConflictComparison && /* @__PURE__ */
|
|
11460
|
+
documentSnapshot.conflict && showConflictComparison && /* @__PURE__ */ jsx18(Suspense2, { fallback: /* @__PURE__ */ jsx18("div", { role: "status", children: "Loading version comparison\u2026" }), children: /* @__PURE__ */ jsx18(
|
|
11166
11461
|
DocumentConflictDialog,
|
|
11167
11462
|
{
|
|
11168
11463
|
conflict: documentSnapshot.conflict,
|
|
@@ -11172,14 +11467,14 @@ function DocBlocksShell({
|
|
|
11172
11467
|
onClose: () => setShowConflictComparison(false)
|
|
11173
11468
|
}
|
|
11174
11469
|
) }),
|
|
11175
|
-
storageFull && !documentSnapshot.conflict && /* @__PURE__ */
|
|
11176
|
-
/* @__PURE__ */
|
|
11177
|
-
/* @__PURE__ */
|
|
11178
|
-
/* @__PURE__ */
|
|
11179
|
-
/* @__PURE__ */
|
|
11470
|
+
storageFull && !documentSnapshot.conflict && /* @__PURE__ */ jsxs16("div", { className: "db-storage-full-banner", role: "alert", children: [
|
|
11471
|
+
/* @__PURE__ */ jsx18("span", { children: "Browser storage is full -- changes can\u2019t be saved. Free up space or back up your work now." }),
|
|
11472
|
+
/* @__PURE__ */ jsxs16("div", { className: "db-storage-full-banner-actions", children: [
|
|
11473
|
+
/* @__PURE__ */ jsx18("button", { type: "button", onClick: () => void handleDownloadAllWorkspaces(), children: "Back up all workspaces" }),
|
|
11474
|
+
/* @__PURE__ */ jsx18("button", { type: "button", onClick: () => setStorageFull(false), children: "Dismiss" })
|
|
11180
11475
|
] })
|
|
11181
11476
|
] }),
|
|
11182
|
-
workspaceSettingsOpen && activeWorkspaceDescriptor && /* @__PURE__ */
|
|
11477
|
+
workspaceSettingsOpen && activeWorkspaceDescriptor && /* @__PURE__ */ jsx18(
|
|
11183
11478
|
WorkspaceSettingsDialog,
|
|
11184
11479
|
{
|
|
11185
11480
|
workspace: activeWorkspaceDescriptor,
|
|
@@ -11192,8 +11487,8 @@ function DocBlocksShell({
|
|
|
11192
11487
|
onClose: () => setWorkspaceSettingsOpen(false)
|
|
11193
11488
|
}
|
|
11194
11489
|
),
|
|
11195
|
-
/* @__PURE__ */
|
|
11196
|
-
/* @__PURE__ */
|
|
11490
|
+
/* @__PURE__ */ jsxs16("div", { className: "db-shell-panes", ref: panesRef, children: [
|
|
11491
|
+
/* @__PURE__ */ jsxs16(
|
|
11197
11492
|
"aside",
|
|
11198
11493
|
{
|
|
11199
11494
|
ref: sidebarRef,
|
|
@@ -11201,8 +11496,8 @@ function DocBlocksShell({
|
|
|
11201
11496
|
"aria-label": "Workspace and files",
|
|
11202
11497
|
style: singlePane ? void 0 : { width: `${sidebarWidth}px` },
|
|
11203
11498
|
children: [
|
|
11204
|
-
/* @__PURE__ */
|
|
11205
|
-
/* @__PURE__ */
|
|
11499
|
+
/* @__PURE__ */ jsxs16("div", { className: "db-shell-sidebar-header", children: [
|
|
11500
|
+
/* @__PURE__ */ jsx18(
|
|
11206
11501
|
AppMenu,
|
|
11207
11502
|
{
|
|
11208
11503
|
logoUrl,
|
|
@@ -11224,6 +11519,7 @@ function DocBlocksShell({
|
|
|
11224
11519
|
onVersioningPreferenceChange: handleVersioningPreferenceChange,
|
|
11225
11520
|
onOpenWorkspaceSettings: activeWorkspaceDescriptor ? handleOpenWorkspaceSettings : void 0,
|
|
11226
11521
|
onDownloadAllWorkspaces: handleDownloadAllWorkspaces,
|
|
11522
|
+
onRestoreBackup: hostSupports2("nativeWorkspaces") ? void 0 : () => restoreInputRef.current?.click(),
|
|
11227
11523
|
onShowKeyboardShortcuts: singlePane ? void 0 : openKeyboardShortcuts,
|
|
11228
11524
|
onKeepBrowserData: showBrowserStorageWarning && !browserStoragePersistent ? handleKeepBrowserData : void 0,
|
|
11229
11525
|
onInstallApp: installPromptEvent ? handleInstallApp : void 0,
|
|
@@ -11236,10 +11532,26 @@ function DocBlocksShell({
|
|
|
11236
11532
|
settingsRequest
|
|
11237
11533
|
}
|
|
11238
11534
|
),
|
|
11239
|
-
/* @__PURE__ */
|
|
11535
|
+
/* @__PURE__ */ jsx18(
|
|
11536
|
+
"input",
|
|
11537
|
+
{
|
|
11538
|
+
ref: restoreInputRef,
|
|
11539
|
+
type: "file",
|
|
11540
|
+
accept: ".zip,application/zip",
|
|
11541
|
+
"aria-label": "Restore workspace backup",
|
|
11542
|
+
hidden: true,
|
|
11543
|
+
onChange: (event) => {
|
|
11544
|
+
const file = event.currentTarget.files?.[0];
|
|
11545
|
+
event.currentTarget.value = "";
|
|
11546
|
+
if (file) void handleRestoreBackup(file);
|
|
11547
|
+
}
|
|
11548
|
+
}
|
|
11549
|
+
),
|
|
11550
|
+
/* @__PURE__ */ jsx18(
|
|
11240
11551
|
WorkspacePicker,
|
|
11241
11552
|
{
|
|
11242
11553
|
activeWorkspaceId,
|
|
11554
|
+
loading: workspaceStarting,
|
|
11243
11555
|
refreshKey: descriptorRefreshKey,
|
|
11244
11556
|
onSelect: handleWorkspaceSelect,
|
|
11245
11557
|
onOpenFolder: handleOpenFolder,
|
|
@@ -11247,7 +11559,7 @@ function DocBlocksShell({
|
|
|
11247
11559
|
onRemoveWorkspace: (workspace) => void handleRemoveWorkspace(workspace.id)
|
|
11248
11560
|
}
|
|
11249
11561
|
),
|
|
11250
|
-
/* @__PURE__ */
|
|
11562
|
+
/* @__PURE__ */ jsx18(
|
|
11251
11563
|
WorkspaceSettingsButton,
|
|
11252
11564
|
{
|
|
11253
11565
|
onSettings: handleOpenWorkspaceSettings,
|
|
@@ -11258,28 +11570,29 @@ function DocBlocksShell({
|
|
|
11258
11570
|
}
|
|
11259
11571
|
}
|
|
11260
11572
|
),
|
|
11261
|
-
canRestoreSplitView && /* @__PURE__ */
|
|
11573
|
+
canRestoreSplitView && /* @__PURE__ */ jsx18(
|
|
11262
11574
|
"button",
|
|
11263
11575
|
{
|
|
11264
11576
|
className: "db-restore-split",
|
|
11265
11577
|
onClick: () => updateSidebarPreference("pinned"),
|
|
11266
11578
|
"aria-label": "Restore split view",
|
|
11267
11579
|
title: "Restore split view",
|
|
11268
|
-
children: /* @__PURE__ */
|
|
11580
|
+
children: /* @__PURE__ */ jsx18(SplitViewIcon, {})
|
|
11269
11581
|
}
|
|
11270
11582
|
),
|
|
11271
|
-
/* @__PURE__ */
|
|
11583
|
+
/* @__PURE__ */ jsx18("span", { className: "db-window-drag-grip", "aria-hidden": true })
|
|
11272
11584
|
] }),
|
|
11273
|
-
git.available && /* @__PURE__ */
|
|
11585
|
+
git.available && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(
|
|
11274
11586
|
GitUI,
|
|
11275
11587
|
{
|
|
11276
11588
|
onOpenFile: (path) => void handleSelect(path, "file"),
|
|
11277
11589
|
onWorkspaceCloned: handleWorkspaceCloned
|
|
11278
11590
|
}
|
|
11279
11591
|
) }),
|
|
11280
|
-
/* @__PURE__ */
|
|
11592
|
+
/* @__PURE__ */ jsx18(
|
|
11281
11593
|
FileExplorer,
|
|
11282
11594
|
{
|
|
11595
|
+
loading: workspaceStarting,
|
|
11283
11596
|
className: sidebarView === "search" ? "db-sidebar-view--hidden" : void 0,
|
|
11284
11597
|
onShowSearch: canBrowseWorkspace ? openWorkspaceSearch : void 0,
|
|
11285
11598
|
searchShortcutLabel: searchShortcut,
|
|
@@ -11311,7 +11624,7 @@ function DocBlocksShell({
|
|
|
11311
11624
|
},
|
|
11312
11625
|
explorerKey
|
|
11313
11626
|
),
|
|
11314
|
-
searchMounted && /* @__PURE__ */
|
|
11627
|
+
searchMounted && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(
|
|
11315
11628
|
WorkspaceSearchPanel,
|
|
11316
11629
|
{
|
|
11317
11630
|
index: workspaceIndex.index,
|
|
@@ -11322,41 +11635,38 @@ function DocBlocksShell({
|
|
|
11322
11635
|
onShowFiles: () => setSidebarView("files")
|
|
11323
11636
|
}
|
|
11324
11637
|
) }),
|
|
11325
|
-
singlePane && showWelcomeGateway && /* @__PURE__ */
|
|
11326
|
-
/* @__PURE__ */
|
|
11327
|
-
/* @__PURE__ */
|
|
11328
|
-
/* @__PURE__ */
|
|
11329
|
-
|
|
11330
|
-
|
|
11638
|
+
singlePane && showWelcomeGateway && /* @__PURE__ */ jsxs16("section", { className: "db-mobile-first-run", "aria-labelledby": "db-mobile-first-run-title", children: [
|
|
11639
|
+
/* @__PURE__ */ jsx18("p", { className: "db-mobile-first-run-eyebrow", children: "Local-first Markdown editor" }),
|
|
11640
|
+
/* @__PURE__ */ jsx18("h1", { id: "db-mobile-first-run-title", children: "Welcome to DocBlocks" }),
|
|
11641
|
+
/* @__PURE__ */ jsxs16("p", { children: [
|
|
11642
|
+
WELCOME_SUMMARY,
|
|
11643
|
+
" ",
|
|
11644
|
+
WELCOME_PRIVACY_NOTE
|
|
11645
|
+
] }),
|
|
11646
|
+
/* @__PURE__ */ jsxs16("div", { className: "db-mobile-first-run-actions", children: [
|
|
11647
|
+
/* @__PURE__ */ jsx18("button", { type: "button", onClick: () => void handleNewFile(), children: "Create a document" }),
|
|
11648
|
+
/* @__PURE__ */ jsx18(
|
|
11331
11649
|
"button",
|
|
11332
11650
|
{
|
|
11333
11651
|
type: "button",
|
|
11652
|
+
className: "db-mobile-first-run-secondary",
|
|
11334
11653
|
onClick: () => {
|
|
11335
11654
|
closeWelcomeGateway();
|
|
11336
11655
|
setMobileShowEditor(true);
|
|
11337
11656
|
},
|
|
11338
11657
|
children: "Tour the welcome document"
|
|
11339
11658
|
}
|
|
11340
|
-
),
|
|
11341
|
-
/* @__PURE__ */ jsx17(
|
|
11342
|
-
"button",
|
|
11343
|
-
{
|
|
11344
|
-
type: "button",
|
|
11345
|
-
className: "db-mobile-first-run-secondary",
|
|
11346
|
-
onClick: () => void handleNewFile(),
|
|
11347
|
-
children: "Create a document"
|
|
11348
|
-
}
|
|
11349
11659
|
)
|
|
11350
11660
|
] })
|
|
11351
11661
|
] }),
|
|
11352
|
-
git.available && git.pendingGrant && /* @__PURE__ */
|
|
11353
|
-
/* @__PURE__ */
|
|
11354
|
-
/* @__PURE__ */
|
|
11355
|
-
/* @__PURE__ */
|
|
11356
|
-
/* @__PURE__ */
|
|
11357
|
-
/* @__PURE__ */
|
|
11358
|
-
/* @__PURE__ */
|
|
11359
|
-
showBrowserStorageWarning && /* @__PURE__ */
|
|
11662
|
+
git.available && git.pendingGrant && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(GitGrantNotice, {}) }),
|
|
11663
|
+
/* @__PURE__ */ jsxs16("div", { className: "db-shell-sidebar-footer", children: [
|
|
11664
|
+
/* @__PURE__ */ jsx18("a", { href: "https://docblocks.com/docs/", target: "_blank", rel: "noopener noreferrer", children: "Docs" }),
|
|
11665
|
+
/* @__PURE__ */ jsx18("span", { className: "db-shell-sidebar-footer-separator", "aria-hidden": "true", children: "\u2022" }),
|
|
11666
|
+
/* @__PURE__ */ jsx18("a", { href: "https://docblocks.com/terms/", target: "_blank", rel: "noopener noreferrer", children: "Terms" }),
|
|
11667
|
+
/* @__PURE__ */ jsx18("span", { className: "db-shell-sidebar-footer-separator", "aria-hidden": "true", children: "\u2022" }),
|
|
11668
|
+
/* @__PURE__ */ jsx18("a", { href: issueReportUrl, target: "_blank", rel: "noopener noreferrer", children: "Report issue" }),
|
|
11669
|
+
showBrowserStorageWarning && /* @__PURE__ */ jsx18(Fragment11, { children: /* @__PURE__ */ jsxs16(
|
|
11360
11670
|
"button",
|
|
11361
11671
|
{
|
|
11362
11672
|
type: "button",
|
|
@@ -11365,20 +11675,20 @@ function DocBlocksShell({
|
|
|
11365
11675
|
"aria-label": "Back up all workspaces",
|
|
11366
11676
|
title: "Browsers can clear site data. Download a backup of every workspace.",
|
|
11367
11677
|
children: [
|
|
11368
|
-
/* @__PURE__ */
|
|
11678
|
+
/* @__PURE__ */ jsx18(BackupIcon, {}),
|
|
11369
11679
|
"Back up"
|
|
11370
11680
|
]
|
|
11371
11681
|
}
|
|
11372
11682
|
) })
|
|
11373
11683
|
] }),
|
|
11374
|
-
/* @__PURE__ */
|
|
11375
|
-
/* @__PURE__ */
|
|
11376
|
-
/* @__PURE__ */
|
|
11684
|
+
/* @__PURE__ */ jsxs16("div", { className: "db-sidebar-collapse-preview", "aria-hidden": "true", children: [
|
|
11685
|
+
/* @__PURE__ */ jsx18("span", { className: "db-sidebar-collapse-preview-icon", children: /* @__PURE__ */ jsx18(CollapseSidebarGlyph, {}) }),
|
|
11686
|
+
/* @__PURE__ */ jsx18("span", { className: "db-sidebar-collapse-preview-label", children: "Release to hide files" })
|
|
11377
11687
|
] })
|
|
11378
11688
|
]
|
|
11379
11689
|
}
|
|
11380
11690
|
),
|
|
11381
|
-
!singlePane && /* @__PURE__ */
|
|
11691
|
+
!singlePane && /* @__PURE__ */ jsx18(
|
|
11382
11692
|
"div",
|
|
11383
11693
|
{
|
|
11384
11694
|
className: "db-shell-sidebar-resizer",
|
|
@@ -11388,7 +11698,7 @@ function DocBlocksShell({
|
|
|
11388
11698
|
onPointerDown: handleResizerPointerDown
|
|
11389
11699
|
}
|
|
11390
11700
|
),
|
|
11391
|
-
singlePane && /* @__PURE__ */
|
|
11701
|
+
singlePane && /* @__PURE__ */ jsx18(
|
|
11392
11702
|
"div",
|
|
11393
11703
|
{
|
|
11394
11704
|
className: "db-shell-scrim",
|
|
@@ -11396,7 +11706,7 @@ function DocBlocksShell({
|
|
|
11396
11706
|
onPointerDown: () => setMobileShowEditor(true)
|
|
11397
11707
|
}
|
|
11398
11708
|
),
|
|
11399
|
-
/* @__PURE__ */
|
|
11709
|
+
/* @__PURE__ */ jsxs16(
|
|
11400
11710
|
"main",
|
|
11401
11711
|
{
|
|
11402
11712
|
ref: editorAreaRef,
|
|
@@ -11407,8 +11717,8 @@ function DocBlocksShell({
|
|
|
11407
11717
|
editorDropActive ? "db-shell-editor-area--drop-active" : ""
|
|
11408
11718
|
].filter(Boolean).join(" "),
|
|
11409
11719
|
children: [
|
|
11410
|
-
|
|
11411
|
-
selectedManagedOutput === "catalog-html" ? /* @__PURE__ */
|
|
11720
|
+
/* @__PURE__ */ jsxs16("div", { ref: welcomeCoveredRef, className: "db-shell-editor-content", children: [
|
|
11721
|
+
selectedFile && mediaProvider ? /* @__PURE__ */ jsx18(Fragment11, { children: selectedManagedOutput === "catalog-html" ? /* @__PURE__ */ jsx18(
|
|
11412
11722
|
GeneratedCatalogPage,
|
|
11413
11723
|
{
|
|
11414
11724
|
html: editorContent,
|
|
@@ -11416,17 +11726,17 @@ function DocBlocksShell({
|
|
|
11416
11726
|
onOpenSettings: activeWorkspaceDescriptor ? handleOpenWorkspaceSettings : void 0,
|
|
11417
11727
|
onBack: singlePane ? openDrawer : void 0
|
|
11418
11728
|
}
|
|
11419
|
-
) : /* @__PURE__ */
|
|
11729
|
+
) : /* @__PURE__ */ jsx18(
|
|
11420
11730
|
GeneratedFileFrame,
|
|
11421
11731
|
{
|
|
11422
11732
|
kind: selectedManagedOutput,
|
|
11423
11733
|
onOpenSettings: activeWorkspaceDescriptor ? handleOpenWorkspaceSettings : void 0,
|
|
11424
11734
|
onBack: singlePane ? openDrawer : void 0,
|
|
11425
|
-
children: /* @__PURE__ */
|
|
11735
|
+
children: /* @__PURE__ */ jsx18(
|
|
11426
11736
|
Suspense2,
|
|
11427
11737
|
{
|
|
11428
|
-
fallback: /* @__PURE__ */
|
|
11429
|
-
children: editorGenerationSettled && mediaProviderCurrent && /* @__PURE__ */
|
|
11738
|
+
fallback: /* @__PURE__ */ jsx18("div", { className: "db-shell-empty", role: "status", children: "Loading your document\u2026" }),
|
|
11739
|
+
children: editorGenerationSettled && mediaProviderCurrent && /* @__PURE__ */ jsx18(EditorErrorBoundary, { resetKey: `${selectedFile}-${editorKey}`, children: /* @__PURE__ */ jsx18(
|
|
11430
11740
|
EditorShell,
|
|
11431
11741
|
{
|
|
11432
11742
|
initialMarkdown: editorContent,
|
|
@@ -11443,6 +11753,7 @@ function DocBlocksShell({
|
|
|
11443
11753
|
saveDashboardImageOutput: saveRenderedImageOutput,
|
|
11444
11754
|
onChange: handleEditorChange,
|
|
11445
11755
|
onLinkClick: handleEditorLinkClick,
|
|
11756
|
+
wikiLinks,
|
|
11446
11757
|
colorScheme: resolvedTheme,
|
|
11447
11758
|
defaultThemeId: workspaceDefaultThemeId,
|
|
11448
11759
|
defaultThemeLabel: "Workspace default",
|
|
@@ -11476,19 +11787,19 @@ function DocBlocksShell({
|
|
|
11476
11787
|
versioningAutoSaveIdleMs,
|
|
11477
11788
|
onSaveVersion,
|
|
11478
11789
|
statusBarSlotRight,
|
|
11479
|
-
sidePanelSlot: ai && aiPanel && selectedImage === void 0 && (selectedOutsideIn === null || selectedOutsideInEditingEnabled) ? /* @__PURE__ */
|
|
11480
|
-
toolbarSlotLeft: singlePane ? /* @__PURE__ */
|
|
11790
|
+
sidePanelSlot: ai && aiPanel && selectedImage === void 0 && (selectedOutsideIn === null || selectedOutsideInEditingEnabled) ? /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: aiPanel === "review" ? /* @__PURE__ */ jsx18(AiReviewPanel, { ai, onClose: () => setAiPanel(null) }) : /* @__PURE__ */ jsx18(AiIllustratePanel, { ai, onClose: () => setAiPanel(null) }) }) : void 0,
|
|
11791
|
+
toolbarSlotLeft: singlePane ? /* @__PURE__ */ jsx18(
|
|
11481
11792
|
"button",
|
|
11482
11793
|
{
|
|
11483
11794
|
className: "db-mobile-back",
|
|
11484
11795
|
onClick: () => setMobileShowEditor(false),
|
|
11485
11796
|
"aria-label": "Show file list",
|
|
11486
|
-
children: /* @__PURE__ */
|
|
11797
|
+
children: /* @__PURE__ */ jsx18("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx18(FolderGlyph, {}) })
|
|
11487
11798
|
}
|
|
11488
11799
|
) : void 0,
|
|
11489
|
-
summarizationDesigner: selectedImage === void 0 && selectedManagedOutput === void 0 && (selectedOutsideIn === null || selectedOutsideInEditingEnabled) ? (onClose) => /* @__PURE__ */
|
|
11490
|
-
toolbarSlotRight: /* @__PURE__ */
|
|
11491
|
-
canFind && /* @__PURE__ */
|
|
11800
|
+
summarizationDesigner: selectedImage === void 0 && selectedManagedOutput === void 0 && (selectedOutsideIn === null || selectedOutsideInEditingEnabled) ? (onClose) => /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(PresentationMaker, { ai: ai ?? void 0, onClose }) }) : void 0,
|
|
11801
|
+
toolbarSlotRight: /* @__PURE__ */ jsxs16(Fragment11, { children: [
|
|
11802
|
+
canFind && /* @__PURE__ */ jsx18(
|
|
11492
11803
|
FindButton,
|
|
11493
11804
|
{
|
|
11494
11805
|
active: findMode,
|
|
@@ -11496,7 +11807,7 @@ function DocBlocksShell({
|
|
|
11496
11807
|
shortcutLabel: findShortcut
|
|
11497
11808
|
}
|
|
11498
11809
|
),
|
|
11499
|
-
ai && /* @__PURE__ */
|
|
11810
|
+
ai && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(
|
|
11500
11811
|
AiToolbarControl,
|
|
11501
11812
|
{
|
|
11502
11813
|
ai,
|
|
@@ -11505,8 +11816,8 @@ function DocBlocksShell({
|
|
|
11505
11816
|
onOpenPanel: setAiPanel
|
|
11506
11817
|
}
|
|
11507
11818
|
) }),
|
|
11508
|
-
speech && /* @__PURE__ */
|
|
11509
|
-
/* @__PURE__ */
|
|
11819
|
+
speech && /* @__PURE__ */ jsxs16(Suspense2, { fallback: null, children: [
|
|
11820
|
+
/* @__PURE__ */ jsx18(
|
|
11510
11821
|
TextFromNarration,
|
|
11511
11822
|
{
|
|
11512
11823
|
speech,
|
|
@@ -11516,27 +11827,27 @@ function DocBlocksShell({
|
|
|
11516
11827
|
onOpenSettings: openSettings
|
|
11517
11828
|
}
|
|
11518
11829
|
),
|
|
11519
|
-
hostSupports2("speechOutput") ? /* @__PURE__ */
|
|
11830
|
+
hostSupports2("speechOutput") ? /* @__PURE__ */ jsx18(
|
|
11520
11831
|
SpeechToolbarControl,
|
|
11521
11832
|
{
|
|
11522
11833
|
speech,
|
|
11523
11834
|
onOpenSettings: openSettings,
|
|
11524
11835
|
readOnly: selectedImage !== void 0 || selectedOutsideIn !== null && !selectedOutsideInEditingEnabled
|
|
11525
11836
|
}
|
|
11526
|
-
) : /* @__PURE__ */
|
|
11837
|
+
) : /* @__PURE__ */ jsx18(SpeechMenuBridge, {})
|
|
11527
11838
|
] }),
|
|
11528
|
-
canRestoreSplitView && /* @__PURE__ */
|
|
11839
|
+
canRestoreSplitView && /* @__PURE__ */ jsx18(
|
|
11529
11840
|
"button",
|
|
11530
11841
|
{
|
|
11531
11842
|
className: "db-restore-split",
|
|
11532
11843
|
onClick: () => updateSidebarPreference("pinned"),
|
|
11533
11844
|
"aria-label": "Restore split view",
|
|
11534
11845
|
title: "Restore split view",
|
|
11535
|
-
children: /* @__PURE__ */
|
|
11846
|
+
children: /* @__PURE__ */ jsx18(SplitViewIcon, {})
|
|
11536
11847
|
}
|
|
11537
11848
|
),
|
|
11538
|
-
git.repo && /* @__PURE__ */
|
|
11539
|
-
/* @__PURE__ */
|
|
11849
|
+
git.repo && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(GitToolbarControl, { selectedFile }) }),
|
|
11850
|
+
/* @__PURE__ */ jsx18(
|
|
11540
11851
|
ExportToolbarControls,
|
|
11541
11852
|
{
|
|
11542
11853
|
selectedFile,
|
|
@@ -11560,87 +11871,77 @@ function DocBlocksShell({
|
|
|
11560
11871
|
}
|
|
11561
11872
|
)
|
|
11562
11873
|
}
|
|
11563
|
-
),
|
|
11564
|
-
|
|
11565
|
-
|
|
11566
|
-
"
|
|
11567
|
-
/* @__PURE__ */ jsx17("strong", { children: "Slideshow" }),
|
|
11568
|
-
" ",
|
|
11569
|
-
"view\u2014it\u2019s a regular Markdown file, and so is everything you\u2019ll write."
|
|
11874
|
+
) }) : selectedFolder ? /* @__PURE__ */ jsxs16("div", { className: "db-folder-view", children: [
|
|
11875
|
+
singlePane && /* @__PURE__ */ jsxs16("button", { className: "db-mobile-back", onClick: () => setMobileShowEditor(false), children: [
|
|
11876
|
+
/* @__PURE__ */ jsx18("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx18(FolderGlyph, {}) }),
|
|
11877
|
+
"Back to files"
|
|
11570
11878
|
] }),
|
|
11571
|
-
/* @__PURE__ */
|
|
11572
|
-
|
|
11573
|
-
"
|
|
11879
|
+
/* @__PURE__ */ jsxs16("div", { className: "db-folder-view-header", children: [
|
|
11880
|
+
/* @__PURE__ */ jsx18("span", { className: "db-folder-view-icon", children: /* @__PURE__ */ jsx18(FolderGlyph, {}) }),
|
|
11881
|
+
/* @__PURE__ */ jsx18("span", { className: "db-folder-view-path", children: selectedFolder })
|
|
11882
|
+
] }),
|
|
11883
|
+
visibleFolderEntries.length === 0 ? /* @__PURE__ */ jsx18("p", { className: "db-folder-view-empty", children: "This folder is empty." }) : /* @__PURE__ */ jsx18("ul", { className: "db-folder-view-list", children: visibleFolderEntries.map((entry) => /* @__PURE__ */ jsxs16(
|
|
11884
|
+
"li",
|
|
11574
11885
|
{
|
|
11575
|
-
className: "db-
|
|
11576
|
-
onClick:
|
|
11577
|
-
|
|
11578
|
-
|
|
11579
|
-
|
|
11580
|
-
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
|
|
11584
|
-
|
|
11585
|
-
/* @__PURE__ */
|
|
11586
|
-
|
|
11587
|
-
|
|
11588
|
-
|
|
11589
|
-
/* @__PURE__ */
|
|
11590
|
-
|
|
11886
|
+
className: "db-folder-view-item",
|
|
11887
|
+
onClick: () => handleSelect(entry.path, entry.kind),
|
|
11888
|
+
children: [
|
|
11889
|
+
/* @__PURE__ */ jsx18("span", { className: "db-folder-view-item-icon", children: entry.kind === "directory" ? /* @__PURE__ */ jsx18(FolderGlyph, {}) : /* @__PURE__ */ jsx18(FileGlyph, {}) }),
|
|
11890
|
+
entry.name
|
|
11891
|
+
]
|
|
11892
|
+
},
|
|
11893
|
+
entry.path
|
|
11894
|
+
)) })
|
|
11895
|
+
] }) : /* @__PURE__ */ jsxs16("div", { className: "db-shell-empty db-shell-empty--workspace", children: [
|
|
11896
|
+
singlePane && /* @__PURE__ */ jsxs16("button", { className: "db-mobile-back", onClick: () => setMobileShowEditor(false), children: [
|
|
11897
|
+
/* @__PURE__ */ jsx18("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx18(FolderGlyph, {}) }),
|
|
11898
|
+
"Back to files"
|
|
11899
|
+
] }),
|
|
11900
|
+
/* @__PURE__ */ jsxs16("div", { className: "db-workspace-empty-content", children: [
|
|
11901
|
+
/* @__PURE__ */ jsx18("span", { className: "db-workspace-empty-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx18(FileGlyph, {}) }),
|
|
11902
|
+
/* @__PURE__ */ jsx18("h1", { children: activeWorkspaceDescriptor?.name ?? "Workspace" }),
|
|
11903
|
+
/* @__PURE__ */ jsx18("p", { children: "Choose a Markdown document from the sidebar, or create a new one." }),
|
|
11904
|
+
/* @__PURE__ */ jsxs16("div", { className: "db-workspace-empty-actions", children: [
|
|
11905
|
+
/* @__PURE__ */ jsx18("button", { type: "button", onClick: () => void handleNewFile(), children: "New document" }),
|
|
11906
|
+
/* @__PURE__ */ jsx18(
|
|
11907
|
+
"button",
|
|
11908
|
+
{
|
|
11909
|
+
type: "button",
|
|
11910
|
+
className: "db-workspace-empty-secondary",
|
|
11911
|
+
onClick: () => void handleNewFolder(),
|
|
11912
|
+
children: "New folder"
|
|
11913
|
+
}
|
|
11914
|
+
),
|
|
11915
|
+
(hostSupports2("workspaceFolderPicker") || typeof globalThis.showDirectoryPicker === "function") && /* @__PURE__ */ jsx18(
|
|
11916
|
+
"button",
|
|
11917
|
+
{
|
|
11918
|
+
type: "button",
|
|
11919
|
+
className: "db-workspace-empty-secondary",
|
|
11920
|
+
onClick: () => void handleOpenFolder(),
|
|
11921
|
+
children: "Open a folder"
|
|
11922
|
+
}
|
|
11923
|
+
)
|
|
11924
|
+
] }),
|
|
11925
|
+
/* @__PURE__ */ jsx18("p", { className: "db-workspace-empty-hint", children: "Use the sidebar backup action to keep a portable copy of this workspace." })
|
|
11926
|
+
] })
|
|
11591
11927
|
] }),
|
|
11592
|
-
|
|
11593
|
-
|
|
11928
|
+
/* @__PURE__ */ jsx18(
|
|
11929
|
+
UpdateAvailableNotice,
|
|
11594
11930
|
{
|
|
11595
|
-
|
|
11596
|
-
|
|
11597
|
-
|
|
11598
|
-
|
|
11599
|
-
|
|
11600
|
-
|
|
11601
|
-
},
|
|
11602
|
-
entry.path
|
|
11603
|
-
)) })
|
|
11604
|
-
] }) : /* @__PURE__ */ jsxs15("div", { className: "db-shell-empty db-shell-empty--workspace", children: [
|
|
11605
|
-
singlePane && /* @__PURE__ */ jsxs15("button", { className: "db-mobile-back", onClick: () => setMobileShowEditor(false), children: [
|
|
11606
|
-
/* @__PURE__ */ jsx17("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx17(FolderGlyph, {}) }),
|
|
11607
|
-
"Back to files"
|
|
11608
|
-
] }),
|
|
11609
|
-
/* @__PURE__ */ jsxs15("div", { className: "db-workspace-empty-content", children: [
|
|
11610
|
-
/* @__PURE__ */ jsx17("span", { className: "db-workspace-empty-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx17(FileGlyph, {}) }),
|
|
11611
|
-
/* @__PURE__ */ jsx17("h1", { children: activeWorkspaceDescriptor?.name ?? "Workspace" }),
|
|
11612
|
-
/* @__PURE__ */ jsx17("p", { children: "Choose a Markdown document from the sidebar, or create a new one." }),
|
|
11613
|
-
/* @__PURE__ */ jsxs15("div", { className: "db-workspace-empty-actions", children: [
|
|
11614
|
-
/* @__PURE__ */ jsx17("button", { type: "button", onClick: () => void handleNewFile(), children: "New document" }),
|
|
11615
|
-
/* @__PURE__ */ jsx17(
|
|
11616
|
-
"button",
|
|
11617
|
-
{
|
|
11618
|
-
type: "button",
|
|
11619
|
-
className: "db-workspace-empty-secondary",
|
|
11620
|
-
onClick: () => void handleNewFolder(),
|
|
11621
|
-
children: "New folder"
|
|
11622
|
-
}
|
|
11623
|
-
),
|
|
11624
|
-
(hostSupports2("workspaceFolderPicker") || typeof globalThis.showDirectoryPicker === "function") && /* @__PURE__ */ jsx17(
|
|
11625
|
-
"button",
|
|
11626
|
-
{
|
|
11627
|
-
type: "button",
|
|
11628
|
-
className: "db-workspace-empty-secondary",
|
|
11629
|
-
onClick: () => void handleOpenFolder(),
|
|
11630
|
-
children: "Open a folder"
|
|
11631
|
-
}
|
|
11632
|
-
)
|
|
11633
|
-
] }),
|
|
11634
|
-
/* @__PURE__ */ jsx17("p", { className: "db-workspace-empty-hint", children: "Use the sidebar backup action to keep a portable copy of this workspace." })
|
|
11635
|
-
] })
|
|
11931
|
+
available: updateAvailable,
|
|
11932
|
+
onApplyUpdate,
|
|
11933
|
+
blocked: documentSnapshot.conflict !== null || storageFull,
|
|
11934
|
+
statusBarVisible: updateStatusBarVisible
|
|
11935
|
+
}
|
|
11936
|
+
)
|
|
11636
11937
|
] }),
|
|
11637
|
-
/* @__PURE__ */
|
|
11638
|
-
|
|
11938
|
+
welcomeScreenShown && /* @__PURE__ */ jsx18(
|
|
11939
|
+
WelcomeScreen,
|
|
11639
11940
|
{
|
|
11640
|
-
|
|
11641
|
-
|
|
11642
|
-
|
|
11643
|
-
|
|
11941
|
+
onCreateDocument: handleNewFile,
|
|
11942
|
+
onTour: handleTourWelcome,
|
|
11943
|
+
onDismiss: handleTourWelcome,
|
|
11944
|
+
offerApps: hostEnvironment === null
|
|
11644
11945
|
}
|
|
11645
11946
|
)
|
|
11646
11947
|
]
|