11// Copyright (c) jdneo. All rights reserved.
22// Licensed under the MIT license.
33
4+ import * as _ from "lodash" ;
45import { Disposable , ExtensionContext , ViewColumn , WebviewPanel , window } from "vscode" ;
6+ import { markdownEngine } from "./markdownEngine" ;
57
68class LeetCodeResultProvider implements Disposable {
79
@@ -12,19 +14,21 @@ class LeetCodeResultProvider implements Disposable {
1214 this . context = context ;
1315 }
1416
15- public async show ( result : string ) : Promise < void > {
17+ public async show ( resultString : string ) : Promise < void > {
1618 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 , {
1820 retainContextWhenHidden : true ,
1921 enableFindWidget : true ,
22+ localResourceRoots : markdownEngine . localResourceRoots ,
2023 } ) ;
2124
2225 this . panel . onDidDispose ( ( ) => {
2326 this . panel = undefined ;
2427 } , null , this . context . subscriptions ) ;
2528 }
2629
27- this . panel . webview . html = await this . provideHtmlContent ( result ) ;
30+ const result : IResult = this . parseResult ( resultString ) ;
31+ this . panel . webview . html = this . getWebViewContent ( result ) ;
2832 this . panel . reveal ( ViewColumn . Two ) ;
2933 }
3034
@@ -34,19 +38,67 @@ class LeetCodeResultProvider implements Disposable {
3438 }
3539 }
3640
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>
4088 <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 }
4490 </head>
45- <body>
46- <pre> ${ result . trim ( ) } </pre>
91+ <body class="vscode-body 'scrollBeyondLastLine' 'wordWrap' 'showEditorSelection'" style="tab-size:4" >
92+ ${ body }
4793 </body>
48- </html>` ;
94+ </html>
95+ ` ;
4996 }
5097}
5198
99+ interface IResult {
100+ [ key : string ] : string [ ] ;
101+ messages : string [ ] ;
102+ }
103+
52104export const leetCodeResultProvider : LeetCodeResultProvider = new LeetCodeResultProvider ( ) ;
0 commit comments