@tomjs/vite-plugin-vscode 2.1.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 +37 -11
- package/README.zh_CN.md +36 -10
- package/dist/index.d.mts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +82 -39
- package/dist/index.mjs +91 -48
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -30,19 +30,15 @@ yarn add @tomjs/vite-plugin-vscode -D
|
|
|
30
30
|
npm i @tomjs/vite-plugin-vscode --save-dev
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
If you use `pnpm` and enable `webview` debugging, you need to additionally install the dependency [@tomjs/vscode-extension-webview](https://github.com/tomjs/vscode-extension-webview)
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
pnpm add @tomjs/vscode-extension-webview -D
|
|
37
|
-
```
|
|
38
|
-
|
|
39
33
|
## Usage
|
|
40
34
|
|
|
41
|
-
### Recommended
|
|
35
|
+
### Recommended
|
|
36
|
+
|
|
37
|
+
Setting `recommended` will modify some preset configurations. See [PluginOptions](#pluginoptions) and `recommended` parameter descriptions in detail.
|
|
42
38
|
|
|
43
39
|
#### Directory Structure
|
|
44
40
|
|
|
45
|
-
-
|
|
41
|
+
- By default, `recommended:true` will be based on the following directory structure as a convention.
|
|
46
42
|
|
|
47
43
|
```
|
|
48
44
|
|--extension // extension code
|
|
@@ -50,6 +46,7 @@ pnpm add @tomjs/vscode-extension-webview -D
|
|
|
50
46
|
|--src // front-end code
|
|
51
47
|
| |--App.vue
|
|
52
48
|
| |--main.ts
|
|
49
|
+
|--index.html
|
|
53
50
|
```
|
|
54
51
|
|
|
55
52
|
- Zero configuration, default dist output directory
|
|
@@ -63,9 +60,16 @@ pnpm add @tomjs/vscode-extension-webview -D
|
|
|
63
60
|
| | |--index.html
|
|
64
61
|
```
|
|
65
62
|
|
|
66
|
-
|
|
63
|
+
- If you want to modify the `extension` source code directory to `src`, you can set `{ extension: { entry: 'src/index.ts' } }`
|
|
67
64
|
|
|
68
|
-
|
|
65
|
+
```
|
|
66
|
+
|--src // extension code
|
|
67
|
+
| |--index.ts
|
|
68
|
+
|--webview // front-end code
|
|
69
|
+
| |--App.vue
|
|
70
|
+
| |--main.ts
|
|
71
|
+
|--index.html
|
|
72
|
+
```
|
|
69
73
|
|
|
70
74
|
### extension
|
|
71
75
|
|
|
@@ -111,6 +115,8 @@ export default defineConfig({
|
|
|
111
115
|
},
|
|
112
116
|
}),
|
|
113
117
|
vscode(),
|
|
118
|
+
// Modify the extension source code entry path, and also modify the `index.html` entry file path
|
|
119
|
+
// vscode({ extension: { entry: 'src/index.ts' } }),
|
|
114
120
|
],
|
|
115
121
|
});
|
|
116
122
|
```
|
|
@@ -207,7 +213,7 @@ function __getWebviewHtml__(
|
|
|
207
213
|
| --- | --- | --- | --- |
|
|
208
214
|
| recommended | `boolean` | `true` | This option is intended to provide recommended default parameters and behavior. |
|
|
209
215
|
| extension | [ExtensionOptions](#ExtensionOptions) | | Configuration options for the vscode extension. |
|
|
210
|
-
| webview | `boolean`
|
|
216
|
+
| webview | `boolean` \| `string` \| [WebviewOption](#WebviewOption) | `__getWebviewHtml__` | Inject html code |
|
|
211
217
|
|
|
212
218
|
**Notice**
|
|
213
219
|
|
|
@@ -216,6 +222,16 @@ The `recommended` option is used to set the default configuration and behavior,
|
|
|
216
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.
|
|
217
223
|
- Other behaviors to be implemented
|
|
218
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
|
+
|
|
219
235
|
### ExtensionOptions
|
|
220
236
|
|
|
221
237
|
Based on [Options](https://paka.dev/npm/tsup) of [tsup](https://tsup.egoist.dev/), some default values are added for ease of use.
|
|
@@ -226,6 +242,16 @@ Based on [Options](https://paka.dev/npm/tsup) of [tsup](https://tsup.egoist.dev/
|
|
|
226
242
|
| outDir | `string` | `dist-extension/main` | The output directory for the vscode extension file |
|
|
227
243
|
| onSuccess | `() => Promise<void \| undefined \| (() => void \| Promise<void>)>` | `undefined` | A function that will be executed after the build succeeds. |
|
|
228
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
|
+
|
|
229
255
|
### Additional Information
|
|
230
256
|
|
|
231
257
|
- Default values for `extension` when the relevant parameters are not configured
|
package/README.zh_CN.md
CHANGED
|
@@ -30,19 +30,15 @@ yarn add @tomjs/vite-plugin-vscode -D
|
|
|
30
30
|
npm i @tomjs/vite-plugin-vscode --save-dev
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
如果使用 `pnpm` 且开启 `webview` 调试,需要额外安装[@tomjs/vscode-extension-webview](https://github.com/tomjs/vscode-extension-webview) 这个依赖
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
pnpm add @tomjs/vscode-extension-webview -D
|
|
37
|
-
```
|
|
38
|
-
|
|
39
33
|
## 使用说明
|
|
40
34
|
|
|
41
35
|
### 推荐约定
|
|
42
36
|
|
|
37
|
+
设置 `recommended` 参数会修改一些预置配置,详细查看 [PluginOptions](#pluginoptions) 和 `recommended` 参数说明。
|
|
38
|
+
|
|
43
39
|
#### 目录结构
|
|
44
40
|
|
|
45
|
-
-
|
|
41
|
+
- 默认情况下,`recommended:true` 会根据如下目录结构作为约定
|
|
46
42
|
|
|
47
43
|
```
|
|
48
44
|
|--extension // extension code
|
|
@@ -50,6 +46,7 @@ pnpm add @tomjs/vscode-extension-webview -D
|
|
|
50
46
|
|--src // front-end code
|
|
51
47
|
| |--App.vue
|
|
52
48
|
| |--main.ts
|
|
49
|
+
|--index.html
|
|
53
50
|
```
|
|
54
51
|
|
|
55
52
|
- 零配置,默认 dist 输出目录
|
|
@@ -63,9 +60,16 @@ pnpm add @tomjs/vscode-extension-webview -D
|
|
|
63
60
|
| | |--index.html
|
|
64
61
|
```
|
|
65
62
|
|
|
66
|
-
|
|
63
|
+
- 如果你想修改 `extension` 源码目录为 `src`,可以设置 `{ extension: { entry: 'src/index.ts' } }`
|
|
67
64
|
|
|
68
|
-
|
|
65
|
+
```
|
|
66
|
+
|--src // extension code
|
|
67
|
+
| |--index.ts
|
|
68
|
+
|--webview // front-end code
|
|
69
|
+
| |--App.vue
|
|
70
|
+
| |--main.ts
|
|
71
|
+
|--index.html
|
|
72
|
+
```
|
|
69
73
|
|
|
70
74
|
### extension
|
|
71
75
|
|
|
@@ -115,6 +119,8 @@ export default defineConfig({
|
|
|
115
119
|
},
|
|
116
120
|
}),
|
|
117
121
|
vscode(),
|
|
122
|
+
// 修改扩展源码入口路径,同时修改`index.html`入口文件路径
|
|
123
|
+
// vscode({ extension: { entry: 'src/index.ts' } }),
|
|
118
124
|
],
|
|
119
125
|
});
|
|
120
126
|
```
|
|
@@ -211,7 +217,7 @@ function __getWebviewHtml__(
|
|
|
211
217
|
| --- | --- | --- | --- |
|
|
212
218
|
| recommended | `boolean` | `true` | 这个选项是为了提供推荐的默认参数和行为 |
|
|
213
219
|
| extension | [ExtensionOptions](#ExtensionOptions) | | vscode extension 可选配置 |
|
|
214
|
-
| webview | `boolean`
|
|
220
|
+
| webview | `boolean` \| `string` \| [WebviewOption](#WebviewOption) | `__getWebviewHtml__` | 注入 html 代码 |
|
|
215
221
|
|
|
216
222
|
**Notice**
|
|
217
223
|
|
|
@@ -221,6 +227,16 @@ function __getWebviewHtml__(
|
|
|
221
227
|
|
|
222
228
|
- 其他待实现的行为
|
|
223
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
|
+
|
|
224
240
|
### ExtensionOptions
|
|
225
241
|
|
|
226
242
|
继承自 [tsup](https://tsup.egoist.dev/) 的 [Options](https://paka.dev/npm/tsup),添加了一些默认值,方便使用。
|
|
@@ -231,6 +247,16 @@ function __getWebviewHtml__(
|
|
|
231
247
|
| outDir | `string` | `dist-extension/main` | 输出文件夹 |
|
|
232
248
|
| onSuccess | `() => Promise<void \| undefined \| (() => void \| Promise<void>)>` | `undefined` | 构建成功后运行的回调函数 |
|
|
233
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
|
+
|
|
234
260
|
### 补充说明
|
|
235
261
|
|
|
236
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
|
@@ -56,11 +56,14 @@ var createLogger = (tag) => {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
// src/utils.ts
|
|
59
|
+
var _child_process = require('child_process');
|
|
59
60
|
|
|
60
61
|
var _module = require('module');
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
function readJson(path3) {
|
|
65
|
+
if (_fs2.default.existsSync(path3)) {
|
|
66
|
+
return JSON.parse(_fs2.default.readFileSync(path3, "utf8"));
|
|
64
67
|
}
|
|
65
68
|
}
|
|
66
69
|
function emptyPath(dest) {
|
|
@@ -88,11 +91,46 @@ function resolveServerUrl(server) {
|
|
|
88
91
|
const options = server.config.server;
|
|
89
92
|
const protocol = options.https ? "https" : "http";
|
|
90
93
|
const devBase = server.config.base;
|
|
91
|
-
const
|
|
92
|
-
const url =
|
|
94
|
+
const path3 = typeof options.open === "string" ? options.open : devBase;
|
|
95
|
+
const url = path3.startsWith("http") ? path3 : `${protocol}://${hostname}:${port}${path3}`;
|
|
93
96
|
return url;
|
|
94
97
|
}
|
|
95
98
|
}
|
|
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
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} catch (e) {
|
|
127
|
+
npmPath = "";
|
|
128
|
+
}
|
|
129
|
+
if (npmPath) {
|
|
130
|
+
return _path2.default.join(npmPath, "dist");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
96
134
|
|
|
97
135
|
// src/index.ts
|
|
98
136
|
var isDev = process.env.NODE_ENV === "development";
|
|
@@ -154,14 +192,18 @@ function preMergeOptions(options) {
|
|
|
154
192
|
);
|
|
155
193
|
}
|
|
156
194
|
opts.extension = opt;
|
|
157
|
-
if (opts.webview
|
|
158
|
-
|
|
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);
|
|
159
201
|
}
|
|
160
|
-
opts.webview = _nullishCoalesce(opts.webview, () => ( WEBVIEW_METHOD_NAME));
|
|
161
202
|
return opts;
|
|
162
203
|
}
|
|
163
204
|
var prodCachePkgName = `${PACKAGE_NAME}-inject`;
|
|
164
|
-
function genProdWebviewCode(cache) {
|
|
205
|
+
function genProdWebviewCode(cache, webview) {
|
|
206
|
+
webview = Object.assign({}, webview);
|
|
165
207
|
const prodCacheFolder = _path2.default.join(_process.cwd.call(void 0, ), "node_modules", prodCachePkgName);
|
|
166
208
|
emptyPath(prodCacheFolder);
|
|
167
209
|
const destFile = _path2.default.join(prodCacheFolder, "index.ts");
|
|
@@ -171,26 +213,25 @@ function genProdWebviewCode(cache) {
|
|
|
171
213
|
if (!head) {
|
|
172
214
|
root == null ? void 0 : root.insertAdjacentHTML("beforeend", "<head></head>");
|
|
173
215
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
element.setAttribute(
|
|
189
|
-
}
|
|
190
|
-
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
|
+
});
|
|
191
232
|
});
|
|
192
|
-
}
|
|
193
|
-
return root.toString();
|
|
233
|
+
}
|
|
234
|
+
return root.removeWhitespace().toString();
|
|
194
235
|
}
|
|
195
236
|
const cacheCode = (
|
|
196
237
|
/* js */
|
|
@@ -217,7 +258,7 @@ export default function getWebviewHtml(webview: Webview, context: ExtensionConte
|
|
|
217
258
|
const nonce = uuid();
|
|
218
259
|
const baseUri = webview.asWebviewUri(Uri.joinPath(context.extensionUri, (process.env.VITE_WEBVIEW_DIST || 'dist')));
|
|
219
260
|
const html = htmlCode[inputName || 'index'] || '';
|
|
220
|
-
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);
|
|
221
262
|
}
|
|
222
263
|
`
|
|
223
264
|
);
|
|
@@ -259,8 +300,8 @@ function useVSCodePlugin(options) {
|
|
|
259
300
|
let webviewClient;
|
|
260
301
|
let webviewNpmPath;
|
|
261
302
|
if (opts.webview) {
|
|
262
|
-
webviewNpmPath =
|
|
263
|
-
if (!_fs2.default.existsSync(webviewNpmPath)) {
|
|
303
|
+
webviewNpmPath = getWebviewNpmPath();
|
|
304
|
+
if (!webviewNpmPath || !_fs2.default.existsSync(webviewNpmPath)) {
|
|
264
305
|
logger.warn(`[${WEBVIEW_PACKAGE_NAME}] is not installed, please install it first!`);
|
|
265
306
|
} else {
|
|
266
307
|
const fileName = "client.global.js";
|
|
@@ -293,21 +334,22 @@ function useVSCodePlugin(options) {
|
|
|
293
334
|
};
|
|
294
335
|
logger.info("extension build start");
|
|
295
336
|
let buildCount = 0;
|
|
337
|
+
const webview = opts == null ? void 0 : opts.webview;
|
|
296
338
|
const { onSuccess: _onSuccess, ...tsupOptions } = opts.extension || {};
|
|
297
339
|
await _tsup.build.call(void 0,
|
|
298
340
|
_lodashmerge2.default.call(void 0, tsupOptions, {
|
|
299
341
|
watch: true,
|
|
300
342
|
env,
|
|
301
343
|
silent: true,
|
|
302
|
-
esbuildPlugins: [
|
|
344
|
+
esbuildPlugins: !webview ? [] : [
|
|
303
345
|
{
|
|
304
346
|
name: "@tomjs:vscode:inject",
|
|
305
347
|
setup(build) {
|
|
306
348
|
build.onLoad({ filter: /\.ts$/ }, async (args) => {
|
|
307
349
|
const file = _fs2.default.readFileSync(args.path, "utf-8");
|
|
308
|
-
if (file.includes(`${
|
|
350
|
+
if (file.includes(`${webview.name}(`)) {
|
|
309
351
|
return {
|
|
310
|
-
contents: `import ${
|
|
352
|
+
contents: `import ${webview.name} from '@tomjs/vscode-extension-webview';
|
|
311
353
|
` + file,
|
|
312
354
|
loader: "ts"
|
|
313
355
|
};
|
|
@@ -358,8 +400,9 @@ function useVSCodePlugin(options) {
|
|
|
358
400
|
},
|
|
359
401
|
closeBundle() {
|
|
360
402
|
let webviewPath;
|
|
361
|
-
|
|
362
|
-
|
|
403
|
+
const webview = opts == null ? void 0 : opts.webview;
|
|
404
|
+
if (webview) {
|
|
405
|
+
webviewPath = genProdWebviewCode(prodHtmlCache, webview);
|
|
363
406
|
}
|
|
364
407
|
let outDir = buildConfig.build.outDir.replace(_process.cwd.call(void 0, ), "").replaceAll("\\", "/");
|
|
365
408
|
if (outDir.startsWith("/")) {
|
|
@@ -375,15 +418,15 @@ function useVSCodePlugin(options) {
|
|
|
375
418
|
_lodashmerge2.default.call(void 0, tsupOptions, {
|
|
376
419
|
env,
|
|
377
420
|
silent: true,
|
|
378
|
-
esbuildPlugins: !
|
|
421
|
+
esbuildPlugins: !webview ? [] : [
|
|
379
422
|
{
|
|
380
423
|
name: "@tomjs:vscode:inject",
|
|
381
424
|
setup(build) {
|
|
382
425
|
build.onLoad({ filter: /\.ts$/ }, async (args) => {
|
|
383
426
|
const file = _fs2.default.readFileSync(args.path, "utf-8");
|
|
384
|
-
if (file.includes(`${
|
|
427
|
+
if (file.includes(`${webview.name}(`)) {
|
|
385
428
|
return {
|
|
386
|
-
contents: `import ${
|
|
429
|
+
contents: `import ${webview.name} from \`${webviewPath}\`;
|
|
387
430
|
` + file,
|
|
388
431
|
loader: "ts"
|
|
389
432
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import fs2 from "fs";
|
|
3
|
-
import
|
|
4
|
-
import { cwd } from "process";
|
|
3
|
+
import path2 from "path";
|
|
4
|
+
import { cwd as cwd2 } from "process";
|
|
5
5
|
import cloneDeep from "lodash.clonedeep";
|
|
6
6
|
import merge from "lodash.merge";
|
|
7
7
|
import { parse as htmlParser } from "node-html-parser";
|
|
@@ -56,10 +56,13 @@ var createLogger = (tag) => {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
// src/utils.ts
|
|
59
|
+
import { spawnSync } from "child_process";
|
|
59
60
|
import fs from "fs";
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
import path from "path";
|
|
62
|
+
import { cwd } from "process";
|
|
63
|
+
function readJson(path3) {
|
|
64
|
+
if (fs.existsSync(path3)) {
|
|
65
|
+
return JSON.parse(fs.readFileSync(path3, "utf8"));
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
68
|
function emptyPath(dest) {
|
|
@@ -87,17 +90,52 @@ function resolveServerUrl(server) {
|
|
|
87
90
|
const options = server.config.server;
|
|
88
91
|
const protocol = options.https ? "https" : "http";
|
|
89
92
|
const devBase = server.config.base;
|
|
90
|
-
const
|
|
91
|
-
const url =
|
|
93
|
+
const path3 = typeof options.open === "string" ? options.open : devBase;
|
|
94
|
+
const url = path3.startsWith("http") ? path3 : `${protocol}://${hostname}:${port}${path3}`;
|
|
92
95
|
return url;
|
|
93
96
|
}
|
|
94
97
|
}
|
|
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
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} catch {
|
|
126
|
+
npmPath = "";
|
|
127
|
+
}
|
|
128
|
+
if (npmPath) {
|
|
129
|
+
return path.join(npmPath, "dist");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
95
133
|
|
|
96
134
|
// src/index.ts
|
|
97
135
|
var isDev = process.env.NODE_ENV === "development";
|
|
98
136
|
var logger = createLogger();
|
|
99
137
|
function getPkg() {
|
|
100
|
-
const pkgFile =
|
|
138
|
+
const pkgFile = path2.resolve(process.cwd(), "package.json");
|
|
101
139
|
if (!fs2.existsSync(pkgFile)) {
|
|
102
140
|
throw new Error("Main file is not specified, and no package.json found");
|
|
103
141
|
}
|
|
@@ -153,43 +191,46 @@ function preMergeOptions(options) {
|
|
|
153
191
|
);
|
|
154
192
|
}
|
|
155
193
|
opts.extension = opt;
|
|
156
|
-
if (opts.webview
|
|
157
|
-
|
|
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);
|
|
158
200
|
}
|
|
159
|
-
opts.webview = opts.webview ?? WEBVIEW_METHOD_NAME;
|
|
160
201
|
return opts;
|
|
161
202
|
}
|
|
162
203
|
var prodCachePkgName = `${PACKAGE_NAME}-inject`;
|
|
163
|
-
function genProdWebviewCode(cache) {
|
|
164
|
-
|
|
204
|
+
function genProdWebviewCode(cache, webview) {
|
|
205
|
+
webview = Object.assign({}, webview);
|
|
206
|
+
const prodCacheFolder = path2.join(cwd2(), "node_modules", prodCachePkgName);
|
|
165
207
|
emptyPath(prodCacheFolder);
|
|
166
|
-
const destFile =
|
|
208
|
+
const destFile = path2.join(prodCacheFolder, "index.ts");
|
|
167
209
|
function handleHtmlCode(html) {
|
|
168
210
|
const root = htmlParser(html);
|
|
169
211
|
const head = root.querySelector("head");
|
|
170
212
|
if (!head) {
|
|
171
213
|
root == null ? void 0 : root.insertAdjacentHTML("beforeend", "<head></head>");
|
|
172
214
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
element.setAttribute(
|
|
188
|
-
}
|
|
189
|
-
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
|
+
});
|
|
190
231
|
});
|
|
191
|
-
}
|
|
192
|
-
return root.toString();
|
|
232
|
+
}
|
|
233
|
+
return root.removeWhitespace().toString();
|
|
193
234
|
}
|
|
194
235
|
const cacheCode = (
|
|
195
236
|
/* js */
|
|
@@ -216,7 +257,7 @@ export default function getWebviewHtml(webview: Webview, context: ExtensionConte
|
|
|
216
257
|
const nonce = uuid();
|
|
217
258
|
const baseUri = webview.asWebviewUri(Uri.joinPath(context.extensionUri, (process.env.VITE_WEBVIEW_DIST || 'dist')));
|
|
218
259
|
const html = htmlCode[inputName || 'index'] || '';
|
|
219
|
-
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);
|
|
220
261
|
}
|
|
221
262
|
`
|
|
222
263
|
);
|
|
@@ -230,8 +271,8 @@ function useVSCodePlugin(options) {
|
|
|
230
271
|
let outDir = ((_a = config == null ? void 0 : config.build) == null ? void 0 : _a.outDir) || "dist";
|
|
231
272
|
opts.extension ??= {};
|
|
232
273
|
if (opts.recommended) {
|
|
233
|
-
opts.extension.outDir =
|
|
234
|
-
outDir =
|
|
274
|
+
opts.extension.outDir = path2.resolve(outDir, "extension");
|
|
275
|
+
outDir = path2.resolve(outDir, "webview");
|
|
235
276
|
}
|
|
236
277
|
const assetsDir = ((_b = config == null ? void 0 : config.build) == null ? void 0 : _b.assetsDir) || "assets";
|
|
237
278
|
const output = {
|
|
@@ -258,12 +299,12 @@ function useVSCodePlugin(options) {
|
|
|
258
299
|
let webviewClient;
|
|
259
300
|
let webviewNpmPath;
|
|
260
301
|
if (opts.webview) {
|
|
261
|
-
webviewNpmPath =
|
|
262
|
-
if (!fs2.existsSync(webviewNpmPath)) {
|
|
302
|
+
webviewNpmPath = getWebviewNpmPath();
|
|
303
|
+
if (!webviewNpmPath || !fs2.existsSync(webviewNpmPath)) {
|
|
263
304
|
logger.warn(`[${WEBVIEW_PACKAGE_NAME}] is not installed, please install it first!`);
|
|
264
305
|
} else {
|
|
265
306
|
const fileName = "client.global.js";
|
|
266
|
-
const clientFile =
|
|
307
|
+
const clientFile = path2.join(webviewNpmPath, fileName);
|
|
267
308
|
if (!fs2.existsSync(clientFile)) {
|
|
268
309
|
logger.warn(`[${fileName}] is does not exist, please update the package!`);
|
|
269
310
|
} else {
|
|
@@ -292,21 +333,22 @@ function useVSCodePlugin(options) {
|
|
|
292
333
|
};
|
|
293
334
|
logger.info("extension build start");
|
|
294
335
|
let buildCount = 0;
|
|
336
|
+
const webview = opts == null ? void 0 : opts.webview;
|
|
295
337
|
const { onSuccess: _onSuccess, ...tsupOptions } = opts.extension || {};
|
|
296
338
|
await tsupBuild(
|
|
297
339
|
merge(tsupOptions, {
|
|
298
340
|
watch: true,
|
|
299
341
|
env,
|
|
300
342
|
silent: true,
|
|
301
|
-
esbuildPlugins: [
|
|
343
|
+
esbuildPlugins: !webview ? [] : [
|
|
302
344
|
{
|
|
303
345
|
name: "@tomjs:vscode:inject",
|
|
304
346
|
setup(build) {
|
|
305
347
|
build.onLoad({ filter: /\.ts$/ }, async (args) => {
|
|
306
348
|
const file = fs2.readFileSync(args.path, "utf-8");
|
|
307
|
-
if (file.includes(`${
|
|
349
|
+
if (file.includes(`${webview.name}(`)) {
|
|
308
350
|
return {
|
|
309
|
-
contents: `import ${
|
|
351
|
+
contents: `import ${webview.name} from '@tomjs/vscode-extension-webview';
|
|
310
352
|
` + file,
|
|
311
353
|
loader: "ts"
|
|
312
354
|
};
|
|
@@ -357,10 +399,11 @@ function useVSCodePlugin(options) {
|
|
|
357
399
|
},
|
|
358
400
|
closeBundle() {
|
|
359
401
|
let webviewPath;
|
|
360
|
-
|
|
361
|
-
|
|
402
|
+
const webview = opts == null ? void 0 : opts.webview;
|
|
403
|
+
if (webview) {
|
|
404
|
+
webviewPath = genProdWebviewCode(prodHtmlCache, webview);
|
|
362
405
|
}
|
|
363
|
-
let outDir = buildConfig.build.outDir.replace(
|
|
406
|
+
let outDir = buildConfig.build.outDir.replace(cwd2(), "").replaceAll("\\", "/");
|
|
364
407
|
if (outDir.startsWith("/")) {
|
|
365
408
|
outDir = outDir.substring(1);
|
|
366
409
|
}
|
|
@@ -374,15 +417,15 @@ function useVSCodePlugin(options) {
|
|
|
374
417
|
merge(tsupOptions, {
|
|
375
418
|
env,
|
|
376
419
|
silent: true,
|
|
377
|
-
esbuildPlugins: !
|
|
420
|
+
esbuildPlugins: !webview ? [] : [
|
|
378
421
|
{
|
|
379
422
|
name: "@tomjs:vscode:inject",
|
|
380
423
|
setup(build) {
|
|
381
424
|
build.onLoad({ filter: /\.ts$/ }, async (args) => {
|
|
382
425
|
const file = fs2.readFileSync(args.path, "utf-8");
|
|
383
|
-
if (file.includes(`${
|
|
426
|
+
if (file.includes(`${webview.name}(`)) {
|
|
384
427
|
return {
|
|
385
|
-
contents: `import ${
|
|
428
|
+
contents: `import ${webview.name} from \`${webviewPath}\`;
|
|
386
429
|
` + file,
|
|
387
430
|
loader: "ts"
|
|
388
431
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomjs/vite-plugin-vscode",
|
|
3
|
-
"version": "2.
|
|
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",
|