mirror of
https://github.com/10h30/wordpress-export-to-markdown.git
synced 2026-07-11 18:56:14 +09:00
149 lines
4.1 KiB
JavaScript
149 lines
4.1 KiB
JavaScript
const chalk = require('chalk');
|
|
const fs = require('fs');
|
|
const luxon = require('luxon');
|
|
const path = require('path');
|
|
const requestPromiseNative = require('request-promise-native');
|
|
|
|
const shared = require('./shared');
|
|
|
|
async function writeFilesPromise(posts, config) {
|
|
await writeMarkdownFilesPromise(posts, config);
|
|
await writeImageFilesPromise(posts, config);
|
|
}
|
|
|
|
async function processPayloadsPromise(payloads, writeFunc, config) {
|
|
const promises = payloads.map(payload => new Promise((resolve, reject) => {
|
|
setTimeout(async () => {
|
|
try {
|
|
await writeFunc(payload.item, config);
|
|
console.log(chalk.green('[OK]') + ' ' + payload.name);
|
|
resolve();
|
|
} catch (ex) {
|
|
console.error(chalk.red('[FAILED]') + ' ' + payload.name + ' ' + chalk.red('(' + ex.toString() + ')'));
|
|
reject();
|
|
}
|
|
}, payload.delay);
|
|
}));
|
|
|
|
const results = await Promise.allSettled(promises);
|
|
const failedCount = results.filter(result => result.status === 'rejected').length;
|
|
if (failedCount === 0) {
|
|
console.log('Done, got them all!');
|
|
} else {
|
|
console.log('Done, but with ' + chalk.red(failedCount + ' failed') + '.');
|
|
}
|
|
}
|
|
|
|
async function writeMarkdownFilesPromise(posts,config ) {
|
|
// package up posts into payloads
|
|
const payloads = posts.map((post, index) => ({
|
|
item: post,
|
|
name: post.meta.slug,
|
|
delay: index * 25
|
|
}));
|
|
|
|
console.log('\nSaving posts...');
|
|
await processPayloadsPromise(payloads, writeMarkdownFilePromise, config);
|
|
}
|
|
|
|
async function writeMarkdownFilePromise(post, config) {
|
|
let output = '---\n';
|
|
Object.entries(post.frontmatter).forEach(pair => {
|
|
const key = pair[0];
|
|
const value = pair[1].replace(/"/g, '\\"');
|
|
output += key + ': "' + value + '"\n';
|
|
});
|
|
output += '---\n\n' + post.content + '\n';
|
|
|
|
const postDir = getPostDir(post, config);
|
|
await createDirPromise(postDir);
|
|
const postPath = path.join(postDir, getPostFilename(post, config));
|
|
await fs.promises.writeFile(postPath, output);
|
|
}
|
|
|
|
async function writeImageFilesPromise(posts, config) {
|
|
// collect image data from all posts into a single flattened array
|
|
let images = posts.flatMap(post => {
|
|
const postDir = getPostDir(post, config);
|
|
return post.meta.imageUrls.map(imageUrl => ({
|
|
postDir,
|
|
url: imageUrl,
|
|
filename: shared.getFilenameFromUrl(imageUrl)
|
|
}));
|
|
});
|
|
|
|
// package up images into payloads
|
|
const payloads = images.map((image, index) => ({
|
|
item: image,
|
|
name: image.filename,
|
|
delay: index * 100
|
|
}));
|
|
|
|
console.log('\nSaving images...');
|
|
await processPayloadsPromise(payloads, writeImageFilePromise);
|
|
}
|
|
|
|
async function writeImageFilePromise(image) {
|
|
let buffer;
|
|
try {
|
|
buffer = await requestPromiseNative.get({
|
|
url: image.url,
|
|
encoding: null // preserves binary encoding
|
|
});
|
|
} catch (ex) {
|
|
if (ex.name === 'StatusCodeError') {
|
|
// these errors contain a lot of noise, simplify to just the status code
|
|
ex.message = ex.statusCode;
|
|
}
|
|
throw ex;
|
|
}
|
|
|
|
const imageDir = path.join(image.postDir, 'images');
|
|
await createDirPromise(imageDir);
|
|
|
|
const imagePath = path.join(imageDir, image.filename);
|
|
const stream = fs.createWriteStream(imagePath);
|
|
stream.write(buffer);
|
|
}
|
|
|
|
async function createDirPromise(dir) {
|
|
return fs.promises.mkdir(dir, { recursive: true });
|
|
}
|
|
|
|
function getPostDir(post, config) {
|
|
let dir = config.output;
|
|
let dt = luxon.DateTime.fromISO(post.frontmatter.date);
|
|
|
|
if (config.yearmonthfolders) {
|
|
dir = path.join(dir, dt.toFormat('yyyy'), dt.toFormat('LL'));
|
|
} else if (config.yearfolders) {
|
|
dir = path.join(dir, dt.toFormat('yyyy'));
|
|
}
|
|
|
|
if (config.postfolders) {
|
|
let folder = post.meta.slug;
|
|
if (config.prefixdate) {
|
|
folder = dt.toFormat('yyyy-LL-dd') + '-' + folder;
|
|
}
|
|
dir = path.join(dir, folder);
|
|
}
|
|
|
|
return dir;
|
|
}
|
|
|
|
function getPostFilename(post, config) {
|
|
if (config.postfolders) {
|
|
// the containing folder name will be unique, just use index.md here
|
|
return 'index.md';
|
|
} else {
|
|
let filename = post.meta.slug + '.md';
|
|
if (config.prefixdate) {
|
|
let dt = luxon.DateTime.fromISO(post.frontmatter.date);
|
|
filename = dt.toFormat('yyyy-LL-dd') + '-' + filename;
|
|
}
|
|
return filename;
|
|
}
|
|
}
|
|
|
|
exports.writeFilesPromise = writeFilesPromise;
|