diff --git a/CHANGELOG.md b/CHANGELOG.md index ff2fa57d..3c9426a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Change Log +## [7.3.x] - 2022-05-xx + +### 🎨 Enhancements + +- [#330](https://github.com/estruyf/vscode-front-matter/issues/330): Allow custom scripts to easily update front matter + +### ⚡️ Optimizations + +### 🐞 Fixes + ## [7.2.0] - 2022-05-02 - [Release notes](https://beta.frontmatter.codes/updates/v7.2.0) ### 🎨 Enhancements diff --git a/frontmatter.json b/frontmatter.json index 5dfc5256..535cb57c 100644 --- a/frontmatter.json +++ b/frontmatter.json @@ -50,6 +50,28 @@ ], "openingTags": "{{", "closingTags": "}}" + }, + "Issue link": { + "description": "Link to a GitHub issue", + "body": "- [#{{id}}](https://github.com/estruyf/vscode-front-matter/issues/{{id}}): {{title}}", + "fields": [ + { + "name": "id", + "title": "Issue ID", + "type": "string", + "single": true, + "default": "" + }, + { + "name": "title", + "title": "Title", + "type": "string", + "single": true, + "default": "" + } + ], + "openingTags": "{{", + "closingTags": "}}" } } } \ No newline at end of file diff --git a/src/helpers/ArticleHelper.ts b/src/helpers/ArticleHelper.ts index b998df62..e6ad3113 100644 --- a/src/helpers/ArticleHelper.ts +++ b/src/helpers/ArticleHelper.ts @@ -1,3 +1,4 @@ +import { Uri, workspace } from 'vscode'; import { MarkdownFoldingProvider } from './../providers/MarkdownFoldingProvider'; import { DEFAULT_CONTENT_TYPE, DEFAULT_CONTENT_TYPE_NAME } from './../constants/ContentType'; import * as vscode from 'vscode'; @@ -82,6 +83,23 @@ export class ArticleHelper { await editor.edit(builder => builder.replace(update.range, update.newText)); } + /** + * Store the new information for the article path + * + * @param path + * @param article + */ + public static async updateByPath(path: string, article: ParsedFrontMatter) { + const file = await workspace.openTextDocument(Uri.parse(path)); + const editor = await window.showTextDocument(file); + + if (file && editor) { + const update = this.generateUpdate(file, article); + + await editor.edit(builder => builder.replace(update.range, update.newText)); + } + } + /** * Generate the update to be applied to the article. * @param article diff --git a/src/helpers/CustomScript.ts b/src/helpers/CustomScript.ts index 89f8025b..7f5ffca5 100644 --- a/src/helpers/CustomScript.ts +++ b/src/helpers/CustomScript.ts @@ -41,6 +41,13 @@ export class CustomScript { } } + /** + * Run the script on the current file + * @param wsPath + * @param script + * @param path + * @returns + */ private static async singleRun(wsPath: string, script: ICustomScript, path: string | null = null): Promise { let articlePath: string | null = path; let article: ParsedFrontMatter | null = null; @@ -62,13 +69,19 @@ export class CustomScript { cancellable: false }, async () => { const output = await CustomScript.runScript(wsPath, article, articlePath as string, script); - CustomScript.showOutput(output, script); + CustomScript.showOutput(output, script, articlePath); }); } else { Notifications.warning(`${script.title}: Article couldn't be retrieved.`); } } + /** + * Run the script on multiple files + * @param wsPath + * @param script + * @returns + */ private static async bulkRun(wsPath: string, script: ICustomScript): Promise { const folders = await Folders.getInfo(); @@ -106,6 +119,13 @@ export class CustomScript { }); } + /** + * Run a script for a media file + * @param wsPath + * @param path + * @param script + * @returns + */ private static async runMediaScript(wsPath: string, path: string | null, script: ICustomScript): Promise { if (!path) { Notifications.error(`${script.title}: There was no folder or media path specified.`); @@ -138,6 +158,14 @@ export class CustomScript { }); } + /** + * Script runner + * @param wsPath + * @param article + * @param contentPath + * @param script + * @returns + */ private static async runScript(wsPath: string, article: ParsedFrontMatter | null, contentPath: string, script: ICustomScript): Promise { return new Promise((resolve, reject) => { let articleData = ""; @@ -160,16 +188,56 @@ export class CustomScript { }); } - private static showOutput(output: string | null, script: ICustomScript): void { + /** + * Show/process the output of the script + * @param output + * @param script + */ + private static showOutput(output: string | null, script: ICustomScript, articlePath?: string | null): void { if (output) { - if (script.output === "editor") { - ContentProvider.show(output, script.title, script.outputType || "text"); - } else { - window.showInformationMessage(`${script.title}: ${output}`, 'Copy output').then(value => { - if (value === 'Copy output') { - vscodeEnv.clipboard.writeText(output); + try { + const data = JSON.parse(output); + + if (data.frontmatter) { + let article = null; + const editor = window.activeTextEditor; + + if (!articlePath) { + if (!editor) return; + + articlePath = editor.document.uri.fsPath; + article = ArticleHelper.getFrontMatter(editor); + } else { + article = ArticleHelper.getFrontMatterByPath(articlePath); } - }); + + if (article && article.data) { + for (const key in data.frontmatter) { + article.data[key] = data.frontmatter[key]; + } + + if (articlePath) { + ArticleHelper.updateByPath(articlePath, article); + } else if (editor) { + ArticleHelper.update(editor, article); + } else { + throw new Error(`Couldn't update article.`); + } + Notifications.info(`${script.title}: front matter updated.`); + } + } else { + throw new Error(`No frontmatter found.`); + } + } catch (error) { + if (script.output === "editor") { + ContentProvider.show(output, script.title, script.outputType || "text"); + } else { + window.showInformationMessage(`${script.title}: ${output}`, 'Copy output').then(value => { + if (value === 'Copy output') { + vscodeEnv.clipboard.writeText(output); + } + }); + } } } else { Notifications.info(`${script.title}: Executed your custom script.`);