UNPKG

kss

Version:

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

178 lines (153 loc) 6.08 kB
'use strict'; /** * The `kss/builder/base/nunjucks` module loads the KssBuilderBaseNunjucks * class, a `{@link KssBuilderBase}` sub-class using no templating. * ``` * const KssBuilderBaseNunjucks = require('kss/builder/base/nunjucks'); * ``` * @module kss/builder/base/nunjucks */ // Import the KssBuilderBase class. We will extend it to scaffold our builder. // Note: Since you will be building a sub-class outside of the kss module, this // next line will be: const KssBuilderBase = require('kss/builder/base'); const KssBuilderBase = require('../kss_builder_base.js'); const path = require('path'); const nunjucks = require('nunjucks'); const Promise = require('bluebird'); const fs = Promise.promisifyAll(require('fs-extra')); // Define "KssBuilderBaseNunjucks" as the name of our nunjucks builder class. // // Our builder is a sub-class of the KssBuilderBase class with additional // functionality added by overriding the parent methods. class KssBuilderBaseNunjucks extends KssBuilderBase { /** * Create a KssBuilderBaseNunjucks object. * * ``` * const KssBuilderBaseNunjucks = require('kss/builder/base/nunjucks'); * const builder = new KssBuilderBaseNunjucks(); * ``` */ 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 use of other file extensions // @see: https://mozilla.github.io/nunjucks/templating.html#file-extensions this.addOptionDefinitions({ extension: { multiple: false, describe: 'The preferred Nunjucks extension', group: 'Style guide:', default: 'njk' } }); } /** * 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.<KssStyleGuide>} A `Promise` object resolving to * `styleGuide`. */ prepare(styleGuide) { // First we let KssBuilderBase.prepare() clean-up the style guide object. return super.prepare(styleGuide).then((styleGuide) => { // Then we do our own prep work inside this Promise's .then() method. this.Nunjucks = nunjucks; this.Nunjucks.installJinjaCompat(); this.NunjucksEnv = this.Nunjucks.configure({ autoescape: false }); const prepTasks = []; // Create a new destination directory. prepTasks.push(this.prepareDestination('kss-assets')); // Load modules that extend Nunjucks. prepTasks.push(this.prepareExtend(this.NunjucksEnv)); 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} A `Promise` object. */ build(styleGuide) { const options = {}; options.templateExtension = this.options.extension; options.emptyTemplate = '{# Cannot be an empty string. #}'; this.templates = {}; // Returns a promise to read/load a template provided by the builder. options.readBuilderTemplate = (name) => { const templateName = `${name}.${options.templateExtension}`; const templatePath = path.resolve(this.options.builder, templateName); return fs.readFileAsync(templatePath, 'utf8').then((content) => { return this.Nunjucks.compile(content, this.NunjucksEnv); }); }; // Returns a promise to read/load a template specified by a section. options.readSectionTemplate = (name, filepath) => { return fs.readFileAsync(filepath, 'utf8').then((contents) => { const compiled = this.Nunjucks.compile(contents, this.NunjucksEnv); this.templates[name] = compiled; return compiled; }); }; // Returns a promise to load an inline template from markup. options.loadInlineTemplate = (name, markup) => { const compiled = this.Nunjucks.compile(markup, this.NunjucksEnv); this.templates[name] = compiled; return Promise.resolve(compiled); }; // 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) => { return Promise.resolve(this.templates[name]); }; // Returns a promise to get a template's markup by name. options.getTemplateMarkup = (name) => { return options.getTemplate(name).then((template) => { return template.tmplStr; }); }; // Renders a template and returns the markup. options.templateRender = (template, context) => { try { return this.Nunjucks.render(template, context); } catch (e) { // istanbul ignore next return ''; } }; // 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)); }; return this.buildGuide(styleGuide, options); } } // Export our "KssBuilderBaseNunjucks" class. module.exports = KssBuilderBaseNunjucks;