From 4767b68000943fc93f26bd47aca3d056206d566f Mon Sep 17 00:00:00 2001 From: Oscar Otero Date: Sun, 27 Oct 2024 17:26:09 +0100 Subject: [PATCH] Fix #683 --- CHANGELOG.md | 2 + core/utils/data_values.ts | 74 +++++++++++++++++++-------- tests/__snapshots__/feed.test.ts.snap | 8 ++- tests/feed.test.ts | 4 +- 4 files changed, 59 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 918113a2..fc445eb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Go to the `v1` branch to see the changelog of Lume 1. - New plugin: `brotli` to compress files. [#681] - New plugin: `gzip` to compress files. [#680] - New `precompress` middleware, to serve precompressed files. [#664] +- Allow to specify fallbacks for `metas` and `feed` plugins [#683]. ### Fixed - Nav plugin: Breadcrumb with urls with CJK characters. @@ -570,6 +571,7 @@ Go to the `v1` branch to see the changelog of Lume 1. [#679]: https://github.com/lumeland/lume/issues/679 [#680]: https://github.com/lumeland/lume/issues/680 [#681]: https://github.com/lumeland/lume/issues/681 +[#683]: https://github.com/lumeland/lume/issues/683 [Unreleased]: https://github.com/lumeland/lume/compare/v2.3.3...HEAD [2.3.3]: https://github.com/lumeland/lume/compare/v2.3.2...v2.3.3 diff --git a/core/utils/data_values.ts b/core/utils/data_values.ts index aab93522..860a6bcf 100644 --- a/core/utils/data_values.ts +++ b/core/utils/data_values.ts @@ -8,37 +8,68 @@ import type { Data } from "../file.ts"; export function getDataValue(data: Partial, value?: unknown) { // Get the value from the page data if (typeof value === "string") { - if (value.startsWith("=")) { - const key = value.slice(1); - - if (!key.includes(".")) { - return data[key]; - } - - const keys = key.split("."); - let val = data; - for (const key of keys) { - val = val?.[key]; - } - return val; + return searchValue(data, value); + } + + if (typeof value === "function") { + return value(data); + } + + return value; +} + +function searchValue(data: Partial, value: string): unknown { + if (!value) { + return; + } + + if (value.startsWith("=")) { + let key = value.slice(1); + [key, value] = parseFallback(key); + + if (!key.includes(".")) { + return data[key] ?? searchValue(data, value); } - if (value.startsWith("$")) { - return queryCss(value, data.page?.document); + const keys = key.split("."); + let val = data; + for (const key of keys) { + val = val?.[key]; } + return val ?? searchValue(data, value); } - if (typeof value === "function") { - return value(data); + if (value.startsWith("$")) { + let selector = value.slice(1); + [selector, value] = parseFallback(selector); + + return queryCss(selector, data.page?.document) ?? searchValue(data, value); } return value; } -function queryCss(value: string, document?: Document) { - // https://regexr.com/7qnot - const checkForAttrPattern = /^\$(.+)\s+(?:attr\(([\w\-]+)\))$/; - const checkResult = value.match(checkForAttrPattern); +function parseFallback(key: string): [string, string] { + const fallback = key.indexOf("||"); + + if (fallback !== -1) { + return [ + key.slice(0, fallback).trim(), + key.slice(fallback + 2).trim(), + ]; + } + + return [ + key, + "", + ]; +} + +// https://regexr.com/7qnot +const checkForAttrPattern = /^(.+)\s+(?:attr\(([\w\-]+)\))$/; + +function queryCss(query: string, document?: Document) { + const checkResult = query.match(checkForAttrPattern); const hasAttr = checkResult?.[0]; if (hasAttr) { @@ -46,6 +77,5 @@ function queryCss(value: string, document?: Document) { return document?.querySelector(query)?.getAttribute(name); } - const query = value.slice(1); return document?.querySelector(query)?.innerHTML; } diff --git a/tests/__snapshots__/feed.test.ts.snap b/tests/__snapshots__/feed.test.ts.snap index b06c81af..5b2bdf2e 100644 --- a/tests/__snapshots__/feed.test.ts.snap +++ b/tests/__snapshots__/feed.test.ts.snap @@ -117,10 +117,10 @@ snapshot[`RSS plugin 2`] = `[]`; snapshot[`RSS plugin 3`] = ` [ { - content: '{"version":"https://jsonfeed.org/version/1","title":"My RSS Feed","home_page_url":"https://example.com/","feed_url":"https://example.com/feed.json","description":"","items":[{"id":"https://example.com/page5/","url":"https://example.com/page5/","title":"PAGE 5","content_html":"Content of Page 5","date_published":"Thu, 21 Jun 1979 23:45:00 GMT","date_modified":"Thu, 21 Jun 1979 23:45:00 GMT"}]}', + content: '{"version":"https://jsonfeed.org/version/1","title":"My RSS Feed","home_page_url":"https://example.com/","feed_url":"https://example.com/feed.json","items":[{"id":"https://example.com/page5/","url":"https://example.com/page5/","title":"PAGE 5","content_html":"Content of Page 5","date_published":"Thu, 21 Jun 1979 23:45:00 GMT","date_modified":"Thu, 21 Jun 1979 23:45:00 GMT"}]}', data: { basename: "feed", - content: '{"version":"https://jsonfeed.org/version/1","title":"My RSS Feed","home_page_url":"https://example.com/","feed_url":"https://example.com/feed.json","description":"","items":[{"id":"https://example.com/page5/","url":"https://example.com/page5/","title":"PAGE 5","content_html":"Content of Page 5","date_published":"Thu, 21 Jun 1979 23:45:00 GMT","date_modified":"Thu, 21 Jun 1979 23:45:00 GMT"}]}', + content: '{"version":"https://jsonfeed.org/version/1","title":"My RSS Feed","home_page_url":"https://example.com/","feed_url":"https://example.com/feed.json","items":[{"id":"https://example.com/page5/","url":"https://example.com/page5/","title":"PAGE 5","content_html":"Content of Page 5","date_published":"Thu, 21 Jun 1979 23:45:00 GMT","date_modified":"Thu, 21 Jun 1979 23:45:00 GMT"}]}', page: [ "src", "data", @@ -142,7 +142,6 @@ snapshot[`RSS plugin 3`] = ` My RSS Feed https://example.com/ - Wed, 01 Jan 2020 00:00:00 GMT en https://lume.land @@ -164,7 +163,6 @@ snapshot[`RSS plugin 3`] = ` My RSS Feed https://example.com/ - Wed, 01 Jan 2020 00:00:00 GMT en https://lume.land @@ -225,7 +223,7 @@ snapshot[`RSS plugin 3`] = ` }, { content: " -Content of Page 5", +Content of Page 5", data: { basename: "page5", children: "Content of Page 5", diff --git a/tests/feed.test.ts b/tests/feed.test.ts index f83edb10..a3ae816b 100644 --- a/tests/feed.test.ts +++ b/tests/feed.test.ts @@ -16,8 +16,8 @@ Deno.test("RSS plugin", async (t) => { }, items: { title: (data) => data.title?.toUpperCase(), - updated: "=date", - published: "=published", + updated: "=date || $.date", + published: "$.not-found || =published", }, }), );