Unify the Webpack bundle

This will move all webviews into a single Webpack bundle. This will make
it easier to add new webviews since we don't need to add a new bundle,
but just need to add a new directory with an `index.tsx` file.

It also moves the CSS processing to Webpack so that we don't need to
specify the CSS files to use separately, but can simply do so in the
TypeScript files.
This commit is contained in:
Koen Vlaswinkel
2022-08-26 11:15:24 +02:00
parent ac7211c117
commit 45da1e0f1f
56 changed files with 395 additions and 221 deletions

View File

@@ -1,5 +1,5 @@
import * as gulp from 'gulp';
import { compileTypeScript, watchTypeScript, copyViewCss, cleanOutput, watchCss } from './typescript';
import { compileTypeScript, watchTypeScript, cleanOutput } from './typescript';
import { compileTextMateGrammar } from './textmate';
import { copyTestData } from './tests';
import { compileView, watchView } from './webpack';
@@ -10,7 +10,7 @@ export const buildWithoutPackage =
gulp.series(
cleanOutput,
gulp.parallel(
compileTypeScript, compileTextMateGrammar, compileView, copyTestData, copyViewCss
compileTypeScript, compileTextMateGrammar, compileView, copyTestData
)
);
@@ -23,6 +23,5 @@ export {
copyTestData,
injectAppInsightsKey,
compileView,
watchCss
};
export default gulp.series(buildWithoutPackage, injectAppInsightsKey, packageExtension);

View File

