var metalsmith = require('metalsmith') var layouts = require('metalsmith-layouts') var markdown = require('metalsmith-markdown') var collections = require('metalsmith-collections') var pagination = require('metalsmith-pagination') var paths = require('metalsmith-paths') var filemetadata = require('metalsmith-filemetadata') var matters = require('metalsmith-matters') var postcss = require('metalsmith-postcss') var fs = require('fs'); var moment = require('moment'); var _ = require('underscore'); var handlebars = require('handlebars'); var handlebars_layout = require('handlebars-layouts'); moment.locale('fr'); //--------------------------- Handlebars -----------------------------// handlebars.registerHelper(handlebars_layout(handlebars)); handlebars.registerHelper('formatDate', function(date) { return moment(new Date(date)).format('DD MMMM YYYY'); }); handlebars.registerHelper('formatTimestamp', function(date) { return moment(date, 'X').format('MMMM D, YYYY HH:mm:ss'); }); function compareWith(v1, v2, operator) { var itm = false; switch (operator) { case '==': itm = (v1 == v2); break; case '!=': itm = (v1 != v2); break; case '===': itm = (v1 === v2); break; case '<': itm = (v1 < v2); break; case '<=': itm = (v1 <= v2); break; case '>': itm = (v1 > v2); break; case '>=': itm = (v1 >= v2); break; } return itm; } handlebars.registerHelper('eachSorted', function(context, member, item, order, options) { var tot = ''; var entries = _.sortBy(context, function(item){ return item[member][item] === undefined? 0 : item[member][item]; }) if (order === 'desc') { entries = entries.reverse(); } for (var i = 0; i < entries.length; i++) { tot += options.fn(entries[i]); } return tot; }); handlebars.registerHelper('eachCenter', function(context, number, index, options) { if (number > context.length) { number = context.length; } var start = index - number / 2; if (start < 0) { start = 0; } var end = start + number; if (end > context.length) { end = context.length; start = end - number; } var tot = ''; for (var i = start; i < end; i++) { if (i === index) { tot += options.inverse(context[i]); } else { tot += options.fn(context[i]); } } return tot; }); handlebars.registerHelper('ifCond', function (v1, operator, v2, options) { if (compareWith(v1, v2, operator)) { return options.fn(this); } else { return options.inverse(this); } }); //--------------------------- Build pipeline -------------------------// metalsmith(__dirname) .source('recettes') .metadata(require('./config/metadata')) .frontmatter(false) .use(matters(require('./config/matters'))) .use(filemetadata(require('./config/filemetadata'))) .use(addCategory()) .use(createCategories()) .use(collections(require('./config/collections'))) .use(markdown(require('./config/markdown'))) .use(pagination(require('./config/pagination'))) .use(paths(require('./config/paths'))) .use(layouts(require('./config/layouts'))) .use(copyVendor()) .use(postcss(require('./config/postcss'))) .use(epubGen()) .destination('build') .build(function (err) { if (err) { throw err } }) //--------------------- Helper functions -----------------------------// // Generates an epub file from the list of recettes. function epubGen() { var fs = require('fs'); var epubGenerator = require('epub-generator'); return function(files, metalsmith, done) { var epubStream = epubGenerator({ title: metalsmith.metadata().site.title, author: metalsmith.metadata().site.authors, language: metalsmith.metadata().site.language }); for (var f in files) { if (files[f].type == 'recette') { epubStream.add(f, files[f].contents, { title: files[f].data.title, toc: true }); } else if (files[f].type == 'style') { epubStream.add(f, files[f].contents, { toc: false }); } } epubStream.end() .pipe( fs.createWriteStream('basic.epub') ) .on('error', function(err){ console.trace(err); }); return done(); } } function createCategories() { return function(files, metalsmith, done) { var tagList = {}; for (var fileName in files) { var data = files[fileName]; if (!data) { continue; } var tagsData = data.category; if (!tagsData) { continue; } if (typeof tagsData === 'string') { tagsData = tagsData.split(','); } data.category = []; tagsData.forEach(function(rawTag) { var tag = String(rawTag).trim(); data.category.push(tag); if (!tagList[tag]) { tagList[tag] = []; } tagList[tag].push(fileName); }); } var metadata = metalsmith.metadata(); metadata.tags = metadata.tags || {}; for (var tag in tagList) { var posts = tagList[tag].map(function(fileName) { return files[fileName]; }); var tagPage = files[tag + '/index.md']; tagPage.tag = tag; tagPage.posts = posts; tagPage.title = tagPage.data.title; posts.forEach(function(post) { post.categoryPage = tagPage; }); metadata['tags'][tag] = tagPage; } tagList = {}; return done(); } } // Adds the category to the recette entry based on the parent directory function addCategory() { return function(files, metalsmith, done) { for (var f in files) { if (f.indexOf('.md') > 0 && f.indexOf('index.md') < 0) { var idx = f.indexOf('/'); var cat = f.substring(0, idx); files[f].category = cat; files[f].title = files[f].data.title; } } return done(); } } function copyVendor() { return function(files, metalsmith, done){ var styleFiles = fs.readdirSync('styles'); for (var i = 0; i < styleFiles.length; i++) { var stylePath = 'styles/' + styleFiles[i]; files[stylePath] = { contents: fs.readFileSync(stylePath), type: 'style' }; } var fontFiles = fs.readdirSync('fonts'); for (var i = 0; i < fontFiles.length; i++) { var fontPath = 'fonts/' + fontFiles[i]; files[fontPath] = { contents: fs.readFileSync(fontPath), type: 'font' }; } return done(); }; }