#352 - Custom placeholders now support scripting

This commit is contained in:
Elio Struyf
2022-07-21 18:38:53 +03:00
parent 9445ce6d37
commit 7badfda41b
10 changed files with 70 additions and 19 deletions
+1
View File
@@ -4,6 +4,7 @@
### 🎨 Enhancements ### 🎨 Enhancements
- [#352](https://github.com/estruyf/vscode-front-matter/issues/352): Custom placeholders now support scripting
- [#370](https://github.com/estruyf/vscode-front-matter/issues/370): Define the tags and categories as reserved keywords for custom taxonomy - [#370](https://github.com/estruyf/vscode-front-matter/issues/370): Define the tags and categories as reserved keywords for custom taxonomy
- [#372](https://github.com/estruyf/vscode-front-matter/issues/372): Rename Taxonomy tab to Taxonomies - [#372](https://github.com/estruyf/vscode-front-matter/issues/372): Rename Taxonomy tab to Taxonomies
- [#374](https://github.com/estruyf/vscode-front-matter/issues/374): Hide the front matter section to use the panel instead - [#374](https://github.com/estruyf/vscode-front-matter/issues/374): Hide the front matter section to use the panel instead
+3 -3
View File
@@ -2,7 +2,7 @@ import { DEFAULT_CONTENT_TYPE } from './../constants/ContentType';
import { isValidFile } from './../helpers/isValidFile'; import { isValidFile } from './../helpers/isValidFile';
import { SETTING_AUTO_UPDATE_DATE, SETTING_MODIFIED_FIELD, SETTING_SLUG_UPDATE_FILE_NAME, SETTING_TEMPLATES_PREFIX, CONFIG_KEY, SETTING_DATE_FORMAT, SETTING_SLUG_PREFIX, SETTING_SLUG_SUFFIX, SETTING_CONTENT_PLACEHOLDERS, TelemetryEvent } from './../constants'; import { SETTING_AUTO_UPDATE_DATE, SETTING_MODIFIED_FIELD, SETTING_SLUG_UPDATE_FILE_NAME, SETTING_TEMPLATES_PREFIX, CONFIG_KEY, SETTING_DATE_FORMAT, SETTING_SLUG_PREFIX, SETTING_SLUG_SUFFIX, SETTING_CONTENT_PLACEHOLDERS, TelemetryEvent } from './../constants';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { Field, TaxonomyType } from "../models"; import { CustomPlaceholder, Field, TaxonomyType } from "../models";
import { format } from "date-fns"; import { format } from "date-fns";
import { ArticleHelper, Settings, SlugHelper } from '../helpers'; import { ArticleHelper, Settings, SlugHelper } from '../helpers';
import { Notifications } from '../helpers/Notifications'; import { Notifications } from '../helpers/Notifications';
@@ -225,8 +225,8 @@ export class Article {
} }
// Update the fields containing a custom placeholder that depends on slug // Update the fields containing a custom placeholder that depends on slug
const placeholders = Settings.get<{id: string, value: string}[]>(SETTING_CONTENT_PLACEHOLDERS); const placeholders = Settings.get<CustomPlaceholder[]>(SETTING_CONTENT_PLACEHOLDERS);
const customPlaceholders = placeholders?.filter(p => p.value.includes("{{slug}}")); const customPlaceholders = placeholders?.filter(p => p.value && p.value.includes("{{slug}}"));
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string; const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
for (const customPlaceholder of (customPlaceholders || [])) { for (const customPlaceholder of (customPlaceholders || [])) {
const customPlaceholderFields = contentType.fields.filter(f => f.default === `{{${customPlaceholder.id}}}`); const customPlaceholderFields = contentType.fields.filter(f => f.default === `{{${customPlaceholder.id}}}`);
+1 -1
View File
@@ -175,7 +175,7 @@ export class Template {
} }
if (frontMatter.data) { if (frontMatter.data) {
frontMatter.data = ArticleHelper.updatePlaceholders(frontMatter.data, titleValue); frontMatter.data = await ArticleHelper.updatePlaceholders(frontMatter.data, titleValue, newFilePath);
frontMatter = Article.updateDate(frontMatter); frontMatter = Article.updateDate(frontMatter);
+37 -6
View File
@@ -1,3 +1,4 @@
import { CustomPlaceholder } from './../models/CustomPlaceholder';
import { Uri, workspace } from 'vscode'; import { Uri, workspace } from 'vscode';
import { MarkdownFoldingProvider } from './../providers/MarkdownFoldingProvider'; import { MarkdownFoldingProvider } from './../providers/MarkdownFoldingProvider';
import { DEFAULT_CONTENT_TYPE, DEFAULT_CONTENT_TYPE_NAME } from './../constants/ContentType'; import { DEFAULT_CONTENT_TYPE, DEFAULT_CONTENT_TYPE_NAME } from './../constants/ContentType';
@@ -22,6 +23,8 @@ import { fromMarkdown } from 'mdast-util-from-markdown';
import { Link, Parent } from 'mdast-util-from-markdown/lib'; import { Link, Parent } from 'mdast-util-from-markdown/lib';
import { Content } from 'mdast'; import { Content } from 'mdast';
import { processKnownPlaceholders } from './PlaceholderHelper'; import { processKnownPlaceholders } from './PlaceholderHelper';
import { CustomScript } from './CustomScript';
import { Folders } from '../commands/Folders';
export class ArticleHelper { export class ArticleHelper {
private static notifiedFiles: string[] = []; private static notifiedFiles: string[] = [];
@@ -368,7 +371,7 @@ export class ArticleHelper {
* @param title * @param title
* @returns * @returns
*/ */
public static updatePlaceholders(data: any, title: string) { public static async updatePlaceholders(data: any, title: string, filePath: string) {
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string; const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
const fmData = Object.assign({}, data); const fmData = Object.assign({}, data);
@@ -384,7 +387,7 @@ export class ArticleHelper {
} }
fmData[fieldName] = processKnownPlaceholders(fmData[fieldName], title, dateFormat); fmData[fieldName] = processKnownPlaceholders(fmData[fieldName], title, dateFormat);
fmData[fieldName] = this.processCustomPlaceholders(fmData[fieldName], title); fmData[fieldName] = await this.processCustomPlaceholders(fmData[fieldName], title, filePath);
} }
return fmData; return fmData;
@@ -396,16 +399,44 @@ export class ArticleHelper {
* @param title * @param title
* @returns * @returns
*/ */
public static processCustomPlaceholders(value: string, title: string) { public static async processCustomPlaceholders(value: string, title: string, filePath: string) {
if (value && typeof value === "string") { if (value && typeof value === "string") {
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string; const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
const placeholders = Settings.get<{id: string, value: string}[]>(SETTING_CONTENT_PLACEHOLDERS); const placeholders = Settings.get<CustomPlaceholder[]>(SETTING_CONTENT_PLACEHOLDERS);
if (placeholders && placeholders.length > 0) { if (placeholders && placeholders.length > 0) {
for (const placeholder of placeholders) { for (const placeholder of placeholders) {
if (value.includes(`{{${placeholder.id}}}`)) { if (value.includes(`{{${placeholder.id}}}`)) {
let placeHolderValue = placeholder.value || "";
if (placeholder.script) {
const wsFolder = Folders.getWorkspaceFolder();
const script = { title: placeholder.id, script: placeholder.script, command: placeholder.command };
let output: string | any = await CustomScript.executeScript(script, wsFolder?.fsPath || "", `'${filePath}' '${title}'`);
if (output) {
// Check if the output needs to be parsed
if (output.includes("{") && output.includes("}")) {
try {
output = JSON.parse(output);
} catch (e) {
// Do nothing
}
} else {
output = output.split("\n");
}
placeHolderValue = output;
}
}
const regex = new RegExp(`{{${placeholder.id}}}`, "g"); const regex = new RegExp(`{{${placeholder.id}}}`, "g");
const updatedValue = processKnownPlaceholders(placeholder.value, title, dateFormat); const updatedValue = processKnownPlaceholders(placeHolderValue, title, dateFormat);
value = value.replace(regex, updatedValue);
if (value === `{{${placeholder.id}}}`) {
value = updatedValue;
} else {
value = value.replace(regex, updatedValue);
}
} }
} }
} }
+5 -5
View File
@@ -526,7 +526,7 @@ export class ContentType {
} }
} }
let data: any = this.processFields(contentType, titleValue, templateData?.data || {}); let data: any = await this.processFields(contentType, titleValue, templateData?.data || {}, newFilePath);
data = ArticleHelper.updateDates(Object.assign({}, data)); data = ArticleHelper.updateDates(Object.assign({}, data));
@@ -553,7 +553,7 @@ export class ContentType {
* @param contentType * @param contentType
* @param data * @param data
*/ */
private static processFields(obj: IContentType | Field, titleValue: string, data: any) { private static async processFields(obj: IContentType | Field, titleValue: string, data: any, filePath: string) {
if (obj.fields) { if (obj.fields) {
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string; const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
@@ -561,19 +561,19 @@ export class ContentType {
if (field.name === "title") { if (field.name === "title") {
if (field.default) { if (field.default) {
data[field.name] = processKnownPlaceholders(field.default, titleValue, dateFormat); data[field.name] = processKnownPlaceholders(field.default, titleValue, dateFormat);
data[field.name] = ArticleHelper.processCustomPlaceholders(data[field.name], titleValue); data[field.name] = await ArticleHelper.processCustomPlaceholders(data[field.name], titleValue, filePath);
} else { } else {
data[field.name] = titleValue; data[field.name] = titleValue;
} }
} else { } else {
if (field.type === "fields") { if (field.type === "fields") {
data[field.name] = this.processFields(field, titleValue, {}); data[field.name] = await this.processFields(field, titleValue, {}, filePath);
} else { } else {
const defaultValue = field.default; const defaultValue = field.default;
if (typeof defaultValue === "string") { if (typeof defaultValue === "string") {
data[field.name] = processKnownPlaceholders(defaultValue, titleValue, dateFormat); data[field.name] = processKnownPlaceholders(defaultValue, titleValue, dateFormat);
data[field.name] = ArticleHelper.processCustomPlaceholders(data[field.name], titleValue); data[field.name] = await ArticleHelper.processCustomPlaceholders(data[field.name], titleValue, filePath);
} else { } else {
data[field.name] = typeof defaultValue !== "undefined" ? defaultValue : ""; data[field.name] = typeof defaultValue !== "undefined" ? defaultValue : "";
} }
+6 -1
View File
@@ -246,7 +246,7 @@ export class CustomScript {
* @param args * @param args
* @returns * @returns
*/ */
private static async executeScript(script: ICustomScript, wsPath: string, args: string): Promise<string> { public static async executeScript(script: ICustomScript, wsPath: string, args: string): Promise<string> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Check the command to use // Check the command to use
@@ -264,6 +264,11 @@ export class CustomScript {
reject(error.message); reject(error.message);
} }
if (stdout && stdout.endsWith(`\n`)) {
// Remove empty line at the end of the string
stdout = stdout.slice(0, -1);
}
resolve(stdout); resolve(stdout);
}); });
}); });
+9 -2
View File
@@ -322,11 +322,18 @@ export class DataListener extends BaseListener {
} }
} }
private static updatePlaceholder(field: string, value: string, title: string) { /**
* Update the placeholder
* @param field
* @param value
* @param title
*/
private static async updatePlaceholder(field: string, value: string, title: string) {
if (field && value) { if (field && value) {
const crntFile = window.activeTextEditor?.document;
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string; const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
value = processKnownPlaceholders(value, title || "", dateFormat); value = processKnownPlaceholders(value, title || "", dateFormat);
value = ArticleHelper.processCustomPlaceholders(value, title || ""); value = await ArticleHelper.processCustomPlaceholders(value, title || "", crntFile?.uri.fsPath || "");
} }
this.sendMsg(Command.updatePlaceholder, { field, value }); this.sendMsg(Command.updatePlaceholder, { field, value });
+6
View File
@@ -0,0 +1,6 @@
export interface CustomPlaceholder {
id: string;
value?: string;
script?: string;
command?: string
}
+1 -1
View File
@@ -118,7 +118,7 @@ export interface CustomScript {
output?: "notification" | "editor"; output?: "notification" | "editor";
outputType?: string; outputType?: string;
type?: ScriptType; type?: ScriptType;
command?: CommandType; command?: CommandType | string;
} }
export interface PreviewSettings { export interface PreviewSettings {
+1
View File
@@ -1,6 +1,7 @@
export * from './BlockFieldData'; export * from './BlockFieldData';
export * from './Choice'; export * from './Choice';
export * from './ContentFolder'; export * from './ContentFolder';
export * from './CustomPlaceholder';
export * from './CustomTaxonomyData'; export * from './CustomTaxonomyData';
export * from './DashboardData'; export * from './DashboardData';
export * from './DataFile'; export * from './DataFile';