mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 12:21:13 -05:00
Add vscode-webview-ui-toolkit and follow tutorial to get started
This commit is contained in:
@@ -16,7 +16,7 @@
|
|||||||
"format": [ "camelCase", "PascalCase" ]
|
"format": [ "camelCase", "PascalCase" ]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"@typescript-eslint/semi": "warn",
|
"@typescript-eslint/semi": "off",
|
||||||
"curly": "warn",
|
"curly": "warn",
|
||||||
"eqeqeq": "warn",
|
"eqeqeq": "warn",
|
||||||
"no-throw-literal": "warn",
|
"no-throw-literal": "warn",
|
||||||
|
|||||||
7
.prettierrc.json
Normal file
7
.prettierrc.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"tabWidth": 4,
|
||||||
|
"useTabs": true,
|
||||||
|
"printWidth": 120,
|
||||||
|
"semi": false,
|
||||||
|
"jsxBracketSameLine": true
|
||||||
|
}
|
||||||
90
esbuild.js
90
esbuild.js
@@ -1,56 +1,72 @@
|
|||||||
const esbuild = require("esbuild");
|
const esbuild = require("esbuild")
|
||||||
|
|
||||||
const production = process.argv.includes('--production');
|
const production = process.argv.includes("--production")
|
||||||
const watch = process.argv.includes('--watch');
|
const watch = process.argv.includes("--watch")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {import('esbuild').Plugin}
|
* @type {import('esbuild').Plugin}
|
||||||
*/
|
*/
|
||||||
const esbuildProblemMatcherPlugin = {
|
const esbuildProblemMatcherPlugin = {
|
||||||
name: 'esbuild-problem-matcher',
|
name: "esbuild-problem-matcher",
|
||||||
|
|
||||||
setup(build) {
|
setup(build) {
|
||||||
build.onStart(() => {
|
build.onStart(() => {
|
||||||
console.log('[watch] build started');
|
console.log("[watch] build started")
|
||||||
});
|
})
|
||||||
build.onEnd((result) => {
|
build.onEnd((result) => {
|
||||||
result.errors.forEach(({ text, location }) => {
|
result.errors.forEach(({ text, location }) => {
|
||||||
console.error(`✘ [ERROR] ${text}`);
|
console.error(`✘ [ERROR] ${text}`)
|
||||||
console.error(` ${location.file}:${location.line}:${location.column}:`);
|
console.error(` ${location.file}:${location.line}:${location.column}:`)
|
||||||
});
|
})
|
||||||
console.log('[watch] build finished');
|
console.log("[watch] build finished")
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
|
const baseConfig = {
|
||||||
|
bundle: true,
|
||||||
|
minify: production,
|
||||||
|
sourcemap: !production,
|
||||||
|
logLevel: "silent",
|
||||||
|
plugins: [
|
||||||
|
/* add to the end of plugins array */
|
||||||
|
esbuildProblemMatcherPlugin,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const extensionConfig = {
|
||||||
|
...baseConfig,
|
||||||
|
entryPoints: ["src/extension.ts"],
|
||||||
|
format: "cjs",
|
||||||
|
sourcesContent: false,
|
||||||
|
platform: "node",
|
||||||
|
outfile: "dist/extension.js",
|
||||||
|
external: ["vscode"],
|
||||||
|
}
|
||||||
|
|
||||||
|
const webviewConfig = {
|
||||||
|
...baseConfig,
|
||||||
|
target: "es2020",
|
||||||
|
format: "esm",
|
||||||
|
entryPoints: ["src/webview/main.ts"],
|
||||||
|
outfile: "dist/webview.js",
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const ctx = await esbuild.context({
|
const extensionCtx = await esbuild.context(extensionConfig)
|
||||||
entryPoints: [
|
const webviewCtx = await esbuild.context(webviewConfig)
|
||||||
'src/extension.ts'
|
|
||||||
],
|
|
||||||
bundle: true,
|
|
||||||
format: 'cjs',
|
|
||||||
minify: production,
|
|
||||||
sourcemap: !production,
|
|
||||||
sourcesContent: false,
|
|
||||||
platform: 'node',
|
|
||||||
outfile: 'dist/extension.js',
|
|
||||||
external: ['vscode'],
|
|
||||||
logLevel: 'silent',
|
|
||||||
plugins: [
|
|
||||||
/* add to the end of plugins array */
|
|
||||||
esbuildProblemMatcherPlugin,
|
|
||||||
],
|
|
||||||
});
|
|
||||||
if (watch) {
|
if (watch) {
|
||||||
await ctx.watch();
|
await extensionCtx.watch()
|
||||||
|
await webviewCtx.watch()
|
||||||
} else {
|
} else {
|
||||||
await ctx.rebuild();
|
await extensionCtx.rebuild()
|
||||||
await ctx.dispose();
|
await extensionCtx.dispose()
|
||||||
|
await webviewCtx.rebuild()
|
||||||
|
await webviewCtx.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch(e => {
|
main().catch((e) => {
|
||||||
console.error(e);
|
console.error(e)
|
||||||
process.exit(1);
|
process.exit(1)
|
||||||
});
|
})
|
||||||
|
|||||||
123
package-lock.json
generated
123
package-lock.json
generated
@@ -7,10 +7,14 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "claude-dev",
|
"name": "claude-dev",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
|
"dependencies": {
|
||||||
|
"@vscode/webview-ui-toolkit": "^1.4.0"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/mocha": "^10.0.7",
|
"@types/mocha": "^10.0.7",
|
||||||
"@types/node": "20.x",
|
"@types/node": "20.x",
|
||||||
"@types/vscode": "^1.82.0",
|
"@types/vscode": "^1.82.0",
|
||||||
|
"@types/vscode-webview": "^1.57.5",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
||||||
"@typescript-eslint/parser": "^7.11.0",
|
"@typescript-eslint/parser": "^7.11.0",
|
||||||
"@vscode/test-cli": "^0.0.9",
|
"@vscode/test-cli": "^0.0.9",
|
||||||
@@ -653,6 +657,52 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@microsoft/fast-element": {
|
||||||
|
"version": "1.13.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.13.0.tgz",
|
||||||
|
"integrity": "sha512-iFhzKbbD0cFRo9cEzLS3Tdo9BYuatdxmCEKCpZs1Cro/93zNMpZ/Y9/Z7SknmW6fhDZbpBvtO8lLh9TFEcNVAQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@microsoft/fast-foundation": {
|
||||||
|
"version": "2.49.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.49.6.tgz",
|
||||||
|
"integrity": "sha512-DZVr+J/NIoskFC1Y6xnAowrMkdbf2d5o7UyWK6gW5AiQ6S386Ql8dw4KcC4kHaeE1yL2CKvweE79cj6ZhJhTvA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@microsoft/fast-element": "^1.13.0",
|
||||||
|
"@microsoft/fast-web-utilities": "^5.4.1",
|
||||||
|
"tabbable": "^5.2.0",
|
||||||
|
"tslib": "^1.13.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@microsoft/fast-foundation/node_modules/tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
|
"license": "0BSD"
|
||||||
|
},
|
||||||
|
"node_modules/@microsoft/fast-react-wrapper": {
|
||||||
|
"version": "0.3.24",
|
||||||
|
"resolved": "https://registry.npmjs.org/@microsoft/fast-react-wrapper/-/fast-react-wrapper-0.3.24.tgz",
|
||||||
|
"integrity": "sha512-sRnSBIKaO42p4mYoYR60spWVkg89wFxFAgQETIMazAm2TxtlsnsGszJnTwVhXq2Uz+XNiD8eKBkfzK5c/i6/Kw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@microsoft/fast-element": "^1.13.0",
|
||||||
|
"@microsoft/fast-foundation": "^2.49.6"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@microsoft/fast-web-utilities": {
|
||||||
|
"version": "5.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@microsoft/fast-web-utilities/-/fast-web-utilities-5.4.1.tgz",
|
||||||
|
"integrity": "sha512-ReWYncndjV3c8D8iq9tp7NcFNc1vbVHvcBFPME2nNFKNbS1XCesYZGlIlf3ot5EmuOXPlrzUHOWzQ2vFpIkqDg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"exenv-es6": "^1.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@nodelib/fs.scandir": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@@ -733,6 +783,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/vscode-webview": {
|
||||||
|
"version": "1.57.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/vscode-webview/-/vscode-webview-1.57.5.tgz",
|
||||||
|
"integrity": "sha512-iBAUYNYkz+uk1kdsq05fEcoh8gJmwT3lqqFPN7MGyjQ3HVloViMdo7ZJ8DFIP8WOK74PjOEilosqAyxV2iUFUw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "7.15.0",
|
"version": "7.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.15.0.tgz",
|
||||||
@@ -974,6 +1031,21 @@
|
|||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@vscode/webview-ui-toolkit": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-modXVHQkZLsxgmd5yoP3ptRC/G8NBDD+ob+ngPiWNQdlrH6H1xR/qgOBD85bfU3BhOB5sZzFWBwwhp9/SfoHww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@microsoft/fast-element": "^1.12.0",
|
||||||
|
"@microsoft/fast-foundation": "^2.49.4",
|
||||||
|
"@microsoft/fast-react-wrapper": "^0.3.22",
|
||||||
|
"tslib": "^2.6.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.12.1",
|
"version": "8.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
|
||||||
@@ -2118,6 +2190,12 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/exenv-es6": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-vlVu3N8d6yEMpMsEm+7sUBAI81aqYYuEvfK0jNqmdb/OPXzzH7QWDDnVjMvDSY47JdHEqx/dfC/q8WkfoTmpGQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
@@ -3159,6 +3237,13 @@
|
|||||||
"@pkgjs/parseargs": "^0.11.0"
|
"@pkgjs/parseargs": "^0.11.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/js-tokens": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
@@ -3303,6 +3388,19 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/loose-envify": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"loose-envify": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "10.3.0",
|
"version": "10.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz",
|
||||||
@@ -4275,6 +4373,19 @@
|
|||||||
"safe-buffer": "^5.1.0"
|
"safe-buffer": "^5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react": {
|
||||||
|
"version": "18.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||||
|
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"loose-envify": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/read-pkg": {
|
"node_modules/read-pkg": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
|
||||||
@@ -4980,6 +5091,12 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tabbable": {
|
||||||
|
"version": "5.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz",
|
||||||
|
"integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/tapable": {
|
"node_modules/tapable": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||||
@@ -5084,6 +5201,12 @@
|
|||||||
"typescript": ">=4.2.0"
|
"typescript": ">=4.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tslib": {
|
||||||
|
"version": "2.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
|
||||||
|
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
|
||||||
|
"license": "0BSD"
|
||||||
|
},
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
|
|||||||
16
package.json
16
package.json
@@ -34,16 +34,20 @@
|
|||||||
"test": "vscode-test"
|
"test": "vscode-test"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/vscode": "^1.82.0",
|
|
||||||
"@types/mocha": "^10.0.7",
|
"@types/mocha": "^10.0.7",
|
||||||
"@types/node": "20.x",
|
"@types/node": "20.x",
|
||||||
|
"@types/vscode": "^1.82.0",
|
||||||
|
"@types/vscode-webview": "^1.57.5",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
||||||
"@typescript-eslint/parser": "^7.11.0",
|
"@typescript-eslint/parser": "^7.11.0",
|
||||||
"eslint": "^8.57.0",
|
|
||||||
"esbuild": "^0.21.5",
|
|
||||||
"npm-run-all": "^4.1.5",
|
|
||||||
"typescript": "^5.4.5",
|
|
||||||
"@vscode/test-cli": "^0.0.9",
|
"@vscode/test-cli": "^0.0.9",
|
||||||
"@vscode/test-electron": "^2.4.0"
|
"@vscode/test-electron": "^2.4.0",
|
||||||
|
"esbuild": "^0.21.5",
|
||||||
|
"eslint": "^8.57.0",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
|
"typescript": "^5.4.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@vscode/webview-ui-toolkit": "^1.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
112
src/HelloWorldPanel.ts
Normal file
112
src/HelloWorldPanel.ts
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
Example of vscode-webview-ui-toolkit
|
||||||
|
https://github.com/microsoft/vscode-webview-ui-toolkit/blob/main/docs/getting-started.md
|
||||||
|
https://github.com/microsoft/vscode-webview-ui-toolkit/blob/main/docs/components.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import * as vscode from "vscode"
|
||||||
|
import { getUri } from "./utilities/getUri"
|
||||||
|
import { getNonce } from "./utilities/getNonce"
|
||||||
|
|
||||||
|
export class HelloWorldPanel {
|
||||||
|
/*
|
||||||
|
- public can be access outside of class
|
||||||
|
- private can only be accessed by class itself (_ is a convention not required)
|
||||||
|
- readonly means var can only be set during declaration or in constructor
|
||||||
|
- static means var is shared among all instances of class
|
||||||
|
*/
|
||||||
|
public static currentPanel: HelloWorldPanel | undefined
|
||||||
|
private readonly panel: vscode.WebviewPanel
|
||||||
|
private disposables: vscode.Disposable[] = []
|
||||||
|
|
||||||
|
private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) {
|
||||||
|
this.panel = panel
|
||||||
|
|
||||||
|
// the method can be triggered when the webview panel is closed
|
||||||
|
this.panel.onDidDispose(() => this.dispose(), null, this.disposables)
|
||||||
|
|
||||||
|
this.panel.webview.html = this.getWebviewContent(this.panel.webview, extensionUri)
|
||||||
|
this.setWebviewMessageListener(this.panel.webview);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will be responsible for rendering the current webview panel – if it exists – or creating and displaying a new webview panel.
|
||||||
|
public static render(extensionUri: vscode.Uri) {
|
||||||
|
if (HelloWorldPanel.currentPanel) {
|
||||||
|
HelloWorldPanel.currentPanel.panel.reveal(vscode.ViewColumn.One)
|
||||||
|
} else {
|
||||||
|
const panel = vscode.window.createWebviewPanel("helloworld", "Hello World", vscode.ViewColumn.One, {
|
||||||
|
// Enable javascript in the webview
|
||||||
|
enableScripts: true,
|
||||||
|
// Restrict the webview to only load resources from the `out` directory
|
||||||
|
localResourceRoots: [vscode.Uri.joinPath(extensionUri, "dist")],
|
||||||
|
})
|
||||||
|
|
||||||
|
HelloWorldPanel.currentPanel = new HelloWorldPanel(panel, extensionUri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// webview resources are cleaned up when the webview panel is closed by the user or closed programmatically.
|
||||||
|
public dispose() {
|
||||||
|
HelloWorldPanel.currentPanel = undefined
|
||||||
|
|
||||||
|
this.panel.dispose()
|
||||||
|
|
||||||
|
while (this.disposables.length) {
|
||||||
|
const disposable = this.disposables.pop()
|
||||||
|
if (disposable) {
|
||||||
|
disposable.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// where the UI of the extension will be defined. This is also where references to CSS and JavaScript files are created and inserted into the webview HTML.
|
||||||
|
private getWebviewContent(webview: vscode.Webview, extensionUri: vscode.Uri) {
|
||||||
|
const webviewUri = getUri(webview, extensionUri, ["dist", "webview.js"])
|
||||||
|
/*
|
||||||
|
content security policy of your webview to only allow scripts that have a specific nonce
|
||||||
|
create a content security policy meta tag so that only loading scripts with a nonce is allowed
|
||||||
|
As your extension grows you will likely want to add custom styles, fonts, and/or images to your webview. If you do, you will need to update the content security policy meta tag to explicity allow for these resources. E.g.
|
||||||
|
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource}; font-src ${webview.cspSource}; img-src ${webview.cspSource} https:; script-src 'nonce-${nonce}';">
|
||||||
|
|
||||||
|
|
||||||
|
in meta tag we add nonce attribute: A cryptographic nonce (only used once) to allow scripts. The server must generate a unique nonce value each time it transmits a policy. It is critical to provide a nonce that cannot be guessed as bypassing a resource's policy is otherwise trivial.
|
||||||
|
*/
|
||||||
|
const nonce = getNonce()
|
||||||
|
|
||||||
|
return /*html*/ `
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'nonce-${nonce}';">
|
||||||
|
<title>Hello World!</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello World!</h1>
|
||||||
|
<vscode-button id="howdy">Howdy!</vscode-button>
|
||||||
|
<script type="module" nonce="${nonce}" src="${webviewUri}"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
// responsible for setting up an event listener that listens for messages passed from the webview context and executes code based on the received message.
|
||||||
|
private setWebviewMessageListener(webview: vscode.Webview) {
|
||||||
|
webview.onDidReceiveMessage(
|
||||||
|
(message: any) => {
|
||||||
|
const command = message.command
|
||||||
|
const text = message.text
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
case "hello":
|
||||||
|
vscode.window.showInformationMessage(text)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
this.disposables
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +1,31 @@
|
|||||||
// The module 'vscode' contains the VS Code extensibility API
|
// The module 'vscode' contains the VS Code extensibility API
|
||||||
// Import the module and reference it with the alias vscode in your code below
|
// Import the module and reference it with the alias vscode in your code below
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from "vscode"
|
||||||
|
import { HelloWorldPanel } from "./HelloWorldPanel"
|
||||||
|
|
||||||
// This method is called when your extension is activated
|
// This method is called when your extension is activated
|
||||||
// Your extension is activated the very first time the command is executed
|
// Your extension is activated the very first time the command is executed
|
||||||
export function activate(context: vscode.ExtensionContext) {
|
export function activate(context: vscode.ExtensionContext) {
|
||||||
|
|
||||||
// Use the console to output diagnostic information (console.log) and errors (console.error)
|
// Use the console to output diagnostic information (console.log) and errors (console.error)
|
||||||
// This line of code will only be executed once when your extension is activated
|
// This line of code will only be executed once when your extension is activated
|
||||||
console.log('Congratulations, your extension "claude-dev" is now active!');
|
console.log('Congratulations, your extension "claude-dev" is now active!')
|
||||||
|
|
||||||
// The command has been defined in the package.json file
|
// The command has been defined in the package.json file
|
||||||
// Now provide the implementation of the command with registerCommand
|
// Now provide the implementation of the command with registerCommand
|
||||||
// The commandId parameter must match the command field in package.json
|
// The commandId parameter must match the command field in package.json
|
||||||
const disposable = vscode.commands.registerCommand('claude-dev.helloWorld', () => {
|
// const disposable = vscode.commands.registerCommand("claude-dev.helloWorld", () => {
|
||||||
// The code you place here will be executed every time your command is executed
|
// // The code you place here will be executed every time your command is executed
|
||||||
// Display a message box to the user
|
// // Display a message box to the user
|
||||||
vscode.window.showInformationMessage('Hello World from claude-dev!');
|
// vscode.window.showInformationMessage("Hello World from claude-dev!")
|
||||||
});
|
// })
|
||||||
|
|
||||||
context.subscriptions.push(disposable);
|
// context.subscriptions.push(disposable)
|
||||||
|
|
||||||
|
const helloCommand = vscode.commands.registerCommand("claude-dev.helloWorld", () => {
|
||||||
|
HelloWorldPanel.render(context.extensionUri)
|
||||||
|
})
|
||||||
|
|
||||||
|
context.subscriptions.push(helloCommand)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method is called when your extension is deactivated
|
// This method is called when your extension is deactivated
|
||||||
|
|||||||
8
src/utilities/getNonce.ts
Normal file
8
src/utilities/getNonce.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export function getNonce() {
|
||||||
|
let text = ""
|
||||||
|
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||||
|
for (let i = 0; i < 32; i++) {
|
||||||
|
text += possible.charAt(Math.floor(Math.random() * possible.length))
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
5
src/utilities/getUri.ts
Normal file
5
src/utilities/getUri.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { Uri, Webview } from "vscode"
|
||||||
|
|
||||||
|
export function getUri(webview: Webview, extensionUri: Uri, pathList: string[]) {
|
||||||
|
return webview.asWebviewUri(Uri.joinPath(extensionUri, ...pathList))
|
||||||
|
}
|
||||||
25
src/webview/main.ts
Normal file
25
src/webview/main.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { provideVSCodeDesignSystem, vsCodeButton, vsCodeCheckbox } from "@vscode/webview-ui-toolkit"
|
||||||
|
// const toolkit = require("@vscode/webview-ui-toolkit")
|
||||||
|
// /*
|
||||||
|
// You must register the components you want to use
|
||||||
|
// */
|
||||||
|
provideVSCodeDesignSystem().register(vsCodeButton(), vsCodeCheckbox())
|
||||||
|
|
||||||
|
const vscode = acquireVsCodeApi();
|
||||||
|
|
||||||
|
window.addEventListener("load", main);
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
// To get improved type annotations/IntelliSense the associated class for
|
||||||
|
// a given toolkit component can be imported and used to type cast a reference
|
||||||
|
// to the element (i.e. the `as Button` syntax)
|
||||||
|
const howdyButton = document.getElementById("howdy") as Button;
|
||||||
|
howdyButton?.addEventListener("click", handleHowdyClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleHowdyClick() {
|
||||||
|
vscode.postMessage({
|
||||||
|
command: "hello",
|
||||||
|
text: "Hey there partner! 🤠",
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,16 +1,23 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "Node16",
|
"esModuleInterop": true,
|
||||||
"target": "ES2022",
|
"experimentalDecorators": true,
|
||||||
"lib": [
|
"forceConsistentCasingInFileNames": true,
|
||||||
"ES2022"
|
"isolatedModules": true,
|
||||||
],
|
"lib": ["es2022", "esnext.disposable", "DOM"],
|
||||||
"sourceMap": true,
|
"module": "esnext",
|
||||||
|
"moduleResolution": "Bundler",
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"resolveJsonModule": true,
|
||||||
"rootDir": "src",
|
"rootDir": "src",
|
||||||
"strict": true /* enable all strict type-checking options */
|
"skipLibCheck": true,
|
||||||
/* Additional Checks */
|
"sourceMap": true,
|
||||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
"strict": true,
|
||||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
"target": "es2022",
|
||||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
"useDefineForClassFields": true,
|
||||||
|
"useUnknownInCatchVariables": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user