From 77b5ed54ff722f8c961385c7e033becd0711798d Mon Sep 17 00:00:00 2001 From: Jeremy Epstein Date: Thu, 16 Dec 2021 11:35:25 +1100 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 | 21 ++++++++++++--------- 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, 61 insertions(+), 14 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 a2fce8ef9..ebc772542 100755 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -2,6 +2,7 @@ const lodashChunk = require("lodash/chunk"); const lodashGet = require("lodash/get"); const lodashSet = require("lodash/set"); const EleventyBaseError = require("../EleventyBaseError"); +const getPaginationDataKey = require("../Util/GetPaginationDataKey"); class PaginationConfigError extends EleventyBaseError {} class PaginationError extends EleventyBaseError {} @@ -30,13 +31,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( @@ -63,7 +64,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; @@ -129,16 +130,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; @@ -205,7 +208,7 @@ class Pagination { getOverrideData(pageItems) { let override = { pagination: { - data: this.data.pagination.data, + data: getPaginationDataKey(this.data), size: this.data.pagination.size, alias: this.alias, items: pageItems, diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 13f3e45e9..49dcaa491 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -5,6 +5,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"); @@ -78,16 +79,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 a1d67e0c8..5bf45cc71 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -654,6 +654,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 %}