@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 +21 -1
- package/README.zh_CN.md +23 -1
- package/dist/index.d.mts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +80 -73
- package/dist/index.mjs +80 -73
- package/package.json +2 -2
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`
|
|
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`
|
|
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
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
|
|
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
|
|
196
|
-
|
|
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
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
element.setAttribute(
|
|
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
|
|
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
|
|
298
|
-
let
|
|
299
|
+
let devWebviewClient;
|
|
300
|
+
let devWebviewPath;
|
|
299
301
|
if (opts.webview) {
|
|
300
|
-
|
|
301
|
-
if (
|
|
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(
|
|
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
|
-
|
|
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(`${
|
|
352
|
+
if (file.includes(`${webview.name}(`)) {
|
|
347
353
|
return {
|
|
348
|
-
contents: `import ${
|
|
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 || !
|
|
379
|
+
if (!opts.webview || !devWebviewClient) {
|
|
374
380
|
return html;
|
|
375
381
|
}
|
|
376
|
-
return html.replace(/<\/title>/i, `</title><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
|
-
|
|
400
|
-
|
|
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: !
|
|
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(`${
|
|
429
|
+
if (file.includes(`${webview.name}(`)) {
|
|
423
430
|
return {
|
|
424
|
-
contents: `import ${
|
|
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
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (
|
|
112
|
-
|
|
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
|
|
195
|
-
|
|
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
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
element.setAttribute(
|
|
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
|
|
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
|
|
297
|
-
let
|
|
298
|
+
let devWebviewClient;
|
|
299
|
+
let devWebviewPath;
|
|
298
300
|
if (opts.webview) {
|
|
299
|
-
|
|
300
|
-
if (
|
|
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(
|
|
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
|
-
|
|
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(`${
|
|
351
|
+
if (file.includes(`${webview.name}(`)) {
|
|
346
352
|
return {
|
|
347
|
-
contents: `import ${
|
|
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 || !
|
|
378
|
+
if (!opts.webview || !devWebviewClient) {
|
|
373
379
|
return html;
|
|
374
380
|
}
|
|
375
|
-
return html.replace(/<\/title>/i, `</title><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
|
-
|
|
399
|
-
|
|
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: !
|
|
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(`${
|
|
428
|
+
if (file.includes(`${webview.name}(`)) {
|
|
422
429
|
return {
|
|
423
|
-
contents: `import ${
|
|
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.
|
|
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",
|