@jiangzhongxi0322/messagechannel 1.0.0 → 1.0.2

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.
Files changed (70) hide show
  1. package/README.md +181 -0
  2. package/dist/messageChannel.d.ts +10 -0
  3. package/dist/{messageChennel.js → messageChannel.js} +25 -8
  4. package/examples/command-webview-sample/.eslintrc.js +23 -0
  5. package/examples/command-webview-sample/.vscode/extensions.json +9 -0
  6. package/examples/command-webview-sample/.vscode/launch.json +18 -0
  7. package/examples/command-webview-sample/.vscode/settings.json +3 -0
  8. package/examples/command-webview-sample/.vscode/tasks.json +20 -0
  9. package/examples/command-webview-sample/README.md +47 -0
  10. package/examples/command-webview-sample/demo.gif +0 -0
  11. package/examples/command-webview-sample/media/cat.gif +0 -0
  12. package/examples/command-webview-sample/media/jsconfig.json +22 -0
  13. package/examples/command-webview-sample/media/main.js +41 -0
  14. package/examples/command-webview-sample/media/reset.css +30 -0
  15. package/examples/command-webview-sample/media/vscode.css +91 -0
  16. package/examples/command-webview-sample/package-lock.json +2764 -0
  17. package/examples/command-webview-sample/package.json +51 -0
  18. package/examples/command-webview-sample/src/extension.ts +227 -0
  19. package/{src/messageChennel.ts → examples/command-webview-sample/src/messageChannel.ts} +34 -21
  20. package/examples/command-webview-sample/tsconfig.json +12 -0
  21. package/examples/publish-webview-sample/.eslintrc.js +20 -0
  22. package/examples/publish-webview-sample/.vscode/extensions.json +9 -0
  23. package/examples/publish-webview-sample/.vscode/launch.json +18 -0
  24. package/examples/publish-webview-sample/.vscode/settings.json +3 -0
  25. package/examples/publish-webview-sample/.vscode/tasks.json +20 -0
  26. package/examples/publish-webview-sample/README.md +24 -0
  27. package/examples/publish-webview-sample/media/main.css +54 -0
  28. package/examples/publish-webview-sample/media/main.js +100 -0
  29. package/examples/publish-webview-sample/media/reset.css +30 -0
  30. package/examples/publish-webview-sample/media/vscode.css +91 -0
  31. package/examples/publish-webview-sample/package-lock.json +2720 -0
  32. package/examples/publish-webview-sample/package.json +71 -0
  33. package/examples/publish-webview-sample/src/extension.ts +170 -0
  34. package/examples/publish-webview-sample/src/messageChannel.ts +264 -0
  35. package/examples/publish-webview-sample/tsconfig.json +12 -0
  36. package/examples/url-webview-sample/.eslintignore +1 -0
  37. package/examples/url-webview-sample/.eslintrc.js +20 -0
  38. package/examples/url-webview-sample/.vscode/extensions.json +9 -0
  39. package/examples/url-webview-sample/.vscode/launch.json +18 -0
  40. package/examples/url-webview-sample/.vscode/settings.json +3 -0
  41. package/examples/url-webview-sample/.vscode/tasks.json +20 -0
  42. package/examples/url-webview-sample/README.md +25 -0
  43. package/examples/url-webview-sample/documentation/example.png +0 -0
  44. package/examples/url-webview-sample/exampleFiles/example.cscratch +14 -0
  45. package/examples/url-webview-sample/exampleFiles/example.pawDraw +0 -0
  46. package/examples/url-webview-sample/exampleFiles/log/python-kaleido-case-api.exe.log +1 -0
  47. package/examples/url-webview-sample/exampleFiles/log/python-request.exe.log +1 -0
  48. package/examples/url-webview-sample/exampleFiles/pump/config/default.json +1 -0
  49. package/examples/url-webview-sample/exampleFiles/test_cases/log/output_202511181702.log +6 -0
  50. package/examples/url-webview-sample/media/catScratch.css +65 -0
  51. package/examples/url-webview-sample/media/catScratch.js +100 -0
  52. package/examples/url-webview-sample/media/paw-color.svg +21 -0
  53. package/examples/url-webview-sample/media/paw-outline.svg +21 -0
  54. package/examples/url-webview-sample/media/pawDraw.css +83 -0
  55. package/examples/url-webview-sample/media/pawDraw.js +266 -0
  56. package/examples/url-webview-sample/media/reset.css +30 -0
  57. package/examples/url-webview-sample/media/sand-dark.jpg +0 -0
  58. package/examples/url-webview-sample/media/sand.jpg +0 -0
  59. package/examples/url-webview-sample/media/vscode.css +91 -0
  60. package/examples/url-webview-sample/package-lock.json +2751 -0
  61. package/examples/url-webview-sample/package.json +64 -0
  62. package/examples/url-webview-sample/src/catScratchEditor.ts +215 -0
  63. package/examples/url-webview-sample/src/dispose.ts +37 -0
  64. package/examples/url-webview-sample/src/extension.ts +7 -0
  65. package/examples/url-webview-sample/src/messageChannel.ts +264 -0
  66. package/examples/url-webview-sample/src/util.ts +8 -0
  67. package/examples/url-webview-sample/tsconfig.json +13 -0
  68. package/package.json +3 -3
  69. package/src/messageChannel.ts +264 -0
  70. package/dist/messageChennel.d.ts +0 -15
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "publish-webview-sample",
3
+ "description": "Calico Colors - A Webview View API Sample",
4
+ "version": "0.1.8",
5
+ "publisher": "walker",
6
+ "private": true,
7
+ "license": "MIT",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/Microsoft/vscode-extension-samples"
11
+ },
12
+ "engines": {
13
+ "vscode": "^1.74.0"
14
+ },
15
+ "extensionKind": [
16
+ "ui",
17
+ "workspace"
18
+ ],
19
+ "categories": [
20
+ "Other"
21
+ ],
22
+ "activationEvents": [],
23
+ "main": "./out/extension.js",
24
+ "contributes": {
25
+ "views": {
26
+ "explorer": [
27
+ {
28
+ "type": "webview",
29
+ "id": "calicoColors.colorsView",
30
+ "name": "Calico Colors",
31
+ "icon": "media/icon.png"
32
+ }
33
+ ]
34
+ },
35
+ "commands": [
36
+ {
37
+ "command": "calicoColors.addColor",
38
+ "category": "Calico Colors",
39
+ "title": "Add Color"
40
+ },
41
+ {
42
+ "command": "calicoColors.clearColors",
43
+ "category": "Calico Colors",
44
+ "title": "Clear Colors",
45
+ "icon": "$(clear-all)"
46
+ }
47
+ ],
48
+ "menus": {
49
+ "view/title": [
50
+ {
51
+ "command": "calicoColors.clearColors",
52
+ "group": "navigation",
53
+ "when": "view == calicoColors.colorsView"
54
+ }
55
+ ]
56
+ }
57
+ },
58
+ "scripts": {
59
+ "vscode:prepublish": "npm run compile",
60
+ "compile": "tsc -p ./",
61
+ "lint": "eslint \"src/**/*.ts\"",
62
+ "watch": "tsc -w -p ./"
63
+ },
64
+ "devDependencies": {
65
+ "@types/vscode": "^1.73.0",
66
+ "@typescript-eslint/eslint-plugin": "^6.7.0",
67
+ "@typescript-eslint/parser": "^6.7.0",
68
+ "eslint": "^8.32.0",
69
+ "typescript": "^5.4.2"
70
+ }
71
+ }
@@ -0,0 +1,170 @@
1
+ import * as vscode from 'vscode';
2
+ import MessageChannel from './messageChannel';
3
+
4
+ const mc = MessageChannel();
5
+
6
+ export function activate(context: vscode.ExtensionContext) {
7
+
8
+ const provider = new ColorsViewProvider(context.extensionUri);
9
+
10
+ mc.initiator(ColorsViewProvider.viewType);
11
+
12
+ context.subscriptions.push(
13
+ vscode.window.registerWebviewViewProvider(ColorsViewProvider.viewType, provider));
14
+
15
+ context.subscriptions.push(
16
+ vscode.commands.registerCommand('calicoColors.addColor', () => {
17
+ provider.addColor();
18
+ }));
19
+
20
+ context.subscriptions.push(
21
+ vscode.commands.registerCommand('calicoColors.clearColors', () => {
22
+ provider.clearColors();
23
+ }));
24
+ }
25
+
26
+ class ColorsViewProvider implements vscode.WebviewViewProvider {
27
+
28
+ public static readonly viewType = 'calicoColors.colorsView';
29
+
30
+ private _view?: vscode.WebviewView;
31
+
32
+ constructor(
33
+ private readonly _extensionUri: vscode.Uri,
34
+ ) { }
35
+
36
+ public resolveWebviewView(
37
+ webviewView: vscode.WebviewView,
38
+ context: vscode.WebviewViewResolveContext,
39
+ _token: vscode.CancellationToken,
40
+ ) {
41
+ this._view = webviewView;
42
+ mc.setCarrier(webviewView.webview);
43
+ webviewView.webview.options = {
44
+ // Allow scripts in the webview
45
+ enableScripts: true,
46
+
47
+ localResourceRoots: [
48
+ this._extensionUri
49
+ ]
50
+ };
51
+
52
+ webviewView.webview.html = this._getHtmlForWebview(webviewView.webview);
53
+
54
+ webviewView.webview.onDidReceiveMessage(data => {
55
+ switch (data.type) {
56
+ case 'colorSelected':
57
+ {
58
+ vscode.window.activeTextEditor?.insertSnippet(new vscode.SnippetString(`#${data.value}`));
59
+ break;
60
+ }
61
+ }
62
+ });
63
+ }
64
+
65
+ public addColor() {
66
+ if (this._view) {
67
+ this._view.show?.(true); // `show` is not implemented in 1.49 but is for 1.50 insiders
68
+ this._view.webview.postMessage({ type: 'addColor' });
69
+ }
70
+ }
71
+
72
+ public clearColors() {
73
+ if (this._view) {
74
+ this._view.webview.postMessage({ type: 'clearColors' });
75
+ }
76
+ }
77
+
78
+ private _getHtmlForWebview(webview: vscode.Webview) {
79
+ // Get the local path to main script run in the webview, then convert it to a uri we can use in the webview.
80
+ const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'media', 'main.js'));
81
+
82
+ // Do the same for the stylesheet.
83
+ const styleResetUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'media', 'reset.css'));
84
+ const styleVSCodeUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'media', 'vscode.css'));
85
+ const styleMainUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'media', 'main.css'));
86
+
87
+ // Use a nonce to only allow a specific script to be run.
88
+ const nonce = getNonce();
89
+
90
+ return `<!DOCTYPE html>
91
+ <html lang="en">
92
+ <head>
93
+ <meta charset="UTF-8">
94
+
95
+ <!--
96
+ Use a content security policy to only allow loading styles from our extension directory,
97
+ and only allow scripts that have a specific nonce.
98
+ (See the 'webview-sample' extension sample for img-src content security policy examples)
99
+ -->
100
+ <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource}; script-src 'nonce-${nonce}';">
101
+
102
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
103
+
104
+ <link href="${styleResetUri}" rel="stylesheet">
105
+ <link href="${styleVSCodeUri}" rel="stylesheet">
106
+ <link href="${styleMainUri}" rel="stylesheet">
107
+
108
+ <title>Cat Colors</title>
109
+ </head>
110
+ <body>
111
+ <ul class="color-list">
112
+ </ul>
113
+
114
+
115
+ <div class="url-webview">
116
+ <h2>url-webview</h2>
117
+ <div class="send-message">
118
+ <input type="text" placeholder="请输入发送的数据" />
119
+ <button>发送</button>
120
+ </div>
121
+ <div class="response-message">发送对象反馈的数据:<div>暂无</div></div>
122
+ </div>
123
+
124
+ <div class="command-webview">
125
+ <h2>command-webview</h2>
126
+ <div class="send-message">
127
+ <input type="text" placeholder="请输入发送的数据" />
128
+ <button>发送</button>
129
+ </div>
130
+ <div class="response-message">发送对象反馈的数据:<div>暂无</div></div>
131
+ </div>
132
+
133
+ <script nonce="${nonce}">
134
+ window.mc = (${MessageChannel.toString()})()
135
+ window.mc.setCarrier();
136
+ document.querySelector('.url-webview button').addEventListener('click', () => {
137
+ const input = document.querySelector('.url-webview .send-message input');
138
+ const value = input.value;
139
+ window.mc.pubWithSub('walker.response-url-webview-sample',
140
+ {
141
+ viewType: 'catCustoms.catScratch',
142
+ source: 'D:\\\\project\\\\vscode\\\\vscode-extension-samples\\\\url-webview-sample\\\\exampleFiles\\\\example.cscratch',
143
+ selector: ['input'],
144
+ payload: value
145
+ },
146
+ (data) => {
147
+ document.querySelector('.url-webview .response-message').innerText = data;
148
+ });
149
+ });
150
+ document.querySelector('.command-webview button').addEventListener('click', () => {
151
+ const input = document.querySelector('.command-webview .send-message input');
152
+ const value = input.value;
153
+ window.mc.pubWithSub('walker.command-webview-sample', { viewType: 'catCoding', source: 'catCoding.start', selector: ['input'], payload: value }, (data) => {
154
+ document.querySelector('.command-webview .response-message').innerText = data;
155
+ });
156
+ });
157
+ </script>
158
+ </body>
159
+ </html>`;
160
+ }
161
+ }
162
+
163
+ function getNonce() {
164
+ let text = '';
165
+ const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
166
+ for (let i = 0; i < 32; i++) {
167
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
168
+ }
169
+ return text;
170
+ }
@@ -0,0 +1,264 @@
1
+ import * as vscode from 'vscode';
2
+
3
+ interface Event {
4
+ typename?: string;
5
+ key?: string;
6
+ channelId: string;
7
+ data: any;
8
+ }
9
+
10
+ // 每个vscode的node端和webview都分别拥有一个MessageChannel返回的对象,因为他们是不同载体
11
+ // 同一webview如果打开了多个文档,各个文档也应该有不同的载体
12
+ declare const window: any;
13
+
14
+ const MessageChannel = () => {
15
+ let cachedCarrier: vscode.Webview | null;
16
+ let dispose: vscode.Disposable;
17
+
18
+ /**
19
+ * @carrier 在vscode的webviewProvider以及webview的web内都调用这个接口,设置发送和接受事件的载体
20
+ * webviewProvider示例:CI.setCarrier(webviewView.webview); // 在最早获取到webview的地方
21
+ * webview的react项目示例:CI.setCarrier(); // 在根组件
22
+ * carrier如果为空,则清空之前的载体
23
+ */
24
+ const setCarrier = (carrier?: null | vscode.Webview) => {
25
+ if (carrier === undefined) {
26
+ cachedCarrier = (window as any).acquireVsCodeApi();
27
+ (window as any).addEventListener('message', (event: any) => {
28
+ messageHandler(event.data);
29
+ });
30
+ return;
31
+ }
32
+ if (cachedCarrier) {
33
+ dispose.dispose();
34
+ }
35
+ cachedCarrier = carrier;
36
+ if (cachedCarrier === null) {
37
+ return;
38
+ }
39
+ dispose = cachedCarrier.onDidReceiveMessage((event) =>
40
+ messageHandler(event)
41
+ );
42
+ };
43
+
44
+ const subscribers: {
45
+ [i: string]: ((data: any) => void)[];
46
+ } = {};
47
+
48
+ const messageHandler = async (event: Event) => {
49
+ const { data, typename } = event;
50
+ const isTalkInExtension = typename && subscribers[typename];
51
+ if (isTalkInExtension) {
52
+ subscribers[typename as string].forEach((resolver) => {
53
+ resolver(data);
54
+ });
55
+ return;
56
+ }
57
+ const isTalkToExtension = typename && (data as any)?.viewType;
58
+ if(isTalkToExtension) {
59
+ const activeTargetExtension = async (extensionId: string) => {
60
+ const targetExtension = vscode.extensions.getExtension(extensionId);
61
+ if(!targetExtension ) {
62
+ console.warn(`Extension ${extensionId} not found`);
63
+ return;
64
+ }
65
+ if(!targetExtension.isActive) {
66
+ await targetExtension?.activate();
67
+ }
68
+ return true;
69
+ };
70
+ if(await activeTargetExtension(typename)) {
71
+ const commands = await vscode.commands.getCommands();
72
+ const commandID = `to_${data.viewType}`;
73
+ if(commands.includes(commandID)) {
74
+ const talkToOtherExtension = async () => {
75
+ const result = await vscode.commands.executeCommand(commandID, data);
76
+ publish(typename, result);
77
+ if (result !== undefined) {
78
+ await talkToOtherExtension();
79
+ }
80
+ };
81
+ await talkToOtherExtension();
82
+ } else {
83
+ console.warn(`Command ${commandID} not found`);
84
+ }
85
+ }
86
+
87
+ }
88
+
89
+ };
90
+ /**
91
+ * typename: 消息类型,消息的发布和订阅都依赖这个typename
92
+ * subscriber:收到消息后把消息传递给subscriber
93
+ * once:一次性订阅,收到消息后就把订阅者移除
94
+ */
95
+ const subscribe = (
96
+ typename: string,
97
+ subscriber: (data: any) => any,
98
+ once = false
99
+ ) => {
100
+ if (!subscriber || !(subscriber instanceof Function)) {
101
+ return;
102
+ }
103
+ const resolver = (data: any) => {
104
+ const result = subscriber(data);
105
+ if (result !== undefined) {
106
+ if (result instanceof Promise) {
107
+ result.then((data) => {
108
+ publish(typename, data);
109
+ });
110
+ } else {
111
+ publish(typename, result);
112
+ }
113
+ }
114
+ if (once) {
115
+ const subscriber = subscribers[typename];
116
+ if (subscriber?.length) {
117
+ const i = subscriber.indexOf(resolver);
118
+ subscriber.splice(i, 1);
119
+ }
120
+ }
121
+ };
122
+ const _subscribers = subscribers;
123
+ if (_subscribers[typename]) {
124
+ _subscribers[typename].push(resolver);
125
+ } else {
126
+ _subscribers[typename] = [resolver];
127
+ }
128
+ return () => {
129
+ const subscriber = subscribers[typename];
130
+ if (subscriber?.length) {
131
+ const i = subscriber.indexOf(resolver);
132
+ subscriber.splice(i, 1);
133
+ }
134
+ };
135
+ };
136
+
137
+ /**
138
+ * typename: 消息类型,消息的发布和订阅都依赖这个typename
139
+ * msg:消息发布时带的参数
140
+ */
141
+ const publish = (typename: string, data?: any) => {
142
+ try {
143
+ cachedCarrier?.postMessage({
144
+ typename: typename,
145
+ data: data,
146
+ });
147
+ } catch (error) {0;}
148
+ };
149
+
150
+
151
+ /**
152
+ * 如果要唤醒其余插件的webview,则双方插件的provider、web都要调用这个函数初始化
153
+ * viewType:provider传递WebviewProvieder的viewType,web则不用传递参数
154
+ */
155
+ const initiator = (viewType?: string) => {
156
+ // for node
157
+ if(viewType) {
158
+ vscode.commands.registerCommand(`to_${viewType}`, async (args) => {
159
+ const { source } = args;
160
+ const openWebview = async () => {
161
+ const commands = await vscode.commands.getCommands();
162
+ if(commands.includes(source)) {
163
+ await vscode.commands.executeCommand(source);
164
+ } else {
165
+ const uri = vscode.Uri.file(source);
166
+ if(!uri) {
167
+ return;
168
+ }
169
+ await vscode.commands.executeCommand(
170
+ 'vscode.openWith',
171
+ uri,
172
+ viewType,
173
+ vscode.ViewColumn.One
174
+ );
175
+ }
176
+ };
177
+
178
+ return new Promise((resolve) => { // 通过这个返回数据源
179
+ // 首次打开webview
180
+ subscribe('webviewRenderDone', () => {
181
+ pubWithSub('clickAnyElement', args, (data) => {
182
+ resolve(data);
183
+ });
184
+ }, true);
185
+ // 已经打开过webview
186
+ pubWithSub('clickAnyElement', args, (data) => {
187
+ resolve(data);
188
+ });
189
+ openWebview();
190
+ });
191
+ });
192
+ return;
193
+ }
194
+ publish('webviewRenderDone');
195
+ subscribe('clickAnyElement', (data) => {
196
+ const clickAnyElement = async (data: any) => {
197
+ const selectorList = data?.selector;
198
+ let index = 0;
199
+ const timer = setInterval(() => {
200
+ const allDone = index >= (selectorList?.length || 0);
201
+ if(allDone) {
202
+ clearInterval(timer);
203
+ return;
204
+ }
205
+
206
+ const originSelector = selectorList?.[index];
207
+ const i = originSelector?.split('$')[1];
208
+ const selector =originSelector.split('$')[0];
209
+ const element = (window as any).document?.querySelector(selector);
210
+
211
+ if(selector && element) {
212
+ element.dataset['payload'] = data?.payload;
213
+ element?.click();
214
+ index++;
215
+ }
216
+ }, 1000);
217
+ };
218
+ return new Promise((resolve) => {
219
+ window.feedbackResult = resolve;
220
+ clickAnyElement(data);
221
+ });
222
+ });
223
+ };
224
+ /**
225
+ * key: 唯一key,插件identifier或者消息类型
226
+ * args: 传递的数据
227
+ * {
228
+ * viewType: 要打开的webview的类型
229
+ * source: webview如果是命令打开则是命令ID,如果是则是文件的绝对路径
230
+ * selectorList: 要点击的元素选择器列表
231
+ * }
232
+ * subscribe?: 发布后通过订阅获取反馈数据,如果没有subscribe,则可以通过异步等待获取反馈的数据
233
+ *
234
+ */
235
+ const pubWithSub = async (
236
+ typename: string,
237
+ msg: any,
238
+ subscriber?: (data: any) => any
239
+ ) => {
240
+ publish(typename, msg);
241
+
242
+ return new Promise((resolve) => {
243
+ const removeSubscribe = subscribe(typename, (data: any) => {
244
+ if (subscriber) {
245
+ subscriber(data);
246
+ } else {
247
+ resolve(data);
248
+ }
249
+ removeSubscribe && removeSubscribe();
250
+ });
251
+ });
252
+ };
253
+
254
+ return {
255
+ publish,
256
+ subscribe,
257
+ setCarrier,
258
+ pubWithSub,
259
+ initiator,
260
+ getCarrier: () => cachedCarrier,
261
+ };
262
+ };
263
+
264
+ export default MessageChannel;
@@ -0,0 +1,12 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "commonjs",
4
+ "target": "es2020",
5
+ "lib": ["es2020", "dom"],
6
+ "outDir": "out",
7
+ "sourceMap": true,
8
+ "strict": true,
9
+ "rootDir": "src"
10
+ },
11
+ "exclude": ["node_modules", ".vscode-test"]
12
+ }
@@ -0,0 +1 @@
1
+ media/*.js
@@ -0,0 +1,20 @@
1
+ /**@type {import('eslint').Linter.Config} */
2
+ // eslint-disable-next-line no-undef
3
+ module.exports = {
4
+ root: true,
5
+ parser: '@typescript-eslint/parser',
6
+ plugins: [
7
+ '@typescript-eslint',
8
+ ],
9
+ extends: [
10
+ 'eslint:recommended',
11
+ 'plugin:@typescript-eslint/recommended',
12
+ ],
13
+ rules: {
14
+ 'semi': [2, "always"],
15
+ '@typescript-eslint/no-unused-vars': 0,
16
+ '@typescript-eslint/no-explicit-any': 0,
17
+ '@typescript-eslint/explicit-module-boundary-types': 0,
18
+ '@typescript-eslint/no-non-null-assertion': 0
19
+ }
20
+ };
@@ -0,0 +1,9 @@
1
+ {
2
+ // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
3
+ // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
4
+
5
+ // List of extensions which should be recommended for users of this workspace.
6
+ "recommendations": [
7
+ "dbaeumer.vscode-eslint"
8
+ ]
9
+ }
@@ -0,0 +1,18 @@
1
+ // A launch configuration that compiles the extension and then opens it inside a new window
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ {
6
+ "version": "0.2.0",
7
+ "configurations": [
8
+ {
9
+ "name": "Run Extension",
10
+ "type": "extensionHost",
11
+ "request": "launch",
12
+ "runtimeExecutable": "${execPath}",
13
+ "args": ["--extensionDevelopmentPath=${workspaceRoot}"],
14
+ "outFiles": ["${workspaceFolder}/out/**/*.js"],
15
+ "preLaunchTask": "npm: compile"
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "editor.insertSpaces": false
3
+ }
@@ -0,0 +1,20 @@
1
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
2
+ // for the documentation about the tasks.json format
3
+ {
4
+ "version": "2.0.0",
5
+ "tasks": [
6
+ {
7
+ "type": "npm",
8
+ "script": "watch",
9
+ "problemMatcher": "$tsc-watch",
10
+ "isBackground": true,
11
+ "presentation": {
12
+ "reveal": "never"
13
+ },
14
+ "group": {
15
+ "kind": "build",
16
+ "isDefault": true
17
+ }
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,25 @@
1
+ # Cat Customs - Custom Editor API Samples
2
+
3
+ ![Paw draw editor ](documentation/example.png)
4
+
5
+ Demonstrates VS Code's [custom editor API](https://code.visualstudio.com/api/extension-guides/custom-editors) using two custom editors:
6
+
7
+ - Cat Scratch — Uses the finalized custom text editor api to provide a custom editor for `.cscratch` files (which are just json files)
8
+ - Paw Draw - Uses the binary custom editor api to provide a custom editor for `.pawdraw` files (which are just png files with a different file extension).
9
+
10
+ ## VS Code API
11
+
12
+ ### `vscode` module
13
+
14
+ - [`window.registerCustomEditorProvider`](https://code.visualstudio.com/api/references/vscode-api#window.registerCustomEditorProvider)
15
+ - [`CustomTextEditor`](https://code.visualstudio.com/api/references/vscode-api#CustomTextEditor)
16
+ - [`CustomEditor`](https://code.visualstudio.com/api/references/vscode-api#CustomEditor)
17
+
18
+ ## Running the example
19
+
20
+ - Open this example in VS Code 1.46+
21
+ - `npm install`
22
+ - `npm run watch` or `npm run compile`
23
+ - `F5` to start debugging
24
+
25
+ Open the example files from the `exampleFiles` directory.
@@ -0,0 +1,14 @@
1
+ {
2
+ "scratches": [
3
+ {
4
+ "id": "8lYOoWqz2rHtPuhvnZ43eMx1mG6WnFrm",
5
+ "text": "😸",
6
+ "created": 1584577931699
7
+ },
8
+ {
9
+ "id": "aZ57bJUEaXZ5wuBAX6NfGuj85Y6iw84N",
10
+ "text": "😻",
11
+ "created": 1584577933329
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1 @@
1
+ 工程管理插件 python-kaleido-case-api.exe 开始服务时间:2025/11/18 17:02:22
@@ -0,0 +1 @@
1
+ 工程管理插件 python-request.exe 开始服务时间:2025/11/18 17:02:28
@@ -0,0 +1,6 @@
1
+ 2025-11-18 17:02:28,916 - d:\project\新版画图工具\messageChannel\examples\url-webview-sample\exampleFiles\test_cases\log\output_202511181702.log
2
+ 2025-11-18 17:02:28,916 - 约束求解执行文件路径:d:\software\vscode各个版本\kaleidoscope-win10精简版\KaleidoApi\RFS\src\fsm\constraint_problem_solving\Requirement_diagram_analysis.exe
3
+ 2025-11-18 17:02:28,951 - C++ server started with PID: 22952
4
+ 2025-11-18 17:02:28,959 - output: Server is listening on http://localhost:58930
5
+ 2025-11-18 17:02:28,960 - Log monitoring started in a separate thread.
6
+ 2025-11-18 17:02:28,960 - Error: C++ server exited with code None