Skip to content

Commit

Permalink
Pagination: let data key be a function
Browse files Browse the repository at this point in the history
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;
        },
    ...
  • Loading branch information
Jaza committed Dec 16, 2021
1 parent 4a505f1 commit 77b5ed5
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 14 deletions.
21 changes: 12 additions & 9 deletions src/Plugins/Pagination.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down Expand Up @@ -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(
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
9 changes: 4 additions & 5 deletions src/TemplateMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down Expand Up @@ -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));
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/Util/GetPaginationDataKey.js
Original file line number Diff line number Diff line change
@@ -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;
};
13 changes: 13 additions & 0 deletions test/GetPaginationDataKeyTest.js
Original file line number Diff line number Diff line change
@@ -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"
);
});
14 changes: 14 additions & 0 deletions test/PaginationTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
11 changes: 11 additions & 0 deletions test/stubs/paged/paged-data-key-func.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---js
{
dataCanBeFoundIn: "items",
pagination: {
data: (data) => data.dataCanBeFoundIn,
size: 1
},
items: ["foo", "woo"]
}
---
<ol>{% for item in pagination.items %}<li>{{ item }}</li>{% endfor %}</ol>

0 comments on commit 77b5ed5

Please sign in to comment.