22// Licensed under the MIT license.
33
44import { Disposable , ExtensionContext , ViewColumn , WebviewPanel , window } from "vscode" ;
5+ import { leetCodeChannel } from "../leetCodeChannel" ;
6+ import { MarkdownEngine } from "./MarkdownEngine" ;
57
68class LeetCodeResultProvider implements Disposable {
79
810 private context : ExtensionContext ;
911 private panel : WebviewPanel | undefined ;
12+ private mdEngine : MarkdownEngine ;
1013
1114 public initialize ( context : ExtensionContext ) : void {
15+ this . mdEngine = new MarkdownEngine ( ) ;
1216 this . context = context ;
1317 }
1418
15- public async show ( result : string ) : Promise < void > {
19+ public async show ( resultString : string ) : Promise < void > {
1620 if ( ! this . panel ) {
1721 this . panel = window . createWebviewPanel ( "leetcode.result" , "LeetCode Results" , ViewColumn . Two , {
1822 retainContextWhenHidden : true ,
1923 enableFindWidget : true ,
24+ localResourceRoots : this . mdEngine . localResourceRoots ,
2025 } ) ;
2126
2227 this . panel . onDidDispose ( ( ) => {
2328 this . panel = undefined ;
2429 } , null , this . context . subscriptions ) ;
2530 }
2631
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 ) ;
2835 this . panel . reveal ( ViewColumn . Two ) ;
2936 }
3037
@@ -34,19 +41,98 @@ class LeetCodeResultProvider implements Disposable {
3441 }
3542 }
3643
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>
40107 <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 }
44109 </head>
45- <body>
46- <pre> ${ result . trim ( ) } </pre>
110+ <body class="vscode-body 'scrollBeyondLastLine' 'wordWrap' 'showEditorSelection'" style="tab-size:4" >
111+ ${ body }
47112 </body>
48- </html>` ;
113+ </html>
114+ ` ;
49115 }
50116}
51117
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+
52138export const leetCodeResultProvider : LeetCodeResultProvider = new LeetCodeResultProvider ( ) ;
0 commit comments