module.exports = function(params, callback) { 'use strict'; var path = require('path'); var async = require('async'); var _ = require('lodash'); var assemble = params.assemble; var grunt = params.grunt; var options = assemble.options; var pages = options.pages; var defaults = options.permalink; var escRegEx = function(string) { return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); }; var PATH_SEP = path.sep.slice(-1); var INDEX = 'index.html'; var INDEX_RE = new RegExp(escRegEx(PATH_SEP + INDEX) + '$'); // parse lodash template <%= %> var parseTpl = function(input, data, page) { try { return _.template(input, data); } catch (error) { grunt.fail.fatal(error.message + ' at ' + page.src); } }; // convert {{ variable }} to <%= variable %> // {{{{ not_variable }}}} to {{ not_variable }} var unescTpl = function(input) { return input.replace(/\{{2,}/g, function(match) { return match.length > 2 ? match.substr(2) : '<%='; }).replace(/\}{2,}/g, function(match) { return match.length > 2 ? match.substr(2) : '%>'; }); }; // standardize permalink output var standard = function(permalink) { permalink = permalink || ''; if (permalink.slice(0, 1) !== PATH_SEP) { permalink = PATH_SEP + permalink; } permalink = permalink.replace(INDEX_RE, PATH_SEP); return permalink; }; if (_.isString(defaults) && !_.isEmpty(defaults)) { defaults = unescTpl(defaults); } async.each(pages, function(page, next) { page.data = page.data || {}; var yfm = page.data; var permalink = defaults; var dirname = page.dirname; if (page.filePair && page.filePair.dest) { dirname = page.filePair.destForPermalink || page.filePair.dest_for_permalink || page.filePair.dest; } if (!_.isUndefined(yfm.permalink)) { permalink = yfm.permalink; } if (!_.isEmpty(permalink)) { var data = _.assign({}, options, page, yfm); var permalinks; if (_.isString(permalink)) { permalink = unescTpl(permalink); permalink = parseTpl(permalink, data, page); permalink = permalink.trim(); permalinks = permalink.split('\n'); } else if (_.isArray(permalink)) { permalinks = permalink; } else { grunt.fail.fatal('the permalink of ' + page.src + ' is neither a string nor an array'); } for (var i = permalinks.length - 1; i >= 0; i--) { var permalink = permalinks[i]; if (_.isEmpty(permalink)) continue; permalink = unescTpl(permalink); permalink = parseTpl(permalink, data, page); permalink = permalink.trim(); if (_.isEmpty(permalink)) continue; page.dest = path.join(dirname, permalink); if (page.dest.slice(-1) === PATH_SEP) { page.dest = path.join(page.dest, 'index.html'); } page.data.permalink = standard(permalink); if (i > 0) { page = _.cloneDeep(page); pages.push(page); } } } if (!page.data.permalink) { page.data.permalink = page.dest.substr(dirname.length); } page.data.permalink = standard(page.data.permalink); if (typeof options.permalinkCallback === 'function') { options.permalinkCallback.call(page); } next(); }); callback(); };