diff --git a/package.json b/package.json index 25496260..9340119f 100644 --- a/package.json +++ b/package.json @@ -198,6 +198,30 @@ }, "scope": "Content" }, + "frontMatter.content.placeholders": { + "type": "array", + "default": [], + "markdownDescription": "This array of placeholders defines the placeholders that you can use in your content types and templates for automatically populating your content its front matter. [Check in the docs](https://frontmatter.codes/docs/settings#frontmatter.content.placeholders)", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "ID of the placeholder, in your content type or template, use it as follows: {{placeholder}}" + }, + "value": { + "type": "string", + "description": "The placeholder its value" + } + }, + "additionalProperties": false, + "required": [ + "id", + "value" + ] + }, + "scope": "Content" + }, "frontMatter.content.publicFolder": { "type": "string", "default": "", diff --git a/src/commands/Template.ts b/src/commands/Template.ts index d3e4ddc8..c63045c8 100644 --- a/src/commands/Template.ts +++ b/src/commands/Template.ts @@ -159,13 +159,7 @@ export class Template { } if (frontMatter.data) { - const fmData = frontMatter.data; - if (typeof fmData.title !== "undefined") { - fmData.title = titleValue; - } - if (typeof fmData.slug !== "undefined") { - fmData.slug = ArticleHelper.sanitize(titleValue); - } + frontMatter.data = ArticleHelper.updatePlaceholders(frontMatter.data, titleValue); frontMatter = Article.updateDate(frontMatter); diff --git a/src/constants/settings.ts b/src/constants/settings.ts index a17cbcb1..a88b8c6a 100644 --- a/src/constants/settings.ts +++ b/src/constants/settings.ts @@ -46,6 +46,7 @@ export const SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT = "content.fmHighlight"; export const SETTINGS_CONTENT_DRAFT_FIELD = "content.draftField"; export const SETTINGS_CONTENT_SORTING = "content.sorting"; export const SETTINGS_CONTENT_WYSIWYG = "content.wysiwyg"; +export const SETTINGS_CONTENT_PLACEHOLDERS = "content.placeholders"; export const SETTINGS_CONTENT_SORTING_DEFAULT = "content.defaultSorting"; export const SETTINGS_MEDIA_SORTING_DEFAULT = "content.defaultSorting"; diff --git a/src/helpers/ArticleHelper.ts b/src/helpers/ArticleHelper.ts index f8de7be8..1283dd7c 100644 --- a/src/helpers/ArticleHelper.ts +++ b/src/helpers/ArticleHelper.ts @@ -3,7 +3,7 @@ import { DEFAULT_CONTENT_TYPE, DEFAULT_CONTENT_TYPE_NAME } from './../constants/ import * as vscode from 'vscode'; import * as matter from "gray-matter"; import * as fs from "fs"; -import { DefaultFields, SETTINGS_CONTENT_DEFAULT_FILETYPE, SETTING_COMMA_SEPARATED_FIELDS, SETTING_DATE_FIELD, SETTING_DATE_FORMAT, SETTING_INDENT_ARRAY, SETTING_REMOVE_QUOTES, SETTING_TAXONOMY_CONTENT_TYPES, SETTING_TEMPLATES_PREFIX } from '../constants'; +import { DefaultFields, SETTINGS_CONTENT_DEFAULT_FILETYPE, SETTINGS_CONTENT_PLACEHOLDERS, SETTING_COMMA_SEPARATED_FIELDS, SETTING_DATE_FIELD, SETTING_DATE_FORMAT, SETTING_INDENT_ARRAY, SETTING_REMOVE_QUOTES, SETTING_TAXONOMY_CONTENT_TYPES, SETTING_TEMPLATES_PREFIX } from '../constants'; import { DumpOptions } from 'js-yaml'; import { TomlEngine, getFmLanguage, getFormatOpts } from './TomlEngine'; import { Extension, Settings } from '.'; @@ -274,6 +274,78 @@ export class ArticleHelper { return newFilePath; } + /** + * Update placeholder values in the front matter content + * @param data + * @param title + * @returns + */ + public static updatePlaceholders(data: any, title: string) { + const fmData = Object.assign({}, data); + + for (const fieldName of Object.keys(fmData)) { + const fieldValue = fmData[fieldName]; + + if (fieldName === "title" && (fieldValue === null || fieldValue === "")) { + fmData[fieldName] = title; + } + + if (fieldName === "slug" && (fieldValue === null || fieldValue === "")) { + fmData[fieldName] = ArticleHelper.sanitize(title); + } + + fmData[fieldName] = this.processKnownPlaceholders(fmData[fieldName], title); + fmData[fieldName] = this.processCustomPlaceholders(fmData[fieldName], title); + } + + return fmData; + } + + /** + * Replace the known placeholders + * @param value + * @param title + * @returns + */ + public static processKnownPlaceholders(value: string, title: string) { + if (value && typeof value === "string") { + if (value.includes("{{title}}")) { + const regex = new RegExp("{{title}}", "g"); + value = value.replace(regex, title); + } + + if (value.includes("{{slug}}")) { + const regex = new RegExp("{{slug}}", "g"); + value = value.replace(regex, ArticleHelper.sanitize(title)); + } + } + + return value; + } + + /** + * Replace the custom placeholders + * @param value + * @param title + * @returns + */ + public static processCustomPlaceholders(value: string, title: string) { + if (value && typeof value === "string") { + const placeholders = Settings.get<{id: string, value: string}[]>(SETTINGS_CONTENT_PLACEHOLDERS); + if (placeholders && placeholders.length > 0) { + for (const placeholder of placeholders) { + if (value.includes(`{{${placeholder.id}}}`)) { + const regex = new RegExp(`{{${placeholder.id}}}`, "g"); + const updatedValue = this.processKnownPlaceholders(placeholder.value, title); + value = value.replace(regex, updatedValue); + } + } + } + } + + return value; + } + /** * Parse a markdown file and its front matter * @param fileContents diff --git a/src/helpers/ContentType.ts b/src/helpers/ContentType.ts index 1a94ea63..d9447e24 100644 --- a/src/helpers/ContentType.ts +++ b/src/helpers/ContentType.ts @@ -135,15 +135,22 @@ export class ContentType { * @param data */ private static processFields(obj: IContentType | Field, titleValue: string, data: any) { + if (obj.fields) { for (const field of obj.fields) { if (field.name === "title") { - data[field.name] = titleValue; + if (field.default) { + data[field.name] = ArticleHelper.processKnownPlaceholders(field.default, titleValue); + data[field.name] = ArticleHelper.processCustomPlaceholders(data[field.name], titleValue); + } else { + data[field.name] = titleValue; + } } else { if (field.type === "fields") { data[field.name] = this.processFields(field, titleValue, {}); } else { - data[field.name] = field.default || ""; + data[field.name] = field.default ? ArticleHelper.processKnownPlaceholders(field.default, titleValue) : ""; + data[field.name] = field.default ? ArticleHelper.processCustomPlaceholders(data[field.name], titleValue) : ""; } } }