]> Git Repo - pico-vscode.git/blob - src/commands/openSdkDocumentation.mts
Some code refactoring
[pico-vscode.git] / src / commands / openSdkDocumentation.mts
1 /* eslint-disable max-len */
2 import { CommandWithArgs } from "./command.mjs";
3 import Logger from "../logger.mjs";
4 import {
5   type QuickPickItem,
6   ViewColumn,
7   window,
8   Uri,
9   type WebviewPanel,
10 } from "vscode";
11 import { readFileSync } from "fs";
12
13 export enum DocumentationId {
14   hardware = 0,
15   highLevel = 1,
16   networking = 2,
17   runtimeInfrastructure = 3,
18 }
19
20 export const DOCUMENTATION_LABEL_BY_ID: string[] = [
21   "Hardware APIs",
22   "High Level APIs",
23   "Networking Libraries",
24   "Runtime Infrastructure",
25 ];
26
27 // eslint-disable-next-line @typescript-eslint/no-unused-vars
28 const DOCUMENTATION_URLS_BY_ID: string[] = [
29   //"https://raspberrypi.github.io/pico-sdk-doxygen/index.html",
30   "https://www.raspberrypi.com/documentation/pico-sdk/hardware.html",
31   "https://www.raspberrypi.com/documentation/pico-sdk/high_level.html",
32   "https://www.raspberrypi.com/documentation/pico-sdk/networking.html",
33   "https://www.raspberrypi.com/documentation/pico-sdk/runtime.html",
34 ];
35
36 const LOCAL_DOCUMENTATION_URLS_BY_ID: string[] = [
37   "group__hardware.html",
38   "group__high__level.html",
39   "group__networking.html",
40   "group__runtime.html",
41 ];
42
43 export default class OpenSdkDocumentationCommand extends CommandWithArgs {
44   private _logger: Logger = new Logger("OpenSdkDocumentationCommand");
45
46   public static readonly id = "openSdkDocumentation";
47   private _panel: WebviewPanel | undefined = undefined;
48
49   constructor(private readonly _extensionUri: Uri) {
50     super(OpenSdkDocumentationCommand.id);
51   }
52
53   async execute(docId?: DocumentationId, fileName?: string): Promise<void> {
54     let url = "";
55     if (typeof docId === "number") {
56       url = docId !== undefined ? LOCAL_DOCUMENTATION_URLS_BY_ID[docId] : "";
57     } else if (fileName !== undefined) {
58       url = fileName;
59     } else {
60       const options: QuickPickItem[] = DOCUMENTATION_LABEL_BY_ID.map(
61         (label, index) => ({
62           label,
63           detail: LOCAL_DOCUMENTATION_URLS_BY_ID[index],
64         })
65       );
66
67       const result = await window.showQuickPick(options, {
68         placeHolder: "Select Category",
69         canPickMany: false,
70         ignoreFocusOut: false,
71       });
72
73       if (result === undefined || result.detail === undefined) {
74         return;
75       }
76
77       url = result.detail;
78     }
79
80     // show webview
81     this._logger.info("Opening SDK documentation in browser...");
82     if (this._panel === undefined) {
83       Logger.log("New panel");
84       this._panel = window.createWebviewPanel(
85         "pico-sdk-documentation",
86         "Pico SDK Documentation",
87         { viewColumn: ViewColumn.Two, preserveFocus: false },
88         {
89           enableScripts: true,
90           retainContextWhenHidden: true,
91           enableFindWidget: true,
92           localResourceRoots: [Uri.joinPath(this._extensionUri, "web", "docs")],
93           enableCommandUris: true,
94         }
95       );
96     }
97
98     const panel = this._panel;
99
100     panel.webview.html = this._getHtmlForWebview(
101       Uri.joinPath(this._extensionUri, "web", "docs", url).fsPath,
102       panel.webview.cspSource,
103       panel,
104       this._extensionUri
105     );
106     panel.reveal();
107
108     // dispose when hidden
109     panel.onDidDispose(() => {
110       this._panel = undefined;
111     }, this);
112   }
113
114   private _getHtmlForWebview(
115     url: string,
116     cspSource: string,
117     panel: WebviewPanel,
118     extensionUri: Uri
119   ): string {
120     const regexa = /<a\s+(.*?)?href="([^"]+)"/g;
121     const regexsrc = /src="([^"]+)"/g;
122     const regexcss = /<link href="([^"]+)" rel="stylesheet"/g;
123
124     // load from file
125     return (
126       readFileSync(url)
127         .toString("utf-8")
128         /*.replace(/{{jquery}}/g, jquery)
129       .replace(/{{jquery-ui}}/g, jqueryUi)
130       .replace(/{{jquery-tocify}}/g, jqueryTocify)
131       .replace(/{{nonce}}/g, nonce)*/
132         .replace(/{{cspSource}}/g, cspSource)
133         .replace(regexa, function (match, space: string, file: string) {
134           if (file === "/") {
135             file = "index.html";
136           }
137           if (space === undefined) {
138             space = "";
139           }
140           if (file.match("#") || file.match("https")) {
141             if (file.match("#")) {
142               file = `#${file.split("#")[1]}`;
143             }
144             const ret = `<a ${space}href="${file}"`;
145
146             return ret;
147           }
148           const command = Uri.parse(
149             `command:raspberry-pi-pico.openSdkDocumentation?${encodeURIComponent(
150               JSON.stringify([undefined, file])
151             )}`
152           ).toString();
153           const ret = `<a ${space}href="${command}"`;
154
155           return ret;
156         })
157         .replace(regexsrc, function (match, file: string) {
158           const ret = `src="${panel.webview
159             .asWebviewUri(Uri.joinPath(extensionUri, "web", "docs", file))
160             .toString()}"`;
161
162           return ret;
163         })
164         .replace(regexcss, function (match, file: string) {
165           const ret = `<link href="${panel.webview
166             .asWebviewUri(Uri.joinPath(extensionUri, "web", "docs", file))
167             .toString()}" rel="stylesheet"`;
168
169           return ret;
170         })
171         .replace('<div class="navigation-toggle">', "<div hidden>")
172         .replace('<div id="main-nav">', '<div id="main-nav" hidden>')
173     );
174   }
175 }
This page took 0.044513 seconds and 4 git commands to generate.