2
2
// Licensed under the MIT license.
3
3
4
4
import { Disposable , ExtensionContext , ViewColumn , WebviewPanel , window } from "vscode" ;
5
+ import { leetCodeChannel } from "../leetCodeChannel" ;
6
+ import { MarkdownEngine } from "./MarkdownEngine" ;
5
7
6
8
class LeetCodeResultProvider implements Disposable {
7
9
8
10
private context : ExtensionContext ;
9
11
private panel : WebviewPanel | undefined ;
12
+ private mdEngine : MarkdownEngine ;
10
13
11
14
public initialize ( context : ExtensionContext ) : void {
15
+ this . mdEngine = new MarkdownEngine ( ) ;
12
16
this . context = context ;
13
17
}
14
18
15
- public async show ( result : string ) : Promise < void > {
19
+ public async show ( resultString : string ) : Promise < void > {
16
20
if ( ! this . panel ) {
17
21
this . panel = window . createWebviewPanel ( "leetcode.result" , "LeetCode Results" , ViewColumn . Two , {
18
22
retainContextWhenHidden : true ,
19
23
enableFindWidget : true ,
24
+ localResourceRoots : this . mdEngine . localResourceRoots ,
20
25
} ) ;
21
26
22
27
this . panel . onDidDispose ( ( ) => {
23
28
this . panel = undefined ;
24
29
} , null , this . context . subscriptions ) ;
25
30
}
26
31
27
- this . panel . webview . html = await this . provideHtmlContent ( result ) ;
32
+ const result : Result = this . parseResult ( resultString ) ;
33
+ this . panel . title = `${ "" } : Result` ;
34
+ this . panel . webview . html = this . getWebViewContent ( result ) ;
28
35
this . panel . reveal ( ViewColumn . Two ) ;
29
36
}
30
37
@@ -34,19 +41,98 @@ class LeetCodeResultProvider implements Disposable {
34
41
}
35
42
}
36
43
37
- private async provideHtmlContent ( result : string ) : Promise < string > {
38
- return `<!DOCTYPE html>
39
- <html lang="en">
44
+ private parseResult ( raw : string ) : Result {
45
+ try {
46
+ switch ( raw [ 2 ] ) {
47
+ case "√" : {
48
+ const result : AcceptResult = new AcceptResult ( ) ;
49
+ [ result . status , raw ] = raw . split ( / . ( .+ ) ( [ ^ ] + ) / ) . slice ( 1 ) ;
50
+ [ result . passed , raw ] = raw . split ( / \n . ( .+ ) ( [ ^ ] + ) / ) . slice ( 1 ) ;
51
+ [ result . runtime , raw ] = raw . split ( / \n . ( .+ ) ( [ ^ ] + ) / ) . slice ( 1 ) ;
52
+ [ result . memory , raw ] = raw . split ( / \n . ( .+ ) / ) . slice ( 1 ) ;
53
+ return result ;
54
+ }
55
+ case "×" : {
56
+ const result : FailedResult = new FailedResult ( ) ;
57
+ [ result . status , raw ] = raw . split ( / . ( .+ ) ( [ ^ ] + ) / ) . slice ( 1 ) ;
58
+ [ result . passed , raw ] = raw . split ( / \n . ( .+ ) ( [ ^ ] + ) / ) . slice ( 1 ) ;
59
+ [ result . testcase , raw ] = raw . split ( / \n . t e s t c a s e : ' ( .+ ) ' ( [ ^ ] + ) / ) . slice ( 1 ) ;
60
+ [ result . answer , raw ] = raw . split ( / \n . a n s w e r : ( .+ ) ( [ ^ ] + ) / ) . slice ( 1 ) ;
61
+ [ result . expected , raw ] = raw . split ( / \n . e x p e c t e d _ a n s w e r : ( .+ ) ( [ ^ ] + ) / ) . slice ( 1 ) ;
62
+ [ result . stdout , raw ] = raw . split ( / \n . s t d o u t : ( [ ^ ] + ?) \n $ / ) . slice ( 1 ) ;
63
+ result . testcase = result . testcase . replace ( "\\n" , "\n" ) ;
64
+ return result ;
65
+ }
66
+ default : {
67
+ throw new TypeError ( raw ) ;
68
+ }
69
+ }
70
+ } catch ( error ) {
71
+ leetCodeChannel . appendLine ( `Result parsing failed: ${ error . message } ` ) ;
72
+ throw error ;
73
+ }
74
+ }
75
+
76
+ private getWebViewContent ( result : Result ) : string {
77
+ const styles : string = this . mdEngine . getStylesHTML ( ) ;
78
+ let body : string ;
79
+ if ( result instanceof AcceptResult ) {
80
+ const accpet : AcceptResult = result as AcceptResult ;
81
+ body = this . mdEngine . render ( [
82
+ `## ${ result . status } ` ,
83
+ `` ,
84
+ `* ${ result . passed } ` ,
85
+ `* ${ accpet . runtime } ` ,
86
+ `* ${ accpet . memory } ` ,
87
+ ] . join ( "\n" ) ) ;
88
+ } else {
89
+ const failed : FailedResult = result as FailedResult ;
90
+ body = this . mdEngine . render ( [
91
+ `## ${ result . status } ` ,
92
+ `* ${ result . passed } ` ,
93
+ `` ,
94
+ `### Testcase` , // TODO: add command to copy raw testcase
95
+ `\`\`\`\n${ failed . testcase } \n\`\`\`` ,
96
+ `### Answer` ,
97
+ `\`\`\`\n${ failed . answer } \n\`\`\`` ,
98
+ `### Expected` ,
99
+ `\`\`\`\n${ failed . expected } \n\`\`\`` ,
100
+ `### Stdout` ,
101
+ `\`\`\`\n${ failed . stdout } \n\`\`\`` ,
102
+ ] . join ( "\n" ) ) ;
103
+ }
104
+ return `
105
+ <!DOCTYPE html>
106
+ <html>
40
107
<head>
41
- <meta charset="UTF-8">
42
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
43
- <title>LeetCode Results</title>
108
+ ${ styles }
44
109
</head>
45
- <body>
46
- <pre> ${ result . trim ( ) } </pre>
110
+ <body class="vscode-body 'scrollBeyondLastLine' 'wordWrap' 'showEditorSelection'" style="tab-size:4" >
111
+ ${ body }
47
112
</body>
48
- </html>` ;
113
+ </html>
114
+ ` ;
49
115
}
50
116
}
51
117
118
+ // tslint:disable-next-line:max-classes-per-file
119
+ abstract class Result {
120
+ public status : string ;
121
+ public passed : string ;
122
+ }
123
+
124
+ // tslint:disable-next-line:max-classes-per-file
125
+ class AcceptResult extends Result {
126
+ public runtime : string ;
127
+ public memory : string ;
128
+ }
129
+
130
+ // tslint:disable-next-line:max-classes-per-file
131
+ class FailedResult extends Result {
132
+ public testcase : string ;
133
+ public answer : string ;
134
+ public expected : string ;
135
+ public stdout : string ;
136
+ }
137
+
52
138
export const leetCodeResultProvider : LeetCodeResultProvider = new LeetCodeResultProvider ( ) ;
0 commit comments