mirror of
https://github.com/placeholder-soft/web.git
synced 2026-01-12 22:45:00 +08:00
This code improves error handling, is made more readable, and uses asynchronous fs.promises operations for a more modern approach to reading files and working with the file system.
94 lines
2.8 KiB
JavaScript
94 lines
2.8 KiB
JavaScript
const yaml = require('js-yaml');
|
|
const fs = require('fs');
|
|
const { readFile, readdir, stat } = fs.promises;
|
|
const path = require('path');
|
|
const crypto = require('crypto');
|
|
|
|
const tutorialsDir = path.join(__dirname, '..', 'tutorials', 'docs');
|
|
const outputFilePath = path.join(__dirname, '..', 'tutorials', 'data.json');
|
|
|
|
async function getDuration(filePath) {
|
|
try {
|
|
const content = await readFile(filePath, 'utf8');
|
|
const words = content.trim().split(/\s+/).length;
|
|
const averageReadingSpeed = 225;
|
|
const readingTimeMinutes = (words / averageReadingSpeed) * 2;
|
|
|
|
const hours = Math.floor(readingTimeMinutes / 60);
|
|
const minutes = Math.round(readingTimeMinutes % 60);
|
|
|
|
let timeString = '';
|
|
if (hours > 0) {
|
|
timeString += `${hours} hr `;
|
|
}
|
|
timeString += `${minutes} min`;
|
|
|
|
return `${timeString} read`;
|
|
} catch (error) {
|
|
console.error('Error reading file:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async function formatDate(date) {
|
|
const months = [
|
|
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
|
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
|
|
];
|
|
const month = months[date.getMonth()];
|
|
const day = date.getDate();
|
|
const year = date.getFullYear();
|
|
return `${month} ${day}, ${year}`;
|
|
}
|
|
|
|
async function calculateChecksum(filePath) {
|
|
return new Promise((resolve, reject) => {
|
|
const hash = crypto.createHash('sha256');
|
|
const stream = fs.createReadStream(filePath);
|
|
stream.on('data', (data) => hash.update(data));
|
|
stream.on('end', () => resolve(hash.digest('hex')));
|
|
stream.on('error', reject);
|
|
});
|
|
}
|
|
|
|
(async () => {
|
|
const tutorials = {};
|
|
let existingData = {};
|
|
|
|
try {
|
|
existingData = JSON.parse(await readFile(outputFilePath, 'utf8'));
|
|
} catch (e) {
|
|
console.error('Failed to read existing data:', e);
|
|
}
|
|
|
|
try {
|
|
const files = await readdir(tutorialsDir);
|
|
for (const file of files) {
|
|
const tutorialsPath = path.join(tutorialsDir, file);
|
|
const tutorialsStat = await stat(tutorialsPath);
|
|
if (tutorialsStat.isFile()) {
|
|
let content = await readFile(tutorialsPath, 'utf8');
|
|
const frontMatter = yaml.load(content.split('---\n')[1]);
|
|
const slug = path.parse(file).name;
|
|
const checksum = await calculateChecksum(tutorialsPath);
|
|
const currentDate = new Date();
|
|
|
|
if (!existingData[slug] || existingData[slug].checksum !== checksum) {
|
|
tutorials[slug] = {
|
|
...frontMatter,
|
|
last_updated: await formatDate(currentDate),
|
|
duration: await getDuration(tutorialsPath),
|
|
checksum: checksum,
|
|
};
|
|
} else {
|
|
tutorials[slug] = existingData[slug];
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error('Error updating tutorial data:', e);
|
|
}
|
|
|
|
fs.writeFileSync(outputFilePath, JSON.stringify(tutorials, null, 4));
|
|
})();
|