Skip to content

Instantly share code, notes, and snippets.

@llbbl
Created February 11, 2025 03:26
Show Gist options
  • Save llbbl/70aa59c78f80652ec1ea2fe99459f966 to your computer and use it in GitHub Desktop.
Save llbbl/70aa59c78f80652ec1ea2fe99459f966 to your computer and use it in GitHub Desktop.
fix markdown file names for astro
import fs from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
interface ProcessResult {
success: boolean;
error?: Error;
changes: {
type: 'file' | 'directory';
from: string;
to: string;
}[];
}
// Function to convert string to kebab case
function toKebabCase(str: string): string {
return str
.toLowerCase()
// Replace special characters with spaces
.replace(/[?!()[\]<>:'"]/g, '')
// Replace multiple spaces with single space
.replace(/\s+/g, ' ')
// Trim spaces from ends
.trim()
// Replace spaces with hyphens
.replace(/\s/g, '-')
// Remove any non-alphanumeric characters (except hyphens)
.replace(/[^a-z0-9-]/g, '');
}
// Function to process a single file
async function processFile(filePath: string): Promise<ProcessResult> {
const changes: ProcessResult['changes'] = [];
try {
const stats = await fs.stat(filePath);
if (stats.isDirectory()) {
// Handle directory
const items = await fs.readdir(filePath);
const newDirName = toKebabCase(path.basename(filePath));
const parentDir = path.dirname(filePath);
const newDirPath = path.join(parentDir, newDirName);
// Rename directory if needed
if (newDirName !== path.basename(filePath)) {
await fs.rename(filePath, newDirPath);
console.log(`Renamed directory: ${path.basename(filePath)} → ${newDirName}`);
changes.push({
type: 'directory',
from: path.basename(filePath),
to: newDirName
});
}
// Process all items in directory
for (const item of items) {
const result = await processFile(path.join(newDirPath, item));
changes.push(...result.changes);
}
} else if (path.extname(filePath) === '.md') {
// Handle markdown file
const originalName = path.basename(filePath, '.md');
const newName = toKebabCase(originalName) + '.md';
const dirPath = path.dirname(filePath);
const newPath = path.join(dirPath, newName);
if (newName !== path.basename(filePath)) {
// Read original content
const content = await fs.readFile(filePath, 'utf8');
// Prepend the original file name as an H1 header.
// If front matter exists (starting with '---'), insert it after the front matter.
let newContent;
if (content.startsWith('---')) {
const frontMatterMatch = content.match(/^(---\s*\n[\s\S]*?\n---\s*\n)/);
if (frontMatterMatch) {
const frontMatter = frontMatterMatch[1];
const restContent = content.slice(frontMatter.length);
newContent = `${frontMatter}# ${originalName}\n\n${restContent}`;
} else {
newContent = `# ${originalName}\n\n${content}`;
}
} else {
newContent = `# ${originalName}\n\n${content}`;
}
// Write new content to renamed file
await fs.writeFile(newPath, newContent, 'utf8');
// Remove old file now that we've created the new one
await fs.unlink(filePath);
console.log(`Renamed file: ${path.basename(filePath)} → ${newName}`);
changes.push({
type: 'file',
from: path.basename(filePath),
to: newName
});
}
}
return { success: true, changes };
} catch (error) {
console.error(`Error processing ${filePath}:`, error);
return {
success: false,
error: error instanceof Error ? error : new Error(String(error)),
changes
};
}
}
// Main function
async function main(): Promise<void> {
const pagesDir = path.join(__dirname, '..', 'src', 'pages');
try {
const result = await processFile(pagesDir);
console.log('File processing complete!');
if (result.changes.length > 0) {
console.log('\nChanges made:');
result.changes.forEach(change => {
console.log(`${change.type}: ${change.from} → ${change.to}`);
});
} else {
console.log('No changes were necessary.');
}
} catch (error) {
console.error('Error:', error);
process.exit(1);
}
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment