mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 04:11:10 -05:00
Remove previous webview since we use react app now
This commit is contained in:
87
README.md
87
README.md
@@ -69,3 +69,90 @@ You can author your README using Visual Studio Code. Here are some useful editor
|
|||||||
* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/)
|
* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/)
|
||||||
|
|
||||||
**Enjoy!**
|
**Enjoy!**
|
||||||
|
|
||||||
|
# React + Create React App + Webview UI Toolkit webview extension
|
||||||
|
|
||||||
|
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/tree/main/frameworks/hello-world-react-cra
|
||||||
|
|
||||||
|
# Extension commands
|
||||||
|
|
||||||
|
A quick run down of some of the important commands that can be run when at the root of the project.
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run install:all Install package dependencies for both the extension and React webview source code.
|
||||||
|
npm run start:webview Runs the React webview source code in development mode. Open http://localhost:3000 to view it in the browser.
|
||||||
|
npm run build:webview Build React webview source code. Must be executed before compiling or running the extension.
|
||||||
|
npm run compile Compile VS Code extension
|
||||||
|
```
|
||||||
|
|
||||||
|
# Extension development cycle
|
||||||
|
|
||||||
|
The intended development cycle of this React-based webview extension is slightly different than that of other VS Code extensions.
|
||||||
|
|
||||||
|
Due to the fact that the `webview-ui` directory holds a self-contained React application we get to take advantage of some of the perks that that enables. In particular,
|
||||||
|
|
||||||
|
- UI development and iteration cycles can happen much more quickly by using Create React App (CRA)
|
||||||
|
- Dependency management and project configuration is hugely simplified
|
||||||
|
|
||||||
|
## UI development cycle
|
||||||
|
|
||||||
|
Since we can take advantage of the much faster CRA dev server, it is encouraged to begin developing webview UI by running the `npm run start:webview` command and then editing the code in the `webview-ui/src` directory.
|
||||||
|
|
||||||
|
_Tip: Open the command palette and run the `Simple Browser` command and fill in `http://localhost:3000/` when prompted. This will open a simple browser environment right inside VS Code._
|
||||||
|
|
||||||
|
### Message passing
|
||||||
|
If you need to implement message passing between the webview context and extension context via the VS Code API, a helpful utility is provided in the `webview-ui/src/utilities/vscode.ts` file.
|
||||||
|
|
||||||
|
This file contains a utility wrapper around the `acquireVsCodeApi()` function, which enables message passing and state management between the webview and extension contexts.
|
||||||
|
|
||||||
|
This utility also enables webview code to be run in the CRA dev server by using native web browser features that mock the functionality enabled by acquireVsCodeApi. This means you can keep building your webview UI with the CRA dev server even when using the VS Code API.
|
||||||
|
|
||||||
|
### Move to traditional extension development
|
||||||
|
Once you're ready to start building other parts of your extension, simply shift to a development model where you run the `npm run build:webview` command as you make changes, press `F5` to compile your extension and open a new Extension Development Host window. Inside the host window, open the command palette (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and type `Hello World (React + CRA): Show`.
|
||||||
|
|
||||||
|
## Dependency management and project configuration
|
||||||
|
|
||||||
|
As mentioned above, the `webview-ui` directory holds a self-contained and isolated React application meaning you can (for the most part) treat the development of your webview UI in the same way you would treat the development of a regular React application.
|
||||||
|
|
||||||
|
To install webview-specific dependencies simply navigate (i.e. `cd`) into the `webview-ui` directory and install any packages you need or set up any React specific configurations you want.
|
||||||
|
|
||||||
|
# Extension structure
|
||||||
|
|
||||||
|
This section provides a quick introduction into how this sample extension is organized and structured.
|
||||||
|
|
||||||
|
The two most important directories to take note of are the following:
|
||||||
|
|
||||||
|
- `src`: Contains all of the extension source code
|
||||||
|
- `webview-ui`: Contains all of the webview UI source code
|
||||||
|
|
||||||
|
## `src` directory
|
||||||
|
|
||||||
|
The `src` directory contains all of the extension-related source code and can be thought of as containing the "backend" code/logic for the entire extension. Inside of this directory you'll find the:
|
||||||
|
|
||||||
|
- `panels` directory
|
||||||
|
- `utilities` directory
|
||||||
|
- `extension.ts` file
|
||||||
|
|
||||||
|
The `panels` directory contains all of the webview-related code that will be executed within the extension context. It can be thought of as the place where all of the "backend" code for each webview panel is contained.
|
||||||
|
|
||||||
|
This directory will typically contain individual TypeScript or JavaScript files that contain a class which manages the state and behavior of a given webview panel. Each class is usually in charge of:
|
||||||
|
|
||||||
|
- Creating and rendering the webview panel
|
||||||
|
- Properly cleaning up and disposing of webview resources when the panel is closed
|
||||||
|
- Setting message listeners so data can be passed between the webview and extension
|
||||||
|
- Setting the initial HTML markdown of the webview panel
|
||||||
|
- Other custom logic and behavior related to webview panel management
|
||||||
|
|
||||||
|
As the name might suggest, the `utilties` directory contains all of the extension utility functions that make setting up and managing an extension easier. In this case, it contains `getUri.ts` which contains a helper function which will get the webview URI of a given file or resource.
|
||||||
|
|
||||||
|
Finally, `extension.ts` is where all the logic for activating and deactiving the extension usually live. This is also the place where extension commands are registered.
|
||||||
|
|
||||||
|
## `webview-ui` directory
|
||||||
|
|
||||||
|
The `webview-ui` directory contains all of the React-based webview source code and can be thought of as containing the "frontend" code/logic for the extension webview.
|
||||||
|
|
||||||
|
This directory is special because it contains a full-blown React application which was created using the TypeScript [Create React App](https://create-react-app.dev/) template. As a result, `webview-ui` contains its own `package.json`, `node_modules`, `tsconfig.json`, and so on––separate from the `hello-world` extension in the root directory.
|
||||||
|
|
||||||
|
This strays a bit from other extension structures, in that you'll usually find the extension and webview dependencies, configurations, and source code more closely integrated or combined with each other.
|
||||||
|
|
||||||
|
However, in this case, there are some unique benefits and reasons for why this sample extension does not follow those patterns such as easier management of conflicting dependencies and configurations, as well as the ability to use the CRA dev server, which drastically improves the speed of developing your webview UI, versus recompiling your extension code every time you make a change to the webview.
|
||||||
|
|||||||
12
esbuild.js
12
esbuild.js
@@ -44,25 +44,13 @@ const extensionConfig = {
|
|||||||
external: ["vscode"],
|
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 extensionCtx = await esbuild.context(extensionConfig)
|
const extensionCtx = await esbuild.context(extensionConfig)
|
||||||
const webviewCtx = await esbuild.context(webviewConfig)
|
|
||||||
if (watch) {
|
if (watch) {
|
||||||
await extensionCtx.watch()
|
await extensionCtx.watch()
|
||||||
await webviewCtx.watch()
|
|
||||||
} else {
|
} else {
|
||||||
await extensionCtx.rebuild()
|
await extensionCtx.rebuild()
|
||||||
await extensionCtx.dispose()
|
await extensionCtx.dispose()
|
||||||
await webviewCtx.rebuild()
|
|
||||||
await webviewCtx.dispose()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
123
package-lock.json
generated
123
package-lock.json
generated
@@ -7,14 +7,10 @@
|
|||||||
"": {
|
"": {
|
||||||
"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",
|
||||||
@@ -657,52 +653,6 @@
|
|||||||
"@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",
|
||||||
@@ -783,13 +733,6 @@
|
|||||||
"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",
|
||||||
@@ -1031,21 +974,6 @@
|
|||||||
"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",
|
||||||
@@ -2190,12 +2118,6 @@
|
|||||||
"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",
|
||||||
@@ -3237,13 +3159,6 @@
|
|||||||
"@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",
|
||||||
@@ -3388,19 +3303,6 @@
|
|||||||
"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",
|
||||||
@@ -4373,19 +4275,6 @@
|
|||||||
"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",
|
||||||
@@ -5091,12 +4980,6 @@
|
|||||||
"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",
|
||||||
@@ -5201,12 +5084,6 @@
|
|||||||
"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",
|
||||||
|
|||||||
@@ -75,7 +75,6 @@
|
|||||||
"@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",
|
||||||
@@ -84,8 +83,5 @@
|
|||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"typescript": "^5.4.5"
|
"typescript": "^5.4.5"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@vscode/webview-ui-toolkit": "^1.4.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
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,7 +1,6 @@
|
|||||||
// 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"
|
|
||||||
import { SidebarProvider } from "./providers/SidebarProvider"
|
import { SidebarProvider } from "./providers/SidebarProvider"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -28,15 +27,8 @@ export function activate(context: vscode.ExtensionContext) {
|
|||||||
// // 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)
|
|
||||||
|
|
||||||
const provider = new SidebarProvider(context.extensionUri)
|
const provider = new SidebarProvider(context.extensionUri)
|
||||||
|
|
||||||
context.subscriptions.push(vscode.window.registerWebviewViewProvider(SidebarProvider.viewType, provider))
|
context.subscriptions.push(vscode.window.registerWebviewViewProvider(SidebarProvider.viewType, provider))
|
||||||
|
|||||||
@@ -65,6 +65,15 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
|
|||||||
// const stylesheetUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, "assets", "main.css"))
|
// const stylesheetUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, "assets", "main.css"))
|
||||||
|
|
||||||
// Use a nonce to only allow a specific script to be run.
|
// Use a nonce to only allow a specific script to be run.
|
||||||
|
/*
|
||||||
|
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()
|
const nonce = getNonce()
|
||||||
|
|
||||||
// Tip: Install the es6-string-html VS Code extension to enable code highlighting below
|
// Tip: Install the es6-string-html VS Code extension to enable code highlighting below
|
||||||
|
|||||||
@@ -1,177 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
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! 🤠",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/webview/main.ts
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
import {
|
|
||||||
provideVSCodeDesignSystem,
|
|
||||||
Button,
|
|
||||||
Dropdown,
|
|
||||||
ProgressRing,
|
|
||||||
TextField,
|
|
||||||
vsCodeButton,
|
|
||||||
vsCodeDropdown,
|
|
||||||
vsCodeOption,
|
|
||||||
vsCodeTextField,
|
|
||||||
vsCodeProgressRing,
|
|
||||||
} from "@vscode/webview-ui-toolkit";
|
|
||||||
|
|
||||||
// In order to use the Webview UI Toolkit web components they
|
|
||||||
// must be registered with the browser (i.e. webview) using the
|
|
||||||
// syntax below.
|
|
||||||
provideVSCodeDesignSystem().register(
|
|
||||||
vsCodeButton(),
|
|
||||||
vsCodeDropdown(),
|
|
||||||
vsCodeOption(),
|
|
||||||
vsCodeProgressRing(),
|
|
||||||
vsCodeTextField()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get access to the VS Code API from within the webview context
|
|
||||||
const vscode = acquireVsCodeApi();
|
|
||||||
|
|
||||||
// Just like a regular webpage we need to wait for the webview
|
|
||||||
// DOM to load before we can reference any of the HTML elements
|
|
||||||
// or toolkit components
|
|
||||||
window.addEventListener("load", main);
|
|
||||||
|
|
||||||
// Main function that gets executed once the webview DOM loads
|
|
||||||
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 checkWeatherButton = document.getElementById("check-weather-button") as Button;
|
|
||||||
checkWeatherButton.addEventListener("click", checkWeather);
|
|
||||||
|
|
||||||
setVSCodeMessageListener();
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkWeather() {
|
|
||||||
const location = document.getElementById("location") as TextField;
|
|
||||||
const unit = document.getElementById("unit") as Dropdown;
|
|
||||||
|
|
||||||
// Passes a message back to the extension context with the location that
|
|
||||||
// should be searched for and the degree unit (F or C) that should be returned
|
|
||||||
vscode.postMessage({
|
|
||||||
command: "weather",
|
|
||||||
location: location.value,
|
|
||||||
unit: unit.value,
|
|
||||||
});
|
|
||||||
|
|
||||||
displayLoadingState();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets up an event listener to listen for messages passed from the extension context
|
|
||||||
// and executes code based on the message that is recieved
|
|
||||||
function setVSCodeMessageListener() {
|
|
||||||
window.addEventListener("message", (event) => {
|
|
||||||
const command = event.data.command;
|
|
||||||
|
|
||||||
// switch (command) {
|
|
||||||
// case "weather":
|
|
||||||
// const weatherData = JSON.parse(event.data.payload);
|
|
||||||
// displayWeatherData(weatherData);
|
|
||||||
// break;
|
|
||||||
// case "error":
|
|
||||||
// displayError(event.data.message);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayLoadingState() {
|
|
||||||
const loading = document.getElementById("loading") as ProgressRing;
|
|
||||||
const icon = document.getElementById("icon");
|
|
||||||
const summary = document.getElementById("summary");
|
|
||||||
if (loading && icon && summary) {
|
|
||||||
loading.classList.remove("hidden");
|
|
||||||
icon.classList.add("hidden");
|
|
||||||
summary.textContent = "Getting weather...";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// function displayWeatherData(weatherData) {
|
|
||||||
// const loading = document.getElementById("loading") as ProgressRing;
|
|
||||||
// const icon = document.getElementById("icon");
|
|
||||||
// const summary = document.getElementById("summary");
|
|
||||||
// if (loading && icon && summary) {
|
|
||||||
// loading.classList.add("hidden");
|
|
||||||
// icon.classList.remove("hidden");
|
|
||||||
// icon.textContent = getWeatherIcon(weatherData);
|
|
||||||
// summary.textContent = getWeatherSummary(weatherData);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function displayError(errorMsg) {
|
|
||||||
// const loading = document.getElementById("loading") as ProgressRing;
|
|
||||||
// const icon = document.getElementById("icon");
|
|
||||||
// const summary = document.getElementById("summary");
|
|
||||||
// if (loading && icon && summary) {
|
|
||||||
// loading.classList.add("hidden");
|
|
||||||
// icon.classList.add("hidden");
|
|
||||||
// summary.textContent = errorMsg;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function getWeatherSummary(weatherData) {
|
|
||||||
// const skyText = weatherData.current.skytext;
|
|
||||||
// const temperature = weatherData.current.temperature;
|
|
||||||
// const degreeType = weatherData.location.degreetype;
|
|
||||||
|
|
||||||
// return `${skyText}, ${temperature}${degreeType}`;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function getWeatherIcon(weatherData) {
|
|
||||||
// const skyText = weatherData.current.skytext.toLowerCase();
|
|
||||||
// let icon = "";
|
|
||||||
|
|
||||||
// switch (skyText) {
|
|
||||||
// case "sunny":
|
|
||||||
// icon = "☀️";
|
|
||||||
// break;
|
|
||||||
// case "mostly sunny":
|
|
||||||
// icon = "🌤";
|
|
||||||
// break;
|
|
||||||
// case "partly sunny":
|
|
||||||
// icon = "🌥";
|
|
||||||
// break;
|
|
||||||
// case "clear":
|
|
||||||
// icon = "☀️";
|
|
||||||
// break;
|
|
||||||
// case "fair":
|
|
||||||
// icon = "🌥";
|
|
||||||
// break;
|
|
||||||
// case "mostly cloudy":
|
|
||||||
// icon = "☁️";
|
|
||||||
// break;
|
|
||||||
// case "cloudy":
|
|
||||||
// icon = "☁️";
|
|
||||||
// break;
|
|
||||||
// case "rain showers":
|
|
||||||
// icon = "🌦";
|
|
||||||
// break;
|
|
||||||
// default:
|
|
||||||
// icon = "✨";
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return icon;
|
|
||||||
// }
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
h1 {
|
|
||||||
font-size: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#search-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#location {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#unit {
|
|
||||||
min-width: 30px;
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#check-weather-button {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#results-container {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-around;
|
|
||||||
background-color: var(--vscode-input-background);
|
|
||||||
padding: 1rem;
|
|
||||||
margin: 1rem 0;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#icon {
|
|
||||||
font-size: 3em;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,14 @@ import logo from "./logo.svg"
|
|||||||
import "./App.css"
|
import "./App.css"
|
||||||
|
|
||||||
import { vscode } from "./utilities/vscode"
|
import { vscode } from "./utilities/vscode"
|
||||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
import {
|
||||||
|
VSCodeButton,
|
||||||
|
VSCodeDataGrid,
|
||||||
|
VSCodeDataGridRow,
|
||||||
|
VSCodeDataGridCell,
|
||||||
|
VSCodeTextField,
|
||||||
|
VSCodeProgressRing,
|
||||||
|
} from "@vscode/webview-ui-toolkit/react"
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
function handleHowdyClick() {
|
function handleHowdyClick() {
|
||||||
@@ -13,10 +20,65 @@ function App() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rowData = [
|
||||||
|
{
|
||||||
|
cell1: "Cell Data",
|
||||||
|
cell2: "Cell Data",
|
||||||
|
cell3: "Cell Data",
|
||||||
|
cell4: "Cell Data",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cell1: "Cell Data",
|
||||||
|
cell2: "Cell Data",
|
||||||
|
cell3: "Cell Data",
|
||||||
|
cell4: "Cell Data",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cell1: "Cell Data",
|
||||||
|
cell2: "Cell Data",
|
||||||
|
cell3: "Cell Data",
|
||||||
|
cell4: "Cell Data",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main>
|
<main>
|
||||||
<h1>Hello World!</h1>
|
<h1>Hello World!</h1>
|
||||||
<VSCodeButton onClick={handleHowdyClick}>Howdy!</VSCodeButton>
|
<VSCodeButton onClick={handleHowdyClick}>Howdy!</VSCodeButton>
|
||||||
|
|
||||||
|
<div className="grid gap-3 p-2 place-items-start">
|
||||||
|
<VSCodeDataGrid>
|
||||||
|
<VSCodeDataGridRow row-type="header">
|
||||||
|
<VSCodeDataGridCell cell-type="columnheader" grid-column="1">
|
||||||
|
A Custom Header Title
|
||||||
|
</VSCodeDataGridCell>
|
||||||
|
<VSCodeDataGridCell cell-type="columnheader" grid-column="2">
|
||||||
|
Another Custom Title
|
||||||
|
</VSCodeDataGridCell>
|
||||||
|
<VSCodeDataGridCell cell-type="columnheader" grid-column="3">
|
||||||
|
Title Is Custom
|
||||||
|
</VSCodeDataGridCell>
|
||||||
|
<VSCodeDataGridCell cell-type="columnheader" grid-column="4">
|
||||||
|
Custom Title
|
||||||
|
</VSCodeDataGridCell>
|
||||||
|
</VSCodeDataGridRow>
|
||||||
|
{rowData.map((row) => (
|
||||||
|
<VSCodeDataGridRow>
|
||||||
|
<VSCodeDataGridCell grid-column="1">{row.cell1}</VSCodeDataGridCell>
|
||||||
|
<VSCodeDataGridCell grid-column="2">{row.cell2}</VSCodeDataGridCell>
|
||||||
|
<VSCodeDataGridCell grid-column="3">{row.cell3}</VSCodeDataGridCell>
|
||||||
|
<VSCodeDataGridCell grid-column="4">{row.cell4}</VSCodeDataGridCell>
|
||||||
|
</VSCodeDataGridRow>
|
||||||
|
))}
|
||||||
|
</VSCodeDataGrid>
|
||||||
|
|
||||||
|
<span className="flex gap-3">
|
||||||
|
<VSCodeProgressRing />
|
||||||
|
<VSCodeTextField />
|
||||||
|
<VSCodeButton>Add</VSCodeButton>
|
||||||
|
<VSCodeButton appearance="secondary">Remove</VSCodeButton>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user