@lvce-editor/api 8.43.1 → 8.45.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/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/parts/CommandMap/CommandMap.d.ts +6 -0
- package/dist/parts/ExtensionApiCommandMap/ExtensionApiCommandMap.d.ts +6 -0
- package/dist/parts/ExtensionApiCommandMap/ExtensionApiCommandMap.js +3 -0
- package/dist/parts/ExtensionApiWorkerCommandMap/ExtensionApiWorkerCommandMap.d.ts +6 -0
- package/dist/parts/LanguageProvider/LanguageProvider.d.ts +24 -0
- package/dist/parts/LanguageProvider/LanguageProvider.js +77 -0
- package/dist/parts/View/View.d.ts +8 -0
- package/dist/parts/ViewRegistry/ViewRegistry.js +35 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -9,11 +9,13 @@ export { executeFormattingProvider, getFormattingProviderRegistrySnapshot, regis
|
|
|
9
9
|
export { exists, mkdir, readDirWithFileTypes, readFile, remove, stat, writeFile } from './parts/FileSystem/FileSystem.ts';
|
|
10
10
|
export { confirm, getWorkspaceFolder, handleWorkspaceRefresh, openUri } from './parts/Host/Host.ts';
|
|
11
11
|
export { executeHoverProvider, getHoverProviderRegistrySnapshot, registerHoverProvider, resetHoverProviderRegistry } from './parts/Hover/Hover.ts';
|
|
12
|
+
export { registerBraceCompletionProvider, registerClosingTagProvider, registerCodeActionsProvider, registerCommentProvider, registerDefinitionProvider, registerImplementationProvider, registerReferenceProvider, registerRenameProvider, registerSelectionProvider, registerTabCompletionProvider, registerTypeDefinitionProvider, resetLanguageProviderRegistry, } from './parts/LanguageProvider/LanguageProvider.ts';
|
|
13
|
+
export type { LanguageProvider } from './parts/LanguageProvider/LanguageProvider.ts';
|
|
12
14
|
export { executeSourceControlAcceptInput, executeSourceControlAdd, executeSourceControlDiscard, executeSourceControlGenerateCommitMessage, executeSourceControlGetBadgeCount, executeSourceControlGetChangedFiles, executeSourceControlGetFeatures, executeSourceControlGetFileBefore, executeSourceControlGetFileDecorations, executeSourceControlGetGroups, executeSourceControlIsActive, registerSourceControlProvider, resetSourceControlProviderRegistry, } from './parts/SourceControl/SourceControl.ts';
|
|
13
15
|
export { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewRegistrySnapshot, renderViewInstance, registerView, resetViewRegistry, saveViewInstanceState, } from './parts/ViewRegistry/ViewRegistry.ts';
|
|
14
16
|
export { createOutputChannel, getOutputChannelRegistrySnapshot, resetOutputChannelRegistry } from './parts/OutputChannel/OutputChannel.ts';
|
|
15
17
|
export { getStatusBarItemProviderRegistrySnapshot, registerStatusBarItemProvider, resetStatusBarItemProviderRegistry, } from './parts/StatusBar/StatusBar.ts';
|
|
16
|
-
export type { RegisteredView, View, ViewAction, ViewCommand, ViewContext, ViewEvent, ViewKind, MenuEntry, ViewRegistrySnapshot, ViewRenderResult, VirtualDomViewInstance, } from './parts/View/View.ts';
|
|
18
|
+
export type { RegisteredView, View, ViewAction, ViewCommand, ViewContext, ViewEvent, ViewKind, MenuEntry, ViewRegistrySnapshot, ViewRenderResult, ViewSelection, VirtualDomViewInstance, } from './parts/View/View.ts';
|
|
17
19
|
export { handleExtensionManagementMessagePort } from './parts/HandleExtensionManagementMessagePort/HandleExtensionManagementMessagePort.ts';
|
|
18
20
|
export { createNodeRpc, createRpc } from './parts/Rpc/Rpc.ts';
|
|
19
21
|
export type { Command } from './parts/Command/Command.ts';
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export { executeFormattingProvider, getFormattingProviderRegistrySnapshot, regis
|
|
|
9
9
|
export { exists, mkdir, readDirWithFileTypes, readFile, remove, stat, writeFile } from "./parts/FileSystem/FileSystem.js";
|
|
10
10
|
export { confirm, getWorkspaceFolder, handleWorkspaceRefresh, openUri } from "./parts/Host/Host.js";
|
|
11
11
|
export { executeHoverProvider, getHoverProviderRegistrySnapshot, registerHoverProvider, resetHoverProviderRegistry } from "./parts/Hover/Hover.js";
|
|
12
|
+
export { registerBraceCompletionProvider, registerClosingTagProvider, registerCodeActionsProvider, registerCommentProvider, registerDefinitionProvider, registerImplementationProvider, registerReferenceProvider, registerRenameProvider, registerSelectionProvider, registerTabCompletionProvider, registerTypeDefinitionProvider, resetLanguageProviderRegistry, } from "./parts/LanguageProvider/LanguageProvider.js";
|
|
12
13
|
export { executeSourceControlAcceptInput, executeSourceControlAdd, executeSourceControlDiscard, executeSourceControlGenerateCommitMessage, executeSourceControlGetBadgeCount, executeSourceControlGetChangedFiles, executeSourceControlGetFeatures, executeSourceControlGetFileBefore, executeSourceControlGetFileDecorations, executeSourceControlGetGroups, executeSourceControlIsActive, registerSourceControlProvider, resetSourceControlProviderRegistry, } from "./parts/SourceControl/SourceControl.js";
|
|
13
14
|
export { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewRegistrySnapshot, renderViewInstance, registerView, resetViewRegistry, saveViewInstanceState, } from "./parts/ViewRegistry/ViewRegistry.js";
|
|
14
15
|
export { createOutputChannel, getOutputChannelRegistrySnapshot, resetOutputChannelRegistry } from "./parts/OutputChannel/OutputChannel.js";
|
|
@@ -8,6 +8,12 @@ export declare const commandMap: {
|
|
|
8
8
|
'ExtensionApi.executeDiagnosticProvider': (textDocument: import("../DiagnosticTextDocument/DiagnosticTextDocument.ts").TextDocument, ...args: readonly unknown[]) => Promise<readonly import("../DiagnosticResult/DiagnosticResult.ts").Diagnostic[]>;
|
|
9
9
|
'ExtensionApi.executeFormattingProvider': (textDocument: import("../FormattingTextDocument/FormattingTextDocument.ts").TextDocument, ...args: readonly unknown[]) => Promise<readonly import("../FormattingEdit/FormattingEdit.ts").FormattingEdit[]>;
|
|
10
10
|
'ExtensionApi.executeHoverProvider': (textDocument: import("../HoverTextDocument/HoverTextDocument.ts").TextDocument, offset: number, ...args: readonly unknown[]) => Promise<import("../HoverResult/HoverResult.ts").HoverResult | undefined>;
|
|
11
|
+
'ExtensionApi.executeLanguageProvider': (kind: string, methodName: string, textDocument: {
|
|
12
|
+
readonly languageId: string;
|
|
13
|
+
}, ...args: readonly unknown[]) => Promise<unknown>;
|
|
14
|
+
'ExtensionApi.executeOrganizeImportsProvider': (textDocument: {
|
|
15
|
+
readonly languageId: string;
|
|
16
|
+
}) => Promise<unknown>;
|
|
11
17
|
'ExtensionApi.executeResolveCompletionItemProvider': (textDocument: import("../CompletionTextDocument/CompletionTextDocument.ts").TextDocument, offset: number, name: string, completionItem: import("../CompletionItem/CompletionItem.ts").CompletionItem, ...args: readonly unknown[]) => Promise<import("../CompletionItem/CompletionItem.ts").CompletionItem | undefined>;
|
|
12
18
|
'ExtensionApi.executeSourceControlAcceptInput': (id: string, value: string) => Promise<unknown>;
|
|
13
19
|
'ExtensionApi.executeSourceControlAdd': (id: string, path: string) => Promise<unknown>;
|
|
@@ -7,6 +7,12 @@ export declare const commandMap: {
|
|
|
7
7
|
'ExtensionApi.executeDiagnosticProvider': (textDocument: import("../DiagnosticTextDocument/DiagnosticTextDocument.ts").TextDocument, ...args: readonly unknown[]) => Promise<readonly import("../DiagnosticResult/DiagnosticResult.ts").Diagnostic[]>;
|
|
8
8
|
'ExtensionApi.executeFormattingProvider': (textDocument: import("../FormattingTextDocument/FormattingTextDocument.ts").TextDocument, ...args: readonly unknown[]) => Promise<readonly import("../FormattingEdit/FormattingEdit.ts").FormattingEdit[]>;
|
|
9
9
|
'ExtensionApi.executeHoverProvider': (textDocument: import("../HoverTextDocument/HoverTextDocument.ts").TextDocument, offset: number, ...args: readonly unknown[]) => Promise<import("../HoverResult/HoverResult.ts").HoverResult | undefined>;
|
|
10
|
+
'ExtensionApi.executeLanguageProvider': (kind: string, methodName: string, textDocument: {
|
|
11
|
+
readonly languageId: string;
|
|
12
|
+
}, ...args: readonly unknown[]) => Promise<unknown>;
|
|
13
|
+
'ExtensionApi.executeOrganizeImportsProvider': (textDocument: {
|
|
14
|
+
readonly languageId: string;
|
|
15
|
+
}) => Promise<unknown>;
|
|
10
16
|
'ExtensionApi.executeResolveCompletionItemProvider': (textDocument: import("../CompletionTextDocument/CompletionTextDocument.ts").TextDocument, offset: number, name: string, completionItem: import("../CompletionItem/CompletionItem.ts").CompletionItem, ...args: readonly unknown[]) => Promise<import("../CompletionItem/CompletionItem.ts").CompletionItem | undefined>;
|
|
11
17
|
'ExtensionApi.executeSourceControlAcceptInput': (id: string, value: string) => Promise<unknown>;
|
|
12
18
|
'ExtensionApi.executeSourceControlAdd': (id: string, path: string) => Promise<unknown>;
|
|
@@ -4,6 +4,7 @@ import { executeDiagnosticProvider, getDiagnosticProviderRegistrySnapshot } from
|
|
|
4
4
|
import { executeFormattingProvider, getFormattingProviderRegistrySnapshot } from "../Formatting/Formatting.js";
|
|
5
5
|
import { getStatusBarItems } from "../GetStatusBarItems/GetStatusBarItems.js";
|
|
6
6
|
import { executeHoverProvider, getHoverProviderRegistrySnapshot } from "../Hover/Hover.js";
|
|
7
|
+
import { executeLanguageProvider, executeOrganizeImportsProvider } from "../LanguageProvider/LanguageProvider.js";
|
|
7
8
|
import { getOutputChannelRegistrySnapshot } from "../OutputChannel/OutputChannel.js";
|
|
8
9
|
import { executeSourceControlAcceptInput, executeSourceControlAdd, executeSourceControlDiscard, executeSourceControlGenerateCommitMessage, executeSourceControlGetBadgeCount, executeSourceControlGetChangedFiles, executeSourceControlGetFeatures, executeSourceControlGetFileBefore, executeSourceControlGetFileDecorations, executeSourceControlGetGroups, executeSourceControlIsActive, getSourceControlProviderRegistrySnapshot, } from "../SourceControl/SourceControl.js";
|
|
9
10
|
import { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewActions, getViewMenuEntries, getViewRegistrySnapshot, renderViewInstance, saveViewInstanceState, } from "../ViewRegistry/ViewRegistry.js";
|
|
@@ -16,6 +17,8 @@ export const commandMap = {
|
|
|
16
17
|
'ExtensionApi.executeDiagnosticProvider': executeDiagnosticProvider,
|
|
17
18
|
'ExtensionApi.executeFormattingProvider': executeFormattingProvider,
|
|
18
19
|
'ExtensionApi.executeHoverProvider': executeHoverProvider,
|
|
20
|
+
'ExtensionApi.executeLanguageProvider': executeLanguageProvider,
|
|
21
|
+
'ExtensionApi.executeOrganizeImportsProvider': executeOrganizeImportsProvider,
|
|
19
22
|
'ExtensionApi.executeResolveCompletionItemProvider': executeResolveCompletionItemProvider,
|
|
20
23
|
'ExtensionApi.executeSourceControlAcceptInput': executeSourceControlAcceptInput,
|
|
21
24
|
'ExtensionApi.executeSourceControlAdd': executeSourceControlAdd,
|
|
@@ -9,6 +9,12 @@ export declare const commandMap: {
|
|
|
9
9
|
'ExtensionApi.executeDiagnosticProvider': (textDocument: import("../DiagnosticTextDocument/DiagnosticTextDocument.ts").TextDocument, ...args: readonly unknown[]) => Promise<readonly import("../DiagnosticResult/DiagnosticResult.ts").Diagnostic[]>;
|
|
10
10
|
'ExtensionApi.executeFormattingProvider': (textDocument: import("../FormattingTextDocument/FormattingTextDocument.ts").TextDocument, ...args: readonly unknown[]) => Promise<readonly import("../FormattingEdit/FormattingEdit.ts").FormattingEdit[]>;
|
|
11
11
|
'ExtensionApi.executeHoverProvider': (textDocument: import("../HoverTextDocument/HoverTextDocument.ts").TextDocument, offset: number, ...args: readonly unknown[]) => Promise<import("../HoverResult/HoverResult.ts").HoverResult | undefined>;
|
|
12
|
+
'ExtensionApi.executeLanguageProvider': (kind: string, methodName: string, textDocument: {
|
|
13
|
+
readonly languageId: string;
|
|
14
|
+
}, ...args: readonly unknown[]) => Promise<unknown>;
|
|
15
|
+
'ExtensionApi.executeOrganizeImportsProvider': (textDocument: {
|
|
16
|
+
readonly languageId: string;
|
|
17
|
+
}) => Promise<unknown>;
|
|
12
18
|
'ExtensionApi.executeResolveCompletionItemProvider': (textDocument: import("../CompletionTextDocument/CompletionTextDocument.ts").TextDocument, offset: number, name: string, completionItem: import("../CompletionItem/CompletionItem.ts").CompletionItem, ...args: readonly unknown[]) => Promise<import("../CompletionItem/CompletionItem.ts").CompletionItem | undefined>;
|
|
13
19
|
'ExtensionApi.executeSourceControlAcceptInput': (id: string, value: string) => Promise<unknown>;
|
|
14
20
|
'ExtensionApi.executeSourceControlAdd': (id: string, path: string) => Promise<unknown>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Disposable } from '../Disposable/Disposable.ts';
|
|
2
|
+
export interface LanguageProvider {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly languageId: string;
|
|
5
|
+
readonly [key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
export declare const executeLanguageProvider: (kind: string, methodName: string, textDocument: {
|
|
8
|
+
readonly languageId: string;
|
|
9
|
+
}, ...args: readonly unknown[]) => Promise<unknown>;
|
|
10
|
+
export declare const executeOrganizeImportsProvider: (textDocument: {
|
|
11
|
+
readonly languageId: string;
|
|
12
|
+
}) => Promise<unknown>;
|
|
13
|
+
export declare const registerBraceCompletionProvider: (provider: LanguageProvider) => Disposable;
|
|
14
|
+
export declare const registerClosingTagProvider: (provider: LanguageProvider) => Disposable;
|
|
15
|
+
export declare const registerCodeActionsProvider: (provider: LanguageProvider) => Disposable;
|
|
16
|
+
export declare const registerCommentProvider: (provider: LanguageProvider) => Disposable;
|
|
17
|
+
export declare const registerDefinitionProvider: (provider: LanguageProvider) => Disposable;
|
|
18
|
+
export declare const registerImplementationProvider: (provider: LanguageProvider) => Disposable;
|
|
19
|
+
export declare const registerReferenceProvider: (provider: LanguageProvider) => Disposable;
|
|
20
|
+
export declare const registerRenameProvider: (provider: LanguageProvider) => Disposable;
|
|
21
|
+
export declare const registerSelectionProvider: (provider: LanguageProvider) => Disposable;
|
|
22
|
+
export declare const registerTabCompletionProvider: (provider: LanguageProvider) => Disposable;
|
|
23
|
+
export declare const registerTypeDefinitionProvider: (provider: LanguageProvider) => Disposable;
|
|
24
|
+
export declare const resetLanguageProviderRegistry: () => void;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ExtensionApiError } from "../ExtensionApiError/ExtensionApiError.js";
|
|
2
|
+
const providers = Object.create(null);
|
|
3
|
+
const getProvider = (kind, languageId) => {
|
|
4
|
+
return providers[kind]?.find((provider) => provider.languageId === languageId);
|
|
5
|
+
};
|
|
6
|
+
const registerProvider = (kind, provider, requiredMethods) => {
|
|
7
|
+
if (!provider || typeof provider !== 'object') {
|
|
8
|
+
throw new ExtensionApiError(`${kind} provider is not defined`);
|
|
9
|
+
}
|
|
10
|
+
if (typeof provider.id !== 'string' || provider.id.length === 0) {
|
|
11
|
+
throw new ExtensionApiError(`${kind} provider is missing id`);
|
|
12
|
+
}
|
|
13
|
+
if (typeof provider.languageId !== 'string' || provider.languageId.length === 0) {
|
|
14
|
+
throw new ExtensionApiError(`${kind} provider ${provider.id} is missing languageId`);
|
|
15
|
+
}
|
|
16
|
+
for (const methodName of requiredMethods) {
|
|
17
|
+
if (typeof provider[methodName] !== 'function') {
|
|
18
|
+
throw new ExtensionApiError(`${kind} provider ${provider.id} is missing ${methodName} function`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const kindProviders = (providers[kind] ||= []);
|
|
22
|
+
if (kindProviders.some((registeredProvider) => registeredProvider.id === provider.id)) {
|
|
23
|
+
throw new ExtensionApiError(`${kind} provider ${provider.id} is already registered`);
|
|
24
|
+
}
|
|
25
|
+
kindProviders.push(provider);
|
|
26
|
+
return {
|
|
27
|
+
dispose() {
|
|
28
|
+
const index = kindProviders.indexOf(provider);
|
|
29
|
+
if (index !== -1) {
|
|
30
|
+
kindProviders.splice(index, 1);
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export const executeLanguageProvider = async (kind, methodName, textDocument, ...args) => {
|
|
36
|
+
const provider = getProvider(kind, textDocument.languageId);
|
|
37
|
+
if (!provider) {
|
|
38
|
+
throw new ExtensionApiError(`No ${kind} provider found for ${textDocument.languageId}`);
|
|
39
|
+
}
|
|
40
|
+
const method = provider[methodName];
|
|
41
|
+
if (typeof method !== 'function') {
|
|
42
|
+
throw new ExtensionApiError(`${kind} provider ${provider.id} is missing ${methodName} function`);
|
|
43
|
+
}
|
|
44
|
+
return method(textDocument, ...args);
|
|
45
|
+
};
|
|
46
|
+
export const executeOrganizeImportsProvider = async (textDocument) => {
|
|
47
|
+
const provider = getProvider('code action', textDocument.languageId);
|
|
48
|
+
if (!provider) {
|
|
49
|
+
throw new ExtensionApiError(`No code action provider found for ${textDocument.languageId}`);
|
|
50
|
+
}
|
|
51
|
+
const provideCodeActions = provider.provideCodeActions;
|
|
52
|
+
const actions = await provideCodeActions(textDocument);
|
|
53
|
+
if (!Array.isArray(actions)) {
|
|
54
|
+
throw new ExtensionApiError('invalid code action result: code actions must be of type array');
|
|
55
|
+
}
|
|
56
|
+
const action = actions.find((candidate) => candidate && typeof candidate === 'object' && candidate.kind === 'source.organizeImports');
|
|
57
|
+
if (!action || typeof action.execute !== 'function') {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
return action.execute(textDocument);
|
|
61
|
+
};
|
|
62
|
+
export const registerBraceCompletionProvider = (provider) => registerProvider('brace completion', provider, ['provideBraceCompletion']);
|
|
63
|
+
export const registerClosingTagProvider = (provider) => registerProvider('closing tag', provider, ['provideClosingTag']);
|
|
64
|
+
export const registerCodeActionsProvider = (provider) => registerProvider('code action', provider, ['provideCodeActions']);
|
|
65
|
+
export const registerCommentProvider = (provider) => registerProvider('comment', provider, ['provideComment']);
|
|
66
|
+
export const registerDefinitionProvider = (provider) => registerProvider('definition', provider, ['provideDefinition']);
|
|
67
|
+
export const registerImplementationProvider = (provider) => registerProvider('implementation', provider, ['provideImplementations']);
|
|
68
|
+
export const registerReferenceProvider = (provider) => registerProvider('reference', provider, ['provideReferences']);
|
|
69
|
+
export const registerRenameProvider = (provider) => registerProvider('rename', provider, ['provideRename']);
|
|
70
|
+
export const registerSelectionProvider = (provider) => registerProvider('selection', provider, ['provideSelections']);
|
|
71
|
+
export const registerTabCompletionProvider = (provider) => registerProvider('tab completion', provider, ['provideTabCompletion']);
|
|
72
|
+
export const registerTypeDefinitionProvider = (provider) => registerProvider('type definition', provider, ['provideTypeDefinition']);
|
|
73
|
+
export const resetLanguageProviderRegistry = () => {
|
|
74
|
+
for (const kind of Object.keys(providers)) {
|
|
75
|
+
delete providers[kind];
|
|
76
|
+
}
|
|
77
|
+
};
|
|
@@ -26,6 +26,11 @@ export interface ViewAction {
|
|
|
26
26
|
readonly icon: string;
|
|
27
27
|
readonly title: string;
|
|
28
28
|
}
|
|
29
|
+
export interface ViewSelection {
|
|
30
|
+
readonly end: number;
|
|
31
|
+
readonly name: string;
|
|
32
|
+
readonly start: number;
|
|
33
|
+
}
|
|
29
34
|
export interface DomEventListener {
|
|
30
35
|
readonly capture?: boolean;
|
|
31
36
|
readonly name: string | number;
|
|
@@ -42,6 +47,7 @@ export interface VirtualDomViewInstance {
|
|
|
42
47
|
readonly render: () => readonly VirtualDomNode[] | Promise<readonly VirtualDomNode[]>;
|
|
43
48
|
readonly renderActions?: () => readonly ViewAction[] | Promise<readonly ViewAction[]>;
|
|
44
49
|
readonly renderFocus?: (oldContext: Readonly<Record<string, boolean>>, newContext: Readonly<Record<string, boolean>>) => string | Promise<string>;
|
|
50
|
+
readonly renderSelections?: () => readonly ViewSelection[] | Promise<readonly ViewSelection[]>;
|
|
45
51
|
readonly renderTitle?: () => string | Promise<string>;
|
|
46
52
|
readonly saveState?: () => unknown;
|
|
47
53
|
}
|
|
@@ -72,12 +78,14 @@ export interface ViewRegistrySnapshot {
|
|
|
72
78
|
export interface ViewRenderResultDom {
|
|
73
79
|
readonly dom: readonly VirtualDomNode[];
|
|
74
80
|
readonly focusSelector?: string;
|
|
81
|
+
readonly selections?: readonly ViewSelection[];
|
|
75
82
|
readonly title?: string;
|
|
76
83
|
readonly type: 'setDom';
|
|
77
84
|
}
|
|
78
85
|
export interface ViewRenderResultPatches {
|
|
79
86
|
readonly focusSelector?: string;
|
|
80
87
|
readonly patches: readonly unknown[];
|
|
88
|
+
readonly selections?: readonly ViewSelection[];
|
|
81
89
|
readonly title?: string;
|
|
82
90
|
readonly type: 'setPatches';
|
|
83
91
|
}
|
|
@@ -237,6 +237,26 @@ const normalizeViewActions = (actions) => {
|
|
|
237
237
|
}
|
|
238
238
|
return actions.map(normalizeViewAction);
|
|
239
239
|
};
|
|
240
|
+
const normalizeViewSelection = (selection, index) => {
|
|
241
|
+
if (!selection || typeof selection !== 'object' || Array.isArray(selection)) {
|
|
242
|
+
throw new ExtensionApiError(`view selection ${index} must be an object`);
|
|
243
|
+
}
|
|
244
|
+
const viewSelection = selection;
|
|
245
|
+
assertString(viewSelection.name, `view selection ${index} is missing name`);
|
|
246
|
+
assertNumber(viewSelection.start, `view selection ${index} is missing start`);
|
|
247
|
+
assertNumber(viewSelection.end, `view selection ${index} is missing end`);
|
|
248
|
+
return {
|
|
249
|
+
end: viewSelection.end,
|
|
250
|
+
name: viewSelection.name,
|
|
251
|
+
start: viewSelection.start,
|
|
252
|
+
};
|
|
253
|
+
};
|
|
254
|
+
const normalizeViewSelections = (selections) => {
|
|
255
|
+
if (!Array.isArray(selections)) {
|
|
256
|
+
throw new ExtensionApiError('view selections must be an array');
|
|
257
|
+
}
|
|
258
|
+
return selections.map(normalizeViewSelection);
|
|
259
|
+
};
|
|
240
260
|
const renderPatches = async (uid, instance) => {
|
|
241
261
|
const oldDom = renderedDoms[uid] || [];
|
|
242
262
|
const newDom = await renderDom(instance);
|
|
@@ -336,9 +356,23 @@ const withTitle = async (result, instance) => {
|
|
|
336
356
|
title,
|
|
337
357
|
};
|
|
338
358
|
};
|
|
359
|
+
const withSelections = async (result, instance) => {
|
|
360
|
+
if (typeof instance.renderSelections !== 'function') {
|
|
361
|
+
return result;
|
|
362
|
+
}
|
|
363
|
+
const selections = normalizeViewSelections(await instance.renderSelections());
|
|
364
|
+
if (selections.length === 0) {
|
|
365
|
+
return result;
|
|
366
|
+
}
|
|
367
|
+
return {
|
|
368
|
+
...result,
|
|
369
|
+
selections,
|
|
370
|
+
};
|
|
371
|
+
};
|
|
339
372
|
const withRenderMetadata = async (result, instance, contextChange) => {
|
|
340
373
|
const resultWithFocus = await withFocusSelector(result, instance, contextChange);
|
|
341
|
-
|
|
374
|
+
const resultWithSelections = await withSelections(resultWithFocus, instance);
|
|
375
|
+
return withTitle(resultWithSelections, instance);
|
|
342
376
|
};
|
|
343
377
|
const maybeClearContext = async (uid, viewId) => {
|
|
344
378
|
if (!contexts[uid]) {
|