From 2eb7e25854000090bdb3a8729aed3c3c1f06e381 Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Sat, 6 Jul 2024 15:07:40 +0200 Subject: [PATCH] Parse YAML dates into strings --- common/settings.ts | 4 ++-- plug-api/lib/frontmatter.ts | 5 +++-- plug-api/lib/json.test.ts | 8 ++++---- plug-api/lib/json.ts | 35 +++++++++++++++++++++++++++++++---- website/CHANGELOG.md | 1 + 5 files changed, 41 insertions(+), 12 deletions(-) diff --git a/common/settings.ts b/common/settings.ts index dd100101..7ec4cab4 100644 --- a/common/settings.ts +++ b/common/settings.ts @@ -1,7 +1,7 @@ import YAML from "js-yaml"; import { INDEX_TEMPLATE, SETTINGS_TEMPLATE } from "./PAGE_TEMPLATES.ts"; import { SpacePrimitives } from "./spaces/space_primitives.ts"; -import { expandPropertyNames } from "../plug-api/lib/json.ts"; +import { cleanupJSON } from "../plug-api/lib/json.ts"; import type { BuiltinSettings } from "../type/web.ts"; const yamlSettingsRegex = /^(```+|~~~+)ya?ml\r?\n([\S\s]+?)\1/m; @@ -97,6 +97,6 @@ export async function ensureAndLoadSettingsAndIndex( } const settings: any = parseYamlSettings(settingsText); - expandPropertyNames(settings); + cleanupJSON(settings); return { ...defaultSettings, ...settings }; } diff --git a/plug-api/lib/frontmatter.ts b/plug-api/lib/frontmatter.ts index 06f33f0d..ca4b39af 100644 --- a/plug-api/lib/frontmatter.ts +++ b/plug-api/lib/frontmatter.ts @@ -5,7 +5,7 @@ import { replaceNodesMatchingAsync, traverseTreeAsync, } from "./tree.ts"; -import { expandPropertyNames } from "./json.ts"; +import { cleanupJSON } from "./json.ts"; import { YAML } from "../syscalls.ts"; export type FrontMatter = { tags?: string[] } & Record; @@ -73,6 +73,7 @@ export async function extractFrontmatter( const yamlText = renderToText(yamlNode); try { const parsedData: any = await YAML.parse(yamlText); + console.log("Parsed front matter", parsedData); const newData = { ...parsedData }; data = { ...data, ...parsedData }; // Make sure we have a tags array @@ -130,7 +131,7 @@ export async function extractFrontmatter( // console.log("Extracted tags", data.tags); // Expand property names (e.g. "foo.bar" => { foo: { bar: true } }) - data = expandPropertyNames(data); + data = cleanupJSON(data); return data; } diff --git a/plug-api/lib/json.test.ts b/plug-api/lib/json.test.ts index dbf1c4e4..9d8ebbc3 100644 --- a/plug-api/lib/json.test.ts +++ b/plug-api/lib/json.test.ts @@ -1,5 +1,5 @@ import { assertEquals } from "$std/testing/asserts.ts"; -import { deepEqual, deepObjectMerge, expandPropertyNames } from "./json.ts"; +import { cleanupJSON, deepEqual, deepObjectMerge } from "./json.ts"; Deno.test("utils", () => { assertEquals(deepEqual({ a: 1 }, { a: 1 }), true); @@ -11,11 +11,11 @@ Deno.test("utils", () => { assertEquals(deepObjectMerge({ a: { b: 1 } }, { a: { c: 2 } }), { a: { b: 1, c: 2 }, }); - assertEquals(expandPropertyNames({ "a.b": 1 }), { a: { b: 1 } }); - assertEquals(expandPropertyNames({ a: { "a.b": 1 } }), { + assertEquals(cleanupJSON({ "a.b": 1 }), { a: { b: 1 } }); + assertEquals(cleanupJSON({ a: { "a.b": 1 } }), { a: { a: { b: 1 } }, }); - assertEquals(expandPropertyNames({ a: [{ "a.b": 1 }] }), { + assertEquals(cleanupJSON({ a: [{ "a.b": 1 }] }), { a: [{ a: { b: 1 } }], }); }); diff --git a/plug-api/lib/json.ts b/plug-api/lib/json.ts index 7bb56758..0c3d4432 100644 --- a/plug-api/lib/json.ts +++ b/plug-api/lib/json.ts @@ -34,8 +34,31 @@ export function deepEqual(a: any, b: any): boolean { return false; } -// Expands property names in an object containing a .-separated path -export function expandPropertyNames(a: any): any { +// Converts a Date object to a date string in the format YYYY-MM-DD if it just contains a date (and no significant time), or a full ISO string otherwise +export function cleanStringDate(d: Date): string { + function pad(n: number) { + let s = String(n); + if (s.length === 1) { + s = "0" + s; + } + return s; + } + + // If no significant time, return a date string only + if ( + d.getUTCHours() === 0 && d.getUTCMinutes() === 0 && d.getUTCSeconds() === 0 + ) { + return d.getFullYear() + "-" + pad(d.getMonth() + 1) + "-" + + pad(d.getDate()); + } else { + return d.toISOString(); + } +} + +// Processes a JSON (typically coming from parse YAML frontmatter) in two ways: +// 1. Expands property names in an object containing a .-separated path +// 2. Converts dates to strings in sensible ways +export function cleanupJSON(a: any): any { if (!a) { return a; } @@ -43,7 +66,11 @@ export function expandPropertyNames(a: any): any { return a; } if (Array.isArray(a)) { - return a.map(expandPropertyNames); + return a.map(cleanupJSON); + } + // If a is a date, convert to a string + if (a instanceof Date) { + return cleanStringDate(a); } const expanded: any = {}; for (const key of Object.keys(a)) { @@ -56,7 +83,7 @@ export function expandPropertyNames(a: any): any { } target = target[part]; } - target[parts[parts.length - 1]] = expandPropertyNames(a[key]); + target[parts[parts.length - 1]] = cleanupJSON(a[key]); } return expanded; } diff --git a/website/CHANGELOG.md b/website/CHANGELOG.md index bbb181ab..60ed7589 100644 --- a/website/CHANGELOG.md +++ b/website/CHANGELOG.md @@ -15,6 +15,7 @@ _These features are not yet properly released, you need to use [the edge builds] * Improved selection behavior (by [MrMugame](https://github.com/silverbulletmd/silverbullet/pull/904)) * Hide `\` escapes in [[Live Preview]] (by [MrMugame](https://github.com/silverbulletmd/silverbullet/pull/901)) * Added Erlang [[Markdown/Syntax Highlighting]] +* Dates (formatted as e.g. `2023-07-01` or `2023-07-01 23:33`) in [[Frontmatter]] are now converted into strings (rather than empty objects) * Numerous other bug fixes (thanks MrMugame and onespaceman) ---