@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
|
@@ -16,8 +16,9 @@ import {
|
|
|
16
16
|
buildExportFilename
|
|
17
17
|
} from "./chunk-5O5YTOXG.js";
|
|
18
18
|
import {
|
|
19
|
+
OpenAfterSaveCheckbox,
|
|
19
20
|
loadTransformStyleSummaries
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-H3BK5MK6.js";
|
|
21
22
|
import {
|
|
22
23
|
FORMAT_EXTENSIONS,
|
|
23
24
|
loadLastExportOptions,
|
|
@@ -26,7 +27,7 @@ import {
|
|
|
26
27
|
} from "./chunk-6MSHXQNB.js";
|
|
27
28
|
import {
|
|
28
29
|
Dialog
|
|
29
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-VJPGZCFS.js";
|
|
30
31
|
|
|
31
32
|
// src/Export/ExportToolbarControls.tsx
|
|
32
33
|
import {
|
|
@@ -45,22 +46,40 @@ import {
|
|
|
45
46
|
} from "@bendyline/squisq-editor-react";
|
|
46
47
|
import { readFrontmatterThemeId } from "@bendyline/squisq/markdown";
|
|
47
48
|
import { getThemeSummaries } from "@bendyline/squisq/schemas";
|
|
49
|
+
|
|
50
|
+
// src/preferences/export.ts
|
|
51
|
+
var STORAGE_KEY = "docblocks:openAfterExport";
|
|
52
|
+
function loadOpenAfterExport() {
|
|
53
|
+
try {
|
|
54
|
+
return localStorage.getItem(STORAGE_KEY) === "true";
|
|
55
|
+
} catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function saveOpenAfterExport(value) {
|
|
60
|
+
try {
|
|
61
|
+
localStorage.setItem(STORAGE_KEY, String(value));
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/Export/ExportToolbarControls.tsx
|
|
48
67
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
49
68
|
var ExportDialog = lazy(
|
|
50
|
-
() => import("./ExportDialog-
|
|
69
|
+
() => import("./ExportDialog-LGWBXIWN.js").then((module) => ({ default: module.ExportDialog }))
|
|
51
70
|
);
|
|
52
71
|
var ShareDialog = lazy(
|
|
53
|
-
() => import("./ShareDialog-
|
|
72
|
+
() => import("./ShareDialog-PF7D7ORP.js").then((module) => ({ default: module.ShareDialog }))
|
|
54
73
|
);
|
|
55
74
|
var runExportModulePromise = null;
|
|
56
75
|
function loadRunExportModule() {
|
|
57
|
-
runExportModulePromise ?? (runExportModulePromise = import("./run-export-
|
|
76
|
+
runExportModulePromise ?? (runExportModulePromise = import("./run-export-SPNNH32M.js"));
|
|
58
77
|
return runExportModulePromise;
|
|
59
78
|
}
|
|
60
79
|
var ExportCancelledError = class extends Error {
|
|
61
80
|
};
|
|
62
81
|
var AudioExportDialog = lazy(
|
|
63
|
-
() => import("./AudioExportDialog-
|
|
82
|
+
() => import("./AudioExportDialog-IOYIEAER.js").then((module) => ({
|
|
64
83
|
default: module.AudioExportDialog
|
|
65
84
|
}))
|
|
66
85
|
);
|
|
@@ -159,6 +178,13 @@ function ExportToolbarControls({
|
|
|
159
178
|
const [transformSummaries, setTransformSummaries] = useState([]);
|
|
160
179
|
const [exporting, setExporting] = useState(false);
|
|
161
180
|
const [exportError, setExportError] = useState(null);
|
|
181
|
+
const [openAfterSave, setOpenAfterSave] = useState(loadOpenAfterExport);
|
|
182
|
+
const [openError, setOpenError] = useState(null);
|
|
183
|
+
const handleOpenAfterSaveChange = useCallback((checked) => {
|
|
184
|
+
setOpenAfterSave(checked);
|
|
185
|
+
saveOpenAfterExport(checked);
|
|
186
|
+
}, []);
|
|
187
|
+
const [exportNotice, setExportNotice] = useState(null);
|
|
162
188
|
const [destinationTarget, setDestinationTarget] = useState(null);
|
|
163
189
|
const [quickDestination, setQuickDestination] = useState(null);
|
|
164
190
|
const [quickDestinationPending, setQuickDestinationPending] = useState(false);
|
|
@@ -300,6 +326,7 @@ function ExportToolbarControls({
|
|
|
300
326
|
setVideoModalOpen(false);
|
|
301
327
|
setVideoDoc(null);
|
|
302
328
|
setVideoLoadError(null);
|
|
329
|
+
setOpenError(null);
|
|
303
330
|
}, []);
|
|
304
331
|
const handleOptionsChange = useCallback(
|
|
305
332
|
(options) => {
|
|
@@ -327,13 +354,28 @@ function ExportToolbarControls({
|
|
|
327
354
|
const savedTarget = await destinationAdapter.saveBlob(blob, filename, target);
|
|
328
355
|
if (!savedTarget) throw new ExportCancelledError();
|
|
329
356
|
setDestinationTarget(savedTarget);
|
|
357
|
+
return savedTarget;
|
|
330
358
|
},
|
|
331
359
|
[destinationAdapter]
|
|
332
360
|
);
|
|
361
|
+
const openSaved = useCallback(
|
|
362
|
+
async (target) => {
|
|
363
|
+
if (!openAfterSave || !destinationAdapter?.openSaved) return;
|
|
364
|
+
try {
|
|
365
|
+
await destinationAdapter.openSaved(target);
|
|
366
|
+
} catch (caught) {
|
|
367
|
+
const detail = hostErrorDetail(caught);
|
|
368
|
+
setOpenError(`The file was saved, but it couldn't be opened.${detail ? ` ${detail}` : ""}`);
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
[destinationAdapter, openAfterSave]
|
|
372
|
+
);
|
|
333
373
|
const handleExport = useCallback(
|
|
334
374
|
async (opts) => {
|
|
335
375
|
setExporting(true);
|
|
336
376
|
setExportError(null);
|
|
377
|
+
setOpenError(null);
|
|
378
|
+
setExportNotice(null);
|
|
337
379
|
try {
|
|
338
380
|
let exportTarget = destinationTarget;
|
|
339
381
|
if (!fileShare && destinationAdapter?.pickBeforeSave) {
|
|
@@ -343,7 +385,8 @@ function ExportToolbarControls({
|
|
|
343
385
|
setDestinationTarget(exportTarget);
|
|
344
386
|
}
|
|
345
387
|
const { runExport } = await loadRunExportModule();
|
|
346
|
-
|
|
388
|
+
let savedTarget;
|
|
389
|
+
const result = await runExport(
|
|
347
390
|
markdownSource,
|
|
348
391
|
selectedFile,
|
|
349
392
|
opts,
|
|
@@ -351,9 +394,13 @@ function ExportToolbarControls({
|
|
|
351
394
|
fileShare && destinationAdapter?.shareBlob ? async (blob, filename) => {
|
|
352
395
|
const outcome = await destinationAdapter.shareBlob(blob, filename);
|
|
353
396
|
if (outcome === "cancelled") throw new ExportCancelledError();
|
|
354
|
-
} : destinationAdapter ? (blob, filename) =>
|
|
397
|
+
} : destinationAdapter ? async (blob, filename) => {
|
|
398
|
+
savedTarget = await saveToDestination(blob, filename, exportTarget);
|
|
399
|
+
} : saveBlob
|
|
355
400
|
);
|
|
356
401
|
setDialogOpen(false);
|
|
402
|
+
if (result.warnings.length > 0) setExportNotice(result.warnings);
|
|
403
|
+
if (savedTarget) await openSaved(savedTarget);
|
|
357
404
|
} catch (caught) {
|
|
358
405
|
if (!(caught instanceof ExportCancelledError)) setExportError(exportErrorMessage(caught));
|
|
359
406
|
} finally {
|
|
@@ -368,7 +415,8 @@ function ExportToolbarControls({
|
|
|
368
415
|
destinationAdapter,
|
|
369
416
|
destinationTarget,
|
|
370
417
|
saveToDestination,
|
|
371
|
-
saveBlob
|
|
418
|
+
saveBlob,
|
|
419
|
+
openSaved
|
|
372
420
|
]
|
|
373
421
|
);
|
|
374
422
|
const handleQuickExport = useCallback(async () => {
|
|
@@ -376,6 +424,8 @@ function ExportToolbarControls({
|
|
|
376
424
|
closeMenu(true);
|
|
377
425
|
setExporting(true);
|
|
378
426
|
setExportError(null);
|
|
427
|
+
setOpenError(null);
|
|
428
|
+
setExportNotice(null);
|
|
379
429
|
try {
|
|
380
430
|
saveExportOptions(lastOptions);
|
|
381
431
|
let quickTarget = null;
|
|
@@ -390,13 +440,18 @@ function ExportToolbarControls({
|
|
|
390
440
|
}
|
|
391
441
|
}
|
|
392
442
|
const { runExport } = await loadRunExportModule();
|
|
393
|
-
|
|
443
|
+
let savedTarget;
|
|
444
|
+
const result = await runExport(
|
|
394
445
|
markdownSource,
|
|
395
446
|
selectedFile,
|
|
396
447
|
lastOptions,
|
|
397
448
|
mediaContainer,
|
|
398
|
-
destinationAdapter ? async (blob, filename) =>
|
|
449
|
+
destinationAdapter ? async (blob, filename) => {
|
|
450
|
+
savedTarget = await saveToDestination(blob, filename, quickTarget);
|
|
451
|
+
} : saveBlob
|
|
399
452
|
);
|
|
453
|
+
if (result.warnings.length > 0) setExportNotice(result.warnings);
|
|
454
|
+
if (savedTarget) await openSaved(savedTarget);
|
|
400
455
|
} catch (caught) {
|
|
401
456
|
if (!(caught instanceof ExportCancelledError)) setExportError(exportErrorMessage(caught));
|
|
402
457
|
} finally {
|
|
@@ -411,14 +466,26 @@ function ExportToolbarControls({
|
|
|
411
466
|
saveBlob,
|
|
412
467
|
saveToDestination,
|
|
413
468
|
selectedFile,
|
|
414
|
-
quickDestinationTarget
|
|
469
|
+
quickDestinationTarget,
|
|
470
|
+
openSaved
|
|
415
471
|
]);
|
|
416
472
|
const handleDismissExportError = useCallback(() => {
|
|
417
473
|
setExportError(null);
|
|
418
474
|
}, []);
|
|
475
|
+
const handleDismissExportNotice = useCallback(() => {
|
|
476
|
+
setExportNotice(null);
|
|
477
|
+
}, []);
|
|
419
478
|
const videoSaveOutput = useMemo(
|
|
420
|
-
() => destinationAdapter ? createImageSaveOutput(
|
|
421
|
-
|
|
479
|
+
() => destinationAdapter ? createImageSaveOutput({
|
|
480
|
+
...destinationAdapter,
|
|
481
|
+
saveBlob: async (blob, filename, target) => {
|
|
482
|
+
setOpenError(null);
|
|
483
|
+
const saved = await destinationAdapter.saveBlob(blob, filename, target);
|
|
484
|
+
if (saved) await openSaved(saved);
|
|
485
|
+
return saved;
|
|
486
|
+
}
|
|
487
|
+
}) : void 0,
|
|
488
|
+
[destinationAdapter, openSaved]
|
|
422
489
|
);
|
|
423
490
|
const LoadedVideoExportModal = videoModules?.Modal;
|
|
424
491
|
const showAnimatedGifExport = showVideoExport && typeof ffmpegWasm?.coreURL === "string" && ffmpegWasm.coreURL.length > 0;
|
|
@@ -598,6 +665,7 @@ function ExportToolbarControls({
|
|
|
598
665
|
documentThemes,
|
|
599
666
|
exporting,
|
|
600
667
|
error: exportError,
|
|
668
|
+
openAfterSave: !fileShare && destinationAdapter?.openSaved ? { checked: openAfterSave, onChange: handleOpenAfterSaveChange } : void 0,
|
|
601
669
|
destination: destinationAdapter && destinationAdapter.showDestination !== false ? {
|
|
602
670
|
value: destinationTarget?.displayPath ?? "",
|
|
603
671
|
onPick: handlePickDestination,
|
|
@@ -636,6 +704,28 @@ function ExportToolbarControls({
|
|
|
636
704
|
children: /* @__PURE__ */ jsx("p", { className: "db-export-error", role: "alert", children: exportError })
|
|
637
705
|
}
|
|
638
706
|
),
|
|
707
|
+
openError && !videoModalOpen && /* @__PURE__ */ jsx(Dialog, { title: "Open saved export", onClose: () => setOpenError(null), children: /* @__PURE__ */ jsx("p", { role: "alert", children: openError }) }),
|
|
708
|
+
exportNotice && !dialogOpen && !exportError && !openError && /* @__PURE__ */ jsx(
|
|
709
|
+
Dialog,
|
|
710
|
+
{
|
|
711
|
+
title: "Export Document",
|
|
712
|
+
onClose: handleDismissExportNotice,
|
|
713
|
+
footer: /* @__PURE__ */ jsx(
|
|
714
|
+
"button",
|
|
715
|
+
{
|
|
716
|
+
type: "button",
|
|
717
|
+
className: "db-export-btn db-export-btn--secondary",
|
|
718
|
+
onClick: handleDismissExportNotice,
|
|
719
|
+
children: "Close"
|
|
720
|
+
}
|
|
721
|
+
),
|
|
722
|
+
children: /* @__PURE__ */ jsxs("div", { role: "status", children: [
|
|
723
|
+
/* @__PURE__ */ jsx("p", { children: "The file was saved, but not everything in the document could be included." }),
|
|
724
|
+
exportNotice.map((warning) => /* @__PURE__ */ jsx("p", { children: warning }, warning)),
|
|
725
|
+
/* @__PURE__ */ jsx("p", { children: "Export to Word, HTML or EPUB to keep every character." })
|
|
726
|
+
] })
|
|
727
|
+
}
|
|
728
|
+
),
|
|
639
729
|
shareDialogOpen && /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
|
|
640
730
|
ShareDialog,
|
|
641
731
|
{
|
|
@@ -662,6 +752,16 @@ function ExportToolbarControls({
|
|
|
662
752
|
mediaEditRenders,
|
|
663
753
|
colorScheme,
|
|
664
754
|
uiPalette: videoExportPalette,
|
|
755
|
+
saveOptions: destinationAdapter?.openSaved ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
756
|
+
/* @__PURE__ */ jsx(
|
|
757
|
+
OpenAfterSaveCheckbox,
|
|
758
|
+
{
|
|
759
|
+
checked: openAfterSave,
|
|
760
|
+
onChange: handleOpenAfterSaveChange
|
|
761
|
+
}
|
|
762
|
+
),
|
|
763
|
+
openError && /* @__PURE__ */ jsx("p", { role: "alert", children: openError })
|
|
764
|
+
] }) : void 0,
|
|
665
765
|
defaultConfig: {
|
|
666
766
|
audioPolicy: "best-effort",
|
|
667
767
|
...ffmpegWasm ? { ffmpegWasm } : {},
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SHELL_SHORTCUTS,
|
|
3
3
|
isApplePlatform
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ACQF63SB.js";
|
|
5
5
|
import {
|
|
6
6
|
Dialog
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-VJPGZCFS.js";
|
|
8
8
|
|
|
9
9
|
// src/DocBlocksShell/KeyboardShortcutsDialog.tsx
|
|
10
10
|
import { Fragment, useId, useMemo } from "react";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PresentationMaker
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-PNZFIIWW.js";
|
|
4
|
+
import "./chunk-7V34VUK6.js";
|
|
5
5
|
import "./chunk-K4I3NJFL.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-VJPGZCFS.js";
|
|
7
7
|
export {
|
|
8
8
|
PresentationMaker
|
|
9
9
|
};
|
|
@@ -14,8 +14,7 @@ type AccentColor = (typeof ACCENT_COLORS)[number];
|
|
|
14
14
|
* face: the Hanken Grotesk variable binary every surface already ships for
|
|
15
15
|
* documents set in it, and the sans docblocks.com uses. The app and the site
|
|
16
16
|
* then read as one product, and the interface renders identically on every
|
|
17
|
-
* OS
|
|
18
|
-
* baselines across platforms at all.
|
|
17
|
+
* OS.
|
|
19
18
|
*
|
|
20
19
|
* `system` resolves `system-ui`, for anyone who would rather DocBlocks looked
|
|
21
20
|
* native on each platform; the chrome then fetches no font.
|
|
@@ -35,7 +34,7 @@ declare function saveInterfaceFont(value: InterfaceFontPreference): void;
|
|
|
35
34
|
* (the wire/persisted contract) and the `docblocks.writeCanvasFontScheme` enum
|
|
36
35
|
* in the VS Code `package.json`; a guard test keeps the three in sync.
|
|
37
36
|
*/
|
|
38
|
-
type WriteCanvasFontScheme = 'theme' | 'serif-sans' | 'sans-sans' | 'serif-serif' | 'pt-serif' | 'hanken' | 'playfair-pt-serif' | 'hanken-lora' | 'dm-serif-dm-sans' | 'inter';
|
|
37
|
+
type WriteCanvasFontScheme = 'theme' | 'serif-sans' | 'sans-sans' | 'serif-serif' | 'pt-serif' | 'hanken' | 'playfair-pt-serif' | 'hanken-lora' | 'dm-serif-dm-sans' | 'inter' | 'inconsolata';
|
|
39
38
|
type WriteCanvasFontSchemeGroup = 'theme' | 'system' | 'curated';
|
|
40
39
|
interface WriteCanvasFontSchemeOption {
|
|
41
40
|
id: WriteCanvasFontScheme;
|
|
@@ -116,8 +115,7 @@ interface InterfaceFontSettingsProps {
|
|
|
116
115
|
* The default follows the operating system, which is what almost everyone
|
|
117
116
|
* should keep. The bundled option exists for two reasons worth stating in the
|
|
118
117
|
* UI: identical typography across machines, and a rendering that is the same
|
|
119
|
-
*
|
|
120
|
-
* of baselines across operating systems at all.
|
|
118
|
+
* on every operating system.
|
|
121
119
|
*/
|
|
122
120
|
declare function InterfaceFontSettings({ value, onChange, name, }: InterfaceFontSettingsProps): react_jsx_runtime.JSX.Element;
|
|
123
121
|
interface AccentColorSettingsProps {
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "./chunk-GMA4KGGO.js";
|
|
16
16
|
import {
|
|
17
17
|
Dialog
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-VJPGZCFS.js";
|
|
19
19
|
|
|
20
20
|
// src/Speech/SpeechToolbarControl.tsx
|
|
21
21
|
import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "./chunk-K4I3NJFL.js";
|
|
11
11
|
import {
|
|
12
12
|
Dialog
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-VJPGZCFS.js";
|
|
14
14
|
|
|
15
15
|
// src/Speech/TextFromNarration.tsx
|
|
16
16
|
import { useEffect as useEffect3, useMemo, useRef as useRef3, useState as useState3 } from "react";
|
|
@@ -4,24 +4,53 @@ import {
|
|
|
4
4
|
|
|
5
5
|
// src/Export/run-export.ts
|
|
6
6
|
import {
|
|
7
|
+
isSvgImageSource,
|
|
7
8
|
parseFrontmatter,
|
|
8
9
|
parseMarkdown,
|
|
9
10
|
readFrontmatterThemeId,
|
|
10
|
-
splitFrontmatterBlock
|
|
11
|
+
splitFrontmatterBlock,
|
|
12
|
+
svgSourceFromBytes
|
|
11
13
|
} from "@bendyline/squisq/markdown";
|
|
14
|
+
async function diagramRendererFor(overrides) {
|
|
15
|
+
if (overrides.diagramRenderer) return overrides.diagramRenderer;
|
|
16
|
+
const module = await import("@bendyline/squisq-react/diagram-pictures");
|
|
17
|
+
return module.createDiagramPictureRenderer();
|
|
18
|
+
}
|
|
12
19
|
async function pictureDiagrams(doc, overrides, kinds) {
|
|
13
20
|
try {
|
|
14
|
-
const [{ rasterizeDiagrams }, render] = await Promise.all([
|
|
21
|
+
const [{ rasterizeDiagrams, EXPORT_DIAGRAM_KINDS }, render] = await Promise.all([
|
|
15
22
|
import("@bendyline/squisq-formats/diagrams"),
|
|
16
|
-
overrides
|
|
17
|
-
(module) => module.createDiagramPictureRenderer()
|
|
18
|
-
)
|
|
23
|
+
diagramRendererFor(overrides)
|
|
19
24
|
]);
|
|
20
|
-
return await rasterizeDiagrams(doc, render, {
|
|
25
|
+
return await rasterizeDiagrams(doc, render, {
|
|
26
|
+
kinds: kinds === "all" ? EXPORT_DIAGRAM_KINDS : kinds,
|
|
27
|
+
urlPrefix: "docblocks-diagram"
|
|
28
|
+
});
|
|
21
29
|
} catch {
|
|
22
|
-
return { markdownDoc: doc, images: /* @__PURE__ */ new Map(), mermaid: /* @__PURE__ */ new Map() };
|
|
30
|
+
return { markdownDoc: doc, images: /* @__PURE__ */ new Map(), mermaid: /* @__PURE__ */ new Map(), svg: /* @__PURE__ */ new Map() };
|
|
23
31
|
}
|
|
24
32
|
}
|
|
33
|
+
async function pictureSvgAttachments(attachments, overrides) {
|
|
34
|
+
const pictures = /* @__PURE__ */ new Map();
|
|
35
|
+
const sources = /* @__PURE__ */ new Set();
|
|
36
|
+
for (const [url, data] of attachments) {
|
|
37
|
+
if (isSvgImageSource(url)) sources.add(svgSourceFromBytes(data).trim());
|
|
38
|
+
}
|
|
39
|
+
if (sources.size === 0) return pictures;
|
|
40
|
+
try {
|
|
41
|
+
const render = await diagramRendererFor(overrides);
|
|
42
|
+
for (const source of sources) {
|
|
43
|
+
const diagram = { kind: "svg", markdown: "", source, template: "", alt: "" };
|
|
44
|
+
const picture = await render(diagram).catch(() => null);
|
|
45
|
+
if (picture && picture.width > 0 && picture.height > 0) pictures.set(source, picture);
|
|
46
|
+
}
|
|
47
|
+
} catch {
|
|
48
|
+
}
|
|
49
|
+
return pictures;
|
|
50
|
+
}
|
|
51
|
+
function imageBytes(images) {
|
|
52
|
+
return [...images].map(([url, image]) => [url, image.data]);
|
|
53
|
+
}
|
|
25
54
|
var MIME_TYPES = {
|
|
26
55
|
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
27
56
|
pdf: "application/pdf",
|
|
@@ -58,6 +87,19 @@ function buildFilename(selectedFile, format) {
|
|
|
58
87
|
return base + FORMAT_EXTENSIONS[format];
|
|
59
88
|
}
|
|
60
89
|
async function runExport(markdown, selectedFile, options, mediaContainer, saveBlob, converterOverrides = {}) {
|
|
90
|
+
const warnings = [];
|
|
91
|
+
await exportDocument(
|
|
92
|
+
markdown,
|
|
93
|
+
selectedFile,
|
|
94
|
+
options,
|
|
95
|
+
mediaContainer,
|
|
96
|
+
saveBlob,
|
|
97
|
+
converterOverrides,
|
|
98
|
+
warnings
|
|
99
|
+
);
|
|
100
|
+
return { warnings };
|
|
101
|
+
}
|
|
102
|
+
async function exportDocument(markdown, selectedFile, options, mediaContainer, saveBlob, converterOverrides, warnings) {
|
|
61
103
|
const filename = buildFilename(selectedFile, options.format);
|
|
62
104
|
const themeId = exporterThemeId(markdown, options.themeId);
|
|
63
105
|
if (options.format === "md") {
|
|
@@ -72,26 +114,36 @@ async function runExport(markdown, selectedFile, options, mediaContainer, saveBl
|
|
|
72
114
|
if (options.format === "docx") {
|
|
73
115
|
const { markdownDocToDocx } = await import("@bendyline/squisq-formats/docx");
|
|
74
116
|
const pictured = await pictureDiagrams(doc, converterOverrides);
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
]);
|
|
79
|
-
const buf = await markdownDocToDocx(pictured.markdownDoc, {
|
|
117
|
+
const { svg } = await pictureDiagrams(doc, converterOverrides, ["svg"]);
|
|
118
|
+
const attachments = await resolveImages(doc, mediaContainer);
|
|
119
|
+
const svgAttachments = await pictureSvgAttachments(imageBytes(attachments), converterOverrides);
|
|
120
|
+
const images = new Map([...attachments, ...pictured.images]);
|
|
121
|
+
const buf = await markdownDocToDocx(pictured.markdownDoc, {
|
|
122
|
+
themeId,
|
|
123
|
+
images,
|
|
124
|
+
svgIslandFallbacks: new Map([...svg, ...svgAttachments])
|
|
125
|
+
});
|
|
80
126
|
await saveExportBlob(new Blob([buf], { type: MIME_TYPES.docx }), filename, saveBlob);
|
|
81
127
|
return;
|
|
82
128
|
}
|
|
83
129
|
if (options.format === "pdf") {
|
|
84
130
|
const { markdownDocToPdf } = await import("@bendyline/squisq-formats/pdf");
|
|
85
|
-
const pictured = await pictureDiagrams(doc, converterOverrides);
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
]);
|
|
131
|
+
const pictured = await pictureDiagrams(doc, converterOverrides, "all");
|
|
132
|
+
const attachments = await resolveImages(doc, mediaContainer);
|
|
133
|
+
const svgPictures = await pictureSvgAttachments(imageBytes(attachments), converterOverrides);
|
|
134
|
+
const images = new Map([...withSvgPictures(attachments, svgPictures), ...pictured.images]);
|
|
90
135
|
const buf = await markdownDocToPdf(pictured.markdownDoc, {
|
|
91
136
|
themeId,
|
|
92
137
|
pageSize: options.pageSize,
|
|
93
|
-
images
|
|
138
|
+
images,
|
|
139
|
+
// Check fidelity before any download or destination write occurs.
|
|
140
|
+
onWarning: (message) => warnings.push(message)
|
|
94
141
|
});
|
|
142
|
+
if (warnings.length > 0) {
|
|
143
|
+
throw new Error(
|
|
144
|
+
"PDF was not saved because its fonts cannot preserve all of this document\u2019s text. Export as Word, HTML, or EPUB to keep every character. " + warnings.join(" ")
|
|
145
|
+
);
|
|
146
|
+
}
|
|
95
147
|
await saveExportBlob(new Blob([buf], { type: MIME_TYPES.pdf }), filename, saveBlob);
|
|
96
148
|
return;
|
|
97
149
|
}
|
|
@@ -110,21 +162,37 @@ async function runExport(markdown, selectedFile, options, mediaContainer, saveBl
|
|
|
110
162
|
}
|
|
111
163
|
if (options.format === "pptx") {
|
|
112
164
|
const pptxModule = converterOverrides.docToPptx ? Promise.resolve({ docToPptx: converterOverrides.docToPptx }) : import("@bendyline/squisq-formats/pptx");
|
|
113
|
-
const [
|
|
165
|
+
const [
|
|
166
|
+
{ markdownToDoc },
|
|
167
|
+
{ applyTransform, PRESENTATION_KEY },
|
|
168
|
+
{ buildPreviewDoc },
|
|
169
|
+
{ docToPptx }
|
|
170
|
+
] = await Promise.all([
|
|
114
171
|
import("@bendyline/squisq/doc"),
|
|
115
172
|
import("@bendyline/squisq/transform"),
|
|
116
173
|
import("@bendyline/squisq-editor-react"),
|
|
117
174
|
pptxModule
|
|
118
175
|
]);
|
|
119
176
|
const baseDoc = markdownToDoc(doc);
|
|
120
|
-
|
|
121
|
-
|
|
177
|
+
if (!options.transformStyle) {
|
|
178
|
+
baseDoc.frontmatter = { ...baseDoc.frontmatter };
|
|
179
|
+
delete baseDoc.frontmatter["squisq-transform"];
|
|
180
|
+
delete baseDoc.frontmatter["transform-style"];
|
|
181
|
+
delete baseDoc.frontmatter[PRESENTATION_KEY];
|
|
182
|
+
}
|
|
183
|
+
const contentDoc = options.transformStyle ? applyTransform(baseDoc, options.transformStyle).doc : baseDoc;
|
|
184
|
+
const enrichedDoc = buildPreviewDoc(contentDoc);
|
|
122
185
|
if (themeId) {
|
|
123
186
|
enrichedDoc.themeId = themeId;
|
|
124
187
|
}
|
|
125
188
|
const images = mediaContainer ? await resolveImageData(doc, mediaContainer) : void 0;
|
|
126
|
-
const { mermaid } = await pictureDiagrams(doc, converterOverrides, ["mermaid"]);
|
|
127
|
-
const
|
|
189
|
+
const { mermaid, svg } = await pictureDiagrams(doc, converterOverrides, ["mermaid", "svg"]);
|
|
190
|
+
const svgAttachments = await pictureSvgAttachments(images ?? [], converterOverrides);
|
|
191
|
+
const buf = await docToPptx(enrichedDoc, {
|
|
192
|
+
themeId,
|
|
193
|
+
images,
|
|
194
|
+
diagramImages: new Map([...mermaid, ...svg, ...svgAttachments])
|
|
195
|
+
});
|
|
128
196
|
await saveExportBlob(new Blob([buf], { type: MIME_TYPES.pptx }), filename, saveBlob);
|
|
129
197
|
return;
|
|
130
198
|
}
|
|
@@ -288,8 +356,9 @@ function collectMarkdownImageUrls(doc) {
|
|
|
288
356
|
return Array.from(new Set(urls));
|
|
289
357
|
}
|
|
290
358
|
async function resolveImages(doc, container) {
|
|
291
|
-
const urls = collectMarkdownImageUrls(doc);
|
|
292
359
|
const map = /* @__PURE__ */ new Map();
|
|
360
|
+
if (!container) return map;
|
|
361
|
+
const urls = collectMarkdownImageUrls(doc);
|
|
293
362
|
for (const url of urls) {
|
|
294
363
|
if (map.has(url)) continue;
|
|
295
364
|
if (isExternalUrl(url)) continue;
|
|
@@ -301,6 +370,22 @@ async function resolveImages(doc, container) {
|
|
|
301
370
|
}
|
|
302
371
|
return map;
|
|
303
372
|
}
|
|
373
|
+
function withSvgPictures(images, pictures) {
|
|
374
|
+
const result = /* @__PURE__ */ new Map();
|
|
375
|
+
for (const [url, image] of images) {
|
|
376
|
+
const picture = isSvgImageSource(url) ? pictures.get(svgSourceFromBytes(image.data).trim()) : void 0;
|
|
377
|
+
result.set(
|
|
378
|
+
url,
|
|
379
|
+
picture ? {
|
|
380
|
+
data: picture.data,
|
|
381
|
+
contentType: "image/png",
|
|
382
|
+
width: picture.width,
|
|
383
|
+
height: picture.height
|
|
384
|
+
} : image
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
return result;
|
|
388
|
+
}
|
|
304
389
|
async function resolveImageData(doc, container) {
|
|
305
390
|
const urls = collectMarkdownImageUrls(doc);
|
|
306
391
|
const map = /* @__PURE__ */ new Map();
|