@bendyline/docblocks-react 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -3
- package/dist/ExportDialog-VYATD5UC.js +9 -0
- package/dist/{ExportToolbarControls-GHAOJMH6.js → ExportToolbarControls-5HUE3LSX.js} +69 -40
- package/dist/{GitToolbarControl-GNMRVKWQ.js → GitToolbarControl-FW3BZFXV.js} +2 -3
- package/dist/{GitUI-VHOBQY43.js → GitUI-GMH3PAYL.js} +3 -4
- package/dist/{LazyEditorShell-EF2BWRXU.js → LazyEditorShell-RF54B5UD.js} +0 -1
- package/dist/{ShareDialog-63ENBEDZ.js → ShareDialog-PAMOQQFB.js} +0 -1
- package/dist/{chunk-UNYZQXWR.js → chunk-3CZ27FOA.js} +45 -10
- package/dist/{chunk-FEWQUQML.js → chunk-3QSZY74C.js} +1 -2
- package/dist/chunk-BI7NVU6T.js +31 -0
- package/dist/{chunk-VHDP4IPL.js → chunk-BPGEBGAN.js} +0 -1
- package/dist/{chunk-DD4VFJQI.js → chunk-EBWYGTN7.js} +2 -1
- package/dist/{chunk-ZI56BNB7.js → chunk-GHQ4X7KM.js} +27 -7
- package/dist/{chunk-5A4KEWKT.js → chunk-HFYPTTCH.js} +0 -1
- package/dist/{chunk-FMGTHSTX.js → chunk-LG6HAWCK.js} +0 -1
- package/dist/{chunk-57ZJJOC5.js → chunk-TFMO7EVO.js} +0 -1
- package/dist/{chunk-4XXSWN3T.js → chunk-YBEYTVU2.js} +0 -1
- package/dist/editor.js +1 -2
- package/dist/export/index.d.ts +18 -8
- package/dist/export/index.js +10 -7
- package/dist/index.d.ts +16 -7
- package/dist/index.js +346 -97
- package/dist/run-export-Z5BVFLIR.js +9 -0
- package/dist/settings/index.js +2 -3
- package/package.json +8 -8
- package/src/styles/docblocks.css +448 -9
- package/dist/ExportDialog-7LDIXJZ3.js +0 -10
- package/dist/ExportDialog-7LDIXJZ3.js.map +0 -1
- package/dist/ExportToolbarControls-GHAOJMH6.js.map +0 -1
- package/dist/GitToolbarControl-GNMRVKWQ.js.map +0 -1
- package/dist/GitUI-VHOBQY43.js.map +0 -1
- package/dist/LazyEditorShell-EF2BWRXU.js.map +0 -1
- package/dist/ShareDialog-63ENBEDZ.js.map +0 -1
- package/dist/chunk-4XXSWN3T.js.map +0 -1
- package/dist/chunk-57ZJJOC5.js.map +0 -1
- package/dist/chunk-5A4KEWKT.js.map +0 -1
- package/dist/chunk-DD4VFJQI.js.map +0 -1
- package/dist/chunk-FEWQUQML.js.map +0 -1
- package/dist/chunk-FMGTHSTX.js.map +0 -1
- package/dist/chunk-UNYZQXWR.js.map +0 -1
- package/dist/chunk-VHDP4IPL.js.map +0 -1
- package/dist/chunk-ZI56BNB7.js.map +0 -1
- package/dist/editor.js.map +0 -1
- package/dist/export/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/run-export-ICTZITXC.js +0 -10
- package/dist/run-export-ICTZITXC.js.map +0 -1
- package/dist/settings/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -38,11 +38,19 @@ export default defineConfig({ worker: { format: 'es' } });
|
|
|
38
38
|
The canonical DocBlocks experience in one component — file explorer, workspace picker, app menu, the Squisq editor with its Editor / Markdown / Play views, and the export pipeline.
|
|
39
39
|
|
|
40
40
|
```tsx
|
|
41
|
-
<DocBlocksShell
|
|
41
|
+
<DocBlocksShell
|
|
42
|
+
theme="auto"
|
|
43
|
+
logoUrl="/logo.png"
|
|
44
|
+
ffmpegWasm={{
|
|
45
|
+
coreURL: '/ffmpeg-core/ffmpeg-core.js',
|
|
46
|
+
wasmURL: '/ffmpeg-core/ffmpeg-core.wasm',
|
|
47
|
+
}}
|
|
48
|
+
/>
|
|
42
49
|
```
|
|
43
50
|
|
|
44
51
|
- `theme` — `'light' | 'dark' | 'auto'` (auto follows `prefers-color-scheme`)
|
|
45
52
|
- `logoUrl` — brand mark for the app menu button
|
|
53
|
+
- `ffmpegWasm` — optional same-origin ffmpeg core URLs; supplying them enables the built-in Animated GIF flow on cross-origin-isolated hosts
|
|
46
54
|
|
|
47
55
|
Storage is abstracted behind the byte-authoritative `FileSystemProviderV2` contract from `@bendyline/docblocks/filesystem`: browser-local (IndexedDB), native folders (File System Access API), transient memory workspaces, or the Electron host. Built-in compatibility facades expose it as `provider.v2`; first-party shell and file-tree operations are v2-first.
|
|
48
56
|
|
|
@@ -80,7 +88,7 @@ and an optional initial Use mode. Opening the URL creates a session-only
|
|
|
80
88
|
workspace; generated links warn after 4,096 characters and are capped at
|
|
81
89
|
32,768 characters.
|
|
82
90
|
|
|
83
|
-
The export flow: quick re-export of the last configuration plus the full dialog — format (PDF, Word, PowerPoint, HTML, Markdown), visual theme, and page size.
|
|
91
|
+
The export flow: quick re-export of the last configuration plus the full dialog — format (PDF, Word, PowerPoint, EPUB, HTML, Markdown), visual theme, and page size. Hosts that supply `ffmpegWasm` also expose Animated GIF with timing, orientation, captions, looping, and color controls.
|
|
84
92
|
|
|
85
93
|
## Hooks
|
|
86
94
|
|
|
@@ -100,7 +108,8 @@ File tree state management over any v2-capable provider — returns the tree, se
|
|
|
100
108
|
import '@bendyline/docblocks-react/styles';
|
|
101
109
|
```
|
|
102
110
|
|
|
103
|
-
One stylesheet
|
|
111
|
+
One explicit stylesheet import covers the Squisq editor and all DocBlocks components in both
|
|
112
|
+
themes. Theme fonts are supplied by the host application; this package does not bundle fonts.
|
|
104
113
|
|
|
105
114
|
## Where new UI belongs
|
|
106
115
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadTransformStyleSummaries
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YBEYTVU2.js";
|
|
4
4
|
import {
|
|
5
5
|
Dialog
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LG6HAWCK.js";
|
|
7
7
|
import {
|
|
8
8
|
DEFAULT_OPTIONS,
|
|
9
9
|
FORMAT_EXTENSIONS,
|
|
10
10
|
loadLastExportOptions,
|
|
11
11
|
saveExportOptions
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-EBWYGTN7.js";
|
|
13
13
|
|
|
14
14
|
// src/Export/ExportToolbarControls.tsx
|
|
15
15
|
import {
|
|
@@ -26,14 +26,14 @@ import { getThemeSummaries } from "@bendyline/squisq/schemas";
|
|
|
26
26
|
import { parseMarkdown } from "@bendyline/squisq/markdown";
|
|
27
27
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
28
28
|
var ExportDialog = lazy(
|
|
29
|
-
() => import("./ExportDialog-
|
|
29
|
+
() => import("./ExportDialog-VYATD5UC.js").then((module) => ({ default: module.ExportDialog }))
|
|
30
30
|
);
|
|
31
31
|
var ShareDialog = lazy(
|
|
32
|
-
() => import("./ShareDialog-
|
|
32
|
+
() => import("./ShareDialog-PAMOQQFB.js").then((module) => ({ default: module.ShareDialog }))
|
|
33
33
|
);
|
|
34
34
|
var runExportModulePromise = null;
|
|
35
35
|
function loadRunExportModule() {
|
|
36
|
-
runExportModulePromise ?? (runExportModulePromise = import("./run-export-
|
|
36
|
+
runExportModulePromise ?? (runExportModulePromise = import("./run-export-Z5BVFLIR.js"));
|
|
37
37
|
return runExportModulePromise;
|
|
38
38
|
}
|
|
39
39
|
var SHARED_USE_MODES = Object.freeze({
|
|
@@ -103,6 +103,7 @@ function ExportToolbarControls({
|
|
|
103
103
|
destinationAdapter,
|
|
104
104
|
trigger = "menu",
|
|
105
105
|
showVideoExport = true,
|
|
106
|
+
ffmpegWasm,
|
|
106
107
|
colorScheme = "light",
|
|
107
108
|
videoExportPalette,
|
|
108
109
|
shareBaseUrl,
|
|
@@ -113,6 +114,7 @@ function ExportToolbarControls({
|
|
|
113
114
|
const [dialogOpen, setDialogOpen] = useState(false);
|
|
114
115
|
const [shareDialogOpen, setShareDialogOpen] = useState(false);
|
|
115
116
|
const [videoModalOpen, setVideoModalOpen] = useState(false);
|
|
117
|
+
const [videoOutputFormat, setVideoOutputFormat] = useState("mp4");
|
|
116
118
|
const [videoLoading, setVideoLoading] = useState(false);
|
|
117
119
|
const [videoLoadError, setVideoLoadError] = useState(null);
|
|
118
120
|
const [videoModules, setVideoModules] = useState(null);
|
|
@@ -197,21 +199,36 @@ function ExportToolbarControls({
|
|
|
197
199
|
const handleCloseShareDialog = useCallback(() => {
|
|
198
200
|
setShareDialogOpen(false);
|
|
199
201
|
}, []);
|
|
200
|
-
const handleOpenVideoModal = useCallback(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
202
|
+
const handleOpenVideoModal = useCallback(
|
|
203
|
+
async (outputFormat) => {
|
|
204
|
+
setMenuOpen(false);
|
|
205
|
+
setVideoOutputFormat(outputFormat);
|
|
206
|
+
setVideoModalOpen(true);
|
|
207
|
+
setVideoLoadError(null);
|
|
208
|
+
if (outputFormat === "gif" && typeof SharedArrayBuffer === "undefined") {
|
|
209
|
+
setVideoLoading(false);
|
|
210
|
+
setVideoLoadError(
|
|
211
|
+
"Animated GIF export needs cross-origin isolation. If this app just finished installing for offline use, reload it once and try again."
|
|
212
|
+
);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
setVideoLoading(true);
|
|
216
|
+
try {
|
|
217
|
+
const modules = videoModules ?? await loadVideoExportModules();
|
|
218
|
+
setVideoModules(modules);
|
|
219
|
+
setVideoDoc(modules.markdownToDoc(parseMarkdown(markdownSource)));
|
|
220
|
+
} catch {
|
|
221
|
+
setVideoLoadError("Video export could not be loaded.");
|
|
222
|
+
} finally {
|
|
223
|
+
setVideoLoading(false);
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
[markdownSource, videoModules]
|
|
227
|
+
);
|
|
228
|
+
const handleOpenAnimatedGifFromDialog = useCallback(() => {
|
|
229
|
+
setDialogOpen(false);
|
|
230
|
+
void handleOpenVideoModal("gif");
|
|
231
|
+
}, [handleOpenVideoModal]);
|
|
215
232
|
const handleCloseVideoModal = useCallback(() => {
|
|
216
233
|
setVideoModalOpen(false);
|
|
217
234
|
setVideoDoc(null);
|
|
@@ -320,6 +337,7 @@ function ExportToolbarControls({
|
|
|
320
337
|
setExportError(null);
|
|
321
338
|
}, []);
|
|
322
339
|
const LoadedVideoExportModal = videoModules?.Modal;
|
|
340
|
+
const showAnimatedGifExport = showVideoExport && typeof ffmpegWasm?.coreURL === "string" && ffmpegWasm.coreURL.length > 0;
|
|
323
341
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
324
342
|
initialSharedMode && /* @__PURE__ */ jsx(SharedModeInitializer, { mode: initialSharedMode }),
|
|
325
343
|
trigger === "button" ? /* @__PURE__ */ jsx(
|
|
@@ -334,7 +352,7 @@ function ExportToolbarControls({
|
|
|
334
352
|
children: /* @__PURE__ */ jsx(ExportGlyph, {})
|
|
335
353
|
}
|
|
336
354
|
) : /* @__PURE__ */ jsxs("div", { className: "db-toolbar-menu", ref: menuRef, children: [
|
|
337
|
-
/* @__PURE__ */
|
|
355
|
+
/* @__PURE__ */ jsxs(
|
|
338
356
|
"button",
|
|
339
357
|
{
|
|
340
358
|
type: "button",
|
|
@@ -344,7 +362,10 @@ function ExportToolbarControls({
|
|
|
344
362
|
"aria-haspopup": "menu",
|
|
345
363
|
"aria-expanded": menuOpen,
|
|
346
364
|
title: "Export and share",
|
|
347
|
-
children:
|
|
365
|
+
children: [
|
|
366
|
+
/* @__PURE__ */ jsx(ShareGlyph, {}),
|
|
367
|
+
/* @__PURE__ */ jsx("span", { className: "db-toolbar-menu-trigger-label", children: "Export" })
|
|
368
|
+
]
|
|
348
369
|
}
|
|
349
370
|
),
|
|
350
371
|
menuOpen && /* @__PURE__ */ jsxs("div", { className: "db-toolbar-menu-dropdown", role: "menu", children: [
|
|
@@ -387,9 +408,19 @@ function ExportToolbarControls({
|
|
|
387
408
|
type: "button",
|
|
388
409
|
role: "menuitem",
|
|
389
410
|
className: "db-toolbar-menu-item",
|
|
390
|
-
onClick: handleOpenVideoModal,
|
|
411
|
+
onClick: () => void handleOpenVideoModal("mp4"),
|
|
391
412
|
children: "Export Video..."
|
|
392
413
|
}
|
|
414
|
+
),
|
|
415
|
+
showAnimatedGifExport && /* @__PURE__ */ jsx(
|
|
416
|
+
"button",
|
|
417
|
+
{
|
|
418
|
+
type: "button",
|
|
419
|
+
role: "menuitem",
|
|
420
|
+
className: "db-toolbar-menu-item",
|
|
421
|
+
onClick: () => void handleOpenVideoModal("gif"),
|
|
422
|
+
children: "Export Animated GIF..."
|
|
423
|
+
}
|
|
393
424
|
)
|
|
394
425
|
] })
|
|
395
426
|
] })
|
|
@@ -407,6 +438,7 @@ function ExportToolbarControls({
|
|
|
407
438
|
} : void 0,
|
|
408
439
|
onExport: handleExport,
|
|
409
440
|
onOptionsChange: destinationAdapter ? handleOptionsChange : void 0,
|
|
441
|
+
onAnimatedGifExport: showAnimatedGifExport ? handleOpenAnimatedGifFromDialog : void 0,
|
|
410
442
|
onClose: handleCloseDialog
|
|
411
443
|
}
|
|
412
444
|
) }),
|
|
@@ -436,21 +468,14 @@ function ExportToolbarControls({
|
|
|
436
468
|
onClose: handleCloseShareDialog
|
|
437
469
|
}
|
|
438
470
|
) }),
|
|
439
|
-
videoModalOpen && (videoLoading || videoLoadError) && /* @__PURE__ */ jsx(
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
"aria-label": "Close",
|
|
448
|
-
children: "\xD7"
|
|
449
|
-
}
|
|
450
|
-
)
|
|
451
|
-
] }),
|
|
452
|
-
/* @__PURE__ */ jsx("div", { className: "db-dialog-body", children: /* @__PURE__ */ jsx("p", { className: "db-export-hint", children: videoLoadError ?? "Loading..." }) })
|
|
453
|
-
] }) }),
|
|
471
|
+
videoModalOpen && (videoLoading || videoLoadError) && /* @__PURE__ */ jsx(
|
|
472
|
+
Dialog,
|
|
473
|
+
{
|
|
474
|
+
title: videoOutputFormat === "gif" ? "Export Animated GIF" : "Export Video",
|
|
475
|
+
onClose: handleCloseVideoModal,
|
|
476
|
+
children: /* @__PURE__ */ jsx("p", { className: "db-export-hint", role: videoLoadError ? "alert" : void 0, children: videoLoadError ?? "Loading..." })
|
|
477
|
+
}
|
|
478
|
+
),
|
|
454
479
|
videoModalOpen && videoModules && LoadedVideoExportModal && videoDoc && !videoLoading && !videoLoadError && /* @__PURE__ */ jsx(
|
|
455
480
|
LoadedVideoExportModal,
|
|
456
481
|
{
|
|
@@ -458,6 +483,11 @@ function ExportToolbarControls({
|
|
|
458
483
|
playerScript: videoModules.playerScript,
|
|
459
484
|
colorScheme,
|
|
460
485
|
uiPalette: videoExportPalette,
|
|
486
|
+
defaultConfig: {
|
|
487
|
+
audioPolicy: "best-effort",
|
|
488
|
+
...ffmpegWasm ? { ffmpegWasm } : {},
|
|
489
|
+
outputFormat: videoOutputFormat
|
|
490
|
+
},
|
|
461
491
|
onClose: handleCloseVideoModal
|
|
462
492
|
}
|
|
463
493
|
)
|
|
@@ -505,4 +535,3 @@ function ShareGlyph() {
|
|
|
505
535
|
export {
|
|
506
536
|
ExportToolbarControls
|
|
507
537
|
};
|
|
508
|
-
//# sourceMappingURL=ExportToolbarControls-GHAOJMH6.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useMenuKeyboard
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TFMO7EVO.js";
|
|
4
4
|
import {
|
|
5
5
|
isFileDirty,
|
|
6
6
|
useGitContext
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-HFYPTTCH.js";
|
|
8
8
|
|
|
9
9
|
// src/Git/GitToolbarControl.tsx
|
|
10
10
|
import { useEffect, useRef, useState } from "react";
|
|
@@ -133,4 +133,3 @@ function BranchGlyph() {
|
|
|
133
133
|
export {
|
|
134
134
|
GitToolbarControl
|
|
135
135
|
};
|
|
136
|
-
//# sourceMappingURL=GitToolbarControl-GNMRVKWQ.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useMenuKeyboard
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TFMO7EVO.js";
|
|
4
4
|
import {
|
|
5
5
|
BADGE_GLYPHS,
|
|
6
6
|
BADGE_LABELS,
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
formatAheadBehind,
|
|
9
9
|
summarizeDirty,
|
|
10
10
|
useGitContext
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-HFYPTTCH.js";
|
|
12
12
|
import {
|
|
13
13
|
Dialog
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-LG6HAWCK.js";
|
|
15
15
|
|
|
16
16
|
// src/Git/GitStatusBar.tsx
|
|
17
17
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
@@ -1130,4 +1130,3 @@ function GitUI({ onOpenFile, onWorkspaceCloned }) {
|
|
|
1130
1130
|
export {
|
|
1131
1131
|
GitUI
|
|
1132
1132
|
};
|
|
1133
|
-
//# sourceMappingURL=GitUI-VHOBQY43.js.map
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadTransformStyleSummaries
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YBEYTVU2.js";
|
|
4
4
|
import {
|
|
5
5
|
Dialog
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LG6HAWCK.js";
|
|
7
7
|
import {
|
|
8
8
|
FORMAT_LABELS,
|
|
9
9
|
saveExportOptions
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-EBWYGTN7.js";
|
|
11
11
|
|
|
12
12
|
// src/Export/ExportDialog.tsx
|
|
13
13
|
import { useState, useCallback, useEffect, useMemo } from "react";
|
|
14
14
|
import { getThemeSummaries } from "@bendyline/squisq/schemas";
|
|
15
15
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
16
|
-
var FORMATS = ["pdf", "docx", "pptx", "html", "md"];
|
|
16
|
+
var FORMATS = ["pdf", "docx", "pptx", "epub", "html", "md"];
|
|
17
17
|
var FORMAT_CHIP_LABELS = {
|
|
18
18
|
pdf: "PDF",
|
|
19
19
|
docx: "Word",
|
|
20
20
|
pptx: "PowerPoint",
|
|
21
|
+
epub: "EPUB",
|
|
21
22
|
html: "HTML",
|
|
22
23
|
md: "Markdown"
|
|
23
24
|
};
|
|
@@ -75,6 +76,7 @@ function ExportDialog({
|
|
|
75
76
|
destination,
|
|
76
77
|
onExport,
|
|
77
78
|
onOptionsChange,
|
|
79
|
+
onAnimatedGifExport,
|
|
78
80
|
onClose
|
|
79
81
|
}) {
|
|
80
82
|
const [format, setFormat] = useState(initial.format);
|
|
@@ -87,7 +89,7 @@ function ExportDialog({
|
|
|
87
89
|
const [entryAsIndex, setEntryAsIndex] = useState(initial.entryAsIndex);
|
|
88
90
|
const [transforms, setTransforms] = useState([]);
|
|
89
91
|
const themes = getThemeSummaries();
|
|
90
|
-
const showTheme = format === "docx" || format === "pdf" || format === "pptx" || format === "html";
|
|
92
|
+
const showTheme = format === "docx" || format === "pdf" || format === "pptx" || format === "epub" || format === "html";
|
|
91
93
|
const showTransform = format === "pptx";
|
|
92
94
|
const showPageSize = format === "pdf";
|
|
93
95
|
const showHtmlOptions = format === "html";
|
|
@@ -134,9 +136,10 @@ function ExportDialog({
|
|
|
134
136
|
onOptionsChange?.(currentOptions);
|
|
135
137
|
}, [currentOptions, onOptionsChange]);
|
|
136
138
|
const handleExport = useCallback(() => {
|
|
139
|
+
if (destination?.error) return;
|
|
137
140
|
saveExportOptions(currentOptions);
|
|
138
141
|
onExport(currentOptions);
|
|
139
|
-
}, [currentOptions, onExport]);
|
|
142
|
+
}, [currentOptions, destination?.error, onExport]);
|
|
140
143
|
return /* @__PURE__ */ jsxs(
|
|
141
144
|
Dialog,
|
|
142
145
|
{
|
|
@@ -160,7 +163,7 @@ function ExportDialog({
|
|
|
160
163
|
type: "button",
|
|
161
164
|
className: "db-export-btn db-export-btn--primary",
|
|
162
165
|
onClick: handleExport,
|
|
163
|
-
disabled: exporting,
|
|
166
|
+
disabled: exporting || Boolean(destination?.error),
|
|
164
167
|
children: exporting ? "Exporting..." : "Export"
|
|
165
168
|
}
|
|
166
169
|
)
|
|
@@ -191,10 +194,13 @@ function ExportDialog({
|
|
|
191
194
|
id: "db-export-path",
|
|
192
195
|
className: "db-export-path-input",
|
|
193
196
|
value: destination.value,
|
|
194
|
-
|
|
197
|
+
onChange: destination.onChange ? (event) => destination.onChange?.(event.target.value, currentOptions) : void 0,
|
|
198
|
+
readOnly: !destination.onChange,
|
|
195
199
|
disabled: exporting,
|
|
196
200
|
spellCheck: false,
|
|
197
|
-
autoComplete: "off"
|
|
201
|
+
autoComplete: "off",
|
|
202
|
+
"aria-invalid": Boolean(destination.error),
|
|
203
|
+
"aria-describedby": destination.error ? "db-export-path-error" : void 0
|
|
198
204
|
}
|
|
199
205
|
),
|
|
200
206
|
/* @__PURE__ */ jsx(
|
|
@@ -210,6 +216,15 @@ function ExportDialog({
|
|
|
210
216
|
}
|
|
211
217
|
)
|
|
212
218
|
] }),
|
|
219
|
+
destination.error && /* @__PURE__ */ jsx(
|
|
220
|
+
"span",
|
|
221
|
+
{
|
|
222
|
+
id: "db-export-path-error",
|
|
223
|
+
className: "db-export-hint db-export-hint--error",
|
|
224
|
+
role: "alert",
|
|
225
|
+
children: destination.error
|
|
226
|
+
}
|
|
227
|
+
),
|
|
213
228
|
destination.hint && /* @__PURE__ */ jsx("span", { className: "db-export-hint", children: destination.hint })
|
|
214
229
|
] }),
|
|
215
230
|
showHtmlOptions && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -312,6 +327,27 @@ function ExportDialog({
|
|
|
312
327
|
}
|
|
313
328
|
)
|
|
314
329
|
] }),
|
|
330
|
+
onAnimatedGifExport && /* @__PURE__ */ jsxs("div", { className: "db-export-field", children: [
|
|
331
|
+
/* @__PURE__ */ jsx("span", { className: "db-export-label", children: "Animated media" }),
|
|
332
|
+
/* @__PURE__ */ jsx(
|
|
333
|
+
"button",
|
|
334
|
+
{
|
|
335
|
+
type: "button",
|
|
336
|
+
className: "db-export-btn db-export-btn--secondary",
|
|
337
|
+
onClick: onAnimatedGifExport,
|
|
338
|
+
children: "Animated GIF..."
|
|
339
|
+
}
|
|
340
|
+
),
|
|
341
|
+
/* @__PURE__ */ jsx("span", { className: "db-export-hint", children: "Opens timing, orientation, captions, looping, and color controls." })
|
|
342
|
+
] }),
|
|
343
|
+
/* @__PURE__ */ jsxs("p", { className: "db-export-more-formats", children: [
|
|
344
|
+
"Need spreadsheets, ",
|
|
345
|
+
onAnimatedGifExport ? "" : "animated media, ",
|
|
346
|
+
"portable bundles, or automation?",
|
|
347
|
+
" ",
|
|
348
|
+
/* @__PURE__ */ jsx("a", { href: "https://docblocks.com/cli/", target: "_blank", rel: "noopener noreferrer", children: "More formats with the DocBlocks CLI" }),
|
|
349
|
+
"."
|
|
350
|
+
] }),
|
|
315
351
|
error && /* @__PURE__ */ jsx("p", { className: "db-export-error", role: "alert", children: error })
|
|
316
352
|
]
|
|
317
353
|
}
|
|
@@ -321,4 +357,3 @@ function ExportDialog({
|
|
|
321
357
|
export {
|
|
322
358
|
ExportDialog
|
|
323
359
|
};
|
|
324
|
-
//# sourceMappingURL=chunk-UNYZQXWR.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Dialog
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LG6HAWCK.js";
|
|
4
4
|
|
|
5
5
|
// src/preferences/theme.ts
|
|
6
6
|
var ACCENT_COLORS = [
|
|
@@ -253,4 +253,3 @@ export {
|
|
|
253
253
|
AccentColorSettings,
|
|
254
254
|
WriteCanvasSettingsControls
|
|
255
255
|
};
|
|
256
|
-
//# sourceMappingURL=chunk-FEWQUQML.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/Export/export-destination.ts
|
|
2
|
+
function updateExportTargetExtension(targetPath, suggestedFilename) {
|
|
3
|
+
const nextExtension = extensionOf(suggestedFilename);
|
|
4
|
+
if (!nextExtension) return targetPath;
|
|
5
|
+
if (!targetPath.trim()) return suggestedFilename;
|
|
6
|
+
const suffixIndex = firstSuffixIndex(targetPath);
|
|
7
|
+
const pathPart = suffixIndex === -1 ? targetPath : targetPath.slice(0, suffixIndex);
|
|
8
|
+
const suffix = suffixIndex === -1 ? "" : targetPath.slice(suffixIndex);
|
|
9
|
+
const separatorIndex = Math.max(pathPart.lastIndexOf("/"), pathPart.lastIndexOf("\\"));
|
|
10
|
+
const dotIndex = pathPart.lastIndexOf(".");
|
|
11
|
+
const stem = dotIndex > separatorIndex ? pathPart.slice(0, dotIndex) : pathPart;
|
|
12
|
+
return `${stem}${nextExtension}${suffix}`;
|
|
13
|
+
}
|
|
14
|
+
function extensionOf(value) {
|
|
15
|
+
const suffixIndex = firstSuffixIndex(value);
|
|
16
|
+
const pathPart = suffixIndex === -1 ? value : value.slice(0, suffixIndex);
|
|
17
|
+
const separatorIndex = Math.max(pathPart.lastIndexOf("/"), pathPart.lastIndexOf("\\"));
|
|
18
|
+
const dotIndex = pathPart.lastIndexOf(".");
|
|
19
|
+
return dotIndex > separatorIndex ? pathPart.slice(dotIndex) : "";
|
|
20
|
+
}
|
|
21
|
+
function firstSuffixIndex(value) {
|
|
22
|
+
const query = value.indexOf("?");
|
|
23
|
+
const fragment = value.indexOf("#");
|
|
24
|
+
if (query === -1) return fragment;
|
|
25
|
+
if (fragment === -1) return query;
|
|
26
|
+
return Math.min(query, fragment);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
updateExportTargetExtension
|
|
31
|
+
};
|
|
@@ -3,6 +3,7 @@ var FORMAT_LABELS = {
|
|
|
3
3
|
docx: "Word Document (.docx)",
|
|
4
4
|
pdf: "PDF (.pdf)",
|
|
5
5
|
pptx: "PowerPoint (.pptx)",
|
|
6
|
+
epub: "EPUB e-book (.epub)",
|
|
6
7
|
md: "Markdown (.md)",
|
|
7
8
|
html: "HTML (.html)"
|
|
8
9
|
};
|
|
@@ -10,6 +11,7 @@ var FORMAT_EXTENSIONS = {
|
|
|
10
11
|
docx: ".docx",
|
|
11
12
|
pdf: ".pdf",
|
|
12
13
|
pptx: ".pptx",
|
|
14
|
+
epub: ".epub",
|
|
13
15
|
md: ".md",
|
|
14
16
|
html: ".html"
|
|
15
17
|
};
|
|
@@ -48,4 +50,3 @@ export {
|
|
|
48
50
|
loadLastExportOptions,
|
|
49
51
|
saveExportOptions
|
|
50
52
|
};
|
|
51
|
-
//# sourceMappingURL=chunk-DD4VFJQI.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FORMAT_EXTENSIONS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EBWYGTN7.js";
|
|
4
4
|
|
|
5
5
|
// src/Export/run-export.ts
|
|
6
6
|
import { parseMarkdown } from "@bendyline/squisq/markdown";
|
|
@@ -8,6 +8,7 @@ var MIME_TYPES = {
|
|
|
8
8
|
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
9
9
|
pdf: "application/pdf",
|
|
10
10
|
pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
11
|
+
epub: "application/epub+zip",
|
|
11
12
|
md: "text/markdown",
|
|
12
13
|
html: "text/html"
|
|
13
14
|
};
|
|
@@ -38,7 +39,7 @@ function buildExportFilename(selectedFile, options) {
|
|
|
38
39
|
}
|
|
39
40
|
return base + FORMAT_EXTENSIONS[options.format];
|
|
40
41
|
}
|
|
41
|
-
async function runExport(markdown, selectedFile, options, mediaContainer, saveBlob) {
|
|
42
|
+
async function runExport(markdown, selectedFile, options, mediaContainer, saveBlob, converterOverrides = {}) {
|
|
42
43
|
const filename = buildFilename(selectedFile, options.format);
|
|
43
44
|
const themeId = options.themeId !== "standard" ? options.themeId : void 0;
|
|
44
45
|
if (options.format === "md") {
|
|
@@ -66,19 +67,29 @@ async function runExport(markdown, selectedFile, options, mediaContainer, saveBl
|
|
|
66
67
|
await saveExportBlob(new Blob([buf], { type: MIME_TYPES.pdf }), filename, saveBlob);
|
|
67
68
|
return;
|
|
68
69
|
}
|
|
70
|
+
if (options.format === "epub") {
|
|
71
|
+
const { markdownDocToEpub } = await import("@bendyline/squisq-formats/epub");
|
|
72
|
+
const images = mediaContainer ? await resolveImageData(doc, mediaContainer) : void 0;
|
|
73
|
+
const buf = await markdownDocToEpub(doc, { themeId, images });
|
|
74
|
+
await saveExportBlob(new Blob([buf], { type: MIME_TYPES.epub }), filename, saveBlob);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
69
77
|
if (options.format === "pptx") {
|
|
70
|
-
const
|
|
78
|
+
const pptxModule = converterOverrides.docToPptx ? Promise.resolve({ docToPptx: converterOverrides.docToPptx }) : import("@bendyline/squisq-formats/pptx");
|
|
79
|
+
const [{ markdownToDoc }, { applyTransform }, { buildPreviewDoc }, { docToPptx }] = await Promise.all([
|
|
71
80
|
import("@bendyline/squisq/doc"),
|
|
72
81
|
import("@bendyline/squisq/transform"),
|
|
73
|
-
import("@bendyline/squisq-
|
|
82
|
+
import("@bendyline/squisq-editor-react"),
|
|
83
|
+
pptxModule
|
|
74
84
|
]);
|
|
75
85
|
const baseDoc = markdownToDoc(doc);
|
|
76
86
|
const transformed = applyTransform(baseDoc, options.transformStyle);
|
|
77
|
-
const enrichedDoc = transformed.doc;
|
|
87
|
+
const enrichedDoc = buildPreviewDoc(transformed.doc);
|
|
78
88
|
if (themeId) {
|
|
79
89
|
enrichedDoc.themeId = themeId;
|
|
80
90
|
}
|
|
81
|
-
const
|
|
91
|
+
const images = mediaContainer ? await resolveImageData(doc, mediaContainer) : void 0;
|
|
92
|
+
const buf = await docToPptx(enrichedDoc, { themeId, images });
|
|
82
93
|
await saveExportBlob(new Blob([buf], { type: MIME_TYPES.pptx }), filename, saveBlob);
|
|
83
94
|
return;
|
|
84
95
|
}
|
|
@@ -242,6 +253,16 @@ async function resolveImages(doc, container) {
|
|
|
242
253
|
}
|
|
243
254
|
return map;
|
|
244
255
|
}
|
|
256
|
+
async function resolveImageData(doc, container) {
|
|
257
|
+
const urls = collectMarkdownImageUrls(doc);
|
|
258
|
+
const map = /* @__PURE__ */ new Map();
|
|
259
|
+
for (const url of urls) {
|
|
260
|
+
if (map.has(url) || isExternalUrl(url)) continue;
|
|
261
|
+
const data = await container.readFile(url);
|
|
262
|
+
if (data) map.set(url, data);
|
|
263
|
+
}
|
|
264
|
+
return map;
|
|
265
|
+
}
|
|
245
266
|
function basenameForBundle(selectedFile) {
|
|
246
267
|
const clean = selectedFile.replace(/^\/+/, "");
|
|
247
268
|
const idx = clean.lastIndexOf("/");
|
|
@@ -267,4 +288,3 @@ export {
|
|
|
267
288
|
buildExportFilename,
|
|
268
289
|
runExport
|
|
269
290
|
};
|
|
270
|
-
//# sourceMappingURL=chunk-ZI56BNB7.js.map
|