feat: add stripDatePrefix option for Jekyll-style filenames 45d74d99
Adds a new `stripDatePrefix` configuration option that removes
YYYY-MM-DD- prefixes from filenames when deriving slugs. This
supports Jekyll-style post naming where files like
`2024-01-15-my-post.md` should produce slug `my-post`.
vincent · 2026-02-02 22:04 5 file(s) · +18 −1
packages/cli/src/commands/publish.ts +1 −0
110 110
			ignorePatterns: config.ignore,
111 111
			slugField: config.frontmatter?.slugField,
112 112
			removeIndexFromSlug: config.removeIndexFromSlug,
113 +
			stripDatePrefix: config.stripDatePrefix,
113 114
		});
114 115
		s.stop(`Found ${posts.length} posts`);
115 116
packages/cli/src/commands/sync.ts +1 −0
105 105
			ignorePatterns: config.ignore,
106 106
			slugField: config.frontmatter?.slugField,
107 107
			removeIndexFromSlug: config.removeIndexFromSlug,
108 +
			stripDatePrefix: config.stripDatePrefix,
108 109
		});
109 110
		s.stop(`Found ${localPosts.length} local posts`);
110 111
packages/cli/src/lib/config.ts +5 −0
82 82
	frontmatter?: FrontmatterMapping;
83 83
	ignore?: string[];
84 84
	removeIndexFromSlug?: boolean;
85 +
	stripDatePrefix?: boolean;
85 86
	textContentField?: string;
86 87
	bluesky?: BlueskyConfig;
87 88
}): string {
122 123
123 124
	if (options.removeIndexFromSlug) {
124 125
		config.removeIndexFromSlug = options.removeIndexFromSlug;
126 +
	}
127 +
128 +
	if (options.stripDatePrefix) {
129 +
		config.stripDatePrefix = options.stripDatePrefix;
125 130
	}
126 131
127 132
	if (options.textContentField) {
packages/cli/src/lib/markdown.ts +10 −1
178 178
export interface SlugOptions {
179 179
	slugField?: string;
180 180
	removeIndexFromSlug?: boolean;
181 +
	stripDatePrefix?: boolean;
181 182
}
182 183
183 184
export function getSlugFromOptions(
185 186
	rawFrontmatter: Record<string, unknown>,
186 187
	options: SlugOptions = {},
187 188
): string {
188 -
	const { slugField, removeIndexFromSlug = false } = options;
189 +
	const { slugField, removeIndexFromSlug = false, stripDatePrefix = false } = options;
189 190
190 191
	let slug: string;
191 192
218 219
		slug = slug.replace(/\/_?index$/, "");
219 220
	}
220 221
222 +
	// Strip Jekyll-style date prefix (YYYY-MM-DD-) from filename
223 +
	if (stripDatePrefix) {
224 +
		slug = slug.replace(/(^|\/)(\d{4}-\d{2}-\d{2})-/g, "$1");
225 +
	}
226 +
221 227
	return slug;
222 228
}
223 229
243 249
	ignorePatterns?: string[];
244 250
	slugField?: string;
245 251
	removeIndexFromSlug?: boolean;
252 +
	stripDatePrefix?: boolean;
246 253
}
247 254
248 255
export async function scanContentDirectory(
274 281
		ignorePatterns: ignore = [],
275 282
		slugField,
276 283
		removeIndexFromSlug,
284 +
		stripDatePrefix,
277 285
	} = options;
278 286
279 287
	const patterns = ["**/*.md", "**/*.mdx"];
302 310
				const slug = getSlugFromOptions(relativePath, rawFrontmatter, {
303 311
					slugField,
304 312
					removeIndexFromSlug,
313 +
					stripDatePrefix,
305 314
				});
306 315
307 316
				posts.push({
packages/cli/src/lib/types.ts +1 −0
33 33
	frontmatter?: FrontmatterMapping; // Custom frontmatter field mappings
34 34
	ignore?: string[]; // Glob patterns for files to ignore (e.g., ["_index.md", "**/drafts/**"])
35 35
	removeIndexFromSlug?: boolean; // Remove "/index" or "/_index" suffix from paths (default: false)
36 +
	stripDatePrefix?: boolean; // Remove YYYY-MM-DD- prefix from filenames (Jekyll-style, default: false)
36 37
	textContentField?: string; // Frontmatter field to use for textContent instead of markdown body
37 38
	bluesky?: BlueskyConfig; // Optional Bluesky posting configuration
38 39
}