@tomjs/vite-plugin-vscode 2.2.0 → 2.3.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
@@ -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
@@ -192,14 +192,18 @@ function preMergeOptions(options) {
192
192
  );
193
193
  }
194
194
  opts.extension = opt;
195
- if (opts.webview === true) {
196
- opts.webview = WEBVIEW_METHOD_NAME;
195
+ if (opts.webview !== false) {
196
+ let name = WEBVIEW_METHOD_NAME;
197
+ if (typeof opts.webview === "string") {
198
+ name = _nullishCoalesce(opts.webview, () => ( WEBVIEW_METHOD_NAME));
199
+ }
200
+ opts.webview = Object.assign({ name }, opts.webview);
197
201
  }
198
- opts.webview = _nullishCoalesce(opts.webview, () => ( WEBVIEW_METHOD_NAME));
199
202
  return opts;
200
203
  }
201
204
  var prodCachePkgName = `${PACKAGE_NAME}-inject`;
202
- function genProdWebviewCode(cache) {
205
+ function genProdWebviewCode(cache, webview) {
206
+ webview = Object.assign({}, webview);
203
207
  const prodCacheFolder = _path2.default.join(_process.cwd.call(void 0, ), "node_modules", prodCachePkgName);
204
208
  emptyPath(prodCacheFolder);
205
209
  const destFile = _path2.default.join(prodCacheFolder, "index.ts");
@@ -209,26 +213,25 @@ function genProdWebviewCode(cache) {
209
213
  if (!head) {
210
214
  root == null ? void 0 : root.insertAdjacentHTML("beforeend", "<head></head>");
211
215
  }
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}}");
216
+ 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';">`;
217
+ head.insertAdjacentHTML("afterbegin", csp);
218
+ if (csp && csp.includes("{{nonce}}")) {
219
+ const tags = {
220
+ script: "src",
221
+ link: "href"
222
+ };
223
+ Object.keys(tags).forEach((tag) => {
224
+ const elements = root.querySelectorAll(tag);
225
+ elements.forEach((element) => {
226
+ const attr = element.getAttribute(tags[tag]);
227
+ if (attr) {
228
+ element.setAttribute(tags[tag], `{{baseUri}}${attr}`);
229
+ }
230
+ element.setAttribute("nonce", "{{nonce}}");
231
+ });
229
232
  });
230
- });
231
- return root.toString();
233
+ }
234
+ return root.removeWhitespace().toString();
232
235
  }
