@tomjs/vite-plugin-vscode 1.5.0 → 2.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 +101 -47
- package/README.zh_CN.md +101 -43
- package/dist/index.d.mts +12 -8
- package/dist/index.d.ts +12 -8
- package/dist/index.js +115 -12
- package/dist/index.mjs +115 -12
- package/env.d.ts +17 -4
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -4,17 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
**English** | [中文](./README.zh_CN.md)
|
|
6
6
|
|
|
7
|
-
>
|
|
7
|
+
> Use `vue`/`react` to develop [vscode extension webview](https://code.visualstudio.com/api/references/vscode-api#WebviewPanel), supporting `esm` and `cjs`.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
In development mode, inject the code of [@tomjs/vscode-extension-webview](https://github.com/tomjs/vscode-extension-webview) into `vscode extension code` and `web page code`, use To support `HMR`; during production build, the final generated `index.html` code is injected into `vscode extension code` to reduce the workload.
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
13
|
+
- Use [tsup](https://github.com/egoist/tsup) to quickly build `extension code`
|
|
14
|
+
- Simple configuration, focus on business
|
|
15
15
|
- Support `esm` and `cjs`
|
|
16
16
|
- Support webview `HMR`
|
|
17
|
-
- Support
|
|
17
|
+
- Support [Multi-Page App](https://vitejs.dev/guide/build.html#multi-page-app)
|
|
18
|
+
- Supports `vue` and `react` and other [frameworks](https://cn.vitejs.dev/guide/#trying-vite-online) supported by `vite`
|
|
18
19
|
|
|
19
20
|
## Install
|
|
20
21
|
|
|
@@ -75,39 +76,11 @@ const panel = window.createWebviewPanel('showHelloWorld', 'Hello World', ViewCol
|
|
|
75
76
|
enableScripts: true,
|
|
76
77
|
localResourceRoots: [Uri.joinPath(extensionUri, 'dist/webview')],
|
|
77
78
|
});
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
```ts
|
|
81
|
-
private _getWebviewContent(webview: Webview, extensionUri: Uri) {
|
|
82
|
-
// The CSS file from the Vue build output
|
|
83
|
-
const stylesUri = getUri(webview, extensionUri, ['dist', 'webview', 'assets', 'index.css']);
|
|
84
|
-
// The JS file from the Vue build output
|
|
85
|
-
const scriptUri = getUri(webview, extensionUri, ['dist', 'webview', 'assets', 'index.js']);
|
|
86
|
-
|
|
87
|
-
const nonce = uuid();
|
|
88
|
-
|
|
89
|
-
if (process.env.VITE_DEV_SERVER_URL) {
|
|
90
|
-
return __getWebviewHtml__(process.env.VITE_DEV_SERVER_URL);
|
|
91
|
-
}
|
|
92
79
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
<head>
|
|
98
|
-
<meta charset="UTF-8" />
|
|
99
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
100
|
-
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource}; script-src 'nonce-${nonce}';">
|
|
101
|
-
<script type="module" crossorigin nonce="${nonce}" src="${scriptUri}"></script>
|
|
102
|
-
<link rel="stylesheet" crossorigin href="${stylesUri}">
|
|
103
|
-
<title>Hello World</title>
|
|
104
|
-
</head>
|
|
105
|
-
<body>
|
|
106
|
-
<div id="app"></div>
|
|
107
|
-
</body>
|
|
108
|
-
</html>
|
|
109
|
-
`;
|
|
110
|
-
}
|
|
80
|
+
// Vite development mode and production mode inject different webview codes to reduce development work
|
|
81
|
+
panel.webview.html = process.env.VITE_DEV_SERVER_URL
|
|
82
|
+
? __getWebviewHtml__(process.env.VITE_DEV_SERVER_URL)
|
|
83
|
+
: __getWebviewHtml__(webview, context);
|
|
111
84
|
```
|
|
112
85
|
|
|
113
86
|
- `package.json`
|
|
@@ -157,6 +130,70 @@ export default defineConfig({
|
|
|
157
130
|
});
|
|
158
131
|
```
|
|
159
132
|
|
|
133
|
+
### Multi-page application
|
|
134
|
+
|
|
135
|
+
See [vue-import](./examples/vue-import) example
|
|
136
|
+
|
|
137
|
+
- `vite.config.ts`
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
import path from 'node:path';
|
|
141
|
+
import vscode from '@tomjs/vite-plugin-vscode';
|
|
142
|
+
|
|
143
|
+
export default defineConfig({
|
|
144
|
+
build: {
|
|
145
|
+
plugins: [vscode()]
|
|
146
|
+
rollupOptions: {
|
|
147
|
+
// https://cn.vitejs.dev/guide/build.html#multi-page-app
|
|
148
|
+
input: [path.resolve(__dirname, 'index.html'), path.resolve(__dirname, 'index2.html')],
|
|
149
|
+
// You can also customize the name
|
|
150
|
+
// input:{
|
|
151
|
+
// 'index': path.resolve(__dirname, 'index.html'),
|
|
152
|
+
// 'index2': path.resolve(__dirname, 'index2.html'),
|
|
153
|
+
// }
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
- page one
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
process.env.VITE_DEV_SERVER_URL
|
|
163
|
+
? __getWebviewHtml__(process.env.VITE_DEV_SERVER_URL)
|
|
164
|
+
: __getWebviewHtml__(webview, context);
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
- page two
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
process.env.VITE_DEV_SERVER_URL
|
|
171
|
+
? __getWebviewHtml__(`${process.env.VITE_DEV_SERVER_URL}/index2.html`)
|
|
172
|
+
: __getWebviewHtml__(webview, context, 'index2');
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**getWebviewHtml** Description
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
/**
|
|
179
|
+
* `[vite serve]` Gets the html of webview in development mode.
|
|
180
|
+
* @param options serverUrl: The url of the vite dev server.
|
|
181
|
+
*/
|
|
182
|
+
function __getWebviewHtml__(options?: string | { serverUrl: string }): string;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* `[vite build]` Gets the html of webview in production mode.
|
|
186
|
+
* @param webview The WebviewPanel instance of the extension.
|
|
187
|
+
* @param context The ExtensionContext instance of the extension.
|
|
188
|
+
* @param inputName vite build.rollupOptions.input name. Default is `index`.
|
|
189
|
+
*/
|
|
190
|
+
function __getWebviewHtml__(
|
|
191
|
+
webview: Webview,
|
|
192
|
+
context: ExtensionContext,
|
|
193
|
+
inputName?: string,
|
|
194
|
+
): string;
|
|
195
|
+
```
|
|
196
|
+
|
|
160
197
|
## Documentation
|
|
161
198
|
|
|
162
199
|
- [API Documentation](https://paka.dev/npm/@tomjs/vite-plugin-vscode) provided by [paka.dev](https://paka.dev).
|
|
@@ -206,15 +243,15 @@ Based on [Options](https://paka.dev/npm/tsup) of [tsup](https://tsup.egoist.dev/
|
|
|
206
243
|
|
|
207
244
|
- `development` mode
|
|
208
245
|
|
|
209
|
-
| Variable | Description
|
|
210
|
-
| --------------------- |
|
|
211
|
-
| `VITE_DEV_SERVER_URL` | The url of the vite dev server
|
|
246
|
+
| Variable | Description |
|
|
247
|
+
| --------------------- | ------------------------------ |
|
|
248
|
+
| `VITE_DEV_SERVER_URL` | The url of the vite dev server |
|
|
212
249
|
|
|
213
250
|
- `production` mode
|
|
214
251
|
|
|
215
|
-
| Variable
|
|
216
|
-
|
|
|
217
|
-
| `
|
|
252
|
+
| Variable | Description |
|
|
253
|
+
| ------------------- | ----------------------------- |
|
|
254
|
+
| `VITE_WEBVIEW_DIST` | vite webview page output path |
|
|
218
255
|
|
|
219
256
|
## Debug
|
|
220
257
|
|
|
@@ -232,7 +269,15 @@ Run `Debug Extension` through `vscode` to debug. For debugging tools, refer to [
|
|
|
232
269
|
"request": "launch",
|
|
233
270
|
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
|
|
234
271
|
"outFiles": ["${workspaceFolder}/dist/extension/*.js"],
|
|
235
|
-
"preLaunchTask": "
|
|
272
|
+
"preLaunchTask": "npm: dev"
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"name": "Preview Extension",
|
|
276
|
+
"type": "extensionHost",
|
|
277
|
+
"request": "launch",
|
|
278
|
+
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
|
|
279
|
+
"outFiles": ["${workspaceFolder}/dist/extension/*.js"],
|
|
280
|
+
"preLaunchTask": "npm: build"
|
|
236
281
|
}
|
|
237
282
|
]
|
|
238
283
|
}
|
|
@@ -272,6 +317,15 @@ Run `Debug Extension` through `vscode` to debug. For debugging tools, refer to [
|
|
|
272
317
|
"kind": "build",
|
|
273
318
|
"isDefault": true
|
|
274
319
|
}
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
"type": "npm",
|
|
323
|
+
"script": "build",
|
|
324
|
+
"group": {
|
|
325
|
+
"kind": "build",
|
|
326
|
+
"isDefault": true
|
|
327
|
+
},
|
|
328
|
+
"problemMatcher": []
|
|
275
329
|
}
|
|
276
330
|
]
|
|
277
331
|
}
|
|
@@ -288,6 +342,6 @@ pnpm build
|
|
|
288
342
|
|
|
289
343
|
Open the [examples](./examples) directory, there are `vue` and `react` examples.
|
|
290
344
|
|
|
291
|
-
- [react](./examples/react):
|
|
292
|
-
- [vue](./examples/vue):
|
|
293
|
-
- [vue-import](./examples/vue-import):
|
|
345
|
+
- [react](./examples/react): Simple react example.
|
|
346
|
+
- [vue](./examples/vue): Simple vue example.
|
|
347
|
+
- [vue-import](./examples/vue-import): Dynamic import() and multi-page examples.
|
package/README.zh_CN.md
CHANGED
|
@@ -4,17 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
[English](./README.md) | **中文**
|
|
6
6
|
|
|
7
|
-
> [vscode extension](https://code.visualstudio.com/api
|
|
7
|
+
> 用 `vue`/`react` 来开发 [vscode extension webview](https://code.visualstudio.com/api/references/vscode-api#WebviewPanel) ,支持 `esm` 和 `cjs`。
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
在开发模式时,给 `vscode 扩展代码` 和 `web 页面代码`中注入 [@tomjs/vscode-extension-webview](https://github.com/tomjs/vscode-extension-webview) 的代码,用来支持 `HMR`;生产构建时,将最终生成的`index.html` 代码注入到 `vscode 扩展代码` 中,减少工作量。
|
|
10
10
|
|
|
11
11
|
## 特性
|
|
12
12
|
|
|
13
|
-
- 使用 [tsup](https://github.com/egoist/tsup) 快速构建
|
|
13
|
+
- 使用 [tsup](https://github.com/egoist/tsup) 快速构建 `扩展代码`
|
|
14
14
|
- 配置简单,专注业务
|
|
15
15
|
- 支持 `esm`和 `cjs`
|
|
16
16
|
- 支持 webview `HMR`
|
|
17
|
-
- 支持
|
|
17
|
+
- 支持[多页面应用](https://cn.vitejs.dev/guide/build.html#multi-page-app)
|
|
18
|
+
- 支持 `vue` 、`react` 等其他 `vite` 支持的[框架](https://cn.vitejs.dev/guide/#trying-vite-online)
|
|
18
19
|
|
|
19
20
|
## 安装
|
|
20
21
|
|
|
@@ -75,39 +76,15 @@ const panel = window.createWebviewPanel('showHelloWorld', 'Hello World', ViewCol
|
|
|
75
76
|
enableScripts: true,
|
|
76
77
|
localResourceRoots: [Uri.joinPath(extensionUri, 'dist/webview')],
|
|
77
78
|
});
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
```ts
|
|
81
|
-
private _getWebviewContent(webview: Webview, extensionUri: Uri) {
|
|
82
|
-
// The CSS file from the Vue build output
|
|
83
|
-
const stylesUri = getUri(webview, extensionUri, ['dist/webview/assets/index.css']);
|
|
84
|
-
// The JS file from the Vue build output
|
|
85
|
-
const scriptUri = getUri(webview, extensionUri, ['dist/webview/assets/index.js']);
|
|
86
79
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
80
|
+
// vite 开发模式和生产模式注入不同的webview代码,减少开发工作
|
|
81
|
+
function getHtml(webview: Webview, context: ExtensionContext) {
|
|
82
|
+
process.env.VITE_DEV_SERVER_URL
|
|
83
|
+
? __getWebviewHtml__(process.env.VITE_DEV_SERVER_URL)
|
|
84
|
+
: __getWebviewHtml__(webview, context);
|
|
85
|
+
}
|
|
92
86
|
|
|
93
|
-
|
|
94
|
-
return /*html*/ `
|
|
95
|
-
<!doctype html>
|
|
96
|
-
<html lang="en">
|
|
97
|
-
<head>
|
|
98
|
-
<meta charset="UTF-8" />
|
|
99
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
100
|
-
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource}; script-src 'nonce-${nonce}';">
|
|
101
|
-
<script type="module" crossorigin nonce="${nonce}" src="${scriptUri}"></script>
|
|
102
|
-
<link rel="stylesheet" crossorigin href="${stylesUri}">
|
|
103
|
-
<title>Hello World</title>
|
|
104
|
-
</head>
|
|
105
|
-
<body>
|
|
106
|
-
<div id="app"></div>
|
|
107
|
-
</body>
|
|
108
|
-
</html>
|
|
109
|
-
`;
|
|
110
|
-
}
|
|
87
|
+
panel.webview.html = getHtml(webview, context);
|
|
111
88
|
```
|
|
112
89
|
|
|
113
90
|
- `package.json`
|
|
@@ -157,6 +134,70 @@ export default defineConfig({
|
|
|
157
134
|
});
|
|
158
135
|
```
|
|
159
136
|
|
|
137
|
+
### **getWebviewHtml**
|
|
138
|
+
|
|
139
|
+
可查看 [vue-import](./examples/vue-import) 示例
|
|
140
|
+
|
|
141
|
+
- `vite.config.ts`
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import path from 'node:path';
|
|
145
|
+
import vscode from '@tomjs/vite-plugin-vscode';
|
|
146
|
+
|
|
147
|
+
export default defineConfig({
|
|
148
|
+
build: {
|
|
149
|
+
plugins: [vscode()]
|
|
150
|
+
rollupOptions: {
|
|
151
|
+
// https://cn.vitejs.dev/guide/build.html#multi-page-app
|
|
152
|
+
input: [path.resolve(__dirname, 'index.html'), path.resolve(__dirname, 'index2.html')],
|
|
153
|
+
// 也可自定义名称
|
|
154
|
+
// input:{
|
|
155
|
+
// 'index': path.resolve(__dirname, 'index.html'),
|
|
156
|
+
// 'index2': path.resolve(__dirname, 'index2.html'),
|
|
157
|
+
// }
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
- 页面一
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
process.env.VITE_DEV_SERVER_URL
|
|
167
|
+
? __getWebviewHtml__(process.env.VITE_DEV_SERVER_URL)
|
|
168
|
+
: __getWebviewHtml__(webview, context);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
- 页面二
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
process.env.VITE_DEV_SERVER_URL
|
|
175
|
+
? __getWebviewHtml__(`${process.env.VITE_DEV_SERVER_URL}/index2.html`)
|
|
176
|
+
: __getWebviewHtml__(webview, context, 'index2');
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**getWebviewHtml** 说明
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
/**
|
|
183
|
+
* `[vite serve]` 在开发模式获取webview的html
|
|
184
|
+
* @param options serverUrl: vite开发服务器的url
|
|
185
|
+
*/
|
|
186
|
+
function __getWebviewHtml__(options?: string | { serverUrl: string }): string;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* `[vite build]` 在生产模式获取webview的html
|
|
190
|
+
* @param webview 扩展的 Webview 实例
|
|
191
|
+
* @param context 扩展的 ExtensionContext 实例
|
|
192
|
+
* @param inputName vite build.rollupOptions.input 设置的名称. 默认 `index`.
|
|
193
|
+
*/
|
|
194
|
+
function __getWebviewHtml__(
|
|
195
|
+
webview: Webview,
|
|
196
|
+
context: ExtensionContext,
|
|
197
|
+
inputName?: string,
|
|
198
|
+
): string;
|
|
199
|
+
```
|
|
200
|
+
|
|
160
201
|
## 文档
|
|
161
202
|
|
|
162
203
|
- [paka.dev](https://paka.dev) 提供的 [API文档](https://paka.dev/npm/@tomjs/vite-plugin-vscode).
|
|
@@ -205,15 +246,15 @@ export default defineConfig({
|
|
|
205
246
|
|
|
206
247
|
- `development` 模式
|
|
207
248
|
|
|
208
|
-
| 变量 | 描述
|
|
209
|
-
| --------------------- |
|
|
210
|
-
| `VITE_DEV_SERVER_URL` | vite开发服务器的url
|
|
249
|
+
| 变量 | 描述 |
|
|
250
|
+
| --------------------- | ------------------- |
|
|
251
|
+
| `VITE_DEV_SERVER_URL` | vite开发服务器的url |
|
|
211
252
|
|
|
212
253
|
- `production` 模式
|
|
213
254
|
|
|
214
|
-
| 变量
|
|
215
|
-
|
|
|
216
|
-
| `
|
|
255
|
+
| 变量 | 描述 |
|
|
256
|
+
| ------------------- | ------------------------- |
|
|
257
|
+
| `VITE_WEBVIEW_DIST` | vite webview 页面输出路径 |
|
|
217
258
|
|
|
218
259
|
## Debug
|
|
219
260
|
|
|
@@ -231,7 +272,15 @@ export default defineConfig({
|
|
|
231
272
|
"request": "launch",
|
|
232
273
|
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
|
|
233
274
|
"outFiles": ["${workspaceFolder}/dist/extension/*.js"],
|
|
234
|
-
"preLaunchTask": "
|
|
275
|
+
"preLaunchTask": "npm: dev"
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
"name": "Preview Extension",
|
|
279
|
+
"type": "extensionHost",
|
|
280
|
+
"request": "launch",
|
|
281
|
+
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
|
|
282
|
+
"outFiles": ["${workspaceFolder}/dist/extension/*.js"],
|
|
283
|
+
"preLaunchTask": "npm: build"
|
|
235
284
|
}
|
|
236
285
|
]
|
|
237
286
|
}
|
|
@@ -271,6 +320,15 @@ export default defineConfig({
|
|
|
271
320
|
"kind": "build",
|
|
272
321
|
"isDefault": true
|
|
273
322
|
}
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"type": "npm",
|
|
326
|
+
"script": "build",
|
|
327
|
+
"group": {
|
|
328
|
+
"kind": "build",
|
|
329
|
+
"isDefault": true
|
|
330
|
+
},
|
|
331
|
+
"problemMatcher": []
|
|
274
332
|
}
|
|
275
333
|
]
|
|
276
334
|
}
|
|
@@ -289,4 +347,4 @@ pnpm build
|
|
|
289
347
|
|
|
290
348
|
- [react](./examples/react):简单的 react 示例。
|
|
291
349
|
- [vue](./examples/vue):简单的 vue 示例。
|
|
292
|
-
- [vue-import](./examples/vue-import):动态 import()
|
|
350
|
+
- [vue-import](./examples/vue-import):动态 import() 和多页面示例。
|
package/dist/index.d.mts
CHANGED
|
@@ -43,19 +43,23 @@ interface PluginOptions {
|
|
|
43
43
|
/**
|
|
44
44
|
* 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.
|
|
45
45
|
*
|
|
46
|
-
* *
|
|
47
|
-
*
|
|
46
|
+
* * vite serve
|
|
47
|
+
* * extension: Inject `import __getWebviewHtml__ from '@tomjs/vscode-extension-webview';` above the file that calls the `__getWebviewHtml__` method
|
|
48
|
+
* * web: Add `<script>` tag to index.html and inject `@tomjs/vscode-extension-webview/client` code
|
|
49
|
+
* * vite build
|
|
50
|
+
* * extension: Inject `import __getWebviewHtml__ from '@tomjs/vite-plugin-vscode-inject';` above the file that calls the `__getWebviewHtml__` method
|
|
48
51
|
*
|
|
49
|
-
* If is string, will set inject method name. Default is '
|
|
52
|
+
* If is string, will set inject method name. Default is '__getWebviewHtml__'.
|
|
50
53
|
*
|
|
51
54
|
* @example
|
|
52
55
|
* extension file
|
|
53
56
|
* ```ts
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
57
|
+
*function setupHtml(webview: Webview, context: ExtensionContext) {
|
|
58
|
+
* if (process.env.VITE_DEV_SERVER_URL) {
|
|
59
|
+
* return __getWebviewHtml__(process.env.VITE_DEV_SERVER_URL);
|
|
60
|
+
* }
|
|
61
|
+
* return __getWebviewHtml__(webview, context);
|
|
62
|
+
*}
|
|
59
63
|
* ```
|
|
60
64
|
* webview client
|
|
61
65
|
* ```html
|
package/dist/index.d.ts
CHANGED
|
@@ -43,19 +43,23 @@ interface PluginOptions {
|
|
|
43
43
|
/**
|
|
44
44
|
* 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.
|
|
45
45
|
*
|
|
46
|
-
* *
|
|
47
|
-
*
|
|
46
|
+
* * vite serve
|
|
47
|
+
* * extension: Inject `import __getWebviewHtml__ from '@tomjs/vscode-extension-webview';` above the file that calls the `__getWebviewHtml__` method
|
|
48
|
+
* * web: Add `<script>` tag to index.html and inject `@tomjs/vscode-extension-webview/client` code
|
|
49
|
+
* * vite build
|
|
50
|
+
* * extension: Inject `import __getWebviewHtml__ from '@tomjs/vite-plugin-vscode-inject';` above the file that calls the `__getWebviewHtml__` method
|
|
48
51
|
*
|
|
49
|
-
* If is string, will set inject method name. Default is '
|
|
52
|
+
* If is string, will set inject method name. Default is '__getWebviewHtml__'.
|
|
50
53
|
*
|
|
51
54
|
* @example
|
|
52
55
|
* extension file
|
|
53
56
|
* ```ts
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
57
|
+
*function setupHtml(webview: Webview, context: ExtensionContext) {
|
|
58
|
+
* if (process.env.VITE_DEV_SERVER_URL) {
|
|
59
|
+
* return __getWebviewHtml__(process.env.VITE_DEV_SERVER_URL);
|
|
60
|
+
* }
|
|
61
|
+
* return __getWebviewHtml__(webview, context);
|
|
62
|
+
*}
|
|
59
63
|
* ```
|
|
60
64
|
* webview client
|
|
61
65
|
* ```html
|
package/dist/index.js
CHANGED
|
@@ -4,10 +4,12 @@ var _path = require('path'); var _path2 = _interopRequireDefault(_path);
|
|
|
4
4
|
var _process = require('process');
|
|
5
5
|
var _lodashclonedeep = require('lodash.clonedeep'); var _lodashclonedeep2 = _interopRequireDefault(_lodashclonedeep);
|
|
6
6
|
var _lodashmerge = require('lodash.merge'); var _lodashmerge2 = _interopRequireDefault(_lodashmerge);
|
|
7
|
+
var _nodehtmlparser = require('node-html-parser');
|
|
7
8
|
var _tsup = require('tsup');
|
|
8
9
|
|
|
9
10
|
// src/constants.ts
|
|
10
11
|
var PLUGIN_NAME = "@tomjs:vscode";
|
|
12
|
+
var PACKAGE_NAME = "@tomjs/vite-plugin-vscode";
|
|
11
13
|
var WEBVIEW_PACKAGE_NAME = "@tomjs/vscode-extension-webview";
|
|
12
14
|
var WEBVIEW_METHOD_NAME = "__getWebviewHtml__";
|
|
13
15
|
|
|
@@ -61,6 +63,12 @@ function readJson(path2) {
|
|
|
61
63
|
return JSON.parse(_fs2.default.readFileSync(path2, "utf8"));
|
|
62
64
|
}
|
|
63
65
|
}
|
|
66
|
+
function emptyPath(dest) {
|
|
67
|
+
if (_fs2.default.existsSync(dest)) {
|
|
68
|
+
_fs2.default.rmSync(dest, { recursive: true });
|
|
69
|
+
}
|
|
70
|
+
_fs2.default.mkdirSync(dest, { recursive: true });
|
|
71
|
+
}
|
|
64
72
|
function resolveHostname(hostname) {
|
|
65
73
|
const loopbackHosts = /* @__PURE__ */ new Set([
|
|
66
74
|
"localhost",
|
|
@@ -152,12 +160,69 @@ function preMergeOptions(options) {
|
|
|
152
160
|
opts.webview = _nullishCoalesce(opts.webview, () => ( WEBVIEW_METHOD_NAME));
|
|
153
161
|
return opts;
|
|
154
162
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
163
|
+
var prodCachePkgName = `${PACKAGE_NAME}-inject`;
|
|
164
|
+
function genProdWebviewCode(cache) {
|
|
165
|
+
const prodCacheFolder = _path2.default.join(_process.cwd.call(void 0, ), "node_modules", prodCachePkgName);
|
|
166
|
+
emptyPath(prodCacheFolder);
|
|
167
|
+
const destFile = _path2.default.join(prodCacheFolder, "index.ts");
|
|
168
|
+
function handleHtmlCode(html) {
|
|
169
|
+
const root = _nodehtmlparser.parse.call(void 0, html);
|
|
170
|
+
const head = root.querySelector("head");
|
|
171
|
+
if (!head) {
|
|
172
|
+
root == null ? void 0 : root.insertAdjacentHTML("beforeend", "<head></head>");
|
|
173
|
+
}
|
|
174
|
+
head.insertAdjacentHTML(
|
|
175
|
+
"afterbegin",
|
|
176
|
+
`
|
|
177
|
+
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src {{cspSource}} 'unsafe-inline'; script-src 'nonce-{{nonce}}' 'unsafe-eval';">`
|
|
178
|
+
);
|
|
179
|
+
const tags = {
|
|
180
|
+
script: "src",
|
|
181
|
+
link: "href"
|
|
182
|
+
};
|
|
183
|
+
Object.keys(tags).forEach((tag) => {
|
|
184
|
+
const elements = root.querySelectorAll(tag);
|
|
185
|
+
elements.forEach((element) => {
|
|
186
|
+
const attr = element.getAttribute(tags[tag]);
|
|
187
|
+
if (attr) {
|
|
188
|
+
element.setAttribute(tags[tag], `{{baseUri}}${attr}`);
|
|
189
|
+
}
|
|
190
|
+
element.setAttribute("nonce", "{{nonce}}");
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
return root.toString();
|
|
194
|
+
}
|
|
195
|
+
const cacheCode = (
|
|
196
|
+
/* js */
|
|
197
|
+
`const htmlCode = {
|
|
198
|
+
${Object.keys(cache).map((s) => `${s}: \`${handleHtmlCode(cache[s])}\`,`).join("\n")}
|
|
199
|
+
};`
|
|
200
|
+
);
|
|
201
|
+
const code = (
|
|
202
|
+
/* js */
|
|
203
|
+
`import { ExtensionContext, Uri, Webview } from 'vscode';
|
|
204
|
+
|
|
205
|
+
${cacheCode}
|
|
206
|
+
|
|
207
|
+
function uuid() {
|
|
208
|
+
let text = '';
|
|
209
|
+
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
210
|
+
for (let i = 0; i < 32; i++) {
|
|
211
|
+
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
|
212
|
+
}
|
|
213
|
+
return text;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export default function getWebviewHtml(webview: Webview, context: ExtensionContext, inputName?:string){
|
|
217
|
+
const nonce = uuid();
|
|
218
|
+
const baseUri = webview.asWebviewUri(Uri.joinPath(context.extensionUri, (process.env.VITE_WEBVIEW_DIST || 'dist')));
|
|
219
|
+
const html = htmlCode[inputName || 'index'] || '';
|
|
220
|
+
return html.replaceAll('{{cspSource}}',webview.cspSource).replaceAll('{{nonce}}', nonce).replaceAll('{{baseUri}}', baseUri);
|
|
221
|
+
}
|
|
222
|
+
`
|
|
223
|
+
);
|
|
224
|
+
_fs2.default.writeFileSync(destFile, code, { encoding: "utf8" });
|
|
225
|
+
return destFile.replaceAll("\\", "/");
|
|
161
226
|
}
|
|
162
227
|
function useVSCodePlugin(options) {
|
|
163
228
|
const opts = preMergeOptions(options);
|
|
@@ -208,6 +273,7 @@ function useVSCodePlugin(options) {
|
|
|
208
273
|
}
|
|
209
274
|
}
|
|
210
275
|
let buildConfig;
|
|
276
|
+
const prodHtmlCache = {};
|
|
211
277
|
return [
|
|
212
278
|
{
|
|
213
279
|
name: "@tomjs:vscode",
|
|
@@ -275,26 +341,63 @@ function useVSCodePlugin(options) {
|
|
|
275
341
|
{
|
|
276
342
|
name: "@tomjs:vscode",
|
|
277
343
|
apply: "build",
|
|
344
|
+
enforce: "post",
|
|
278
345
|
config(config) {
|
|
279
346
|
return handleConfig(config);
|
|
280
347
|
},
|
|
281
348
|
configResolved(config) {
|
|
282
349
|
buildConfig = config;
|
|
283
350
|
},
|
|
351
|
+
transformIndexHtml(html, ctx) {
|
|
352
|
+
var _a;
|
|
353
|
+
if (!opts.webview) {
|
|
354
|
+
return html;
|
|
355
|
+
}
|
|
356
|
+
prodHtmlCache[(_a = ctx.chunk) == null ? void 0 : _a.name] = html;
|
|
357
|
+
return html;
|
|
358
|
+
},
|
|
284
359
|
closeBundle() {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
360
|
+
let webviewPath;
|
|
361
|
+
if (opts.webview) {
|
|
362
|
+
webviewPath = genProdWebviewCode(prodHtmlCache);
|
|
363
|
+
}
|
|
364
|
+
let outDir = buildConfig.build.outDir.replace(_process.cwd.call(void 0, ), "").replaceAll("\\", "/");
|
|
365
|
+
if (outDir.startsWith("/")) {
|
|
366
|
+
outDir = outDir.substring(1);
|
|
367
|
+
}
|
|
368
|
+
const env = {
|
|
369
|
+
NODE_ENV: buildConfig.mode || "production",
|
|
370
|
+
VITE_WEBVIEW_DIST: outDir
|
|
371
|
+
};
|
|
372
|
+
logger.info("extension build start");
|
|
288
373
|
const { onSuccess: _onSuccess, ...tsupOptions } = opts.extension || {};
|
|
289
374
|
_tsup.build.call(void 0,
|
|
290
375
|
_lodashmerge2.default.call(void 0, tsupOptions, {
|
|
291
|
-
env
|
|
292
|
-
|
|
293
|
-
|
|
376
|
+
env,
|
|
377
|
+
silent: true,
|
|
378
|
+
esbuildPlugins: !opts.webview ? [] : [
|
|
379
|
+
{
|
|
380
|
+
name: "@tomjs:vscode:inject",
|
|
381
|
+
setup(build) {
|
|
382
|
+
build.onLoad({ filter: /\.ts$/ }, async (args) => {
|
|
383
|
+
const file = _fs2.default.readFileSync(args.path, "utf-8");
|
|
384
|
+
if (file.includes(`${opts.webview}(`)) {
|
|
385
|
+
return {
|
|
386
|
+
contents: `import ${opts.webview} from \`${webviewPath}\`;
|
|
387
|
+
` + file,
|
|
388
|
+
loader: "ts"
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
return {};
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
],
|
|
294
396
|
async onSuccess() {
|
|
295
397
|
if (typeof _onSuccess === "function") {
|
|
296
398
|
await _onSuccess();
|
|
297
399
|
}
|
|
400
|
+
logger.info("extension build success");
|
|
298
401
|
}
|
|
299
402
|
})
|
|
300
403
|
);
|
package/dist/index.mjs
CHANGED
|
@@ -4,10 +4,12 @@ import path from "path";
|
|
|
4
4
|
import { cwd } from "process";
|
|
5
5
|
import cloneDeep from "lodash.clonedeep";
|
|
6
6
|
import merge from "lodash.merge";
|
|
7
|
+
import { parse as htmlParser } from "node-html-parser";
|
|
7
8
|
import { build as tsupBuild } from "tsup";
|
|
8
9
|
|
|
9
10
|
// src/constants.ts
|
|
10
11
|
var PLUGIN_NAME = "@tomjs:vscode";
|
|
12
|
+
var PACKAGE_NAME = "@tomjs/vite-plugin-vscode";
|
|
11
13
|
var WEBVIEW_PACKAGE_NAME = "@tomjs/vscode-extension-webview";
|
|
12
14
|
var WEBVIEW_METHOD_NAME = "__getWebviewHtml__";
|
|
13
15
|
|
|
@@ -60,6 +62,12 @@ function readJson(path2) {
|
|
|
60
62
|
return JSON.parse(fs.readFileSync(path2, "utf8"));
|
|
61
63
|
}
|
|
62
64
|
}
|
|
65
|
+
function emptyPath(dest) {
|
|
66
|
+
if (fs.existsSync(dest)) {
|
|
67
|
+
fs.rmSync(dest, { recursive: true });
|
|
68
|
+
}
|
|
69
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
70
|
+
}
|
|
63
71
|
function resolveHostname(hostname) {
|
|
64
72
|
const loopbackHosts = /* @__PURE__ */ new Set([
|
|
65
73
|
"localhost",
|
|
@@ -151,12 +159,69 @@ function preMergeOptions(options) {
|
|
|
151
159
|
opts.webview = opts.webview ?? WEBVIEW_METHOD_NAME;
|
|
152
160
|
return opts;
|
|
153
161
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
162
|
+
var prodCachePkgName = `${PACKAGE_NAME}-inject`;
|
|
163
|
+
function genProdWebviewCode(cache) {
|
|
164
|
+
const prodCacheFolder = path.join(cwd(), "node_modules", prodCachePkgName);
|
|
165
|
+
emptyPath(prodCacheFolder);
|
|
166
|
+
const destFile = path.join(prodCacheFolder, "index.ts");
|
|
167
|
+
function handleHtmlCode(html) {
|
|
168
|
+
const root = htmlParser(html);
|
|
169
|
+
const head = root.querySelector("head");
|
|
170
|
+
if (!head) {
|
|
171
|
+
root == null ? void 0 : root.insertAdjacentHTML("beforeend", "<head></head>");
|
|
172
|
+
}
|
|
173
|
+
head.insertAdjacentHTML(
|
|
174
|
+
"afterbegin",
|
|
175
|
+
`
|
|
176
|
+
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src {{cspSource}} 'unsafe-inline'; script-src 'nonce-{{nonce}}' 'unsafe-eval';">`
|
|
177
|
+
);
|
|
178
|
+
const tags = {
|
|
179
|
+
script: "src",
|
|
180
|
+
link: "href"
|
|
181
|
+
};
|
|
182
|
+
Object.keys(tags).forEach((tag) => {
|
|
183
|
+
const elements = root.querySelectorAll(tag);
|
|
184
|
+
elements.forEach((element) => {
|
|
185
|
+
const attr = element.getAttribute(tags[tag]);
|
|
186
|
+
if (attr) {
|
|
187
|
+
element.setAttribute(tags[tag], `{{baseUri}}${attr}`);
|
|
188
|
+
}
|
|
189
|
+
element.setAttribute("nonce", "{{nonce}}");
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
return root.toString();
|
|
193
|
+
}
|
|
194
|
+
const cacheCode = (
|
|
195
|
+
/* js */
|
|
196
|
+
`const htmlCode = {
|
|
197
|
+
${Object.keys(cache).map((s) => `${s}: \`${handleHtmlCode(cache[s])}\`,`).join("\n")}
|
|
198
|
+
};`
|
|
199
|
+
);
|
|
200
|
+
const code = (
|
|
201
|
+
/* js */
|
|
202
|
+
`import { ExtensionContext, Uri, Webview } from 'vscode';
|
|
203
|
+
|
|
204
|
+
${cacheCode}
|
|
205
|
+
|
|
206
|
+
function uuid() {
|
|
207
|
+
let text = '';
|
|
208
|
+
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
209
|
+
for (let i = 0; i < 32; i++) {
|
|
210
|
+
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
|
211
|
+
}
|
|
212
|
+
return text;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export default function getWebviewHtml(webview: Webview, context: ExtensionContext, inputName?:string){
|
|
216
|
+
const nonce = uuid();
|
|
217
|
+
const baseUri = webview.asWebviewUri(Uri.joinPath(context.extensionUri, (process.env.VITE_WEBVIEW_DIST || 'dist')));
|
|
218
|
+
const html = htmlCode[inputName || 'index'] || '';
|
|
219
|
+
return html.replaceAll('{{cspSource}}',webview.cspSource).replaceAll('{{nonce}}', nonce).replaceAll('{{baseUri}}', baseUri);
|
|
220
|
+
}
|
|
221
|
+
`
|
|
222
|
+
);
|
|
223
|
+
fs2.writeFileSync(destFile, code, { encoding: "utf8" });
|
|
224
|
+
return destFile.replaceAll("\\", "/");
|
|
160
225
|
}
|
|
161
226
|
function useVSCodePlugin(options) {
|
|
162
227
|
const opts = preMergeOptions(options);
|
|
@@ -207,6 +272,7 @@ function useVSCodePlugin(options) {
|
|
|
207
272
|
}
|
|
208
273
|
}
|
|
209
274
|
let buildConfig;
|
|
275
|
+
const prodHtmlCache = {};
|
|
210
276
|
return [
|
|
211
277
|
{
|
|
212
278
|
name: "@tomjs:vscode",
|
|
@@ -274,26 +340,63 @@ function useVSCodePlugin(options) {
|
|
|
274
340
|
{
|
|
275
341
|
name: "@tomjs:vscode",
|
|
276
342
|
apply: "build",
|
|
343
|
+
enforce: "post",
|
|
277
344
|
config(config) {
|
|
278
345
|
return handleConfig(config);
|
|
279
346
|
},
|
|
280
347
|
configResolved(config) {
|
|
281
348
|
buildConfig = config;
|
|
282
349
|
},
|
|
350
|
+
transformIndexHtml(html, ctx) {
|
|
351
|
+
var _a;
|
|
352
|
+
if (!opts.webview) {
|
|
353
|
+
return html;
|
|
354
|
+
}
|
|
355
|
+
prodHtmlCache[(_a = ctx.chunk) == null ? void 0 : _a.name] = html;
|
|
356
|
+
return html;
|
|
357
|
+
},
|
|
283
358
|
closeBundle() {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
359
|
+
let webviewPath;
|
|
360
|
+
if (opts.webview) {
|
|
361
|
+
webviewPath = genProdWebviewCode(prodHtmlCache);
|
|
362
|
+
}
|
|
363
|
+
let outDir = buildConfig.build.outDir.replace(cwd(), "").replaceAll("\\", "/");
|
|
364
|
+
if (outDir.startsWith("/")) {
|
|
365
|
+
outDir = outDir.substring(1);
|
|
366
|
+
}
|
|
367
|
+
const env = {
|
|
368
|
+
NODE_ENV: buildConfig.mode || "production",
|
|
369
|
+
VITE_WEBVIEW_DIST: outDir
|
|
370
|
+
};
|
|
371
|
+
logger.info("extension build start");
|
|
287
372
|
const { onSuccess: _onSuccess, ...tsupOptions } = opts.extension || {};
|
|
288
373
|
tsupBuild(
|
|
289
374
|
merge(tsupOptions, {
|
|
290
|
-
env
|
|
291
|
-
|
|
292
|
-
|
|
375
|
+
env,
|
|
376
|
+
silent: true,
|
|
377
|
+
esbuildPlugins: !opts.webview ? [] : [
|
|
378
|
+
{
|
|
379
|
+
name: "@tomjs:vscode:inject",
|
|
380
|
+
setup(build) {
|
|
381
|
+
build.onLoad({ filter: /\.ts$/ }, async (args) => {
|
|
382
|
+
const file = fs2.readFileSync(args.path, "utf-8");
|
|
383
|
+
if (file.includes(`${opts.webview}(`)) {
|
|
384
|
+
return {
|
|
385
|
+
contents: `import ${opts.webview} from \`${webviewPath}\`;
|
|
386
|
+
` + file,
|
|
387
|
+
loader: "ts"
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
return {};
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
],
|
|
293
395
|
async onSuccess() {
|
|
294
396
|
if (typeof _onSuccess === "function") {
|
|
295
397
|
await _onSuccess();
|
|
296
398
|
}
|
|
399
|
+
logger.info("extension build success");
|
|
297
400
|
}
|
|
298
401
|
})
|
|
299
402
|
);
|
package/env.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { ExtensionContext, Webview } from 'vscode';
|
|
2
|
+
// Make this a module
|
|
3
|
+
export {};
|
|
3
4
|
declare global {
|
|
4
5
|
/**
|
|
5
6
|
* fix code hint
|
|
@@ -19,13 +20,25 @@ declare global {
|
|
|
19
20
|
/**
|
|
20
21
|
* `[vite build]` All js files in the dist directory, excluding index.js. It's to be a json string.
|
|
21
22
|
*/
|
|
22
|
-
|
|
23
|
+
VITE_WEBVIEW_DIST?: string;
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
|
-
* `[vite serve]`
|
|
28
|
+
* `[vite serve]` Gets the html of webview in development mode.
|
|
28
29
|
* @param options serverUrl: The url of the vite dev server.
|
|
29
30
|
*/
|
|
30
31
|
function __getWebviewHtml__(options?: string | { serverUrl: string }): string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* `[vite build]` Gets the html of webview in production mode.
|
|
35
|
+
* @param webview The Webview instance of the extension.
|
|
36
|
+
* @param context The ExtensionContext instance of the extension.
|
|
37
|
+
* @param inputName vite build.rollupOptions.input name. Default is `index`.
|
|
38
|
+
*/
|
|
39
|
+
function __getWebviewHtml__(
|
|
40
|
+
webview: Webview,
|
|
41
|
+
context: ExtensionContext,
|
|
42
|
+
inputName?: string,
|
|
43
|
+
): string;
|
|
31
44
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomjs/vite-plugin-vscode",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "Use vue/react to develop 'vscode extension webview', supporting esm/cjs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vite",
|
|
7
7
|
"plugin",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
"kolorist": "^1.8.0",
|
|
48
48
|
"lodash.clonedeep": "^4.5.0",
|
|
49
49
|
"lodash.merge": "^4.6.2",
|
|
50
|
+
"node-html-parser": "^6.1.12",
|
|
50
51
|
"tsup": "7.2.0"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|