From 37ef0f6dcaeb6418cf942dc2fe32ecd6a0806d74 Mon Sep 17 00:00:00 2001 From: Jeremy Epstein Date: Thu, 12 May 2022 09:49:11 +1000 Subject: [PATCH] Pagination: let data key be a function So that pagination data key can be determined dynamically, based on a callback function that gets passed all template data. So you can do something like: ---js { pagination: { data: (data) => { return "collections." + data.foo; }, ... --- src/Plugins/Pagination.js | 19 +++++++++++-------- src/TemplateMap.js | 9 ++++----- src/Util/GetPaginationDataKey.js | 7 +++++++ test/GetPaginationDataKeyTest.js | 13 +++++++++++++ test/PaginationTest.js | 14 ++++++++++++++ test/stubs/paged/paged-data-key-func.njk | 11 +++++++++++ 6 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 src/Util/GetPaginationDataKey.js create mode 100644 test/GetPaginationDataKeyTest.js create mode 100644 test/stubs/paged/paged-data-key-func.njk diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index 7a52166b0..300f1536e 100755 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -4,6 +4,7 @@ const lodashSet = require("lodash/set"); const EleventyBaseError = require("../EleventyBaseError"); const { DeepCopy } = require("../Util/Merge"); const { ProxyWrap } = require("../Util/ProxyWrap"); +const getPaginationDataKey = require("../Util/GetPaginationDataKey"); class PaginationConfigError extends EleventyBaseError {} class PaginationError extends EleventyBaseError {} @@ -32,13 +33,13 @@ class Pagination { return Pagination.hasPagination(this.data); } - circularReferenceCheck(data) { - if (data.eleventyExcludeFromCollections) { + circularReferenceCheck() { + if (this.data.eleventyExcludeFromCollections) { return; } - let key = data.pagination.data; - let tags = data.tags || []; + let key = getPaginationDataKey(this.data); + let tags = this.data.tags || []; for (let tag of tags) { if (`collections.${tag}` === key) { throw new PaginationError( @@ -65,7 +66,7 @@ class Pagination { } else if (!("size" in data.pagination)) { throw new Error("Missing pagination size in front matter data."); } - this.circularReferenceCheck(data); + this.circularReferenceCheck(); this.size = data.pagination.size; this.alias = data.pagination.alias; @@ -141,16 +142,18 @@ class Pagination { _has(target, key) { let notFoundValue = "__NOT_FOUND_ERROR__"; - let data = lodashGet(target, key, notFoundValue); + let paginationDataKey = getPaginationDataKey(this.data); + let data = lodashGet(target, paginationDataKey, notFoundValue); return data !== notFoundValue; } _get(target, key) { let notFoundValue = "__NOT_FOUND_ERROR__"; - let data = lodashGet(target, key, notFoundValue); + let paginationDataKey = getPaginationDataKey(this.data); + let data = lodashGet(target, paginationDataKey, notFoundValue); if (data === notFoundValue) { throw new Error( - `Could not find pagination data, went looking for: ${key}` + `Could not find pagination data, went looking for: ${paginationDataKey}` ); } return data; diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 7b1ec2779..a05cd0ed5 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -6,6 +6,7 @@ const EleventyErrorUtil = require("./EleventyErrorUtil"); const UsingCircularTemplateContentReferenceError = require("./Errors/UsingCircularTemplateContentReferenceError"); const debug = require("debug")("Eleventy:TemplateMap"); const debugDev = require("debug")("Dev:Eleventy:TemplateMap"); +const getPaginationDataKey = require("./Util/GetPaginationDataKey"); const EleventyBaseError = require("./EleventyBaseError"); @@ -81,16 +82,14 @@ class TemplateMap { */ isPaginationOverAllCollections(entry) { if (entry.data.pagination && entry.data.pagination.data) { - return ( - entry.data.pagination.data === "collections" || - entry.data.pagination.data === "collections.all" - ); + const key = getPaginationDataKey(entry.data); + return key === "collections" || key === "collections.all"; } } getPaginationTagTarget(entry) { if (entry.data.pagination && entry.data.pagination.data) { - return this.getTagTarget(entry.data.pagination.data); + return this.getTagTarget(getPaginationDataKey(entry.data)); } } diff --git a/src/Util/GetPaginationDataKey.js b/src/Util/GetPaginationDataKey.js new file mode 100644 index 000000000..12abd3f2d --- /dev/null +++ b/src/Util/GetPaginationDataKey.js @@ -0,0 +1,7 @@ +const lodashIsFunction = require("lodash/isFunction"); + +module.exports = function (data) { + return lodashIsFunction(data.pagination.data) + ? data.pagination.data(data) + : data.pagination.data; +}; diff --git a/test/GetPaginationDataKeyTest.js b/test/GetPaginationDataKeyTest.js new file mode 100644 index 000000000..97050277b --- /dev/null +++ b/test/GetPaginationDataKeyTest.js @@ -0,0 +1,13 @@ +const test = require("ava"); +const getPaginationDataKey = require("../src/Util/GetPaginationDataKey"); + +test("getPaginationDataKey when key is string", (t) => { + t.is(getPaginationDataKey({pagination: {data: "foo"}}), "foo"); +}); + +test("getPaginationDataKey when key is function", (t) => { + t.is( + getPaginationDataKey({foo: "bar", pagination: {data: (data) => data.foo}}), + "bar" + ); +}); diff --git a/test/PaginationTest.js b/test/PaginationTest.js index f1462d37b..89e8fe0dc 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -706,6 +706,20 @@ test("Pagination `before` Callback with a Filter", async (t) => { t.deepEqual(templates[0].data.myalias, "item2"); }); +test("Pagination when `data` is a function", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/paged/paged-data-key-func.njk", + "./test/stubs/", + "./dist" + ); + + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + t.is(templates.length, 2); + t.deepEqual(templates[0].data.pagination.items, ["foo"]); + t.deepEqual(templates[1].data.pagination.items, ["woo"]); +}); + test("Pagination `before` Callback with `reverse: true` (test order of operations)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/paged/paged-before-and-reverse.njk", diff --git a/test/stubs/paged/paged-data-key-func.njk b/test/stubs/paged/paged-data-key-func.njk new file mode 100644 index 000000000..9c4f29f2c --- /dev/null +++ b/test/stubs/paged/paged-data-key-func.njk @@ -0,0 +1,11 @@ +---js +{ + dataCanBeFoundIn: "items", + pagination: { + data: (data) => data.dataCanBeFoundIn, + size: 1 + }, + items: ["foo", "woo"] +} +--- +
    {% for item in pagination.items %}
  1. {{ item }}
  2. {% endfor %}