Skip to content

Commit 229c6b8

Browse files
committedSep 21, 2019
parse webview from jsdom
·
v0.19.40.2.0
1 parent e7b084d commit 229c6b8

File tree

7 files changed

+4903
-5691
lines changed

7 files changed

+4903
-5691
lines changed
 

‎.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
node_modules
22
.vscode-test/
33
*.vsix
4+
.DS_Store
45

56
# local
67
.env

‎package-lock.json

Lines changed: 0 additions & 1945 deletions
This file was deleted.

‎package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"dependencies": {
3333
"@types/mocha": "^5.2.7",
3434
"dotenv": "^8.1.0",
35+
"jsdom": "^15.1.1",
3536
"vscode": "^1.1.36",
3637
"xstate": "^4.6.7"
3738
},
@@ -40,6 +41,7 @@
4041
"@types/dotenv": "^6.1.1",
4142
"@types/glob": "^7.1.1",
4243
"@types/graphql": "^14.5.0",
44+
"@types/jsdom": "^12.2.4",
4345
"@types/node": "^12.7.5",
4446
"assert": "^2.0.0",
4547
"concurrently": "^4.1.2",

‎src/editor/ReactWebView.ts

Lines changed: 61 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import {Action} from 'typings'
22
import * as path from 'path'
33
import * as vscode from 'vscode'
4-
import Channel from '../Channel'
4+
import {JSDOM} from 'jsdom'
5+
import Channel from '../channel'
56