@@ -39,13 +39,3 @@ export function compileTypeScript() {
export function watchTypeScript() {
gulp.watch('src/**/*.ts', compileTypeScript);
}
export function watchCss() {
gulp.watch('src/**/*.css', copyViewCss);
}
/** Copy CSS files for the results view into the output directory. */
export function copyViewCss() {
return gulp.src('src/**/view/*.css')
.pipe(gulp.dest('out'));
}

View File

@@ -1,12 +1,11 @@
import * as path from 'path';
import * as webpack from 'webpack';
import * as MiniCssExtractPlugin from 'mini-css-extract-plugin';
export const config: webpack.Configuration = {
mode: 'development',
entry: {
resultsView: './src/view/results.tsx',
compareView: './src/compare/view/Compare.tsx',
remoteQueriesView: './src/remote-queries/view/RemoteQueries.tsx',
webview: './src/view/webview.tsx'
},
output: {
path: path.resolve(__dirname, '..', 'out'),
@@ -31,9 +30,7 @@ export const config: webpack.Configuration = {
{
test: /\.less$/,
use: [
{
loader: 'style-loader'
},
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
@@ -53,9 +50,7 @@ export const config: webpack.Configuration = {
{
test: /\.css$/,
use: [
{
loader: 'style-loader'
},
MiniCssExtractPlugin.loader,
{
loader: 'css-loader'
}
@@ -65,5 +60,6 @@ export const config: webpack.Configuration = {
},
performance: {
hints: false
}
},
plugins: [new MiniCssExtractPlugin()],
};

View File

@@ -81,6 +81,7 @@
"@types/unzipper": "~0.10.1",
"@types/vscode": "^1.59.0",
"@types/webpack": "^5.28.0",
"@types/webpack-env": "^1.18.0",
"@types/xml2js": "~0.4.4",
"@typescript-eslint/eslint-plugin": "^4.26.0",
"@typescript-eslint/parser": "^4.26.0",
@@ -99,6 +100,7 @@
"gulp-typescript": "^5.0.1",
"husky": "~4.3.8",
"lint-staged": "~10.2.2",
"mini-css-extract-plugin": "^2.6.1",
"mocha": "^10.0.0",
"mocha-sinon": "~2.1.2",
"npm-run-all": "^4.1.5",
@@ -106,7 +108,6 @@
"proxyquire": "~2.1.3",
"sinon": "~13.0.1",
"sinon-chai": "~3.5.0",
"style-loader": "~3.3.1",
"through2": "^4.0.2",
"ts-loader": "^8.1.0",
"ts-node": "^10.7.0",
@@ -1880,6 +1881,12 @@
"webpack": "^5"
}
},
"node_modules/@types/webpack-env": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.0.tgz",
"integrity": "sha512-56/MAlX5WMsPVbOg7tAxnYvNYMMWr/QJiIp6BxVSW3JJXUVzzOn64qW8TzQyMSqSUFM2+PVI4aUHcHOzIz/1tg==",
"dev": true
},
"node_modules/@types/webpack/node_modules/tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
@@ -2478,6 +2485,45 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/ajv-formats": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
"dev": true,
"dependencies": {
"ajv": "^8.0.0"
},
"peerDependencies": {
"ajv": "^8.0.0"
},
"peerDependenciesMeta": {
"ajv": {
"optional": true
}
}
},
"node_modules/ajv-formats/node_modules/ajv": {
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
"dev": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/ajv-formats/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
},
"node_modules/ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
@@ -9191,6 +9237,78 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/mini-css-extract-plugin": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz",
"integrity": "sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg==",
"dev": true,
"dependencies": {
"schema-utils": "^4.0.0"
},
"engines": {
"node": ">= 12.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"webpack": "^5.0.0"
}
},
"node_modules/mini-css-extract-plugin/node_modules/ajv": {
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
"dev": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
"dev": true,
"dependencies": {
"fast-deep-equal": "^3.1.3"
},
"peerDependencies": {
"ajv": "^8.8.2"
}
},
"node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
},
"node_modules/mini-css-extract-plugin/node_modules/schema-utils": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz",
"integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
"ajv": "^8.8.0",
"ajv-formats": "^2.1.1",
"ajv-keywords": "^5.0.0"
},
"engines": {
"node": ">= 12.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
}
},
"node_modules/minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -11314,6 +11432,15 @@
"node": ">=0.10.0"
}
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/require-main-filename": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
@@ -12327,22 +12454,6 @@
"node": ">=8"
}
},
"node_modules/style-loader": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz",
"integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==",
"dev": true,
"engines": {
"node": ">= 12.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"webpack": "^5.0.0"
}
},
"node_modules/styled-components": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.3.tgz",
@@ -16142,6 +16253,12 @@
}
}
},
"@types/webpack-env": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.0.tgz",
"integrity": "sha512-56/MAlX5WMsPVbOg7tAxnYvNYMMWr/QJiIp6BxVSW3JJXUVzzOn64qW8TzQyMSqSUFM2+PVI4aUHcHOzIz/1tg==",
"dev": true
},
"@types/xml2js": {
"version": "0.4.5",
"resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.5.tgz",
@@ -16589,6 +16706,35 @@
"uri-js": "^4.2.2"
}
},
"ajv-formats": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
"dev": true,
"requires": {
"ajv": "^8.0.0"
},
"dependencies": {
"ajv": {
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
}
},
"json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
}
}
},
"ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
@@ -21980,6 +22126,56 @@
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
"dev": true
},
"mini-css-extract-plugin": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz",
"integrity": "sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg==",
"dev": true,
"requires": {
"schema-utils": "^4.0.0"
},
"dependencies": {
"ajv": {
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
}
},
"ajv-keywords": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.3"
}
},
"json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
},
"schema-utils": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz",
"integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.9",
"ajv": "^8.8.0",
"ajv-formats": "^2.1.1",
"ajv-keywords": "^5.0.0"
}
}
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -23626,6 +23822,12 @@
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
"dev": true
},
"require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true
},
"require-main-filename": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
@@ -24439,13 +24641,6 @@
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
},
"style-loader": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz",
"integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==",
"dev": true,
"requires": {}
},
"styled-components": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.3.tgz",

View File

