@workbench-kit/shell-react 0.0.2-prototype.0.2.17 → 0.0.2-prototype.0.2.19
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/package.json +9 -8
- package/src/extensions/builtin/accounts/src/index.ts +13 -0
- package/src/extensions/builtin/accounts/workbench.extension.json +45 -0
- package/src/extensions/builtin/chat/src/index.ts +40 -0
- package/src/extensions/builtin/chat/workbench.extension.json +66 -0
- package/src/extensions/builtin/commands/src/command-inspector-editor-host.ts +79 -0
- package/src/extensions/builtin/commands/src/index.ts +65 -0
- package/src/extensions/builtin/commands/workbench.extension.json +64 -0
- package/src/extensions/builtin/editor/src/index.ts +95 -0
- package/src/extensions/builtin/editor/src/missing-resource-editor-host.ts +58 -0
- package/src/extensions/builtin/editor/src/resource-uri.ts +16 -0
- package/src/extensions/builtin/editor/src/text-editor-host.ts +86 -0
- package/src/extensions/builtin/editor/workbench.extension.json +32 -0
- package/src/extensions/builtin/explorer/src/index.ts +466 -0
- package/src/extensions/builtin/explorer/workbench.extension.json +132 -0
- package/src/extensions/builtin/extensions/src/index.ts +28 -0
- package/src/extensions/builtin/extensions/workbench.extension.json +53 -0
- package/src/extensions/builtin/keybindings/src/index.ts +6 -0
- package/src/extensions/builtin/keybindings/workbench.extension.json +21 -0
- package/src/extensions/builtin/search/src/index.ts +22 -0
- package/src/extensions/builtin/search/workbench.extension.json +43 -0
- package/src/extensions/builtin/settings/src/index.ts +23 -0
- package/src/extensions/builtin/settings/workbench.extension.json +41 -0
- package/src/extensions/builtin/workspace/src/index.ts +12 -0
- package/src/extensions/builtin/workspace/workbench.extension.json +37 -0
- package/src/extensions/builtin-extensions.ts +591 -0
- package/src/extensions/management-model.ts +41 -35
- package/src/extensions/use-extension-management.ts +11 -4
- package/src/index.ts +2 -0
- package/src/shell/provider.tsx +6 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workbench-kit/shell-react",
|
|
3
|
-
"version": "0.0.2-prototype.0.2.
|
|
3
|
+
"version": "0.0.2-prototype.0.2.19",
|
|
4
4
|
"private": false,
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css"
|
|
@@ -24,13 +24,14 @@
|
|
|
24
24
|
"@xyflow/react": "^12.11.2",
|
|
25
25
|
"jsonata": "^2.2.0",
|
|
26
26
|
"react-table-mapping": "^1.0.3",
|
|
27
|
-
"@workbench-kit/react": "0.0.2-prototype.0.2.
|
|
28
|
-
"@workbench-kit/
|
|
29
|
-
"@workbench-kit/
|
|
30
|
-
"@workbench-kit/
|
|
31
|
-
"@workbench-kit/workbench-core": "0.0.2-prototype.0.2.
|
|
32
|
-
"@workbench-kit/
|
|
33
|
-
"@workbench-kit/workspace": "0.0.2-prototype.0.2.
|
|
27
|
+
"@workbench-kit/react": "0.0.2-prototype.0.2.19",
|
|
28
|
+
"@workbench-kit/field-remap": "0.0.2-prototype.0.2.19",
|
|
29
|
+
"@workbench-kit/tokens": "0.0.2-prototype.0.2.19",
|
|
30
|
+
"@workbench-kit/workbench-config": "0.0.2-prototype.0.2.19",
|
|
31
|
+
"@workbench-kit/workbench-core": "0.0.2-prototype.0.2.19",
|
|
32
|
+
"@workbench-kit/workbench-extension-sdk": "0.0.2-prototype.0.2.19",
|
|
33
|
+
"@workbench-kit/workspace": "0.0.2-prototype.0.2.19",
|
|
34
|
+
"@workbench-kit/platform": "0.0.2-prototype.0.2.19"
|
|
34
35
|
},
|
|
35
36
|
"peerDependencies": {
|
|
36
37
|
"react": "^19.0.0",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { WORKBENCH_AUTH_CAPABILITY_ID, type WorkbenchAuthProvider } from '@workbench-kit/platform';
|
|
2
|
+
import type { ExtensionContext } from '@workbench-kit/workbench-extension-sdk';
|
|
3
|
+
|
|
4
|
+
export const EXTENSION_ID = 'workbench-kit.builtin.accounts' as const;
|
|
5
|
+
|
|
6
|
+
export const MANAGE_ACCOUNTS_COMMAND_ID = 'workbench-kit.builtin.accounts.manage' as const;
|
|
7
|
+
|
|
8
|
+
export function activate(context: ExtensionContext): void {
|
|
9
|
+
context.commands.registerCommand(MANAGE_ACCOUNTS_COMMAND_ID, () => ({
|
|
10
|
+
authCapabilityAvailable:
|
|
11
|
+
context.getCapability<WorkbenchAuthProvider>(WORKBENCH_AUTH_CAPABILITY_ID) !== undefined,
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "workbench-kit.builtin.accounts",
|
|
4
|
+
"name": "builtin-accounts",
|
|
5
|
+
"displayName": "Accounts",
|
|
6
|
+
"version": "0.0.0",
|
|
7
|
+
"publisher": "workbench-kit",
|
|
8
|
+
"engines": {
|
|
9
|
+
"workbench": "^0.0.0",
|
|
10
|
+
"extensionApi": "^0.0.0"
|
|
11
|
+
},
|
|
12
|
+
"activationEvents": ["onStartup"],
|
|
13
|
+
"capabilities": {
|
|
14
|
+
"requires": ["workbench.auth"]
|
|
15
|
+
},
|
|
16
|
+
"contributes": {
|
|
17
|
+
"commands": [
|
|
18
|
+
{
|
|
19
|
+
"command": "workbench-kit.builtin.accounts.manage",
|
|
20
|
+
"title": "Manage Accounts",
|
|
21
|
+
"category": "Accounts"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"menus": {
|
|
25
|
+
"status/account": [
|
|
26
|
+
{
|
|
27
|
+
"command": "workbench-kit.builtin.accounts.manage",
|
|
28
|
+
"group": "account",
|
|
29
|
+
"order": 1
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"configuration": {
|
|
34
|
+
"properties": {
|
|
35
|
+
"workbench.accounts.enabled": {
|
|
36
|
+
"type": "boolean",
|
|
37
|
+
"default": true,
|
|
38
|
+
"scope": "application",
|
|
39
|
+
"description": "Enable the workbench account entry point."
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"permissions": ["account.read"]
|
|
45
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ExtensionContext } from '@workbench-kit/workbench-extension-sdk';
|
|
2
|
+
|
|
3
|
+
export const EXTENSION_ID = 'workbench-kit.builtin.chat' as const;
|
|
4
|
+
|
|
5
|
+
export const CHATTING_VIEW_ID = 'workbench-kit.builtin.chat.chatting' as const;
|
|
6
|
+
export const AI_CHAT_VIEW_ID = 'workbench-kit.builtin.chat.aiChat' as const;
|
|
7
|
+
export const CHAT_VIEW_RENDER_KIND = 'workbench-kit.builtin.chat.view' as const;
|
|
8
|
+
|
|
9
|
+
export type BuiltinChatViewMode = 'aiChat' | 'chatting';
|
|
10
|
+
|
|
11
|
+
export interface BuiltinChatViewRenderData {
|
|
12
|
+
readonly kind: typeof CHAT_VIEW_RENDER_KIND;
|
|
13
|
+
readonly mode: BuiltinChatViewMode;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function activate(context: ExtensionContext): void {
|
|
17
|
+
context.views.registerViewProvider({
|
|
18
|
+
viewId: CHATTING_VIEW_ID,
|
|
19
|
+
resolveViewHost: () => ({
|
|
20
|
+
dispose() {},
|
|
21
|
+
render: (): BuiltinChatViewRenderData => ({
|
|
22
|
+
kind: CHAT_VIEW_RENDER_KIND,
|
|
23
|
+
mode: 'chatting',
|
|
24
|
+
}),
|
|
25
|
+
title: 'Chat',
|
|
26
|
+
}),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
context.views.registerViewProvider({
|
|
30
|
+
viewId: AI_CHAT_VIEW_ID,
|
|
31
|
+
resolveViewHost: () => ({
|
|
32
|
+
dispose() {},
|
|
33
|
+
render: (): BuiltinChatViewRenderData => ({
|
|
34
|
+
kind: CHAT_VIEW_RENDER_KIND,
|
|
35
|
+
mode: 'aiChat',
|
|
36
|
+
}),
|
|
37
|
+
title: 'AI Chat',
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "workbench-kit.builtin.chat",
|
|
4
|
+
"name": "builtin-chat",
|
|
5
|
+
"displayName": "Chat",
|
|
6
|
+
"version": "0.0.0",
|
|
7
|
+
"publisher": "workbench-kit",
|
|
8
|
+
"engines": {
|
|
9
|
+
"workbench": "^0.0.0",
|
|
10
|
+
"extensionApi": "^0.0.0"
|
|
11
|
+
},
|
|
12
|
+
"activationEvents": [
|
|
13
|
+
"onView:workbench-kit.builtin.chat.chatting",
|
|
14
|
+
"onView:workbench-kit.builtin.chat.aiChat"
|
|
15
|
+
],
|
|
16
|
+
"contributes": {
|
|
17
|
+
"viewContainers": {
|
|
18
|
+
"activitybar": [
|
|
19
|
+
{
|
|
20
|
+
"id": "chatting",
|
|
21
|
+
"title": "Chat",
|
|
22
|
+
"icon": "comment-discussion",
|
|
23
|
+
"order": 30
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "aiChat",
|
|
27
|
+
"title": "AI Chat",
|
|
28
|
+
"icon": "sparkle",
|
|
29
|
+
"order": 40
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"activities": [
|
|
34
|
+
{
|
|
35
|
+
"id": "workbench-kit.builtin.chat.chatting.activity",
|
|
36
|
+
"viewContainerId": "chatting",
|
|
37
|
+
"icon": "comment-discussion",
|
|
38
|
+
"title": "Chat",
|
|
39
|
+
"order": 30,
|
|
40
|
+
"when": "workbench.permissions.canUseChat"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "workbench-kit.builtin.chat.aiChat.activity",
|
|
44
|
+
"viewContainerId": "aiChat",
|
|
45
|
+
"icon": "sparkle",
|
|
46
|
+
"title": "AI Chat",
|
|
47
|
+
"order": 40,
|
|
48
|
+
"when": "workbench.permissions.canUseChat"
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"views": {
|
|
52
|
+
"chatting": [
|
|
53
|
+
{
|
|
54
|
+
"id": "workbench-kit.builtin.chat.chatting",
|
|
55
|
+
"name": "Chat"
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
"aiChat": [
|
|
59
|
+
{
|
|
60
|
+
"id": "workbench-kit.builtin.chat.aiChat",
|
|
61
|
+
"name": "AI Chat"
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { EditorHost } from '@workbench-kit/workbench-extension-sdk';
|
|
2
|
+
|
|
3
|
+
const COMMAND_INSPECTOR_URI_PREFIX = 'workbench://command/inspect/' as const;
|
|
4
|
+
|
|
5
|
+
export const COMMAND_INSPECTOR_EDITOR_ID = 'workbench-kit.builtin.commands.inspector' as const;
|
|
6
|
+
export const COMMAND_INSPECTOR_EDITOR_HOST_RENDER_KIND =
|
|
7
|
+
'workbench-kit.builtin.commands/inspector' as const;
|
|
8
|
+
|
|
9
|
+
export interface CommandInspectorEditorHostRenderData {
|
|
10
|
+
readonly commandId: string;
|
|
11
|
+
readonly kind: typeof COMMAND_INSPECTOR_EDITOR_HOST_RENDER_KIND;
|
|
12
|
+
readonly resourceUri: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface CommandInspectorEditorHostOptions {
|
|
16
|
+
readonly resourceUri: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class CommandInspectorEditorHost implements EditorHost {
|
|
20
|
+
readonly title: string;
|
|
21
|
+
dirty = false;
|
|
22
|
+
onDidChangeDirty?: (dirty: boolean) => void;
|
|
23
|
+
|
|
24
|
+
private readonly commandId: string;
|
|
25
|
+
|
|
26
|
+
constructor(private readonly options: CommandInspectorEditorHostOptions) {
|
|
27
|
+
const commandId = parseCommandInspectorUri(options.resourceUri);
|
|
28
|
+
if (!commandId) {
|
|
29
|
+
throw new Error(`Invalid command inspector resource URI: ${options.resourceUri}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this.commandId = commandId;
|
|
33
|
+
this.title = commandId;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
dispose(): void {
|
|
37
|
+
this.onDidChangeDirty = undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
render(): CommandInspectorEditorHostRenderData {
|
|
41
|
+
return {
|
|
42
|
+
commandId: this.commandId,
|
|
43
|
+
kind: COMMAND_INSPECTOR_EDITOR_HOST_RENDER_KIND,
|
|
44
|
+
resourceUri: this.options.resourceUri,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function parseCommandInspectorUri(resourceUri: string): string | undefined {
|
|
50
|
+
if (!resourceUri.startsWith(COMMAND_INSPECTOR_URI_PREFIX)) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const encodedId = resourceUri.slice(COMMAND_INSPECTOR_URI_PREFIX.length);
|
|
55
|
+
if (!encodedId) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
return decodeURIComponent(encodedId);
|
|
61
|
+
} catch {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function isCommandInspectorEditorHostRenderData(
|
|
67
|
+
value: unknown,
|
|
68
|
+
): value is CommandInspectorEditorHostRenderData {
|
|
69
|
+
if (typeof value !== 'object' || value === null) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const candidate = value as Partial<CommandInspectorEditorHostRenderData>;
|
|
74
|
+
return (
|
|
75
|
+
candidate.kind === COMMAND_INSPECTOR_EDITOR_HOST_RENDER_KIND &&
|
|
76
|
+
typeof candidate.commandId === 'string' &&
|
|
77
|
+
typeof candidate.resourceUri === 'string'
|
|
78
|
+
);
|
|
79
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ExtensionContext } from '@workbench-kit/workbench-extension-sdk';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
COMMAND_INSPECTOR_EDITOR_ID,
|
|
5
|
+
CommandInspectorEditorHost,
|
|
6
|
+
parseCommandInspectorUri,
|
|
7
|
+
} from './command-inspector-editor-host.js';
|
|
8
|
+
|
|
9
|
+
export const EXTENSION_ID = 'workbench-kit.builtin.commands' as const;
|
|
10
|
+
export const COMMANDS_VIEW_ID = 'workbench-kit.builtin.commands.panel' as const;
|
|
11
|
+
export const COMMANDS_VIEW_RENDER_KIND = 'workbench-kit.builtin.commands.view' as const;
|
|
12
|
+
export const FOCUS_COMMAND_ID = 'workbench-kit.builtin.commands.focus' as const;
|
|
13
|
+
export const REFRESH_COMMAND_ID = 'workbench-kit.builtin.commands.refresh' as const;
|
|
14
|
+
|
|
15
|
+
export interface BuiltinCommandsViewRenderData {
|
|
16
|
+
readonly kind: typeof COMMANDS_VIEW_RENDER_KIND;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export {
|
|
20
|
+
COMMAND_INSPECTOR_EDITOR_HOST_RENDER_KIND,
|
|
21
|
+
COMMAND_INSPECTOR_EDITOR_ID,
|
|
22
|
+
CommandInspectorEditorHost,
|
|
23
|
+
isCommandInspectorEditorHostRenderData,
|
|
24
|
+
parseCommandInspectorUri,
|
|
25
|
+
type CommandInspectorEditorHostRenderData,
|
|
26
|
+
} from './command-inspector-editor-host.js';
|
|
27
|
+
|
|
28
|
+
export function activate(context: ExtensionContext): void {
|
|
29
|
+
context.editorResolvers.registerResolver({
|
|
30
|
+
id: 'command-inspector',
|
|
31
|
+
priority: 20,
|
|
32
|
+
canResolve: ({ resourceUri }) => parseCommandInspectorUri(resourceUri) !== undefined,
|
|
33
|
+
resolve: () => COMMAND_INSPECTOR_EDITOR_ID,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
context.editorHostFactories.registerFactory({
|
|
37
|
+
id: 'workbench-kit.builtin.commands.inspectorHost',
|
|
38
|
+
priority: 20,
|
|
39
|
+
canCreate: ({ editorId }) => editorId === COMMAND_INSPECTOR_EDITOR_ID,
|
|
40
|
+
create: ({ resourceUri }) => {
|
|
41
|
+
return new CommandInspectorEditorHost({ resourceUri });
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
context.commands.registerCommand(FOCUS_COMMAND_ID, () => ({
|
|
46
|
+
focused: true,
|
|
47
|
+
viewId: COMMANDS_VIEW_ID,
|
|
48
|
+
}));
|
|
49
|
+
|
|
50
|
+
context.commands.registerCommand(REFRESH_COMMAND_ID, () => ({
|
|
51
|
+
refreshed: true,
|
|
52
|
+
viewId: COMMANDS_VIEW_ID,
|
|
53
|
+
}));
|
|
54
|
+
|
|
55
|
+
context.views.registerViewProvider({
|
|
56
|
+
viewId: COMMANDS_VIEW_ID,
|
|
57
|
+
resolveViewHost: () => ({
|
|
58
|
+
dispose() {},
|
|
59
|
+
render: (): BuiltinCommandsViewRenderData => ({
|
|
60
|
+
kind: COMMANDS_VIEW_RENDER_KIND,
|
|
61
|
+
}),
|
|
62
|
+
title: 'Commands',
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "workbench-kit.builtin.commands",
|
|
4
|
+
"name": "builtin-commands",
|
|
5
|
+
"displayName": "Commands",
|
|
6
|
+
"version": "0.0.0",
|
|
7
|
+
"publisher": "workbench-kit",
|
|
8
|
+
"engines": {
|
|
9
|
+
"workbench": "^0.0.0",
|
|
10
|
+
"extensionApi": "^0.0.0"
|
|
11
|
+
},
|
|
12
|
+
"activationEvents": ["onView:workbench-kit.builtin.commands.panel"],
|
|
13
|
+
"contributes": {
|
|
14
|
+
"commands": [
|
|
15
|
+
{
|
|
16
|
+
"command": "workbench-kit.builtin.commands.focus",
|
|
17
|
+
"title": "Focus Commands Sidebar",
|
|
18
|
+
"category": "Workbench"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"command": "workbench-kit.builtin.commands.refresh",
|
|
22
|
+
"title": "Refresh Command Registry",
|
|
23
|
+
"category": "Workbench"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"viewContainers": {
|
|
27
|
+
"activitybar": [
|
|
28
|
+
{
|
|
29
|
+
"id": "commands",
|
|
30
|
+
"title": "Commands",
|
|
31
|
+
"icon": "terminal",
|
|
32
|
+
"order": 25
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
"activities": [
|
|
37
|
+
{
|
|
38
|
+
"id": "workbench-kit.builtin.commands.activity",
|
|
39
|
+
"viewContainerId": "commands",
|
|
40
|
+
"icon": "terminal",
|
|
41
|
+
"title": "Commands",
|
|
42
|
+
"order": 25,
|
|
43
|
+
"when": "workbench.permissions.canManageCommands"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"views": {
|
|
47
|
+
"commands": [
|
|
48
|
+
{
|
|
49
|
+
"id": "workbench-kit.builtin.commands.panel",
|
|
50
|
+
"name": "Commands"
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
"menus": {
|
|
55
|
+
"view/title": [
|
|
56
|
+
{
|
|
57
|
+
"command": "workbench-kit.builtin.commands.refresh",
|
|
58
|
+
"group": "navigation",
|
|
59
|
+
"when": "view == workbench-kit.builtin.commands.panel"
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { ExtensionContext } from '@workbench-kit/workbench-extension-sdk';
|
|
2
|
+
|
|
3
|
+
import { MissingResourceEditorHost } from './missing-resource-editor-host.js';
|
|
4
|
+
import { isWorkspaceFileResourceUri } from './resource-uri.js';
|
|
5
|
+
import { TextEditorHost } from './text-editor-host.js';
|
|
6
|
+
|
|
7
|
+
export const EXTENSION_ID = 'workbench-kit.builtin.editor' as const;
|
|
8
|
+
export const TEXT_EDITOR_ID = 'workbench-kit.builtin.editor.text' as const;
|
|
9
|
+
export const TEXT_EDITOR_HOST_FACTORY_ID = 'workbench-kit.builtin.editor.textHost' as const;
|
|
10
|
+
export const MARKDOWN_PREVIEW_PROVIDER_ID =
|
|
11
|
+
'workbench-kit.builtin.editor.markdown-preview' as const;
|
|
12
|
+
export const MARKDOWN_PREVIEW_RENDER_KIND =
|
|
13
|
+
'workbench-kit.builtin.editor.markdown-preview' as const;
|
|
14
|
+
|
|
15
|
+
export interface BuiltinEditorMarkdownPreviewRenderData {
|
|
16
|
+
readonly kind: typeof MARKDOWN_PREVIEW_RENDER_KIND;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export {
|
|
20
|
+
MISSING_RESOURCE_EDITOR_HOST_RENDER_KIND,
|
|
21
|
+
MissingResourceEditorHost,
|
|
22
|
+
isMissingResourceEditorHostRenderData,
|
|
23
|
+
type MissingResourceEditorHostRenderData,
|
|
24
|
+
} from './missing-resource-editor-host.js';
|
|
25
|
+
export {
|
|
26
|
+
TEXT_EDITOR_HOST_RENDER_KIND,
|
|
27
|
+
TextEditorHost,
|
|
28
|
+
isTextEditorHostRenderData,
|
|
29
|
+
type TextEditorHostRenderData,
|
|
30
|
+
} from './text-editor-host.js';
|
|
31
|
+
|
|
32
|
+
function isMarkdownDocument(path: string, mimeType: string | undefined): boolean {
|
|
33
|
+
const normalizedPath = path.replace(/\\/g, '/').toLowerCase();
|
|
34
|
+
const normalizedMime = mimeType?.toLowerCase();
|
|
35
|
+
return (
|
|
36
|
+
normalizedPath.endsWith('.md') ||
|
|
37
|
+
normalizedPath.endsWith('.mdx') ||
|
|
38
|
+
normalizedMime === 'text/markdown'
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function activate(context: ExtensionContext): void {
|
|
43
|
+
context.editorDocumentViews.registerProvider({
|
|
44
|
+
id: MARKDOWN_PREVIEW_PROVIDER_ID,
|
|
45
|
+
kind: 'preview',
|
|
46
|
+
label: 'Preview',
|
|
47
|
+
priority: 5,
|
|
48
|
+
filenamePatterns: ['*.md', '*.mdx'],
|
|
49
|
+
mimeTypes: ['text/markdown'],
|
|
50
|
+
matches: (document) => isMarkdownDocument(document.path, document.mimeType),
|
|
51
|
+
render: (): BuiltinEditorMarkdownPreviewRenderData => ({
|
|
52
|
+
kind: MARKDOWN_PREVIEW_RENDER_KIND,
|
|
53
|
+
}),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
context.editorResolvers.registerResolver({
|
|
57
|
+
id: 'workspace-file',
|
|
58
|
+
priority: 10,
|
|
59
|
+
canResolve: ({ resourceUri }) => isWorkspaceFileResourceUri(resourceUri),
|
|
60
|
+
resolve: () => TEXT_EDITOR_ID,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
context.editorHostFactories.registerFactory({
|
|
64
|
+
id: TEXT_EDITOR_HOST_FACTORY_ID,
|
|
65
|
+
priority: 10,
|
|
66
|
+
canCreate: ({ editorId }) => editorId === TEXT_EDITOR_ID,
|
|
67
|
+
create: ({ resource, resourceMissing, resourceUri }) => {
|
|
68
|
+
if (resourceMissing) {
|
|
69
|
+
return new MissingResourceEditorHost({ resourceUri });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const initialContent = readWorkspaceFileContent(resource);
|
|
73
|
+
const mimeType = readWorkspaceFileMimeType(resource);
|
|
74
|
+
return new TextEditorHost({ initialContent, mimeType, resourceUri });
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function readWorkspaceFileContent(resource: unknown): string | undefined {
|
|
80
|
+
if (typeof resource !== 'object' || resource === null) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const content = (resource as { content?: unknown }).content;
|
|
85
|
+
return typeof content === 'string' ? content : undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function readWorkspaceFileMimeType(resource: unknown): string | undefined {
|
|
89
|
+
if (typeof resource !== 'object' || resource === null) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const mimeType = (resource as { mimeType?: unknown }).mimeType;
|
|
94
|
+
return typeof mimeType === 'string' ? mimeType : undefined;
|
|
95
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { EditorHost } from '@workbench-kit/workbench-extension-sdk';
|
|
2
|
+
|
|
3
|
+
import { labelForWorkspaceFileResource } from './resource-uri.js';
|
|
4
|
+
|
|
5
|
+
export const MISSING_RESOURCE_EDITOR_HOST_RENDER_KIND =
|
|
6
|
+
'workbench-kit.builtin.editor/missing-resource' as const;
|
|
7
|
+
|
|
8
|
+
export interface MissingResourceEditorHostRenderData {
|
|
9
|
+
readonly kind: typeof MISSING_RESOURCE_EDITOR_HOST_RENDER_KIND;
|
|
10
|
+
readonly message: string;
|
|
11
|
+
readonly resourceUri: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface MissingResourceEditorHostOptions {
|
|
15
|
+
readonly message?: string | undefined;
|
|
16
|
+
readonly resourceUri: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class MissingResourceEditorHost implements EditorHost {
|
|
20
|
+
readonly title: string;
|
|
21
|
+
dirty = false;
|
|
22
|
+
onDidChangeDirty?: (dirty: boolean) => void;
|
|
23
|
+
|
|
24
|
+
constructor(private readonly options: MissingResourceEditorHostOptions) {
|
|
25
|
+
this.title = getResourceLabel(options.resourceUri);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
dispose(): void {
|
|
29
|
+
this.onDidChangeDirty = undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
render(): MissingResourceEditorHostRenderData {
|
|
33
|
+
return {
|
|
34
|
+
kind: MISSING_RESOURCE_EDITOR_HOST_RENDER_KIND,
|
|
35
|
+
message: this.options.message ?? 'The file was deleted or moved.',
|
|
36
|
+
resourceUri: this.options.resourceUri,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function isMissingResourceEditorHostRenderData(
|
|
42
|
+
value: unknown,
|
|
43
|
+
): value is MissingResourceEditorHostRenderData {
|
|
44
|
+
if (typeof value !== 'object' || value === null) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const candidate = value as Partial<MissingResourceEditorHostRenderData>;
|
|
49
|
+
return (
|
|
50
|
+
candidate.kind === MISSING_RESOURCE_EDITOR_HOST_RENDER_KIND &&
|
|
51
|
+
typeof candidate.resourceUri === 'string' &&
|
|
52
|
+
typeof candidate.message === 'string'
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getResourceLabel(resourceUri: string): string {
|
|
57
|
+
return labelForWorkspaceFileResource(resourceUri);
|
|
58
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { parseWorkspaceResourceUri } from '@workbench-kit/workspace';
|
|
2
|
+
|
|
3
|
+
export function isWorkspaceFileResourceUri(resourceUri: string): boolean {
|
|
4
|
+
return parseWorkspaceResourceUri(resourceUri)?.kind === 'file';
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function pathForWorkspaceFileResource(resourceUri: string): string | undefined {
|
|
8
|
+
const parsed = parseWorkspaceResourceUri(resourceUri);
|
|
9
|
+
return parsed?.kind === 'file' ? parsed.path : undefined;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function labelForWorkspaceFileResource(resourceUri: string): string {
|
|
13
|
+
const path = pathForWorkspaceFileResource(resourceUri) ?? resourceUri;
|
|
14
|
+
const segments = path.split('/');
|
|
15
|
+
return segments[segments.length - 1] || path;
|
|
16
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { EditorHost } from '@workbench-kit/workbench-extension-sdk';
|
|
2
|
+
|
|
3
|
+
import { labelForWorkspaceFileResource } from './resource-uri.js';
|
|
4
|
+
|
|
5
|
+
export const TEXT_EDITOR_HOST_RENDER_KIND = 'workbench-kit.builtin.editor/text' as const;
|
|
6
|
+
|
|
7
|
+
export interface TextEditorHostRenderData {
|
|
8
|
+
readonly initialContent: string;
|
|
9
|
+
readonly kind: typeof TEXT_EDITOR_HOST_RENDER_KIND;
|
|
10
|
+
readonly mimeType?: string | undefined;
|
|
11
|
+
readonly resourceUri: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface TextEditorHostOptions {
|
|
15
|
+
readonly initialContent?: string | undefined;
|
|
16
|
+
readonly mimeType?: string | undefined;
|
|
17
|
+
readonly resourceUri: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class TextEditorHost implements EditorHost {
|
|
21
|
+
dirty = false;
|
|
22
|
+
readonly title: string;
|
|
23
|
+
onDidChangeDirty?: (dirty: boolean) => void;
|
|
24
|
+
private content: string;
|
|
25
|
+
|
|
26
|
+
constructor(private readonly options: TextEditorHostOptions) {
|
|
27
|
+
this.title = getResourceLabel(options.resourceUri);
|
|
28
|
+
this.content = options.initialContent ?? createPlaceholderContent(options.resourceUri);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getContent(): string {
|
|
32
|
+
return this.content;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setContent(nextContent: string): void {
|
|
36
|
+
this.content = nextContent;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
markDirty(): void {
|
|
40
|
+
this.setDirty(true);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
setDirty(nextDirty: boolean): void {
|
|
44
|
+
if (this.dirty === nextDirty) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.dirty = nextDirty;
|
|
49
|
+
this.onDidChangeDirty?.(nextDirty);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
dispose(): void {
|
|
53
|
+
this.onDidChangeDirty = undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
render(): TextEditorHostRenderData {
|
|
57
|
+
return {
|
|
58
|
+
initialContent: this.content,
|
|
59
|
+
kind: TEXT_EDITOR_HOST_RENDER_KIND,
|
|
60
|
+
mimeType: this.options.mimeType,
|
|
61
|
+
resourceUri: this.options.resourceUri,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function isTextEditorHostRenderData(value: unknown): value is TextEditorHostRenderData {
|
|
67
|
+
if (typeof value !== 'object' || value === null) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const candidate = value as Partial<TextEditorHostRenderData>;
|
|
72
|
+
return (
|
|
73
|
+
candidate.kind === TEXT_EDITOR_HOST_RENDER_KIND &&
|
|
74
|
+
typeof candidate.resourceUri === 'string' &&
|
|
75
|
+
typeof candidate.initialContent === 'string'
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function getResourceLabel(resourceUri: string): string {
|
|
80
|
+
return labelForWorkspaceFileResource(resourceUri);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function createPlaceholderContent(resourceUri: string): string {
|
|
84
|
+
const label = getResourceLabel(resourceUri);
|
|
85
|
+
return `// ${label}\n// Opened from ${resourceUri}\n`;
|
|
86
|
+
}
|