From 43190099e576e51c79fbb8476b080340b8fcec6f Mon Sep 17 00:00:00 2001 From: Danil Semelenov Date: Thu, 7 May 2026 11:17:41 -0400 Subject: [PATCH] feat: add frontMatter.file.slugSeparator setting Allows users to configure the word separator used when generating slugs and file names from titles. Defaults to `-` (hyphen) to preserve existing behavior. Set to `_` for underscore-separated file names. Co-Authored-By: Claude Sonnet 4.6 --- package.json | 6 ++++++ package.nls.json | 1 + src/constants/settings.ts | 1 + src/helpers/ArticleHelper.ts | 4 +++- src/helpers/SlugHelper.ts | 8 +++++--- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 6b0d7f27..559ca62d 100644 --- a/package.json +++ b/package.json @@ -965,6 +965,12 @@ "markdownDescription": "%setting.frontMatter.file.preserveCasing.markdownDescription%", "scope": "File" }, + "frontMatter.file.slugSeparator": { + "type": "string", + "default": "-", + "markdownDescription": "%setting.frontMatter.file.slugSeparator.markdownDescription%", + "scope": "File" + }, "frontMatter.framework.id": { "type": "string", "default": "", diff --git a/package.nls.json b/package.nls.json index 3973023b..c081df1e 100644 --- a/package.nls.json +++ b/package.nls.json @@ -155,6 +155,7 @@ "setting.frontMatter.data.types.markdownDescription": "Specify the data types. These types can be used in for your data files. [Docs](https://frontmatter.codes/docs/settings/overview#frontmatter.data.types) - [View in VS Code](command:simpleBrowser.show?%5B%22https://frontmatter.codes/docs/settings/overview%23frontmatter.data.types%22%5D)", "setting.frontMatter.data.types.items.properties.id.description": "Your unique ID you want to use for your data type.", "setting.frontMatter.file.preserveCasing.markdownDescription": "Specify if you want to preserve the casing of your file names from the title. [Docs](https://frontmatter.codes/docs/settings/overview#frontmatter.file.preservecasing) - [View in VS Code](command:simpleBrowser.show?%5B%22https://frontmatter.codes/docs/settings/overview%23frontmatter.file.preservecasing%22%5D)", + "setting.frontMatter.file.slugSeparator.markdownDescription": "Specify the separator character used between words when generating slugs and file names from titles. Default is `-` (hyphen). Use `_` for underscores.", "setting.frontMatter.framework.id.markdownDescription": "Specify the ID of your static site generator or framework you are using for your website. [Docs](https://frontmatter.codes/docs/settings/overview#frontmatter.framework.id) - [View in VS Code](command:simpleBrowser.show?%5B%22https://frontmatter.codes/docs/settings/overview%23frontmatter.framework.id%22%5D)", "setting.frontMatter.framework.startCommand.markdownDescription": "Specify the command you want to use to start your static site generator or framework. [Docs](https://frontmatter.codes/docs/settings/overview#frontmatter.framework.startcommand) - [View in VS Code](command:simpleBrowser.show?%5B%22https://frontmatter.codes/docs/settings/overview%23frontmatter.framework.startcommand%22%5D)", "setting.frontMatter.git.enabled.markdownDescription": "Specify if you want to use the Git actions for your website. [Docs](https://frontmatter.codes/docs/settings/overview#frontmatter.git.enabled) - [View in VS Code](command:simpleBrowser.show?%5B%22https://frontmatter.codes/docs/settings/overview%23frontmatter.git.enabled%22%5D)", diff --git a/src/constants/settings.ts b/src/constants/settings.ts index cb138441..f13a298e 100644 --- a/src/constants/settings.ts +++ b/src/constants/settings.ts @@ -97,6 +97,7 @@ export const SETTING_DATA_FOLDERS = 'data.folders'; export const SETTING_DATA_TYPES = 'data.types'; export const SETTING_FILE_PRESERVE_CASING = 'file.preserveCasing'; +export const SETTING_FILE_SLUG_SEPARATOR = 'file.slugSeparator'; export const SETTING_FRAMEWORK_ID = 'framework.id'; export const SETTING_FRAMEWORK_START = 'framework.startCommand'; diff --git a/src/helpers/ArticleHelper.ts b/src/helpers/ArticleHelper.ts index d8050020..6b1cd64c 100644 --- a/src/helpers/ArticleHelper.ts +++ b/src/helpers/ArticleHelper.ts @@ -10,6 +10,7 @@ import { SETTING_CONTENT_PLACEHOLDERS, SETTING_CONTENT_SUPPORTED_FILETYPES, SETTING_FILE_PRESERVE_CASING, + SETTING_FILE_SLUG_SEPARATOR, SETTING_COMMA_SEPARATED_FIELDS, SETTING_DATE_FIELD, SETTING_DATE_FORMAT, @@ -660,7 +661,8 @@ export class ArticleHelper { */ public static sanitize(value: string): string { const preserveCasing = Settings.get(SETTING_FILE_PRESERVE_CASING) as boolean; - return sanitize((preserveCasing ? value : value.toLowerCase()).replace(/ /g, '-')); + const separator = (Settings.get(SETTING_FILE_SLUG_SEPARATOR) as string) || '-'; + return sanitize((preserveCasing ? value : value.toLowerCase()).replace(/ /g, separator)); } /** diff --git a/src/helpers/SlugHelper.ts b/src/helpers/SlugHelper.ts index 77acbc18..036181fa 100644 --- a/src/helpers/SlugHelper.ts +++ b/src/helpers/SlugHelper.ts @@ -1,5 +1,5 @@ import { parseWinPath, Settings } from '.'; -import { stopWords, charMap, SETTING_DATE_FORMAT, SETTING_SLUG_TEMPLATE } from '../constants'; +import { stopWords, charMap, SETTING_DATE_FORMAT, SETTING_SLUG_TEMPLATE, SETTING_FILE_SLUG_SEPARATOR } from '../constants'; import { processTimePlaceholders, processFmPlaceholders } from '.'; import { parse } from 'path'; @@ -26,7 +26,8 @@ export class SlugHelper { if (typeof slugTemplate === 'string') { if (slugTemplate.includes('{{title}}')) { const regex = new RegExp('{{title}}', 'g'); - slugTemplate = slugTemplate.replace(regex, articleTitle.toLowerCase().replace(/\s/g, '-')); + const separator = (Settings.get(SETTING_FILE_SLUG_SEPARATOR) as string) || '-'; + slugTemplate = slugTemplate.replace(regex, articleTitle.toLowerCase().replace(/\s/g, separator)); } else if (slugTemplate.includes('{{seoTitle}}')) { const regex = new RegExp('{{seoTitle}}', 'g'); slugTemplate = slugTemplate.replace(regex, SlugHelper.slugify(articleTitle)); @@ -69,7 +70,8 @@ export class SlugHelper { let words = cleanTitle.split(/\s/); // Removing stop words words = this.removeStopWords(words); - cleanTitle = words.join('-'); + const separator = (Settings.get(SETTING_FILE_SLUG_SEPARATOR) as string) || '-'; + cleanTitle = words.join(separator); cleanTitle = this.replaceCharacters(cleanTitle); return cleanTitle; }