Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Apply markdown engine to result provider #232

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 27, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/webview/leetCodePreviewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class LeetCodePreviewProvider implements Disposable {
}

this.panel.webview.html = await this.provideHtmlContent(node);
this.panel.title = node.name;
this.panel.title = `${node.name}: Preview`;
this.panel.reveal();
}

Expand Down
76 changes: 64 additions & 12 deletions src/webview/leetCodeResultProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT license.

import { Disposable, ExtensionContext, ViewColumn, WebviewPanel, window } from "vscode";
import { markdownEngine } from "./markdownEngine";

class LeetCodeResultProvider implements Disposable {

Expand All @@ -12,19 +13,21 @@ class LeetCodeResultProvider implements Disposable {
this.context = context;
}

public async show(result: string): Promise<void> {
public async show(resultString: string): Promise<void> {
if (!this.panel) {
this.panel = window.createWebviewPanel("leetcode.result", "LeetCode Results", ViewColumn.Two, {
this.panel = window.createWebviewPanel("leetcode.result", "Submission Result", ViewColumn.Two, {
retainContextWhenHidden: true,
enableFindWidget: true,
localResourceRoots: markdownEngine.localResourceRoots,
});

this.panel.onDidDispose(() => {
this.panel = undefined;
}, null, this.context.subscriptions);
}

this.panel.webview.html = await this.provideHtmlContent(result);
const result: IResult = this.parseResult(resultString);
this.panel.webview.html = this.getWebViewContent(result);
this.panel.reveal(ViewColumn.Two);
}

Expand All @@ -34,19 +37,68 @@ class LeetCodeResultProvider implements Disposable {
}
}

private async provideHtmlContent(result: string): Promise<string> {
return `<!DOCTYPE html>
<html lang="en">
private parseResult(raw: string): IResult {
raw = raw.concat(" √ "); // Append a dummy sentinel to the end of raw string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What will happen if we don't append ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RegEx captures anything in between two . If we don't append it, the last section (normally stdout) won't be captured.

Worth to note that, with this trick, messages like [WARN] Failed to get memory percentile will be captured as one part of Your runtime beats 81.3 % of python submissions, and will also be printed out even it does not starts with .

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... still feeling the logic here is too tricky for maintaince.

It's ok to merge for now.

const regSplit: RegExp = / [√×✔✘vx] ([^]+?)\n(?= [√×✔✘vx] )/g;
const regKeyVal: RegExp = /(.+?): ([^]*)/;
const result: IResult = { messages: [] };
let entry: RegExpExecArray | null;
do {
entry = regSplit.exec(raw);
if (!entry) {
continue;
}
const kvMatch: RegExpExecArray | null = regKeyVal.exec(entry[1]);
if (kvMatch) {
const key: string = kvMatch[1].split("_").map((k: string) => `${k[0].toUpperCase()}${k.slice(1)}`).join(" ");
let value: string = kvMatch[2];
if (!result[key]) {
result[key] = [];
}
if (key === "Testcase") {
value = value.slice(1, -1).replace("\\n", "\n");
}
result[key].push(value);
} else {
result.messages.push(entry[1]);
}
} while (entry);
return result;
}

private getWebViewContent(result: IResult): string {
const styles: string = markdownEngine.getStylesHTML();
const title: string = `## ${result.messages[0]}`;
const messages: string[] = result.messages.slice(1).map((m: string) => `* ${m}`);
const sections: string[] = Object.keys(result).filter((k: string) => k !== "messages").map((key: string) => [
`### ${key}`,
"```",
result[key].join("\n\n"),
"```",
].join("\n"));
const body: string = markdownEngine.render([
title,
...messages,
...sections,
].join("\n"));
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LeetCode Results</title>
${styles}
</head>
<body>
<pre>${result.trim()}</pre>
<body class="vscode-body 'scrollBeyondLastLine' 'wordWrap' 'showEditorSelection'" style="tab-size:4">
${body}
</body>
</html>`;
</html>
`;
}
}

// tslint:disable-next-line:max-classes-per-file
interface IResult {
[key: string]: string[];
messages: string[];
}

export const leetCodeResultProvider: LeetCodeResultProvider = new LeetCodeResultProvider();
23 changes: 10 additions & 13 deletions src/webview/leetCodeSolutionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,33 @@

import { Disposable, ExtensionContext, ViewColumn, WebviewPanel, window } from "vscode";
import { IProblem } from "../shared";
import { MarkdownEngine } from "./MarkdownEngine";
import { markdownEngine } from "./markdownEngine";

class LeetCodeSolutionProvider implements Disposable {

private context: ExtensionContext;
private panel: WebviewPanel | undefined;
private mdEngine: MarkdownEngine;
private solution: Solution;

public initialize(context: ExtensionContext): void {
this.context = context;
this.mdEngine = new MarkdownEngine();
}

public async show(solutionString: string, problem: IProblem): Promise<void> {
if (!this.panel) {
this.panel = window.createWebviewPanel("leetCode.solution", "Top Voted Solution", ViewColumn.Active, {
retainContextWhenHidden: true,
enableFindWidget: true,
localResourceRoots: this.mdEngine.localResourceRoots,
localResourceRoots: markdownEngine.localResourceRoots,
});

this.panel.onDidDispose(() => {
this.panel = undefined;
}, null, this.context.subscriptions);
}

this.solution = this.parseSolution(solutionString);
this.panel.title = problem.name;
this.panel.webview.html = this.getWebViewContent(this.solution);
const solution: Solution = this.parseSolution(solutionString);
this.panel.title = `${problem.name}: Solution`;
this.panel.webview.html = this.getWebViewContent(solution);
this.panel.reveal(ViewColumn.Active);
}

Expand All @@ -56,17 +53,17 @@ class LeetCodeSolutionProvider implements Disposable {
}

private getWebViewContent(solution: Solution): string {
const styles: string = this.mdEngine.getStylesHTML();
const styles: string = markdownEngine.getStylesHTML();
const { title, url, lang, author, votes } = solution;
const head: string = this.mdEngine.render(`# [${title}](${url})`);
const head: string = markdownEngine.render(`# [${title}](${url})`);
const auth: string = `[${author}](https://leetcode.com/${author}/)`;
const info: string = this.mdEngine.render([
const info: string = markdownEngine.render([
`| Language | Author | Votes |`,
`| :------: | :------: | :------: |`,
`| ${lang} | ${auth} | ${votes} |`,
].join("\n"));
const body: string = this.mdEngine.render(solution.body, {
lang: this.solution.lang,
const body: string = markdownEngine.render(solution.body, {
lang: solution.lang,
host: "https://discuss.leetcode.com/",
});
return `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as path from "path";
import * as vscode from "vscode";
import { leetCodeChannel } from "../leetCodeChannel";

export class MarkdownEngine {
class MarkdownEngine {

private readonly engine: MarkdownIt;
private readonly extRoot: string; // root path of vscode built-in markdown extension
Expand Down Expand Up @@ -106,3 +106,5 @@ export class MarkdownEngine {
};
}
}

export const markdownEngine: MarkdownEngine = new MarkdownEngine();