mirror of
https://github.com/10h30/wordpress-export-to-markdown.git
synced 2026-07-15 12:43:38 +09:00
All about that wizard
This commit is contained in:
+4
-4
@@ -13,13 +13,13 @@ async function parseFilePromise(config) {
|
||||
tagNameProcessors: [xml2js.processors.stripPrefix]
|
||||
});
|
||||
|
||||
let posts = collectPosts(data);
|
||||
let posts = collectPosts(data, config);
|
||||
|
||||
let images = [];
|
||||
if (config.saveattachedimages) {
|
||||
if (config.saveAttachedImages) {
|
||||
images.push(...collectAttachedImages(data));
|
||||
}
|
||||
if (config.savescrapedimages) {
|
||||
if (config.saveScrapedImages) {
|
||||
images.push(...collectScrapedImages(data));
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ function getItemsOfType(data, type) {
|
||||
return data.rss.channel[0].item.filter(item => item.post_type[0] === type);
|
||||
}
|
||||
|
||||
function collectPosts(data) {
|
||||
function collectPosts(data, config) {
|
||||
// this is passed into getPostContent() for the markdown conversion
|
||||
turndownService = translator.initTurndownService();
|
||||
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ function getPostContent(post, turndownService, config) {
|
||||
// without mucking up content inside of other elemnts (like <code> blocks)
|
||||
content = content.replace(/(\r?\n){2}/g, '\n<div></div>\n');
|
||||
|
||||
if (config.savescrapedimages) {
|
||||
if (config.saveScrapedImages) {
|
||||
// writeImageFile() will save all content images to a relative /images
|
||||
// folder so update references in post content to match
|
||||
content = content.replace(/(<img[^>]*src=").*?([^\/"]+\.(?:gif|jpe?g|png))("[^>]*>)/gi, '$1images/$2$3');
|
||||
|
||||
+147
-31
@@ -1,40 +1,156 @@
|
||||
const camelcase = require('camelcase');
|
||||
const chalk = require('chalk');
|
||||
const commander = require('commander');
|
||||
const fs = require('fs');
|
||||
const minimist = require('minimist');
|
||||
const inquirer = require('inquirer');
|
||||
const path = require('path');
|
||||
|
||||
function getConfig() {
|
||||
let args = process.argv.slice(2);
|
||||
let config = minimist(args, {
|
||||
string: [
|
||||
'input',
|
||||
'output'
|
||||
],
|
||||
boolean: [
|
||||
'yearmonthfolders',
|
||||
'yearfolders',
|
||||
'postfolders',
|
||||
'prefixdate',
|
||||
'saveattachedimages',
|
||||
'savescrapedimages'
|
||||
],
|
||||
default: {
|
||||
input: 'export.xml',
|
||||
output: 'output',
|
||||
yearmonthfolders: false,
|
||||
yearfolders: false,
|
||||
postfolders: true,
|
||||
prefixdate: false,
|
||||
saveattachedimages: true,
|
||||
savescrapedimages: true
|
||||
// expected user inputs are declard here
|
||||
const inputs = [
|
||||
// wizard must always be first
|
||||
{
|
||||
name: 'wizard',
|
||||
type: 'boolean',
|
||||
description: 'Use wizard',
|
||||
default: true
|
||||
},
|
||||
{
|
||||
name: 'input',
|
||||
type: 'file',
|
||||
description: 'Path to input file',
|
||||
default: 'export.xml'
|
||||
},
|
||||
{
|
||||
name: 'output',
|
||||
type: 'folder',
|
||||
description: 'Path to output folder',
|
||||
default: 'output'
|
||||
},
|
||||
{
|
||||
name: 'year-folders',
|
||||
type: 'boolean',
|
||||
description: 'Create year folders',
|
||||
default: false
|
||||
},
|
||||
{
|
||||
name: 'month-folders',
|
||||
type: 'boolean',
|
||||
description: 'Create month folders',
|
||||
default: false
|
||||
},
|
||||
{
|
||||
name: 'post-folders',
|
||||
type: 'boolean',
|
||||
description: 'Create a folder for each post',
|
||||
default: true
|
||||
},
|
||||
{
|
||||
name: 'prefix-date',
|
||||
type: 'boolean',
|
||||
description: 'Prefix post folders/files with date',
|
||||
default: false
|
||||
},
|
||||
{
|
||||
name: 'save-attached-images',
|
||||
type: 'boolean',
|
||||
description: 'Save images attached to posts',
|
||||
default: true
|
||||
},
|
||||
{
|
||||
name: 'save-scraped-images',
|
||||
type: 'boolean',
|
||||
description: 'Save images scraped from post body content',
|
||||
default: true
|
||||
}
|
||||
];
|
||||
|
||||
async function getConfig() {
|
||||
extendInputsData();
|
||||
const program = parseCommandLine(process.argv);
|
||||
|
||||
let questions = inputs.map(input => ({
|
||||
when: input.name !== 'wizard' && program.wizard && !input.isProvided,
|
||||
name: camelcase(input.name),
|
||||
type: input.prompt,
|
||||
message: input.description + '?',
|
||||
default: input.default,
|
||||
|
||||
// boolean inputs don't use filter or validate, which is fine
|
||||
filter: input.coerce,
|
||||
validate: input.validate
|
||||
}));
|
||||
let answers = await inquirer.prompt(questions);
|
||||
|
||||
const config = { ...program.opts(), ...answers };
|
||||
return config;
|
||||
}
|
||||
|
||||
function extendInputsData() {
|
||||
// based on each input's type, add more data that will be used later
|
||||
const map = {
|
||||
boolean: {
|
||||
prompt: 'confirm',
|
||||
coerce: coerceBoolean,
|
||||
},
|
||||
file: {
|
||||
prompt: 'input',
|
||||
coerce: coercePath,
|
||||
validate: validateFile
|
||||
},
|
||||
folder: {
|
||||
prompt: 'input',
|
||||
coerce: coercePath,
|
||||
validate: validateFolder
|
||||
}
|
||||
};
|
||||
|
||||
inputs.forEach(input => {
|
||||
Object.assign(input, map[input.type]);
|
||||
});
|
||||
}
|
||||
|
||||
function parseCommandLine(argv) {
|
||||
// setup for help output
|
||||
commander
|
||||
.name('node index.js')
|
||||
.helpOption('-h, --help', 'See the thing you\'re looking at right now')
|
||||
.on('--help', () => {
|
||||
console.log('\nMore documentation at https://github.com/lonekorean/wordpress-export-to-markdown');
|
||||
})
|
||||
|
||||
inputs.forEach(input => {
|
||||
const flag = '--' + input.name + ' <' + input.type + '>';
|
||||
const coerce = (value) => {
|
||||
// commander only calls coerce when an input is present on the command line, which
|
||||
// provides an easy way to flag (for later) if it should be excluded from the wizard
|
||||
input.isProvided = true;
|
||||
return input.coerce(value);
|
||||
};
|
||||
commander.option(flag, input.description, coerce, input.default);
|
||||
});
|
||||
|
||||
// TODO: when wizard is implemented user will be asked to repeat input instead of bombing
|
||||
if (!checkFileExists(config.input)) {
|
||||
throw new Error('Input file does not exist.');
|
||||
return commander.parse(argv);
|
||||
}
|
||||
|
||||
function coerceBoolean(value) {
|
||||
return !['false', 'no', '0'].includes(value.toLowerCase());
|
||||
}
|
||||
|
||||
function coercePath(value) {
|
||||
return path.normalize(value);
|
||||
}
|
||||
|
||||
function validateFile(value) {
|
||||
if (checkFileExists(value)) {
|
||||
return true;
|
||||
} else {
|
||||
return 'Unable to find file: ' + path.resolve(value);
|
||||
}
|
||||
|
||||
delete config._;
|
||||
return config;
|
||||
}
|
||||
|
||||
function validateFolder(value) {
|
||||
// TODO: implement
|
||||
return true;
|
||||
}
|
||||
|
||||
function checkFileExists(path) {
|
||||
|
||||
+6
-7
@@ -110,23 +110,22 @@ function getPostPath(post, config) {
|
||||
// start with base output dir
|
||||
let pathSegments = [config.output];
|
||||
|
||||
// add year/month dirs as specified
|
||||
if (config.yearfolders || config.yearmonthfolders) {
|
||||
if (config.yearFolders) {
|
||||
pathSegments.push(dt.toFormat('yyyy'));
|
||||
}
|
||||
|
||||
if (config.yearmonthfolders) {
|
||||
pathSegments.push(dt.toFormat('LL'));
|
||||
}
|
||||
if (config.monthFolders) {
|
||||
pathSegments.push(dt.toFormat('LL'));
|
||||
}
|
||||
|
||||
// create slug fragment, possibly date prefixed
|
||||
let slugFragment = post.meta.slug;
|
||||
if (config.prefixdate) {
|
||||
if (config.prefixDate) {
|
||||
slugFragment = dt.toFormat('yyyy-LL-dd') + '-' + slugFragment;
|
||||
}
|
||||
|
||||
// use slug fragment as folder or filename as specified
|
||||
if (config.postfolders) {
|
||||
if (config.postFolders) {
|
||||
pathSegments.push(slugFragment, 'index.md');
|
||||
} else {
|
||||
pathSegments.push(slugFragment + '.md');
|
||||
|
||||
Reference in New Issue
Block a user