11// Copyright (c) jdneo. All rights reserved.
22// Licensed under the MIT license.
33
4- import { commands, Disposable, ExtensionContext, ViewColumn, WebviewPanel, window } from "vscode";
4+ import { commands, ViewColumn } from "vscode";
55import { leetCodeExecutor } from "../leetCodeExecutor";
66import { IProblem } from "../shared";
7+ import { ILeetCodeWebviewOption, LeetCodeWebview } from "./LeetCodeWebview";
78import { markdownEngine } from "./markdownEngine";
89
9- class LeetCodePreviewProvider implements Disposable {
10+ class LeetCodePreviewProvider extends LeetCodeWebview {
1011
11- private context: ExtensionContext;
1212 private node: IProblem;
13- private panel: WebviewPanel | undefined;
14-
15- public initialize(context: ExtensionContext): void {
16- this.context = context;
17- }
13+ private description: IDescription;
1814
1915 public async show(node: IProblem): Promise<void> {
20- // Fetch problem first before creating webview panel
21- const descString: string = await leetCodeExecutor.getDescription(node);
22-
16+ this.description = this.parseDescription(await leetCodeExecutor.getDescription(node), node);
2317 this.node = node;
24- if (!this.panel) {
25- this.panel = window.createWebviewPanel("leetcode.preview", "Preview Problem", ViewColumn.One, {
26- enableScripts: true,
27- enableCommandUris: true,
28- enableFindWidget: true,
29- retainContextWhenHidden: true,
30- localResourceRoots: markdownEngine.localResourceRoots,
31- });
32-
33- this.panel.webview.onDidReceiveMessage(async (message: IWebViewMessage) => {
34- switch (message.command) {
35- case "ShowProblem": {
36- await commands.executeCommand("leetcode.showProblem", this.node);
37- break;
38- }
39- }
40- }, this, this.context.subscriptions);
41-
42- this.panel.onDidDispose(() => {
43- this.panel = undefined;
44- }, null, this.context.subscriptions);
45- }
46-
47- const description: IDescription = this.parseDescription(descString, node);
48- this.panel.webview.html = this.getWebViewContent(description);
49- this.panel.title = `${node.name}: Preview`;
50- this.panel.reveal(ViewColumn.One);
18+ this.showWebviewInternal();
5119 }
5220
53- public dispose(): void {
54- if (this.panel) {
55- this.panel.dispose();
56- }
57- }
58-
59- private parseDescription(descString: string, problem: IProblem): IDescription {
60- const [
61- /* title */, ,
62- url, ,
63- /* tags */, ,
64- /* langs */, ,
65- category,
66- difficulty,
67- likes,
68- dislikes,
69- /* accepted */,
70- /* submissions */,
71- /* testcase */, ,
72- ...body
73- ] = descString.split("\n");
21+ protected getWebviewOption(): ILeetCodeWebviewOption {
7422 return {
75- title: problem.name,
76- url,
77- tags: problem.tags,
78- companies: problem.companies,
79- category: category.slice(2),
80- difficulty: difficulty.slice(2),
81- likes: likes.split(": ")[1].trim(),
82- dislikes: dislikes.split(": ")[1].trim(),
83- body: body.join("\n").replace(/<pre>\s*([^]+?)\s*<\/pre>/g, "<pre><code>$1</code></pre>"),
23+ viewType: "leetcode.preview",
24+ title: `${this.node.name}: Preview`,
25+ viewColumn: ViewColumn.One,
8426 };
8527 }
8628
87- private getWebViewContent(desc: IDescription): string {
88- const mdStyles: string = markdownEngine.getStyles();
89- const buttonStyle: string = `
90- <style>
29+ protected getWebviewContent(): string {
30+ const button: { element: string, script: string, style: string } = {
31+ element: `<button id="solve">Code Now</button>`,
32+ script: `const button = document.getElementById('solve');
33+ button.onclick = () => vscode.postMessage({
34+ command: 'ShowProblem',
35+ });`,
36+ style: `<style>
9137 #solve {
9238 position: fixed;
9339 bottom: 1rem;
@@ -104,9 +50,9 @@ class LeetCodePreviewProvider implements Disposable {
10450 #solve:active {
10551 border: 0;
10652 }
107- </style>
108- ` ;
109- const { title, url, category, difficulty, likes, dislikes, body } = desc ;
53+ </style>`,
54+ } ;
55+ const { title, url, category, difficulty, likes, dislikes, body } = this.description ;
11056 const head: string = markdownEngine.render(`# [${title}](${url})`);
11157 const info: string = markdownEngine.render([
11258 `| Category | Difficulty | Likes | Dislikes |`,
@@ -117,7 +63,7 @@ class LeetCodePreviewProvider implements Disposable {
11763 `<details>`,
11864 `<summary><strong>Tags</strong></summary>`,
11965 markdownEngine.render(
120- desc .tags
66+ this.description .tags
12167 .map((t: string) => `[\`${t}\`](https://leetcode.com/tag/${t})`)
12268 .join(" | "),
12369 ),
@@ -127,7 +73,7 @@ class LeetCodePreviewProvider implements Disposable {
12773 `<details>`,
12874 `<summary><strong>Companies</strong></summary>`,
12975 markdownEngine.render(
130- desc .companies
76+ this.description .companies
13177 .map((c: string) => `\`${c}\``)
13278 .join(" | "),
13379 ),
@@ -137,28 +83,67 @@ class LeetCodePreviewProvider implements Disposable {
13783 <!DOCTYPE html>
13884 <html>
13985 <head>
140- ${mdStyles }
141- ${buttonStyle }
86+ ${markdownEngine.getStyles() }
87+ ${button.style }
14288 </head>
14389 <body>
14490 ${head}
14591 ${info}
14692 ${tags}
14793 ${companies}
14894 ${body}
149- < button id="solve">Code Now</button>
95+ ${ button.element}
15096 <script>
15197 const vscode = acquireVsCodeApi();
152- const button = document.getElementById('solve');
153- button.onclick = () => vscode.postMessage({
154- command: 'ShowProblem',
155- });
98+ ${button.script}
15699 </script>
157100 </body>
158101 </html>
159102 `;
160103 }
161104
105+ protected onDidDisposeWebview(): void {
106+ super.onDidDisposeWebview();
107+ delete this.node;
108+ delete this.description;
109+ }
110+
111+ protected async onDidReceiveMessage(message: IWebViewMessage): Promise<void> {
112+ switch (message.command) {
113+ case "ShowProblem": {
114+ await commands.executeCommand("leetcode.showProblem", this.node);
115+ break;
116+ }
117+ }
118+ }
119+
120+ private parseDescription(descString: string, problem: IProblem): IDescription {
121+ const [
122+ /* title */, ,
123+ url, ,
124+ /* tags */, ,
125+ /* langs */, ,
126+ category,
127+ difficulty,
128+ likes,
129+ dislikes,
130+ /* accepted */,
131+ /* submissions */,
132+ /* testcase */, ,
133+ ...body
134+ ] = descString.split("\n");
135+ return {
136+ title: problem.name,
137+ url,
138+ tags: problem.tags,
139+ companies: problem.companies,
140+ category: category.slice(2),
141+ difficulty: difficulty.slice(2),
142+ likes: likes.split(": ")[1].trim(),
143+ dislikes: dislikes.split(": ")[1].trim(),
144+ body: body.join("\n").replace(/<pre>\s*([^]+?)\s*<\/pre>/g, "<pre><code>$1</code></pre>"),
145+ };
146+ }
162147}
163148
164149interface IDescription {
0 commit comments