1
1
// Copyright (c) jdneo. All rights reserved.
2
2
// Licensed under the MIT license.
3
3
4
+ import * as _ from "lodash" ;
4
5
import { Disposable , ExtensionContext , ViewColumn , WebviewPanel , window } from "vscode" ;
6
+ import { markdownEngine } from "./markdownEngine" ;
5
7
6
8
class LeetCodeResultProvider implements Disposable {
7
9
@@ -12,19 +14,21 @@ class LeetCodeResultProvider implements Disposable {
12
14
this . context = context ;
13
15
}
14
16
15
- public async show ( result : string ) : Promise < void > {
17
+ public async show ( resultString : string ) : Promise < void > {
16
18
if ( ! this . panel ) {
17
- this . panel = window . createWebviewPanel ( "leetcode.result" , "LeetCode Results " , ViewColumn . Two , {
19
+ this . panel = window . createWebviewPanel ( "leetcode.result" , "Submission Result " , ViewColumn . Two , {
18
20
retainContextWhenHidden : true ,
19
21
enableFindWidget : true ,
22
+ localResourceRoots : markdownEngine . localResourceRoots ,
20
23
} ) ;
21
24
22
25
this . panel . onDidDispose ( ( ) => {
23
26
this . panel = undefined ;
24
27
} , null , this . context . subscriptions ) ;
25
28
}
26
29
27
- this . panel . webview . html = await this . provideHtmlContent ( result ) ;
30
+ const result : IResult = this . parseResult ( resultString ) ;
31
+ this . panel . webview . html = this . getWebViewContent ( result ) ;
28
32
this . panel . reveal ( ViewColumn . Two ) ;
29
33
}
30
34
@@ -34,19 +38,67 @@ class LeetCodeResultProvider implements Disposable {
34
38
}
35
39
}
36
40
37
- private async provideHtmlContent ( result : string ) : Promise < string > {
38
- return `<!DOCTYPE html>
39
- <html lang="en">
41
+ private parseResult ( raw : string ) : IResult {
42
+ raw = raw . concat ( " √ " ) ; // Append a dummy sentinel to the end of raw string
43
+ const regSplit : RegExp = / [ √ × ✔ ✘ v x ] ( [ ^ ] + ?) \n (? = [ √ × ✔ ✘ v x ] ) / g;
44
+ const regKeyVal : RegExp = / ( .+ ?) : ( [ ^ ] * ) / ;
45
+ const result : IResult = { messages : [ ] } ;
46
+ let entry : RegExpExecArray | null ;
47
+ do {
48
+ entry = regSplit . exec ( raw ) ;
49
+ if ( ! entry ) {
50
+ continue ;
51
+ }
52
+ const kvMatch : RegExpExecArray | null = regKeyVal . exec ( entry [ 1 ] ) ;
53
+ if ( kvMatch ) {
54
+ const key : string = _ . startCase ( kvMatch [ 1 ] ) ;
55
+ let value : string = kvMatch [ 2 ] ;
56
+ if ( ! result [ key ] ) {
57
+ result [ key ] = [ ] ;
58
+ }
59
+ if ( key === "Testcase" ) {
60
+ value = value . slice ( 1 , - 1 ) . replace ( "\\n" , "\n" ) ;
61
+ }
62
+ result [ key ] . push ( value ) ;
63
+ } else {
64
+ result . messages . push ( entry [ 1 ] ) ;
65
+ }
66
+ } while ( entry ) ;
67
+ return result ;
68
+ }
69
+
70
+ private getWebViewContent ( result : IResult ) : string {
71
+ const styles : string = markdownEngine . getStylesHTML ( ) ;
72
+ const title : string = `## ${ result . messages [ 0 ] } ` ;
73
+ const messages : string [ ] = result . messages . slice ( 1 ) . map ( ( m : string ) => `* ${ m } ` ) ;
74
+ const sections : string [ ] = Object . keys ( result ) . filter ( ( k : string ) => k !== "messages" ) . map ( ( key : string ) => [
75
+ `### ${ key } ` ,
76
+ "```" ,
77
+ result [ key ] . join ( "\n\n" ) ,
78
+ "```" ,
79
+ ] . join ( "\n" ) ) ;
80
+ const body : string = markdownEngine . render ( [
81
+ title ,
82
+ ...messages ,
83
+ ...sections ,
84
+ ] . join ( "\n" ) ) ;
85
+ return `
86
+ <!DOCTYPE html>
87
+ <html>
40
88
<head>
41
- <meta charset="UTF-8">
42
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
43
- <title>LeetCode Results</title>
89
+ ${ styles }
44
90
</head>
45
- <body>
46
- <pre> ${ result . trim ( ) } </pre>
91
+ <body class="vscode-body 'scrollBeyondLastLine' 'wordWrap' 'showEditorSelection'" style="tab-size:4" >
92
+ ${ body }
47
93
</body>
48
- </html>` ;
94
+ </html>
95
+ ` ;
49
96
}
50
97
}
51
98
99
+ interface IResult {
100
+ [ key : string ] : string [ ] ;
101
+ messages : string [ ] ;
102
+ }
103
+
52
104
export const leetCodeResultProvider : LeetCodeResultProvider = new LeetCodeResultProvider ( ) ;
0 commit comments