mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-03-28 17:42:40 +01:00
#352 - Custom placeholders now support scripting
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
### 🎨 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
|
||||
- [#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
|
||||
|
||||
@@ -2,7 +2,7 @@ import { DEFAULT_CONTENT_TYPE } from './../constants/ContentType';
|
||||
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 * as vscode from 'vscode';
|
||||
import { Field, TaxonomyType } from "../models";
|
||||
import { CustomPlaceholder, Field, TaxonomyType } from "../models";
|
||||
import { format } from "date-fns";
|
||||
import { ArticleHelper, Settings, SlugHelper } from '../helpers';
|
||||
import { Notifications } from '../helpers/Notifications';
|
||||
@@ -225,8 +225,8 @@ export class Article {
|
||||
}
|
||||
|
||||
// Update the fields containing a custom placeholder that depends on slug
|
||||
const placeholders = Settings.get<{id: string, value: string}[]>(SETTING_CONTENT_PLACEHOLDERS);
|
||||
const customPlaceholders = placeholders?.filter(p => p.value.includes("{{slug}}"));
|
||||
const placeholders = Settings.get<CustomPlaceholder[]>(SETTING_CONTENT_PLACEHOLDERS);
|
||||
const customPlaceholders = placeholders?.filter(p => p.value && p.value.includes("{{slug}}"));
|
||||
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
|
||||
for (const customPlaceholder of (customPlaceholders || [])) {
|
||||
const customPlaceholderFields = contentType.fields.filter(f => f.default === `{{${customPlaceholder.id}}}`);
|
||||
|
||||
@@ -175,7 +175,7 @@ export class Template {
|
||||
}
|
||||
|
||||
if (frontMatter.data) {
|
||||
frontMatter.data = ArticleHelper.updatePlaceholders(frontMatter.data, titleValue);
|
||||
frontMatter.data = await ArticleHelper.updatePlaceholders(frontMatter.data, titleValue, newFilePath);
|
||||
|
||||
frontMatter = Article.updateDate(frontMatter);
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { CustomPlaceholder } from './../models/CustomPlaceholder';
|
||||
import { Uri, workspace } from 'vscode';
|
||||
import { MarkdownFoldingProvider } from './../providers/MarkdownFoldingProvider';
|
||||
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 { Content } from 'mdast';
|
||||
import { processKnownPlaceholders } from './PlaceholderHelper';
|
||||
import { CustomScript } from './CustomScript';
|
||||
import { Folders } from '../commands/Folders';
|
||||
|
||||
export class ArticleHelper {
|
||||
private static notifiedFiles: string[] = [];
|
||||
@@ -368,7 +371,7 @@ export class ArticleHelper {
|
||||
* @param title
|
||||
* @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 fmData = Object.assign({}, data);
|
||||
|
||||
@@ -384,7 +387,7 @@ export class ArticleHelper {
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -396,16 +399,44 @@ export class ArticleHelper {
|
||||
* @param title
|
||||
* @returns
|
||||
*/
|
||||
public static processCustomPlaceholders(value: string, title: string) {
|
||||
public static async processCustomPlaceholders(value: string, title: string, filePath: string) {
|
||||
if (value && typeof value === "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) {
|
||||
for (const placeholder of placeholders) {
|
||||
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 updatedValue = processKnownPlaceholders(placeholder.value, title, dateFormat);
|
||||
value = value.replace(regex, updatedValue);
|
||||
const updatedValue = processKnownPlaceholders(placeHolderValue, title, dateFormat);
|
||||
|
||||
if (value === `{{${placeholder.id}}}`) {
|
||||
value = updatedValue;
|
||||
} else {
|
||||
value = value.replace(regex, updatedValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -553,7 +553,7 @@ export class ContentType {
|
||||
* @param contentType
|
||||
* @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) {
|
||||
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
|
||||
@@ -561,19 +561,19 @@ export class ContentType {
|
||||
if (field.name === "title") {
|
||||
if (field.default) {
|
||||
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 {
|
||||
data[field.name] = titleValue;
|
||||
}
|
||||
} else {
|
||||
if (field.type === "fields") {
|
||||
data[field.name] = this.processFields(field, titleValue, {});
|
||||
data[field.name] = await this.processFields(field, titleValue, {}, filePath);
|
||||
} else {
|
||||
const defaultValue = field.default;
|
||||
|
||||
if (typeof defaultValue === "string") {
|
||||
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 {
|
||||
data[field.name] = typeof defaultValue !== "undefined" ? defaultValue : "";
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ export class CustomScript {
|
||||
* @param args
|
||||
* @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) => {
|
||||
|
||||
// Check the command to use
|
||||
@@ -264,6 +264,11 @@ export class CustomScript {
|
||||
reject(error.message);
|
||||
}
|
||||
|
||||
if (stdout && stdout.endsWith(`\n`)) {
|
||||
// Remove empty line at the end of the string
|
||||
stdout = stdout.slice(0, -1);
|
||||
}
|
||||
|
||||
resolve(stdout);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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) {
|
||||
const crntFile = window.activeTextEditor?.document;
|
||||
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
|
||||
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 });
|
||||
|
||||
6
src/models/CustomPlaceholder.ts
Normal file
6
src/models/CustomPlaceholder.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export interface CustomPlaceholder {
|
||||
id: string;
|
||||
value?: string;
|
||||
script?: string;
|
||||
command?: string
|
||||
}
|
||||
@@ -118,7 +118,7 @@ export interface CustomScript {
|
||||
output?: "notification" | "editor";
|
||||
outputType?: string;
|
||||
type?: ScriptType;
|
||||
command?: CommandType;
|
||||
command?: CommandType | string;
|
||||
}
|
||||
|
||||
export interface PreviewSettings {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export * from './BlockFieldData';
|
||||
export * from './Choice';
|
||||
export * from './ContentFolder';
|
||||
export * from './CustomPlaceholder';
|
||||
export * from './CustomTaxonomyData';
|
||||
export * from './DashboardData';
|
||||
export * from './DataFile';
|
||||
|
||||
Reference in New Issue
Block a user