233
236
  const cacheCode = (
234
237
  /* js */
@@ -255,7 +258,7 @@ export default function getWebviewHtml(webview: Webview, context: ExtensionConte
255
258
  const nonce = uuid();
256
259
  const baseUri = webview.asWebviewUri(Uri.joinPath(context.extensionUri, (process.env.VITE_WEBVIEW_DIST || 'dist')));
257
260
  const html = htmlCode[inputName || 'index'] || '';
258
- return html.replaceAll('{{cspSource}}',webview.cspSource).replaceAll('{{nonce}}', nonce).replaceAll('{{baseUri}}', baseUri);
261
+ return html.replaceAll('{{cspSource}}', webview.cspSource).replaceAll('{{nonce}}', nonce).replaceAll('{{baseUri}}', baseUri);
259
262
  }
260
263
  `
261
264
  );
@@ -331,21 +334,22 @@ function useVSCodePlugin(options) {
331
334
  };
332
335
  logger.info("extension build start");
333
336
  let buildCount = 0;
337
+ const webview = opts == null ? void 0 : opts.webview;
334
338
  const { onSuccess: _onSuccess, ...tsupOptions } = opts.extension || {};
335
339
  await _tsup.build.call(void 0,
336
340
  _lodashmerge2.default.call(void 0, tsupOptions, {
337
341
  watch: true,
338
342
  env,
339
343
  silent: true,
340
- esbuildPlugins: [
344
+ esbuildPlugins: !webview ? [] : [
341
345
  {
342
346
  name: "@tomjs:vscode:inject",
343
347
  setup(build) {
344
348
  build.onLoad({ filter: /\.ts$/ }, async (args) => {
345
349
  const file = _fs2.default.readFileSync(args.path, "utf-8");
346
- if (file.includes(`${opts.webview}(`)) {
350
+ if (file.includes(`${webview.name}(`)) {
347
351
  return {
348
- contents: `import ${opts.webview} from '@tomjs/vscode-extension-webview';
352
+ contents: `import ${webview.name} from '@tomjs/vscode-extension-webview';
349
353
  ` + file,
350
354
  loader: "ts"
351
355
  };
@@ -396,8 +400,9 @@ function useVSCodePlugin(options) {
396
400
  },
397
401
  closeBundle() {
398
402
  let webviewPath;
399
- if (opts.webview) {
400
- webviewPath = genProdWebviewCode(prodHtmlCache);
403
+ const webview = opts == null ? void 0 : opts.webview;
404
+ if (webview) {
405
+ webviewPath = genProdWebviewCode(prodHtmlCache, webview);
401
406
  }
402
407
  let outDir = buildConfig.build.outDir.replace(_process.cwd.call(void 0, ), "").replaceAll("\\", "/");
403
408
  if (outDir.startsWith("/")) {
@@ -413,15 +418,15 @@ function useVSCodePlugin(options) {
413
418
  _lodashmerge2.default.call(void 0, tsupOptions, {
414
419
  env,
415
420
  silent: true,
416
- esbuildPlugins: !opts.webview ? [] : [
421
+ esbuildPlugins: !webview ? [] : [
417
422
  {
418
423
  name: "@tomjs:vscode:inject",
419
424
  setup(build) {
420
425
  build.onLoad({ filter: /\.ts$/ }, async (args) => {
421
426
  const file = _fs2.default.readFileSync(args.path, "utf-8");
422
- if (file.includes(`${opts.webview}(`)) {
427
+ if (file.includes(`${webview.name}(`)) {
423
428
  return {
424
- contents: `import ${opts.webview} from \`${webviewPath}\`;
429
+ contents: `import ${webview.name} from \`${webviewPath}\`;
425
430
  ` + file,
426
431
  loader: "ts"
427
432
  };
package/dist/index.mjs CHANGED
@@ -191,14 +191,18 @@ function preMergeOptions(options) {
191
191
  );
192
192
  }
193
193
  opts.extension = opt;
194
- if (opts.webview === true) {
195
- opts.webview = WEBVIEW_METHOD_NAME;
194
+ if (opts.webview !== false) {
195
+ let name = WEBVIEW_METHOD_NAME;
196
+ if (typeof opts.webview === "string") {
197
+ name = opts.webview ?? WEBVIEW_METHOD_NAME;
198
+ }
199
+ opts.webview = Object.assign({ name }, opts.webview);
196
200
  }
197
- opts.webview = opts.webview ?? WEBVIEW_METHOD_NAME;
198
201
  return opts;
199
202
  }
200
203
  var prodCachePkgName = `${PACKAGE_NAME}-inject`;
201
- function genProdWebviewCode(cache) {
204
+ function genProdWebviewCode(cache, webview) {
205
+ webview = Object.assign({}, webview);
202
206
  const prodCacheFolder = path2.join(cwd2(), "node_modules", prodCachePkgName);
203
207
  emptyPath(prodCacheFolder);
204
208
  const destFile = path2.join(prodCacheFolder, "index.ts");
@@ -208,26 +212,25 @@ function genProdWebviewCode(cache) {
208
212
  if (!head) {
209
213
  root == null ? void 0 : root.insertAdjacentHTML("beforeend", "<head></head>");
210
214
  }
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}}");
215
+ 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';">`;
216
+ head.insertAdjacentHTML("afterbegin", csp);
217
+ if (csp && csp.includes("{{nonce}}")) {
218
+ const tags = {
219
+ script: "src",
220
+ link: "href"
221
+ };
222
+ Object.keys(tags).forEach((tag) => {
223
+ const elements = root.querySelectorAll(tag);
224
+ elements.forEach((element) => {
225
+ const attr = element.getAttribute(tags[tag]);
226
+ if (attr) {
227
+ element.setAttribute(tags[tag], `{{baseUri}}${attr}`);
228
+ }
229
+ element.setAttribute("nonce", "{{nonce}}");
230
+ });
228
231
  });
229
- });
230
- return root.toString();
232
+ }
233
+ return root.removeWhitespace().toString();
231
234
  }
232
235
  const cacheCode = (
233
236
  /* js */
@@ -254,7 +257,7 @@ export default function getWebviewHtml(webview: Webview, context: ExtensionConte
254
257
  const nonce = uuid();
255
258
  const baseUri = webview.asWebviewUri(Uri.joinPath(context.extensionUri, (process.env.VITE_WEBVIEW_DIST || 'dist')));
256
259
  const html = htmlCode[inputName || 'index'] || '';
257
- return html.replaceAll('{{cspSource}}',webview.cspSource).replaceAll('{{nonce}}', nonce).replaceAll('{{baseUri}}', baseUri);
260
+ return html.replaceAll('{{cspSource}}', webview.cspSource).replaceAll('{{nonce}}', nonce).replaceAll('{{baseUri}}', baseUri);
258
261
  }
259
262
  `
260
263
  );
@@ -330,21 +333,22 @@ function useVSCodePlugin(options) {
330
333
  };
331
334
  logger.info("extension build start");
332
335
  let buildCount = 0;
336
+ const webview = opts == null ? void 0 : opts.webview;
333
337
  const { onSuccess: _onSuccess, ...tsupOptions } = opts.extension || {};
334
338
  await tsupBuild(
335
339
  merge(tsupOptions, {
336
340
  watch: true,
337
341
  env,
338
342
  silent: true,
339
- esbuildPlugins: [
343
+ esbuildPlugins: !webview ? [] : [
340
344
  {
341
345
  name: "@tomjs:vscode:inject",
342
346
  setup(build) {
343
347
  build.onLoad({ filter: /\.ts$/ }, async (args) => {
344
348
  const file = fs2.readFileSync(args.path, "utf-8");
345
- if (file.includes(`${opts.webview}(`)) {
349
+ if (file.includes(`${webview.name}(`)) {
346
350
  return {
347
- contents: `import ${opts.webview} from '@tomjs/vscode-extension-webview';
351
+ contents: `import ${webview.name} from '@tomjs/vscode-extension-webview';
348
352
  ` + file,
349
353
  loader: "ts"
350
354
  };
@@ -395,8 +399,9 @@ function useVSCodePlugin(options) {
395
399
  },
396
400
  closeBundle() {
397
401
  let webviewPath;
398
- if (opts.webview) {
399
- webviewPath = genProdWebviewCode(prodHtmlCache);
402
+ const webview = opts == null ? void 0 : opts.webview;
403
+ if (webview) {
404
+ webviewPath = genProdWebviewCode(prodHtmlCache, webview);
400
405
  }
401
406
  let outDir = buildConfig.build.outDir.replace(cwd2(), "").replaceAll("\\", "/");
402
407
  if (outDir.startsWith("/")) {
@@ -412,15 +417,15 @@ function useVSCodePlugin(options) {
412
417
  merge(tsupOptions, {
413
418
  env,
414
419
  silent: true,
415
- esbuildPlugins: !opts.webview ? [] : [
420
+ esbuildPlugins: !webview ? [] : [
416
421
  {
417
422
  name: "@tomjs:vscode:inject",
418
423
  setup(build) {
419
424
  build.onLoad({ filter: /\.ts$/ }, async (args) => {
420
425
  const file = fs2.readFileSync(args.path, "utf-8");
421
- if (file.includes(`${opts.webview}(`)) {
426
+ if (file.includes(`${webview.name}(`)) {
422
427
  return {
423
- contents: `import ${opts.webview} from \`${webviewPath}\`;
428
+ contents: `import ${webview.name} from \`${webviewPath}\`;
424
429
  ` + file,
425
430
  loader: "ts"
426
431
  };
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.0",
4
4
  "description": "Use vue/react to develop 'vscode extension webview', supporting esm/cjs",
5
5
  "keywords": [
6
6
  "vite",
@@ -66,7 +66,6 @@
66
66
  "eslint": "^8.56.0",
67
67
  "husky": "^8.0.3",
68
68
  "lint-staged": "^15.2.0",
69
- "np": "^9.2.0",
70
69
  "npm-run-all": "^4.1.5",
71
70
  "prettier": "^3.2.2",
72
71
  "rimraf": "^5.0.5",