assemble-pager
v0.1.2
Published
Assemble plugin that adds prev/next pager information to the context.
Downloads
2
Maintainers
Readme
assemble-pager
Assemble plugin that adds prev/next pager information to the context.
Table of Contents
(TOC generated by verb using markdown-toc)
Install
Install with npm:
$ npm install --save assemble-pager
Adds data to the context to enable creating pagers that work like this:
Usage
var assemble = require('assemble');
var pager = require('assemble-pager');
var app = assemble();
// register the plugin
app.use(pager());
app.task('site', function() {
return app.src('src/*.md')
.pipe(app.pager()) // then add "app.pager()" before "app.renderFile()"
.pipe(app.renderFile())
.pipe(app.dest('blog'));
});
When app.pager()
is called, it adds the pager
variable to the context so that it's available to all views in the collection being rendered.
Specify a collection
// only add paging to the "posts" collection
.pipe(app.pager({collection: 'posts'}))
Excluding files
If you don't specify a collection, all files in the stream will be buffered and included. However, you can selectively exclude files by setting file.data.pager
to false
, either in another plugin, middleware, or by defining it on yaml front-matter.
Examples
// plugin, defined before `app.pager()`
.pipe(through.obj(function(file, enc, next) {
file.data.pager = false;
next(null, file);
}))
// middleware
app.onLoad(/\.foo$/, function(file, next) {
file.data.pager = false;
next();
});
Or yaml front-matter
---
pager: false
---
This is a page that should be skipped by `app.pager()`
Template usage
The pager
variable is an object with the following properties:
pager.prev
{Object} - the previous view that was rendered. This is an actual view, so you can get any data you need from it (likepager.prev.path
orpager.prev.data.title
, etc)pager.next
{Object} - the next view to be rendered. This is an actual view, so you can get any data you need from it (likepager.next.path
orpager.next.data.title
, etc)pager.current
{Object} - the view that is currently being renderedpager.first
{Object} - Returns the first file in the listpager.last
{Object} - Returns the last file in the listpager.isFirst
{Boolean} - returns true if the "current" file is the first to be renderedpager.isLast
{Boolean} - returns true if the "current" file is the last to be renderedpager.index
{Number} - the list index of the current file being rendered
Helpers
Some helpers are included with this plugin. To use them, do the following:
var pager = require('assemble-pager');
app.helpers(pager.helpers);
Which adds the following helpers:
relative
- calculates the relative path from fileA
to fileB
(e.g. "current" file to next or previous file)ifFirst
- returns true if the current file being rendered is the first fileifLast
- returns true if the current file being rendered is the last filenext
- used inhref=""
, returns either the relative path to the "next" file, or#
if the current file being rendered is the last fileprev
- used inhref=""
, returns either the relative path to the "previous" file, or#
if the current file being rendered is the first fileattr
- stringify the options hash arguments to HTML attributes. For example, you can use this to conditionally add a class for a disabled next/prev link:{{ifFirst (attr class="disabled")}}
, or{{ifLast (attr class="disabled")}}
etc.
Overriding helpers
Helpers are exposed as an object so that you can choose to register them if you want, and/or override them if necessary:
For example, this is how the included "relative" helper works:
var relative = require('relative');
app.helper('relative', function(from, to) {
return relative(from.data.path, to.data.path);
});
Example usage
Since pager
is just another variable on the context, you can do anything you normally would with a variable in your handlebars templates.
<!-- generate relative paths using the relative helper
from the "usage" section above -->
<a href="{{#if pager.prev}}{{relative pager.current pager.prev}}{{/if}}">Prev</a>
Or you can create a block:
{{#pager}}
<!-- generate relative paths using "link-to" -->
<a href="{{#if prev}}{{relative current prev}}{{/if}}">Prev</a>
{{/pager}}
Partials
To simplify paging even more, you can define partials like the following:
app.partial('prev', '<a href="{{prev pager}}"{{ifFirst pager (attr class="disabled")}}>Prev</a>');
app.partial('next', '\n<a href="{{next pager}}"{{ifLast pager (attr class="disabled")}}>Next</a>');
app.partial('pager', '{{> prev }}\n{{> next }}');
Troubleshooting
The easiest way to see how this works is to log out the pager
variables, to see what's on the context. You can use the built-in log
helper to do this:
{{log pager}}
How it works
This is really all the plugin does, with the addition of error and options handling (a commented version is below). You can copy this and create your own plugin if you need to:
function pagerPlugin() {
var list = new app.List({pager: true});
return through.obj(function(file, enc, next) {
list.addItem(file);
next();
}, function(cb) {
for (var i = 0; i < list.items.length; i++) {
this.push(item);
}
cb();
});
}
With comments:
function pagerPlugin() {
// create a new assemble `List`. Lists are like collections,
// but the items are stored as an array, versus an object
var list = new app.List({pager: true});
return through.obj(function(file, enc, next) {
// add files to the list as they come through the stream
list.addItem(file);
// don't pass the file through, we'll do
// that in the flush function
next();
}, function(cb) {
// all of the files have now been buffered onto the
// `list.items` array. We can now loop over that array
// and push the items back into the stream (it's important
// for all the items to be buffered this way so that all
// items are available on the context before anything is
// rendered, or items will be missing)
for (var i = 0; i < list.items.length; i++) {
this.push(item); //<= push the item into the stream
}
cb();
});
}
About
Contributing
Pull requests and stars are always welcome. For bugs and feature requests, please create an issue.
Please read the contributing guide for advice on opening issues, pull requests, and coding standards.
Building docs
(This project's readme.md is generated by verb, please don't edit the readme directly. Any changes to the readme must be made in the .verb.md readme template.)
To generate the readme, run the following command:
$ npm install -g verbose/verb#dev verb-generate-readme && verb
Running tests
Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
$ npm install && npm test
Author
Jon Schlinkert
License
Copyright © 2017, Jon Schlinkert. MIT
This file was generated by verb-generate-readme, v0.4.2, on February 09, 2017.