refactor: Refactor VSCode extension using React.
This commit is contained in:
parent
cad699681b
commit
84222db4cc
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 115 KiB |
54
assets/chatPanel.html
Normal file
54
assets/chatPanel.html
Normal file
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<!-- Meta tags for responsiveness and charset -->
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<title>Chat Panel</title>
|
||||
|
||||
<!-- Font Awesome icons -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.0/css/all.min.css" />
|
||||
<link rel="stylesheet" href="<vscode-resource:/assets/chatPanel.css>" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/markdown-it/dist/markdown-it.min.js"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/themes/prism.min.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/prism.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="chat-container">
|
||||
<div id="messages-container">
|
||||
<!-- Chat messages will be added here dynamically -->
|
||||
</div>
|
||||
<div id="input-resize-handle" class="input-resize-handle"></div>
|
||||
<div id="input-container">
|
||||
<textarea id="message-input" placeholder="Type your message..."></textarea>
|
||||
<button id="send-button">Send</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="context-menu" id="context-menu">
|
||||
<div class="context-menu-item" id="menu-item-1">Insert Code</div>
|
||||
</div>
|
||||
|
||||
<!-- Load the chatPanel.js file -->
|
||||
<script src="<vscode-resource:/assets/messageUtil.js>"></script>
|
||||
<script src="<vscode-resource:/assets/codeBlock.js>"></script>
|
||||
<script src="<vscode-resource:/assets/markdown.js>"></script>
|
||||
<script src="<vscode-resource:/assets/contextMenu.js>"></script>
|
||||
<script src="<vscode-resource:/assets/inputContainer.js>"></script>
|
||||
<script src="<vscode-resource:/assets/messageContainer.js>"></script>
|
||||
<script src="<vscode-resource:/assets/actionButton.js>"></script>
|
||||
<script src="<vscode-resource:/assets/chatUI.js>"></script>
|
||||
<script src="<vscode-resource:/assets/resizeInput.js>"></script>
|
||||
<script src="<vscode-resource:/assets/clipboard.js>"></script>
|
||||
<script src="<vscode-resource:/assets/main.js>"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
Prism.highlightAll();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
3
babel.config.js
Normal file
3
babel.config.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ['@babel/preset-env', '@babel/preset-react'],
|
||||
};
|
@ -1,51 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Meta tags for responsiveness and charset -->
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<title>Chat Panel</title>
|
||||
|
||||
<!-- Font Awesome icons -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.0/css/all.min.css" />
|
||||
<link rel="stylesheet" href="<vscode-resource:/chatPanel.css>" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/markdown-it/dist/markdown-it.min.js"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/themes/prism.min.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/prism.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="chat-container">
|
||||
<div id="messages-container">
|
||||
<!-- Chat messages will be added here dynamically -->
|
||||
</div>
|
||||
<div id="input-resize-handle" class="input-resize-handle"></div>
|
||||
<div id="input-container">
|
||||
<textarea id="message-input" placeholder="Type your message..."></textarea>
|
||||
<button id="send-button">Send</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="context-menu" id="context-menu">
|
||||
<div class="context-menu-item" id="menu-item-1">Insert Code</div>
|
||||
</div>
|
||||
|
||||
<!-- Load the chatPanel.js file -->
|
||||
<script src="<vscode-resource:/messageUtil.js>"></script>
|
||||
<script src="<vscode-resource:/codeBlock.js>"></script>
|
||||
<script src="<vscode-resource:/markdown.js>"></script>
|
||||
<script src="<vscode-resource:/contextMenu.js>"></script>
|
||||
<script src="<vscode-resource:/inputContainer.js>"></script>
|
||||
<script src="<vscode-resource:/messageContainer.js>"></script>
|
||||
<script src="<vscode-resource:/actionButton.js>"></script>
|
||||
<script src="<vscode-resource:/chatUI.js>"></script>
|
||||
<script src="<vscode-resource:/resizeInput.js>"></script>
|
||||
<script src="<vscode-resource:/clipboard.js>"></script>
|
||||
<script src="<vscode-resource:/main.js>"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
Prism.highlightAll();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
10661
package-lock.json
generated
10661
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
42
package.json
42
package.json
@ -11,6 +11,12 @@
|
||||
],
|
||||
"activationEvents": [],
|
||||
"main": "./dist/extension.js",
|
||||
"files": [
|
||||
"dist/*",
|
||||
"assets/*",
|
||||
"LICENSE",
|
||||
"README.md"
|
||||
],
|
||||
"contributes": {
|
||||
"views": {
|
||||
"explorer": [
|
||||
@ -71,31 +77,61 @@
|
||||
"watch-tests": "tsc -p . -w --outDir out",
|
||||
"pretest": "npm run compile-tests && npm run compile && npm run lint",
|
||||
"lint": "eslint src --ext ts",
|
||||
"test": "node ./out/test/runTest.js"
|
||||
"test": "node ./out/test/runTest.js",
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"dev": "webpack serve --config webpack.config.js --open"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.21.8",
|
||||
"@babel/preset-env": "^7.21.5",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@babel/preset-typescript": "^7.21.5",
|
||||
"@types/glob": "^8.1.0",
|
||||
"@types/jest": "^29.5.1",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/node": "16.x",
|
||||
"@types/react-dom": "^18.2.3",
|
||||
"@types/shell-escape": "^0.2.1",
|
||||
"@types/vscode": "^1.77.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.56.0",
|
||||
"@typescript-eslint/parser": "^5.56.0",
|
||||
"@vscode/test-electron": "^2.3.0",
|
||||
"babel-loader": "^9.1.2",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.7.3",
|
||||
"dotenv": "^16.0.3",
|
||||
"eslint": "^8.36.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"glob": "^8.1.0",
|
||||
"html-webpack-plugin": "^5.5.1",
|
||||
"jest": "^29.5.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"mocha": "^10.2.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-redux": "^8.0.5",
|
||||
"redux": "^4.2.1",
|
||||
"style-loader": "^3.3.2",
|
||||
"ts-jest": "^29.1.0",
|
||||
"ts-loader": "^9.4.2",
|
||||
"typescript": "^4.9.5",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.76.3",
|
||||
"webpack-cli": "^5.0.1"
|
||||
"webpack-cli": "^5.0.1",
|
||||
"webpack-dev-server": "^4.13.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.10.8",
|
||||
"@mantine/core": "^6.0.10",
|
||||
"@mantine/dropzone": "^6.0.10",
|
||||
"@mantine/hooks": "^6.0.10",
|
||||
"@mantine/prism": "^6.0.10",
|
||||
"@mantine/tiptap": "^6.0.10",
|
||||
"@tabler/icons-react": "^2.17.0",
|
||||
"@tiptap/extension-link": "^2.0.3",
|
||||
"@tiptap/react": "^2.0.3",
|
||||
"@tiptap/starter-kit": "^2.0.3",
|
||||
"axios": "^1.3.6",
|
||||
"dotenv": "^16.0.3",
|
||||
"node-fetch": "^3.3.1",
|
||||
"nonce": "^1.0.4",
|
||||
"openai": "^3.2.1",
|
||||
|
@ -37,7 +37,7 @@ export default class ChatPanel {
|
||||
column || vscode.ViewColumn.One,
|
||||
{
|
||||
enableScripts: true,
|
||||
localResourceRoots: [vscode.Uri.joinPath(extensionUri, 'media')],
|
||||
localResourceRoots: [vscode.Uri.joinPath(extensionUri, 'dist')],
|
||||
retainContextWhenHidden: true
|
||||
}
|
||||
);
|
||||
@ -55,7 +55,7 @@ export default class ChatPanel {
|
||||
private setWebviewOptions(extensionUri: vscode.Uri) {
|
||||
this._panel.webview.options = {
|
||||
enableScripts: true,
|
||||
localResourceRoots: [vscode.Uri.joinPath(extensionUri, 'media')],
|
||||
localResourceRoots: [vscode.Uri.joinPath(extensionUri, 'dist')],
|
||||
};
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ export default class ChatPanel {
|
||||
this._panel.webview.html = this._getHtmlContent(extensionUri);
|
||||
}
|
||||
|
||||
public panel() : vscode.WebviewPanel {
|
||||
public panel(): vscode.WebviewPanel {
|
||||
return this._panel;
|
||||
}
|
||||
|
||||
@ -83,11 +83,12 @@ export default class ChatPanel {
|
||||
|
||||
// Get the HTML content for the panel
|
||||
private _getHtmlContent(extensionUri: vscode.Uri): string {
|
||||
const htmlPath = vscode.Uri.joinPath(extensionUri, 'media', 'chatPanel.html');
|
||||
const htmlPath = vscode.Uri.joinPath(extensionUri, 'dist', 'assets', 'chatPanel.html');
|
||||
// const htmlPath = vscode.Uri.joinPath(extensionUri, 'dist', 'index.html');
|
||||
const htmlContent = fs.readFileSync(htmlPath.fsPath, 'utf8');
|
||||
|
||||
return htmlContent.replace(/<vscode-resource:(\/.+?)>/g, (_, resourcePath) => {
|
||||
const resourceUri = vscode.Uri.joinPath(extensionUri, 'media', resourcePath);
|
||||
const resourceUri = vscode.Uri.joinPath(extensionUri, 'dist', resourcePath);
|
||||
return this._panel.webview.asWebviewUri(resourceUri).toString();
|
||||
});
|
||||
}
|
||||
|
13
src/views/App.tsx
Normal file
13
src/views/App.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import { Button } from '@mantine/core';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<div>
|
||||
<h1>Hello World!</h1>
|
||||
<Button>Click me!</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
0
src/views/index.css
Normal file
0
src/views/index.css
Normal file
18
src/views/index.html
Normal file
18
src/views/index.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>My Extension</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.3.0/css/bootstrap.min.css"
|
||||
integrity="sha512-1lCvz8lRFF66HJzKpD6A+U6IVaUkV9U6xuUQVdqfdNV8YJ7zjKwJRYI95gUZ8JpWj1O9x6UuV2v0pz1yaYWX7w=="
|
||||
crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="<vscode-resource:/index.js>"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
10
src/views/index.tsx
Normal file
10
src/views/index.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import * as React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
import { MantineProvider } from '@mantine/core';
|
||||
|
||||
ReactDOM.render(
|
||||
<MantineProvider withGlobalStyles withNormalizeCSS>
|
||||
<App />
|
||||
</MantineProvider>,
|
||||
document.getElementById('root'));
|
@ -3,12 +3,15 @@
|
||||
"module": "commonjs",
|
||||
"target": "ES2020",
|
||||
"lib": [
|
||||
"ES2020"
|
||||
"ES2020",
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"outDir": "./dist",
|
||||
"sourceMap": true,
|
||||
"rootDir": "src",
|
||||
"strict": true
|
||||
"strict": true,
|
||||
"jsx": "react",
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,9 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const { DefinePlugin } = require('webpack');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
|
||||
//@ts-check
|
||||
/** @typedef {import('webpack').Configuration} WebpackConfig **/
|
||||
@ -10,13 +13,16 @@ const path = require('path');
|
||||
/** @type WebpackConfig */
|
||||
const extensionConfig = {
|
||||
target: 'node', // VS Code extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
|
||||
mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
|
||||
mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
|
||||
|
||||
entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
|
||||
entry: {
|
||||
extension: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
|
||||
index: './src/views/index.tsx'
|
||||
},
|
||||
output: {
|
||||
// the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'extension.js',
|
||||
filename: '[name].js',
|
||||
libraryTarget: 'commonjs2'
|
||||
},
|
||||
externals: {
|
||||
@ -25,18 +31,66 @@ const extensionConfig = {
|
||||
},
|
||||
resolve: {
|
||||
// support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
|
||||
extensions: ['.ts', '.js']
|
||||
extensions: ['.ts', '.tsx', '.js', '.json']
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
test: /\.tsx?$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
presets: [
|
||||
'@babel/preset-env',
|
||||
'@babel/preset-react',
|
||||
'@babel/preset-typescript'
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
loader: 'ts-loader'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.jsx?$/,
|
||||
use: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'style-loader',
|
||||
},
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
modules: {
|
||||
localIdentName: '[name]__[local]___[hash:base64:5]'
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
include: /views/
|
||||
},
|
||||
{
|
||||
test: /\.json$/i,
|
||||
use: 'json-loader',
|
||||
type: 'asset/source'
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 8192,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -44,5 +98,23 @@ const extensionConfig = {
|
||||
infrastructureLogging: {
|
||||
level: "log", // enables logging required for problem matchers
|
||||
},
|
||||
plugins: [
|
||||
// generate an HTML file that includes the extension's JavaScript file
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.resolve(__dirname, 'src', 'views', 'index.html'),
|
||||
filename: 'index.html',
|
||||
chunks: ['index']
|
||||
}),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{ from: 'assets', to: 'assets' },
|
||||
],
|
||||
}),
|
||||
// define global variables
|
||||
new DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('development')
|
||||
})
|
||||
]
|
||||
};
|
||||
module.exports = [ extensionConfig ];
|
||||
|
||||
module.exports = [extensionConfig];
|
||||
|
Loading…
x
Reference in New Issue
Block a user