@rightkit/document-workspace 0.0.0-stage → 0.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/CHANGELOG.md +11 -0
- package/LICENSE-APACHE +201 -0
- package/LICENSE-MIT +21 -0
- package/README.md +74 -2
- package/dist/app/App.d.ts +1 -0
- package/dist/app/App.js +6 -0
- package/dist/app/AppDialogs.d.ts +52 -0
- package/dist/app/AppDialogs.js +23 -0
- package/dist/app/AppDialogsHost.d.ts +31 -0
- package/dist/app/AppDialogsHost.js +30 -0
- package/dist/app/AppLifecycle.d.ts +19 -0
- package/dist/app/AppLifecycle.js +87 -0
- package/dist/app/AppProvider.d.ts +317 -0
- package/dist/app/AppProvider.js +217 -0
- package/dist/app/AppRoot.d.ts +8 -0
- package/dist/app/AppRoot.js +159 -0
- package/dist/app/AppShell.d.ts +2 -0
- package/dist/app/AppShell.js +81 -0
- package/dist/app/CommandPalette.d.ts +13 -0
- package/dist/app/CommandPalette.js +47 -0
- package/dist/app/DocActionBar.d.ts +36 -0
- package/dist/app/DocActionBar.js +300 -0
- package/dist/app/DocumentContextMenu.d.ts +29 -0
- package/dist/app/DocumentContextMenu.js +122 -0
- package/dist/app/DocumentPane.d.ts +52 -0
- package/dist/app/DocumentPane.js +30 -0
- package/dist/app/DocumentRouterTable.d.ts +58 -0
- package/dist/app/DocumentRouterTable.js +143 -0
- package/dist/app/ErrorBoundary.d.ts +12 -0
- package/dist/app/ErrorBoundary.js +16 -0
- package/dist/app/FindBar.d.ts +12 -0
- package/dist/app/FindBar.js +199 -0
- package/dist/app/LiveTitle.d.ts +14 -0
- package/dist/app/LiveTitle.js +14 -0
- package/dist/app/OpeningProgress.d.ts +13 -0
- package/dist/app/OpeningProgress.js +21 -0
- package/dist/app/PrintPreviewWindow.d.ts +2 -0
- package/dist/app/PrintPreviewWindow.js +57 -0
- package/dist/app/ShortcutHelp.d.ts +3 -0
- package/dist/app/ShortcutHelp.js +99 -0
- package/dist/app/Sidebar.d.ts +36 -0
- package/dist/app/Sidebar.js +121 -0
- package/dist/app/ToastViewport.d.ts +1 -0
- package/dist/app/ToastViewport.js +31 -0
- package/dist/app/Toolbar.d.ts +26 -0
- package/dist/app/Toolbar.js +63 -0
- package/dist/app/activeFormatSavers.d.ts +7 -0
- package/dist/app/activeFormatSavers.js +4 -0
- package/dist/app/clipboardPaths.d.ts +1 -0
- package/dist/app/clipboardPaths.js +31 -0
- package/dist/app/documentDrafts.d.ts +17 -0
- package/dist/app/documentDrafts.js +104 -0
- package/dist/app/draftResolution.d.ts +5 -0
- package/dist/app/draftResolution.js +25 -0
- package/dist/app/markdownPaletteActions.d.ts +8 -0
- package/dist/app/markdownPaletteActions.js +107 -0
- package/dist/app/resourceCensusDev.d.ts +41 -0
- package/dist/app/resourceCensusDev.js +518 -0
- package/dist/app/setupRecovery.d.ts +34 -0
- package/dist/app/setupRecovery.js +70 -0
- package/dist/app/shell/DocStatsPill.d.ts +18 -0
- package/dist/app/shell/DocStatsPill.js +32 -0
- package/dist/app/shell/DocumentTools.d.ts +9 -0
- package/dist/app/shell/DocumentTools.js +73 -0
- package/dist/app/shell/InfoInspector.d.ts +9 -0
- package/dist/app/shell/InfoInspector.js +67 -0
- package/dist/app/shell/StartPage.d.ts +9 -0
- package/dist/app/shell/StartPage.js +49 -0
- package/dist/app/shell/readEdit.d.ts +6 -0
- package/dist/app/shell/readEdit.js +6 -0
- package/dist/app/sidebar/SidebarDocumentMenu.d.ts +20 -0
- package/dist/app/sidebar/SidebarDocumentMenu.js +56 -0
- package/dist/app/sidebar/SidebarExpandedPanel.d.ts +9 -0
- package/dist/app/sidebar/SidebarExpandedPanel.js +78 -0
- package/dist/app/sidebar/SidebarIcons.d.ts +3 -0
- package/dist/app/sidebar/SidebarIcons.js +18 -0
- package/dist/app/sidebar/SidebarMenus.d.ts +19 -0
- package/dist/app/sidebar/SidebarMenus.js +64 -0
- package/dist/app/sidebar/SidebarPathUtils.d.ts +10 -0
- package/dist/app/sidebar/SidebarPathUtils.js +55 -0
- package/dist/app/sidebar/SidebarPrimitives.d.ts +12 -0
- package/dist/app/sidebar/SidebarPrimitives.js +45 -0
- package/dist/app/sidebar/SidebarRail.d.ts +5 -0
- package/dist/app/sidebar/SidebarRail.js +37 -0
- package/dist/app/sidebar/explorer/ExplorerRowMenu.d.ts +21 -0
- package/dist/app/sidebar/explorer/ExplorerRowMenu.js +37 -0
- package/dist/app/sidebar/explorer/ExplorerSections.d.ts +16 -0
- package/dist/app/sidebar/explorer/ExplorerSections.js +259 -0
- package/dist/app/sidebar/explorer/ExplorerTree.d.ts +46 -0
- package/dist/app/sidebar/explorer/ExplorerTree.js +387 -0
- package/dist/app/sidebar/explorer/explorerState.d.ts +37 -0
- package/dist/app/sidebar/explorer/explorerState.js +135 -0
- package/dist/app/tabMountPolicy.d.ts +45 -0
- package/dist/app/tabMountPolicy.js +104 -0
- package/dist/app/tabWarmOrder.d.ts +7 -0
- package/dist/app/tabWarmOrder.js +48 -0
- package/dist/app/tabs/TabFuseCurves.d.ts +3 -0
- package/dist/app/tabs/TabFuseCurves.js +15 -0
- package/dist/app/tabs/TabOverview.d.ts +24 -0
- package/dist/app/tabs/TabOverview.js +121 -0
- package/dist/app/tabs/TabStrip.d.ts +42 -0
- package/dist/app/tabs/TabStrip.js +380 -0
- package/dist/app/tabs/tabIds.d.ts +5 -0
- package/dist/app/tabs/tabIds.js +7 -0
- package/dist/app/tabs/useTabDirty.d.ts +3 -0
- package/dist/app/tabs/useTabDirty.js +11 -0
- package/dist/app/useAppChromeState.d.ts +21 -0
- package/dist/app/useAppChromeState.js +48 -0
- package/dist/app/useAppCommands.d.ts +66 -0
- package/dist/app/useAppCommands.js +71 -0
- package/dist/app/useAppDocumentCore.d.ts +210 -0
- package/dist/app/useAppDocumentCore.js +40 -0
- package/dist/app/useAppEffects.d.ts +18 -0
- package/dist/app/useAppEffects.js +52 -0
- package/dist/app/useAppPaneSearch.d.ts +37 -0
- package/dist/app/useAppPaneSearch.js +74 -0
- package/dist/app/useAppShellSetup.d.ts +40 -0
- package/dist/app/useAppShellSetup.js +52 -0
- package/dist/app/useAppSlots.d.ts +28 -0
- package/dist/app/useAppSlots.js +40 -0
- package/dist/app/useAppTabChrome.d.ts +51 -0
- package/dist/app/useAppTabChrome.js +66 -0
- package/dist/app/useAutoSave.d.ts +34 -0
- package/dist/app/useAutoSave.js +116 -0
- package/dist/app/useCloseAll.d.ts +52 -0
- package/dist/app/useCloseAll.js +295 -0
- package/dist/app/useClosedTabEviction.d.ts +10 -0
- package/dist/app/useClosedTabEviction.js +38 -0
- package/dist/app/useCommandPalette.d.ts +44 -0
- package/dist/app/useCommandPalette.js +254 -0
- package/dist/app/useCrossDocSearch.d.ts +7 -0
- package/dist/app/useCrossDocSearch.js +94 -0
- package/dist/app/useDistractionFree.d.ts +21 -0
- package/dist/app/useDistractionFree.js +73 -0
- package/dist/app/useDocumentCreation.d.ts +18 -0
- package/dist/app/useDocumentCreation.js +63 -0
- package/dist/app/useDocumentDirty.d.ts +31 -0
- package/dist/app/useDocumentDirty.js +46 -0
- package/dist/app/useDocumentLoader.d.ts +55 -0
- package/dist/app/useDocumentLoader.js +267 -0
- package/dist/app/useDocumentOutputActions.d.ts +6 -0
- package/dist/app/useDocumentOutputActions.js +45 -0
- package/dist/app/useDocumentRuntimeEffects.d.ts +36 -0
- package/dist/app/useDocumentRuntimeEffects.js +458 -0
- package/dist/app/useDocumentSaver.d.ts +58 -0
- package/dist/app/useDocumentSaver.js +511 -0
- package/dist/app/useDocumentTabs.d.ts +41 -0
- package/dist/app/useDocumentTabs.js +207 -0
- package/dist/app/useDocumentWatcher.d.ts +83 -0
- package/dist/app/useDocumentWatcher.js +393 -0
- package/dist/app/useDocumentZoom.d.ts +24 -0
- package/dist/app/useDocumentZoom.js +104 -0
- package/dist/app/useDocuments.d.ts +169 -0
- package/dist/app/useDocuments.js +455 -0
- package/dist/app/useDraftConfirmGate.d.ts +27 -0
- package/dist/app/useDraftConfirmGate.js +47 -0
- package/dist/app/useFileDragOverlay.d.ts +12 -0
- package/dist/app/useFileDragOverlay.js +49 -0
- package/dist/app/useFormatApis.d.ts +13 -0
- package/dist/app/useFormatApis.js +62 -0
- package/dist/app/useFormatDirtyState.d.ts +29 -0
- package/dist/app/useFormatDirtyState.js +81 -0
- package/dist/app/useGlobalShortcuts.d.ts +47 -0
- package/dist/app/useGlobalShortcuts.js +359 -0
- package/dist/app/useHtmlSession.d.ts +68 -0
- package/dist/app/useHtmlSession.js +463 -0
- package/dist/app/useHtmlSessionProps.d.ts +33 -0
- package/dist/app/useHtmlSessionProps.js +57 -0
- package/dist/app/useLibrary.d.ts +21 -0
- package/dist/app/useLibrary.js +81 -0
- package/dist/app/useOpenFromClipboard.d.ts +7 -0
- package/dist/app/useOpenFromClipboard.js +44 -0
- package/dist/app/usePaneLiveness.d.ts +29 -0
- package/dist/app/usePaneLiveness.js +199 -0
- package/dist/app/usePendingSavePaths.d.ts +19 -0
- package/dist/app/usePendingSavePaths.js +67 -0
- package/dist/app/useReadyShow.d.ts +12 -0
- package/dist/app/useReadyShow.js +142 -0
- package/dist/app/useSearchController.d.ts +22 -0
- package/dist/app/useSearchController.js +114 -0
- package/dist/app/useSetupRecovery.d.ts +41 -0
- package/dist/app/useSetupRecovery.js +153 -0
- package/dist/app/useTabChrome.d.ts +40 -0
- package/dist/app/useTabChrome.js +115 -0
- package/dist/app/useViewState.d.ts +27 -0
- package/dist/app/useViewState.js +160 -0
- package/dist/appName.d.ts +2 -0
- package/dist/appName.js +8 -0
- package/dist/documents/DocumentRouter.d.ts +102 -0
- package/dist/documents/DocumentRouter.js +153 -0
- package/dist/documents/FileTypeIcon.d.ts +6 -0
- package/dist/documents/FileTypeIcon.js +93 -0
- package/dist/documents/ImageDocument.d.ts +14 -0
- package/dist/documents/ImageDocument.js +61 -0
- package/dist/documents/capabilities.d.ts +17 -0
- package/dist/documents/capabilities.js +18 -0
- package/dist/documents/html/HtmlDocument.d.ts +15 -0
- package/dist/documents/html/HtmlDocument.js +584 -0
- package/dist/documents/html/HtmlDocumentLayout.d.ts +87 -0
- package/dist/documents/html/HtmlDocumentLayout.js +25 -0
- package/dist/documents/html/HtmlDocumentProps.d.ts +60 -0
- package/dist/documents/html/HtmlDocumentProps.js +1 -0
- package/dist/documents/html/HtmlDocumentSource.d.ts +34 -0
- package/dist/documents/html/HtmlDocumentSource.js +28 -0
- package/dist/documents/markdown/MarkdownSplitPane.d.ts +115 -0
- package/dist/documents/markdown/MarkdownSplitPane.js +352 -0
- package/dist/documents/mdx/MdxSplitPane.d.ts +32 -0
- package/dist/documents/mdx/MdxSplitPane.js +60 -0
- package/dist/documents/txt/LinkDialog.d.ts +8 -0
- package/dist/documents/txt/LinkDialog.js +34 -0
- package/dist/documents/txt/MarkdownSourceToolbar.d.ts +8 -0
- package/dist/documents/txt/MarkdownSourceToolbar.js +25 -0
- package/dist/documents/txt/SourceEditorToolbar.d.ts +12 -0
- package/dist/documents/txt/SourceEditorToolbar.js +4 -0
- package/dist/documents/txt/TxtEditor.d.ts +39 -0
- package/dist/documents/txt/TxtEditor.js +186 -0
- package/dist/documents/txt/sourceEditorTypes.d.ts +49 -0
- package/dist/documents/txt/sourceEditorTypes.js +1 -0
- package/dist/documents/txt/sourceExtensions.d.ts +38 -0
- package/dist/documents/txt/sourceExtensions.js +444 -0
- package/dist/documents/txt/sourceFormatting.d.ts +18 -0
- package/dist/documents/txt/sourceFormatting.js +183 -0
- package/dist/documents/txt/sourceTheme.d.ts +5 -0
- package/dist/documents/txt/sourceTheme.js +220 -0
- package/dist/documents/txt/useCodeMirrorSourceEditor.d.ts +69 -0
- package/dist/documents/txt/useCodeMirrorSourceEditor.js +546 -0
- package/dist/documents/txt/useSourceSearch.d.ts +39 -0
- package/dist/documents/txt/useSourceSearch.js +122 -0
- package/dist/documents/txt/useTextEditorCommands.d.ts +26 -0
- package/dist/documents/txt/useTextEditorCommands.js +151 -0
- package/dist/documents/web/LivePreviewPane.d.ts +11 -0
- package/dist/documents/web/LivePreviewPane.js +58 -0
- package/dist/env.d.ts +66 -0
- package/dist/index.d.ts +121 -0
- package/dist/index.js +123 -0
- package/dist/settings/AppearanceMenu.d.ts +9 -0
- package/dist/settings/AppearanceMenu.js +54 -0
- package/dist/settings/SettingsPanel.d.ts +7 -0
- package/dist/settings/SettingsPanel.js +104 -0
- package/dist/settings/publishedSections.d.ts +22 -0
- package/dist/settings/publishedSections.js +79 -0
- package/dist/settings/sections/AboutSection.d.ts +1 -0
- package/dist/settings/sections/AboutSection.js +13 -0
- package/dist/settings/sections/DiagnosticsSection.d.ts +1 -0
- package/dist/settings/sections/DiagnosticsSection.js +42 -0
- package/dist/settings/sections/PrivacySection.d.ts +3 -0
- package/dist/settings/sections/PrivacySection.js +51 -0
- package/dist/settings/sections/UpdateLicenseBlock.d.ts +10 -0
- package/dist/settings/sections/UpdateLicenseBlock.js +158 -0
- package/dist/state/explorer.d.ts +32 -0
- package/dist/state/explorer.js +111 -0
- package/dist/state/legal.d.ts +51 -0
- package/dist/state/legal.js +130 -0
- package/dist/state/library.d.ts +33 -0
- package/dist/state/library.js +110 -0
- package/dist/state/updateLicense.d.ts +31 -0
- package/dist/state/updateLicense.js +340 -0
- package/dist/styles/explorer.css +219 -0
- package/dist/styles/index.css +1477 -0
- package/dist/styles/tabs.css +467 -0
- package/dist/styles.css +6 -0
- package/package.json +88 -3
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
import { useEffect, useMemo, useRef } from "react";
|
|
2
|
+
import { closeBrackets } from "@codemirror/autocomplete";
|
|
3
|
+
import { history, redo, undo } from "@codemirror/commands";
|
|
4
|
+
import { bracketMatching, indentOnInput, syntaxHighlighting } from "@codemirror/language";
|
|
5
|
+
import { highlightSelectionMatches } from "@codemirror/search";
|
|
6
|
+
import { Compartment, EditorState } from "@codemirror/state";
|
|
7
|
+
import { dropCursor, EditorView, highlightActiveLine, rectangularSelection, } from "@codemirror/view";
|
|
8
|
+
import { bytesToBase64 } from "@rightkit/document-core/documents/base64";
|
|
9
|
+
import { completionExtension, contentAttributesExtension, diagnosticsExtension, gutterExtension, imagePasteExtension, invisibleCharactersExtension, languageExtension, loadDiagnosticsExtension, loadLanguageExtension, loadMarkdownCoreCompletionExtension, readOnlyExtension, searchHighlightClickExtension, searchHighlightField, sourceKeymap, sourceWrapExtension, } from "./sourceExtensions.js";
|
|
10
|
+
import { sourceHighlightStyle } from "./sourceTheme.js";
|
|
11
|
+
import { acquireResource } from "@rightkit/document-core/app/resourceCensus";
|
|
12
|
+
export function useCodeMirrorSourceEditor(args) {
|
|
13
|
+
// The EditorView construction effect is mount-only. Runtime settings live in compartments below;
|
|
14
|
+
// putting every changing argument in its dependency list destroys/recreates the view on a simple
|
|
15
|
+
// read-only or spellcheck update. Keep the initial construction snapshot separate from live refs.
|
|
16
|
+
const constructionArgsRef = useRef(args);
|
|
17
|
+
constructionArgsRef.current = args;
|
|
18
|
+
const languageCompartment = useMemo(() => new Compartment(), []);
|
|
19
|
+
const readOnlyCompartment = useMemo(() => new Compartment(), []);
|
|
20
|
+
const contentAttributesCompartment = useMemo(() => new Compartment(), []);
|
|
21
|
+
const wordWrapCompartment = useMemo(() => new Compartment(), []);
|
|
22
|
+
const gutterCompartment = useMemo(() => new Compartment(), []);
|
|
23
|
+
const themeCompartment = useMemo(() => new Compartment(), []);
|
|
24
|
+
const keymapCompartment = useMemo(() => new Compartment(), []);
|
|
25
|
+
const completionCompartment = useMemo(() => new Compartment(), []);
|
|
26
|
+
const diagnosticsCompartment = useMemo(() => new Compartment(), []);
|
|
27
|
+
const invisiblesCompartment = useMemo(() => new Compartment(), []);
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const previousRegister = args.registerSearchProviderRef.current;
|
|
30
|
+
if (previousRegister === args.registerSearchProvider)
|
|
31
|
+
return;
|
|
32
|
+
args.registerSearchProviderRef.current = args.registerSearchProvider;
|
|
33
|
+
const provider = args.registeredProviderRef.current;
|
|
34
|
+
if (!provider)
|
|
35
|
+
return;
|
|
36
|
+
previousRegister(null);
|
|
37
|
+
args.registerSearchProvider(provider);
|
|
38
|
+
}, [args.registerSearchProvider, args.registerSearchProviderRef, args.registeredProviderRef]);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
const args = constructionArgsRef.current;
|
|
41
|
+
const host = args.hostRef.current;
|
|
42
|
+
if (!host)
|
|
43
|
+
return;
|
|
44
|
+
let applyingFromCore = false;
|
|
45
|
+
const handleSmartPaste = async (event, view) => {
|
|
46
|
+
const core = args.markdownCore;
|
|
47
|
+
if (!core || args.language !== "markdown")
|
|
48
|
+
return false;
|
|
49
|
+
const html = event.clipboardData?.getData("text/html") ?? "";
|
|
50
|
+
const text = event.clipboardData?.getData("text/plain") ?? "";
|
|
51
|
+
if (!html)
|
|
52
|
+
return false;
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
const [{ smartPaste }, { DEFAULT_MARKDOWN_ASSET_SETTINGS }, { NativeMarkdownAssetClient, validateMarkdownAsset },] = await Promise.all([
|
|
55
|
+
import("@rightkit/markdown-editor/documents/markdown/assets/smartPaste"),
|
|
56
|
+
import("@rightkit/markdown-editor/documents/markdown/assets/markdownAssetSettings"),
|
|
57
|
+
import("@rightkit/markdown-editor/documents/markdown/assets/markdownAsset"),
|
|
58
|
+
]);
|
|
59
|
+
const selection = view.state.selection.main;
|
|
60
|
+
const snapshot = core.snapshot();
|
|
61
|
+
const client = new NativeMarkdownAssetClient();
|
|
62
|
+
const saved = [];
|
|
63
|
+
try {
|
|
64
|
+
const result = await smartPaste({
|
|
65
|
+
html,
|
|
66
|
+
text,
|
|
67
|
+
documentBasename: core.state.documentId.split(/[\\/]/).pop() ?? "document",
|
|
68
|
+
settings: DEFAULT_MARKDOWN_ASSET_SETTINGS,
|
|
69
|
+
insertAt: selection.from,
|
|
70
|
+
resolveAssetPath: async (payload) => {
|
|
71
|
+
const error = validateMarkdownAsset(payload);
|
|
72
|
+
if (error)
|
|
73
|
+
throw error;
|
|
74
|
+
const source = assetPayloadBase64(payload.source);
|
|
75
|
+
const savedAsset = await client.save({
|
|
76
|
+
payloadBase64: source,
|
|
77
|
+
hintName: payload.hintName,
|
|
78
|
+
mimeKind: payload.mimeKind,
|
|
79
|
+
documentPath: core.state.documentId,
|
|
80
|
+
});
|
|
81
|
+
if (savedAsset.rollbackToken)
|
|
82
|
+
saved.push(savedAsset.rollbackToken);
|
|
83
|
+
return savedAsset.relativePath;
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
const edits = result.edits.map((edit) => ({ ...edit, to: selection.to }));
|
|
87
|
+
core.applyCommand({
|
|
88
|
+
edits,
|
|
89
|
+
expectedRevision: snapshot.revision,
|
|
90
|
+
origin: "source",
|
|
91
|
+
label: "Paste",
|
|
92
|
+
isolateHistory: true,
|
|
93
|
+
});
|
|
94
|
+
await Promise.all(saved.map((token) => client.commit(token)));
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
await Promise.all(saved.map((token) => client.rollback(token)));
|
|
98
|
+
}
|
|
99
|
+
return true;
|
|
100
|
+
};
|
|
101
|
+
const extensions = [
|
|
102
|
+
...(args.externalHistory ? [] : [history()]),
|
|
103
|
+
dropCursor(),
|
|
104
|
+
rectangularSelection(),
|
|
105
|
+
highlightActiveLine(),
|
|
106
|
+
indentOnInput(),
|
|
107
|
+
bracketMatching(),
|
|
108
|
+
closeBrackets(),
|
|
109
|
+
completionCompartment.of(completionExtension(args.language)),
|
|
110
|
+
syntaxHighlighting(sourceHighlightStyle, { fallback: true }),
|
|
111
|
+
highlightSelectionMatches(),
|
|
112
|
+
searchHighlightField,
|
|
113
|
+
searchHighlightClickExtension,
|
|
114
|
+
gutterCompartment.of(gutterExtension(args.language)),
|
|
115
|
+
diagnosticsCompartment.of(diagnosticsExtension(args.language, null)),
|
|
116
|
+
themeCompartment.of(args.themeExtension),
|
|
117
|
+
readOnlyCompartment.of(readOnlyExtension(args.readOnly)),
|
|
118
|
+
contentAttributesCompartment.of(contentAttributesExtension(args.settingsSpellcheck, args.readOnly)),
|
|
119
|
+
wordWrapCompartment.of(sourceWrapExtension(args.settingsWordWrap, args.language, args.sourceWrap)),
|
|
120
|
+
invisiblesCompartment.of(invisibleCharactersExtension(args.showInvisibles)),
|
|
121
|
+
imagePasteExtension(args.language, args.markdownCore ? handleSmartPaste : undefined),
|
|
122
|
+
EditorView.updateListener.of((update) => {
|
|
123
|
+
const core = args.markdownCore;
|
|
124
|
+
if (update.selectionSet && core && args.language === "markdown") {
|
|
125
|
+
const selection = update.state.selection.main;
|
|
126
|
+
core.postSelectionHint({
|
|
127
|
+
surface: "source",
|
|
128
|
+
nodeId: null,
|
|
129
|
+
anchor: selection.anchor,
|
|
130
|
+
head: selection.head,
|
|
131
|
+
assoc: selection.head >= selection.anchor ? -1 : 1,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
if (update.selectionSet && args.sourceTypewriterMode) {
|
|
135
|
+
const head = update.state.selection.main.head;
|
|
136
|
+
update.view.dispatch({ effects: EditorView.scrollIntoView(head, { y: "center" }) });
|
|
137
|
+
}
|
|
138
|
+
if (!update.docChanged)
|
|
139
|
+
return;
|
|
140
|
+
// Feed CodeMirror's change set directly to the core to avoid
|
|
141
|
+
// the whole-string LCS diff on every keystroke. This keeps the
|
|
142
|
+
// hot path O(edits) instead of O(n*m) for large documents.
|
|
143
|
+
const next = update.state.doc.toString();
|
|
144
|
+
args.textRef.current = next;
|
|
145
|
+
if (args.suppressChangeRef.current || applyingFromCore)
|
|
146
|
+
return;
|
|
147
|
+
if (!core) {
|
|
148
|
+
args.onChangeRef.current(next);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const snapshot = core.snapshot();
|
|
152
|
+
if (snapshot.logicalSource === next)
|
|
153
|
+
return;
|
|
154
|
+
// Prefer the incremental change set; fall back to whole-doc diff
|
|
155
|
+
// only for external reconciliation where the guard applies.
|
|
156
|
+
const edits = [];
|
|
157
|
+
let hasChanges = false;
|
|
158
|
+
try {
|
|
159
|
+
update.changes.iterChanges((fromA, toA, _fromB, _toB, inserted) => {
|
|
160
|
+
hasChanges = true;
|
|
161
|
+
edits.push({
|
|
162
|
+
from: fromA,
|
|
163
|
+
to: toA,
|
|
164
|
+
insert: inserted.toString(),
|
|
165
|
+
inheritMode: "inherit",
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
// If iterating fails, fall back to bounded diff (external path).
|
|
171
|
+
hasChanges = false;
|
|
172
|
+
}
|
|
173
|
+
if (hasChanges) {
|
|
174
|
+
try {
|
|
175
|
+
core.applyCommand({
|
|
176
|
+
edits,
|
|
177
|
+
expectedRevision: snapshot.revision,
|
|
178
|
+
origin: "source",
|
|
179
|
+
label: "Typing",
|
|
180
|
+
coalesceKey: "source:typing",
|
|
181
|
+
});
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// fall through to recovery — stale revision or validation
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
// CodeMirror normally yields at least one range for docChanged. If
|
|
190
|
+
// it does not, keep source typing incremental without invoking LCS.
|
|
191
|
+
try {
|
|
192
|
+
core.applyCommand({
|
|
193
|
+
edits: [
|
|
194
|
+
{
|
|
195
|
+
from: 0,
|
|
196
|
+
to: snapshot.logicalSource.length,
|
|
197
|
+
insert: next,
|
|
198
|
+
inheritMode: "preserve",
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
expectedRevision: snapshot.revision,
|
|
202
|
+
origin: "source",
|
|
203
|
+
label: "Typing",
|
|
204
|
+
coalesceKey: "source:typing",
|
|
205
|
+
});
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
// fall through to recovery — stale revision or validation
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// Recovery: resync editor from core.
|
|
213
|
+
applyingFromCore = true;
|
|
214
|
+
try {
|
|
215
|
+
const current = core.snapshot().logicalSource;
|
|
216
|
+
view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: current } });
|
|
217
|
+
args.textRef.current = current;
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
applyingFromCore = false;
|
|
221
|
+
}
|
|
222
|
+
}),
|
|
223
|
+
keymapCompartment.of(sourceKeymap(args.markdownToolbar, args.saveFromEditor, args.formatFromEditor, args.allowNextTabFocusRef, args.wrapInline, args.openLink, args.externalHistory, () => args.markdownCore?.undo(), () => args.markdownCore?.redo())),
|
|
224
|
+
languageCompartment.of(languageExtension(args.language)),
|
|
225
|
+
];
|
|
226
|
+
const view = new EditorView({
|
|
227
|
+
state: EditorState.create({
|
|
228
|
+
doc: args.textRef.current,
|
|
229
|
+
selection: args.initialViewState
|
|
230
|
+
? {
|
|
231
|
+
anchor: Math.min(args.initialViewState.anchor, args.textRef.current.length),
|
|
232
|
+
head: Math.min(args.initialViewState.head, args.textRef.current.length),
|
|
233
|
+
}
|
|
234
|
+
: undefined,
|
|
235
|
+
extensions,
|
|
236
|
+
}),
|
|
237
|
+
parent: host,
|
|
238
|
+
});
|
|
239
|
+
args.viewRef.current = view;
|
|
240
|
+
const releaseCensus = acquireResource({
|
|
241
|
+
kind: "codemirror-view",
|
|
242
|
+
documentPath: args.markdownCore?.state.documentId ?? args.documentPath,
|
|
243
|
+
format: args.language === "markdown" ? "md" : args.language === "html" ? "html" : "txt",
|
|
244
|
+
});
|
|
245
|
+
// MarkdownSurfaceId.CodeMirrorSource === 1 << 1 === 2. Avoid static import of markdown core enum to keep TXT isolated.
|
|
246
|
+
const MARKDOWN_SURFACE_ID_CODEMIRROR = 2;
|
|
247
|
+
const searchResultListeners = new Set();
|
|
248
|
+
const unsubscribeCore = args.markdownCore?.subscribe(MARKDOWN_SURFACE_ID_CODEMIRROR, (summary) => {
|
|
249
|
+
const next = args.markdownCore?.snapshot().logicalSource;
|
|
250
|
+
if (next !== undefined && view.state.doc.toString() !== next) {
|
|
251
|
+
applyingFromCore = true;
|
|
252
|
+
try {
|
|
253
|
+
const changes = summary.forwardEdits.map((edit) => ({
|
|
254
|
+
from: edit.from,
|
|
255
|
+
to: edit.to,
|
|
256
|
+
insert: edit.insert,
|
|
257
|
+
}));
|
|
258
|
+
const changeSet = view.state.changes(changes);
|
|
259
|
+
const transaction = view.state.update({
|
|
260
|
+
changes: changeSet,
|
|
261
|
+
selection: mapSelectionThroughChanges(view.state.selection.main, changeSet),
|
|
262
|
+
});
|
|
263
|
+
if (changes.length && transaction.newDoc.toString() === next) {
|
|
264
|
+
view.dispatch(transaction);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
const { from, to, insert } = boundedSourceTransition(view.state.doc.toString(), next);
|
|
268
|
+
const fallbackChanges = view.state.changes({ from, to, insert });
|
|
269
|
+
view.dispatch({
|
|
270
|
+
changes: fallbackChanges,
|
|
271
|
+
selection: mapSelectionThroughChanges(view.state.selection.main, fallbackChanges),
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
args.textRef.current = next;
|
|
275
|
+
}
|
|
276
|
+
finally {
|
|
277
|
+
applyingFromCore = false;
|
|
278
|
+
}
|
|
279
|
+
if (args.searchRef.current.query) {
|
|
280
|
+
const result = args.refreshSearch();
|
|
281
|
+
const query = args.searchRef.current.query;
|
|
282
|
+
for (const listener of searchResultListeners)
|
|
283
|
+
listener(query, result);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
const hint = summary.selectionHint;
|
|
287
|
+
if (hint?.surface === "prosemirror") {
|
|
288
|
+
const anchor = Math.max(0, Math.min(hint.anchor, view.state.doc.length));
|
|
289
|
+
const head = Math.max(0, Math.min(hint.head, view.state.doc.length));
|
|
290
|
+
view.dispatch({ selection: { anchor, head } });
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
args.onEditorReadyRef.current?.(view);
|
|
294
|
+
if (args.autoFocus && !args.readOnlyRef.current) {
|
|
295
|
+
requestAnimationFrame(() => {
|
|
296
|
+
if (args.viewRef.current === view)
|
|
297
|
+
view.focus();
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
const onSourceScroll = () => {
|
|
301
|
+
const block = view.lineBlockAtHeight(view.scrollDOM.scrollTop + 12);
|
|
302
|
+
args.onSourceScrollLineRef.current?.(view.state.doc.lineAt(block.from).number);
|
|
303
|
+
};
|
|
304
|
+
view.scrollDOM.addEventListener("scroll", onSourceScroll, { passive: true });
|
|
305
|
+
const onUndo = () => {
|
|
306
|
+
if (args.activeRef.current)
|
|
307
|
+
undo(view);
|
|
308
|
+
};
|
|
309
|
+
const onRedo = () => {
|
|
310
|
+
if (args.activeRef.current)
|
|
311
|
+
redo(view);
|
|
312
|
+
};
|
|
313
|
+
if (!args.externalHistory) {
|
|
314
|
+
window.addEventListener("viewright:undo", onUndo);
|
|
315
|
+
window.addEventListener("viewright:redo", onRedo);
|
|
316
|
+
}
|
|
317
|
+
requestAnimationFrame(() => {
|
|
318
|
+
if (args.viewRef.current !== view)
|
|
319
|
+
return;
|
|
320
|
+
view.requestMeasure();
|
|
321
|
+
requestAnimationFrame(() => {
|
|
322
|
+
if (args.viewRef.current === view)
|
|
323
|
+
view.requestMeasure();
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
if (args.initialViewState) {
|
|
327
|
+
requestAnimationFrame(() => {
|
|
328
|
+
if (args.viewRef.current === view && args.initialViewState) {
|
|
329
|
+
view.scrollDOM.scrollTop = args.initialViewState.scrollTop;
|
|
330
|
+
view.scrollDOM.scrollLeft = args.initialViewState.scrollLeft;
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
const provider = {
|
|
335
|
+
kind: "source",
|
|
336
|
+
canReplace: !args.readOnlyRef.current,
|
|
337
|
+
supportsMatchCase: true,
|
|
338
|
+
supportsWholeWord: true,
|
|
339
|
+
supportsRegex: true,
|
|
340
|
+
find: (query, options) => args.runFind(query, options),
|
|
341
|
+
next: () => args.stepSearch(1),
|
|
342
|
+
prev: () => args.stepSearch(-1),
|
|
343
|
+
replace: (replacement) => args.replaceAndFind(replacement, false),
|
|
344
|
+
replaceAll: (replacement) => args.replaceAndFind(replacement, true),
|
|
345
|
+
subscribe: (listener) => {
|
|
346
|
+
searchResultListeners.add(listener);
|
|
347
|
+
return () => searchResultListeners.delete(listener);
|
|
348
|
+
},
|
|
349
|
+
close: () => {
|
|
350
|
+
args.searchRef.current = {
|
|
351
|
+
query: "",
|
|
352
|
+
options: args.searchRef.current.options,
|
|
353
|
+
matches: [],
|
|
354
|
+
activeIndex: -1,
|
|
355
|
+
};
|
|
356
|
+
args.dispatchSearchHighlights([], -1);
|
|
357
|
+
},
|
|
358
|
+
};
|
|
359
|
+
args.registeredProviderRef.current = provider;
|
|
360
|
+
args.registerSearchProviderRef.current(provider);
|
|
361
|
+
return () => {
|
|
362
|
+
unsubscribeCore?.();
|
|
363
|
+
if (!args.externalHistory) {
|
|
364
|
+
window.removeEventListener("viewright:undo", onUndo);
|
|
365
|
+
window.removeEventListener("viewright:redo", onRedo);
|
|
366
|
+
}
|
|
367
|
+
view.scrollDOM.removeEventListener("scroll", onSourceScroll);
|
|
368
|
+
const sel = view.state.selection.main;
|
|
369
|
+
args.onViewStateChangeRef.current?.({
|
|
370
|
+
anchor: sel.anchor,
|
|
371
|
+
head: sel.head,
|
|
372
|
+
scrollTop: view.scrollDOM.scrollTop,
|
|
373
|
+
scrollLeft: view.scrollDOM.scrollLeft,
|
|
374
|
+
});
|
|
375
|
+
args.registerSearchProviderRef.current(null);
|
|
376
|
+
args.registeredProviderRef.current = null;
|
|
377
|
+
args.onEditorReadyRef.current?.(null);
|
|
378
|
+
view.destroy();
|
|
379
|
+
releaseCensus();
|
|
380
|
+
if (args.viewRef.current === view)
|
|
381
|
+
args.viewRef.current = null;
|
|
382
|
+
};
|
|
383
|
+
}, [
|
|
384
|
+
completionCompartment,
|
|
385
|
+
contentAttributesCompartment,
|
|
386
|
+
diagnosticsCompartment,
|
|
387
|
+
gutterCompartment,
|
|
388
|
+
invisiblesCompartment,
|
|
389
|
+
keymapCompartment,
|
|
390
|
+
languageCompartment,
|
|
391
|
+
readOnlyCompartment,
|
|
392
|
+
themeCompartment,
|
|
393
|
+
wordWrapCompartment,
|
|
394
|
+
]);
|
|
395
|
+
useEffect(() => {
|
|
396
|
+
const view = args.viewRef.current;
|
|
397
|
+
if (!view)
|
|
398
|
+
return;
|
|
399
|
+
if (args.language === "plain") {
|
|
400
|
+
view.dispatch({
|
|
401
|
+
effects: [
|
|
402
|
+
languageCompartment.reconfigure(languageExtension(args.language)),
|
|
403
|
+
gutterCompartment.reconfigure(gutterExtension(args.language)),
|
|
404
|
+
completionCompartment.reconfigure(completionExtension(args.language)),
|
|
405
|
+
diagnosticsCompartment.reconfigure(diagnosticsExtension(args.language, null)),
|
|
406
|
+
],
|
|
407
|
+
});
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
let cancelled = false;
|
|
411
|
+
void (async () => {
|
|
412
|
+
const [langExt, diagExt] = await Promise.all([
|
|
413
|
+
loadLanguageExtension(args.language),
|
|
414
|
+
loadDiagnosticsExtension(args.language, args.markdownCore),
|
|
415
|
+
]);
|
|
416
|
+
if (cancelled || args.viewRef.current !== view)
|
|
417
|
+
return;
|
|
418
|
+
let combinedCompletion = completionExtension(args.language);
|
|
419
|
+
if (args.language === "markdown" && args.markdownCore) {
|
|
420
|
+
const mdCompletion = await loadMarkdownCoreCompletionExtension(args.markdownCore);
|
|
421
|
+
if (cancelled || args.viewRef.current !== view)
|
|
422
|
+
return;
|
|
423
|
+
combinedCompletion = mdCompletion.length
|
|
424
|
+
? mdCompletion // includes the slash insert source; a second override would conflict
|
|
425
|
+
: combinedCompletion;
|
|
426
|
+
}
|
|
427
|
+
view.dispatch({
|
|
428
|
+
effects: [
|
|
429
|
+
languageCompartment.reconfigure(langExt),
|
|
430
|
+
gutterCompartment.reconfigure(gutterExtension(args.language)),
|
|
431
|
+
completionCompartment.reconfigure(combinedCompletion),
|
|
432
|
+
diagnosticsCompartment.reconfigure(diagExt),
|
|
433
|
+
],
|
|
434
|
+
});
|
|
435
|
+
})();
|
|
436
|
+
return () => {
|
|
437
|
+
cancelled = true;
|
|
438
|
+
};
|
|
439
|
+
}, [
|
|
440
|
+
args.language,
|
|
441
|
+
args.markdownCore,
|
|
442
|
+
args.viewRef,
|
|
443
|
+
completionCompartment,
|
|
444
|
+
diagnosticsCompartment,
|
|
445
|
+
gutterCompartment,
|
|
446
|
+
languageCompartment,
|
|
447
|
+
]);
|
|
448
|
+
useEffect(() => {
|
|
449
|
+
args.viewRef.current?.dispatch({ effects: themeCompartment.reconfigure(args.themeExtension) });
|
|
450
|
+
}, [args.themeExtension, args.viewRef, themeCompartment]);
|
|
451
|
+
useEffect(() => {
|
|
452
|
+
args.readOnlyRef.current = args.readOnly;
|
|
453
|
+
args.registeredProviderRef.current = args.registeredProviderRef.current
|
|
454
|
+
? { ...args.registeredProviderRef.current, canReplace: !args.readOnly }
|
|
455
|
+
: null;
|
|
456
|
+
if (args.registeredProviderRef.current)
|
|
457
|
+
args.registerSearchProviderRef.current(args.registeredProviderRef.current);
|
|
458
|
+
const view = args.viewRef.current;
|
|
459
|
+
if (!view)
|
|
460
|
+
return;
|
|
461
|
+
view.dispatch({
|
|
462
|
+
effects: [
|
|
463
|
+
readOnlyCompartment.reconfigure(readOnlyExtension(args.readOnly)),
|
|
464
|
+
contentAttributesCompartment.reconfigure(contentAttributesExtension(args.settingsSpellcheck, args.readOnly)),
|
|
465
|
+
],
|
|
466
|
+
});
|
|
467
|
+
}, [
|
|
468
|
+
args.readOnly,
|
|
469
|
+
args.readOnlyRef,
|
|
470
|
+
args.registerSearchProviderRef,
|
|
471
|
+
args.registeredProviderRef,
|
|
472
|
+
args.settingsSpellcheck,
|
|
473
|
+
args.viewRef,
|
|
474
|
+
contentAttributesCompartment,
|
|
475
|
+
readOnlyCompartment,
|
|
476
|
+
]);
|
|
477
|
+
useEffect(() => {
|
|
478
|
+
args.viewRef.current?.dispatch({
|
|
479
|
+
effects: wordWrapCompartment.reconfigure(sourceWrapExtension(args.settingsWordWrap, args.language, args.sourceWrap)),
|
|
480
|
+
});
|
|
481
|
+
}, [args.language, args.settingsWordWrap, args.sourceWrap, args.viewRef, wordWrapCompartment]);
|
|
482
|
+
useEffect(() => {
|
|
483
|
+
args.viewRef.current?.dispatch({
|
|
484
|
+
effects: invisiblesCompartment.reconfigure(invisibleCharactersExtension(args.showInvisibles)),
|
|
485
|
+
});
|
|
486
|
+
}, [args.showInvisibles, args.viewRef, invisiblesCompartment]);
|
|
487
|
+
useEffect(() => {
|
|
488
|
+
args.viewRef.current?.dispatch({
|
|
489
|
+
effects: keymapCompartment.reconfigure(sourceKeymap(args.markdownToolbar, args.saveFromEditor, args.formatFromEditor, args.allowNextTabFocusRef, args.wrapInline, args.openLink, args.externalHistory, () => args.markdownCore?.undo(), () => args.markdownCore?.redo())),
|
|
490
|
+
});
|
|
491
|
+
}, [
|
|
492
|
+
args.allowNextTabFocusRef,
|
|
493
|
+
args.externalHistory,
|
|
494
|
+
args.formatFromEditor,
|
|
495
|
+
args.markdownToolbar,
|
|
496
|
+
args.markdownCore,
|
|
497
|
+
args.openLink,
|
|
498
|
+
args.saveFromEditor,
|
|
499
|
+
args.viewRef,
|
|
500
|
+
args.wrapInline,
|
|
501
|
+
keymapCompartment,
|
|
502
|
+
]);
|
|
503
|
+
useEffect(() => {
|
|
504
|
+
const view = args.viewRef.current;
|
|
505
|
+
if (!view)
|
|
506
|
+
return;
|
|
507
|
+
if (args.textRef.current === args.text && view.state.doc.toString() === args.text)
|
|
508
|
+
return;
|
|
509
|
+
args.suppressChangeRef.current = true;
|
|
510
|
+
view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: args.text } });
|
|
511
|
+
args.suppressChangeRef.current = false;
|
|
512
|
+
args.textRef.current = args.text;
|
|
513
|
+
if (args.searchRef.current.query)
|
|
514
|
+
args.runFind(args.searchRef.current.query, args.searchRef.current.options);
|
|
515
|
+
}, [args.runFind, args.searchRef, args.suppressChangeRef, args.text, args.textRef, args.viewRef]);
|
|
516
|
+
}
|
|
517
|
+
function mapSelectionThroughChanges(selection, changes) {
|
|
518
|
+
const forward = selection.anchor <= selection.head;
|
|
519
|
+
const anchorAssoc = selection.empty ? 1 : forward ? -1 : 1;
|
|
520
|
+
const headAssoc = selection.empty ? 1 : forward ? 1 : -1;
|
|
521
|
+
return {
|
|
522
|
+
anchor: changes.mapPos(selection.anchor, anchorAssoc),
|
|
523
|
+
head: changes.mapPos(selection.head, headAssoc),
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
function boundedSourceTransition(previous, next) {
|
|
527
|
+
let from = 0;
|
|
528
|
+
const commonLimit = Math.min(previous.length, next.length);
|
|
529
|
+
while (from < commonLimit && previous.charCodeAt(from) === next.charCodeAt(from))
|
|
530
|
+
from++;
|
|
531
|
+
let previousEnd = previous.length;
|
|
532
|
+
let nextEnd = next.length;
|
|
533
|
+
while (previousEnd > from &&
|
|
534
|
+
nextEnd > from &&
|
|
535
|
+
previous.charCodeAt(previousEnd - 1) === next.charCodeAt(nextEnd - 1)) {
|
|
536
|
+
previousEnd--;
|
|
537
|
+
nextEnd--;
|
|
538
|
+
}
|
|
539
|
+
return { from, to: previousEnd, insert: next.slice(from, nextEnd) };
|
|
540
|
+
}
|
|
541
|
+
function assetPayloadBase64(source) {
|
|
542
|
+
if (typeof source !== "string")
|
|
543
|
+
return bytesToBase64(source);
|
|
544
|
+
const comma = source.indexOf(",");
|
|
545
|
+
return source.startsWith("data:") && comma >= 0 ? source.slice(comma + 1) : source;
|
|
546
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type MutableRefObject } from "react";
|
|
2
|
+
import type { EditorView } from "@codemirror/view";
|
|
3
|
+
import { type TextMatch } from "@rightkit/document-core/documents/searchUtils";
|
|
4
|
+
type SearchOptions = {
|
|
5
|
+
matchCase: boolean;
|
|
6
|
+
wholeWord: boolean;
|
|
7
|
+
regex?: boolean;
|
|
8
|
+
};
|
|
9
|
+
interface SourceSearchSnapshot {
|
|
10
|
+
query: string;
|
|
11
|
+
options: SearchOptions;
|
|
12
|
+
matches: TextMatch[];
|
|
13
|
+
activeIndex: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function useSourceSearch({ viewRef, readOnlyRef, }: {
|
|
16
|
+
viewRef: MutableRefObject<EditorView | null>;
|
|
17
|
+
readOnlyRef: MutableRefObject<boolean>;
|
|
18
|
+
}): {
|
|
19
|
+
clearSearch: () => void;
|
|
20
|
+
dispatchSearchHighlights: (matches: TextMatch[], activeIndex: number) => void;
|
|
21
|
+
replaceAndFind: (replacement: string, all: boolean) => {
|
|
22
|
+
count: number;
|
|
23
|
+
activeIndex: number;
|
|
24
|
+
};
|
|
25
|
+
refreshSearch: () => {
|
|
26
|
+
count: number;
|
|
27
|
+
activeIndex: number;
|
|
28
|
+
};
|
|
29
|
+
runFind: (query: string, options: SearchOptions) => {
|
|
30
|
+
count: number;
|
|
31
|
+
activeIndex: number;
|
|
32
|
+
};
|
|
33
|
+
searchRef: import("react").RefObject<SourceSearchSnapshot>;
|
|
34
|
+
stepSearch: (delta: number) => {
|
|
35
|
+
count: number;
|
|
36
|
+
activeIndex: number;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
export {};
|