@jiangzhongxi0322/messagechannel 1.0.0 → 1.0.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.
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 +1 -1
  69. package/src/messageChannel.ts +264 -0
  70. package/dist/messageChennel.d.ts +0 -15
@@ -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;
@@ -1,15 +0,0 @@
1
- import * as vscode from 'vscode';
2
- interface FeedbackData {
3
- code: 0 | 1 | 2;
4
- msg: string;
5
- data: any;
6
- }
7
- declare const MessageChannel: () => {
8
- publish: (typename: string, msg?: any) => void;
9
- subscribe: (typename: string, subscriber: (data: FeedbackData) => any, once?: boolean) => (() => void) | undefined;
10
- setCarrier: (carrier: any) => void;
11
- pubWithSub: (typename: string, msg: any, subscriber?: (data: FeedbackData) => any) => Promise<unknown>;
12
- initiator: (viewType: string) => void;
13
- getCarrier: () => vscode.Webview;
14
- };
15
- export default MessageChannel;