@tomjs/vite-plugin-vscode 2.4.0 → 2.5.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @tomjs/vite-plugin-vscode
2
2
 
3
- [![npm](https://img.shields.io/npm/v/@tomjs/vite-plugin-vscode)](https://www.npmjs.com/package/@tomjs/vite-plugin-vscode) ![node-current (scoped)](https://img.shields.io/node/v/@tomjs/vite-plugin-vscode) ![NPM](https://img.shields.io/npm/l/@tomjs/vite-plugin-vscode) [![Docs](https://www.paka.dev/badges/v0/cute.svg)](https://www.paka.dev/npm/@tomjs/vite-plugin-vscode)
3
+ [![npm](https://img.shields.io/npm/v/@tomjs/vite-plugin-vscode)](https://www.npmjs.com/package/@tomjs/vite-plugin-vscode) ![node-current (scoped)](https://img.shields.io/node/v/@tomjs/vite-plugin-vscode) ![NPM](https://img.shields.io/npm/l/@tomjs/vite-plugin-vscode)
4
4
 
5
5
  **English** | [中文](./README.zh_CN.md)
6
6
 
@@ -200,9 +200,16 @@ function __getWebviewHtml__(
200
200
  ): string;
201
201
  ```
202
202
 
203
+ ### Warning
204
+
205
+ When using the `acquireVsCodeApi().getState()` method of [@types/vscode-webview](https://www.npmjs.com/package/@types/vscode-webview), you must use `await` to call it. Since `acquireVsCodeApi` is a simulated implementation of this method by the plugin, it is inconsistent with the original method. I am very sorry. If you have other solutions, please share them. Thank you very much.
206
+
207
+ ```ts
208
+ const value = await acquireVsCodeApi().getState();
209
+ ```
210
+
203
211
  ## Documentation
204
212
 
205
- - [API Documentation](https://paka.dev/npm/@tomjs/vite-plugin-vscode) provided by [paka.dev](https://paka.dev).
206
213
  - [index.d.ts](https://www.unpkg.com/browse/@tomjs/vite-plugin-vscode/dist/index.d.ts) provided by [unpkg.com](https://www.unpkg.com).
207
214
 
208
215
  ## Parameters
@@ -371,3 +378,9 @@ Open the [examples](./examples) directory, there are `vue` and `react` examples.
371
378
  - [react](./examples/react): Simple react example.
372
379
  - [vue](./examples/vue): Simple vue example.
373
380
  - [vue-import](./examples/vue-import): Dynamic import() and multi-page examples.
381
+
382
+ ## Related
383
+
384
+ - [@tomjs/vscode](https://npmjs.com/package/@tomjs/vscode): Some utilities to simplify the development of [VSCode Extensions](https://marketplace.visualstudio.com/VSCode).
385
+ - [@tomjs/vscode-dev](https://npmjs.com/package/@tomjs/vscode-dev): Some development tools to simplify the development of [vscode extensions](https://marketplace.visualstudio.com/VSCode).
386
+ - [@tomjs/vscode-webview](https://npmjs.com/package/@tomjs/webview): Optimize the `postMessage` issue between `webview` page and [vscode extensions](https://marketplace.visualstudio.com/VSCode)
package/README.zh_CN.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @tomjs/vite-plugin-vscode
2
2
 
3
- [![npm](https://img.shields.io/npm/v/@tomjs/vite-plugin-vscode)](https://www.npmjs.com/package/@tomjs/vite-plugin-vscode) ![node-current (scoped)](https://img.shields.io/node/v/@tomjs/vite-plugin-vscode) ![NPM](https://img.shields.io/npm/l/@tomjs/vite-plugin-vscode) [![Docs](https://www.paka.dev/badges/v0/cute.svg)](https://www.paka.dev/npm/@tomjs/vite-plugin-vscode)
3
+ [![npm](https://img.shields.io/npm/v/@tomjs/vite-plugin-vscode)](https://www.npmjs.com/package/@tomjs/vite-plugin-vscode) ![node-current (scoped)](https://img.shields.io/node/v/@tomjs/vite-plugin-vscode) ![NPM](https://img.shields.io/npm/l/@tomjs/vite-plugin-vscode)
4
4
 
5
5
  [English](./README.md) | **中文**
6
6
 
@@ -204,9 +204,16 @@ function __getWebviewHtml__(
204
204
  ): string;
205
205
  ```
206
206
 
207
+ ### 警告
208
+
209
+ 使用 [@types/vscode-webview](https://www.npmjs.com/package/@types/vscode-webview) 的 `acquireVsCodeApi().getState()` 方法时,要使用 `await` 调用。由于 `acquireVsCodeApi` 是插件对该方法的模拟实现,故与原方法出现不一致性,非常抱歉。如果有其他方案,请分享,非常感谢。
210
+
211
+ ```ts
212
+ const value = await acquireVsCodeApi().getState();
213
+ ```
214
+
207
215
  ## 文档
208
216
 
209
- - [paka.dev](https://paka.dev) 提供的 [API文档](https://paka.dev/npm/@tomjs/vite-plugin-vscode).
210
217
  - [unpkg.com](https://www.unpkg.com/) 提供的 [index.d.ts](https://www.unpkg.com/browse/@tomjs/vite-plugin-vscode/dist/index.d.ts).
211
218
 
212
219
  ## 参数
@@ -374,3 +381,9 @@ pnpm build
374
381
  - [react](./examples/react):简单的 react 示例。
375
382
  - [vue](./examples/vue):简单的 vue 示例。
376
383
  - [vue-import](./examples/vue-import):动态 import() 和多页面示例。
384
+
385
+ ## 关联
386
+
387
+ - [@tomjs/vscode](https://npmjs.com/package/@tomjs/vscode): 一些实用工具,用于简化 [vscode 扩展](https://marketplace.visualstudio.com/VSCode) 的开发。
388
+ - [@tomjs/vscode-dev](https://npmjs.com/package/@tomjs/vscode-dev): 一些开发工具,用于简化 [vscode 扩展](https://marketplace.visualstudio.com/VSCode) 的开发。
389
+ - [@tomjs/vscode-webview](https://npmjs.com/package/@tomjs/vscode-webview): 优化 `webview` 页面与 [vscode 扩展](https://marketplace.visualstudio.com/VSCode) 的 `postMessage` 问题
@@ -20,47 +20,60 @@
20
20
  document.addEventListener("DOMContentLoaded", callback);
21
21
  }
22
22
  }
23
- function setStateData(data) {
24
- localStorage.setItem("vscode.state", JSON.stringify(data));
25
- }
26
- function getStateData() {
27
- try {
28
- const v = localStorage.getItem("vscode.state");
29
- return v ? JSON.parse(v) : v;
30
- } catch (e) {
31
- }
32
- return;
33
- }
34
23
  function patchInitData(data) {
35
- const { state, style, body, root } = data;
36
- setStateData(state);
37
- document.documentElement.style.cssText = root.cssText;
38
- document.body.className = body.className;
39
- Object.keys(body.dataset).forEach((key) => {
40
- document.body.dataset[key] = body.dataset[key];
24
+ onDomReady(() => {
25
+ console.log(TAG, "patch client style");
26
+ const { style, body, root } = data;
27
+ document.documentElement.style.cssText = root.cssText;
28
+ document.body.className = body.className;
29
+ Object.keys(body.dataset).forEach((key) => {
30
+ document.body.dataset[key] = body.dataset[key];
31
+ });
32
+ const defaultStyles = document.createElement("style");
33
+ defaultStyles.id = "_defaultStyles";
34
+ defaultStyles.textContent = style;
35
+ document.head.appendChild(defaultStyles);
41
36
  });
42
- const defaultStyles = document.createElement("style");
43
- defaultStyles.id = "_defaultStyles";
44
- defaultStyles.textContent = style;
45
- document.head.appendChild(defaultStyles);
46
37
  }
38
+ var GET_STATE_TYPE = "[vscode:client]:getState";
39
+ var SET_STATE_TYPE = "[vscode:client]:setState";
40
+ var POST_MESSAGE_TYPE = "[vscode:client]:postMessage";
47
41
  function patchAcquireVsCodeApi() {
48
42
  class AcquireVsCodeApi {
49
43
  postMessage(message) {
50
- console.log(TAG + " acquireVsCodeApi.postMessage:", message);
51
- window.parent.postMessage({ type: "[vscode:client]:postMessage", data: message }, "*");
44
+ console.log(TAG, "mock acquireVsCodeApi.postMessage:", message);
45
+ window.parent.postMessage({ type: POST_MESSAGE_TYPE, data: message }, "*");
52
46
  }
53
47
  getState() {
54
- console.log(TAG + " acquireVsCodeApi.getState");
55
- return getStateData();
48
+ console.log(TAG, "mock acquireVsCodeApi.getState");
49
+ return new Promise((resolve, reject) => {
50
+ function post() {
51
+ window.parent.postMessage({ type: GET_STATE_TYPE }, "*");
52
+ }
53
+ const timeoutId = setTimeout(() => {
54
+ window.removeEventListener("message", receive);
55
+ reject(new Error("Timeout"));
56
+ }, 2e3);
57
+ function receive(e) {
58
+ var _a, _b;
59
+ console.log(e);
60
+ if (!e.origin.startsWith("vscode-webview://") || ((_a = e.data) == null ? void 0 : _a.type) !== GET_STATE_TYPE) {
61
+ return;
62
+ }
63
+ window.removeEventListener("message", receive);
64
+ clearTimeout(timeoutId);
65
+ resolve((_b = e.data) == null ? void 0 : _b.data);
66
+ }
67
+ window.addEventListener("message", receive);
68
+ post();
69
+ });
56
70
  }
57
71
  setState(newState) {
58
- console.log(TAG + " acquireVsCodeApi.setState:", newState);
59
- setStateData(newState);
60
- window.parent.postMessage({ type: "[vscode:client]:setSate", data: newState }, "*");
72
+ console.log(TAG, "mock acquireVsCodeApi.setState:", newState);
73
+ window.parent.postMessage({ type: SET_STATE_TYPE, data: newState }, "*");
61
74
  }
62
75
  }
63
- console.log(TAG + "patch acquireVsCodeApi");
76
+ console.log(TAG, "patch acquireVsCodeApi");
64
77
  let api;
65
78
  window.acquireVsCodeApi = () => {
66
79
  if (!api) {
@@ -72,19 +85,12 @@
72
85
  };
73
86
  }
74
87
  var INIT_TYPE = "[vscode:extension]:init";
75
- var GET_STATE_TYPE = "[vscode:extension]:state";
76
88
  window.addEventListener("message", (e) => {
77
89
  const { type, data } = e.data || {};
78
- if (!e.origin.startsWith("vscode-webview://") || ![INIT_TYPE, GET_STATE_TYPE].includes(type)) {
90
+ if (!e.origin.startsWith("vscode-webview://") || type !== INIT_TYPE) {
79
91
  return;
80
92
  }
81
- onDomReady(function() {
82
- if (type === INIT_TYPE) {
83
- patchInitData(data);
84
- } else if (type === GET_STATE_TYPE) {
85
- localStorage.setItem("vscode.state", JSON.stringify(data));
86
- }
87
- });
93
+ patchInitData(data);
88
94
  });
89
95
  }
90
96
  });
package/dist/webview.js CHANGED
@@ -1,148 +1,189 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/webview/template.html
2
2
  var template_default = `<!doctype html>
3
3
  <html lang="en">
4
- <head>
5
- <meta charset="UTF-8" />
6
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
7
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
- <style>
9
- html,
10
- body {
11
- width: 100%;
12
- height: 100%;
13
- margin: 0;
14
- padding: 0;
15
- overflow: hidden;
16
- }
17
4
 
18
- #webview-patch-iframe {
19
- width: 100%;
20
- height: 100%;
21
- border: none;
5
+ <head>
6
+ <meta charset="UTF-8" />
7
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
8
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
9
+ <style>
10
+ html,
11
+ body {
12
+ width: 100%;
13
+ height: 100%;
14
+ margin: 0;
15
+ padding: 0;
16
+ overflow: hidden;
17
+ }
18
+
19
+ #webview-patch-iframe {
20
+ width: 100%;
21
+ height: 100%;
22
+ border: none;
23
+ }
24
+
25
+ .outer {
26
+ width: 100%;
27
+ height: 100%;
28
+ overflow: hidden;
29
+ }
30
+ </style>
31
+
32
+ <script type="module" id="webview-patch">
33
+ const TAG = '[@tomjs:vscode:extension] ';
34
+
35
+ function onDomReady(callback, doc) {
36
+ const _doc = doc || document
37
+ if (_doc.readyState === 'interactive' || _doc.readyState === 'complete') {
38
+ callback();
39
+ } else {
40
+ _doc.addEventListener('DOMContentLoaded', callback);
22
41
  }
42
+ }
23
43
 
24
- .outer {
25
- width: 100%;
26
- height: 100%;
27
- overflow: hidden;
28
- }
29
- </style>
44
+ let vsCodeApi;
30
45
 
31
- <script type="module" id="webview-patch">
32
- const TAG = '[@tomjs:vscode:extension] ';
46
+ function getApi() {
47
+ if (vsCodeApi) return vsCodeApi;
48
+ return (vsCodeApi = acquireVsCodeApi());
49
+ }
50
+
51
+ function sendInitData(iframe) {
52
+ console.log(TAG + 'init data');
53
+ const dataset = {};
54
+ Object.keys(document.body.dataset).forEach(key => {
55
+ dataset[key] = document.body.dataset[key];
56
+ });
33
57
 
34
- function onDomReady(callback) {
35
- if (document.readyState === 'interactive' || document.readyState === 'complete') {
36
- callback();
37
- } else {
38
- document.addEventListener('DOMContentLoaded', callback);
58
+ iframe.contentWindow.postMessage(
59
+ {
60
+ type: '[vscode:extension]:init',
61
+ data: {
62
+ state: getApi().getState(),
63
+ style: document.getElementById('_defaultStyles').innerHTML,
64
+ root: {
65
+ cssText: document.documentElement.style.cssText,
66
+ },
67
+ body: {
68
+ dataset: dataset,
69
+ className: document.body.className,
70
+ role: document.body.getAttribute('role'),
71
+ },
72
+ },
73
+ },
74
+ '*',
75
+ );
76
+ }
77
+
78
+ function observeAttributeChanges(element, attributeName, callback) {
79
+ const observer = new MutationObserver(function (mutationsList) {
80
+ for (let mutation of mutationsList) {
81
+ if (mutation.type === 'attributes' && mutation.attributeName === attributeName) {
82
+ callback(mutation.target.getAttribute(attributeName));
83
+ }
39
84
  }
85
+ });
86
+ observer.observe(element, { attributes: true });
87
+ return observer;
88
+ }
89
+
90
+ // message handler
91
+ let iframeLoaded = false;
92
+ const cacheMessages = [];
93
+
94
+ function handleMessage(e) {
95
+ const iframe = document.getElementById('webview-patch-iframe');
96
+ if (!iframeLoaded || !iframe) {
97
+ return;
40
98
  }
41
-
42
- let vsCodeApi;
43
-
44
- function getApi() {
45
- if (vsCodeApi) return vsCodeApi;
46
- return (vsCodeApi = acquireVsCodeApi());
99
+ if (e.origin.startsWith('vscode-webview://')) {
100
+ iframe.contentWindow.postMessage(e.data, '*');
101
+ } else if ('{{serverUrl}}'.startsWith(e.origin)) {
102
+ const { type, data } = e.data;
103
+ console.log(TAG + ' received:', e.data);
104
+ if (type === '[vscode:client]:postMessage') {
105
+ getApi().postMessage(data);
106
+ } else if (type === '[vscode:client]:getState') {
107
+ iframe.contentWindow.postMessage(
108
+ {
109
+ type: '[vscode:client]:getState',
110
+ data: getApi().getState(),
111
+ },
112
+ '*',
113
+ );
114
+ } else if (type === '[vscode:client]:setState') {
115
+ getApi().setState(data);
116
+ }
47
117
  }
118
+ }
48
119
 
49
- function sendInitData(iframe) {
50
- console.log(TAG + 'init data');
51
- const dataset = {};
52
- Object.keys(document.body.dataset).forEach(key => {
53
- dataset[key] = document.body.dataset[key];
54
- });
55
-
56
- iframe.contentWindow.postMessage(
57
- {
58
- type: '[vscode:extension]:init',
59
- data: {
60
- state: getApi().getState(),
61
- style: document.getElementById('_defaultStyles').innerHTML,
62
- root: {
63
- cssText: document.documentElement.style.cssText,
64
- },
65
- body: {
66
- dataset: dataset,
67
- className: document.body.className,
68
- role: document.body.getAttribute('role'),
69
- },
70
- },
71
- },
72
- '*',
73
- );
120
+ window.addEventListener('message', function (event) {
121
+ if (event.origin.startsWith('vscode-webview://')) {
122
+ cacheMessages.push(event);
123
+ return;
74
124
  }
125
+ handleMessage(event);
126
+ });
75
127
 
76
- function addListeners(iframe) {
77
- window.addEventListener('message', function (e) {
78
- if (e.origin.startsWith('vscode-webview://')) {
79
- iframe.contentWindow.postMessage(e.data, '*');
80
- } else if ('{{serverUrl}}'.startsWith(e.origin)) {
81
- const { type, data } = e.data;
82
- if (type === '[vscode:client]:postMessage') {
83
- getApi().postMessage(data);
84
- } else if (type === '[vscode:client]:getState') {
85
- iframe.contentWindow.postMessage(
86
- {
87
- type: '[vscode:extension]:getState',
88
- data: getApi().getState(),
89
- },
90
- '*',
91
- );
92
- } else if (type === '[vscode:client]:setState') {
93
- getApi().setState(data);
94
- }
95
- }
96
- });
128
+ let isCacheWorking = false;
129
+ setInterval(() => {
130
+ if (isCacheWorking) {
131
+ return;
97
132
  }
98
133
 
99
- function observeAttributeChanges(element, attributeName, callback) {
100
- const observer = new MutationObserver(function (mutationsList) {
101
- for (let mutation of mutationsList) {
102
- if (mutation.type === 'attributes' && mutation.attributeName === attributeName) {
103
- callback(mutation.target.getAttribute(attributeName));
104
- }
105
- }
106
- });
107
- observer.observe(element, { attributes: true });
108
- return observer;
134
+ isCacheWorking = true;
135
+ if (iframeLoaded) {
136
+ let event = cacheMessages.shift()
137
+ while (event) {
138
+ handleMessage(event);
139
+ event = cacheMessages.shift()
140
+ }
109
141
  }
142
+ isCacheWorking = false;
143
+ }, 50);
144
+
145
+ onDomReady(function () {
146
+ /** @type {HTMLIFrameElement} */
147
+ const iframe = document.getElementById('webview-patch-iframe');
148
+ observeAttributeChanges(document.body, 'class', function (className) {
149
+ sendInitData(iframe);
150
+ });
110
151
 
111
152
  onDomReady(function () {
112
- const iframe = document.getElementById('webview-patch-iframe');
113
- observeAttributeChanges(document.body, 'class', function (className) {
114
- sendInitData(iframe);
115
- });
116
- iframe.addEventListener('load', function (e) {
117
- let interval = setInterval(() => {
118
- try {
119
- if (document.getElementById('_defaultStyles')) {
120
- sendInitData(iframe);
121
- addListeners(iframe);
122
- clearInterval(interval);
123
- return;
124
- }
125
- } catch (e) {
153
+ iframeLoaded = true;
154
+ sendInitData(iframe);
155
+ }, iframe.contentDocument);
156
+
157
+
158
+ iframe.addEventListener('load', function (e) {
159
+ iframeLoaded = true;
160
+
161
+ let interval = setInterval(() => {
162
+ try {
163
+ if (document.getElementById('_defaultStyles')) {
164
+ sendInitData(iframe);
165
+ // addListeners(iframe);
126
166
  clearInterval(interval);
127
- console.error(e);
167
+ return;
128
168
  }
129
- }, 10);
130
- });
169
+ } catch (e) {
170
+ clearInterval(interval);
171
+ console.error(e);
172
+ }
173
+ }, 10);
131
174
  });
132
- </script>
133
- </head>
134
-
135
- <body>
136
- <div class="outer">
137
- <iframe
138
- id="webview-patch-iframe"
139
- frameborder="0"
140
- sandbox="allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-downloads"
141
- allow="cross-origin-isolated; autoplay; clipboard-read; clipboard-write"
142
- src="{{serverUrl}}"
143
- ></iframe>
144
- </div>
145
- </body>
175
+ });
176
+ </script>
177
+ </head>
178
+
179
+ <body>
180
+ <div class="outer">
181
+ <iframe id="webview-patch-iframe" frameborder="0"
182
+ sandbox="allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-downloads"
183
+ allow="cross-origin-isolated; autoplay; clipboard-read; clipboard-write" src="{{serverUrl}}"></iframe>
184
+ </div>
185
+ </body>
186
+
146
187
  </html>
147
188
  `;
148
189
 
package/dist/webview.mjs CHANGED
@@ -1,148 +1,189 @@
1
1
  // src/webview/template.html
2
2
  var template_default = `<!doctype html>
3
3
  <html lang="en">
4
- <head>
5
- <meta charset="UTF-8" />
6
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
7
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
- <style>
9
- html,
10
- body {
11
- width: 100%;
12
- height: 100%;
13
- margin: 0;
14
- padding: 0;
15
- overflow: hidden;
16
- }
17
4
 
18
- #webview-patch-iframe {
19
- width: 100%;
20
- height: 100%;
21
- border: none;
22
- }
5
+ <head>
6
+ <meta charset="UTF-8" />
7
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
8
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
9
+ <style>
10
+ html,
11
+ body {
12
+ width: 100%;
13
+ height: 100%;
14
+ margin: 0;
15
+ padding: 0;
16
+ overflow: hidden;
17
+ }
23
18
 
24
- .outer {
25
- width: 100%;
26
- height: 100%;
27
- overflow: hidden;
28
- }
29
- </style>
19
+ #webview-patch-iframe {
20
+ width: 100%;
21
+ height: 100%;
22
+ border: none;
23
+ }
30
24
 
31
- <script type="module" id="webview-patch">
32
- const TAG = '[@tomjs:vscode:extension] ';
25
+ .outer {
26
+ width: 100%;
27
+ height: 100%;
28
+ overflow: hidden;
29
+ }
30
+ </style>
33
31
 
34
- function onDomReady(callback) {
35
- if (document.readyState === 'interactive' || document.readyState === 'complete') {
36
- callback();
37
- } else {
38
- document.addEventListener('DOMContentLoaded', callback);
39
- }
32
+ <script type="module" id="webview-patch">
33
+ const TAG = '[@tomjs:vscode:extension] ';
34
+
35
+ function onDomReady(callback, doc) {
36
+ const _doc = doc || document
37
+ if (_doc.readyState === 'interactive' || _doc.readyState === 'complete') {
38
+ callback();
39
+ } else {
40
+ _doc.addEventListener('DOMContentLoaded', callback);
40
41
  }
42
+ }
41
43
 
42
- let vsCodeApi;
44
+ let vsCodeApi;
43
45
 
44
- function getApi() {
45
- if (vsCodeApi) return vsCodeApi;
46
- return (vsCodeApi = acquireVsCodeApi());
47
- }
46
+ function getApi() {
47
+ if (vsCodeApi) return vsCodeApi;
48
+ return (vsCodeApi = acquireVsCodeApi());
49
+ }
50
+
51
+ function sendInitData(iframe) {
52
+ console.log(TAG + 'init data');
53
+ const dataset = {};
54
+ Object.keys(document.body.dataset).forEach(key => {
55
+ dataset[key] = document.body.dataset[key];
56
+ });
48
57
 
49
- function sendInitData(iframe) {
50
- console.log(TAG + 'init data');
51
- const dataset = {};
52
- Object.keys(document.body.dataset).forEach(key => {
53
- dataset[key] = document.body.dataset[key];
54
- });
55
-
56
- iframe.contentWindow.postMessage(
57
- {
58
- type: '[vscode:extension]:init',
59
- data: {
60
- state: getApi().getState(),
61
- style: document.getElementById('_defaultStyles').innerHTML,
62
- root: {
63
- cssText: document.documentElement.style.cssText,
64
- },
65
- body: {
66
- dataset: dataset,
67
- className: document.body.className,
68
- role: document.body.getAttribute('role'),
69
- },
58
+ iframe.contentWindow.postMessage(
59
+ {
60
+ type: '[vscode:extension]:init',
61
+ data: {
62
+ state: getApi().getState(),
63
+ style: document.getElementById('_defaultStyles').innerHTML,
64
+ root: {
65
+ cssText: document.documentElement.style.cssText,
66
+ },
67
+ body: {
68
+ dataset: dataset,
69
+ className: document.body.className,
70
+ role: document.body.getAttribute('role'),
70
71
  },
71
72
  },
72
- '*',
73
- );
74
- }
73
+ },
74
+ '*',
75
+ );
76
+ }
75
77
 
76
- function addListeners(iframe) {
77
- window.addEventListener('message', function (e) {
78
- if (e.origin.startsWith('vscode-webview://')) {
79
- iframe.contentWindow.postMessage(e.data, '*');
80
- } else if ('{{serverUrl}}'.startsWith(e.origin)) {
81
- const { type, data } = e.data;
82
- if (type === '[vscode:client]:postMessage') {
83
- getApi().postMessage(data);
84
- } else if (type === '[vscode:client]:getState') {
85
- iframe.contentWindow.postMessage(
86
- {
87
- type: '[vscode:extension]:getState',
88
- data: getApi().getState(),
89
- },
90
- '*',
91
- );
92
- } else if (type === '[vscode:client]:setState') {
93
- getApi().setState(data);
94
- }
78
+ function observeAttributeChanges(element, attributeName, callback) {
79
+ const observer = new MutationObserver(function (mutationsList) {
80
+ for (let mutation of mutationsList) {
81
+ if (mutation.type === 'attributes' && mutation.attributeName === attributeName) {
82
+ callback(mutation.target.getAttribute(attributeName));
95
83
  }
96
- });
84
+ }
85
+ });
86
+ observer.observe(element, { attributes: true });
87
+ return observer;
88
+ }
89
+
90
+ // message handler
91
+ let iframeLoaded = false;
92
+ const cacheMessages = [];
93
+
94
+ function handleMessage(e) {
95
+ const iframe = document.getElementById('webview-patch-iframe');
96
+ if (!iframeLoaded || !iframe) {
97
+ return;
97
98
  }
99
+ if (e.origin.startsWith('vscode-webview://')) {
100
+ iframe.contentWindow.postMessage(e.data, '*');
101
+ } else if ('{{serverUrl}}'.startsWith(e.origin)) {
102
+ const { type, data } = e.data;
103
+ console.log(TAG + ' received:', e.data);
104
+ if (type === '[vscode:client]:postMessage') {
105
+ getApi().postMessage(data);
106
+ } else if (type === '[vscode:client]:getState') {
107
+ iframe.contentWindow.postMessage(
108
+ {
109
+ type: '[vscode:client]:getState',
110
+ data: getApi().getState(),
111
+ },
112
+ '*',
113
+ );
114
+ } else if (type === '[vscode:client]:setState') {
115
+ getApi().setState(data);
116
+ }
117
+ }
118
+ }
98
119
 
99
- function observeAttributeChanges(element, attributeName, callback) {
100
- const observer = new MutationObserver(function (mutationsList) {
101
- for (let mutation of mutationsList) {
102
- if (mutation.type === 'attributes' && mutation.attributeName === attributeName) {
103
- callback(mutation.target.getAttribute(attributeName));
104
- }
105
- }
106
- });
107
- observer.observe(element, { attributes: true });
108
- return observer;
120
+ window.addEventListener('message', function (event) {
121
+ if (event.origin.startsWith('vscode-webview://')) {
122
+ cacheMessages.push(event);
123
+ return;
124
+ }
125
+ handleMessage(event);
126
+ });
127
+
128
+ let isCacheWorking = false;
129
+ setInterval(() => {
130
+ if (isCacheWorking) {
131
+ return;
132
+ }
133
+
134
+ isCacheWorking = true;
135
+ if (iframeLoaded) {
136
+ let event = cacheMessages.shift()
137
+ while (event) {
138
+ handleMessage(event);
139
+ event = cacheMessages.shift()
140
+ }
109
141
  }
142
+ isCacheWorking = false;
143
+ }, 50);
144
+
145
+ onDomReady(function () {
146
+ /** @type {HTMLIFrameElement} */
147
+ const iframe = document.getElementById('webview-patch-iframe');
148
+ observeAttributeChanges(document.body, 'class', function (className) {
149
+ sendInitData(iframe);
150
+ });
110
151
 
111
152
  onDomReady(function () {
112
- const iframe = document.getElementById('webview-patch-iframe');
113
- observeAttributeChanges(document.body, 'class', function (className) {
114
- sendInitData(iframe);
115
- });
116
- iframe.addEventListener('load', function (e) {
117
- let interval = setInterval(() => {
118
- try {
119
- if (document.getElementById('_defaultStyles')) {
120
- sendInitData(iframe);
121
- addListeners(iframe);
122
- clearInterval(interval);
123
- return;
124
- }
125
- } catch (e) {
153
+ iframeLoaded = true;
154
+ sendInitData(iframe);
155
+ }, iframe.contentDocument);
156
+
157
+
158
+ iframe.addEventListener('load', function (e) {
159
+ iframeLoaded = true;
160
+
161
+ let interval = setInterval(() => {
162
+ try {
163
+ if (document.getElementById('_defaultStyles')) {
164
+ sendInitData(iframe);
165
+ // addListeners(iframe);
126
166
  clearInterval(interval);
127
- console.error(e);
167
+ return;
128
168
  }
129
- }, 10);
130
- });
169
+ } catch (e) {
170
+ clearInterval(interval);
171
+ console.error(e);
172
+ }
173
+ }, 10);
131
174
  });
132
- </script>
133
- </head>
134
-
135
- <body>
136
- <div class="outer">
137
- <iframe
138
- id="webview-patch-iframe"
139
- frameborder="0"
140
- sandbox="allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-downloads"
141
- allow="cross-origin-isolated; autoplay; clipboard-read; clipboard-write"
142
- src="{{serverUrl}}"
143
- ></iframe>
144
- </div>
145
- </body>
175
+ });
176
+ </script>
177
+ </head>
178
+
179
+ <body>
180
+ <div class="outer">
181
+ <iframe id="webview-patch-iframe" frameborder="0"
182
+ sandbox="allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-downloads"
183
+ allow="cross-origin-isolated; autoplay; clipboard-read; clipboard-write" src="{{serverUrl}}"></iframe>
184
+ </div>
185
+ </body>
186
+
146
187
  </html>
147
188
  `;
148
189
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomjs/vite-plugin-vscode",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "Use vue/react to develop 'vscode extension webview', supporting esm/cjs",
5
5
  "keywords": [
6
6
  "vite",