125 lines
4.3 KiB
JavaScript
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/post');
|
|
|
|
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.');
|