Skip to content

Commit

Permalink
Small refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
DaanV2 committed Oct 16, 2023
1 parent 7795920 commit 514c224
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 30 deletions.
4 changes: 1 addition & 3 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,19 @@
"version": "0.2.0",
"configurations": [
{
"type": "pwa-extensionHost",
"type": "extensionHost",
"request": "launch",
"name": "Launch Client",
"runtimeExecutable": "${execPath}",
"args": ["--disable-extensions", "--extensionDevelopmentPath=${workspaceFolder}"],
"sourceMaps": true,
"outFiles": ["${workspaceFolder}/client/out/**/*.js"],
"preLaunchTask": "npm watch 'vscode-plugin'"
},
{
"type": "node",
"request": "attach",
"name": "Attach to Server",
"address": "localhost",
"protocol": "inspector",
"port": 6009,
"sourceMaps": true,
"outFiles": ["${workspaceFolder}/server/out/**/*.js"]
Expand Down
106 changes: 85 additions & 21 deletions client/src/Commands/Docs/ShowDocs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { commands, ExtensionContext, FileType, ProgressLocation, Uri, window, workspace } from "vscode";
import { Commands } from "@blockception/shared";
import fetch, { RequestInit } from "node-fetch";
import path from "path";
import { Console } from '../../Console/Console';

export function Activate(context: ExtensionContext): void {
async function ShowDocs(args: any) {
Expand All @@ -23,7 +23,13 @@ export function Activate(context: ExtensionContext): void {
}

// Find the item by title or processed title
return command.process(sidebar.find((x) => x.processedTitle === title || x.toc_title === title));
const item = sidebar.find((x) => x.processedTitle === title || x.toc_title === title);
if (!item) {
Console.Error("Failed to find docs item", title);
return;
}

return command.process(item);
});
}

Expand All @@ -35,24 +41,47 @@ const day_diff_2 = 1000 * 60 * 60 * 24 * 2;
const sidebar_url = "https://learn.microsoft.com/en-us/minecraft/creator/toc.json";
// URL to the docs, that will be prepended to the href
const html_url = "https://learn.microsoft.com/en-us/minecraft/creator/";
// Cached flattened sidebar
let sidebar: SidebarItem[] | undefined;

/**
* Represents a command to show documentation.
*/
class ShowDocsCommand {
private storage: string;
// Cached flattened sidebar
private sidebar: SidebarItem[];

/**
* Creates a new instance of the ShowDocsCommand class.
* @param storage The storage path.
*/
constructor(storage: string) {
this.storage = storage;
this.sidebar = [];
}

/**
* Gets the flattened sidebar.
* @returns A promise that resolves to the flattened sidebar. or an empty array if the sidebar could not be downloaded.
*/
async getSidebar(): Promise<SidebarItem[]> {
if (sidebar) {
return Promise.resolve(sidebar);
if (this.sidebar.length > 0) {
return this.sidebar;
}
const data = await fetch(sidebar_url);

if (!data.ok) {
window.showErrorMessage("Failed to download docs sidebar");
return this.sidebar;
}

const jsonData = (await data.json()) as Sidebar;
sidebar = this.flattenSidebar(jsonData.items);
return sidebar;

if (!Sidebar.is(jsonData)) {
window.showErrorMessage("Failed to parse docs sidebar");
return this.sidebar;
}

return (this.sidebar = this.flattenSidebar(jsonData.items));
}

/**
Expand All @@ -69,7 +98,7 @@ class ShowDocsCommand {
const item = sidebar[I];
// Add the prefix to the title
// Remove the docs title from the path, because it is too long
item.processedTitle = (prefix + "/" + item.toc_title).replace("/Minecraft: Bedrock Documentation/", "");
item.processedTitle = `${prefix}/${item.toc_title}`.replace("/Minecraft: Bedrock Documentation/", "");
if (item.href) {
result.push(item);
}
Expand All @@ -83,11 +112,21 @@ class ShowDocsCommand {
return result;
}

/**
* Gets the filepath for the specified sidebar item.
* @param item The sidebar item.
* @returns The filepath for the specified sidebar item.
*/
getFilepath(item: SidebarItem): string {
// At this point, elements without href are filtered out
return path.join(this.storage, item.href! + ".md");
}

/**
* Checks if the specified file can be read.
* @param filepath The filepath of the file to check.
* @returns A promise that resolves to true if the file can be read, false otherwise.
*/
async canRead(filepath: string): Promise<boolean> {
try {
const stat = await workspace.fs.stat(Uri.file(filepath));
Expand All @@ -97,15 +136,22 @@ class ShowDocsCommand {
//Check if the file is not older then 2 days
const now = new Date();
const file = new Date(stat.mtime);

const diff = now.getTime() - file.getTime();

return diff <= day_diff_2;
} catch (err) {
return false;
Console.Error(`Failed to read file ${filepath}`, )
}

return false;
}

/**
* Downloads the specified URI to the specified filepath.
* @param uri The URI to download.
* @param filepath The filepath to download to.
* @returns A promise that resolves when the download is complete.
*/
async download(uri: string, filepath: string): Promise<void> {
const progressOptions = {
location: ProgressLocation.Notification,
Expand All @@ -126,13 +172,19 @@ class ShowDocsCommand {
try {
// Download the html page
const result = await fetch(uri, options);

if (!result.ok) {
window.showErrorMessage("Failed to download docs\n", `${uri}\n${filepath}\n`, result.statusText);
return;
}

const text = await result.text();

progress.report({ increment: 50 });
// Find the github link and change blob to raw. It's not the best solution, but it works
const matches = /(https:\/\/github.com\/MicrosoftDocs\/minecraft-creator\/blob\/main\/[^"]+)/g.exec(text);
if (!matches || matches.length === 0 || !matches[0]) {
window.showErrorMessage("Failed to download docs\n", uri + "\n", filepath + "\nNo github link found");
if (!matches || matches.length === 0 || matches[0] === undefined) {
window.showErrorMessage("Failed to download docs\n", `${uri}\n${filepath}\nNo github link found`);
return;
}
const mdUrl = matches[0].replace(
Expand All @@ -141,24 +193,31 @@ class ShowDocsCommand {
);
// Download the markdown file
const mdResult = await fetch(mdUrl, options);

if (!mdResult.ok) {
window.showErrorMessage("Failed to download docs\n", `${uri}\n${filepath}\n`, mdResult.statusText);
return;
}

const mdText = await mdResult.text();

await workspace.fs.writeFile(Uri.file(filepath), Buffer.from(mdText, "utf8"));
Console.Info("Downloaded docs", filepath);
} catch (err) {
window.showErrorMessage("Failed to download docs\n", uri + "\n", filepath + "\n", JSON.stringify(err));
window.showErrorMessage("Failed to download docs\n", `${uri}\n${filepath}\n`, JSON.stringify(err));
}
console.log("Downloaded docs", filepath);

progress.report({ increment: 50 });
});
}

async process(item: SidebarItem | undefined): Promise<void> {
if (!item) {
return;
}
/**
* Processes the specified sidebar item.
* @param item The sidebar item to process.
* @returns A promise that resolves when the processing is complete.
*/
async process(item: SidebarItem): Promise<void> {
const filepath = this.getFilepath(item);

const dir = path.dirname(filepath);

await workspace.fs.createDirectory(Uri.file(dir));
Expand All @@ -180,7 +239,6 @@ class ShowDocsCommand {
}

// Interfaces for the sidebar. It's not complete, but it's enough for this use case

interface Sidebar {
items: SidebarItem[];
}
Expand All @@ -192,3 +250,9 @@ interface SidebarItem {
// This is added by the flattenSidebar function
processedTitle?: string;
}

namespace Sidebar {
export function is(item: any): item is Sidebar {
return item && item.items && Array.isArray(item.items);
}
}
12 changes: 6 additions & 6 deletions client/src/Console/Console.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
export class Console {
/**Sends a error to the console log of the server*/
static Error(message: string): void {
console.error(message);
static Error(message: string, ...optionalParams: any[]): void {
console.error(message, ...optionalParams);
}

/**Sends a error to the console log of the server*/
static Info(message: string): void {
console.info(message);
static Info(message: string, ...optionalParams: any[]): void {
console.info(message, ...optionalParams);
}

/**Sends a error to the console log of the server*/
Expand All @@ -15,7 +15,7 @@ export class Console {
}

/**Sends a error to the console log of the server*/
static Warn(message: string): void {
console.warn(message);
static Warn(message: string, ...optionalParams: any[]): void {
console.warn(message, ...optionalParams);
}
}

0 comments on commit 514c224

Please sign in to comment.