A CLI for publishing standard.site documents to ATProto sequoia.pub
standard site lexicon cli publishing

feat: add stripDatePrefix option for Jekyll-style filenames

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`.

authored by xx-c.tngl.sh and committed by tangled.org 45d74d99 2a742692

+18 -1
+1
packages/cli/src/commands/publish.ts
··· 110 ignorePatterns: config.ignore, 111 slugField: config.frontmatter?.slugField, 112 removeIndexFromSlug: config.removeIndexFromSlug, 113 }); 114 s.stop(`Found ${posts.length} posts`); 115
··· 110 ignorePatterns: config.ignore, 111 slugField: config.frontmatter?.slugField, 112 removeIndexFromSlug: config.removeIndexFromSlug, 113 + stripDatePrefix: config.stripDatePrefix, 114 }); 115 s.stop(`Found ${posts.length} posts`); 116
+1
packages/cli/src/commands/sync.ts
··· 105 ignorePatterns: config.ignore, 106 slugField: config.frontmatter?.slugField, 107 removeIndexFromSlug: config.removeIndexFromSlug, 108 }); 109 s.stop(`Found ${localPosts.length} local posts`); 110
··· 105 ignorePatterns: config.ignore, 106 slugField: config.frontmatter?.slugField, 107 removeIndexFromSlug: config.removeIndexFromSlug, 108 + stripDatePrefix: config.stripDatePrefix, 109 }); 110 s.stop(`Found ${localPosts.length} local posts`); 111
+5
packages/cli/src/lib/config.ts
··· 82 frontmatter?: FrontmatterMapping; 83 ignore?: string[]; 84 removeIndexFromSlug?: boolean; 85 textContentField?: string; 86 bluesky?: BlueskyConfig; 87 }): string { ··· 122 123 if (options.removeIndexFromSlug) { 124 config.removeIndexFromSlug = options.removeIndexFromSlug; 125 } 126 127 if (options.textContentField) {
··· 82 frontmatter?: FrontmatterMapping; 83 ignore?: string[]; 84 removeIndexFromSlug?: boolean; 85 + stripDatePrefix?: boolean; 86 textContentField?: string; 87 bluesky?: BlueskyConfig; 88 }): string { ··· 123 124 if (options.removeIndexFromSlug) { 125 config.removeIndexFromSlug = options.removeIndexFromSlug; 126 + } 127 + 128 + if (options.stripDatePrefix) { 129 + config.stripDatePrefix = options.stripDatePrefix; 130 } 131 132 if (options.textContentField) {
+10 -1
packages/cli/src/lib/markdown.ts
··· 178 export interface SlugOptions { 179 slugField?: string; 180 removeIndexFromSlug?: boolean; 181 } 182 183 export function getSlugFromOptions( ··· 185 rawFrontmatter: Record<string, unknown>, 186 options: SlugOptions = {}, 187 ): string { 188 - const { slugField, removeIndexFromSlug = false } = options; 189 190 let slug: string; 191 ··· 218 slug = slug.replace(/\/_?index$/, ""); 219 } 220 221 return slug; 222 } 223 ··· 243 ignorePatterns?: string[]; 244 slugField?: string; 245 removeIndexFromSlug?: boolean; 246 } 247 248 export async function scanContentDirectory( ··· 274 ignorePatterns: ignore = [], 275 slugField, 276 removeIndexFromSlug, 277 } = options; 278 279 const patterns = ["**/*.md", "**/*.mdx"]; ··· 302 const slug = getSlugFromOptions(relativePath, rawFrontmatter, { 303 slugField, 304 removeIndexFromSlug, 305 }); 306 307 posts.push({
··· 178 export interface SlugOptions { 179 slugField?: string; 180 removeIndexFromSlug?: boolean; 181 + stripDatePrefix?: boolean; 182 } 183 184 export function getSlugFromOptions( ··· 186 rawFrontmatter: Record<string, unknown>, 187 options: SlugOptions = {}, 188 ): string { 189 + const { slugField, removeIndexFromSlug = false, stripDatePrefix = false } = options; 190 191 let slug: string; 192 ··· 219 slug = slug.replace(/\/_?index$/, ""); 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 + 227 return slug; 228 } 229 ··· 249 ignorePatterns?: string[]; 250 slugField?: string; 251 removeIndexFromSlug?: boolean; 252 + stripDatePrefix?: boolean; 253 } 254 255 export async function scanContentDirectory( ··· 281 ignorePatterns: ignore = [], 282 slugField, 283 removeIndexFromSlug, 284 + stripDatePrefix, 285 } = options; 286 287 const patterns = ["**/*.md", "**/*.mdx"]; ··· 310 const slug = getSlugFromOptions(relativePath, rawFrontmatter, { 311 slugField, 312 removeIndexFromSlug, 313 + stripDatePrefix, 314 }); 315 316 posts.push({
+1
packages/cli/src/lib/types.ts
··· 33 frontmatter?: FrontmatterMapping; // Custom frontmatter field mappings 34 ignore?: string[]; // Glob patterns for files to ignore (e.g., ["_index.md", "**/drafts/**"]) 35 removeIndexFromSlug?: boolean; // Remove "/index" or "/_index" suffix from paths (default: false) 36 textContentField?: string; // Frontmatter field to use for textContent instead of markdown body 37 bluesky?: BlueskyConfig; // Optional Bluesky posting configuration 38 }
··· 33 frontmatter?: FrontmatterMapping; // Custom frontmatter field mappings 34 ignore?: string[]; // Glob patterns for files to ignore (e.g., ["_index.md", "**/drafts/**"]) 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) 37 textContentField?: string; // Frontmatter field to use for textContent instead of markdown body 38 bluesky?: BlueskyConfig; // Optional Bluesky posting configuration 39 }