Skip to content

Instantly share code, notes, and snippets.

@monochromer
Last active June 28, 2023 19:05
Show Gist options
  • Save monochromer/2daab8fa5fb183c96810f4491c1de8fa to your computer and use it in GitHub Desktop.
Save monochromer/2daab8fa5fb183c96810f4491c1de8fa to your computer and use it in GitHub Desktop.
Eleventy double pagination
function createPagination(paginationOptions) {
return {
data: typeof paginationOptions.data === 'string'
? paginationOptions.data
: 'collections.all',
size: 1,
alias: paginationOptions.alias ?? 'paginationChunk',
before: function(paginationData, data) {
const chunks = [];
const pageSize = paginationOptions.pageSize;
const allItems = typeof paginationOptions.data === 'function'
? paginationOptions.data(data)
: data[paginationOptions.data];
const getKey = typeof paginationOptions.key === 'function'
? paginationOptions.key
: (item) => item[paginationOptions.key];
const itemsByKey = allItems.reduce((map, item) => {
const key = getKey(item);
map[key] = map[key] || [];
map[key].push(item);
return map;
}, {});
for (const [key, group] of Object.entries(itemsByKey)) {
const pageNumbers = Math.ceil(group.length / pageSize);
const groupChunks = [];
for (let page = 0; page < pageNumbers; page++) {
const items = group.slice(pageSize * page, pageSize * (page + 1));
const item = {
key,
items,
pageSize,
page,
};
Object.defineProperty(item, 'next', {
enumerable: false,
get() {
return groupChunks[page + 1]
}
});
Object.defineProperty(item, 'previous', {
enumerable: false,
get() {
return groupChunks[page - 1]
}
});
groupChunks.push(item);
}
chunks.push(...groupChunks);
}
return chunks;
}
}
}
module.exports = {
users: [
{
id: 1,
name: 'User 1',
role: 'developer'
},
{
id: 2,
name: 'User 2',
role: 'manager'
},
{
id: 3,
name: 'User 3',
role: 'designer'
},
{
id: 4,
name: 'User 4',
role: 'developer'
},
{
id: 5,
name: 'User 5',
role: 'manager'
},
{
id: 6,
name: 'User 6',
role: 'designer'
},
{
id: 7,
name: 'User 7',
role: 'developer'
},
{
id: 8,
name: 'User 8',
role: 'manager'
},
{
id: 9,
name: 'User 9',
role: 'designer'
},
],
pagination: createPagination({
alias: 'paginationChunk',
pageSize: 2,
data: data => data.users,
key: (item) => item.role,
}),
eleventyComputed: {
permalink: function(data) {
const { paginationChunk } = data;
const pageNumber = paginationChunk.page === 0 ? '' : `${paginationChunk.page}/`;
return `/${paginationChunk.key}/${pageNumber}`
},
}
}

Eleventy double pagination

For example, for users collection:

const users = [
  {
    id: 1,
    name: 'User 1',
    role: 'developer'
  },
  {
    id: 2,
    name: 'User 2',
    role: 'manager'
  },
  {
    id: 3,
    name: 'User 3',
    role: 'designer'
  },
  {
    id: 4,
    name: 'User 4',
    role: 'developer'
  },
  {
    id: 5,
    name: 'User 5',
    role: 'manager'
  },
  {
    id: 6,
    name: 'User 6',
    role: 'designer'
  },
  {
    id: 7,
    name: 'User 7',
    role: 'developer'
  },
  {
    id: 8,
    name: 'User 8',
    role: 'manager'
  },
  {
    id: 9,
    name: 'User 9',
    role: 'designer'
  },
]

it produces files output:

/developer/
/developer/1
/manager/
/manager/1/
/designer/
/designer/1
.etc
---
permalink: /
---
<h2>Chunk</h2>
<pre>{{ paginationChunk | dump(2) | safe }}</pre>
<h2>Next</h2>
<pre>{{ paginationChunk.next | dump(2) | safe }}</pre>
<h2>Prev</h2>
<pre>{{ paginationChunk.previous | dump(2) | safe }}</pre>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment