UNPKG

kss

Version:

The Node.js port of KSS: A methodology for documenting CSS and building style guides

147 lines (131 loc) 5.22 kB
'use strict'; /** * The `kss/builder/base/handlebars` module loads the KssBuilderBaseHandlebars * class, a `{@link KssBuilderBase}` sub-class using Handlebars templating. * ``` * const KssBuilderBaseHandlebars = require('kss/builder/base/handlebars'); * ``` * @module kss/builder/base/handlebars */ const KssBuilderBase = require('../kss_builder_base.js'), path = require('path'), Promise = require('bluebird'), Handlebars = require('handlebars'); const fs = Promise.promisifyAll(require('fs-extra')); /** * A kss-node builder takes input files and builds a style guide using * Handlebars templates. */ class KssBuilderBaseHandlebars extends KssBuilderBase { /** * Create a KssBuilderBaseHandlebars object. * * ``` * const KssBuilderBaseHandlebars = require('kss/builder/base/handlebars'); * const builder = new KssBuilderBaseHandlebars(); * ``` */ constructor() { super(); // Store the version of the builder API that the builder instance is // expecting; we will verify this in loadBuilder(). this.API = '3.0'; } /** * Allow the builder to preform pre-build tasks or modify the KssStyleGuide * object. * * The method can be set by any KssBuilderBase sub-class to do any custom * tasks after the KssStyleGuide object is created and before the HTML style * guide is built. * * @param {KssStyleGuide} styleGuide The KSS style guide in object format. * @returns {Promise.<null>} A `Promise` object resolving to `null`. */ prepare(styleGuide) { return super.prepare(styleGuide).then(styleGuide => { if (this.options.verbose) { this.log(''); } // Store the global Handlebars object. this.Handlebars = Handlebars; let prepTasks = []; // Create a new destination directory. prepTasks.push(this.prepareDestination('kss-assets')); // Load modules that extend Handlebars. prepTasks.push(this.prepareExtend(this.Handlebars)); return Promise.all(prepTasks).then(() => { return Promise.resolve(styleGuide); }); }); } /** * Build the HTML files of the style guide given a KssStyleGuide object. * * @param {KssStyleGuide} styleGuide The KSS style guide in object format. * @returns {Promise.<KssStyleGuide>} A `Promise` object resolving to a * `KssStyleGuide` object. */ build(styleGuide) { let options = {}; // Returns a promise to read/load a template provided by the builder. options.readBuilderTemplate = (name) => { return fs.readFileAsync(path.resolve(this.options.builder, name + '.hbs'), 'utf8').then(content => { return this.Handlebars.compile(content); }); }; // Returns a promise to read/load a template specified by a section. options.readSectionTemplate = (name, filepath) => { return fs.readFileAsync(filepath, 'utf8').then(contents => { this.Handlebars.registerPartial(name, contents); return contents; }); }; // Returns a promise to load an inline template from markup. options.loadInlineTemplate = (name, markup) => { this.Handlebars.registerPartial(name, markup); return Promise.resolve(); }; // Returns a promise to load the data context given a template file path. options.loadContext = filepath => { let context; // Load sample context for the template from the sample .json file. try { context = require(path.join(path.dirname(filepath), path.basename(filepath, path.extname(filepath)) + '.json')); // require() returns a cached object. We want an independent clone of // the object so we can make changes without affecting the original. context = JSON.parse(JSON.stringify(context)); } catch (error) { context = {}; } return Promise.resolve(context); }; // Returns a promise to get a template by name. options.getTemplate = name => { // We don't wrap the rendered template in "new handlebars.SafeString()" // since we want the ability to display it as a code sample with {{ }} and // as rendered HTML with {{{ }}}. return Promise.resolve(this.Handlebars.compile('{{> "' + name + '"}}')); }; // Returns a promise to get a template's markup by name. options.getTemplateMarkup = name => { // We don't wrap the rendered template in "new handlebars.SafeString()" // since we want the ability to display it as a code sample with {{ }} and // as rendered HTML with {{{ }}}. return Promise.resolve(this.Handlebars.partials[name]); }; // Renders a template and returns the markup. options.templateRender = (template, context) => { return template(context); }; // Converts a filename into a Handlebars partial name. options.filenameToTemplateRef = filename => { // Return the filename without the full path or the file extension. return path.basename(filename, path.extname(filename)); }; options.templateExtension = 'hbs'; options.emptyTemplate = '{{! Cannot be an empty string. }}'; return this.buildGuide(styleGuide, options); } } module.exports = KssBuilderBaseHandlebars;