From 6c3d28628275aed69413e45f57480a228b7ed049 Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Tue, 10 May 2022 16:26:59 +0200 Subject: [PATCH] #331 - Added functionality to run other type of scripts --- .vscode/extensions.json | 3 +- CHANGELOG.md | 1 + package.json | 21 ++++++++++- src/constants/Extension.ts | 2 ++ src/helpers/CustomScript.ts | 71 +++++++++++++++++++++++++------------ src/helpers/Logger.ts | 6 ++-- src/models/PanelSettings.ts | 9 +++++ 7 files changed, 86 insertions(+), 27 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 0a18b9c4..9f8606d5 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,6 +2,7 @@ // See http://go.microsoft.com/fwlink/?LinkId=827846 // for the documentation about the extensions.json format "recommendations": [ - "ms-vscode.vscode-typescript-tslint-plugin" + "ms-vscode.vscode-typescript-tslint-plugin", + "eliostruyf.vscode-typescript-exportallmodules" ] } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 656a2b7c..7114185b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### 🎨 Enhancements - [#330](https://github.com/estruyf/vscode-front-matter/issues/330): Allow custom scripts to easily update front matter +- [#331](https://github.com/estruyf/vscode-front-matter/issues/331): Added functionality to run other type of scripts ### ⚡️ Optimizations diff --git a/package.json b/package.json index 93966d4a..ec5d74be 100644 --- a/package.json +++ b/package.json @@ -342,7 +342,7 @@ }, "nodeBin": { "type": "string", - "description": "Path to the node executable. This is required when using NVM, so that there is no confusion of which node version to use." + "description": "Path to the node executable. This is required when using NVM, so that there is no confusion of which node version to use. (deprecated: use the command property instead)" }, "bulk": { "type": "boolean", @@ -369,6 +369,25 @@ "mediaFile" ], "description": "The type for which the script will be used." + }, + "command": { + "type": "string", + "oneOf": [ + { + "enum": [ + "node", + "bash", + "powershell", + "python", + "python3" + ] + }, + { + "type": "string" + } + ], + "description": "The type of script you want to execute.", + "default": "node" } }, "additionalProperties": false, diff --git a/src/constants/Extension.ts b/src/constants/Extension.ts index 8cfe890d..5d946737 100644 --- a/src/constants/Extension.ts +++ b/src/constants/Extension.ts @@ -37,6 +37,8 @@ export const COMMAND_NAME = { diagnostics: getCommandName("diagnostics"), modeSwitch: getCommandName("mode.switch"), + showOutputChannel: getCommandName("showOutputChannel"), + // Insert dashboards insertMedia: getCommandName("insertMedia"), insertSnippet: getCommandName("insertSnippet"), diff --git a/src/helpers/CustomScript.ts b/src/helpers/CustomScript.ts index 7f5ffca5..ae0989fa 100644 --- a/src/helpers/CustomScript.ts +++ b/src/helpers/CustomScript.ts @@ -1,6 +1,7 @@ +import { CommandType } from './../models/PanelSettings'; import { CustomScript as ICustomScript, ScriptType } from '../models/PanelSettings'; import { window, env as vscodeEnv, ProgressLocation } from 'vscode'; -import { ArticleHelper, Telemetry } from '.'; +import { ArticleHelper, Logger, Telemetry } from '.'; import { Folders } from '../commands/Folders'; import { exec } from 'child_process'; import * as os from 'os'; @@ -138,22 +139,20 @@ export class CustomScript { title: `Executing: ${script.title}`, cancellable: false }, async () => { - exec(`${script.nodeBin || "node"} ${join(wsPath, script.script)} "${wsPath}" "${path}"`, (error, stdout) => { - if (error) { - Notifications.error(`${script.title}: ${error.message}`); - resolve(); - return; - } - - CustomScript.showOutput(stdout, script); + try { + const output = await CustomScript.executeScript(script, wsPath, `"${wsPath}" "${path}"`); + + CustomScript.showOutput(output, script); Dashboard.postWebviewMessage({ command: DashboardCommand.mediaUpdate }); - - resolve(); + return; - }); + } catch (e) { + Notifications.error(`${script.title}: ${(e as Error).message}`); + return; + } }); }); } @@ -167,7 +166,7 @@ export class CustomScript { * @returns */ private static async runScript(wsPath: string, article: ParsedFrontMatter | null, contentPath: string, script: ICustomScript): Promise { - return new Promise((resolve, reject) => { + try { let articleData = ""; if (os.type() === "Windows_NT") { articleData = `"${JSON.stringify(article?.data).replace(/"/g, `""`)}"`; @@ -176,16 +175,12 @@ export class CustomScript { articleData = `'${articleData}'`; } - exec(`${script.nodeBin || "node"} ${join(wsPath, script.script)} "${wsPath}" "${contentPath}" ${articleData}`, (error, stdout) => { - if (error) { - Notifications.error(`${script.title}: ${error.message}`); - resolve(null); - return; - } - - resolve(stdout); - }); - }); + const output = await CustomScript.executeScript(script, wsPath, `"${wsPath}" "${contentPath}" ${articleData}`); + return output; + } catch (e) { + Notifications.error(`${script.title}: ${(e as Error).message}`); + return null; + } } /** @@ -243,4 +238,34 @@ export class CustomScript { Notifications.info(`${script.title}: Executed your custom script.`); } } + + /** + * Execute script + * @param script + * @param wsPath + * @param args + * @returns + */ + private static async executeScript(script: ICustomScript, wsPath: string, args: string): Promise { + return new Promise((resolve, reject) => { + + // Check the command to use + let command = script.nodeBin || "node"; + if (script.command && script.command !== CommandType.Node) { + command = script.command; + } + + const scriptPath = join(wsPath, script.script); + const fullScript = `${command} ${scriptPath} ${args}`; + Logger.info(`Executing: ${fullScript}`); + + exec(fullScript, (error, stdout) => { + if (error) { + reject(error.message); + } + + resolve(stdout); + }); + }); + } } \ No newline at end of file diff --git a/src/helpers/Logger.ts b/src/helpers/Logger.ts index 42a8ed9c..02fc0239 100644 --- a/src/helpers/Logger.ts +++ b/src/helpers/Logger.ts @@ -1,14 +1,16 @@ import { Extension } from './Extension'; -import { OutputChannel, window } from 'vscode'; +import { commands, OutputChannel, window } from 'vscode'; import { format } from 'date-fns'; +import { COMMAND_NAME } from '../constants'; export class Logger { private static instance: Logger; - private static channel: OutputChannel | null = null; + public static channel: OutputChannel | null = null; private constructor() { const displayName = Extension.getInstance().displayName; Logger.channel = window.createOutputChannel(displayName); + commands.registerCommand(COMMAND_NAME.showOutputChannel, () => { Logger.channel?.show(); }); } public static getInstance(): Logger { diff --git a/src/models/PanelSettings.ts b/src/models/PanelSettings.ts index 6273514a..0dee30ea 100644 --- a/src/models/PanelSettings.ts +++ b/src/models/PanelSettings.ts @@ -111,6 +111,7 @@ export interface CustomScript { output?: "notification" | "editor"; outputType?: string; type?: ScriptType; + command?: CommandType; } export interface PreviewSettings { @@ -127,4 +128,12 @@ export enum ScriptType { Content = "content", MediaFolder = "mediaFolder", MediaFile = "mediaFile" +} + +export enum CommandType { + Node = "node", + Shell = "shell", + PowerShell = "powershell", + Python = "python", + Python3 = "python3" } \ No newline at end of file