Files
blog/scripts/migrate_slugs.js
T

125 lines
4.3 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const matter = require('gray-matter');
const postsDir = path.resolve(__dirname, '../content/posts');
function formatDate(date) {
if (!date) return null;
const d = new Date(date);
if (isNaN(d.getTime())) return null;
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
return `${year}${month}${day}`;
}
function traverseDir(dir) {
const files = fs.readdirSync(dir);
files.forEach(file => {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
traverseDir(filePath);
} else if (file.endsWith('.md')) {
processFile(filePath);
}
});
}
function processFile(filePath) {
try {
const fileContent = fs.readFileSync(filePath, 'utf8');
const parsed = matter(fileContent);
// Check if slug is already in target format (YYYYMMDDHHmm)
// Or if it matches YYYYMMDD (old format we are migrating to)
if (parsed.data.slug && /^\d{8,12}$/.test(String(parsed.data.slug))) {
// console.log(`Skipping ${filePath}: Slug already formatted (${parsed.data.slug})`);
return;
}
const dateSlug = formatDate(parsed.data.date);
if (!dateSlug) {
console.warn(`Skipping ${filePath}: No valid date found`);
return;
}
// Update slug
// Note: gray-matter might reformat the front matter slightly
// We preserve existing data but update slug
parsed.data.slug = dateSlug;
// Convert back to string
// Hugo front matter usually uses '---' delimiters
// gray-matter defaults to '---'
// We need to be careful about date formatting in output,
// but gray-matter usually handles Date objects by converting to ISO string
// Force date to be string if it was parsed as Date object to avoid format changes?
// Actually, Hugo likes ISO dates, so Date object to ISO string is fine.
const newContent = matter.stringify(parsed.content, parsed.data);
// fs.writeFileSync(filePath, newContent);
// console.log(`Updated ${filePath}: slug set to ${dateSlug}`);
// Wait, gray-matter stringify might change the order or format of other fields.
// A safer approach is regex replacement if we only want to change slug.
// But regex is brittle.
// Let's stick to gray-matter but be careful.
// Actually, let's use a custom replacement to be safe and preserve comments/formatting.
let lines = fileContent.split('\n');
let inFrontMatter = false;
let slugFound = false;
let dateFound = false;
let newLines = [];
let fmEndIndex = -1;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line.trim() === '---') {
if (!inFrontMatter) {
inFrontMatter = true;
} else {
inFrontMatter = false;
fmEndIndex = i;
}
newLines.push(line);
continue;
}
if (inFrontMatter) {
if (line.trim().startsWith('slug:')) {
newLines.push(`slug: ${dateSlug}`);
slugFound = true;
} else if (line.trim().startsWith('date:')) {
newLines.push(line);
dateFound = true;
} else {
newLines.push(line);
}
} else {
newLines.push(line);
}
}
if (!slugFound && fmEndIndex !== -1) {
// Insert slug before the end of front matter
// Find the last non-empty line before ---
newLines.splice(fmEndIndex, 0, `slug: ${dateSlug}`);
}
fs.writeFileSync(filePath, newLines.join('\n'));
console.log(`Updated ${filePath}: slug set to ${dateSlug}`);
} catch (e) {
console.error(`Error processing ${filePath}:`, e);
}
}
console.log('Starting slug migration...');
traverseDir(postsDir);
console.log('Migration complete.');