0.1.2 • Published 7 years ago

assemble-pager v0.1.2

Weekly downloads
3
License
MIT
Repository
github
Last release
7 years ago

assemble-pager NPM version NPM monthly downloads NPM total downloads Linux Build Status

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:

image

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 (like pager.prev.path or pager.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 (like pager.next.path or pager.next.data.title, etc)
  • pager.current {Object} - the view that is currently being rendered
  • pager.first {Object} - Returns the first file in the list
  • pager.last {Object} - Returns the last file in the list
  • pager.isFirst {Boolean} - returns true if the "current" file is the first to be rendered
  • pager.isLast {Boolean} - returns true if the "current" file is the last to be rendered
  • pager.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 file A to file B (e.g. "current" file to next or previous file)
  • ifFirst- returns true if the current file being rendered is the first file
  • ifLast- returns true if the current file being rendered is the last file
  • next- used in href="", returns either the relative path to the "next" file, or # if the current file being rendered is the last file
  • prev- used in href="", returns either the relative path to the "previous" file, or # if the current file being rendered is the first file
  • attr- 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.