@lvce-editor/api 9.36.0 → 9.37.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/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/parts/LanguageProvider/LanguageProvider.d.ts +3 -0
- package/dist/parts/LanguageProvider/LanguageProvider.js +4 -2
- package/dist/parts/Markdown/Markdown.d.ts +2 -0
- package/dist/parts/Markdown/Markdown.js +7 -0
- package/dist/parts/Markdown/SanitizeMarkdownVirtualDom.d.ts +2 -0
- package/dist/parts/Markdown/SanitizeMarkdownVirtualDom.js +30 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { activate } from './parts/Activation/Activation.ts';
|
|
2
2
|
export { getColorThemeNames } from './parts/ColorTheme/ColorTheme.ts';
|
|
3
|
+
export { markdownToVirtualDom } from './parts/Markdown/Markdown.ts';
|
|
3
4
|
export { getAccessToken, type GetAccessTokenOptions } from './parts/Authentication/Authentication.ts';
|
|
4
5
|
export { createElectronWebContentsView } from './parts/ElectronWebContentsView/ElectronWebContentsView.ts';
|
|
5
6
|
export { executeCommand } from './parts/ExecuteCommand/ExecuteCommand.ts';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { activate } from "./parts/Activation/Activation.js";
|
|
2
2
|
export { getColorThemeNames } from "./parts/ColorTheme/ColorTheme.js";
|
|
3
|
+
export { markdownToVirtualDom } from "./parts/Markdown/Markdown.js";
|
|
3
4
|
export { getAccessToken } from "./parts/Authentication/Authentication.js";
|
|
4
5
|
export { createElectronWebContentsView } from "./parts/ElectronWebContentsView/ElectronWebContentsView.js";
|
|
5
6
|
export { executeCommand } from "./parts/ExecuteCommand/ExecuteCommand.js";
|
|
@@ -26,6 +26,9 @@ export interface DocumentSymbolProvider extends LanguageProvider {
|
|
|
26
26
|
export declare const executeLanguageProvider: (kind: string, methodName: string, textDocument: {
|
|
27
27
|
readonly languageId: string;
|
|
28
28
|
}, ...args: readonly unknown[]) => Promise<unknown>;
|
|
29
|
+
export declare const executeSourceActionProvider: (textDocument: {
|
|
30
|
+
readonly languageId: string;
|
|
31
|
+
}, kind: string) => Promise<unknown>;
|
|
29
32
|
export declare const executeOrganizeImportsProvider: (textDocument: {
|
|
30
33
|
readonly languageId: string;
|
|
31
34
|
}) => Promise<unknown>;
|
|
@@ -45,7 +45,7 @@ export const executeLanguageProvider = async (kind, methodName, textDocument, ..
|
|
|
45
45
|
}
|
|
46
46
|
return method(textDocument, ...args);
|
|
47
47
|
};
|
|
48
|
-
export const
|
|
48
|
+
export const executeSourceActionProvider = async (textDocument, kind) => {
|
|
49
49
|
const provider = getProvider('code action', textDocument.languageId);
|
|
50
50
|
if (!provider) {
|
|
51
51
|
throw new ExtensionApiError(`No code action provider found for ${textDocument.languageId}`);
|
|
@@ -55,12 +55,13 @@ export const executeOrganizeImportsProvider = async (textDocument) => {
|
|
|
55
55
|
if (!Array.isArray(actions)) {
|
|
56
56
|
throw new ExtensionApiError('invalid code action result: code actions must be of type array');
|
|
57
57
|
}
|
|
58
|
-
const action = actions.find((candidate) => candidate && typeof candidate === 'object' && candidate.kind ===
|
|
58
|
+
const action = actions.find((candidate) => candidate && typeof candidate === 'object' && candidate.kind === kind);
|
|
59
59
|
if (!action || typeof action.execute !== 'function') {
|
|
60
60
|
return [];
|
|
61
61
|
}
|
|
62
62
|
return action.execute(textDocument);
|
|
63
63
|
};
|
|
64
|
+
export const executeOrganizeImportsProvider = (textDocument) => executeSourceActionProvider(textDocument, 'source.organizeImports');
|
|
64
65
|
export const registerBraceCompletionProvider = (provider) => registerProvider('brace completion', provider, ['provideBraceCompletion']);
|
|
65
66
|
export const registerClosingTagProvider = (provider) => registerProvider('closing tag', provider, ['provideClosingTag']);
|
|
66
67
|
export const registerCodeActionsProvider = (provider) => registerProvider('code action', provider, ['provideCodeActions']);
|
|
@@ -76,6 +77,7 @@ export const registerTypeDefinitionProvider = (provider) => registerProvider('ty
|
|
|
76
77
|
const commandMap = {
|
|
77
78
|
'ExtensionApi.executeLanguageProvider': executeLanguageProvider,
|
|
78
79
|
'ExtensionApi.executeOrganizeImportsProvider': executeOrganizeImportsProvider,
|
|
80
|
+
'ExtensionApi.executeSourceActionProvider': executeSourceActionProvider,
|
|
79
81
|
};
|
|
80
82
|
export const resetLanguageProviderRegistry = () => {
|
|
81
83
|
for (const kind of Object.keys(providers)) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { RendererWorker } from '@lvce-editor/rpc-registry';
|
|
2
|
+
import { sanitizeMarkdownVirtualDom } from "./SanitizeMarkdownVirtualDom.js";
|
|
3
|
+
export const markdownToVirtualDom = async (markdown) => {
|
|
4
|
+
const html = await RendererWorker.invoke('Markdown.renderMarkdown', markdown);
|
|
5
|
+
const nodes = (await RendererWorker.invoke('Markdown.getVirtualDom', html));
|
|
6
|
+
return sanitizeMarkdownVirtualDom(nodes);
|
|
7
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { VirtualDomElements } from '@lvce-editor/virtual-dom-worker';
|
|
2
|
+
const allowedHrefProtocols = new Set(['http', 'https', 'mailto', 'tel']);
|
|
3
|
+
const allowedSrcProtocols = new Set(['http', 'https']);
|
|
4
|
+
const protocolPattern = /^([a-z][a-z\d+.-]*):/i;
|
|
5
|
+
const isAllowedUrl = (value, allowedProtocols) => {
|
|
6
|
+
const normalizedValue = [...value]
|
|
7
|
+
.filter((character) => {
|
|
8
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
9
|
+
return codePoint > 32 && codePoint !== 127;
|
|
10
|
+
})
|
|
11
|
+
.join('');
|
|
12
|
+
const protocol = protocolPattern.exec(normalizedValue)?.[1]?.toLowerCase();
|
|
13
|
+
return !protocol || allowedProtocols.has(protocol);
|
|
14
|
+
};
|
|
15
|
+
export const sanitizeMarkdownVirtualDom = (nodes) => {
|
|
16
|
+
return nodes.map((node) => {
|
|
17
|
+
const sanitizedNode = { ...node };
|
|
18
|
+
if (typeof sanitizedNode.href === 'string' && !isAllowedUrl(sanitizedNode.href, allowedHrefProtocols)) {
|
|
19
|
+
delete sanitizedNode.href;
|
|
20
|
+
}
|
|
21
|
+
if (sanitizedNode.type === VirtualDomElements.A && typeof sanitizedNode.href === 'string') {
|
|
22
|
+
sanitizedNode.target = '_blank';
|
|
23
|
+
sanitizedNode.rel = 'noopener noreferrer';
|
|
24
|
+
}
|
|
25
|
+
if (typeof sanitizedNode.src === 'string' && !isAllowedUrl(sanitizedNode.src, allowedSrcProtocols)) {
|
|
26
|
+
delete sanitizedNode.src;
|
|
27
|
+
}
|
|
28
|
+
return sanitizedNode;
|
|
29
|
+
});
|
|
30
|
+
};
|