@bendyline/docblocks-react 1.1.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -15
- package/dist/AppMenu/AppMenu.d.ts +29 -2
- package/dist/AppMenu/AppMenu.d.ts.map +1 -1
- package/dist/AppMenu/AppMenu.js +41 -2
- package/dist/AppMenu/AppMenu.js.map +1 -1
- package/dist/AppMenu/index.d.ts +1 -1
- package/dist/AppMenu/index.d.ts.map +1 -1
- package/dist/DocBlocksShell/DocBlocksShell.d.ts +17 -4
- package/dist/DocBlocksShell/DocBlocksShell.d.ts.map +1 -1
- package/dist/DocBlocksShell/DocBlocksShell.js +1710 -299
- package/dist/DocBlocksShell/DocBlocksShell.js.map +1 -1
- package/dist/DocBlocksShell/LazyEditorShell.d.ts +3 -0
- package/dist/DocBlocksShell/LazyEditorShell.d.ts.map +1 -0
- package/dist/DocBlocksShell/LazyEditorShell.js +3 -0
- package/dist/DocBlocksShell/LazyEditorShell.js.map +1 -0
- package/dist/DocBlocksShell/UpdateAvailableNotice.d.ts +13 -0
- package/dist/DocBlocksShell/UpdateAvailableNotice.d.ts.map +1 -0
- package/dist/DocBlocksShell/UpdateAvailableNotice.js +16 -0
- package/dist/DocBlocksShell/UpdateAvailableNotice.js.map +1 -0
- package/dist/DocBlocksShell/document-title.d.ts +3 -0
- package/dist/DocBlocksShell/document-title.d.ts.map +1 -0
- package/dist/DocBlocksShell/document-title.js +17 -0
- package/dist/DocBlocksShell/document-title.js.map +1 -0
- package/dist/DocBlocksShell/workspace-authority-barrier.d.ts +14 -0
- package/dist/DocBlocksShell/workspace-authority-barrier.d.ts.map +1 -0
- package/dist/DocBlocksShell/workspace-authority-barrier.js +23 -0
- package/dist/DocBlocksShell/workspace-authority-barrier.js.map +1 -0
- package/dist/Export/DeferredExportToolbarControls.d.ts +5 -0
- package/dist/Export/DeferredExportToolbarControls.d.ts.map +1 -0
- package/dist/Export/DeferredExportToolbarControls.js +10 -0
- package/dist/Export/DeferredExportToolbarControls.js.map +1 -0
- package/dist/Export/ExportDialog.d.ts +10 -1
- package/dist/Export/ExportDialog.d.ts.map +1 -1
- package/dist/Export/ExportDialog.js +39 -20
- package/dist/Export/ExportDialog.js.map +1 -1
- package/dist/Export/ExportToolbarControls.d.ts +21 -1
- package/dist/Export/ExportToolbarControls.d.ts.map +1 -1
- package/dist/Export/ExportToolbarControls.js +161 -26
- package/dist/Export/ExportToolbarControls.js.map +1 -1
- package/dist/Export/export-destination.d.ts +3 -0
- package/dist/Export/export-destination.d.ts.map +1 -0
- package/dist/Export/export-destination.js +32 -0
- package/dist/Export/export-destination.js.map +1 -0
- package/dist/Export/index.d.ts +8 -4
- package/dist/Export/index.d.ts.map +1 -1
- package/dist/Export/index.js +4 -1
- package/dist/Export/index.js.map +1 -1
- package/dist/Export/public-api.d.ts +12 -0
- package/dist/Export/public-api.d.ts.map +1 -0
- package/dist/Export/public-api.js +9 -0
- package/dist/Export/public-api.js.map +1 -0
- package/dist/Export/run-export.d.ts +3 -1
- package/dist/Export/run-export.d.ts.map +1 -1
- package/dist/Export/run-export.js +58 -25
- package/dist/Export/run-export.js.map +1 -1
- package/dist/Export/transform-summaries.d.ts +7 -0
- package/dist/Export/transform-summaries.d.ts.map +1 -0
- package/dist/Export/transform-summaries.js +6 -0
- package/dist/Export/transform-summaries.js.map +1 -0
- package/dist/ExportDialog-MEUISWZX.js +9 -0
- package/dist/ExportDialog-MEUISWZX.js.map +1 -0
- package/dist/ExportToolbarControls-D2YDWOXW.js +373 -0
- package/dist/ExportToolbarControls-D2YDWOXW.js.map +1 -0
- package/dist/FileExplorer/FileExplorer.d.ts +26 -4
- package/dist/FileExplorer/FileExplorer.d.ts.map +1 -1
- package/dist/FileExplorer/FileExplorer.js +204 -29
- package/dist/FileExplorer/FileExplorer.js.map +1 -1
- package/dist/FileExplorer/FileTreeNode.d.ts +24 -3
- package/dist/FileExplorer/FileTreeNode.d.ts.map +1 -1
- package/dist/FileExplorer/FileTreeNode.js +27 -8
- package/dist/FileExplorer/FileTreeNode.js.map +1 -1
- package/dist/FileExplorer/index.d.ts +1 -1
- package/dist/FileExplorer/index.d.ts.map +1 -1
- package/dist/FileExplorer/useFileTree.d.ts +5 -3
- package/dist/FileExplorer/useFileTree.d.ts.map +1 -1
- package/dist/FileExplorer/useFileTree.js +173 -13
- package/dist/FileExplorer/useFileTree.js.map +1 -1
- package/dist/Git/GitAuthGuidanceDialog.d.ts +18 -0
- package/dist/Git/GitAuthGuidanceDialog.d.ts.map +1 -0
- package/dist/Git/GitAuthGuidanceDialog.js +27 -0
- package/dist/Git/GitAuthGuidanceDialog.js.map +1 -0
- package/dist/Git/GitBranchesDialog.d.ts +13 -0
- package/dist/Git/GitBranchesDialog.d.ts.map +1 -0
- package/dist/Git/GitBranchesDialog.js +59 -0
- package/dist/Git/GitBranchesDialog.js.map +1 -0
- package/dist/Git/GitCloneDialog.d.ts +14 -0
- package/dist/Git/GitCloneDialog.d.ts.map +1 -0
- package/dist/Git/GitCloneDialog.js +79 -0
- package/dist/Git/GitCloneDialog.js.map +1 -0
- package/dist/Git/GitCommitDialog.d.ts +12 -0
- package/dist/Git/GitCommitDialog.d.ts.map +1 -0
- package/dist/Git/GitCommitDialog.js +38 -0
- package/dist/Git/GitCommitDialog.js.map +1 -0
- package/dist/Git/GitConflictsDialog.d.ts +12 -0
- package/dist/Git/GitConflictsDialog.d.ts.map +1 -0
- package/dist/Git/GitConflictsDialog.js +17 -0
- package/dist/Git/GitConflictsDialog.js.map +1 -0
- package/dist/Git/GitContext.d.ts +89 -0
- package/dist/Git/GitContext.d.ts.map +1 -0
- package/dist/Git/GitContext.js +15 -0
- package/dist/Git/GitContext.js.map +1 -0
- package/dist/Git/GitDiffDialog.d.ts +20 -0
- package/dist/Git/GitDiffDialog.d.ts.map +1 -0
- package/dist/Git/GitDiffDialog.js +100 -0
- package/dist/Git/GitDiffDialog.js.map +1 -0
- package/dist/Git/GitDiffView.d.ts +23 -0
- package/dist/Git/GitDiffView.d.ts.map +1 -0
- package/dist/Git/GitDiffView.js +77 -0
- package/dist/Git/GitDiffView.js.map +1 -0
- package/dist/Git/GitHistoryDialog.d.ts +15 -0
- package/dist/Git/GitHistoryDialog.d.ts.map +1 -0
- package/dist/Git/GitHistoryDialog.js +107 -0
- package/dist/Git/GitHistoryDialog.js.map +1 -0
- package/dist/Git/GitStatusBar.d.ts +8 -0
- package/dist/Git/GitStatusBar.d.ts.map +1 -0
- package/dist/Git/GitStatusBar.js +49 -0
- package/dist/Git/GitStatusBar.js.map +1 -0
- package/dist/Git/GitToolbarControl.d.ts +15 -0
- package/dist/Git/GitToolbarControl.d.ts.map +1 -0
- package/dist/Git/GitToolbarControl.js +51 -0
- package/dist/Git/GitToolbarControl.js.map +1 -0
- package/dist/Git/GitUI.d.ts +14 -0
- package/dist/Git/GitUI.d.ts.map +1 -0
- package/dist/Git/GitUI.js +21 -0
- package/dist/Git/GitUI.js.map +1 -0
- package/dist/Git/commit-selection.d.ts +22 -0
- package/dist/Git/commit-selection.d.ts.map +1 -0
- package/dist/Git/commit-selection.js +47 -0
- package/dist/Git/commit-selection.js.map +1 -0
- package/dist/Git/git-clone-utils.d.ts +8 -0
- package/dist/Git/git-clone-utils.d.ts.map +1 -0
- package/dist/Git/git-clone-utils.js +26 -0
- package/dist/Git/git-clone-utils.js.map +1 -0
- package/dist/Git/git-status.d.ts +24 -0
- package/dist/Git/git-status.d.ts.map +1 -0
- package/dist/Git/git-status.js +105 -0
- package/dist/Git/git-status.js.map +1 -0
- package/dist/Git/useGit.d.ts +15 -0
- package/dist/Git/useGit.d.ts.map +1 -0
- package/dist/Git/useGit.js +206 -0
- package/dist/Git/useGit.js.map +1 -0
- package/dist/Git/useGitStatus.d.ts +17 -0
- package/dist/Git/useGitStatus.d.ts.map +1 -0
- package/dist/Git/useGitStatus.js +63 -0
- package/dist/Git/useGitStatus.js.map +1 -0
- package/dist/GitToolbarControl-LMIR4R7I.js +117 -0
- package/dist/GitToolbarControl-LMIR4R7I.js.map +1 -0
- package/dist/GitUI-KGF5MSNV.js +1048 -0
- package/dist/GitUI-KGF5MSNV.js.map +1 -0
- package/dist/LazyEditorShell-EF2BWRXU.js +6 -0
- package/dist/LazyEditorShell-EF2BWRXU.js.map +1 -0
- package/dist/Settings/Settings.d.ts +23 -0
- package/dist/Settings/Settings.d.ts.map +1 -0
- package/dist/Settings/Settings.js +22 -0
- package/dist/Settings/Settings.js.map +1 -0
- package/dist/Settings/public-api.d.ts +3 -0
- package/dist/Settings/public-api.d.ts.map +1 -0
- package/dist/Settings/public-api.js +2 -0
- package/dist/Settings/public-api.js.map +1 -0
- package/dist/WorkspacePicker/WorkspacePicker.d.ts +6 -1
- package/dist/WorkspacePicker/WorkspacePicker.d.ts.map +1 -1
- package/dist/WorkspacePicker/WorkspacePicker.js +16 -5
- package/dist/WorkspacePicker/WorkspacePicker.js.map +1 -1
- package/dist/chunk-3SAXDU2U.js +157 -0
- package/dist/chunk-3SAXDU2U.js.map +1 -0
- package/dist/chunk-4XXSWN3T.js +13 -0
- package/dist/chunk-4XXSWN3T.js.map +1 -0
- package/dist/chunk-5A4KEWKT.js +97 -0
- package/dist/chunk-5A4KEWKT.js.map +1 -0
- package/dist/chunk-AOVTHZU7.js +321 -0
- package/dist/chunk-AOVTHZU7.js.map +1 -0
- package/dist/chunk-DD4VFJQI.js +51 -0
- package/dist/chunk-DD4VFJQI.js.map +1 -0
- package/dist/chunk-GSNZSCIK.js +55 -0
- package/dist/chunk-GSNZSCIK.js.map +1 -0
- package/dist/chunk-VHDP4IPL.js +70 -0
- package/dist/chunk-VHDP4IPL.js.map +1 -0
- package/dist/chunk-ZI56BNB7.js +270 -0
- package/dist/chunk-ZI56BNB7.js.map +1 -0
- package/dist/components/Dialog.d.ts +22 -0
- package/dist/components/Dialog.d.ts.map +1 -0
- package/dist/components/Dialog.js +33 -0
- package/dist/components/Dialog.js.map +1 -0
- package/dist/editor.d.ts +10 -0
- package/dist/editor.d.ts.map +1 -0
- package/dist/editor.js +70 -0
- package/dist/editor.js.map +1 -0
- package/dist/export/index.d.ts +87 -0
- package/dist/export/index.js +26 -0
- package/dist/export/index.js.map +1 -0
- package/dist/hooks/index.d.ts +2 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/useDocumentSession.d.ts +16 -0
- package/dist/hooks/useDocumentSession.d.ts.map +1 -0
- package/dist/hooks/useDocumentSession.js +18 -0
- package/dist/hooks/useDocumentSession.js.map +1 -0
- package/dist/icons.d.ts +11 -6
- package/dist/icons.d.ts.map +1 -1
- package/dist/icons.js +21 -20
- package/dist/icons.js.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/preferences/theme.d.ts +18 -0
- package/dist/preferences/theme.d.ts.map +1 -0
- package/dist/preferences/theme.js +63 -0
- package/dist/preferences/theme.js.map +1 -0
- package/dist/provider-lease.d.ts +10 -0
- package/dist/provider-lease.d.ts.map +1 -0
- package/dist/provider-lease.js +42 -0
- package/dist/provider-lease.js.map +1 -0
- package/dist/run-export-ICTZITXC.js +10 -0
- package/dist/run-export-ICTZITXC.js.map +1 -0
- package/dist/settings/index.d.ts +28 -0
- package/dist/settings/index.js +12 -0
- package/dist/settings/index.js.map +1 -0
- package/package.json +27 -10
- package/src/AppMenu/AppMenu.tsx +169 -99
- package/src/AppMenu/index.ts +1 -1
- package/src/DocBlocksShell/DocBlocksShell.tsx +2183 -516
- package/src/DocBlocksShell/LazyEditorShell.ts +2 -0
- package/src/DocBlocksShell/UpdateAvailableNotice.tsx +60 -0
- package/src/DocBlocksShell/document-title.ts +19 -0
- package/src/DocBlocksShell/workspace-authority-barrier.ts +26 -0
- package/src/Export/DeferredExportToolbarControls.tsx +23 -0
- package/src/Export/ExportDialog.tsx +102 -27
- package/src/Export/ExportToolbarControls.tsx +343 -57
- package/src/Export/export-destination.ts +30 -0
- package/src/Export/index.ts +18 -4
- package/src/Export/public-api.ts +17 -0
- package/src/Export/run-export.ts +66 -29
- package/src/Export/transform-summaries.ts +14 -0
- package/src/FileExplorer/FileExplorer.tsx +284 -38
- package/src/FileExplorer/FileTreeNode.tsx +100 -8
- package/src/FileExplorer/index.ts +1 -1
- package/src/FileExplorer/useFileTree.ts +190 -16
- package/src/Git/GitAuthGuidanceDialog.tsx +84 -0
- package/src/Git/GitBranchesDialog.tsx +144 -0
- package/src/Git/GitCloneDialog.tsx +200 -0
- package/src/Git/GitCommitDialog.tsx +119 -0
- package/src/Git/GitConflictsDialog.tsx +62 -0
- package/src/Git/GitContext.tsx +88 -0
- package/src/Git/GitDiffDialog.tsx +147 -0
- package/src/Git/GitDiffView.tsx +105 -0
- package/src/Git/GitHistoryDialog.tsx +195 -0
- package/src/Git/GitStatusBar.tsx +157 -0
- package/src/Git/GitToolbarControl.tsx +123 -0
- package/src/Git/GitUI.tsx +68 -0
- package/src/Git/commit-selection.ts +63 -0
- package/src/Git/git-clone-utils.ts +23 -0
- package/src/Git/git-status.ts +113 -0
- package/src/Git/useGit.ts +279 -0
- package/src/Git/useGitStatus.ts +78 -0
- package/src/Settings/Settings.tsx +118 -0
- package/src/Settings/public-api.ts +8 -0
- package/src/WorkspacePicker/WorkspacePicker.tsx +62 -8
- package/src/components/Dialog.tsx +81 -0
- package/src/editor.ts +72 -0
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useDocumentSession.ts +37 -0
- package/src/icons.tsx +33 -55
- package/src/index.ts +35 -5
- package/src/preferences/theme.ts +67 -0
- package/src/provider-lease.ts +52 -0
- package/src/styles/docblocks.css +2247 -77
- package/src/types/pwa-dom.d.ts +31 -0
- package/dist/hooks/useAutoSave.d.ts +0 -15
- package/dist/hooks/useAutoSave.d.ts.map +0 -1
- package/dist/hooks/useAutoSave.js +0 -83
- package/dist/hooks/useAutoSave.js.map +0 -1
- package/src/fonts/fonts.css +0 -362
- package/src/fonts/licenses/LICENSE-cormorant-garamond.txt +0 -93
- package/src/fonts/licenses/LICENSE-crimson-text.txt +0 -93
- package/src/fonts/licenses/LICENSE-dm-sans.txt +0 -93
- package/src/fonts/licenses/LICENSE-dm-serif-display.txt +0 -93
- package/src/fonts/licenses/LICENSE-hanken-grotesk.txt +0 -94
- package/src/fonts/licenses/LICENSE-ibm-plex-sans.txt +0 -93
- package/src/fonts/licenses/LICENSE-inter.txt +0 -93
- package/src/fonts/licenses/LICENSE-jetbrains-mono.txt +0 -93
- package/src/fonts/licenses/LICENSE-lora.txt +0 -93
- package/src/fonts/licenses/LICENSE-merriweather.txt +0 -93
- package/src/fonts/licenses/LICENSE-oswald.txt +0 -93
- package/src/fonts/licenses/LICENSE-playfair-display.txt +0 -93
- package/src/fonts/licenses/LICENSE-pt-serif.txt +0 -93
- package/src/fonts/licenses/LICENSE-roboto.txt +0 -93
- package/src/fonts/licenses/LICENSE-source-serif-4.txt +0 -93
- package/src/fonts/woff2/cormorant-garamond-400.woff2 +0 -0
- package/src/fonts/woff2/cormorant-garamond-700.woff2 +0 -0
- package/src/fonts/woff2/crimson-text-400.woff2 +0 -0
- package/src/fonts/woff2/crimson-text-400i.woff2 +0 -0
- package/src/fonts/woff2/crimson-text-700.woff2 +0 -0
- package/src/fonts/woff2/dm-sans-400.woff2 +0 -0
- package/src/fonts/woff2/dm-sans-400i.woff2 +0 -0
- package/src/fonts/woff2/dm-sans-500.woff2 +0 -0
- package/src/fonts/woff2/dm-sans-700.woff2 +0 -0
- package/src/fonts/woff2/dm-serif-display-400.woff2 +0 -0
- package/src/fonts/woff2/hanken-grotesk-400.woff2 +0 -0
- package/src/fonts/woff2/hanken-grotesk-400i.woff2 +0 -0
- package/src/fonts/woff2/hanken-grotesk-500.woff2 +0 -0
- package/src/fonts/woff2/hanken-grotesk-600.woff2 +0 -0
- package/src/fonts/woff2/hanken-grotesk-700.woff2 +0 -0
- package/src/fonts/woff2/ibm-plex-sans-400.woff2 +0 -0
- package/src/fonts/woff2/ibm-plex-sans-400i.woff2 +0 -0
- package/src/fonts/woff2/ibm-plex-sans-500.woff2 +0 -0
- package/src/fonts/woff2/ibm-plex-sans-600.woff2 +0 -0
- package/src/fonts/woff2/ibm-plex-sans-700.woff2 +0 -0
- package/src/fonts/woff2/inter-400.woff2 +0 -0
- package/src/fonts/woff2/inter-400i.woff2 +0 -0
- package/src/fonts/woff2/inter-500.woff2 +0 -0
- package/src/fonts/woff2/inter-600.woff2 +0 -0
- package/src/fonts/woff2/inter-700.woff2 +0 -0
- package/src/fonts/woff2/jetbrains-mono-400.woff2 +0 -0
- package/src/fonts/woff2/jetbrains-mono-400i.woff2 +0 -0
- package/src/fonts/woff2/jetbrains-mono-700.woff2 +0 -0
- package/src/fonts/woff2/lora-400.woff2 +0 -0
- package/src/fonts/woff2/lora-400i.woff2 +0 -0
- package/src/fonts/woff2/lora-700.woff2 +0 -0
- package/src/fonts/woff2/merriweather-400.woff2 +0 -0
- package/src/fonts/woff2/merriweather-700.woff2 +0 -0
- package/src/fonts/woff2/oswald-400.woff2 +0 -0
- package/src/fonts/woff2/oswald-700.woff2 +0 -0
- package/src/fonts/woff2/playfair-display-400.woff2 +0 -0
- package/src/fonts/woff2/playfair-display-700.woff2 +0 -0
- package/src/fonts/woff2/pt-serif-400.woff2 +0 -0
- package/src/fonts/woff2/pt-serif-700.woff2 +0 -0
- package/src/fonts/woff2/roboto-400.woff2 +0 -0
- package/src/fonts/woff2/roboto-400i.woff2 +0 -0
- package/src/fonts/woff2/roboto-700.woff2 +0 -0
- package/src/fonts/woff2/source-serif-4-400.woff2 +0 -0
- package/src/fonts/woff2/source-serif-4-400i.woff2 +0 -0
- package/src/fonts/woff2/source-serif-4-700.woff2 +0 -0
- package/src/hooks/useAutoSave.ts +0 -116
|
@@ -7,15 +7,21 @@
|
|
|
7
7
|
* Must be rendered inside <EditorProvider> so useEditorContext() works.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
lazy,
|
|
12
|
+
Suspense,
|
|
13
|
+
useState,
|
|
14
|
+
useCallback,
|
|
15
|
+
useEffect,
|
|
16
|
+
useRef,
|
|
17
|
+
useMemo,
|
|
18
|
+
type ComponentType,
|
|
19
|
+
} from 'react';
|
|
11
20
|
import { useEditorContext } from '@bendyline/squisq-editor-react';
|
|
12
21
|
import { getThemeSummaries } from '@bendyline/squisq/schemas';
|
|
13
|
-
import { getTransformStyleSummaries } from '@bendyline/squisq/transform';
|
|
14
22
|
import { parseMarkdown } from '@bendyline/squisq/markdown';
|
|
15
|
-
import { markdownToDoc } from '@bendyline/squisq/doc';
|
|
16
|
-
import { VideoExportModal } from '@bendyline/squisq-video-react';
|
|
17
|
-
import { PLAYER_BUNDLE } from '@bendyline/squisq-react/standalone-source';
|
|
18
23
|
import type { ContentContainer } from '@bendyline/squisq/storage';
|
|
24
|
+
import type { VideoExportModalProps } from '@bendyline/squisq-video-react';
|
|
19
25
|
import type { ExportOptions } from './export-options.js';
|
|
20
26
|
import {
|
|
21
27
|
DEFAULT_OPTIONS,
|
|
@@ -23,18 +29,80 @@ import {
|
|
|
23
29
|
loadLastExportOptions,
|
|
24
30
|
saveExportOptions,
|
|
25
31
|
} from './export-options.js';
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
32
|
+
import type { ExportBlobSaver } from './run-export.js';
|
|
33
|
+
import { loadTransformStyleSummaries, type ExportSummaryOption } from './transform-summaries.js';
|
|
34
|
+
|
|
35
|
+
const ExportDialog = lazy(() =>
|
|
36
|
+
import('./ExportDialog.js').then((module) => ({ default: module.ExportDialog })),
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
let runExportModulePromise: Promise<typeof import('./run-export.js')> | null = null;
|
|
40
|
+
|
|
41
|
+
function loadRunExportModule(): Promise<typeof import('./run-export.js')> {
|
|
42
|
+
runExportModulePromise ??= import('./run-export.js');
|
|
43
|
+
return runExportModulePromise;
|
|
44
|
+
}
|
|
28
45
|
|
|
29
46
|
export interface ExportToolbarControlsProps {
|
|
30
47
|
/** Currently selected file path — used to derive the download filename. */
|
|
31
48
|
selectedFile: string | null;
|
|
32
49
|
/** Media container for resolving images during export. */
|
|
33
50
|
mediaContainer?: ContentContainer | null;
|
|
51
|
+
/** Override the default browser download behavior for host-provided save flows. */
|
|
52
|
+
saveBlob?: ExportBlobSaver;
|
|
53
|
+
/** Optional host adapter for displaying, picking, and saving to a native target path. */
|
|
54
|
+
destinationAdapter?: ExportDestinationAdapter;
|
|
55
|
+
/** Render the trigger as a direct Export button instead of the overflow menu. */
|
|
56
|
+
trigger?: 'menu' | 'button';
|
|
57
|
+
/** Whether to show video export in the overflow menu. */
|
|
58
|
+
showVideoExport?: boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Host-specific operations behind the shared export destination control. */
|
|
62
|
+
export interface ExportDestinationTarget {
|
|
63
|
+
grantId: string | null;
|
|
64
|
+
displayPath: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface ExportDestinationAdapter {
|
|
68
|
+
resolveTarget: (filename: string) => Promise<ExportDestinationTarget>;
|
|
69
|
+
pickTarget: (
|
|
70
|
+
filename: string,
|
|
71
|
+
currentTarget?: ExportDestinationTarget | null,
|
|
72
|
+
) => Promise<ExportDestinationTarget | null>;
|
|
73
|
+
saveBlob: (
|
|
74
|
+
blob: Blob,
|
|
75
|
+
filename: string,
|
|
76
|
+
target?: ExportDestinationTarget | null,
|
|
77
|
+
) => Promise<ExportDestinationTarget | null>;
|
|
78
|
+
hint?: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
type ParsedMarkdown = ReturnType<typeof parseMarkdown>;
|
|
82
|
+
|
|
83
|
+
interface VideoExportModules {
|
|
84
|
+
Modal: ComponentType<VideoExportModalProps>;
|
|
85
|
+
markdownToDoc: (doc: ParsedMarkdown) => VideoExportModalProps['doc'];
|
|
86
|
+
playerScript: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let videoExportModulesPromise: Promise<VideoExportModules> | null = null;
|
|
90
|
+
|
|
91
|
+
function loadVideoExportModules(): Promise<VideoExportModules> {
|
|
92
|
+
videoExportModulesPromise ??= Promise.all([
|
|
93
|
+
import('@bendyline/squisq/doc'),
|
|
94
|
+
import('@bendyline/squisq-video-react'),
|
|
95
|
+
import('@bendyline/squisq-react/standalone-source'),
|
|
96
|
+
]).then(([docModule, videoModule, playerModule]) => ({
|
|
97
|
+
Modal: videoModule.VideoExportModal,
|
|
98
|
+
markdownToDoc: docModule.markdownToDoc,
|
|
99
|
+
playerScript: playerModule.PLAYER_BUNDLE,
|
|
100
|
+
}));
|
|
101
|
+
return videoExportModulesPromise;
|
|
34
102
|
}
|
|
35
103
|
|
|
36
104
|
/** Build the quick-export label from saved options. */
|
|
37
|
-
function quickLabel(opts: ExportOptions): string {
|
|
105
|
+
function quickLabel(opts: ExportOptions, transformSummaries: ExportSummaryOption[]): string {
|
|
38
106
|
const baseExt = FORMAT_EXTENSIONS[opts.format].toUpperCase().replace('.', '');
|
|
39
107
|
// Recursive HTML always emits a ZIP (multi-doc tree), regardless of
|
|
40
108
|
// the saved `htmlBundle` value. Applies to both plain and rendered
|
|
@@ -58,7 +126,7 @@ function quickLabel(opts: ExportOptions): string {
|
|
|
58
126
|
if (theme) parts.push(theme.name);
|
|
59
127
|
}
|
|
60
128
|
if (opts.format === 'pptx' && opts.transformStyle) {
|
|
61
|
-
const transform =
|
|
129
|
+
const transform = transformSummaries.find((t) => t.id === opts.transformStyle);
|
|
62
130
|
if (transform) parts.push(transform.name);
|
|
63
131
|
}
|
|
64
132
|
|
|
@@ -71,12 +139,23 @@ function quickLabel(opts: ExportOptions): string {
|
|
|
71
139
|
export function ExportToolbarControls({
|
|
72
140
|
selectedFile,
|
|
73
141
|
mediaContainer,
|
|
142
|
+
saveBlob,
|
|
143
|
+
destinationAdapter,
|
|
144
|
+
trigger = 'menu',
|
|
145
|
+
showVideoExport = true,
|
|
74
146
|
}: ExportToolbarControlsProps) {
|
|
75
147
|
const { markdownSource, markdownDoc } = useEditorContext();
|
|
76
148
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
77
149
|
const [dialogOpen, setDialogOpen] = useState(false);
|
|
78
150
|
const [videoModalOpen, setVideoModalOpen] = useState(false);
|
|
151
|
+
const [videoLoading, setVideoLoading] = useState(false);
|
|
152
|
+
const [videoLoadError, setVideoLoadError] = useState<string | null>(null);
|
|
153
|
+
const [videoModules, setVideoModules] = useState<VideoExportModules | null>(null);
|
|
154
|
+
const [videoDoc, setVideoDoc] = useState<VideoExportModalProps['doc'] | null>(null);
|
|
155
|
+
const [transformSummaries, setTransformSummaries] = useState<ExportSummaryOption[]>([]);
|
|
79
156
|
const [exporting, setExporting] = useState(false);
|
|
157
|
+
const [destinationTarget, setDestinationTarget] = useState<ExportDestinationTarget | null>(null);
|
|
158
|
+
const destinationRequestRef = useRef(0);
|
|
80
159
|
const menuRef = useRef<HTMLDivElement>(null);
|
|
81
160
|
|
|
82
161
|
const lastOptions = loadLastExportOptions();
|
|
@@ -108,13 +187,6 @@ export function ExportToolbarControls({
|
|
|
108
187
|
return docThemeId ? { ...base, themeId: docThemeId } : base;
|
|
109
188
|
}, [lastOptions, docThemeId]);
|
|
110
189
|
|
|
111
|
-
/** Build a Doc from the current markdown for video export. */
|
|
112
|
-
const doc = useMemo(() => {
|
|
113
|
-
if (!videoModalOpen) return null;
|
|
114
|
-
const mdDoc = parseMarkdown(markdownSource);
|
|
115
|
-
return markdownToDoc(mdDoc);
|
|
116
|
-
}, [videoModalOpen, markdownSource]);
|
|
117
|
-
|
|
118
190
|
// Close menu on outside click
|
|
119
191
|
useEffect(() => {
|
|
120
192
|
if (!menuOpen) return;
|
|
@@ -127,39 +199,150 @@ export function ExportToolbarControls({
|
|
|
127
199
|
return () => document.removeEventListener('pointerdown', onPointerDown);
|
|
128
200
|
}, [menuOpen]);
|
|
129
201
|
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
if (
|
|
204
|
+
!menuOpen ||
|
|
205
|
+
lastOptions?.format !== 'pptx' ||
|
|
206
|
+
!lastOptions.transformStyle ||
|
|
207
|
+
transformSummaries.length > 0
|
|
208
|
+
) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
let cancelled = false;
|
|
213
|
+
loadTransformStyleSummaries()
|
|
214
|
+
.then((nextSummaries) => {
|
|
215
|
+
if (!cancelled) setTransformSummaries(nextSummaries);
|
|
216
|
+
})
|
|
217
|
+
.catch(() => {
|
|
218
|
+
if (!cancelled) setTransformSummaries([]);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
return () => {
|
|
222
|
+
cancelled = true;
|
|
223
|
+
};
|
|
224
|
+
}, [lastOptions?.format, lastOptions?.transformStyle, menuOpen, transformSummaries.length]);
|
|
225
|
+
|
|
130
226
|
const handleToggleMenu = useCallback(() => {
|
|
131
227
|
setMenuOpen((prev) => !prev);
|
|
132
228
|
}, []);
|
|
133
229
|
|
|
230
|
+
const refreshDestination = useCallback(
|
|
231
|
+
async (options: ExportOptions) => {
|
|
232
|
+
if (!destinationAdapter) return;
|
|
233
|
+
|
|
234
|
+
const requestId = destinationRequestRef.current + 1;
|
|
235
|
+
destinationRequestRef.current = requestId;
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
const { buildExportFilename } = await loadRunExportModule();
|
|
239
|
+
const filename = buildExportFilename(selectedFile, options);
|
|
240
|
+
const target = await destinationAdapter.resolveTarget(filename);
|
|
241
|
+
if (destinationRequestRef.current === requestId) setDestinationTarget(target);
|
|
242
|
+
} catch {
|
|
243
|
+
if (destinationRequestRef.current === requestId) setDestinationTarget(null);
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
[destinationAdapter, selectedFile],
|
|
247
|
+
);
|
|
248
|
+
|
|
134
249
|
const handleOpenDialog = useCallback(() => {
|
|
135
250
|
setMenuOpen(false);
|
|
136
251
|
setDialogOpen(true);
|
|
137
|
-
|
|
252
|
+
void refreshDestination(dialogInitial);
|
|
253
|
+
}, [dialogInitial, refreshDestination]);
|
|
138
254
|
|
|
139
255
|
const handleCloseDialog = useCallback(() => {
|
|
140
256
|
setDialogOpen(false);
|
|
141
257
|
}, []);
|
|
142
258
|
|
|
143
|
-
const handleOpenVideoModal = useCallback(() => {
|
|
259
|
+
const handleOpenVideoModal = useCallback(async () => {
|
|
144
260
|
setMenuOpen(false);
|
|
145
261
|
setVideoModalOpen(true);
|
|
146
|
-
|
|
262
|
+
setVideoLoading(true);
|
|
263
|
+
setVideoLoadError(null);
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
const modules = videoModules ?? (await loadVideoExportModules());
|
|
267
|
+
setVideoModules(modules);
|
|
268
|
+
setVideoDoc(modules.markdownToDoc(parseMarkdown(markdownSource)));
|
|
269
|
+
} catch {
|
|
270
|
+
setVideoLoadError('Video export could not be loaded.');
|
|
271
|
+
} finally {
|
|
272
|
+
setVideoLoading(false);
|
|
273
|
+
}
|
|
274
|
+
}, [markdownSource, videoModules]);
|
|
147
275
|
|
|
148
276
|
const handleCloseVideoModal = useCallback(() => {
|
|
149
277
|
setVideoModalOpen(false);
|
|
278
|
+
setVideoDoc(null);
|
|
279
|
+
setVideoLoadError(null);
|
|
150
280
|
}, []);
|
|
151
281
|
|
|
282
|
+
const handleOptionsChange = useCallback(
|
|
283
|
+
(options: ExportOptions) => {
|
|
284
|
+
void refreshDestination(options);
|
|
285
|
+
},
|
|
286
|
+
[refreshDestination],
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
const handlePickDestination = useCallback(
|
|
290
|
+
async (options: ExportOptions) => {
|
|
291
|
+
if (!destinationAdapter) return;
|
|
292
|
+
try {
|
|
293
|
+
const { buildExportFilename } = await loadRunExportModule();
|
|
294
|
+
const filename = buildExportFilename(selectedFile, options);
|
|
295
|
+
const pickedTarget = await destinationAdapter.pickTarget(filename, destinationTarget);
|
|
296
|
+
if (pickedTarget === null) return;
|
|
297
|
+
setDestinationTarget(pickedTarget);
|
|
298
|
+
} catch {
|
|
299
|
+
// Native hosts surface picker failures through their own UI channel.
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
[destinationAdapter, destinationTarget, selectedFile],
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
const saveToDestination = useCallback(
|
|
306
|
+
async (blob: Blob, filename: string, target: ExportDestinationTarget | null) => {
|
|
307
|
+
if (!destinationAdapter) return;
|
|
308
|
+
const savedTarget = await destinationAdapter.saveBlob(blob, filename, target);
|
|
309
|
+
if (savedTarget) setDestinationTarget(savedTarget);
|
|
310
|
+
},
|
|
311
|
+
[destinationAdapter],
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
const handleDestinationSaveBlob = useCallback(
|
|
315
|
+
async (blob: Blob, filename: string) => {
|
|
316
|
+
await saveToDestination(blob, filename, destinationTarget);
|
|
317
|
+
},
|
|
318
|
+
[destinationTarget, saveToDestination],
|
|
319
|
+
);
|
|
320
|
+
|
|
152
321
|
const handleExport = useCallback(
|
|
153
322
|
async (opts: ExportOptions) => {
|
|
154
323
|
setExporting(true);
|
|
155
324
|
try {
|
|
156
|
-
|
|
325
|
+
const { runExport } = await loadRunExportModule();
|
|
326
|
+
await runExport(
|
|
327
|
+
markdownSource,
|
|
328
|
+
selectedFile,
|
|
329
|
+
opts,
|
|
330
|
+
mediaContainer,
|
|
331
|
+
destinationAdapter ? handleDestinationSaveBlob : saveBlob,
|
|
332
|
+
);
|
|
157
333
|
} finally {
|
|
158
334
|
setExporting(false);
|
|
159
335
|
setDialogOpen(false);
|
|
160
336
|
}
|
|
161
337
|
},
|
|
162
|
-
[
|
|
338
|
+
[
|
|
339
|
+
markdownSource,
|
|
340
|
+
selectedFile,
|
|
341
|
+
mediaContainer,
|
|
342
|
+
destinationAdapter,
|
|
343
|
+
handleDestinationSaveBlob,
|
|
344
|
+
saveBlob,
|
|
345
|
+
],
|
|
163
346
|
);
|
|
164
347
|
|
|
165
348
|
const handleQuickExport = useCallback(async () => {
|
|
@@ -168,58 +351,161 @@ export function ExportToolbarControls({
|
|
|
168
351
|
setExporting(true);
|
|
169
352
|
try {
|
|
170
353
|
saveExportOptions(lastOptions);
|
|
171
|
-
|
|
354
|
+
const { runExport } = await loadRunExportModule();
|
|
355
|
+
let quickTarget: ExportDestinationTarget | null = null;
|
|
356
|
+
if (destinationAdapter) {
|
|
357
|
+
const { buildExportFilename } = await loadRunExportModule();
|
|
358
|
+
quickTarget = await destinationAdapter.resolveTarget(
|
|
359
|
+
buildExportFilename(selectedFile, lastOptions),
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
await runExport(
|
|
363
|
+
markdownSource,
|
|
364
|
+
selectedFile,
|
|
365
|
+
lastOptions,
|
|
366
|
+
mediaContainer,
|
|
367
|
+
destinationAdapter
|
|
368
|
+
? async (blob, filename) => saveToDestination(blob, filename, quickTarget)
|
|
369
|
+
: saveBlob,
|
|
370
|
+
);
|
|
172
371
|
} finally {
|
|
173
372
|
setExporting(false);
|
|
174
373
|
}
|
|
175
|
-
}, [
|
|
374
|
+
}, [
|
|
375
|
+
destinationAdapter,
|
|
376
|
+
lastOptions,
|
|
377
|
+
markdownSource,
|
|
378
|
+
mediaContainer,
|
|
379
|
+
saveBlob,
|
|
380
|
+
saveToDestination,
|
|
381
|
+
selectedFile,
|
|
382
|
+
]);
|
|
383
|
+
|
|
384
|
+
const LoadedVideoExportModal = videoModules?.Modal;
|
|
176
385
|
|
|
177
386
|
return (
|
|
178
387
|
<>
|
|
179
|
-
|
|
388
|
+
{trigger === 'button' ? (
|
|
180
389
|
<button
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
390
|
+
type="button"
|
|
391
|
+
className="squisq-toolbar-button db-toolbar-export-trigger"
|
|
392
|
+
onClick={handleOpenDialog}
|
|
393
|
+
disabled={exporting}
|
|
394
|
+
aria-label="Export document"
|
|
395
|
+
data-tooltip={exporting ? 'Exporting...' : 'Export document'}
|
|
185
396
|
>
|
|
186
|
-
|
|
397
|
+
<ExportGlyph />
|
|
187
398
|
</button>
|
|
399
|
+
) : (
|
|
400
|
+
<div className="db-toolbar-menu" ref={menuRef}>
|
|
401
|
+
<button
|
|
402
|
+
className="db-toolbar-menu-trigger"
|
|
403
|
+
onClick={handleToggleMenu}
|
|
404
|
+
aria-label="More actions"
|
|
405
|
+
title="More actions"
|
|
406
|
+
>
|
|
407
|
+
···
|
|
408
|
+
</button>
|
|
188
409
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
410
|
+
{menuOpen && (
|
|
411
|
+
<div className="db-toolbar-menu-dropdown">
|
|
412
|
+
{lastOptions && (
|
|
413
|
+
<button
|
|
414
|
+
className="db-toolbar-menu-item"
|
|
415
|
+
onClick={handleQuickExport}
|
|
416
|
+
disabled={exporting}
|
|
417
|
+
>
|
|
418
|
+
{quickLabel(lastOptions, transformSummaries)}
|
|
419
|
+
</button>
|
|
420
|
+
)}
|
|
421
|
+
<button className="db-toolbar-menu-item" onClick={handleOpenDialog}>
|
|
422
|
+
Export...
|
|
198
423
|
</button>
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
424
|
+
{showVideoExport && (
|
|
425
|
+
<>
|
|
426
|
+
<div className="db-toolbar-menu-divider" />
|
|
427
|
+
<button className="db-toolbar-menu-item" onClick={handleOpenVideoModal}>
|
|
428
|
+
Export Video...
|
|
429
|
+
</button>
|
|
430
|
+
</>
|
|
431
|
+
)}
|
|
432
|
+
</div>
|
|
433
|
+
)}
|
|
434
|
+
</div>
|
|
435
|
+
)}
|
|
210
436
|
|
|
211
437
|
{dialogOpen && (
|
|
212
|
-
<
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
438
|
+
<Suspense fallback={null}>
|
|
439
|
+
<ExportDialog
|
|
440
|
+
initial={dialogInitial}
|
|
441
|
+
exporting={exporting}
|
|
442
|
+
destination={
|
|
443
|
+
destinationAdapter
|
|
444
|
+
? {
|
|
445
|
+
value: destinationTarget?.displayPath ?? '',
|
|
446
|
+
onPick: handlePickDestination,
|
|
447
|
+
hint: destinationAdapter.hint,
|
|
448
|
+
}
|
|
449
|
+
: undefined
|
|
450
|
+
}
|
|
451
|
+
onExport={handleExport}
|
|
452
|
+
onOptionsChange={destinationAdapter ? handleOptionsChange : undefined}
|
|
453
|
+
onClose={handleCloseDialog}
|
|
454
|
+
/>
|
|
455
|
+
</Suspense>
|
|
218
456
|
)}
|
|
219
457
|
|
|
220
|
-
{videoModalOpen &&
|
|
221
|
-
<
|
|
458
|
+
{videoModalOpen && (videoLoading || videoLoadError) && (
|
|
459
|
+
<div className="db-dialog-overlay">
|
|
460
|
+
<div className="db-dialog">
|
|
461
|
+
<div className="db-dialog-header">
|
|
462
|
+
<h2 className="db-dialog-title">Export Video</h2>
|
|
463
|
+
<button
|
|
464
|
+
className="db-dialog-close"
|
|
465
|
+
onClick={handleCloseVideoModal}
|
|
466
|
+
aria-label="Close"
|
|
467
|
+
>
|
|
468
|
+
×
|
|
469
|
+
</button>
|
|
470
|
+
</div>
|
|
471
|
+
<div className="db-dialog-body">
|
|
472
|
+
<p className="db-export-hint">{videoLoadError ?? 'Loading...'}</p>
|
|
473
|
+
</div>
|
|
474
|
+
</div>
|
|
475
|
+
</div>
|
|
222
476
|
)}
|
|
477
|
+
|
|
478
|
+
{videoModalOpen &&
|
|
479
|
+
videoModules &&
|
|
480
|
+
LoadedVideoExportModal &&
|
|
481
|
+
videoDoc &&
|
|
482
|
+
!videoLoading &&
|
|
483
|
+
!videoLoadError && (
|
|
484
|
+
<LoadedVideoExportModal
|
|
485
|
+
doc={videoDoc}
|
|
486
|
+
playerScript={videoModules.playerScript}
|
|
487
|
+
onClose={handleCloseVideoModal}
|
|
488
|
+
/>
|
|
489
|
+
)}
|
|
223
490
|
</>
|
|
224
491
|
);
|
|
225
492
|
}
|
|
493
|
+
|
|
494
|
+
function ExportGlyph() {
|
|
495
|
+
return (
|
|
496
|
+
<svg
|
|
497
|
+
viewBox="0 0 16 16"
|
|
498
|
+
fill="none"
|
|
499
|
+
stroke="currentColor"
|
|
500
|
+
strokeWidth="1.5"
|
|
501
|
+
strokeLinecap="round"
|
|
502
|
+
strokeLinejoin="round"
|
|
503
|
+
aria-hidden="true"
|
|
504
|
+
>
|
|
505
|
+
<path d="M4.5 1.75h4.25L12 5v7.25a1.5 1.5 0 0 1-1.5 1.5h-6A1.5 1.5 0 0 1 3 12.25v-9a1.5 1.5 0 0 1 1.5-1.5z" />
|
|
506
|
+
<path d="M8.75 1.75V5h3.25" />
|
|
507
|
+
<path d="M6 8.75h4.5" />
|
|
508
|
+
<path d="M8.75 7 10.5 8.75 8.75 10.5" />
|
|
509
|
+
</svg>
|
|
510
|
+
);
|
|
511
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Keep a user-edited target name while switching the selected export format. */
|
|
2
|
+
export function updateExportTargetExtension(targetPath: string, suggestedFilename: string): string {
|
|
3
|
+
const nextExtension = extensionOf(suggestedFilename);
|
|
4
|
+
if (!nextExtension) return targetPath;
|
|
5
|
+
if (!targetPath.trim()) return suggestedFilename;
|
|
6
|
+
|
|
7
|
+
const suffixIndex = firstSuffixIndex(targetPath);
|
|
8
|
+
const pathPart = suffixIndex === -1 ? targetPath : targetPath.slice(0, suffixIndex);
|
|
9
|
+
const suffix = suffixIndex === -1 ? '' : targetPath.slice(suffixIndex);
|
|
10
|
+
const separatorIndex = Math.max(pathPart.lastIndexOf('/'), pathPart.lastIndexOf('\\'));
|
|
11
|
+
const dotIndex = pathPart.lastIndexOf('.');
|
|
12
|
+
const stem = dotIndex > separatorIndex ? pathPart.slice(0, dotIndex) : pathPart;
|
|
13
|
+
return `${stem}${nextExtension}${suffix}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function extensionOf(value: string): string {
|
|
17
|
+
const suffixIndex = firstSuffixIndex(value);
|
|
18
|
+
const pathPart = suffixIndex === -1 ? value : value.slice(0, suffixIndex);
|
|
19
|
+
const separatorIndex = Math.max(pathPart.lastIndexOf('/'), pathPart.lastIndexOf('\\'));
|
|
20
|
+
const dotIndex = pathPart.lastIndexOf('.');
|
|
21
|
+
return dotIndex > separatorIndex ? pathPart.slice(dotIndex) : '';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function firstSuffixIndex(value: string): number {
|
|
25
|
+
const query = value.indexOf('?');
|
|
26
|
+
const fragment = value.indexOf('#');
|
|
27
|
+
if (query === -1) return fragment;
|
|
28
|
+
if (fragment === -1) return query;
|
|
29
|
+
return Math.min(query, fragment);
|
|
30
|
+
}
|
package/src/Export/index.ts
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
|
-
export { ExportToolbarControls } from './
|
|
2
|
-
export type {
|
|
1
|
+
export { ExportToolbarControls } from './DeferredExportToolbarControls.js';
|
|
2
|
+
export type {
|
|
3
|
+
ExportDestinationAdapter,
|
|
4
|
+
ExportDestinationTarget,
|
|
5
|
+
ExportToolbarControlsProps,
|
|
6
|
+
} from './DeferredExportToolbarControls.js';
|
|
3
7
|
export { ExportDialog } from './ExportDialog.js';
|
|
4
|
-
export type { ExportDialogProps } from './ExportDialog.js';
|
|
5
|
-
export
|
|
8
|
+
export type { ExportDestinationControl, ExportDialogProps } from './ExportDialog.js';
|
|
9
|
+
export {
|
|
10
|
+
DEFAULT_OPTIONS,
|
|
11
|
+
FORMAT_EXTENSIONS,
|
|
12
|
+
FORMAT_LABELS,
|
|
13
|
+
loadLastExportOptions,
|
|
14
|
+
saveExportOptions,
|
|
15
|
+
} from './export-options.js';
|
|
16
|
+
export type { ExportFormat, ExportOptions, HtmlBundle, HtmlStyle } from './export-options.js';
|
|
17
|
+
export { buildExportFilename, runExport } from './run-export.js';
|
|
18
|
+
export { updateExportTargetExtension } from './export-destination.js';
|
|
19
|
+
export type { ExportBlobSaver } from './run-export.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Narrow public export pipeline for hosts that provide their own editor shell.
|
|
3
|
+
* Keep toolbar/video controls out of this entry so consumers such as the VS
|
|
4
|
+
* Code webview do not eagerly transform the video worker graph.
|
|
5
|
+
*/
|
|
6
|
+
export { ExportDialog } from './ExportDialog.js';
|
|
7
|
+
export type { ExportDestinationControl, ExportDialogProps } from './ExportDialog.js';
|
|
8
|
+
export {
|
|
9
|
+
DEFAULT_OPTIONS,
|
|
10
|
+
FORMAT_EXTENSIONS,
|
|
11
|
+
FORMAT_LABELS,
|
|
12
|
+
loadLastExportOptions,
|
|
13
|
+
saveExportOptions,
|
|
14
|
+
} from './export-options.js';
|
|
15
|
+
export type { ExportFormat, ExportOptions, HtmlBundle, HtmlStyle } from './export-options.js';
|
|
16
|
+
export { buildExportFilename, runExport } from './run-export.js';
|
|
17
|
+
export type { ExportBlobSaver } from './run-export.js';
|