@@ -1188,7 +1188,6 @@
"watch": "npm-run-all -p watch:*",
"watch:extension": "tsc --watch",
"watch:webpack": "gulp watchView",
"watch:css": "gulp watchCss",
"test": "mocha --exit -r ts-node/register test/pure-tests/**/*.ts",
"preintegration": "rm -rf ./out/vscode-tests && gulp",
"integration": "node ./out/vscode-tests/run-integration-tests.js no-workspace,minimal-workspace",
@@ -1199,8 +1198,8 @@
"format-staged": "lint-staged"
},
"dependencies": {
"@octokit/rest": "^18.5.6",
"@octokit/plugin-retry": "^3.0.9",
"@octokit/rest": "^18.5.6",
"@primer/octicons-react": "^16.3.0",
"@primer/react": "^35.0.0",
"@vscode/codicons": "^0.0.31",
@@ -1271,6 +1270,7 @@
"@types/unzipper": "~0.10.1",
"@types/vscode": "^1.59.0",
"@types/webpack": "^5.28.0",
"@types/webpack-env": "^1.18.0",
"@types/xml2js": "~0.4.4",
"@typescript-eslint/eslint-plugin": "^4.26.0",
"@typescript-eslint/parser": "^4.26.0",
@@ -1289,6 +1289,7 @@
"gulp-typescript": "^5.0.1",
"husky": "~4.3.8",
"lint-staged": "~10.2.2",
"mini-css-extract-plugin": "^2.6.1",
"mocha": "^10.0.0",
"mocha-sinon": "~2.1.2",
"npm-run-all": "^4.1.5",
@@ -1296,7 +1297,6 @@
"proxyquire": "~2.1.3",
"sinon": "~13.0.1",
"sinon-chai": "~3.5.0",
"style-loader": "~3.3.1",
"through2": "^4.0.2",
"ts-loader": "^8.1.0",
"ts-node": "^10.7.0",

View File

@@ -129,19 +129,10 @@ export class CompareInterfaceManager extends DisposableObject {
ctx.subscriptions
));
const scriptPathOnDisk = Uri.file(
ctx.asAbsolutePath('out/compareView.js')
);
const stylesheetPathOnDisk = Uri.file(
ctx.asAbsolutePath('out/view/resultsView.css')
);
panel.webview.html = getHtmlForWebview(
ctx,
panel.webview,
scriptPathOnDisk,
[stylesheetPathOnDisk],
false
'compare'
);
this.push(panel.webview.onDidReceiveMessage(
async (e) => this.handleMsgFromView(e),

View File

@@ -1,13 +0,0 @@
module.exports = {
env: {
browser: true
},
extends: [
"plugin:react/recommended"
],
settings: {
react: {
version: 'detect'
}
}
}

View File

@@ -1,18 +0,0 @@
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "node",
"target": "es6",
"outDir": "out",
"lib": ["ES2021", "dom"],
"jsx": "react",
"sourceMap": true,
"rootDir": "..",
"strict": true,
"noUnusedLocals": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"experimentalDecorators": true
},
"exclude": ["node_modules"]
}

View File

