@tomjs/vite-plugin-vscode 5.2.1 → 6.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.
package/README.md CHANGED
@@ -82,13 +82,15 @@ Setting `recommended` will modify some preset configurations. See [PluginOptions
82
82
  code snippet, more code see examples
83
83
 
84
84
  ```ts
85
+ import { getWebviewHtml } from 'virtual:vscode';
86
+
85
87
  const panel = window.createWebviewPanel('showHelloWorld', 'Hello World', ViewColumn.One, {
86
88
  enableScripts: true,
87
89
  localResourceRoots: [Uri.joinPath(extensionUri, 'dist/webview')],
88
90
  });
89
91
 
90
92
  // Vite development mode and production mode inject different webview codes to reduce development work
91
- panel.webview.html = __getWebviewHtml__({
93
+ panel.webview.html = getWebviewHtml({
92
94
  // vite dev mode
93
95
  serverUrl: process.env.VITE_DEV_SERVER_URL,
94
96
  // vite prod mode
@@ -178,7 +180,9 @@ export default defineConfig({
178
180
  - page one
179
181
 
180
182
  ```ts
181
- __getWebviewHtml__({
183
+ import { getWebviewHtml } from 'virtual:vscode';
184
+
185
+ getWebviewHtml({
182
186
  // vite dev mode
183
187
  serverUrl: process.env.VITE_DEV_SERVER_URL,
184
188
  // vite prod mode
@@ -190,7 +194,9 @@ __getWebviewHtml__({
190
194
  - page two
191
195
 
192
196
  ```ts
193
- __getWebviewHtml__({
197
+ import { getWebviewHtml } from 'virtual:vscode';
198
+
199
+ getWebviewHtml({
194
200
  // vite dev mode
195
201
  serverUrl: `${process.env.VITE_DEV_SERVER_URL}/index2.html`,
196
202
  // vite prod mode
@@ -203,7 +209,9 @@ __getWebviewHtml__({
203
209
  - A single page uses different parameters to achieve different functions
204
210
 
205
211
  ```ts
206
- __getWebviewHtml__({
212
+ import { getWebviewHtml } from 'virtual:vscode';
213
+
214
+ getWebviewHtml({
207
215
  // vite dev mode
208
216
  serverUrl: `${process.env.VITE_DEV_SERVER_URL}?id=666`,
209
217
  // vite prod mode
@@ -238,11 +246,6 @@ interface WebviewHtmlOptions {
238
246
  */
239
247
  injectCode?: string;
240
248
  }
241
-
242
- /**
243
- * Gets the html of webview
244
- */
245
- function __getWebviewHtml__(options?: WebviewHtmlOptions): string;
246
249
  ```
247
250
 
248
251
  ### Warning
@@ -253,10 +256,6 @@ When using the `acquireVsCodeApi().getState()` method of [@types/vscode-webview]
253
256
  const value = await acquireVsCodeApi().getState();
254
257
  ```
255
258
 
256
- ## Documentation
257
-
258
- - [index.d.ts](https://www.unpkg.com/browse/@tomjs/vite-plugin-vscode/dist/index.d.ts) provided by [unpkg.com](https://www.unpkg.com).
259
-
260
259
  ## Parameters
261
260
 
262
261
  ### PluginOptions
@@ -275,18 +274,6 @@ The `recommended` option is used to set the default configuration and behavior,
275
274
  - The output directory is based on the `build.outDir` parameter of `vite`, and outputs `extension` and `src` to `dist/extension` and `dist/webview` respectively.
276
275
  - Other behaviors to be implemented
277
276
 
278
- #### Webview
279
-
280
- Inject [@tomjs/vscode-extension-webview](https://github.com/tomjs/vscode-extension-webview) into vscode extension code and web client code, so that `webview` can support `HMR` during the development stage.
281
-
282
- - vite serve
283
- - extension: Inject `import __getWebviewHtml__ from '@tomjs/vite-plugin-vscode/webview';` at the top of the file that calls the `__getWebviewHtml__` method
284
- - web: Add `<script>` tag to index.html and inject `@tomjs/vite-plugin-vscode/client` code
285
- - vite build
286
- - extension: Inject `import __getWebviewHtml__ from '@tomjs/vite-plugin-vscode-inject';` at the top of the file that calls the `__getWebviewHtml__` method
287
-
288
- If is string, will set inject method name. Default is `__getWebviewHtml__`.
289
-
290
277
  #### devtools
291
278
 
292
279
  During development, support standalone development tool applications for `react` and `vue`, enabled by default.
@@ -308,7 +295,6 @@ Based on [Options](https://tsdown.dev/reference/api/Interface.Options) of [tsdow
308
295
 
309
296
  | Property | Type | Default | Description |
310
297
  | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
311
- | name | `string` | `__getWebviewHtml__` | The inject method name |
312
298
  | csp | `string` | `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src {{cspSource}} 'unsafe-inline'; script-src 'nonce-{{nonce}}' 'unsafe-eval';">` | The `CSP` meta for the webview |
313
299
 
314
300
  - `{{cspSource}}`: [webview.cspSource](https://code.visualstudio.com/api/references/vscode-api#Webview)
@@ -443,6 +429,38 @@ Open the [examples](./examples) directory, there are `vue` and `react` examples.
443
429
 
444
430
  ## Important Notes
445
431
 
432
+ ### v6.0.0
433
+
434
+ **Breaking Updates:**
435
+
436
+ Change the global `__getWebviewHtml__` method to a virtual module method called `import { getWebviewHtml } from 'virtual:vscode';`.
437
+
438
+ before:
439
+
440
+ ```ts
441
+ __getWebviewHtml__({
442
+ // vite 开发模式
443
+ serverUrl: process.env.VITE_DEV_SERVER_URL,
444
+ // vite 生产模式
445
+ webview,
446
+ context,
447
+ });
448
+ ```
449
+
450
+ after:
451
+
452
+ ```ts
453
+ import { getWebviewHtml } from 'virtual:vscode';
454
+
455
+ getWebviewHtml({
456
+ // vite 开发模式
457
+ serverUrl: process.env.VITE_DEV_SERVER_URL,
458
+ // vite 生产模式
459
+ webview,
460
+ context,
461
+ });
462
+ ```
463
+
446
464
  ### v5.0.0
447
465
 
448
466
  **Breaking Updates:**
package/README.zh_CN.md CHANGED
@@ -82,13 +82,15 @@ npm i @tomjs/vite-plugin-vscode -D
82
82
  代码片段,更多配置看示例
83
83
 
84
84
  ```ts
85
+ import { getWebviewHtml } from 'virtual:vscode';
86
+
85
87
  const panel = window.createWebviewPanel('showHelloWorld', 'Hello World', ViewColumn.One, {
86
88
  enableScripts: true,
87
89
  localResourceRoots: [Uri.joinPath(extensionUri, 'dist/webview')],
88
90
  });
89
91
 
90
92
  // vite 开发模式和生产模式注入不同的webview代码,减少开发工作
91
- panel.webview.html = __getWebviewHtml__({
93
+ panel.webview.html = getWebviewHtml({
92
94
  // vite 开发模式
93
95
  serverUrl: process.env.VITE_DEV_SERVER_URL,
94
96
  // vite 生产模式
@@ -177,7 +179,9 @@ export default defineConfig({
177
179
  - 页面一
178
180
 
179
181
  ```ts
180
- __getWebviewHtml__({
182
+ import { getWebviewHtml } from 'virtual:vscode';
183
+
184
+ getWebviewHtml({
181
185
  // vite 开发模式
182
186
  serverUrl: process.env.VITE_DEV_SERVER_URL,
183
187
  // vite 生产模式
@@ -189,7 +193,9 @@ __getWebviewHtml__({
189
193
  - 页面二
190
194
 
191
195
  ```ts
192
- __getWebviewHtml__({
196
+ import { getWebviewHtml } from 'virtual:vscode';
197
+
198
+ getWebviewHtml({
193
199
  // vite 开发模式
194
200
  serverUrl: `${process.env.VITE_DEV_SERVER_URL}/index2.html`,
195
201
  // vite 生产模式
@@ -202,7 +208,9 @@ __getWebviewHtml__({
202
208
  - 单个页面通过不同参数来实现不同功能
203
209
 
204
210
  ```ts
205
- __getWebviewHtml__({
211
+ import { getWebviewHtml } from 'virtual:vscode';
212
+
213
+ getWebviewHtml({
206
214
  // vite 开发模式
207
215
  serverUrl: `${process.env.VITE_DEV_SERVER_URL}?id=666`,
208
216
  // vite 生产模式
@@ -237,11 +245,6 @@ interface WebviewHtmlOptions {
237
245
  */
238
246
  injectCode?: string;
239
247
  }
240
-
241
- /**
242
- * 获取webview的html
243
- */
244
- function __getWebviewHtml__(options?: WebviewHtmlOptions): string;
245
248
  ```
246
249
 
247
250
  ### 警告
@@ -252,10 +255,6 @@ function __getWebviewHtml__(options?: WebviewHtmlOptions): string;
252
255
  const value = await acquireVsCodeApi().getState();
253
256
  ```
254
257
 
255
- ## 文档
256
-
257
- - [unpkg.com](https://www.unpkg.com/) 提供的 [index.d.ts](https://www.unpkg.com/browse/@tomjs/vite-plugin-vscode/dist/index.d.ts).
258
-
259
258
  ## 参数
260
259
 
261
260
  ### PluginOptions
@@ -275,18 +274,6 @@ const value = await acquireVsCodeApi().getState();
275
274
 
276
275
  - 其他待实现的行为
277
276
 
278
- #### Webview
279
-
280
- 在 vscode 扩展代码和 web 客户端代码中注入 [@tomjs/vscode-extension-webview](https://github.com/tomjs/vscode-extension-webview),使 `webview` 在开发阶段能够支持 `HMR`。
281
-
282
- - vite serve
283
- - extension: 在调用 `__getWebviewHtml__` 方法的文件顶部注入 `import __getWebviewHtml__ from '@tomjs/vscode-extension-webview';`
284
- - web: 在 index.html 中添加 `<script>` 标签,注入 `@tomjs/vscode-extension-webview/client` 代码
285
- - vite build
286
- - extension: 在调用 `__getWebviewHtml__` 方法的文件顶部注入 `import __getWebviewHtml__ from '@tomjs/vite-plugin-vscode-inject';`
287
-
288
- 如果为字符串,则设置注入方法名,默认为 `__getWebviewHtml__`。
289
-
290
277
  #### devtools
291
278
 
292
279
  开发阶段,支持 `react` 和 `vue` 的独立开发工具应用,默认开启。
@@ -308,7 +295,6 @@ const value = await acquireVsCodeApi().getState();
308
295
 
309
296
  | 参数名 | 类型 | 默认值 | 说明 |
310
297
  | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
311
- | name | `string` | `__getWebviewHtml__` | 注入的方法名 |
312
298
  | csp | `string` | `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src {{cspSource}} 'unsafe-inline'; script-src 'nonce-{{nonce}}' 'unsafe-eval';">` | webview 的 `CSP` |
313
299
 
314
300
  - `{{cspSource}}`: [webview.cspSource](https://code.visualstudio.com/api/references/vscode-api#Webview)
@@ -447,6 +433,38 @@ pnpm build
447
433
 
448
434
  ## 重要说明
449
435
 
436
+ ### v6.0.0
437
+
438
+ **破坏性更新:**
439
+
440
+ 全局的 `__getWebviewHtml__` 方法改为 `import { getWebviewHtml } from 'virtual:vscode';` 这种虚拟模块方式调用。
441
+
442
+ 之前:
443
+
444
+ ```ts
445
+ __getWebviewHtml__({
446
+ // vite 开发模式
447
+ serverUrl: process.env.VITE_DEV_SERVER_URL,
448
+ // vite 生产模式
449
+ webview,
450
+ context,
451
+ });
452
+ ```
453
+
454
+ 之后:
455
+
456
+ ```ts
457
+ import { getWebviewHtml } from 'virtual:vscode';
458
+
459
+ getWebviewHtml({
460
+ // vite 开发模式
461
+ serverUrl: process.env.VITE_DEV_SERVER_URL,
462
+ // vite 生产模式
463
+ webview,
464
+ context,
465
+ });
466
+ ```
467
+
450
468
  ### v5.0.0
451
469
 
452
470
  **破坏性更新:**
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { UserConfig } from "tsdown";
1
+ import { InlineConfig } from "tsdown";
2
2
  import { PluginOption } from "vite";
3
3
 
4
4
  //#region src/types.d.ts
5
5
  /**
6
6
  * vscode extension options. See [tsdown](https://tsdown.dev/) and [Config Options](https://tsdown.dev/reference/config-options) for more information.
7
7
  */
8
- interface ExtensionOptions extends Omit<UserConfig, 'entry' | 'format' | 'outDir' | 'watch'> {
8
+ interface ExtensionOptions extends Omit<InlineConfig, 'entry' | 'format' | 'outDir' | 'watch'> {
9
9
  /**
10
10
  * The extension entry file.
11
11
  * @default "extension/index.ts"
@@ -27,10 +27,6 @@ interface ExtensionOptions extends Omit<UserConfig, 'entry' | 'format' | 'outDir
27
27
  * vscode webview options.
28
28
  */
29
29
  interface WebviewOption {
30
- /**
31
- * The method name to inject. Default is `__getWebviewHtml__`
32
- */
33
- name?: string;
34
30
  /**
35
31
  * The CSP meta for the webview. Default is `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src {{cspSource}} 'unsafe-inline'; script-src 'nonce-{{nonce}}' 'unsafe-eval';">`
36
32
  */
@@ -49,22 +45,17 @@ interface PluginOptions {
49
45
  */
50
46
  recommended?: boolean;
51
47
  /**
52
- * Inject code into vscode extension code and web client code, so that webview can support HMR during the development stage.
53
- *
54
- * - vite serve
55
- * - extension: Inject `import __getWebviewHtml__ from '@tomjs/vite-plugin-vscode/webview';` at the top of the file that calls the `__getWebviewHtml__` method
56
- * - web: Add `<script>` tag to index.html and inject `@tomjs/vite-plugin-vscode/client` code
57
- * - vite build
58
- * - extension: Inject `import __getWebviewHtml__ from '@tomjs/vite-plugin-vscode-inject';` at the top of the file that calls the `__getWebviewHtml__` method
59
- *
60
- * If is string, will set inject method name. Default is '__getWebviewHtml__'.
48
+ * During development, inject code into both `vscode extension code` and `web page` code to support `HMR`;
61
49
  *
50
+ * During production builds, inject the final generated `index.html` code into the `vscode extension code` to minimize manual effort.
62
51
  *
63
52
  * @example
64
53
  * extension file
65
54
  * ```ts
55
+ *import {getWebviewHtml} from 'virtual:vscode';
56
+ *
66
57
  *function setupHtml(webview: Webview, context: ExtensionContext) {
67
- * return __getWebviewHtml__({serverUrl:WebviewHtmlOptions, webview, context});
58
+ * return getWebviewHtml({serverUrl:process.env.VITE_DEV_SERVER_URL, webview, context});
68
59
  *}
69
60
  * ```
70
61
  */
package/dist/index.js CHANGED
@@ -1,9 +1,8 @@
1
1
  import path from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import fs from "node:fs";
4
- import os from "node:os";
5
4
  import { cwd } from "node:process";
6
- import { emptyDirSync, readFileSync, readJsonSync } from "@tomjs/node";
5
+ import { readFileSync, readJsonSync } from "@tomjs/node";
7
6
  import { execa } from "execa";
8
7
  import merge from "lodash.merge";
9
8
  import { parse } from "node-html-parser";
@@ -19,8 +18,8 @@ const __dirname = /* @__PURE__ */ getDirname();
19
18
  //#region src/constants.ts
20
19
  const PLUGIN_NAME = "tomjs:vscode";
21
20
  const ORG_NAME = "@tomjs";
22
- const PACKAGE_NAME = "@tomjs/vite-plugin-vscode";
23
- const WEBVIEW_METHOD_NAME = "__getWebviewHtml__";
21
+ const VIRTUAL_MODULE_ID = "virtual:vscode";
22
+ const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
24
23
 
25
24
  //#endregion
26
25
  //#region src/logger.ts
@@ -92,9 +91,7 @@ function preMergeOptions(options) {
92
91
  treeshake: !isDev,
93
92
  publint: false,
94
93
  config: false,
95
- outExtensions() {
96
- return { js: ".js" };
97
- },
94
+ fixedExtension: false,
98
95
  external: ["vscode"]
99
96
  }
100
97
  }, options);
@@ -116,19 +113,10 @@ function preMergeOptions(options) {
116
113
  }
117
114
  if (!isDev && !opt.skipNodeModulesBundle && !opt.noExternal) opt.noExternal = Object.keys(pkg.dependencies || {}).concat(Object.keys(pkg.peerDependencies || {}));
118
115
  opts.extension = opt;
119
- if (opts.webview !== false) {
120
- let name = WEBVIEW_METHOD_NAME;
121
- if (typeof opts.webview === "string") name = opts.webview ?? WEBVIEW_METHOD_NAME;
122
- opts.webview = Object.assign({ name }, opts.webview);
123
- }
124
116
  return opts;
125
117
  }
126
- const prodCachePkgName = `${PACKAGE_NAME}-inject`;
127
118
  function genProdWebviewCode(cache, webview) {
128
119
  webview = Object.assign({}, webview);
129
- const prodCacheFolder = path.join(cwd(), "node_modules", prodCachePkgName);
130
- emptyDirSync(prodCacheFolder);
131
- const destFile = path.join(prodCacheFolder, "index.js");
132
120
  function handleHtmlCode(html) {
133
121
  const root = parse(html);
134
122
  const head = root.querySelector("head");
@@ -150,7 +138,7 @@ function genProdWebviewCode(cache, webview) {
150
138
  }
151
139
  return root.removeWhitespace().toString();
152
140
  }
153
- const code = `import { Uri } from 'vscode';
141
+ return `import { Uri } from 'vscode';
154
142
 
155
143
  ${`const htmlCode = {
156
144
  ${Object.keys(cache).map((s) => `'${s}': \`${handleHtmlCode(cache[s])}\`,`).join("\n")}
@@ -177,12 +165,6 @@ export default function getWebviewHtml(options){
177
165
  return html.replaceAll('{{cspSource}}', webview.cspSource).replaceAll('{{nonce}}', nonce).replaceAll('{{baseUri}}', baseUri);
178
166
  }
179
167
  `;
180
- fs.writeFileSync(destFile, code, { encoding: "utf8" });
181
- return fixWindowsPath(destFile);
182
- }
183
- function fixWindowsPath(webviewPath) {
184
- if (os.platform() === "win32") webviewPath = webviewPath.replaceAll("\\", "/");
185
- return webviewPath;
186
168
  }
187
169
  function useVSCodePlugin(options) {
188
170
  const opts = preMergeOptions(options);
@@ -208,8 +190,8 @@ function useVSCodePlugin(options) {
208
190
  rollupOptions: { output: rollupOutput }
209
191
  } };
210
192
  };
211
- let devWebviewClient;
212
- if (opts.webview) devWebviewClient = readFileSync(path.join(__dirname, "client.iife.js"));
193
+ let devWebviewClientCode;
194
+ let devWebviewVirtualCode;
213
195
  let resolvedConfig;
214
196
  const prodHtmlCache = {};
215
197
  let devtoolsFlag = false;
@@ -221,6 +203,10 @@ function useVSCodePlugin(options) {
221
203
  },
222
204
  configResolved(config) {
223
205
  resolvedConfig = config;
206
+ if (opts.webview) {
207
+ devWebviewClientCode = readFileSync(path.join(__dirname, "client.iife.js"));
208
+ devWebviewVirtualCode = readFileSync(path.join(__dirname, "webview.js"));
209
+ }
224
210
  },
225
211
  configureServer(server) {
226
212
  if (!server || !server.httpServer) return;
@@ -246,10 +232,11 @@ function useVSCodePlugin(options) {
246
232
  logLevel: logLevel ?? "silent",
247
233
  plugins: !webview ? [] : [{
248
234
  name: `${ORG_NAME}:vscode:inject`,
249
- transform(code, id) {
250
- if (id.includes("node_modules")) return;
251
- if (code.includes(`${webview.name}(`)) return `import ${webview.name} from '${PACKAGE_NAME}/webview';\n${code}`;
252
- return code;
235
+ resolveId(id) {
236
+ if (id === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_MODULE_ID;
237
+ },
238
+ load(id) {
239
+ if (id === RESOLVED_VIRTUAL_MODULE_ID) return devWebviewVirtualCode;
253
240
  }
254
241
  }],
255
242
  async onSuccess(config, signal) {
@@ -275,7 +262,7 @@ function useVSCodePlugin(options) {
275
262
  logger.warn("Only support react-devtools and vue-devtools!");
276
263
  }
277
264
  }
278
- return html.replace(/<head>/i, `<head><script>${devWebviewClient}<\/script>`);
265
+ return html.replace(/<head>/i, `<head><script>${devWebviewClientCode}<\/script>`);
279
266
  }
280
267
  }, {
281
268
  name: "@tomjs:vscode",
@@ -293,9 +280,9 @@ function useVSCodePlugin(options) {
293
280
  return html;
294
281
  },
295
282
  closeBundle() {
296
- let webviewPath;
283
+ let webviewVirtualCode;
297
284
  const webview = opts?.webview;
298
- if (webview) webviewPath = genProdWebviewCode(prodHtmlCache, webview);
285
+ if (webview) webviewVirtualCode = genProdWebviewCode(prodHtmlCache, webview);
299
286
  let outDir = resolvedConfig.build.outDir.replace(cwd(), "").replaceAll("\\", "/");
300
287
  if (outDir.startsWith("/")) outDir = outDir.substring(1);
301
288
  const env = {
@@ -309,10 +296,11 @@ function useVSCodePlugin(options) {
309
296
  logLevel: logLevel ?? "silent",
310
297
  plugins: !webview ? [] : [{
311
298
  name: `${ORG_NAME}:vscode:inject`,
312
- transform(code, id) {
313
- if (id.includes("node_modules")) return;
314
- if (code.includes(`${webview.name}(`)) return `import ${webview.name} from "${webviewPath}";\n${code}`;
315
- return code;
299
+ resolveId(id) {
300
+ if (id === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_MODULE_ID;
301
+ },
302
+ load(id) {
303
+ if (id === RESOLVED_VIRTUAL_MODULE_ID) return webviewVirtualCode;
316
304
  }
317
305
  }],
318
306
  async onSuccess(config, signal) {
package/dist/webview.js CHANGED
@@ -1,188 +1,18 @@
1
- var e=`<!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <style>
8
- html,
9
- body {
10
- width: 100%;
11
- height: 100%;
12
- margin: 0;
13
- padding: 0;
14
- overflow: hidden;
15
- }
16
-
17
- #webview-patch-iframe {
18
- width: 100%;
19
- height: 100%;
20
- border: none;
21
- }
22
-
23
- .outer {
24
- width: 100%;
25
- height: 100%;
26
- overflow: hidden;
27
- }
28
- </style>
29
-
30
- <script type="module" id="webview-patch">
31
- const TAG = '[@tomjs:vscode:extension] ';
32
-
33
- function onDomReady(callback, doc) {
34
- const _doc = doc || document;
35
- if (_doc.readyState === 'interactive' || _doc.readyState === 'complete') {
36
- callback();
37
- } else {
38
- _doc.addEventListener('DOMContentLoaded', callback);
39
- }
40
- }
41
-
42
- let vsCodeApi;
43
-
44
- function getApi() {
45
- if (vsCodeApi) return vsCodeApi;
46
- return (vsCodeApi = acquireVsCodeApi());
47
- }
48
-
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
- );
74
- }
75
-
76
- function observeAttributeChanges(element, attributeName, callback) {
77
- const observer = new MutationObserver(function (mutationsList) {
78
- for (let mutation of mutationsList) {
79
- if (mutation.type === 'attributes' && mutation.attributeName === attributeName) {
80
- callback(mutation.target.getAttribute(attributeName));
81
- }
82
- }
83
- });
84
- observer.observe(element, { attributes: true });
85
- return observer;
86
- }
87
-
88
- // message handler
89
- let iframeLoaded = false;
90
- const cacheMessages = [];
91
-
92
- function handleMessage(e) {
93
- const iframe = document.getElementById('webview-patch-iframe');
94
- if (!iframeLoaded || !iframe) {
95
- return;
96
- }
97
- if (e.origin.startsWith('vscode-webview://')) {
98
- iframe.contentWindow.postMessage(e.data, '*');
99
- } else if ('{{serverUrl}}'.startsWith(e.origin)) {
100
- const { type, data } = e.data;
101
- console.log(TAG + ' received:', e.data);
102
- if (type === '[vscode:client]:postMessage') {
103
- getApi().postMessage(data);
104
- } else if (type === '[vscode:client]:commands') {
105
- if (data === 'F1') {
106
- window.dispatchEvent(
107
- new KeyboardEvent('keydown', {
108
- key: 'F1',
109
- keyCode: 112,
110
- code: 'F1',
111
- }),
112
- );
113
- }
114
- }
115
- }
116
- }
117
-
118
- window.addEventListener('message', function (event) {
119
- if (event.origin.startsWith('vscode-webview://')) {
120
- cacheMessages.push(event);
121
- return;
122
- }
123
- handleMessage(event);
124
- });
125
-
126
- let isCacheWorking = false;
127
- setInterval(() => {
128
- if (isCacheWorking) {
129
- return;
130
- }
131
-
132
- isCacheWorking = true;
133
- if (iframeLoaded) {
134
- let event = cacheMessages.shift();
135
- while (event) {
136
- handleMessage(event);
137
- event = cacheMessages.shift();
138
- }
139
- }
140
- isCacheWorking = false;
141
- }, 50);
142
-
143
- onDomReady(function () {
144
- /** @type {HTMLIFrameElement} */
145
- const iframe = document.getElementById('webview-patch-iframe');
146
- observeAttributeChanges(document.body, 'class', function (className) {
147
- sendInitData(iframe);
148
- });
149
-
150
- onDomReady(function () {
151
- iframeLoaded = true;
152
- sendInitData(iframe);
153
- }, iframe.contentDocument);
154
-
155
- iframe.addEventListener('load', function (e) {
156
- iframeLoaded = true;
157
-
158
- let interval = setInterval(() => {
159
- try {
160
- if (document.getElementById('_defaultStyles')) {
161
- sendInitData(iframe);
162
- // addListeners(iframe);
163
- clearInterval(interval);
164
- return;
165
- }
166
- } catch (e) {
167
- clearInterval(interval);
168
- console.error(e);
169
- }
170
- }, 10);
171
- });
172
- });
173
- <\/script>
174
- </head>
175
-
176
- <body>
177
- <div class="outer">
178
- <iframe
179
- id="webview-patch-iframe"
180
- frameborder="0"
181
- sandbox="allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-downloads"
182
- allow="cross-origin-isolated; autoplay; clipboard-read; clipboard-write"
183
- src="{{serverUrl}}"
184
- ></iframe>
185
- </div>
186
- </body>
187
- </html>
188
- `;function t(t){let n={serverUrl:``};return Object.assign(n,t),e.replace(/\{\{serverUrl\}\}/g,n.serverUrl)}var n=t;export{n as default,t as getWebviewHtml};
1
+ //#region src/webview/template.html
2
+ var template_default = "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <style>\n html,\n body {\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n overflow: hidden;\n }\n\n #webview-patch-iframe {\n width: 100%;\n height: 100%;\n border: none;\n }\n\n .outer {\n width: 100%;\n height: 100%;\n overflow: hidden;\n }\n </style>\n\n <script type=\"module\" id=\"webview-patch\">\n const TAG = '[@tomjs:vscode:extension] ';\n\n function onDomReady(callback, doc) {\n const _doc = doc || document;\n if (_doc.readyState === 'interactive' || _doc.readyState === 'complete') {\n callback();\n } else {\n _doc.addEventListener('DOMContentLoaded', callback);\n }\n }\n\n let vsCodeApi;\n\n function getApi() {\n if (vsCodeApi) return vsCodeApi;\n return (vsCodeApi = acquireVsCodeApi());\n }\n\n function sendInitData(iframe) {\n console.log(TAG + 'init data');\n const dataset = {};\n Object.keys(document.body.dataset).forEach((key) => {\n dataset[key] = document.body.dataset[key];\n });\n\n iframe.contentWindow.postMessage(\n {\n type: '[vscode:extension]:init',\n data: {\n state: getApi().getState(),\n style: document.getElementById('_defaultStyles').innerHTML,\n root: {\n cssText: document.documentElement.style.cssText,\n },\n body: {\n dataset: dataset,\n className: document.body.className,\n role: document.body.getAttribute('role'),\n },\n },\n },\n '*',\n );\n }\n\n function observeAttributeChanges(element, attributeName, callback) {\n const observer = new MutationObserver(function (mutationsList) {\n for (let mutation of mutationsList) {\n if (mutation.type === 'attributes' && mutation.attributeName === attributeName) {\n callback(mutation.target.getAttribute(attributeName));\n }\n }\n });\n observer.observe(element, { attributes: true });\n return observer;\n }\n\n // message handler\n let iframeLoaded = false;\n const cacheMessages = [];\n\n function handleMessage(e) {\n const iframe = document.getElementById('webview-patch-iframe');\n if (!iframeLoaded || !iframe) {\n return;\n }\n if (e.origin.startsWith('vscode-webview://')) {\n iframe.contentWindow.postMessage(e.data, '*');\n } else if ('{{serverUrl}}'.startsWith(e.origin)) {\n const { type, data } = e.data;\n console.log(TAG + ' received:', e.data);\n if (type === '[vscode:client]:postMessage') {\n getApi().postMessage(data);\n } else if (type === '[vscode:client]:commands') {\n if (data === 'F1') {\n window.dispatchEvent(\n new KeyboardEvent('keydown', {\n key: 'F1',\n keyCode: 112,\n code: 'F1',\n }),\n );\n }\n }\n }\n }\n\n window.addEventListener('message', function (event) {\n if (event.origin.startsWith('vscode-webview://')) {\n cacheMessages.push(event);\n return;\n }\n handleMessage(event);\n });\n\n let isCacheWorking = false;\n setInterval(() => {\n if (isCacheWorking) {\n return;\n }\n\n isCacheWorking = true;\n if (iframeLoaded) {\n let event = cacheMessages.shift();\n while (event) {\n handleMessage(event);\n event = cacheMessages.shift();\n }\n }\n isCacheWorking = false;\n }, 50);\n\n onDomReady(function () {\n /** @type {HTMLIFrameElement} */\n const iframe = document.getElementById('webview-patch-iframe');\n observeAttributeChanges(document.body, 'class', function (className) {\n sendInitData(iframe);\n });\n\n onDomReady(function () {\n iframeLoaded = true;\n sendInitData(iframe);\n }, iframe.contentDocument);\n\n iframe.addEventListener('load', function (e) {\n iframeLoaded = true;\n\n let interval = setInterval(() => {\n try {\n if (document.getElementById('_defaultStyles')) {\n sendInitData(iframe);\n // addListeners(iframe);\n clearInterval(interval);\n return;\n }\n } catch (e) {\n clearInterval(interval);\n console.error(e);\n }\n }, 10);\n });\n });\n <\/script>\n </head>\n\n <body>\n <div class=\"outer\">\n <iframe\n id=\"webview-patch-iframe\"\n frameborder=\"0\"\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-downloads\"\n allow=\"cross-origin-isolated; autoplay; clipboard-read; clipboard-write\"\n src=\"{{serverUrl}}\"\n ></iframe>\n </div>\n </body>\n</html>\n";
3
+
4
+ //#endregion
5
+ //#region src/webview/webview.ts
6
+ /**
7
+ *
8
+ * @param options serverUrl string or object options
9
+ */
10
+ function getWebviewHtml(options) {
11
+ const opts = { serverUrl: "" };
12
+ Object.assign(opts, options);
13
+ return template_default.replace(/\{\{serverUrl\}\}/g, opts.serverUrl);
14
+ }
15
+ var webview_default = getWebviewHtml;
16
+
17
+ //#endregion
18
+ export { webview_default as default, getWebviewHtml };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Inject some methods such as `getWebviewHtml`
3
+ */
4
+ declare module 'virtual:vscode' {
5
+ import type { ExtensionContext, Webview } from 'vscode';
6
+
7
+ export interface WebviewHtmlOptions {
8
+ /**
9
+ * `[vite serve]` The url of the vite dev server. Please use `process.env.VITE_DEV_SERVER_URL`
10
+ */
11
+ serverUrl?: string;
12
+ /**
13
+ * `[vite build]` The Webview instance of the extension.
14
+ */
15
+ webview: Webview;
16
+ /**
17
+ * `[vite build]` The ExtensionContext instance of the extension.
18
+ */
19
+ context: ExtensionContext;
20
+ /**
21
+ * `[vite build]` vite build.rollupOptions.input name. Default is `index`.
22
+ */
23
+ inputName?: string;
24
+ /**
25
+ * `[vite build]` Inject code into the afterbegin of the head element.
26
+ */
27
+ injectCode?: string;
28
+ }
29
+
30
+ /**
31
+ * Get the html of the webview.
32
+ *
33
+ * @param options
34
+ */
35
+ export const getWebviewHtml: (options?: WebviewHtmlOptions) => string;
36
+
37
+ export default getWebviewHtml;
38
+ }
package/env.d.ts CHANGED
@@ -1,4 +1,6 @@
1
- import type { ExtensionContext, Webview } from 'vscode';
1
+ /// <reference types="./env-webview.d.ts" />
2
+ import type { WebviewHtmlOptions } from 'virtual:vscode';
3
+
2
4
  // Make this a module
3
5
  export {};
4
6
  declare global {
@@ -24,31 +26,25 @@ declare global {
24
26
  }
25
27
  }
26
28
 
27
- interface WebviewHtmlOptions {
28
- /**
29
- * `[vite serve]` The url of the vite dev server. Please use `process.env.VITE_DEV_SERVER_URL`
30
- */
31
- serverUrl?: string;
32
- /**
33
- * `[vite build]` The Webview instance of the extension.
34
- */
35
- webview: Webview;
36
- /**
37
- * `[vite build]` The ExtensionContext instance of the extension.
38
- */
39
- context: ExtensionContext;
40
- /**
41
- * `[vite build]` vite build.rollupOptions.input name. Default is `index`.
42
- */
43
- inputName?: string;
44
- /**
45
- * `[vite build]` Inject code into the afterbegin of the head element.
46
- */
47
- injectCode?: string;
48
- }
49
-
50
29
  /**
51
- * Gets the html of webview
30
+ * Gets the html of webview. It's deprecated. Please use `import { getWebviewHtml } from 'virtual:vscode';`.
31
+ *
32
+ * @example
33
+ * import type { ExtensionContext, Webview } from 'vscode';
34
+ * import { getWebviewHtml } from 'virtual:vscode';
35
+ * import { window } from 'vscode';
36
+ *
37
+ * export class WebviewHelper {
38
+ * public static setupHtml(webview: Webview, context: ExtensionContext) {
39
+ * return getWebviewHtml({
40
+ * serverUrl: process.env.VITE_DEV_SERVER_URL,
41
+ * webview,
42
+ * context,
43
+ * injectCode: `<script>window.__FLAG1__=666;window.__FLAG2__=888;</script>`,
44
+ * });
45
+ * }
46
+ *
47
+ * @deprecated
52
48
  */
53
49
  function __getWebviewHtml__(options?: WebviewHtmlOptions): string;
54
50
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tomjs/vite-plugin-vscode",
3
3
  "type": "module",
4
- "version": "5.2.1",
4
+ "version": "6.0.1",
5
5
  "description": "Use vue/react to develop 'vscode extension webview', supporting esm/cjs",
6
6
  "author": {
7
7
  "name": "Tom Gao",
@@ -21,8 +21,7 @@
21
21
  "extension",
22
22
  "webview",
23
23
  "esm",
24
- "cjs",
25
- "mjs"
24
+ "cjs"
26
25
  ],
27
26
  "exports": {
28
27
  ".": "./dist/index.js",
@@ -33,8 +32,8 @@
33
32
  "module": "./dist/index.js",
34
33
  "types": "./dist/index.d.ts",
35
34
  "files": [
36
- "dist",
37
- "env.d.ts"
35
+ "*.d.ts",
36
+ "dist"
38
37
  ],
39
38
  "engines": {
40
39
  "node": ">=18.19"
@@ -44,27 +43,24 @@
44
43
  "registry": "https://registry.npmjs.org/"
45
44
  },
46
45
  "peerDependencies": {
46
+ "@types/vscode": "^1.56.0",
47
47
  "vite": ">=2"
48
48
  },
49
49
  "dependencies": {
50
50
  "@tomjs/logger": "^1.4.0",
51
51
  "@tomjs/node": "^2.2.3",
52
- "dayjs": "^1.11.19",
53
52
  "execa": "^9.6.1",
54
- "kolorist": "^1.8.0",
55
- "lodash.clonedeep": "^4.5.0",
56
53
  "lodash.merge": "^4.6.2",
57
54
  "node-html-parser": "^7.0.1",
58
55
  "tsdown": "~0.18.3"
59
56
  },
60
57
  "devDependencies": {
61
- "@antfu/eslint-config": "^6.7.1",
58
+ "@antfu/eslint-config": "^6.7.3",
62
59
  "@commitlint/cli": "^20.2.0",
63
60
  "@tomjs/commitlint": "^5.0.0",
64
61
  "@tomjs/eslint": "^6.0.0",
65
62
  "@tomjs/stylelint": "^7.0.0",
66
63
  "@tomjs/tsconfig": "^2.2.0",
67
- "@types/lodash.clonedeep": "^4.5.9",
68
64
  "@types/lodash.merge": "^4.6.9",
69
65
  "@types/node": "^20.19.27",
70
66
  "@vitejs/plugin-vue": "^6.0.3",