Merge pull request #144 from lonekorean/refactor-date-handling

Refactor date handling
This commit is contained in:
Will Boyd
2025-02-04 13:57:33 -05:00
committed by GitHub
7 changed files with 37 additions and 83 deletions
+3 -14
View File
@@ -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
+1 -1
View File
@@ -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);
+11 -3
View File
@@ -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;
+10
View File
@@ -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',
-51
View File
@@ -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'
// ];
+3 -12
View File
@@ -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
+9 -2
View File
@@ -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]) => {
@@ -81,6 +82,12 @@ async function loadMarkdownFilePromise(post) {
// array of one or more strings
outputValue = value.reduce((list, item) => `${list}\n - "${item}"`, '');
}
} else if (value instanceof luxon.DateTime) {
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, '\\"');
@@ -172,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);