@tomjs/vite-plugin-vscode 2.2.0 → 2.3.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
@@ -213,7 +213,7 @@ function __getWebviewHtml__(
213
213
  | --- | --- | --- | --- |
214
214
  | recommended | `boolean` | `true` | This option is intended to provide recommended default parameters and behavior. |
215
215
  | extension | [ExtensionOptions](#ExtensionOptions) | | Configuration options for the vscode extension. |
216
- | webview | `boolean` | `false` | 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. |
216
+ | webview | `boolean` \| `string` \| [WebviewOption](#WebviewOption) | `__getWebviewHtml__` | Inject html code |
217
217
 
218
218
  **Notice**
219
219
 
@@ -222,6 +222,16 @@ The `recommended` option is used to set the default configuration and behavior,
222
222
  - The output directory is based on the `build.outDir` parameter of `vite`, and outputs `extension` and `src` to `dist/extension` and `dist/webview` respectively.
223
223
  - Other behaviors to be implemented
224
224
 
225
+ **Webview**
226
+
227
+ 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.
228
+
229
+ - vite serve
230
+ - extension: Inject `import __getWebviewHtml__ from '@tomjs/vscode-extension-webview';` above the file that calls the `__getWebviewHtml__` method
231
+ - web: Add `<script>` tag to index.html and inject `@tomjs/vscode-extension-webview/client` code
232
+ - vite build
233
+ - extension: Inject `import __getWebviewHtml__ from '@tomjs/vite-plugin-vscode-inject';` above the file that calls the `__getWebviewHtml__` method If is string, will set inject method name. Default is `__getWebviewHtml__`.
234
+
225
235
  ### ExtensionOptions
226
236
 
227
237
  Based on [Options](https://paka.dev/npm/tsup) of [tsup](https://tsup.egoist.dev/), some default values are added for ease of use.
@@ -232,6 +242,16 @@ Based on [Options](https://paka.dev/npm/tsup) of [tsup](https://tsup.egoist.dev/
232
242
  | outDir | `string` | `dist-extension/main` | The output directory for the vscode extension file |
233
243
  | onSuccess | `() => Promise<void \| undefined \| (() => void \| Promise<void>)>` | `undefined` | A function that will be executed after the build succeeds. |
234
244
 
245
+ ### WebviewOption
246
+
247
+ | Property | Type | Default | Description |
248
+ | --- | --- | --- | --- |
249
+ | name | `string` | `__getWebviewHtml__` | The inject method name |
250
+ | 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 |
251
+
252
+ - `{{cspSource}}`: [webview.cspSource](https://code.visualstudio.com/api/references/vscode-api#Webview)
253
+ - `{{nonce}}`: uuid
254
+
235
255
  ### Additional Information
236
256
 
237
257
  - Default values for `extension` when the relevant parameters are not configured
package/README.zh_CN.md CHANGED
@@ -46,6 +46,7 @@ npm i @tomjs/vite-plugin-vscode --save-dev
46
46
  |--src // front-end code
47
47
  | |--App.vue
48
48
  | |--main.ts
49
+ |--index.html
49
50
  ```
50
51
 
51
52
  - 零配置,默认 dist 输出目录
@@ -67,6 +68,7 @@ npm i @tomjs/vite-plugin-vscode --save-dev
67
68
  |--webview // front-end code
68
69
  | |--App.vue
69
70
  | |--main.ts
71
+ |--index.html
70
72
  ```
71
73
 
72
74
  ### extension
@@ -215,7 +217,7 @@ function __getWebviewHtml__(
215
217
  | --- | --- | --- | --- |
216
218
  | recommended | `boolean` | `true` | 这个选项是为了提供推荐的默认参数和行为 |
217
219
  | extension | [ExtensionOptions](#ExtensionOptions) | | vscode extension 可选配置 |
218
- | webview | `boolean` | `false` | 在vscode扩展代码和Web客户端代码中注入[@tomjs/vscode-extension-webview](https://github.com/tomjs/vscode-extension-webview),以便webview在开发阶段可以支持HMR。 |
220
+ | webview | `boolean` \| `string` \| [WebviewOption](#WebviewOption) | `__getWebviewHtml__` | 注入 html 代码 |
219
221
 
220
222
  **Notice**
221
223
 
@@ -225,6 +227,16 @@ function __getWebviewHtml__(
225
227
 
226
228
  - 其他待实现的行为
227
229
 
230
+ **Webview**
231
+
232
+ 在 vscode 扩展代码和 web 客户端代码中注入 [@tomjs/vscode-extension-webview](https://github.com/tomjs/vscode-extension-webview),使 `webview` 在开发阶段能够支持 `HMR`。
233
+
234
+ - vite serve
235
+ - extension: 在调用 `__getWebviewHtml__` 方法的文件上方注入 `import __getWebviewHtml__ from '@tomjs/vscode-extension-webview';`
236
+ - web: 在 index.html 中添加 `<script>` 标签,注入 `@tomjs/vscode-extension-webview/client` 代码
237
+ - vite build
238
+ - extension: 在调用 `__getWebviewHtml__` 方法的文件上方注入 `import __getWebviewHtml__ from '@tomjs/vite-plugin-vscode-inject';` 如果为字符串,则设置注入方法名,默认为 `__getWebviewHtml__`。
239
+
228
240
  ### ExtensionOptions
229
241
 
230
242
  继承自 [tsup](https://tsup.egoist.dev/) 的 [Options](https://paka.dev/npm/tsup),添加了一些默认值,方便使用。
@@ -235,6 +247,16 @@ function __getWebviewHtml__(
235
247
  | outDir | `string` | `dist-extension/main` | 输出文件夹 |
236
248
  | onSuccess | `() => Promise<void \| undefined \| (() => void \| Promise<void>)>` | `undefined` | 构建成功后运行的回调函数 |
237
249
 
250
+ ### WebviewOption
251
+
252
+ | 参数名 | 类型 | 默认值 | 说明 |
253
+ | --- | --- | --- | --- |
254
+ | name | `string` | `__getWebviewHtml__` | 注入的方法名 |
255
+ | 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` |
256
+
257
+ - `{{cspSource}}`: [webview.cspSource](https://code.visualstudio.com/api/references/vscode-api#Webview)
258
+ - `{{nonce}}`: uuid
259
+
238
260
  ### 补充说明
239
261
 
240
262
  - `extension` 未配置相关参数时的默认值
package/dist/index.d.mts CHANGED
@@ -28,6 +28,19 @@ interface ExtensionOptions extends Omit<Options, 'entry' | 'format' | 'outDir' |
28
28
  */
29
29
  onSuccess?: () => Promise<void | undefined | (() => void | Promise<void>)>;
30
30
  }
31
+ /**
32
+ * vscode webview options.
33
+ */
34
+ interface WebviewOption {
35
+ /**
36
+ * The method name to inject. Default is '__getWebviewHtml__'
37
+ */
38
+ name?: string;
39
+ /**
40
+ * 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';">`
41
+ */
42
+ csp?: string;
43
+ }
31
44
  /**
32
45
  * vite plugin options.
33
46
  */
@@ -70,7 +83,7 @@ interface PluginOptions {
70
83
  * </html>
71
84
  * ```
72
85
  */
73
- webview?: boolean | string;
86
+ webview?: boolean | string | WebviewOption;
74
87
  /**
75
88
  * extension vite config.
76
89
  */
package/dist/index.d.ts CHANGED
@@ -28,6 +28,19 @@ interface ExtensionOptions extends Omit<Options, 'entry' | 'format' | 'outDir' |
28
28
  */
29
29
  onSuccess?: () => Promise<void | undefined | (() => void | Promise<void>)>;
30
30
  }
31
+ /**
32
+ * vscode webview options.
33
+ */
34
+ interface WebviewOption {
35
+ /**
36
+ * The method name to inject. Default is '__getWebviewHtml__'
37
+ */
38
+ name?: string;
39
+ /**
40
+ * 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';">`
41
+ */
42
+ csp?: string;
43
+ }
31
44
  /**
32
45
  * vite plugin options.
33
46
  */
@@ -70,7 +83,7 @@ interface PluginOptions {
70
83
  * </html>
71
84
  * ```
72
85
  */
73
- webview?: boolean | string;
86
+ webview?: boolean | string | WebviewOption;
74
87
  /**
75
88
  * extension vite config.
76
89
  */
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/index.ts
2
2
  var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs);
3
+ var _os = require('os'); var _os2 = _interopRequireDefault(_os);
3
4
  var _path = require('path'); var _path2 = _interopRequireDefault(_path);
4
5
  var _process = require('process');
5
6
  var _lodashclonedeep = require('lodash.clonedeep'); var _lodashclonedeep2 = _interopRequireDefault(_lodashclonedeep);
@@ -56,11 +57,11 @@ var createLogger = (tag) => {
56
57
  };
57
58
 
58
59
  // src/utils.ts
59
- var _child_process = require('child_process');
60
60
 
61
61
  var _module = require('module');
62
62
 
63
63
 
64
+ var _execa = require('execa'); var _execa2 = _interopRequireDefault(_execa);
64
65
  function readJson(path3) {
65
66
  if (_fs2.default.existsSync(path3)) {
66
67
  return JSON.parse(_fs2.default.readFileSync(path3, "utf8"));
@@ -96,40 +97,32 @@ function resolveServerUrl(server) {
96
97
  return url;
97
98
  }
98
99
  }
99
- function getWebviewNpmPath() {
100
- let npmPath = _path2.default.join(_process.cwd.call(void 0, ), "node_modules", WEBVIEW_PACKAGE_NAME);
101
- if (!_fs2.default.existsSync(npmPath)) {
102
- try {
103
- const res = _child_process.spawnSync.call(void 0,
104
- process.platform === "win32" ? "pnpm.cmd" : "pnpm",
105
- ["list", "--dev", "--depth=1", "--json"],
106
- {
107
- // stdio: ['inherit', 'ignore'],
108
- cwd: process.cwd(),
109
- encoding: "utf-8"
110
- }
111
- );
112
- if (res.status === 0 && res.stdout) {
113
- const list = JSON.parse(res.stdout.trim());
114
- if (list.length === 0) {
115
- return;
116
- }
117
- const self = (list[0].devDependencies || {})[PACKAGE_NAME];
118
- if (!self) {
119
- return;
120
- }
121
- const dep = self.dependencies[WEBVIEW_PACKAGE_NAME];
122
- if (dep) {
123
- npmPath = dep.path;
124
- }
100
+ function getWebviewPnpmPath() {
101
+ try {
102
+ const res = _execa2.default.sync("pnpm", ["list", "--dev", "--depth=1", "--json"], {});
103
+ if (res.stdout) {
104
+ const list = JSON.parse(res.stdout.trim());
105
+ if (list.length === 0) {
106
+ return;
107
+ }
108
+ const self = (list[0].devDependencies || {})[PACKAGE_NAME];
109
+ if (!self) {
110
+ return;
111
+ }
112
+ const dep = self.dependencies[WEBVIEW_PACKAGE_NAME];
113
+ if (dep) {
114
+ return dep.path;
125
115
  }
126
- } catch (e) {
127
- npmPath = "";
128
- }
129
- if (npmPath) {
130
- return _path2.default.join(npmPath, "dist");
131
116
  }
117
+ } catch (e) {
118
+ }
119
+ }
120
+ function getWebviewNpmPath() {
121
+ const npmPath = _path2.default.join(_process.cwd.call(void 0, ), "node_modules", WEBVIEW_PACKAGE_NAME);
122
+ if (_fs2.default.existsSync(npmPath)) {
123
+ return npmPath;
132
124
  }
125
+ return getWebviewPnpmPath();
133
126
  }
134
127
 
135
128
  // src/index.ts
@@ -192,14 +185,18 @@ function preMergeOptions(options) {
192
185
  );
193
186
  }
194
187
  opts.extension = opt;
195
- if (opts.webview === true) {
196
- opts.webview = WEBVIEW_METHOD_NAME;
188
+ if (opts.webview !== false) {
189
+ let name = WEBVIEW_METHOD_NAME;
190
+ if (typeof opts.webview === "string") {
191
+ name = _nullishCoalesce(opts.webview, () => ( WEBVIEW_METHOD_NAME));
192
+ }
193
+ opts.webview = Object.assign({ name }, opts.webview);
197
194
  }
198
- opts.webview = _nullishCoalesce(opts.webview, () => ( WEBVIEW_METHOD_NAME));
199
195
  return opts;
200
196
  }
201
197
  var prodCachePkgName = `${PACKAGE_NAME}-inject`;
202
- function genProdWebviewCode(cache) {
198
+ function genProdWebviewCode(cache, webview) {
199
+ webview = Object.assign({}, webview);
203
200
  const prodCacheFolder = _path2.default.join(_process.cwd.call(void 0, ), "node_modules", prodCachePkgName);
204
201
  emptyPath(prodCacheFolder);
205
202
  const destFile = _path2.default.join(prodCacheFolder, "index.ts");
@@ -209,26 +206,25 @@ function genProdWebviewCode(cache) {
209
206
  if (!head) {
210
207
  root == null ? void 0 : root.insertAdjacentHTML("beforeend", "<head></head>");
211
208
  }
212
- head.insertAdjacentHTML(
213
- "afterbegin",
214
- `
215
- <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src {{cspSource}} 'unsafe-inline'; script-src 'nonce-{{nonce}}' 'unsafe-eval';">`
216
- );
217
- const tags = {
218
- script: "src",
219
- link: "href"
220
- };
221
- Object.keys(tags).forEach((tag) => {
222
- const elements = root.querySelectorAll(tag);
223
- elements.forEach((element) => {
224
- const attr = element.getAttribute(tags[tag]);
225
- if (attr) {
226
- element.setAttribute(tags[tag], `{{baseUri}}${attr}`);
227
- }
228
- element.setAttribute("nonce", "{{nonce}}");
209
+ const csp = (webview == null ? void 0 : webview.csp) || `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src {{cspSource}} 'unsafe-inline'; script-src 'nonce-{{nonce}}' 'unsafe-eval';">`;
210
+ head.insertAdjacentHTML("afterbegin", csp);
211
+ if (csp && csp.includes("{{nonce}}")) {
212
+ const tags = {
213
+ script: "src",
214
+ link: "href"
215
+ };
216
+ Object.keys(tags).forEach((tag) => {
217
+ const elements = root.querySelectorAll(tag);
218
+ elements.forEach((element) => {
219
+ const attr = element.getAttribute(tags[tag]);
220
+ if (attr) {
221
+ element.setAttribute(tags[tag], `{{baseUri}}${attr}`);
222
+ }
223
+ element.setAttribute("nonce", "{{nonce}}");
224
+ });
229
225
  });
230
- });
231
- return root.toString();
226
+ }
227
+ return root.removeWhitespace().toString();
232
228
  }
233
229
  const cacheCode = (
234
230
  /* js */
@@ -255,12 +251,18 @@ export default function getWebviewHtml(webview: Webview, context: ExtensionConte
255
251
  const nonce = uuid();
256
252
  const baseUri = webview.asWebviewUri(Uri.joinPath(context.extensionUri, (process.env.VITE_WEBVIEW_DIST || 'dist')));
257
253
  const html = htmlCode[inputName || 'index'] || '';
258
- return html.replaceAll('{{cspSource}}',webview.cspSource).replaceAll('{{nonce}}', nonce).replaceAll('{{baseUri}}', baseUri);
254
+ return html.replaceAll('{{cspSource}}', webview.cspSource).replaceAll('{{nonce}}', nonce).replaceAll('{{baseUri}}', baseUri);
259
255
  }
260
256
  `
261
257
  );
262
258
  _fs2.default.writeFileSync(destFile, code, { encoding: "utf8" });
263
- return destFile.replaceAll("\\", "/");
259
+ return fixWindowsPath(destFile);
260
+ }
261
+ function fixWindowsPath(webviewPath) {
262
+ if (_os2.default.platform() === "win32") {
263
+ webviewPath = webviewPath.replaceAll("\\", "/");
264
+ }
265
+ return webviewPath;
264
266
  }
265
267
  function useVSCodePlugin(options) {
266
268
  const opts = preMergeOptions(options);
@@ -294,19 +296,22 @@ function useVSCodePlugin(options) {
294
296
  }
295
297
  };
296
298
  };
297
- let webviewClient;
298
- let webviewNpmPath;
299
+ let devWebviewClient;
300
+ let devWebviewPath;
299
301
  if (opts.webview) {
300
- webviewNpmPath = getWebviewNpmPath();
301
- if (!webviewNpmPath || !_fs2.default.existsSync(webviewNpmPath)) {
302
+ devWebviewPath = getWebviewNpmPath();
303
+ if (devWebviewPath && _os2.default.platform() === "win32") {
304
+ devWebviewPath = devWebviewPath.replaceAll("\\", "/");
305
+ }
306
+ if (!devWebviewPath || !_fs2.default.existsSync(devWebviewPath)) {
302
307
  logger.warn(`[${WEBVIEW_PACKAGE_NAME}] is not installed, please install it first!`);
303
308
  } else {
304
309
  const fileName = "client.global.js";
305
- const clientFile = _path2.default.join(webviewNpmPath, fileName);
310
+ const clientFile = _path2.default.join(devWebviewPath, "dist", fileName);
306
311
  if (!_fs2.default.existsSync(clientFile)) {
307
312
  logger.warn(`[${fileName}] is does not exist, please update the package!`);
308
313
  } else {
309
- webviewClient = _fs2.default.readFileSync(clientFile, "utf-8");
314
+ devWebviewClient = _fs2.default.readFileSync(clientFile, "utf-8");
310
315
  }
311
316
  }
312
317
  }
@@ -331,21 +336,22 @@ function useVSCodePlugin(options) {
331
336
  };
332
337
  logger.info("extension build start");
333
338
  let buildCount = 0;
339
+ const webview = opts == null ? void 0 : opts.webview;
334
340
  const { onSuccess: _onSuccess, ...tsupOptions } = opts.extension || {};
335
341
  await _tsup.build.call(void 0,
336
342
  _lodashmerge2.default.call(void 0, tsupOptions, {
337
343
  watch: true,
338
344
  env,
339
345
  silent: true,
340
- esbuildPlugins: [
346
+ esbuildPlugins: !webview ? [] : [
341
347
  {
342
348
  name: "@tomjs:vscode:inject",
343
349
  setup(build) {
344
350
  build.onLoad({ filter: /\.ts$/ }, async (args) => {
345
351
  const file = _fs2.default.readFileSync(args.path, "utf-8");
346
- if (file.includes(`${opts.webview}(`)) {
352
+ if (file.includes(`${webview.name}(`)) {
347
353
  return {
348
- contents: `import ${opts.webview} from '@tomjs/vscode-extension-webview';
354
+ contents: `import ${webview.name} from '${devWebviewPath}';
349
355
  ` + file,
350
356
  loader: "ts"
351
357
  };
@@ -370,10 +376,10 @@ function useVSCodePlugin(options) {
370
376
  });
371
377
  },
372
378
  transformIndexHtml(html) {
373
- if (!opts.webview || !webviewClient) {
379
+ if (!opts.webview || !devWebviewClient) {
374
380
  return html;
375
381
  }
376
- return html.replace(/<\/title>/i, `</title><script>${webviewClient}</script>`);
382
+ return html.replace(/<\/title>/i, `</title><script>${devWebviewClient}</script>`);
377
383
  }
378
384
  },
379
385
  {
@@ -396,8 +402,9 @@ function useVSCodePlugin(options) {
396
402
  },
397
403
  closeBundle() {
398
404
  let webviewPath;
399
- if (opts.webview) {
400
- webviewPath = genProdWebviewCode(prodHtmlCache);
405
+ const webview = opts == null ? void 0 : opts.webview;
406
+ if (webview) {
407
+ webviewPath = genProdWebviewCode(prodHtmlCache, webview);
401
408
  }
402
409
  let outDir = buildConfig.build.outDir.replace(_process.cwd.call(void 0, ), "").replaceAll("\\", "/");
403
410
  if (outDir.startsWith("/")) {
@@ -413,15 +420,15 @@ function useVSCodePlugin(options) {
413
420
  _lodashmerge2.default.call(void 0, tsupOptions, {
414
421
  env,
415
422
  silent: true,
416
- esbuildPlugins: !opts.webview ? [] : [
423
+ esbuildPlugins: !webview ? [] : [
417
424
  {
418
425
  name: "@tomjs:vscode:inject",
419
426
  setup(build) {
420
427
  build.onLoad({ filter: /\.ts$/ }, async (args) => {
421
428
  const file = _fs2.default.readFileSync(args.path, "utf-8");
422
- if (file.includes(`${opts.webview}(`)) {
429
+ if (file.includes(`${webview.name}(`)) {
423
430
  return {
424
- contents: `import ${opts.webview} from \`${webviewPath}\`;
431
+ contents: `import ${webview.name} from \`${webviewPath}\`;
425
432
  ` + file,
426
433
  loader: "ts"
427
434
  };
package/dist/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  // src/index.ts
2
2
  import fs2 from "fs";
3
+ import os from "os";
3
4
  import path2 from "path";
4
5
  import { cwd as cwd2 } from "process";
5
6
  import cloneDeep from "lodash.clonedeep";
@@ -56,10 +57,10 @@ var createLogger = (tag) => {
56
57
  };
57
58
 
58
59
  // src/utils.ts
59
- import { spawnSync } from "child_process";
60
60
  import fs from "fs";
61
61
  import path from "path";
62
62
  import { cwd } from "process";
63
+ import execa from "execa";
63
64
  function readJson(path3) {
64
65
  if (fs.existsSync(path3)) {
65
66
  return JSON.parse(fs.readFileSync(path3, "utf8"));
@@ -95,40 +96,32 @@ function resolveServerUrl(server) {
95
96
  return url;
96
97
  }
97
98
  }
98
- function getWebviewNpmPath() {
99
- let npmPath = path.join(cwd(), "node_modules", WEBVIEW_PACKAGE_NAME);
100
- if (!fs.existsSync(npmPath)) {
101
- try {
102
- const res = spawnSync(
103
- process.platform === "win32" ? "pnpm.cmd" : "pnpm",
104
- ["list", "--dev", "--depth=1", "--json"],
105
- {
106
- // stdio: ['inherit', 'ignore'],
107
- cwd: process.cwd(),
108
- encoding: "utf-8"
109
- }
110
- );
111
- if (res.status === 0 && res.stdout) {
112
- const list = JSON.parse(res.stdout.trim());
113
- if (list.length === 0) {
114
- return;
115
- }
116
- const self = (list[0].devDependencies || {})[PACKAGE_NAME];
117
- if (!self) {
118
- return;
119
- }
120
- const dep = self.dependencies[WEBVIEW_PACKAGE_NAME];
121
- if (dep) {
122
- npmPath = dep.path;
123
- }
99
+ function getWebviewPnpmPath() {
100
+ try {
101
+ const res = execa.sync("pnpm", ["list", "--dev", "--depth=1", "--json"], {});
102
+ if (res.stdout) {
103
+ const list = JSON.parse(res.stdout.trim());
104
+ if (list.length === 0) {
105
+ return;
106
+ }
107
+ const self = (list[0].devDependencies || {})[PACKAGE_NAME];
108
+ if (!self) {
109
+ return;
110
+ }
111
+ const dep = self.dependencies[WEBVIEW_PACKAGE_NAME];
112
+ if (dep) {
113
+ return dep.path;
124
114
  }
125
- } catch {
126
- npmPath = "";
127
- }
128
- if (npmPath) {
129
- return path.join(npmPath, "dist");
130
115
  }
116
+ } catch {
117
+ }
118
+ }
119
+ function getWebviewNpmPath() {
120
+ const npmPath = path.join(cwd(), "node_modules", WEBVIEW_PACKAGE_NAME);
121
+ if (fs.existsSync(npmPath)) {
122
+ return npmPath;
131
123
  }
124
+ return getWebviewPnpmPath();
132
125
  }
133
126
 
134
127
  // src/index.ts
@@ -191,14 +184,18 @@ function preMergeOptions(options) {
191
184
  );
192
185
  }
193
186
  opts.extension = opt;
194
- if (opts.webview === true) {
195
- opts.webview = WEBVIEW_METHOD_NAME;
187
+ if (opts.webview !== false) {
188
+ let name = WEBVIEW_METHOD_NAME;
189
+ if (typeof opts.webview === "string") {
190
+ name = opts.webview ?? WEBVIEW_METHOD_NAME;
191
+ }
192
+ opts.webview = Object.assign({ name }, opts.webview);
196
193
  }
197
- opts.webview = opts.webview ?? WEBVIEW_METHOD_NAME;
198
194
  return opts;
199
195
  }
200
196
  var prodCachePkgName = `${PACKAGE_NAME}-inject`;
201
- function genProdWebviewCode(cache) {
197
+ function genProdWebviewCode(cache, webview) {
198
+ webview = Object.assign({}, webview);
202
199
  const prodCacheFolder = path2.join(cwd2(), "node_modules", prodCachePkgName);
203
200
  emptyPath(prodCacheFolder);
204
201
  const destFile = path2.join(prodCacheFolder, "index.ts");
@@ -208,26 +205,25 @@ function genProdWebviewCode(cache) {
208
205
  if (!head) {
209
206
  root == null ? void 0 : root.insertAdjacentHTML("beforeend", "<head></head>");
210
207
  }
211
- head.insertAdjacentHTML(
212
- "afterbegin",
213
- `
214
- <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src {{cspSource}} 'unsafe-inline'; script-src 'nonce-{{nonce}}' 'unsafe-eval';">`
215
- );
216
- const tags = {
217
- script: "src",
218
- link: "href"
219
- };
220
- Object.keys(tags).forEach((tag) => {
221
- const elements = root.querySelectorAll(tag);
222
- elements.forEach((element) => {
223
- const attr = element.getAttribute(tags[tag]);
224
- if (attr) {
225
- element.setAttribute(tags[tag], `{{baseUri}}${attr}`);
226
- }
227
- element.setAttribute("nonce", "{{nonce}}");
208
+ const csp = (webview == null ? void 0 : webview.csp) || `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src {{cspSource}} 'unsafe-inline'; script-src 'nonce-{{nonce}}' 'unsafe-eval';">`;
209
+ head.insertAdjacentHTML("afterbegin", csp);
210
+ if (csp && csp.includes("{{nonce}}")) {
211
+ const tags = {
212
+ script: "src",
213
+ link: "href"
214
+ };
215
+ Object.keys(tags).forEach((tag) => {
216
+ const elements = root.querySelectorAll(tag);
217
+ elements.forEach((element) => {
218
+ const attr = element.getAttribute(tags[tag]);
219
+ if (attr) {
220
+ element.setAttribute(tags[tag], `{{baseUri}}${attr}`);
221
+ }
222
+ element.setAttribute("nonce", "{{nonce}}");
223
+ });
228
224
  });
229
- });
230
- return root.toString();
225
+ }
226
+ return root.removeWhitespace().toString();
231
227
  }
232
228
  const cacheCode = (
233
229
  /* js */
@@ -254,12 +250,18 @@ export default function getWebviewHtml(webview: Webview, context: ExtensionConte
254
250
  const nonce = uuid();
255
251
  const baseUri = webview.asWebviewUri(Uri.joinPath(context.extensionUri, (process.env.VITE_WEBVIEW_DIST || 'dist')));
256
252
  const html = htmlCode[inputName || 'index'] || '';
257
- return html.replaceAll('{{cspSource}}',webview.cspSource).replaceAll('{{nonce}}', nonce).replaceAll('{{baseUri}}', baseUri);
253
+ return html.replaceAll('{{cspSource}}', webview.cspSource).replaceAll('{{nonce}}', nonce).replaceAll('{{baseUri}}', baseUri);
258
254
  }
259
255
  `
260
256
  );
261
257
  fs2.writeFileSync(destFile, code, { encoding: "utf8" });
262
- return destFile.replaceAll("\\", "/");
258
+ return fixWindowsPath(destFile);
259
+ }
260
+ function fixWindowsPath(webviewPath) {
261
+ if (os.platform() === "win32") {
262
+ webviewPath = webviewPath.replaceAll("\\", "/");
263
+ }
264
+ return webviewPath;
263
265
  }
264
266
  function useVSCodePlugin(options) {
265
267
  const opts = preMergeOptions(options);
@@ -293,19 +295,22 @@ function useVSCodePlugin(options) {
293
295
  }
294
296
  };
295
297
  };
296
- let webviewClient;
297
- let webviewNpmPath;
298
+ let devWebviewClient;
299
+ let devWebviewPath;
298
300
  if (opts.webview) {
299
- webviewNpmPath = getWebviewNpmPath();
300
- if (!webviewNpmPath || !fs2.existsSync(webviewNpmPath)) {
301
+ devWebviewPath = getWebviewNpmPath();
302
+ if (devWebviewPath && os.platform() === "win32") {
303
+ devWebviewPath = devWebviewPath.replaceAll("\\", "/");
304
+ }
305
+ if (!devWebviewPath || !fs2.existsSync(devWebviewPath)) {
301
306
  logger.warn(`[${WEBVIEW_PACKAGE_NAME}] is not installed, please install it first!`);
302
307
  } else {
303
308
  const fileName = "client.global.js";
304
- const clientFile = path2.join(webviewNpmPath, fileName);
309
+ const clientFile = path2.join(devWebviewPath, "dist", fileName);
305
310
  if (!fs2.existsSync(clientFile)) {
306
311
  logger.warn(`[${fileName}] is does not exist, please update the package!`);
307
312
  } else {
308
- webviewClient = fs2.readFileSync(clientFile, "utf-8");
313
+ devWebviewClient = fs2.readFileSync(clientFile, "utf-8");
309
314
  }
310
315
  }
311
316
  }
@@ -330,21 +335,22 @@ function useVSCodePlugin(options) {
330
335
  };
331
336
  logger.info("extension build start");
332
337
  let buildCount = 0;
338
+ const webview = opts == null ? void 0 : opts.webview;
333
339
  const { onSuccess: _onSuccess, ...tsupOptions } = opts.extension || {};
334
340
  await tsupBuild(
335
341
  merge(tsupOptions, {
336
342
  watch: true,
337
343
  env,
338
344
  silent: true,
339
- esbuildPlugins: [
345
+ esbuildPlugins: !webview ? [] : [
340
346
  {
341
347
  name: "@tomjs:vscode:inject",
342
348
  setup(build) {
343
349
  build.onLoad({ filter: /\.ts$/ }, async (args) => {
344
350
  const file = fs2.readFileSync(args.path, "utf-8");
345
- if (file.includes(`${opts.webview}(`)) {
351
+ if (file.includes(`${webview.name}(`)) {
346
352
  return {
347
- contents: `import ${opts.webview} from '@tomjs/vscode-extension-webview';
353
+ contents: `import ${webview.name} from '${devWebviewPath}';
348
354
  ` + file,
349
355
  loader: "ts"
350
356
  };
@@ -369,10 +375,10 @@ function useVSCodePlugin(options) {
369
375
  });
370
376
  },
371
377
  transformIndexHtml(html) {
372
- if (!opts.webview || !webviewClient) {
378
+ if (!opts.webview || !devWebviewClient) {
373
379
  return html;
374
380
  }
375
- return html.replace(/<\/title>/i, `</title><script>${webviewClient}</script>`);
381
+ return html.replace(/<\/title>/i, `</title><script>${devWebviewClient}</script>`);
376
382
  }
377
383
  },
378
384
  {
@@ -395,8 +401,9 @@ function useVSCodePlugin(options) {
395
401
  },
396
402
  closeBundle() {
397
403
  let webviewPath;
398
- if (opts.webview) {
399
- webviewPath = genProdWebviewCode(prodHtmlCache);
404
+ const webview = opts == null ? void 0 : opts.webview;
405
+ if (webview) {
406
+ webviewPath = genProdWebviewCode(prodHtmlCache, webview);
400
407
  }
401
408
  let outDir = buildConfig.build.outDir.replace(cwd2(), "").replaceAll("\\", "/");
402
409
  if (outDir.startsWith("/")) {
@@ -412,15 +419,15 @@ function useVSCodePlugin(options) {
412
419
  merge(tsupOptions, {
413
420
  env,
414
421
  silent: true,
415
- esbuildPlugins: !opts.webview ? [] : [
422
+ esbuildPlugins: !webview ? [] : [
416
423
  {
417
424
  name: "@tomjs:vscode:inject",
418
425
  setup(build) {
419
426
  build.onLoad({ filter: /\.ts$/ }, async (args) => {
420
427
  const file = fs2.readFileSync(args.path, "utf-8");
421
- if (file.includes(`${opts.webview}(`)) {
428
+ if (file.includes(`${webview.name}(`)) {
422
429
  return {
423
- contents: `import ${opts.webview} from \`${webviewPath}\`;
430
+ contents: `import ${webview.name} from \`${webviewPath}\`;
424
431
  ` + file,
425
432
  loader: "ts"
426
433
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomjs/vite-plugin-vscode",
3
- "version": "2.2.0",
3
+ "version": "2.3.1",
4
4
  "description": "Use vue/react to develop 'vscode extension webview', supporting esm/cjs",
5
5
  "keywords": [
6
6
  "vite",
@@ -46,6 +46,7 @@
46
46
  "dependencies": {
47
47
  "@tomjs/vscode-extension-webview": "^1.2.0",
48
48
  "dayjs": "^1.11.10",
49
+ "execa": "^5.1.1",
49
50
  "kolorist": "^1.8.0",
50
51
  "lodash.clonedeep": "^4.5.0",
51
52
  "lodash.merge": "^4.6.2",
@@ -66,7 +67,6 @@
66
67
  "eslint": "^8.56.0",
67
68
  "husky": "^8.0.3",
68
69
  "lint-staged": "^15.2.0",
69
- "np": "^9.2.0",
70
70
  "npm-run-all": "^4.1.5",
71
71
  "prettier": "^3.2.2",
72
72
  "rimraf": "^5.0.5",