Skip to content

Allow dynamic collection pagination#781

Merged
damiani merged 3 commits into
mainfrom
nd/dynamic-collection-pagination
May 1, 2026
Merged

Allow dynamic collection pagination#781
damiani merged 3 commits into
mainfrom
nd/dynamic-collection-pagination

Conversation

@nicodevs

@nicodevs nicodevs commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

This PR allows paginating custom, dynamic collections. Fixes #273, although it does not use the config approach suggested there.

Issue

To paginate a collection, Jigsaw requires a source Blade template with a pagination key in its YAML front matter pointing at the target collection.

This breaks for dynamic collections, those generated at build time, like posts grouped by tag. You can build them in afterCollections, but each still needs a source file (source/tags/php.blade.php, source/tags/laravel.blade.php, source/tags/javascript.blade.php, etc.) created before you even know which tags exist.

Solution

With this PR, you can register paginated collections on the fly thanks to paginateCollection. The typical use case is tag/category pages. Let's say you want paginated pages of all your posts with certain tag ("PHP", "JavaScript", etc). In bootstrap.php:

$events->afterCollections(function (Jigsaw $jigsaw) {
    $posts = $jigsaw->getCollection('posts');

    $posts->flatMap(fn ($post) => $post->tags ?? [])
        ->unique()
        ->each(function ($tag) use ($jigsaw, $posts) {
            $slug = str($tag)->slug();
            
            $jigsaw->setConfig("tag_{$slug}", $posts->filter(fn ($p) => in_array($tag, $p->tags ?? [])));
            
            
            $jigsaw->paginateCollection(
                path: "tags/{$slug}",
                collection: "tag_{$slug}",
                template: '_layouts.tag',
                perPage: 5,
                variables: ['tag' => $tag],
            );
        });
});

That generates build/tags/php/index.html, build/tags/php/2/index.html, etc. Same pagination object ($pagination->items, $pagination->next, etc.) as the file-based approach, just driven from code instead of a source file.

What changed

  • New Jigsaw::paginateCollection() API: registers a paginated page definition (path, collection, template, perPage, optional variables) for deferred rendering after collections are built
  • PaginatedPageHandler::handleDefinition(): new method that renders paginated pages from a template view name instead of a source file
  • CollectionPaginator::paginate(): refactored to accept relativePath and filename as separate strings instead of a $file object, decoupling it from the filesystem
  • OutputFile: InputFile is now nullable to support pages that have no backing source file
  • SiteBuilder::generatePaginatedPages(): new private method that processes pending page definitions and merges them into the build output
  • ViewRenderer::renderView(): new method to render a view by name (using view()->make()) rather than by file path

How to test

  1. In bootstrap.php, hook into afterCollections. Use teh snippet presented above.
  2. Create a _layouts/tag.blade.php that uses $pagination.
  3. Run ./vendor/bin/jigsaw build and verify build/tags/php/index.html and paginated sub-pages are generated correctly.
  4. Run ./vendor/bin/phpunit tests/DynamicCollectionPaginationTest.php, all 5 tests should pass.

nicodevs and others added 2 commits April 24, 2026 15:21
..................................................✓.........................
.............................................

──────────────────────────────────────────────────────────────────── Laravel
FIXED ................................... 121 files, 1 style issue fixed
✓ src/Handlers/PaginatedPageHandler.php unary_operator_spaces, not_operator…
)
@nicodevs nicodevs marked this pull request as draft April 24, 2026 18:29
@nicodevs nicodevs self-assigned this Apr 24, 2026
@nicodevs nicodevs changed the title Add dynamic collection pagination via paginateCollection() Allow dynamic collection pagination Apr 24, 2026
@nicodevs nicodevs marked this pull request as ready for review April 24, 2026 18:46
@nicodevs nicodevs requested a review from damiani April 24, 2026 18:59
@damiani damiani merged commit f0daf38 into main May 1, 2026
5 checks passed
@damiani damiani deleted the nd/dynamic-collection-pagination branch May 1, 2026 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Custom collections with pagination

2 participants