67
const getNonce = (): string => {
78
let text = ''
@@ -30,13 +31,14 @@ class ReactWebView {
3031
private channel: Channel
3132

3233
public constructor({extensionPath, workspaceState}: ReactWebViewProps) {
34+
console.log(`extPath ${extensionPath}`)
3335
this.extensionPath = extensionPath
3436

3537
// Create and show a new webview panel
3638
this.panel = this.createWebviewPanel(vscode.ViewColumn.Two)
3739

3840
// Set the webview initial html content
39-
this.panel.webview.html = this.getHtmlForWebview()
41+
this.getHtmlForWebview()
4042

4143
// Listen for when the panel is disposed
4244
// This happens when the user closes the panel or when the panel is closed programmatically
@@ -65,15 +67,15 @@ class ReactWebView {
6567

6668
// prevents new panels from going on top of coderoad panel
6769
vscode.window.onDidChangeActiveTextEditor((textEditor?: vscode.TextEditor) => {
68-
console.log('onDidChangeActiveTextEditor')
69-
console.log(textEditor)
70+
// console.log('onDidChangeActiveTextEditor')
71+
// console.log(textEditor)
7072
if (!textEditor || textEditor.viewColumn !== vscode.ViewColumn.Two) {
7173
updateWindows()
7274
}
7375
})
7476
// // prevents moving coderoad panel on top of left panel
7577
vscode.window.onDidChangeVisibleTextEditors((textEditor: vscode.TextEditor[]) => {
76-
console.log('onDidChangeVisibleTextEditors')
78+
// console.log('onDidChangeVisibleTextEditors')
7779
updateWindows()
7880
})
7981

@@ -97,7 +99,7 @@ class ReactWebView {
9799
Promise.all(this.disposables.map((x) => x.dispose()))
98100
}
99101

100-
private createWebviewPanel(column: number): vscode.WebviewPanel {
102+
private createWebviewPanel = (column: number): vscode.WebviewPanel => {
101103
const viewType = 'CodeRoad'
102104
const title = 'CodeRoad'
103105
const config = {
@@ -111,62 +113,64 @@ class ReactWebView {
111113
return vscode.window.createWebviewPanel(viewType, title, column, config)
112114
}
113115

114-
private getHtmlForWebview(): string {
115-
const buildUri = vscode.Uri.file(path.join(this.extensionPath, 'build')).with({scheme: 'vscode-resource'})
116+
private getHtmlForWebview = async (): Promise<void> => {
117+
118+
const dom = await JSDOM.fromFile('./build/index.html')
119+
120+
const {document} = dom.window
121+
122+
const base: HTMLBaseElement = document.createElement('base')
123+
base.href = vscode.Uri.file(path.join(this.extensionPath, 'build')).with({scheme: 'vscode-resource'}).path
124+
document.head.appendChild(base)
116125

117126
const manifest = require(path.join(this.extensionPath, 'build', 'asset-manifest.json'))
118127

119-
const getSrc = (manifestName: string): any => {
120-
const file = manifest.files[manifestName]
121-
const uriPath = vscode.Uri.file(path.join(this.extensionPath, 'build', file))
122-
return uriPath.with({scheme: 'vscode-resource'})
128+
const nonces: string[] = []
129+
130+
const scripts: HTMLScriptElement[] = Array.from(document.getElementsByTagName('script'))
131+
for (const script of scripts) {
132+
const nonce: string = getNonce()
133+
nonces.push(nonce)
134+
script.nonce = nonce
135+
const uriPath = vscode.Uri.file(path.join(this.extensionPath, 'build', script.src))
136+
uriPath.with({scheme: 'vscode-resource'})
137+
}
138+
139+
// add run-time script from webpack
140+
const runTimeScript = document.createElement('script')
141+
runTimeScript.src = manifest.files['runtime-main.js']
142+
runTimeScript.nonce = getNonce()
143+
nonces.push(runTimeScript.nonce)
144+
vscode.Uri.file(path.join(this.extensionPath, 'build', runTimeScript.src)).with({scheme: 'vscode-resource'})
145+
document.body.appendChild(runTimeScript)
146+
147+
const styles: HTMLLinkElement[] = Array.from(document.getElementsByTagName('link'))
148+
for (const style of styles) {
149+
if (style.href) {
150+
const uriPath = vscode.Uri.file(path.join(this.extensionPath, 'build', style.href))
151+
uriPath.with({scheme: 'vscode-resource'})
152+
}
123153
}
124154

125-
const styles = [
126-
'main.css',
127-
// get style chunk
128-
Object.keys(manifest.files).find(f => f.match(/^static\/css\/.+\.css$/)) || ''
129-
].map(style => getSrc(style))
130-
131-
// map over scripts
132-
const scripts = [{
133-
file: './webpackBuild.js',
134-
}, {
135-
manifest: 'runtime~main.js',
136-
}, {
137-
manifest: 'main.js',
138-
}, {
139-
// get js chunk
140-
manifest: Object.keys(manifest.files).find(f => f.match(/^static\/js\/.+\.js$/)),
141-
}].map(script => ({
142-
nonce: getNonce(),
143-
src: script.manifest ? getSrc(script.manifest) : script.file
144-
}))
145-
146-
const indexHtml = `<!DOCTYPE html>
147-
<html lang='en'>
148-
<head>
149-
<meta charset='utf-8'>
150-
<meta name='viewport' content='width=device-width,initial-scale=1,shrink-to-fit=no'>
151-
<meta name='theme-color' content='#000000'>
152-
<meta http-equiv='Content-Security-Policy' content="font-src vscode-resource://*; img-src vscode-resource: https:; script-src ${scripts.map(script => `'nonce-${script.nonce}'`).join(' ')}; style-src vscode-resource: 'unsafe-inline' http: https: data:;">
153-
<title>React App</title>
154-
155-
<link rel='manifest' href='./manifest.json' />
156-
<link rel='stylesheet' href='https://unpkg.com/@alifd/next/dist/next.css' />
157-
${styles.map(styleUri => `<link rel='stylesheet' type='text/css' href='${styleUri}'>`).join('\n')}
158-
159-
<base href='${buildUri}/'>
160-
</head>
161-
162-
<body>
163-
<noscript>You need to enable JavaScript to run this app.</noscript>
164-
<div id='root' style='background-color:white; padding: 1rem;'>Loading...</div>
165-
${scripts.map(s => `<script nonce='${s.nonce}' src='${s.src}'></script>`).join('\n')}
166-
</body>
167-
</html>`
168-
169-
return indexHtml
155+
156+
// content security policy
157+
const cspMeta: HTMLMetaElement = document.createElement('meta')
158+
cspMeta.httpEquiv = 'Content-Security-Policy'
159+
cspMeta.content = [
160+
`default-src 'none';`,
161+
'font-src vscode-resource://*;',
162+
'img-src vscode-resource: https:;',
163+
`script-src ${nonces.map(nonce => `'nonce-${nonce}'`).join(' ')};`,
164+
`style-src 'unsafe-inline' vscode-resource: http: https: data:;`
165+
].join(' ')
166+
document.head.appendChild(cspMeta)
167+
168+
169+
const html = dom.serialize()
170+
171+
console.log(html)
172+
173+
this.panel.webview.html = html
170174
}
171175

172176
}

‎web-app/package-lock.json

Lines changed: 4837 additions & 3611 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎web-app/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"scripts": {
66
"build": "react-scripts build",
7-
"postbuild": "cp -R ./build/ ../build/ && cp public/webpackBuild.js ../build/webpackBuild.js",
7+
"postbuild": "cp -R ./build/ ../build/",
88
"build-storybook": "build-storybook",
99
"start": "react-scripts start",
1010
"storybook": "start-storybook -p 6006",
@@ -37,7 +37,6 @@
3737
"ramda": "^0.26.1",
3838
"react": "^16.9.0",
3939
"react-dom": "^16.9.0",
40-
"react-scripts": "^3.1.2",
4140
"reselect": "^4.0.0",
4241
"typescript": "^3.6.3",
4342
"xstate": "^4.6.7"
@@ -60,6 +59,7 @@
6059
"babel-loader": "^8.0.6",
6160
"babel-plugin-import": "^1.12.1",
6261
"node-sass": "^4.12.0",
62+
"react-scripts": "3.1.2",
6363
"sass-loader": "^8.0.0",
6464
"typescript-eslint-parser": "^22.0.0"
6565
}

‎web-app/public/webpackBuild.js

Lines changed: 0 additions & 76 deletions
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.