From 8a25175c733dfbfdd353392fa745281f9d42afa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20N=C3=BDvlt?= Date: Mon, 17 Jun 2024 10:13:05 +0200 Subject: [PATCH 1/4] Fix datetimes being incorrectly encoded in frontmatter as strings instead of YAML timestamps --- src/writer.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/writer.js b/src/writer.js index d8f8701..c81d229 100644 --- a/src/writer.js +++ b/src/writer.js @@ -81,6 +81,8 @@ async function loadMarkdownFilePromise(post) { // array of one or more strings outputValue = value.reduce((list, item) => `${list}\n - "${item}"`, ''); } + } else if (value instanceof luxon.DateTime) { + outputValue = encodeDate(value); } else { // single string value const escapedValue = (value || '').replace(/"/g, '\\"'); @@ -98,6 +100,16 @@ async function loadMarkdownFilePromise(post) { return output; } +function encodeDate(dateTime) { + if (settings.custom_date_formatting) { + return dateTime.toFormat(settings.custom_date_formatting); + } else if (settings.include_time_with_date) { + return dateTime.toISO(); + } else { + return dateTime.toISODate(); + } +} + async function writeImageFilesPromise(posts, config) { // collect image data from all posts into a single flattened array of payloads let skipCount = 0; From 7934f4e4b44c42bcf45759b3fc55770752b3b7f4 Mon Sep 17 00:00:00 2001 From: Will Boyd Date: Mon, 3 Feb 2025 14:27:37 -0500 Subject: [PATCH 2/4] Change when date is formatted --- src/frontmatter.js | 17 +++-------------- src/parser.js | 14 +++++++++++--- src/questions.js | 10 ++++++++++ src/writer.js | 19 +++++++------------ 4 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/frontmatter.js b/src/frontmatter.js index f2c74e1..1926037 100644 --- a/src/frontmatter.js +++ b/src/frontmatter.js @@ -1,6 +1,3 @@ -import * as luxon from 'luxon'; -import * as settings from './settings.js'; - // get author, without decoding // WordPress doesn't allow funky characters in usernames anyway export function author(post) { @@ -26,18 +23,10 @@ export function coverImage(post) { return post.meta.coverImage; } -// get post date, optionally formatted as specified in settings +// get post date, previously saved as a luxon datetime object on post.meta // this value is also used for year/month folders, date prefixes, etc. as needed -export function date(post, config) { - const dateTime = luxon.DateTime.fromRFC2822(post.data.pubDate[0], { zone: settings.custom_date_timezone }); - - if (settings.custom_date_formatting) { - return dateTime.toFormat(settings.custom_date_formatting); - } else if (config.includeTimeWithDate) { - return dateTime.toISO(); - } else { - return dateTime.toISODate(); - } +export function date(post) { + return post.meta.date; } // get excerpt, not decoded, newlines collapsed diff --git a/src/parser.js b/src/parser.js index b30c655..6819488 100644 --- a/src/parser.js +++ b/src/parser.js @@ -1,4 +1,5 @@ import fs from 'fs'; +import * as luxon from 'luxon'; import xml2js from 'xml2js'; import * as frontmatter from './frontmatter.js'; import * as shared from './shared.js'; @@ -65,12 +66,15 @@ function collectPosts(channelData, postTypes, config) { // meta data isn't written to file, but is used to help with other things meta: { + type: postType, id: getPostId(postData), slug: getPostSlug(postData), + date: getPostDate(postData, config), coverImageId: getPostCoverImageId(postData), - coverImage: undefined, // possibly set later in mergeImagesIntoPosts() - type: postType, - imageUrls: [] // possibly set later in mergeImagesIntoPosts() + + // these are possibly set later in mergeImagesIntoPosts() + coverImage: undefined, + imageUrls: [] }, // contents of the post in markdown @@ -98,6 +102,10 @@ function getPostSlug(postData) { return decodeURIComponent(postData.post_name[0]); } +function getPostDate(postData, config) { + return luxon.DateTime.fromRFC2822(postData.pubDate[0], { zone: config.customDateTimezone }); +} + function getPostCoverImageId(postData) { if (postData.postmeta === undefined) { return undefined; diff --git a/src/questions.js b/src/questions.js index 0e09b86..bf31cbe 100644 --- a/src/questions.js +++ b/src/questions.js @@ -125,6 +125,16 @@ export const all = [ type: 'boolean', default: false }, + { + name: 'custom-date-formatting', + type: 'string', + default: '' + }, + { + name: 'custom-date-timezone', + type: 'string', + default: 'utc' + }, { name: 'strict-ssl', type: 'boolean', diff --git a/src/writer.js b/src/writer.js index c81d229..239803b 100644 --- a/src/writer.js +++ b/src/writer.js @@ -3,6 +3,7 @@ import chalk from 'chalk'; import fs from 'fs'; import http from 'http'; import https from 'https'; +import * as luxon from 'luxon'; import path from 'path'; import * as shared from './shared.js'; @@ -71,7 +72,7 @@ async function writeMarkdownFilesPromise(posts, config) { } } -async function loadMarkdownFilePromise(post) { +async function loadMarkdownFilePromise(post, config) { let output = '---\n'; Object.entries(post.frontmatter).forEach(([key, value]) => { @@ -82,7 +83,11 @@ async function loadMarkdownFilePromise(post) { outputValue = value.reduce((list, item) => `${list}\n - "${item}"`, ''); } } else if (value instanceof luxon.DateTime) { - outputValue = encodeDate(value); + if (config.customDateFormatting) { + outputValue = value.toFormat(config.customDateFormatting); + } else { + outputValue = config.includeTimeWithDate ? value.toISO() : value.toISODate(); + } } else { // single string value const escapedValue = (value || '').replace(/"/g, '\\"'); @@ -100,16 +105,6 @@ async function loadMarkdownFilePromise(post) { return output; } -function encodeDate(dateTime) { - if (settings.custom_date_formatting) { - return dateTime.toFormat(settings.custom_date_formatting); - } else if (settings.include_time_with_date) { - return dateTime.toISO(); - } else { - return dateTime.toISODate(); - } -} - async function writeImageFilesPromise(posts, config) { // collect image data from all posts into a single flattened array of payloads let skipCount = 0; From 71028a272b4629cbf94d09b1d2de9ccff208f7b7 Mon Sep 17 00:00:00 2001 From: Will Boyd Date: Mon, 3 Feb 2025 14:47:43 -0500 Subject: [PATCH 3/4] Fix date stuff in path building --- src/intake.js | 2 +- src/shared.js | 15 +++------------ src/writer.js | 2 +- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/intake.js b/src/intake.js index 63763e2..ea2dfa8 100644 --- a/src/intake.js +++ b/src/intake.js @@ -158,7 +158,7 @@ function normalize(value, type, onError) { export function buildSamplePostPath(config) { const outputDir = path.sep; const type = ''; - const date = luxon.DateTime.now().toFormat('yyyy-LL-dd'); + const date = luxon.DateTime.now(); const slug = 'my-post'; return shared.buildPostPath(outputDir, type, date, slug, config); diff --git a/src/shared.js b/src/shared.js index 6557462..ecade32 100644 --- a/src/shared.js +++ b/src/shared.js @@ -1,30 +1,21 @@ -import * as luxon from 'luxon'; import path from 'path'; -import * as settings from './settings.js'; export function buildPostPath(outputDir, type, date, slug, config) { - let dt; - if (settings.custom_date_formatting) { - dt = luxon.DateTime.fromFormat(date, settings.custom_date_formatting); - } else { - dt = luxon.DateTime.fromISO(date); - } - // start with base output dir and post type const pathSegments = [outputDir, type]; if (config.dateFolders === 'year' || config.dateFolders === 'year-month') { - pathSegments.push(dt.toFormat('yyyy')); + pathSegments.push(date.toFormat('yyyy')); } if (config.dateFolders === 'year-month') { - pathSegments.push(dt.toFormat('LL')); + pathSegments.push(date.toFormat('LL')); } // create slug fragment, possibly date prefixed let slugFragment = slug; if (config.prefixDate) { - slugFragment = dt.toFormat('yyyy-LL-dd') + '-' + slugFragment; + slugFragment = date.toFormat('yyyy-LL-dd') + '-' + slugFragment; } // use slug fragment as folder or filename as specified diff --git a/src/writer.js b/src/writer.js index 239803b..1d82afa 100644 --- a/src/writer.js +++ b/src/writer.js @@ -179,7 +179,7 @@ async function loadImageFilePromise(imageUrl, config) { function buildPostPath(post, config) { const outputDir = config.output; const type = post.meta.type; - const date = post.frontmatter.date; + const date = post.meta.date; const slug = post.meta.slug; return shared.buildPostPath(outputDir, type, date, slug, config); From 032131818346686974f7a2d813ae216ee0133c0a Mon Sep 17 00:00:00 2001 From: Will Boyd Date: Tue, 4 Feb 2025 13:51:24 -0500 Subject: [PATCH 4/4] Remove settings.js --- src/settings.js | 51 ------------------------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 src/settings.js diff --git a/src/settings.js b/src/settings.js deleted file mode 100644 index 97f5e9e..0000000 --- a/src/settings.js +++ /dev/null @@ -1,51 +0,0 @@ -// Which fields to include in frontmatter. Look in /src/frontmatter.js to see available fields. -// Order is preserved. If a field has an empty value, it will not be included. You can rename a -// field by providing an alias after a ':'. For example, 'date:created' will include 'date' in -// frontmatter, but renamed to 'created'. -// export const frontmatter_fields = [ -// 'title', -// 'date', -// 'categories', -// 'tags', -// 'coverImage' -// ]; - -// Time in ms to wait between requesting image files. Increase this if you see timeouts or -// server errors. -// export const image_file_request_delay = 500; - -// Time in ms to wait between saving Markdown files. Increase this if your file system becomes -// overloaded. -// export const markdown_file_write_delay = 25; - -// Enable this to include time with post dates. For example, "2020-12-25" would become -// "2020-12-25T11:20:35.000Z". -// export const include_time_with_date = false; - -// Override post date formatting with a custom formatting string (for example: 'yyyy LLL dd'). -// Tokens are documented here: https://moment.github.io/luxon/#/parsing?id=table-of-tokens. If -// set, this takes precedence over include_time_with_date. -export const custom_date_formatting = ''; - -// Specify the timezone used for post dates. See available zone values and examples here: -// https://moment.github.io/luxon/#/zones?id=specifying-a-zone. -export const custom_date_timezone = 'utc'; - -// Categories to be excluded from post frontmatter. This does not filter out posts themselves, -// just the categories listed in their frontmatter. -// export const filter_categories = ['uncategorized']; - -// Strict SSL is enabled as the safe default when downloading images, but will not work with -// self-signed servers. You can disable it if you're getting a "self-signed certificate" error. -// export const strict_ssl = true; - -// Post types to exclude from output. -// export const filter_post_types = [ -// 'attachment', -// 'revision', -// 'nav_menu_item', -// 'custom_css', -// 'customize_changeset', -// 'wp_global_styles', -// 'wp_navigation' -// ];