mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-08-12 03:43:01 +02:00
#3 - Included the new remapping command
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
# Change Log
|
||||
|
||||
## [0.0.7] - 2019-08-28
|
||||
|
||||
- Added command to remap tags or categories in all posts: `Front Matter: Remap tag/category in all articles`
|
||||
|
||||
## [0.0.6] - 2019-08-28
|
||||
|
||||
- Updated `package.json` file to include preview label
|
||||
- Added the status bar item to quickly view and update the draft status of an article
|
||||
|
||||
## [0.0.5] - 2019-08-27
|
||||
|
||||
|
||||
@@ -7,21 +7,30 @@ This VSCode extension simplifies working with front matter of your markdown arti
|
||||
## Available commands:
|
||||
|
||||
**Front Matter: Create <tag | category>**
|
||||
- Creates a new <tag | category> and allows you to automatically include it into your post
|
||||
|
||||
Creates a new <tag | category> and allows you to automatically include it into your post
|
||||
|
||||

|
||||
|
||||
**Front Matter: Insert <tags | categories>**
|
||||
- Inserts a selected <tags | categories> into the front matter of your article/post/...
|
||||
|
||||
Inserts a selected <tags | categories> into the front matter of your article/post/...
|
||||
|
||||

|
||||
|
||||
**Front Matter: Export all tags & categories to your settings**
|
||||
- Export all the already used tags & categories in your articles/posts/... to your user settings
|
||||
|
||||
Export all the already used tags & categories in your articles/posts/... to your user settings
|
||||
|
||||
**Front Matter: Remap tag/category in all articles**
|
||||
|
||||
This is commands helps you quickly update/remap a tag or category in all your markdown files. You'll be asked to select the taxonomy type (*tag* or *category*), the old taxonomy value and the new one.
|
||||
|
||||
> **Info**: Once the remapping is completed, the taxonomy tags/categories will be updated in your user settings.
|
||||
|
||||
**Front Matter: Set current date**
|
||||
|
||||
- Update the `date` property of the current article/post/... to the current date & time.
|
||||
Update the `date` property of the current article/post/... to the current date & time.
|
||||
|
||||
> **Optional**: if you want, you can specify the format of the date property by adding your own preference in your settings. Settings key: `frontMatter.taxonomy.dateFormat`. Check [date-fns formating](https://date-fns.org/v2.0.1/docs/format) for more information which patterns you can use.
|
||||
|
||||
@@ -39,7 +48,7 @@ The tags and categories are stored in the project VSCode user settings. You can
|
||||
## Usage
|
||||
|
||||
- Start by opening the command prompt:
|
||||
- Windows ⇧+ctrl+P
|
||||
- Windows: ⇧+ctrl+P
|
||||
- Mac: ⇧+⌘+P
|
||||
- Use one of the commands from above
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
"onCommand:frontMatter.createTag",
|
||||
"onCommand:frontMatter.createCategory",
|
||||
"onCommand:frontMatter.exportTaxonomy",
|
||||
"onCommand:frontMatter.remap",
|
||||
"onCommand:frontMatter.setDate"
|
||||
],
|
||||
"main": "./dist/extension",
|
||||
@@ -85,6 +86,10 @@
|
||||
"command": "frontMatter.exportTaxonomy",
|
||||
"title": "Front Matter: Export all tags & categories to your settings"
|
||||
},
|
||||
{
|
||||
"command": "frontMatter.remap",
|
||||
"title": "Front Matter: Remap tag/category in all articles"
|
||||
},
|
||||
{
|
||||
"command": "frontMatter.setDate",
|
||||
"title": "Front Matter: Set current date"
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { TaxonomyType } from "../models";
|
||||
import { CONFIG_KEY, ACTION_TAXONOMY_TAGS, ACTION_TAXONOMY_CATEGORIES, ACTION_DATE_FORMAT } from "../constants/settings";
|
||||
import { format } from "date-fns";
|
||||
import { ArticleHelper, SettingsHelper } from '../helpers';
|
||||
|
||||
|
||||
export class Article {
|
||||
|
||||
/**
|
||||
* 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 article = ArticleHelper.getFrontMatter(editor);
|
||||
if (!article) {
|
||||
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 crntOptions = SettingsHelper.getTaxonomy(type);
|
||||
if (crntOptions && crntOptions.length > 0) {
|
||||
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) {
|
||||
article.data[matterProp] = selectedOptions.map(o => o.label);
|
||||
}
|
||||
|
||||
ArticleHelper.update(editor, article);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the article date
|
||||
*/
|
||||
public static async setDate() {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const article = ArticleHelper.getFrontMatter(editor);
|
||||
if (!article) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dateFormat = config.get(ACTION_DATE_FORMAT) as string;
|
||||
try {
|
||||
if (dateFormat && typeof dateFormat === "string") {
|
||||
article.data["date"] = format(new Date(), dateFormat);
|
||||
} else {
|
||||
article.data["date"] = new Date();
|
||||
}
|
||||
|
||||
ArticleHelper.update(editor, article);
|
||||
} catch (e) {
|
||||
vscode.window.showErrorMessage(`Front Matter: Something failed while parsing the date format. Check your "${CONFIG_KEY}${ACTION_DATE_FORMAT}" setting.`);
|
||||
console.log(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the page its draft mode
|
||||
*/
|
||||
public static async toggleDraft() {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
const article = ArticleHelper.getFrontMatter(editor);
|
||||
if (!article) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newDraftStatus = !article.data["draft"];
|
||||
article.data["draft"] = newDraftStatus;
|
||||
ArticleHelper.update(editor, article);
|
||||
}
|
||||
}
|
||||
@@ -1,311 +0,0 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { TaxonomyType } from "../models";
|
||||
import { CONFIG_KEY, ACTION_TAXONOMY_TAGS, ACTION_TAXONOMY_CATEGORIES, ACTION_DATE_FORMAT } from "../constants/settings";
|
||||
import * as matter from "gray-matter";
|
||||
import { format } from "date-fns";
|
||||
|
||||
|
||||
export class FrontMatter {
|
||||
|
||||
/**
|
||||
* 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 article = this.getArticleData(editor);
|
||||
if (!article) {
|
||||
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) {
|
||||
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) {
|
||||
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;
|
||||
let options = config.get(configSetting) as string[];
|
||||
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 article = this.getArticleData(editor);
|
||||
if (!article) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the tags/categories front matter to the user settings
|
||||
*/
|
||||
public static async export() {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
|
||||
// Retrieve all the Markdown files
|
||||
const mdFiles = await vscode.workspace.findFiles('**/*.md', "**/node_modules/**");
|
||||
const markdownFiles = await vscode.workspace.findFiles('**/*.markdown', "**/node_modules/**");
|
||||
if (!mdFiles && !markdownFiles) {
|
||||
vscode.window.showInformationMessage(`No MD files found.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const allMdFiles = mdFiles.concat(markdownFiles);
|
||||
|
||||
vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: `Front Matter: exporting tags and categories`,
|
||||
cancellable: false
|
||||
}, async (progress) => {
|
||||
// Fetching all tags and categories from MD files
|
||||
let tags: string[] = [];
|
||||
let categories: string[] = [];
|
||||
|
||||
// Set the initial progress
|
||||
const progressNr = allMdFiles.length/100;
|
||||
progress.report({ increment: 0});
|
||||
|
||||
let i = 0;
|
||||
for (const file of allMdFiles) {
|
||||
progress.report({ increment: (++i/progressNr) });
|
||||
const mdFile = await vscode.workspace.openTextDocument(file);
|
||||
if (mdFile) {
|
||||
const txtData = mdFile.getText();
|
||||
if (txtData) {
|
||||
try {
|
||||
const article = matter(txtData);
|
||||
if (article && article.data) {
|
||||
const { data } = article;
|
||||
const mdTags = data["tags"];
|
||||
const mdCategories = data["categories"];
|
||||
if (mdTags) {
|
||||
tags = [...tags, ...mdTags];
|
||||
}
|
||||
if (mdCategories) {
|
||||
categories = [...categories, ...mdCategories];
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Continue with the next file
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the currently known tags, and add the new ones
|
||||
let crntTags: string[] = config.get(ACTION_TAXONOMY_TAGS) as string[];
|
||||
if (!crntTags) { crntTags = []; }
|
||||
crntTags = [...crntTags, ...tags];
|
||||
// Update the tags and filter out the duplicates
|
||||
crntTags = [...new Set(crntTags)];
|
||||
crntTags = crntTags.sort();
|
||||
config.update(ACTION_TAXONOMY_TAGS, crntTags);
|
||||
|
||||
// Retrieve the currently known tags, and add the new ones
|
||||
let crntCategories: string[] = config.get(ACTION_TAXONOMY_CATEGORIES) as string[];
|
||||
if (!crntCategories) { crntCategories = []; }
|
||||
crntCategories = [...crntCategories, ...categories];
|
||||
// Update the categories and filter out the duplicates
|
||||
crntCategories = [...new Set(crntCategories)];
|
||||
crntCategories = crntCategories.sort();
|
||||
config.update(ACTION_TAXONOMY_CATEGORIES, crntCategories);
|
||||
|
||||
// Done
|
||||
vscode.window.showInformationMessage(`Front Matter: export completed. Tags: ${crntTags.length} - Categories: ${crntCategories.length}.`);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the article date
|
||||
*/
|
||||
public static async setDate() {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const article = this.getArticleData(editor);
|
||||
if (!article) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dateFormat = config.get(ACTION_DATE_FORMAT) as string;
|
||||
try {
|
||||
if (dateFormat && typeof dateFormat === "string") {
|
||||
article.data["date"] = format(new Date(), dateFormat);
|
||||
} else {
|
||||
article.data["date"] = new Date();
|
||||
}
|
||||
|
||||
this.updatePage(editor, article);
|
||||
} catch (e) {
|
||||
vscode.window.showErrorMessage(`Front Matter: Something failed while parsing the date format. Check your "${CONFIG_KEY}${ACTION_DATE_FORMAT}" setting.`);
|
||||
console.log(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the text of the status bar
|
||||
*
|
||||
* @param frontMatterStatusBar
|
||||
*/
|
||||
public static async showDraftStatus(frontMatterSB: vscode.StatusBarItem) {
|
||||
const draftMsg = "in draft";
|
||||
const publishMsg = "to publish";
|
||||
|
||||
let editor = vscode.window.activeTextEditor;
|
||||
if (editor && editor.document && editor.document.languageId.toLowerCase() === "markdown") {
|
||||
try {
|
||||
const article = this.getArticleData(editor);
|
||||
if (article && typeof article.data["draft"] !== "undefined") {
|
||||
console.log(`Draft status: ${article.data["draft"]}`);
|
||||
if (article.data["draft"] === true) {
|
||||
frontMatterSB.text = `$(book) ${draftMsg}`;
|
||||
frontMatterSB.show();
|
||||
} else if (article.data["draft"] === false) {
|
||||
frontMatterSB.text = `$(book) ${publishMsg}`;
|
||||
frontMatterSB.show();
|
||||
}
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
frontMatterSB.hide();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the page its draft mode
|
||||
*/
|
||||
public static async toggleDraft() {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
const article = this.getArticleData(editor);
|
||||
if (!article) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newDraftStatus = !article.data["draft"];
|
||||
article.data["draft"] = newDraftStatus;
|
||||
this.updatePage(editor, article);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contents of the current article
|
||||
*
|
||||
* @param editor
|
||||
*/
|
||||
private static getArticleData(editor: vscode.TextEditor) {
|
||||
const article = matter(editor.document.getText());
|
||||
if (article && article.data) {
|
||||
return article;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the new information in the file
|
||||
*
|
||||
* @param editor
|
||||
* @param article
|
||||
*/
|
||||
private static async updatePage(editor: vscode.TextEditor, article: matter.GrayMatterFile<string>) {
|
||||
const newMarkdown = matter.stringify(article.content, article.data);
|
||||
const nrOfLines = editor.document.lineCount as number;
|
||||
await editor.edit(builder => builder.replace(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(nrOfLines, 0)), newMarkdown));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as matter from 'gray-matter';
|
||||
import * as fs from 'fs';
|
||||
import { TaxonomyType } from "../models";
|
||||
import { CONFIG_KEY, ACTION_TAXONOMY_TAGS, ACTION_TAXONOMY_CATEGORIES } from '../constants';
|
||||
import { ArticleHelper, SettingsHelper, FilesHelper } from '../helpers';
|
||||
|
||||
export class Settings {
|
||||
|
||||
/**
|
||||
* 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;
|
||||
let options = config.get(configSetting) as string[];
|
||||
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);
|
||||
await SettingsHelper.update(type, 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 article = ArticleHelper.getFrontMatter(editor);
|
||||
if (!article) {
|
||||
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];
|
||||
}
|
||||
|
||||
ArticleHelper.update(editor, article);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Export the tags/categories front matter to the user settings
|
||||
*/
|
||||
public static async export() {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
|
||||
// Retrieve all the Markdown files
|
||||
const allMdFiles = await FilesHelper.getMdFiles();
|
||||
if (!allMdFiles) {
|
||||
return;
|
||||
}
|
||||
|
||||
vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: `Front Matter: exporting tags and categories`,
|
||||
cancellable: false
|
||||
}, async (progress) => {
|
||||
// Fetching all tags and categories from MD files
|
||||
let tags: string[] = [];
|
||||
let categories: string[] = [];
|
||||
|
||||
// Set the initial progress
|
||||
const progressNr = allMdFiles.length/100;
|
||||
progress.report({ increment: 0});
|
||||
|
||||
let i = 0;
|
||||
for (const file of allMdFiles) {
|
||||
progress.report({ increment: (++i/progressNr) });
|
||||
const mdFile = await vscode.workspace.openTextDocument(file);
|
||||
if (mdFile) {
|
||||
const txtData = mdFile.getText();
|
||||
if (txtData) {
|
||||
try {
|
||||
const article = matter(txtData);
|
||||
if (article && article.data) {
|
||||
const { data } = article;
|
||||
const mdTags = data["tags"];
|
||||
const mdCategories = data["categories"];
|
||||
if (mdTags) {
|
||||
tags = [...tags, ...mdTags];
|
||||
}
|
||||
if (mdCategories) {
|
||||
categories = [...categories, ...mdCategories];
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Continue with the next file
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the currently known tags, and add the new ones
|
||||
let crntTags: string[] = config.get(ACTION_TAXONOMY_TAGS) as string[];
|
||||
if (!crntTags) { crntTags = []; }
|
||||
crntTags = [...crntTags, ...tags];
|
||||
// Update the tags and filter out the duplicates
|
||||
crntTags = [...new Set(crntTags)];
|
||||
crntTags = crntTags.sort();
|
||||
await config.update(ACTION_TAXONOMY_TAGS, crntTags);
|
||||
|
||||
// Retrieve the currently known tags, and add the new ones
|
||||
let crntCategories: string[] = config.get(ACTION_TAXONOMY_CATEGORIES) as string[];
|
||||
if (!crntCategories) { crntCategories = []; }
|
||||
crntCategories = [...crntCategories, ...categories];
|
||||
// Update the categories and filter out the duplicates
|
||||
crntCategories = [...new Set(crntCategories)];
|
||||
crntCategories = crntCategories.sort();
|
||||
await config.update(ACTION_TAXONOMY_CATEGORIES, crntCategories);
|
||||
|
||||
// Done
|
||||
vscode.window.showInformationMessage(`Front Matter: export completed. Tags: ${crntTags.length} - Categories: ${crntCategories.length}.`);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remap a tag or category to a new one
|
||||
*/
|
||||
public static async remap() {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
|
||||
const taxType = await vscode.window.showQuickPick([
|
||||
"Tag",
|
||||
"Category"
|
||||
], {
|
||||
placeHolder: `What do you want to remap?`,
|
||||
canPickMany: false
|
||||
});
|
||||
if (!taxType) {
|
||||
return;
|
||||
}
|
||||
|
||||
const type = taxType === "Tag" ? TaxonomyType.Tag : TaxonomyType.Category;
|
||||
const options = SettingsHelper.getTaxonomy(type);
|
||||
|
||||
if (!options || options.length === 0) {
|
||||
vscode.window.showInformationMessage(`No ${type === TaxonomyType.Tag ? "tags" : "categories"} configured.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedOption = await vscode.window.showQuickPick(options, {
|
||||
placeHolder: `Select your ${type === TaxonomyType.Tag ? "tags" : "categories"} to insert`,
|
||||
canPickMany: false
|
||||
});
|
||||
|
||||
if (!selectedOption) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newOptionValue = await vscode.window.showInputBox({
|
||||
prompt: `Insert the value of the ${type === TaxonomyType.Tag ? "tag" : "category"} with which you want to remap "${selectedOption}".`,
|
||||
placeHolder: `Name of the ${type === TaxonomyType.Tag ? "tag" : "category"}`
|
||||
});
|
||||
|
||||
if (!newOptionValue) {
|
||||
vscode.window.showInformationMessage(`You didn't provide a new value.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve all the markdown files
|
||||
const allMdFiles = await FilesHelper.getMdFiles();
|
||||
if (!allMdFiles) {
|
||||
return;
|
||||
}
|
||||
|
||||
vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: `Front Matter: remapping "${selectedOption}" ${type === TaxonomyType.Tag ? "tag" : "category"} to "${newOptionValue}".`,
|
||||
cancellable: false
|
||||
}, async (progress) => {
|
||||
// Set the initial progress
|
||||
const progressNr = allMdFiles.length/100;
|
||||
progress.report({ increment: 0});
|
||||
|
||||
const matterProp: string = type === TaxonomyType.Tag ? "tags" : "categories";
|
||||
|
||||
let i = 0;
|
||||
for (const file of allMdFiles) {
|
||||
progress.report({ increment: (++i/progressNr) });
|
||||
const mdFile = await vscode.workspace.openTextDocument(file);
|
||||
if (mdFile) {
|
||||
const txtData = mdFile.getText();
|
||||
if (txtData) {
|
||||
try {
|
||||
const article = matter(txtData);
|
||||
if (article && article.data) {
|
||||
const { data } = article;
|
||||
const options: string[] = data[matterProp];
|
||||
if (options && options.length > 0) {
|
||||
const idx = options.findIndex(o => o === selectedOption);
|
||||
if (idx !== -1) {
|
||||
options[idx] = newOptionValue;
|
||||
data[matterProp] = [...new Set(options)].sort();
|
||||
|
||||
// Update the file
|
||||
fs.writeFileSync(mdFile.fileName, matter.stringify(article.content, article.data), { encoding: "utf8" });
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Continue with the next file
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the settings
|
||||
const idx = options.findIndex(o => o === selectedOption);
|
||||
if (idx !== -1) {
|
||||
options[idx] = newOptionValue;
|
||||
} else {
|
||||
options.push(newOptionValue);
|
||||
}
|
||||
await SettingsHelper.update(type, options);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { ArticleHelper } from '../helpers';
|
||||
|
||||
export class StatusBar {
|
||||
|
||||
/**
|
||||
* Update the text of the status bar
|
||||
*
|
||||
* @param frontMatterStatusBar
|
||||
*/
|
||||
public static async showDraftStatus(frontMatterSB: vscode.StatusBarItem) {
|
||||
const draftMsg = "in draft";
|
||||
const publishMsg = "to publish";
|
||||
|
||||
let editor = vscode.window.activeTextEditor;
|
||||
if (editor && editor.document && editor.document.languageId.toLowerCase() === "markdown") {
|
||||
try {
|
||||
const article = ArticleHelper.getFrontMatter(editor);
|
||||
if (article && typeof article.data["draft"] !== "undefined") {
|
||||
console.log(`Draft status: ${article.data["draft"]}`);
|
||||
if (article.data["draft"] === true) {
|
||||
frontMatterSB.text = `$(book) ${draftMsg}`;
|
||||
frontMatterSB.show();
|
||||
} else if (article.data["draft"] === false) {
|
||||
frontMatterSB.text = `$(book) ${publishMsg}`;
|
||||
frontMatterSB.show();
|
||||
}
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
frontMatterSB.hide();
|
||||
}
|
||||
}
|
||||
@@ -1 +1,3 @@
|
||||
export * from './FrontMatter';
|
||||
export * from './Article';
|
||||
export * from './Settings';
|
||||
export * from './StatusBar';
|
||||
|
||||
+14
-9
@@ -1,5 +1,5 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { FrontMatter } from './commands';
|
||||
import { Article, Settings, StatusBar } from './commands';
|
||||
import { TaxonomyType } from './models';
|
||||
|
||||
let frontMatterStatusBar: vscode.StatusBarItem;
|
||||
@@ -8,32 +8,36 @@ let debouncer: { (fnc: any, time: number): void; };
|
||||
export function activate({ subscriptions }: vscode.ExtensionContext) {
|
||||
|
||||
let insertTags = vscode.commands.registerCommand('frontMatter.insertTags', () => {
|
||||
FrontMatter.insert(TaxonomyType.Tag);
|
||||
Article.insert(TaxonomyType.Tag);
|
||||
});
|
||||
|
||||
let insertCategories = vscode.commands.registerCommand('frontMatter.insertCategories', () => {
|
||||
FrontMatter.insert(TaxonomyType.Category);
|
||||
Article.insert(TaxonomyType.Category);
|
||||
});
|
||||
|
||||
let createTag = vscode.commands.registerCommand('frontMatter.createTag', () => {
|
||||
FrontMatter.create(TaxonomyType.Tag);
|
||||
Settings.create(TaxonomyType.Tag);
|
||||
});
|
||||
|
||||
let createCategory = vscode.commands.registerCommand('frontMatter.createCategory', () => {
|
||||
FrontMatter.create(TaxonomyType.Category);
|
||||
Settings.create(TaxonomyType.Category);
|
||||
});
|
||||
|
||||
let exportTaxonomy = vscode.commands.registerCommand('frontMatter.exportTaxonomy', () => {
|
||||
FrontMatter.export();
|
||||
Settings.export();
|
||||
});
|
||||
|
||||
let remap = vscode.commands.registerCommand('frontMatter.remap', () => {
|
||||
Settings.remap();
|
||||
});
|
||||
|
||||
let setDate = vscode.commands.registerCommand('frontMatter.setDate', () => {
|
||||
FrontMatter.setDate();
|
||||
Article.setDate();
|
||||
});
|
||||
|
||||
const toggleDraftCommand = 'frontMatter.toggleDraft';
|
||||
const toggleDraft = vscode.commands.registerCommand(toggleDraftCommand, async () => {
|
||||
await FrontMatter.toggleDraft();
|
||||
await Article.toggleDraft();
|
||||
triggerShowDraftStatus();
|
||||
});
|
||||
|
||||
@@ -54,6 +58,7 @@ export function activate({ subscriptions }: vscode.ExtensionContext) {
|
||||
subscriptions.push(createTag);
|
||||
subscriptions.push(createCategory);
|
||||
subscriptions.push(exportTaxonomy);
|
||||
subscriptions.push(remap);
|
||||
subscriptions.push(setDate);
|
||||
subscriptions.push(toggleDraft);
|
||||
}
|
||||
@@ -61,7 +66,7 @@ export function activate({ subscriptions }: vscode.ExtensionContext) {
|
||||
export function deactivate() {}
|
||||
|
||||
const triggerShowDraftStatus = () => {
|
||||
debouncer(() => { FrontMatter.showDraftStatus(frontMatterStatusBar); }, 1000);
|
||||
debouncer(() => { StatusBar.showDraftStatus(frontMatterStatusBar); }, 1000);
|
||||
};
|
||||
|
||||
const debounceShowDraftTrigger = () => {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as matter from "gray-matter";
|
||||
|
||||
export class ArticleHelper {
|
||||
|
||||
/**
|
||||
* Get the contents of the current article
|
||||
*
|
||||
* @param editor
|
||||
*/
|
||||
public static getFrontMatter(editor: vscode.TextEditor) {
|
||||
const article = matter(editor.document.getText());
|
||||
if (article && article.data) {
|
||||
return article;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the new information in the file
|
||||
*
|
||||
* @param editor
|
||||
* @param article
|
||||
*/
|
||||
public static async update(editor: vscode.TextEditor, article: matter.GrayMatterFile<string>) {
|
||||
const newMarkdown = matter.stringify(article.content, article.data);
|
||||
const nrOfLines = editor.document.lineCount as number;
|
||||
await editor.edit(builder => builder.replace(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(nrOfLines, 0)), newMarkdown));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export class FilesHelper {
|
||||
|
||||
/**
|
||||
* Retrieve all markdown files from the current project
|
||||
*/
|
||||
public static async getMdFiles(): Promise<vscode.Uri[] | null> {
|
||||
const mdFiles = await vscode.workspace.findFiles('**/*.md', "**/node_modules/**");
|
||||
const markdownFiles = await vscode.workspace.findFiles('**/*.markdown', "**/node_modules/**");
|
||||
if (!mdFiles && !markdownFiles) {
|
||||
vscode.window.showInformationMessage(`No MD files found.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const allMdFiles = mdFiles.concat(markdownFiles);
|
||||
return allMdFiles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { TaxonomyType } from '../models';
|
||||
import { ACTION_TAXONOMY_TAGS, ACTION_TAXONOMY_CATEGORIES, CONFIG_KEY } from '../constants';
|
||||
|
||||
export class SettingsHelper {
|
||||
|
||||
/**
|
||||
* Return the taxonomy settings
|
||||
*
|
||||
* @param type
|
||||
*/
|
||||
public static getTaxonomy(type: TaxonomyType) {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
// 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) {
|
||||
return crntOptions;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the taxonomy settings
|
||||
*
|
||||
* @param config
|
||||
* @param type
|
||||
* @param options
|
||||
*/
|
||||
static async update(type: TaxonomyType, options: string[]) {
|
||||
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
|
||||
const configSetting = type === TaxonomyType.Tag ? ACTION_TAXONOMY_TAGS : ACTION_TAXONOMY_CATEGORIES;
|
||||
options = [...new Set(options)];
|
||||
options = options.sort();
|
||||
await config.update(configSetting, options);
|
||||
}
|
||||
}
|
||||
@@ -1 +1,4 @@
|
||||
export * from './ArticleHelper';
|
||||
export * from './FilesHelper';
|
||||
export * from './SettingsHelper';
|
||||
export * from './StringHelpers';
|
||||
|
||||
Reference in New Issue
Block a user