diff --git a/.gitignore b/.gitignore index 0098ccd9..8f0d21cf 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ tmp/ #ignore specific filenames export.xml +export*.xml .DS_Store diff --git a/README.md b/README.md index 72fa0634..86fe5fd2 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,13 @@ Comma separated list of the frontmatter fields to include in Markdown files. Ord Allowed values: -- A comma separated list with any of the following: `author`, `categories`, `coverImage`, `date`, `draft`, `excerpt`, `id`, `slug`, `tags`, `title`, `type`. You can rename a field by appending `:` and the alias to use. For example, `date:created` will rename `date` to `created`. +- A comma separated list with any of the following: `author`, `categories`, `coverImage`, `date`, `draft`, `excerpt`, `id`, `slug`, `tags`, `title`, `type`, `meta`. + - You can rename a field by appending `:` and the alias to use. For example, `date:created` will rename `date` to `created`. + - `meta`: use *dot-notation* as following to access any available post-**meta** fields: + ```bash + npx wordpress-export-to-markdown --frontmatter-fields "title,date,categories,tags,coverImage,draft,meta.YOUR_CUSTOM_FIELDNAME:maybeAliased" + ``` + if the field is not available it is ignored. ### Delay between image file requests? diff --git a/app.js b/app.js old mode 100644 new mode 100755 index 806bc531..8c5e14d9 --- a/app.js +++ b/app.js @@ -36,3 +36,4 @@ import * as writer from './src/writer.js'; console.log('\nSomething went wrong, execution halted early.'); console.error(ex); }); + diff --git a/src/frontmatter.js b/src/frontmatter.js index 22f37c94..22f0741b 100644 --- a/src/frontmatter.js +++ b/src/frontmatter.js @@ -61,3 +61,7 @@ export function type(post) { // previously parsed but not decoded, can be "post", "page", or other custom types return post.type; } + +export function meta(post) { + return post.meta; +} diff --git a/src/parser.js b/src/parser.js index 3363c054..671c85f4 100644 --- a/src/parser.js +++ b/src/parser.js @@ -98,11 +98,12 @@ function buildPost(data) { isDraft: data.childValue('status') === 'draft', slug: decodeURIComponent(data.childValue('post_name')), date: getPostDate(data), + meta: getPostMeta(data), coverImageId: getPostMetaValue(data, '_thumbnail_id'), // these are possibly set later in mergeImagesIntoPosts() coverImage: undefined, - imageUrls: [] + imageUrls: [], }; } @@ -111,6 +112,22 @@ function getPostDate(data) { return date.isValid ? date : undefined; } +function getPostMeta(data) { + const metas = data.children("postmeta"); + let result = metas.reduce((acc, item) => { + const meta_key = item.childValue("meta_key"); + const meta_value = item.childValue("meta_value"); + // console.log("meta_key", meta_key); + // console.log("meta_value", meta_value); + // only add if meta_key is not starting with '_' as this seem to be internal field-names. + if (!meta_key.startsWith("_")) { + acc[meta_key] = meta_value; + } + return acc; + }, {}); + return result; +} + function getPostMetaValue(data, key) { const metas = data.children('postmeta'); const meta = metas.find((meta) => meta.childValue('meta_key') === key); @@ -196,13 +213,26 @@ function populateFrontmatter(posts) { post.frontmatter = {}; shared.config.frontmatterFields.forEach((field) => { const [key, alias] = field.split(':'); - - let frontmatterGetter = frontmatter[key]; + const [frontmatterGetterKey, subKey] = key.split('.') + let frontmatterGetter = frontmatter[frontmatterGetterKey]; if (!frontmatterGetter) { - throw `Could not find a frontmatter getter named "${key}".`; + throw `Could not find a frontmatter getter named "${frontmatterGetterKey}".`; + } + let frontmatterValue = frontmatterGetter(post); + if (subKey) { + const mainObj = frontmatterGetter(post); + frontmatterValue = mainObj[subKey]; + if (!frontmatterValue) { + // throw `Could not find a frontmatter value for subKey "${subKey}".`; + console.log( + `Could not find subKey "${subKey}" in postmeta. Ignoring.` + ); + } else { + post.frontmatter[alias ?? key] = frontmatterValue; + } + } else { + post.frontmatter[alias ?? key] = frontmatterValue; } - - post.frontmatter[alias ?? key] = frontmatterGetter(post); }); }); } diff --git a/src/shared.js b/src/shared.js index b62af447..fbfe250e 100644 --- a/src/shared.js +++ b/src/shared.js @@ -71,6 +71,10 @@ export function buildPostPath(post, overrideConfig) { return path.join(...pathSegments); } +export function getOutputPath(filename) { + return path.join(config.output, filename); +} + export function getFilenameFromUrl(url) { let filename = url.split('/').slice(-1)[0]; diff --git a/src/writer.js b/src/writer.js index cb73b131..34dbabb5 100644 --- a/src/writer.js +++ b/src/writer.js @@ -8,10 +8,18 @@ import path from 'path'; import * as shared from './shared.js'; export async function writeFilesPromise(posts) { + await writeJSONFile(posts); await writeMarkdownFilesPromise(posts); await writeImageFilesPromise(posts); } +async function writeJSONFile(posts) { + shared.logHeading(`Saving posts data as 'posts.json'`); + const jsonData = JSON.stringify(posts, undefined, 4); + const filename = shared.getOutputPath("posts.json"); + writeFile(filename, jsonData); +} + async function processPayloadsPromise(payloads, loadFunc) { const promises = payloads.map((payload) => new Promise((resolve, reject) => { setTimeout(async () => {