diff --git a/README.md b/README.md index 9641e41b..c25e3654 100644 --- a/README.md +++ b/README.md @@ -1,65 +1 @@ -# vscode-hugo-taxonomy README - -This is the README for your extension "vscode-hugo-taxonomy". After writing up a brief description, we recommend including the following sections. - -## Features - -Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file. - -For example if there is an image subfolder under your extension project workspace: - -\!\[feature X\]\(images/feature-x.png\) - -> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow. - -## Requirements - -If you have any requirements or dependencies, add a section describing those and how to install and configure them. - -## Extension Settings - -Include if your extension adds any VS Code settings through the `contributes.configuration` extension point. - -For example: - -This extension contributes the following settings: - -* `myExtension.enable`: enable/disable this extension -* `myExtension.thing`: set to `blah` to do something - -## Known Issues - -Calling out known issues can help limit users opening duplicate issues against your extension. - -## Release Notes - -Users appreciate release notes as you update your extension. - -### 1.0.0 - -Initial release of ... - -### 1.0.1 - -Fixed issue #. - -### 1.1.0 - -Added features X, Y, and Z. - ------------------------------------------------------------------------------------------------------------ - -## Working with Markdown - -**Note:** You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts: - -* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux) -* Toggle preview (`Shift+CMD+V` on macOS or `Shift+Ctrl+V` on Windows and Linux) -* Press `Ctrl+Space` (Windows, Linux) or `Cmd+Space` (macOS) to see a list of Markdown snippets - -### For more information - -* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) -* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) - -**Enjoy!** +# VSCode Hugo Helpers \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 64ad8e1c..39a6b939 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "vscode-hugo-taxonomy", + "name": "vscode-hugo-helpers", "version": "0.0.1", "lockfileVersion": 1, "requires": true, @@ -99,7 +99,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -311,8 +310,7 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esutils": { "version": "2.0.3", @@ -335,6 +333,14 @@ "strip-eof": "^1.0.0" } }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -394,6 +400,17 @@ "path-is-absolute": "^1.0.0" } }, + "gray-matter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.2.tgz", + "integrity": "sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw==", + "requires": { + "js-yaml": "^3.11.0", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + } + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -504,6 +521,11 @@ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "dev": true }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -550,12 +572,16 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" } }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -878,6 +904,15 @@ "glob": "^7.1.3" } }, + "section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "requires": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -914,8 +949,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "string-width": { "version": "2.1.1", @@ -936,6 +970,11 @@ "ansi-regex": "^3.0.0" } }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" + }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", diff --git a/package.json b/package.json index a6a5ef01..6af8a77b 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "vscode-hugo-helpers", "description": "", "version": "0.0.1", - "publisher": "eliostruyf", + "publisher": "eliostruyf", "engines": { "vscode": "^1.37.0" }, @@ -67,5 +67,8 @@ "typescript": "^3.3.1", "tslint": "^5.12.1", "vscode-test": "^1.0.2" + }, + "dependencies": { + "gray-matter": "4.0.2" } } diff --git a/src/commands/Hugo.ts b/src/commands/Hugo.ts index e082a6db..55d9004e 100644 --- a/src/commands/Hugo.ts +++ b/src/commands/Hugo.ts @@ -1,46 +1,83 @@ import * as vscode from 'vscode'; import { TaxonomyType } from "../models"; import { CONFIG_KEY, ACTION_TAXONOMY_TAGS, ACTION_TAXONOMY_CATEGORIES } from "../constants/settings"; +import * as matter from "gray-matter"; export class Hugo { - + + /** + * Insert taxonomy + * + * @param type + */ public static async insert(type: TaxonomyType) { const config = vscode.workspace.getConfiguration(CONFIG_KEY); - + const editor = vscode.window.activeTextEditor; + if (!editor) { + return; + } + + const fileTxt = editor.document.getText(); + const article = matter(fileTxt); + if (!article || !article.data) { + return; + } + let options: vscode.QuickPickItem[] = []; + const matterProp: string = type === TaxonomyType.Tag ? "tags" : "categories"; + + // Add the selected options to the options array + if (article.data[matterProp]) { + const propData = article.data[matterProp]; + if (propData && propData.length > 0) { + options = [...propData].map(p => ({ + label: p, + picked: true + } as vscode.QuickPickItem)); + } + } + + // Add all the known options to the selection list const configSetting = type === TaxonomyType.Tag ? ACTION_TAXONOMY_TAGS : ACTION_TAXONOMY_CATEGORIES; const crntOptions = config.get(configSetting) as string[]; if (crntOptions && crntOptions.length > 0) { - options = crntOptions.map(o => ({ - label: o - }) as vscode.QuickPickItem); + for (const crntOpt of crntOptions) { + if (!options.find(o => o.label === crntOpt)) { + options.push({ + label: crntOpt + }); + } + } } - + if (options.length === 0) { vscode.window.showInformationMessage(`No ${type === TaxonomyType.Tag ? "tags" : "categories"} configured.`); return; } - + const selectedOptions = await vscode.window.showQuickPick(options, { placeHolder: `Select your ${type === TaxonomyType.Tag ? "tags" : "categories"} to insert`, canPickMany: true }); - if (selectedOptions && selectedOptions.length > 0) { - const editor = vscode.window.activeTextEditor; - if (editor) { - await editor.edit(builder => { - builder.insert(editor.selection.start, selectedOptions.map(o => `"${o.label}"`).join(`, `)); - }); - } + + if (selectedOptions) { + article.data[matterProp] = selectedOptions.map(o => o.label); } + + this.updatePage(editor, article); } - + + /** + * Create a new taxonomy + * + * @param type + */ public static async create(type: TaxonomyType) { const newOption = await vscode.window.showInputBox({ prompt: `Insert the value of the ${type === TaxonomyType.Tag ? "tag" : "category"} that you want to add to your configuration.`, placeHolder: `Name of the ${type === TaxonomyType.Tag ? "tag" : "category"}` }); - + if (newOption) { const config = vscode.workspace.getConfiguration(CONFIG_KEY); const configSetting = type === TaxonomyType.Tag ? ACTION_TAXONOMY_TAGS : ACTION_TAXONOMY_CATEGORIES; @@ -48,8 +85,55 @@ export class Hugo { if (!options) { options = []; } + + if (options.find(o => o === newOption)) { + vscode.window.showInformationMessage(`The provided ${type === TaxonomyType.Tag ? "tag" : "category"} already exists.`); + return; + } + options.push(newOption); config.update(configSetting, options); + + // Ask if the new term needs to be added to the page + const addToPage = await vscode.window.showQuickPick(["yes", "no"], { canPickMany: false, placeHolder: `Do you want to add the new ${type === TaxonomyType.Tag ? "tag" : "category"} to the page?` }); + + if (addToPage && addToPage === "yes") { + const editor = vscode.window.activeTextEditor; + if (!editor) { + return; + } + + const fileTxt = editor.document.getText(); + const article = matter(fileTxt); + if (!article || !article.data) { + return; + } + + const matterProp: string = type === TaxonomyType.Tag ? "tags" : "categories"; + // Add the selected options to the options array + if (article.data[matterProp]) { + const propData: string[] = article.data[matterProp]; + if (propData && !propData.find(o => o === newOption)) { + propData.push(newOption); + } + } else { + article.data[matterProp] = [newOption]; + } + + this.updatePage(editor, article); + } } } + + /** + * Store the new information in the file + * + * @param editor + * @param article + */ + private static updatePage(editor: vscode.TextEditor, article: matter.GrayMatterFile) { + const newMarkdown = matter.stringify(article.content, article.data); + const nrOfLines = editor.document.lineCount as number; + editor.edit(builder => builder.replace(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(nrOfLines, 0)), newMarkdown)); + } } \ No newline at end of file