✨ feat(vscode): 代码阅读入口、文件树与预览编辑器
This commit is contained in:
1 parent
4d34b8c715
commit
2b823a32ca
24 files changed
+768
-72
No files matched your search
@@ -0,0 +1,46 @@
|
||||
import type { Webview } from 'vscode'
|
||||
import { randomBytes } from 'node:crypto'
|
||||
import * as fs from 'node:fs'
|
||||
import { Uri } from 'vscode'
|
||||
|
||||
export function makeNonce(): string {
|
||||
return randomBytes(16).toString('base64').replace(/[+/=]/g, '')
|
||||
}
|
||||
|
||||
/** vite 产物目录,也是 webview 唯一放行的本地资源目录(localResourceRoots)。 */
|
||||
export function webviewUiRoot(extensionUri: Uri): Uri {
|
||||
return Uri.joinPath(extensionUri, 'dist', 'webview-ui')
|
||||
}
|
||||
|
||||
/**
|
||||
* 读 dist/webview-ui 下的一个入口页面,改成能在 webview 里跑的样子:
|
||||
* 资源路径改写成 webview URI、每个 `<script>` 带上 nonce、注入只放行这个 nonce 的 CSP。
|
||||
* entry 是入口 html 文件名(例如 'index.html');调用方还要往页面里追加别的 `<script>` 时,把同一个 nonce 传进来。
|
||||
*/
|
||||
export function webviewHtml(webview: Webview, extensionUri: Uri, entry: string, nonce = makeNonce()): string {
|
||||
const distRoot = webviewUiRoot(extensionUri)
|
||||
let html = fs.readFileSync(Uri.joinPath(distRoot, entry).fsPath, 'utf-8')
|
||||
|
||||
// vite 产物的入口是固定名(无 hash),webview 按 URL 缓存资源——必须按文件 mtime 加 ?v= 版本号,
|
||||
// 否则 reload 后仍会跑缓存里的旧入口脚本 / 样式
|
||||
html = html.replace(/(src|href)="(\/[^"]+|[^"/][^"]*)"/g, (_m, attr, p) => {
|
||||
const fileUri = Uri.joinPath(distRoot, p.replace(/^\.?\//, ''))
|
||||
let version = ''
|
||||
try {
|
||||
version = `?v=${fs.statSync(fileUri.fsPath).mtimeMs}`
|
||||
}
|
||||
catch {
|
||||
// 资源文件不存在则不加版本号
|
||||
}
|
||||
return `${attr}="${webview.asWebviewUri(fileUri)}${version}"`
|
||||
})
|
||||
|
||||
html = html.replace(/<script(\s[^>]*)?>/g, (_m, attrs) => `<script nonce="${nonce}"${attrs ?? ''}>`)
|
||||
|
||||
const cspSource = webview.cspSource
|
||||
const csp = `default-src 'none'; img-src ${cspSource} data:; style-src ${cspSource} 'unsafe-inline'; script-src 'nonce-${nonce}'; font-src ${cspSource};`
|
||||
return html.replace(
|
||||
/<head>/,
|
||||
`<head>\n <meta http-equiv="Content-Security-Policy" content="${csp}">`,
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user