@@ -4,6 +4,7 @@ import {
Uri,
Location,
Range,
ExtensionContext,
WebviewPanel,
Webview,
workspace,
@@ -116,11 +117,38 @@ export function tryResolveLocation(
* Uses a content security policy that only loads the given script.
*/
export function getHtmlForWebview(
ctx: ExtensionContext,
webview: Webview,
scriptUriOnDisk: Uri,
stylesheetUrisOnDisk: Uri[],
allowInlineStyles: boolean
view: 'results' | 'compare' | 'remote-queries',
{
allowInlineStyles,
includeCodicons
}: {
allowInlineStyles?: boolean;
includeCodicons?: boolean;
} = {
allowInlineStyles: false,
includeCodicons: false
}
): string {
const scriptUriOnDisk = Uri.file(
ctx.asAbsolutePath('out/webview.js')
);
const stylesheetUrisOnDisk = [
Uri.file(ctx.asAbsolutePath('out/webview.css'))
];
if (includeCodicons) {
// Allows use of the VS Code "codicons" icon set.
// See https://github.com/microsoft/vscode-codicons
const codiconsPathOnDisk = Uri.file(
ctx.asAbsolutePath('node_modules/@vscode/codicons/dist/codicon.css')
);
stylesheetUrisOnDisk.push(codiconsPathOnDisk);
}
// Convert the on-disk URIs into webview URIs.
const scriptWebviewUri = webview.asWebviewUri(scriptUriOnDisk);
const stylesheetWebviewUris = stylesheetUrisOnDisk.map(stylesheetUriOnDisk =>
@@ -155,7 +183,7 @@ export function getHtmlForWebview(
${stylesheetsHtmlLines.join(` ${os.EOL}`)}
</head>
<body>
<div id=root>
<div id=root data-view="${view}">
</div>
<script nonce="${nonce}" src="${scriptWebviewUri}">
</script>

View File

@@ -213,17 +213,10 @@ export class InterfaceManager extends DisposableObject {
null,
ctx.subscriptions
));
const scriptPathOnDisk = vscode.Uri.file(
ctx.asAbsolutePath('out/resultsView.js')
);
const stylesheetPathOnDisk = vscode.Uri.file(
ctx.asAbsolutePath('out/view/resultsView.css')
);
panel.webview.html = getHtmlForWebview(
ctx,
panel.webview,
scriptPathOnDisk,
[stylesheetPathOnDisk],
false
'results'
);
this.push(panel.webview.onDidReceiveMessage(
async (e) => this.handleMsgFromView(e),

View File

@@ -131,29 +131,14 @@ export class RemoteQueriesInterfaceManager {
ctx.subscriptions
);
const scriptPathOnDisk = Uri.file(
ctx.asAbsolutePath('out/remoteQueriesView.js')
);
const baseStylesheetUriOnDisk = Uri.file(
ctx.asAbsolutePath('out/remote-queries/view/baseStyles.css')
);
const stylesheetPathOnDisk = Uri.file(
ctx.asAbsolutePath('out/remote-queries/view/remoteQueries.css')
);
// Allows use of the VS Code "codicons" icon set.
// See https://github.com/microsoft/vscode-codicons
const codiconsPathOnDisk = Uri.file(
ctx.asAbsolutePath('node_modules/@vscode/codicons/dist/codicon.css')
);
panel.webview.html = getHtmlForWebview(
ctx,
panel.webview,
scriptPathOnDisk,
[baseStylesheetUriOnDisk, stylesheetPathOnDisk, codiconsPathOnDisk],
true
'remote-queries',
{
includeCodicons: true,
allowInlineStyles: true,
}
);
ctx.subscriptions.push(
panel.webview.onDidReceiveMessage(

View File

@@ -1,13 +0,0 @@
module.exports = {
env: {
browser: true
},
extends: [
"plugin:react/recommended"
],
settings: {
react: {
version: 'detect'
}
}
}

View File

@@ -1,18 +0,0 @@
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "node",
"target": "es6",
"outDir": "out",
"lib": ["ES2021", "dom"],
"jsx": "react",
"sourceMap": true,
"rootDir": "..",
"strict": true,
"noUnusedLocals": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"experimentalDecorators": true
},
"exclude": ["node_modules"]
}

View File

@@ -1,15 +1,16 @@
import * as React from 'react';
import { useState, useEffect } from 'react';
import * as Rdom from 'react-dom';
import {
ToCompareViewMessage,
SetComparisonsMessage,
} from '../../pure/interface-types';
import CompareSelector from './CompareSelector';
import { vscode } from '../../view/vscode-api';
import { vscode } from '../vscode-api';
import CompareTable from './CompareTable';
import '../results/resultsView.css';
const emptyComparison: SetComparisonsMessage = {
t: 'setComparisons',
stats: {},
@@ -75,10 +76,3 @@ export function Compare(_: Record<string, never>): JSX.Element {
return <div>Error!</div>;
}
}
Rdom.render(
<Compare />,
document.getElementById('root'),
// Post a message to the extension when fully loaded.
() => vscode.postMessage({ t: 'compareViewLoaded' })
);

View File

@@ -1,11 +1,11 @@
import * as React from 'react';
import { SetComparisonsMessage } from '../../pure/interface-types';
import RawTableHeader from '../../view/RawTableHeader';
import { className } from '../../view/result-table-utils';
import RawTableHeader from '../results/RawTableHeader';
import { className } from '../results/result-table-utils';
import { ResultRow } from '../../pure/bqrs-cli-types';
import RawTableRow from '../../view/RawTableRow';
import { vscode } from '../../view/vscode-api';
import RawTableRow from '../results/RawTableRow';
import { vscode } from '../vscode-api';
interface Props {
comparison: SetComparisonsMessage;

View File

@@ -0,0 +1,10 @@
import * as React from 'react';
import { WebviewDefinition } from '../webview-interface';
import { Compare } from './Compare';
const definition: WebviewDefinition = {
component: <Compare />,
loadedMessage: 'compareViewLoaded'
};
export default definition;

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import { AnalysisAlert } from '../shared/analysis-result';
import { AnalysisAlert } from '../../remote-queries/shared/analysis-result';
import CodePaths from './CodePaths';
import FileCodeSnippet from './FileCodeSnippet';

View File

@@ -4,7 +4,7 @@ import { VSCodeDropdown, VSCodeLink, VSCodeOption, VSCodeTag } from '@vscode/web
import * as React from 'react';
import { ChangeEvent, useRef, useState } from 'react';
import styled from 'styled-components';
import { CodeFlow, AnalysisMessage, ResultSeverity } from '../shared/analysis-result';
import { CodeFlow, AnalysisMessage, ResultSeverity } from '../../remote-queries/shared/analysis-result';
import FileCodeSnippet from './FileCodeSnippet';
import SectionTitle from './SectionTitle';
import VerticalSpace from './VerticalSpace';

View File

@@ -1,6 +1,6 @@
import * as React from 'react';
import styled from 'styled-components';
import { CodeSnippet, FileLink, HighlightedRegion, AnalysisMessage, ResultSeverity } from '../shared/analysis-result';
import { CodeSnippet, FileLink, HighlightedRegion, AnalysisMessage, ResultSeverity } from '../../remote-queries/shared/analysis-result';
import VerticalSpace from './VerticalSpace';
import { createRemoteFileRef } from '../../pure/location-link-utils';
import { parseHighlightedLine, shouldHighlightLine } from '../../pure/sarif-utils';

View File

@@ -1,18 +1,17 @@
import * as React from 'react';
import { useEffect, useState } from 'react';
import * as Rdom from 'react-dom';
import { Flash, ThemeProvider } from '@primer/react';
import { ToRemoteQueriesMessage } from '../../pure/interface-types';
import { AnalysisSummary, RemoteQueryResult } from '../shared/remote-query-result';
import { MAX_RAW_RESULTS } from '../shared/result-limits';
import { vscode } from '../../view/vscode-api';
import { AnalysisSummary, RemoteQueryResult } from '../../remote-queries/shared/remote-query-result';
import { MAX_RAW_RESULTS } from '../../remote-queries/shared/result-limits';
import { vscode } from '../vscode-api';
import { VSCodeBadge, VSCodeButton } from '@vscode/webview-ui-toolkit/react';
import SectionTitle from './SectionTitle';
import VerticalSpace from './VerticalSpace';
import HorizontalSpace from './HorizontalSpace';
import ViewTitle from './ViewTitle';
import DownloadButton from './DownloadButton';
import { AnalysisResults, getAnalysisResultCount } from '../shared/analysis-result';
import { AnalysisResults, getAnalysisResultCount } from '../../remote-queries/shared/analysis-result';
import DownloadSpinner from './DownloadSpinner';
import CollapsibleItem from './CollapsibleItem';
import { AlertIcon, CodeSquareIcon, FileCodeIcon, RepoIcon, TerminalIcon } from '@primer/octicons-react';
@@ -24,6 +23,9 @@ import SortRepoFilter, { Sort, sorter } from './SortRepoFilter';
import LastUpdated from './LastUpdated';
import RepoListCopyButton from './RepoListCopyButton';
import './baseStyles.css';
import './remoteQueries.css';
const numOfReposInContractedMode = 10;
const emptyQueryResult: RemoteQueryResult = {
@@ -440,10 +442,3 @@ export function RemoteQueries(): JSX.Element {
return <div>There was an error displaying the view.</div>;
}
}
Rdom.render(
<RemoteQueries />,
document.getElementById('root'),
// Post a message to the extension when fully loaded.
() => vscode.postMessage({ t: 'remoteQueryLoaded' })
);

View File

@@ -1,6 +1,6 @@
import * as React from 'react';
import { vscode } from '../../view/vscode-api';
import { RemoteQueryResult } from '../shared/remote-query-result';
import { vscode } from '../vscode-api';
import { RemoteQueryResult } from '../../remote-queries/shared/remote-query-result';
import { CopyIcon } from '@primer/octicons-react';
import { IconButton } from '@primer/react';

View File

@@ -0,0 +1,10 @@
import * as React from 'react';
import { WebviewDefinition } from '../webview-interface';
import { RemoteQueries } from './RemoteQueries';
const definition: WebviewDefinition = {
component: <RemoteQueries />,
loadedMessage: 'remoteQueryLoaded'
};
export default definition;

View File

@@ -1,9 +1,9 @@
import * as React from 'react';
import { vscode } from './vscode-api';
import { RawResultsSortState, SortDirection } from '../pure/interface-types';
import { vscode } from '../vscode-api';
import { RawResultsSortState, SortDirection } from '../../pure/interface-types';
import { nextSortDirection } from './result-table-utils';
import { Column } from '../pure/bqrs-cli-types';
import { Column } from '../../pure/bqrs-cli-types';
interface Props {
readonly columns: readonly Column[];

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import { ResultRow } from '../pure/bqrs-cli-types';
import { ResultRow } from '../../pure/bqrs-cli-types';
import { zebraStripe } from './result-table-utils';
import RawTableValue from './RawTableValue';

View File

@@ -1,7 +1,7 @@
import * as React from 'react';
import { renderLocation } from './result-table-utils';
import { CellValue } from '../pure/bqrs-cli-types';
import { CellValue } from '../../pure/bqrs-cli-types';
interface Props {
value: CellValue;

View File

@@ -1,19 +1,19 @@
import * as path from 'path';
import * as React from 'react';
import * as Sarif from 'sarif';
import * as Keys from '../pure/result-keys';
import * as Keys from '../../pure/result-keys';
import * as octicons from './octicons';
import { className, renderLocation, ResultTableProps, zebraStripe, selectableZebraStripe, jumpToLocation, nextSortDirection, emptyQueryResultsMessage } from './result-table-utils';
import { onNavigation, NavigationEvent } from './results';
import { InterpretedResultSet, SarifInterpretationData } from '../pure/interface-types';
import { InterpretedResultSet, SarifInterpretationData } from '../../pure/interface-types';
import {
parseSarifPlainTextMessage,
parseSarifLocation,
isNoLocation
} from '../pure/sarif-utils';
import { InterpretedResultsSortColumn, SortDirection, InterpretedResultsSortState } from '../pure/interface-types';
import { vscode } from './vscode-api';
import { isWholeFileLoc, isLineColumnLoc } from '../pure/bqrs-utils';
} from '../../pure/sarif-utils';
import { InterpretedResultsSortColumn, SortDirection, InterpretedResultsSortState } from '../../pure/interface-types';
import { vscode } from '../vscode-api';
import { isWholeFileLoc, isLineColumnLoc } from '../../pure/bqrs-utils';
export type PathTableProps = ResultTableProps & { resultSet: InterpretedResultSet<SarifInterpretationData> };
export interface PathTableState {

View File

@@ -1,10 +1,10 @@
import * as React from 'react';
import * as d3 from 'd3';
import { ResultTableProps } from './result-table-utils';
import { InterpretedResultSet, GraphInterpretationData } from '../pure/interface-types';
import { InterpretedResultSet, GraphInterpretationData } from '../../pure/interface-types';
import { graphviz } from 'd3-graphviz';
import { jumpToLocation } from './result-table-utils';
import { tryGetLocationFromString } from '../pure/bqrs-utils';
import { tryGetLocationFromString } from '../../pure/bqrs-utils';
export type GraphProps = ResultTableProps & { resultSet: InterpretedResultSet<GraphInterpretationData> };
const graphClassName = 'vscode-codeql__result-tables-graph';

View File

@@ -0,0 +1,10 @@
import * as React from 'react';
import { WebviewDefinition } from '../webview-interface';
import { ResultsApp } from './results';
const definition: WebviewDefinition = {
component: <ResultsApp />,
loadedMessage: 'resultViewLoaded'
};
export default definition;

View File

@@ -1,10 +1,10 @@
import * as React from 'react';
import { ResultTableProps, className, emptyQueryResultsMessage } from './result-table-utils';
import { RAW_RESULTS_LIMIT, RawResultsSortState } from '../pure/interface-types';
import { RawTableResultSet } from '../pure/interface-types';
import { RAW_RESULTS_LIMIT, RawResultsSortState } from '../../pure/interface-types';
import { RawTableResultSet } from '../../pure/interface-types';
import RawTableHeader from './RawTableHeader';
import RawTableRow from './RawTableRow';
import { ResultRow } from '../pure/bqrs-cli-types';
import { ResultRow } from '../../pure/bqrs-cli-types';
export type RawTableProps = ResultTableProps & {
resultSet: RawTableResultSet;

View File

@@ -1,11 +1,11 @@
import * as React from 'react';
import { UrlValue, ResolvableLocationValue } from '../pure/bqrs-cli-types';
import { isStringLoc, tryGetResolvableLocation } from '../pure/bqrs-utils';
import { RawResultsSortState, QueryMetadata, SortDirection } from '../pure/interface-types';
import { assertNever } from '../pure/helpers-pure';
import { ResultSet } from '../pure/interface-types';
import { vscode } from './vscode-api';
import { convertNonPrintableChars } from '../text-utils';
import { UrlValue, ResolvableLocationValue } from '../../pure/bqrs-cli-types';
import { isStringLoc, tryGetResolvableLocation } from '../../pure/bqrs-utils';
import { RawResultsSortState, QueryMetadata, SortDirection } from '../../pure/interface-types';
import { assertNever } from '../../pure/helpers-pure';
import { ResultSet } from '../../pure/interface-types';
import { vscode } from '../vscode-api';
import { convertNonPrintableChars } from '../../text-utils';
export interface ResultTableProps {
resultSet: ResultSet;

View File

@@ -13,7 +13,7 @@ import {
getDefaultResultSetName,
ParsedResultSets,
IntoResultsViewMsg,
} from '../pure/interface-types';
} from '../../pure/interface-types';
import { PathTable } from './alert-table';
import { Graph } from './graph';
import { RawTable } from './raw-results-table';
@@ -25,7 +25,7 @@ import {
alertExtrasClassName,
openFile
} from './result-table-utils';
import { vscode } from './vscode-api';
import { vscode } from '../vscode-api';
const FILE_PATH_REGEX = /^(?:.+[\\/])*(.+)$/;

View File

@@ -1,6 +1,5 @@
import * as React from 'react';
import * as Rdom from 'react-dom';
import { assertNever } from '../pure/helpers-pure';
import { assertNever } from '../../pure/helpers-pure';
import {
DatabaseInfo,
Interpretation,
@@ -13,11 +12,12 @@ import {
ALERTS_TABLE_NAME,
GRAPH_TABLE_NAME,
ParsedResultSets,
} from '../pure/interface-types';
} from '../../pure/interface-types';
import { EventHandlers as EventHandlerList } from './event-handler-list';
import { ResultTables } from './result-tables';
import { ResultSet } from '../pure/interface-types';
import { vscode } from './vscode-api';
import { ResultSet } from '../../pure/interface-types';
import './resultsView.css';
/**
* results.tsx
@@ -72,7 +72,7 @@ export const onNavigation = new EventHandlerList<NavigationEvent>();
/**
* A minimal state container for displaying results.
*/
class App extends React.Component<Record<string, never>, ResultsViewState> {
export class ResultsApp extends React.Component<Record<string, never>, ResultsViewState> {
constructor(props: any) {
super(props);
this.state = {
@@ -302,7 +302,6 @@ class App extends React.Component<Record<string, never>, ResultsViewState> {
componentDidMount(): void {
this.vscodeMessageHandler = this.vscodeMessageHandler.bind(this);
window.addEventListener('message', this.vscodeMessageHandler);
vscode.postMessage({ t: 'resultViewLoaded' });
}
componentWillUnmount(): void {
@@ -319,5 +318,3 @@ class App extends React.Component<Record<string, never>, ResultsViewState> {
: console.error(`Invalid event origin ${origin}`);
}
}
Rdom.render(<App />, document.getElementById('root'));

View File

@@ -0,0 +1,4 @@
export type WebviewDefinition = {
component: JSX.Element,
loadedMessage: 'compareViewLoaded' | 'remoteQueryLoaded' | 'resultViewLoaded';
}

View File

@@ -0,0 +1,33 @@
import * as ReactDOM from 'react-dom';
import { vscode } from './vscode-api';
import { WebviewDefinition } from './webview-interface';
const render = () => {
const element = document.getElementById('root');
if (!element) {
console.error('Could not find element with id "root"');
return;
}
const viewName = element.dataset.view;
if (!viewName) {
console.error('Could not find view name in data-view attribute');
return;
}
// It's a lot harder to use dynamic imports since those don't import the CSS
// and require a less strict CSP policy
// eslint-disable-next-line @typescript-eslint/no-var-requires
const view: WebviewDefinition = require(`./${viewName}/index.tsx`).default;
ReactDOM.render(
view.component,
document.getElementById('root'),
// Post a message to the extension when fully loaded.
() => vscode.postMessage({ t: view.loadedMessage })
);
};
render();

6
package-lock.json generated Normal file
View File

@@ -0,0 +1,6 @@
{
"name": "vscode-codeql",
"lockfileVersion": 2,
"requires": true,
"packages": {}
}