11ty-to-astro.mjs
· 3.6 KiB · JavaScript
Orginalformat
// ChatGPT conversation to help with this script:
// https://chatgpt.com/share/6817d17d-5a24-8002-9471-b5aa174f689d
import fs from "fs";
import path from "path";
import matter from "gray-matter";
import yaml from "js-yaml";
// Configuration
const inputDir = "./src/content/post/"; // Folder containing markdown files
const backupDir = "./backup"; // Backup before modifying
// Create backup directory if it doesn't exist
if (!fs.existsSync(backupDir)) {
fs.mkdirSync(backupDir);
}
// Preferred frontmatter key order
const preferredKeyOrder = [
"title",
"description",
"publishDate",
"updatedDate",
"tags",
"slug",
"draft",
];
function sortFrontmatterKeys(data) {
const sorted = {};
preferredKeyOrder.forEach((key) => {
if (data[key] !== undefined) {
sorted[key] = data[key];
}
});
Object.keys(data).forEach((key) => {
if (!sorted.hasOwnProperty(key)) {
sorted[key] = data[key];
}
});
return sorted;
}
// Format dates consistently
function formatDate(value) {
if (value instanceof Date) {
return value.toISOString().split("T")[0];
}
return value;
}
// Extract date from filename if present
function extractDateFromFilename(filename) {
const match = filename.match(/^(\d{4}-\d{2}-\d{2})-(.+)$/);
if (match) {
return {
date: match[1],
newFilename: match[2],
};
}
return null;
}
// Clean and fix a single file
function fixFile(filePath) {
const rawContent = fs.readFileSync(filePath, "utf8");
const { data: frontmatter, content } = matter(rawContent);
let cleanedFrontmatter = { ...frontmatter };
const fileName = path.basename(filePath);
const dateInfo = extractDateFromFilename(fileName);
// Move date from filename into publishDate if missing
if (dateInfo) {
if (!cleanedFrontmatter.publishDate) {
cleanedFrontmatter.publishDate = dateInfo.date;
}
}
// Rename "date" -> "publishDate" if necessary
if (cleanedFrontmatter.date && !cleanedFrontmatter.publishDate) {
cleanedFrontmatter.publishDate = cleanedFrontmatter.date;
delete cleanedFrontmatter.date;
}
// Fix date formats
Object.keys(cleanedFrontmatter).forEach((key) => {
if (key.toLowerCase().includes("date")) {
cleanedFrontmatter[key] = formatDate(cleanedFrontmatter[key]);
}
});
// If publishDate missing, set draft: true
if (
!cleanedFrontmatter.publishDate && cleanedFrontmatter.draft === undefined
) {
cleanedFrontmatter.draft = true;
}
// Sort frontmatter keys
cleanedFrontmatter = sortFrontmatterKeys(cleanedFrontmatter);
const yamlContent = yaml.dump(cleanedFrontmatter, {
lineWidth: 1000,
quotingType: '"',
});
const finalContent = `---\n${yamlContent}---\n\n${content.trim()}\n`;
// Backup original
const backupPath = path.join(backupDir, fileName);
fs.copyFileSync(filePath, backupPath);
// Determine new filename
let outputPath = filePath;
if (dateInfo) {
const newFilename = dateInfo.newFilename;
outputPath = path.join(path.dirname(filePath), newFilename);
}
// Write cleaned file (possibly with new filename)
fs.writeFileSync(outputPath, finalContent, "utf8");
// If filename changed, delete the old file
if (outputPath !== filePath) {
fs.unlinkSync(filePath);
console.log(`Fixed & Renamed: ${fileName} -> ${path.basename(outputPath)}`);
} else {
console.log(`Fixed: ${fileName}`);
}
}
// Process all markdown files
function fixAllFiles() {
const files = fs.readdirSync(inputDir);
files.forEach((file) => {
if (file.endsWith(".md")) {
fixFile(path.join(inputDir, file));
}
});
}
fixAllFiles();
1 | // ChatGPT conversation to help with this script: |
2 | // https://chatgpt.com/share/6817d17d-5a24-8002-9471-b5aa174f689d |
3 | |
4 | import fs from "fs"; |
5 | import path from "path"; |
6 | import matter from "gray-matter"; |
7 | import yaml from "js-yaml"; |
8 | |
9 | // Configuration |
10 | const inputDir = "./src/content/post/"; // Folder containing markdown files |
11 | const backupDir = "./backup"; // Backup before modifying |
12 | |
13 | // Create backup directory if it doesn't exist |
14 | if (!fs.existsSync(backupDir)) { |
15 | fs.mkdirSync(backupDir); |
16 | } |
17 | |
18 | // Preferred frontmatter key order |
19 | const preferredKeyOrder = [ |
20 | "title", |
21 | "description", |
22 | "publishDate", |
23 | "updatedDate", |
24 | "tags", |
25 | "slug", |
26 | "draft", |
27 | ]; |
28 | |
29 | function sortFrontmatterKeys(data) { |
30 | const sorted = {}; |
31 | preferredKeyOrder.forEach((key) => { |
32 | if (data[key] !== undefined) { |
33 | sorted[key] = data[key]; |
34 | } |
35 | }); |
36 | Object.keys(data).forEach((key) => { |
37 | if (!sorted.hasOwnProperty(key)) { |
38 | sorted[key] = data[key]; |
39 | } |
40 | }); |
41 | return sorted; |
42 | } |
43 | |
44 | // Format dates consistently |
45 | function formatDate(value) { |
46 | if (value instanceof Date) { |
47 | return value.toISOString().split("T")[0]; |
48 | } |
49 | return value; |
50 | } |
51 | |
52 | // Extract date from filename if present |
53 | function extractDateFromFilename(filename) { |
54 | const match = filename.match(/^(\d{4}-\d{2}-\d{2})-(.+)$/); |
55 | if (match) { |
56 | return { |
57 | date: match[1], |
58 | newFilename: match[2], |
59 | }; |
60 | } |
61 | return null; |
62 | } |
63 | |
64 | // Clean and fix a single file |
65 | function fixFile(filePath) { |
66 | const rawContent = fs.readFileSync(filePath, "utf8"); |
67 | const { data: frontmatter, content } = matter(rawContent); |
68 | |
69 | let cleanedFrontmatter = { ...frontmatter }; |
70 | const fileName = path.basename(filePath); |
71 | const dateInfo = extractDateFromFilename(fileName); |
72 | |
73 | // Move date from filename into publishDate if missing |
74 | if (dateInfo) { |
75 | if (!cleanedFrontmatter.publishDate) { |
76 | cleanedFrontmatter.publishDate = dateInfo.date; |
77 | } |
78 | } |
79 | |
80 | // Rename "date" -> "publishDate" if necessary |
81 | if (cleanedFrontmatter.date && !cleanedFrontmatter.publishDate) { |
82 | cleanedFrontmatter.publishDate = cleanedFrontmatter.date; |
83 | delete cleanedFrontmatter.date; |
84 | } |
85 | |
86 | // Fix date formats |
87 | Object.keys(cleanedFrontmatter).forEach((key) => { |
88 | if (key.toLowerCase().includes("date")) { |
89 | cleanedFrontmatter[key] = formatDate(cleanedFrontmatter[key]); |
90 | } |
91 | }); |
92 | |
93 | // If publishDate missing, set draft: true |
94 | if ( |
95 | !cleanedFrontmatter.publishDate && cleanedFrontmatter.draft === undefined |
96 | ) { |
97 | cleanedFrontmatter.draft = true; |
98 | } |
99 | |
100 | // Sort frontmatter keys |
101 | cleanedFrontmatter = sortFrontmatterKeys(cleanedFrontmatter); |
102 | |
103 | const yamlContent = yaml.dump(cleanedFrontmatter, { |
104 | lineWidth: 1000, |
105 | quotingType: '"', |
106 | }); |
107 | |
108 | const finalContent = `---\n${yamlContent}---\n\n${content.trim()}\n`; |
109 | |
110 | // Backup original |
111 | const backupPath = path.join(backupDir, fileName); |
112 | fs.copyFileSync(filePath, backupPath); |
113 | |
114 | // Determine new filename |
115 | let outputPath = filePath; |
116 | if (dateInfo) { |
117 | const newFilename = dateInfo.newFilename; |
118 | outputPath = path.join(path.dirname(filePath), newFilename); |
119 | } |
120 | |
121 | // Write cleaned file (possibly with new filename) |
122 | fs.writeFileSync(outputPath, finalContent, "utf8"); |
123 | |
124 | // If filename changed, delete the old file |
125 | if (outputPath !== filePath) { |
126 | fs.unlinkSync(filePath); |
127 | console.log(`Fixed & Renamed: ${fileName} -> ${path.basename(outputPath)}`); |
128 | } else { |
129 | console.log(`Fixed: ${fileName}`); |
130 | } |
131 | } |
132 | |
133 | // Process all markdown files |
134 | function fixAllFiles() { |
135 | const files = fs.readdirSync(inputDir); |
136 | files.forEach((file) => { |
137 | if (file.endsWith(".md")) { |
138 | fixFile(path.join(inputDir, file)); |
139 | } |
140 | }); |
141 | } |
142 | |
143 | fixAllFiles(); |