diff --git a/.eslintrc b/.eslintrc index 78d8eeb1..2c66dcff 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,6 +5,32 @@ "env": { "node": true }, + "ecmaFeatures": { + // Based on https://nodejs.org/en/docs/es6/ + "arrowFunctions": true, + "binaryLiterals": true, + "blockBindings": true, + "classes": true, + "forOf": true, + "generators": true, + "objectLiteralShorthandMethods": true, + "objectLiteralShorthandProperties": true, + "octalLiterals": true, + "templateStrings": true, + "unicodeCodePointEscapes": true, + // Node.js 5.0 and above. + "spread": false, + // Not in Node.js yet. + "defaultParams": false, + "destructuring": false, + "modules": false, + "objectLiteralComputedProperties": false, // Unsure. + "objectLiteralDuplicateProperties": false, // Unsure. + "regexUFlag": false, + "regexYFlag": false, + "restParams": false, + "superInFunctions": false // Unsure. + }, "rules": { // Errors. "array-bracket-spacing": [2, "never"], diff --git a/.travis.yml b/.travis.yml index 6ea127ab..ea4a137c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ sudo: false language: node_js node_js: - - '0.12' - '4.0' - '4.1' - '4.2' diff --git a/bin/kss-node b/bin/kss-node index fc0e8e0c..4bd36b5b 100755 --- a/bin/kss-node +++ b/bin/kss-node @@ -4,7 +4,7 @@ 'use strict'; -var cli = require('../lib/cli'); +const cli = require('../lib/cli'); cli({ stdin: process.stdin, diff --git a/generator/handlebars/helpers.js b/generator/handlebars/helpers.js index f04b2fa4..51d3defd 100644 --- a/generator/handlebars/helpers.js +++ b/generator/handlebars/helpers.js @@ -7,12 +7,7 @@ module.exports.register = function(handlebars, config) { * Outputs the current section's or modifier's markup. */ handlebars.registerHelper('markup', function() { - var options = arguments[arguments.length - 1], - partials = options.data.root.partials, - section, - template, - partial, - data; + let options = arguments[arguments.length - 1]; if (!this) { return options.inverse(''); @@ -20,7 +15,7 @@ module.exports.register = function(handlebars, config) { // Assume the current context is the section we want unless one is passed as // the first parameter of this helper. - section = (arguments.length > 1) ? arguments[0] : this; + let section = (arguments.length > 1) ? arguments[0] : this; // Verify we found a JSON representation of a KssSection object. if (!section.reference) { @@ -28,10 +23,10 @@ module.exports.register = function(handlebars, config) { } // Load the information about this section's markup partial. - partial = partials[section.reference]; + let partial = options.data.root.partials[section.reference]; // Copy the partial.data so we can modify it for this markup instance. - data = JSON.parse(JSON.stringify(partial.data)); + let data = JSON.parse(JSON.stringify(partial.data)); // Display the modifier_class hash (if given), or the modifier's className, // or the placeholder text if this section has modifiers. @@ -52,7 +47,7 @@ module.exports.register = function(handlebars, config) { /* eslint-enable camelcase */ // Compile the section's markup partial into a template. - template = handlebars.compile('{{> "' + partial.name + '"}}'); + let template = handlebars.compile('{{> "' + partial.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 {{{ }}}. @@ -68,7 +63,7 @@ module.exports.register = function(handlebars, config) { handlebars.registerHelper('consoleLog', function() { if (arguments.length > 1) { // 'options' is automatically passed as the last argument, so skip it. - for (var i = 0; i < arguments.length - 1; i++) { + for (let i = 0; i < arguments.length - 1; i++) { console.log(arguments[i]); } } else { diff --git a/generator/handlebars/kss_handlebars_generator.js b/generator/handlebars/kss_handlebars_generator.js index f994ce03..325be327 100644 --- a/generator/handlebars/kss_handlebars_generator.js +++ b/generator/handlebars/kss_handlebars_generator.js @@ -7,13 +7,12 @@ * The `kss/generator/handlebars` module loads the kssHandlebarsGenerator * object, a `{@link KssGenerator}` object using Handlebars templating. * ``` - * var kssHandlebarsGenerator = require('kss/generator/handlebars'); + * const kssHandlebarsGenerator = require('kss/generator/handlebars'); * ``` * @module kss/generator/handlebars */ -var KssGenerator = require('../kss_generator.js'), - KssSection = require('../../lib/kss_section.js'), +const KssGenerator = require('../kss_generator.js'), fs = require('fs'), glob = require('glob'), marked = require('marked'), @@ -23,7 +22,7 @@ var KssGenerator = require('../kss_generator.js'), // Pass a string to KssGenerator() to tell the system which API version is // implemented by kssHandlebarsGenerator. -var kssHandlebarsGenerator = new KssGenerator('2.1', { +let kssHandlebarsGenerator = new KssGenerator('2.1', { 'helpers': { group: 'Style guide:', string: true, @@ -66,8 +65,6 @@ var kssHandlebarsGenerator = new KssGenerator('2.1', { * @returns {*} The callback's return value. */ kssHandlebarsGenerator.init = function(config, cb) { - var i, j, helper; - cb = cb || /* istanbul ignore next */ function() {}; // Save the configuration parameters. @@ -116,14 +113,14 @@ kssHandlebarsGenerator.init = function(config, cb) { // Load Handlebars helpers. if (this.config.helpers.length > 0) { - for (i = 0; i < this.config.helpers.length; i++) { + for (let i = 0; i < this.config.helpers.length; i++) { if (fs.existsSync(this.config.helpers[i])) { // Load custom Handlebars helpers. - var helperFiles = fs.readdirSync(this.config.helpers[i]); + let helperFiles = fs.readdirSync(this.config.helpers[i]); - for (j = 0; j < helperFiles.length; j++) { + for (let j = 0; j < helperFiles.length; j++) { if (path.extname(helperFiles[j]) === '.js') { - helper = require(this.config.helpers[i] + '/' + helperFiles[j]); + let helper = require(this.config.helpers[i] + '/' + helperFiles[j]); if (typeof helper.register === 'function') { helper.register(this.Handlebars, this.config); } @@ -150,27 +147,19 @@ kssHandlebarsGenerator.generate = function(styleGuide, cb) { this.styleGuide = styleGuide; this.partials = {}; - var sections = this.styleGuide.sections(), - sectionCount = sections.length, - sectionRoots = [], - rootCount, - currentRoot, - childSections = [], - partial, - files = [], - newSection, - i, - key; + let sections = this.styleGuide.sections(), + sectionRoots = []; cb = cb || /* istanbul ignore next */ function() {}; if (this.config.verbose && this.styleGuide.meta.files) { - this.log(this.styleGuide.meta.files.map(function(file) { + this.log(this.styleGuide.meta.files.map(file => { return ' - ' + file; }).join('\n')); } // Return an error if no KSS sections are found in the source files. + let sectionCount = sections.length; if (sectionCount === 0) { return cb(Error('No KSS documentation discovered in source files.')); } @@ -179,10 +168,10 @@ kssHandlebarsGenerator.generate = function(styleGuide, cb) { this.log('...Determining section markup:'); } - for (i = 0; i < sectionCount; i += 1) { + for (let i = 0; i < sectionCount; i += 1) { // Register all the markup blocks as Handlebars partials. if (sections[i].markup()) { - partial = { + let partial = { name: sections[i].reference(), reference: sections[i].reference(), file: '', @@ -193,8 +182,8 @@ kssHandlebarsGenerator.generate = function(styleGuide, cb) { if (partial.markup.match(/^[^\n]+\.(html|hbs)$/)) { partial.file = partial.markup; partial.name = path.basename(partial.file, path.extname(partial.file)); - files = []; - for (key in this.config.source) { + let files = []; + for (let key in this.config.source) { if (!files.length) { files = glob.sync(this.config.source[key] + '/**/' + partial.file); } @@ -238,7 +227,7 @@ kssHandlebarsGenerator.generate = function(styleGuide, cb) { // Accumulate an array of section references for all sections at the root of // the style guide. - currentRoot = sections[i].reference().split(/(?:\.|\ \-\ )/)[0]; + let currentRoot = sections[i].reference().split(/(?:\.|\ \-\ )/)[0]; if (sectionRoots.indexOf(currentRoot) === -1) { sectionRoots.push(currentRoot); } @@ -246,24 +235,24 @@ kssHandlebarsGenerator.generate = function(styleGuide, cb) { // If a root element doesn't have an actual section, build one for it. // @TODO: Move this "fixing" into KssStyleGuide. - rootCount = sectionRoots.length; - key = false; - for (i = 0; i < rootCount; i += 1) { - currentRoot = this.styleGuide.sections(sectionRoots[i]); + let rootCount = sectionRoots.length; + let newSection = false; + for (let i = 0; i < rootCount; i += 1) { + let currentRoot = this.styleGuide.sections(sectionRoots[i]); if (currentRoot === false) { - key = sectionRoots[i]; - // @TODO: Add section via KssStyleGuide API. - newSection = new KssSection({ - header: key, - reference: key - }); - this.styleGuide.data.sections.push(newSection); - this.styleGuide.meta.referenceMap[newSection.reference()] = newSection; + // Add a section to the style guide. + newSection = true; + this.styleGuide + .autoInit(false) + .sections({ + header: sectionRoots[i], + reference: sectionRoots[i] + }); } } - // Re-sort the style guide if we added new sections. - if (key !== false) { - this.styleGuide.init(); + // Re-init the style guide if we added new sections. + if (newSection) { + this.styleGuide.autoInit(true); } if (this.config.verbose) { @@ -273,15 +262,14 @@ kssHandlebarsGenerator.generate = function(styleGuide, cb) { // Now, group all of the sections by their root // reference, and make a page for each. rootCount = sectionRoots.length; - for (i = 0; i < rootCount; i += 1) { - childSections = this.styleGuide.sections(sectionRoots[i] + '.*'); + for (let i = 0; i < rootCount; i += 1) { + let childSections = this.styleGuide.sections(sectionRoots[i] + '.*'); this.generatePage(sectionRoots[i], childSections); } // Generate the homepage. - childSections = []; - this.generatePage('styleGuide.homepage', childSections); + this.generatePage('styleGuide.homepage', []); cb(null); }; @@ -295,14 +283,10 @@ kssHandlebarsGenerator.generate = function(styleGuide, cb) { * variable. */ kssHandlebarsGenerator.createMenu = function(pageReference) { - var self = this, - menu, - toMenuItem; - // Helper function that converts a section to a menu item. - toMenuItem = function(section) { + const toMenuItem = function(section) { // @TODO: Add an option to "include" the specific properties returned. - var menuItem = section.toJSON(); + let menuItem = section.toJSON(); // Remove data we definitely won't need for the menu. delete menuItem.markup; @@ -319,23 +303,21 @@ kssHandlebarsGenerator.createMenu = function(pageReference) { }; // Retrieve all the root sections of the style guide. - menu = this.styleGuide.sections('x').map(function(rootSection) { - var menuItem = toMenuItem(rootSection); + return this.styleGuide.sections('x').map(rootSection => { + let menuItem = toMenuItem(rootSection); // Retrieve the child sections for each of the root sections. - menuItem.children = self.styleGuide.sections(rootSection.reference() + '.*').slice(1).map(toMenuItem); + menuItem.children = this.styleGuide.sections(rootSection.reference() + '.*').slice(1).map(toMenuItem); // Remove menu items that are deeper than the nav-depth config setting. - for (var i = 0; i < menuItem.children.length; i++) { - if (menuItem.children[i].depth > self.config['nav-depth']) { + for (let i = 0; i < menuItem.children.length; i++) { + if (menuItem.children[i].depth > this.config['nav-depth']) { delete menuItem.children[i]; } } return menuItem; }); - - return menu; }; /** @@ -346,12 +328,8 @@ kssHandlebarsGenerator.createMenu = function(pageReference) { * @param {Array} sections An array of KssSection objects. */ kssHandlebarsGenerator.generatePage = function(pageReference, sections) { - var filename = '', files, - homepageText = false, - rootSection, - styles = '', - scripts = '', - key; + let filename = '', + homepageText = false; if (pageReference === 'styleGuide.homepage') { filename = 'index.html'; @@ -359,10 +337,10 @@ kssHandlebarsGenerator.generatePage = function(pageReference, sections) { this.log(' - homepage'); } // Ensure homepageText is a non-false value. - for (key in this.config.source) { + for (let key in this.config.source) { if (!homepageText) { try { - files = glob.sync(this.config.source[key] + '/**/' + this.config.homepage); + let files = glob.sync(this.config.source[key] + '/**/' + this.config.homepage); if (files.length) { homepageText = ' ' + marked(fs.readFileSync(files[0], 'utf8')); } @@ -380,7 +358,7 @@ kssHandlebarsGenerator.generatePage = function(pageReference, sections) { } } } else { - rootSection = this.styleGuide.sections(pageReference); + let rootSection = this.styleGuide.sections(pageReference); filename = 'section-' + rootSection.referenceURI() + '.html'; if (this.config.verbose) { this.log( @@ -392,12 +370,14 @@ kssHandlebarsGenerator.generatePage = function(pageReference, sections) { } // Create the HTML to load the optional CSS and JS. - for (key in this.config.css) { + let styles = '', + scripts = ''; + for (let key in this.config.css) { if (this.config.css.hasOwnProperty(key)) { styles = styles + '\n'; } } - for (key in this.config.js) { + for (let key in this.config.js) { if (this.config.js.hasOwnProperty(key)) { scripts = scripts + '\n'; } @@ -406,9 +386,8 @@ kssHandlebarsGenerator.generatePage = function(pageReference, sections) { fs.writeFileSync(this.config.destination + '/' + filename, this.template({ pageReference: pageReference, - sections: sections.map(function(section) { - var context = section.toJSON(); - return context; + sections: sections.map(section => { + return section.toJSON(); }), menu: this.createMenu(pageReference), homepage: homepageText, diff --git a/generator/handlebars/template/template_config.js b/generator/handlebars/template/template_config.js index 8ba918bf..9ae6511e 100644 --- a/generator/handlebars/template/template_config.js +++ b/generator/handlebars/template/template_config.js @@ -8,9 +8,7 @@ // either be named index.js or have its name set in the "main" property of the // template's package.json. -var kssHandlebarsTemplate; - -module.exports = kssHandlebarsTemplate = {}; +const kssHandlebarsTemplate = {}; // Tell kss-node which generator this template uses. try { @@ -59,7 +57,7 @@ kssHandlebarsTemplate.generator.prepare = function(styleGuide, cb) { * @param {String} reference The reference to search for. */ this.Handlebars.registerHelper('section', function(reference, options) { - var section = options.data.root.styleGuide.sections(reference); + let section = options.data.root.styleGuide.sections(reference); return section ? options.fn(section.toJSON()) : options.inverse(''); }); @@ -74,21 +72,19 @@ kssHandlebarsTemplate.generator.prepare = function(styleGuide, cb) { * @param {Mixed} query The section query */ this.Handlebars.registerHelper('eachSection', function(query, options) { - var styleGuide = options.data.root.styleGuide, - buffer = '', - sections, - i, l; + let styleGuide = options.data.root.styleGuide; if (!query.match(/\bx\b|\*/g)) { query = query + '.*'; } - sections = styleGuide.sections(query); + let sections = styleGuide.sections(query); if (!sections) { return options.inverse(''); } - l = sections.length; - for (i = 0; i < l; i += 1) { + let l = sections.length; + let buffer = ''; + for (let i = 0; i < l; i += 1) { buffer += options.fn(sections[i].toJSON()); } @@ -98,3 +94,5 @@ kssHandlebarsTemplate.generator.prepare = function(styleGuide, cb) { return cb(null, styleGuide); }; + +module.exports = kssHandlebarsTemplate; diff --git a/generator/kss_example_generator.js b/generator/kss_example_generator.js index 6f4468e6..519cc462 100644 --- a/generator/kss_example_generator.js +++ b/generator/kss_example_generator.js @@ -4,14 +4,14 @@ * The `kss/generator/example` module loads the KssExampleGenerator * object, a `{@link KssGenerator}` object using no templating. * ``` - * var kssExampleGenerator = require('kss/generator/example'); + * const kssExampleGenerator = require('kss/generator/example'); * ``` * @module kss/generator/example */ // Import the KssGenerator object. We will use its API to scaffold our // generator. -var KssGenerator = require('kss/generator'), +const KssGenerator = require('kss/generator'), Kss = require('kss'), path = require('path'); @@ -21,7 +21,7 @@ var KssGenerator = require('kss/generator'), // additional functionality added by overriding the parent methods. // // See the docs for KssGenerator() for info about its parameters. -var kssExampleGenerator = new KssGenerator('2.1', { +const kssExampleGenerator = new KssGenerator('2.1', { 'example-option': { alias: 'u', string: true, diff --git a/generator/kss_generator.js b/generator/kss_generator.js index a9e3423a..3506668b 100644 --- a/generator/kss_generator.js +++ b/generator/kss_generator.js @@ -3,7 +3,7 @@ /** * The `kss/generator` module loads the {@link KssGenerator} class constructor. * ``` - * var KssGenerator = require('kss/generator'); + * const KssGenerator = require('kss/generator'); * ``` * @module kss/generator */ @@ -12,228 +12,230 @@ See kss_example_generator.js for how to implement a generator. ************************************************************** */ -var Kss = require('../lib/kss.js'), +const Kss = require('../lib/kss.js'), wrench = require('wrench'); -var KssGenerator; +class KssGenerator { + /** + * Create a KssGenerator object. + * + * This is the base object used by all kss-node generators. Implementations of + * KssGenerator MUST pass the version parameter. kss-node will use this to + * ensure that only compatible generators are used. + * + * ``` + * const KssGenerator = require('kss/generator'); + * const customGenerator = new KssGenerator('2.1'); + * ``` + * + * @constructor + * @alias KssGenerator + * @param {string} version The generator API version implemented. + * @param {object} options The Yargs-like options this generator has. + * See https://github.com/bcoe/yargs/blob/master/README.md#optionskey-opt + */ + constructor(version, options) { + if (!(this instanceof KssGenerator)) { + return new KssGenerator(); + } -/** - * Create a KssGenerator object. - * - * This is the base object used by all kss-node generators. Implementations of - * KssGenerator MUST pass the version parameter. kss-node will use this to - * ensure that only compatible generators are used. - * - * ``` - * var KssGenerator = require('kss/generator'); - * var customGenerator = new KssGenerator('2.1'); - * ``` - * - * @constructor - * @alias KssGenerator - * @param {string} version The generator API version implemented. - * @param {object} options The Yargs-like options this generator has. - * See https://github.com/bcoe/yargs/blob/master/README.md#optionskey-opt - */ -module.exports = KssGenerator = function(version, options) { - if (!(this instanceof KssGenerator)) { - return new KssGenerator(); - } + // Tell generators which generator API version is currently running. + this.API = '2.1'; - // Tell generators which generator API version is currently running. - this.API = '2.1'; + // Store the version of the generator API that the generator instance is + // expecting; we will verify this in checkGenerator(). + this.implementsAPI = typeof version === 'undefined' ? 'undefined' : version; - // Store the version of the generator API that the generator instance is - // expecting; we will verify this in checkGenerator(). - this.implementsAPI = typeof version === 'undefined' ? 'undefined' : version; + // Tell kss-node which Yargs-like options this generator has. + this.options = options || {}; - // Tell kss-node which Yargs-like options this generator has. - this.options = options || {}; + // The log function defaults to console.log. + this.setLogFunction(console.log); + } - // The log function defaults to console.log. - this.setLogFunction(console.log); -}; + /** + * Logs a message to be reported to the user. + * + * Since a generator can be used in places other than the console, using + * console.log() is inappropriate. The log() method should be used to pass + * messages to the KSS system so it can report them to the user. + * + * @param {string} message The message to log. + */ + log() { + this.logFunction.apply(null, arguments); + } -/** - * Logs a message to be reported to the user. - * - * Since a generator can be used in places other than the console, using - * console.log() is inappropriate. The log() method should be used to pass - * messages to the KSS system so it can report them to the user. - * - * @param {string} message The message to log. - */ -KssGenerator.prototype.log = function() { - this.logFunction.apply(null, arguments); -}; + /** + * The log() method logs a message for the user. This method allows the system + * to define the underlying function used by the log method to report the + * message to the user. The default log function is a wrapper around + * console.log(). + * + * @param {Function} logFunction Function to log a message to the user. + */ + setLogFunction(logFunction) { + this.logFunction = logFunction; + } -/** - * The log() method logs a message for the user. This method allows the system - * to define the underlying function used by the log method to report the - * message to the user. The default log function is a wrapper around - * console.log(). - * - * @param {Function} logFunction Function to log a message to the user. - */ -KssGenerator.prototype.setLogFunction = function(logFunction) { - this.logFunction = logFunction; -}; + /** + * Checks the generator configuration. + * + * An instance of KssGenerator MUST NOT override this method. A process + * controlling the generator should call this method to verify the + * specified generator has been configured correctly. + * + * @alias KssGenerator.prototype.checkGenerator + * @param {Function} cb Callback that will be given an Error as its first + * parameter, if one occurs. + * @returns {*} The callback's return value. + */ + checkGenerator(cb) { + let isCompatible = true, + version, + apiMajor, + apiMinor, + thisMajor, + thisMinor; + + if (!(this instanceof KssGenerator)) { + return cb(new Error('The loaded generator is not a KssGenerator object.')); + } -/** - * Checks the generator configuration. - * - * An instance of KssGenerator MUST NOT override this method. A process - * controlling the generator should call this method to verify the - * specified generator has been configured correctly. - * - * @alias KssGenerator.prototype.checkGenerator - * @param {Function} cb Callback that will be given an Error as its first - * parameter, if one occurs. - * @returns {*} The callback's return value. - */ -KssGenerator.prototype.checkGenerator = function(cb) { - var isCompatible = true, - version, - apiMajor, - apiMinor, - thisMajor, - thisMinor; - - if (!(this instanceof KssGenerator)) { - return cb(new Error('The loaded generator is not a KssGenerator object.')); - } + if (this.implementsAPI === 'undefined') { + isCompatible = false; + } else { + version = this.API.split('.'); + apiMajor = parseInt(version[0]); + apiMinor = parseInt(version[1]); - if (this.implementsAPI === 'undefined') { - isCompatible = false; - } else { - version = this.API.split('.'); - apiMajor = parseInt(version[0]); - apiMinor = parseInt(version[1]); + version = this.implementsAPI.split('.'); + thisMajor = parseInt(version[0]); + thisMinor = parseInt(version[1]); - version = this.implementsAPI.split('.'); - thisMajor = parseInt(version[0]); - thisMinor = parseInt(version[1]); + if (thisMajor !== apiMajor || thisMinor > apiMinor) { + isCompatible = false; + } + } - if (thisMajor !== apiMajor || thisMinor > apiMinor) { - isCompatible = false; + if (!isCompatible) { + return cb(new Error('kss-node expected the template\'s generator to implement KssGenerator API version ' + this.API + '; version "' + this.implementsAPI + '" is being used instead.')); } - } - if (!isCompatible) { - return cb(new Error('kss-node expected the template\'s generator to implement KssGenerator API version ' + this.API + '; version "' + this.implementsAPI + '" is being used instead.')); + return cb(null); } - return cb(null); -}; - -/** - * Clone a template's files. - * - * This method is fairly simple; it copies one directory to the specified - * location. An instance of KssGenerator does not need to override this method, - * but it can if it needs to do something more complicated. - * - * @alias KssGenerator.prototype.clone - * @param {string} templatePath Path to the template to clone. - * @param {string} destinationPath Path to the destination of the newly cloned - * template. - * @param {Function} cb Callback that will be given an Error as its first - * parameter, if one occurs. - * @returns {*} The callback's return value. - */ -KssGenerator.prototype.clone = function(templatePath, destinationPath, cb) { - return wrench.copyDirRecursive( - templatePath, - destinationPath, - { - forceDelete: false, - excludeHiddenUnix: true - }, - function(error) { - if (error) { - // istanbul ignore else - if (error.message === 'You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.') { - error = new Error('This folder already exists: ' + destinationPath); + /** + * Clone a template's files. + * + * This method is fairly simple; it copies one directory to the specified + * location. An instance of KssGenerator does not need to override this method, + * but it can if it needs to do something more complicated. + * + * @alias KssGenerator.prototype.clone + * @param {string} templatePath Path to the template to clone. + * @param {string} destinationPath Path to the destination of the newly cloned + * template. + * @param {Function} cb Callback that will be given an Error as its first + * parameter, if one occurs. + * @returns {*} The callback's return value. + */ + clone(templatePath, destinationPath, cb) { + return wrench.copyDirRecursive( + templatePath, + destinationPath, + { + forceDelete: false, + excludeHiddenUnix: true + }, + function(error) { + if (error) { + // istanbul ignore else + if (error.message === 'You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.') { + error = new Error('This folder already exists: ' + destinationPath); + } + return cb(error); } - return cb(error); + return cb(null); } - return cb(null); - } - ); -}; + ); + } -/** - * Initialize the style guide creation process. - * - * This method is given a configuration JSON object with the details of the - * requested style guide generation. The generator can use this information for - * any necessary tasks before the KSS parsing of the source files. - * - * @alias KssGenerator.prototype.init - * @param {Object} config Configuration object for the requested generation. - * @param {Function} cb Callback that will be given an Error as its first - * parameter, if one occurs. - * @returns {*} The callback's return value. - */ -KssGenerator.prototype.init = function(config, cb) { - // At the very least, generators MUST save the configuration parameters. - this.config = config; + /** + * Initialize the style guide creation process. + * + * This method is given a configuration JSON object with the details of the + * requested style guide generation. The generator can use this information for + * any necessary tasks before the KSS parsing of the source files. + * + * @alias KssGenerator.prototype.init + * @param {Object} config Configuration object for the requested generation. + * @param {Function} cb Callback that will be given an Error as its first + * parameter, if one occurs. + * @returns {*} The callback's return value. + */ + init(config, cb) { + // At the very least, generators MUST save the configuration parameters. + this.config = config; + + return cb(null); + } - return cb(null); -}; + /** + * Parse the source files for KSS comments and create a KssStyleGuide object. + * + * When finished, it passes the completed KssStyleGuide to the given callback. + * + * @alias KssGenerator.prototype.parse + * @param {Function} cb Callback that will be given an Error as its first + * parameter, if one occurs, and a fully-populated + * KssStyleGuide as its second parameter. + * @returns {*} The callback's return value. + */ + parse(cb) { + if (this.config.verbose) { + this.log('...Parsing your style guide:'); + } -/** - * Parse the source files for KSS comments and create a KssStyleGuide object. - * - * When finished, it passes the completed KssStyleGuide to the given callback. - * - * @alias KssGenerator.prototype.parse - * @param {Function} cb Callback that will be given an Error as its first - * parameter, if one occurs, and a fully-populated - * KssStyleGuide as its second parameter. - * @returns {*} The callback's return value. - */ -KssGenerator.prototype.parse = function(cb) { - if (this.config.verbose) { - this.log('...Parsing your style guide:'); + // The default parse() method looks at the paths to the source folders and + // uses KSS' traverse method to load, read and parse the source files. Other + // generators may want to use KSS' parse method if they have already loaded + // the source files through some other mechanism. + return Kss.traverse(this.config.source, { + header: true, + markdown: true, + markup: true, + mask: this.config.mask, + custom: this.config.custom + }, cb); } - // The default parse() method looks at the paths to the source folders and - // uses KSS' traverse method to load, read and parse the source files. Other - // generators may want to use KSS' parse method if they have already loaded - // the source files through some other mechanism. - return Kss.traverse(this.config.source, { - header: true, - markdown: true, - markup: true, - mask: this.config.mask, - custom: this.config.custom - }, cb); -}; + /** + * Allow the template to prepare itself or modify the KssStyleGuide object. + * + * @alias KssGenerator.prototype.prepare + * @param {KssStyleGuide} styleGuide The KSS style guide in object format. + * @param {Function} cb Callback that will be given an Error as its first + * parameter, if one occurs, and a fully-populated + * KssStyleGuide as its second parameter. + * @returns {*} The callback's return value. + */ + prepare(styleGuide, cb) { + return cb(null, styleGuide); + } -/** - * Allow the template to prepare itself or modify the KssStyleGuide object. - * - * @alias KssGenerator.prototype.prepare - * @param {KssStyleGuide} styleGuide The KSS style guide in object format. - * @param {Function} cb Callback that will be given an Error as its first - * parameter, if one occurs, and a fully-populated - * KssStyleGuide as its second parameter. - * @returns {*} The callback's return value. - */ -KssGenerator.prototype.prepare = function(styleGuide, cb) { - return cb(null, styleGuide); -}; + /** + * Generate the HTML files of the style guide given a KssStyleGuide object. + * + * @alias KssGenerator.prototype.generate + * @param {KssStyleGuide} styleGuide The KSS style guide in object format. + * @param {Function} cb Callback that will be given an Error as its first + * parameter, if one occurs. + * @returns {*} The callback's return value. + */ + generate(styleGuide, cb) { + return cb(null); + } +} -/** - * Generate the HTML files of the style guide given a KssStyleGuide object. - * - * @alias KssGenerator.prototype.generate - * @param {KssStyleGuide} styleGuide The KSS style guide in object format. - * @param {Function} cb Callback that will be given an Error as its first - * parameter, if one occurs. - * @returns {*} The callback's return value. - */ -KssGenerator.prototype.generate = function(styleGuide, cb) { - return cb(null); -}; +module.exports = KssGenerator; diff --git a/lib/cli.js b/lib/cli.js index b14cd19b..54cb4b12 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -1,26 +1,17 @@ 'use strict'; -// var Promise = require('bluebird'), -var fs = require('fs-extra'), +const fs = require('fs-extra'), KssConfig = require('./kss_config.js'), path = require('path'), version = require('../package.json').version, yargs = require('yargs'); -var cli; +const cli = function(opts, done) { + const kssConfig = new KssConfig(); -cli = function(opts, done) { - var generator, - kssConfig = new KssConfig(), - logError, - positionalParams, - stdout, - stderr, - argv; - - stdout = opts.stdout; - stderr = opts.stderr; - argv = opts.argv || []; + let stdout = opts.stdout, + stderr = opts.stderr, + argv = opts.argv || []; // Add options only needed by the CLI or yargs. kssConfig.addOptions({ @@ -69,7 +60,7 @@ cli = function(opts, done) { } else { // Check if there are unnamed parameters. - positionalParams = kssConfig.get('_'); + let positionalParams = kssConfig.get('_'); if (positionalParams.length > 0) { // Check if the destination is the second unnamed parameter. if (positionalParams.length > 1) { @@ -85,19 +76,19 @@ cli = function(opts, done) { // Based on the template location specified in the kssConfig, load the // requested template's generator. - generator = kssConfig.loadGenerator(); + const generator = kssConfig.loadGenerator(); // Set the logging function of the generator. generator.setLogFunction(function() { - var message = ''; - for (var i = 0; i < arguments.length; i++) { + let message = ''; + for (let i = 0; i < arguments.length; i++) { message += arguments[i]; } stdout.write(message + '\n'); }); // Set up an error handling function. - logError = function(error) { + const logError = function(error) { // Show the full error stack if the verbose flag is used. if (kssConfig.get('verbose')) { stderr.write(error + '\n'); diff --git a/lib/kss.js b/lib/kss.js index 3a5a0185..8f5338fd 100644 --- a/lib/kss.js +++ b/lib/kss.js @@ -15,45 +15,50 @@ * ``` * The various constructors and methods can then be accessed with: * ``` - * var KssStyleGuide = require('kss').KssStyleGuide; - * var KssSection = require('kss').KssSection; - * var KssModifier = require('kss').KssModifier; - * var KssParameter = require('kss').KssParameter; - * var KssConfig = require('kss').KssConfig; + * const KssStyleGuide = require('kss').KssStyleGuide; + * const KssSection = require('kss').KssSection; + * const KssModifier = require('kss').KssModifier; + * const KssParameter = require('kss').KssParameter; + * const KssConfig = require('kss').KssConfig; * - * var kss = require('kss'); - * var traverse = require('kss').traverse(); - * var parse = require('kss').parse(); + * const kss = require('kss'); + * const traverse = require('kss').traverse(); + * const parse = require('kss').parse(); * ``` * @module kss */ -var cli = require('./cli.js'); +const cli = require('./cli.js'); /** * Generates a style guide given the proper options. * - * @param {object} options A collection of configuration options. + * @param {object} [options] A collection of configuration options. * @param {Function} done Callback function * @returns {*} null */ -var kss = function(options, done) { - var stdout, stderr, argv, - flag, values, i; +const kss = function(options, done) { + if (typeof options === 'function') { + done = options; + options = {}; + } + options = options || {}; + options.pipes = options.pipes || {}; + done = done || function() {}; // Allow options to provide an alternative to the process' stdout/stderr. - stdout = (options.pipes && options.pipes.stdout) ? options.pipes.stdout : process.stdout; - stderr = (options.pipes && options.pipes.stderr) ? options.pipes.stderr : process.stderr; + let stdout = options.pipes.stdout ? options.pipes.stdout : process.stdout; + let stderr = options.pipes.stderr ? options.pipes.stderr : process.stderr; // Create an argv-like Array from the options. - argv = ['node', 'bin/kss-node']; - for (flag in options) { + let argv = ['node', 'bin/kss-node']; + for (let flag in options) { if (options.hasOwnProperty(flag)) { - values = options[flag]; + let values = options[flag]; if (!Array.isArray(values)) { values = [values]; } - for (i = 0; i < values.length; i++) { + for (let i = 0; i < values.length; i++) { if (values[i] === null || typeof values[i] === 'boolean' || typeof values[i] === 'undefined' diff --git a/lib/kss_config.js b/lib/kss_config.js index db7fe576..d90fd7a2 100644 --- a/lib/kss_config.js +++ b/lib/kss_config.js @@ -2,19 +2,17 @@ /** * The `kss/lib/kss_config` module is normally accessed via the - * [`KssConfig()`]{@link module:kss.KssConfig} constructor of the `kss` - * module: + * [`KssConfig()`]{@link module:kss.KssConfig} class of the `kss` module: * ``` - * var KssConfig = require('kss').KssConfig; + * const KssConfig = require('kss').KssConfig; * ``` * @private * @module kss/lib/kss_config */ -var path = require('path'); +const path = require('path'); -var KssConfig, - coreOptions, +let coreOptions, resolveArray; /* eslint-disable key-spacing */ @@ -91,235 +89,233 @@ coreOptions = { /* eslint-enable key-spacing */ /** - * A KssConfig object stores configuration settings needed when generating a KSS - * style guide. + * Applies path.resolve() to the given path or array of paths. * - * It also validates the settings against the known set of options for the - * configured template and its generator. And makes it easy to load the template - * and its generator. + * Helper function for KssConfig.normalize(). * - * @constructor - * @alias module:kss.KssConfig - * @param {Object} config An object of config settings to store. + * @private + * @param {string} [from] Optional path to resolve the "to" path + * @param {string|array} to Relative path(s) to resolve. + * @returns {string|array} The absolute path(s). */ -KssConfig = function(config) { - if (!(this instanceof KssConfig)) { - return new KssConfig(); +resolveArray = function(from, to) { + let paths = []; + // "from" is optional. + if (typeof to === 'undefined') { + to = from; + from = ''; } - this.options = coreOptions; - this.config = {}; - if (config) { - this.set(config); + if (to instanceof Array) { + to.forEach((value, index) => { + paths[index] = path.resolve(from, value); + }); + } else { + paths = path.resolve(from, to); } + return paths; }; -/** - * Stores the given config settings. - * - * @param {Object} config An object of config settings to store. - */ -KssConfig.prototype.set = function(config) { - var key; - for (key in config) { - // istanbul ignore else - if (config.hasOwnProperty(key)) { - this.config[key] = config[key]; +class KssConfig { + /** + * A KssConfig object stores configuration settings needed when generating a KSS + * style guide. + * + * It also validates the settings against the known set of options for the + * configured template and its generator. And makes it easy to load the template + * and its generator. + * + * @constructor + * @alias module:kss.KssConfig + * @param {Object} [config] An object of config settings to store. + */ + constructor(config) { + if (!(this instanceof KssConfig)) { + return new KssConfig(); + } + this.options = coreOptions; + this.config = {}; + if (config) { + this.set(config); } } -}; - -/** - * Returns the requested configuration setting or, if no key is specified, an - * object containing all settings. - * - * @param {string} key Optional name of config setting to return. - * @returns {string|Object} The specified setting or an object of all settings. - */ -KssConfig.prototype.get = function(key) { - return key ? this.config[key] : this.config; -}; -/** - * Adds additional configuration options to the core kss-node options. - * - * Since kss-node is extendable, generators and templates can provide their own - * options for configuration. - * - * @param {object} options An object of configuration options. - */ -KssConfig.prototype.addOptions = function(options) { - var key; - for (key in options) { - // istanbul ignore else - if (options.hasOwnProperty(key)) { - this.options[key] = options[key]; + /** + * Stores the given config settings. + * + * @param {Object} config An object of config settings to store. + */ + set(config) { + for (let key in config) { + // istanbul ignore else + if (config.hasOwnProperty(key)) { + this.config[key] = config[key]; + } } } -}; -/** - * Adds the configuration settings from the given JSON file. - * - * @param {string} filename The path to the JSON file. - */ -KssConfig.prototype.loadJSON = function(filename) { - filename = path.resolve(filename); - var config = require(filename); + /** + * Returns the requested configuration setting or, if no key is specified, an + * object containing all settings. + * + * @param {string} key Optional name of config setting to return. + * @returns {string|Object} The specified setting or an object of all settings. + */ + get(key) { + return key ? this.config[key] : this.config; + } - this.set({ - // Save the full path to the config file. - config: filename, - // Store the list of config file keys for later. - configFileKeys: Object.keys(config) - }); - this.set(config); -}; + /** + * Adds additional configuration options to the core kss-node options. + * + * Since kss-node is extendable, generators and templates can provide their own + * options for configuration. + * + * @param {object} options An object of configuration options. + */ + addOptions(options) { + for (let key in options) { + // istanbul ignore else + if (options.hasOwnProperty(key)) { + this.options[key] = options[key]; + } + } + } -/** - * Normalizes the configuration object so that it is easy to use inside KSS. - * - * The options specified in the KssConfig object will determine how its - * configuration will be normalized. - * - * If an option object has a: - * - `multiple` property: if set to `false`, the corresponding configuration - * will be normalized to a single value. Otherwise, it will be normalized to - * an array of values. - * - `path` property: if set to `true`, the corresponding configuration will be - * normalized to a path, relative to the current working directory or, if - * given, the location of the JSON config file. - */ -KssConfig.prototype.normalize = function() { - var key; + /** + * Adds the configuration settings from the given JSON file. + * + * @param {string} filename The path to the JSON file. + */ + loadJSON(filename) { + filename = path.resolve(filename); + let config = require(filename); - // If some of the options were specified in a JSON config file, determine - // which ones by loading the keys from the config file. - if (typeof this.config.configFileKeys === 'undefined') { - if (this.config.config) { + this.set({ // Save the full path to the config file. - this.config.config = path.resolve(this.config.config); + config: filename, // Store the list of config file keys for later. - this.config.configFileKeys = Object.keys(require(this.config.config)); - } else { - this.config.configFileKeys = []; - } - } - - // Allow --clone to be used without a path. We can't specify this default path - // in coreOptions or the clone flag would always be "on". - if (this.config['clone'] === '') { - this.config['clone'] = 'custom-template'; + configFileKeys: Object.keys(config) + }); + this.set(config); } - // Normalize all the configuration settings. - for (key in this.config) { - if (typeof this.options[key] !== 'undefined') { - // "multiple" defaults to true. - if (typeof this.options[key].multiple === 'undefined') { - this.options[key].multiple = true; - } - // "path" defaults to false. - if (typeof this.options[key].path === 'undefined') { - this.options[key].path = false; + /** + * Normalizes the configuration object so that it is easy to use inside KSS. + * + * The options specified in the KssConfig object will determine how its + * configuration will be normalized. + * + * If an option object has a: + * - `multiple` property: if set to `false`, the corresponding configuration + * will be normalized to a single value. Otherwise, it will be normalized to + * an array of values. + * - `path` property: if set to `true`, the corresponding configuration will be + * normalized to a path, relative to the current working directory or, if + * given, the location of the JSON config file. + */ + normalize() { + // If some of the options were specified in a JSON config file, determine + // which ones by loading the keys from the config file. + if (typeof this.config.configFileKeys === 'undefined') { + if (this.config.config) { + // Save the full path to the config file. + this.config.config = path.resolve(this.config.config); + // Store the list of config file keys for later. + this.config.configFileKeys = Object.keys(require(this.config.config)); + } else { + this.config.configFileKeys = []; } - // If an option is specified multiple times, yargs will convert it into an - // array, but leave it as a string otherwise. This makes accessing the - // values of options inconsistent, so make all other options an array. - if (this.options[key].multiple) { - if (!(this.config[key] instanceof Array)) { - if (typeof this.config[key] === 'undefined') { - this.config[key] = []; - } else { - this.config[key] = [this.config[key]]; - } + } + + // Allow --clone to be used without a path. We can't specify this default path + // in coreOptions or the clone flag would always be "on". + if (this.config['clone'] === '') { + this.config['clone'] = 'custom-template'; + } + + // Normalize all the configuration settings. + for (let key in this.config) { + if (typeof this.options[key] !== 'undefined') { + // "multiple" defaults to true. + if (typeof this.options[key].multiple === 'undefined') { + this.options[key].multiple = true; } - } else { - // For options marked as "multiple: false", use the last value - // specified, ignoring the others. - if (this.config[key] instanceof Array) { - this.config[key] = this.config[key].pop(); + // "path" defaults to false. + if (typeof this.options[key].path === 'undefined') { + this.options[key].path = false; } - } - // Resolve any paths relative to the config file or to the working - // directory. - if (this.options[key].path && (typeof this.config[key] === 'string' || this.config[key] instanceof Array)) { - if (this.config.configFileKeys.indexOf(key) > -1) { - this.config[key] = resolveArray(path.dirname(this.config.config), this.config[key]); + // If an option is specified multiple times, yargs will convert it into an + // array, but leave it as a string otherwise. This makes accessing the + // values of options inconsistent, so make all other options an array. + if (this.options[key].multiple) { + if (!(this.config[key] instanceof Array)) { + if (typeof this.config[key] === 'undefined') { + this.config[key] = []; + } else { + this.config[key] = [this.config[key]]; + } + } } else { - this.config[key] = resolveArray(this.config[key]); + // For options marked as "multiple: false", use the last value + // specified, ignoring the others. + if (this.config[key] instanceof Array) { + this.config[key] = this.config[key].pop(); + } + } + // Resolve any paths relative to the config file or to the working + // directory. + if (this.options[key].path && (typeof this.config[key] === 'string' || this.config[key] instanceof Array)) { + if (this.config.configFileKeys.indexOf(key) > -1) { + this.config[key] = resolveArray(path.dirname(this.config.config), this.config[key]); + } else { + this.config[key] = resolveArray(this.config[key]); + } } } } } -}; - -/** - * Loads a generator object based on the previously-set configuration. - * - * @returns {object} The generator object - */ -KssConfig.prototype.loadGenerator = function() { - var template, - generator, - self = this; - // Clean up paths and massage options to expected types. - this.normalize(); + /** + * Loads a generator object based on the previously-set configuration. + * + * @returns {object} The generator object + */ + loadGenerator() { + let template, + generator, + self = this; - // Load the template's generator. - try { - template = require(this.config.template); - generator = template.generator; - } catch (e) { - // Templates don't have to load their own generator. If the template fails - // to load a generator, we assume it wanted the default generator. - generator = require('../generator/handlebars'); - } + // Clean up paths and massage options to expected types. + this.normalize(); - // Confirm this is a compatible generator. - return generator.checkGenerator(function(error) { - if (error) { - return error; + // Load the template's generator. + try { + template = require(this.config.template); + generator = template.generator; + } catch (e) { + // Templates don't have to load their own generator. If the template fails + // to load a generator, we assume it wanted the default generator. + generator = require('../generator/handlebars'); } - // Load the generator's and the template's CLI options. - // istanbul ignore else - if (Object.keys(generator.options).length) { - self.addOptions(generator.options); - } - if (template && template.options && Object.keys(template.options).length) { - self.addOptions(template.options); - } + // Confirm this is a compatible generator. + return generator.checkGenerator(function(error) { + if (error) { + return error; + } - return generator; - }); -}; + // Load the generator's and the template's CLI options. + // istanbul ignore else + if (Object.keys(generator.options).length) { + self.addOptions(generator.options); + } + if (template && template.options && Object.keys(template.options).length) { + self.addOptions(template.options); + } -/** - * Applies path.resolve() to the given path or array of paths. - * - * Helper function for KssConfig.normalize(). - * - * @private - * @param {string} from Optional path to resolve the "to" path - * @param {string|array} to Relative path(s) to resolve. - * @returns {string|array} The absolute path(s). - */ -resolveArray = function(from, to) { - var paths = []; - // "from" is optional. - if (typeof to === 'undefined') { - to = from; - from = ''; - } - if (to instanceof Array) { - to.forEach(function(value, index) { - paths[index] = path.resolve(from, value); + return generator; }); - } else { - paths = path.resolve(from, to); } - return paths; -}; +} module.exports = KssConfig; diff --git a/lib/kss_modifier.js b/lib/kss_modifier.js index 65419f8b..f371f5df 100644 --- a/lib/kss_modifier.js +++ b/lib/kss_modifier.js @@ -2,191 +2,187 @@ /** * The `kss/lib/kss_modifier` module is normally accessed via the - * [`KssModifier()`]{@link module:kss.KssModifier} constructor of the `kss` - * module: + * [`KssModifier()`]{@link module:kss.KssModifier} class of the `kss` module: * ``` - * var KssModifier = require('kss').KssModifier; + * const KssModifier = require('kss').KssModifier; * ``` * @private * @module kss/lib/kss_modifier */ -var KssModifier; - -/** - * An instance of this class is returned on calling `KssSection.modifier`. - * Exposes convenience methods for interpreting data. - * - * @constructor - * @alias module:kss.KssModifier - * @param {Object} [data] A part of the data object passed on by `KssSection`. - */ -KssModifier = function(data) { - if (!(this instanceof KssModifier)) { - return new KssModifier(data); +class KssModifier { + + /** + * An instance of this class is returned on calling `KssSection.modifier`. + * Exposes convenience methods for interpreting data. + * + * @constructor + * @alias module:kss.KssModifier + * @param {Object} [data] A part of the data object passed on by `KssSection`. + */ + constructor(data) { + data = data || {}; + + this.meta = { + section: null + }; + + this.data = { + name: '', + description: '', + className: '' + }; + + // Loop through the given properties. + for (let name in data) { + // If the property is defined in this.data or this.meta, add it via our API. + if (data.hasOwnProperty(name) && (this.data.hasOwnProperty(name) || this.meta.hasOwnProperty(name))) { + this[name](data[name]); + } + } } - data = data || {}; - - this.meta = { - section: null - }; - - this.data = { - name: '', - description: '', - className: '' - }; - - // Loop through the given properties. - for (var name in data) { - // If the property is defined in this.data or this.meta, add it via our API. - if (data.hasOwnProperty(name) && (this.data.hasOwnProperty(name) || this.meta.hasOwnProperty(name))) { - this[name](data[name]); + /** + * Gets or sets the `KssSection` object this `KssModifier` is associated with. + * + * If the `section` value is provided, the `KssSection` for this modifier is + * set. Otherwise, the `KssSection` of the modifier is returned. + * + * @param {KssSection} [section] Optional. The `KssSection` that owns the + * `KssModifier`. + * @returns {KssSection|KssModifier} If section is given, the current + * `KssModifier` object is returned to allow chaining of methods. Otherwise, + * the `KssSection` object the modifier belongs to is returned. + */ + section(section) { + if (typeof section === 'undefined') { + return this.meta.section; } - } -}; -/** - * Gets or sets the `KssSection` object this `KssModifier` is associated with. - * - * If the `section` value is provided, the `KssSection` for this modifier is - * set. Otherwise, the `KssSection` of the modifier is returned. - * - * @param {KssSection} [section] Optional. The `KssSection` that owns the - * `KssModifier`. - * @returns {KssSection|KssModifier} If section is given, the current - * `KssModifier` object is returned to allow chaining of methods. Otherwise, - * the `KssSection` object the modifier belongs to is returned. - */ -KssModifier.prototype.section = function(section) { - if (typeof section === 'undefined') { - return this.meta.section; + this.meta.section = section; + // Allow chaining. + return this; } - this.meta.section = section; - // Allow chaining. - return this; -}; + /** + * Gets or sets the name of the `KssModifier`, e.g. `:hover`, `.primary`, etc. + * + * If the `name` value is provided, the name of this `KssModifier` is set. + * Otherwise, the name of the `KssModifier` is returned. + * + * @param {string} [name] Optional. The name of the `KssModifier`. + * @returns {string|KssModifier} If name is given, the current `KssModifier` + * object is returned to allow chaining of methods. Otherwise, the name of the + * `KssModifier` is returned. + */ + name(name) { + if (typeof name === 'undefined') { + return this.data.name; + } -/** - * Gets or sets the name of the `KssModifier`, e.g. `:hover`, `.primary`, etc. - * - * If the `name` value is provided, the name of this `KssModifier` is set. - * Otherwise, the name of the `KssModifier` is returned. - * - * @param {string} [name] Optional. The name of the `KssModifier`. - * @returns {string|KssModifier} If name is given, the current `KssModifier` - * object is returned to allow chaining of methods. Otherwise, the name of the - * `KssModifier` is returned. - */ -KssModifier.prototype.name = function(name) { - if (typeof name === 'undefined') { - return this.data.name; + this.data.name = name; + // Allow chaining. + return this; } - this.data.name = name; - // Allow chaining. - return this; -}; + /** + * Gets or sets the description of the `KssModifier`. + * + * If the `description` is provided, the description of this `KssModifier` is set. + * Otherwise, the description of the `KssModifier` is returned. + * + * @param {string} [description] Optional. The description of the `KssModifier`. + * @returns {string|KssModifier} If description is given, the current + * `KssModifier` object is returned to allow chaining of methods. Otherwise, + * the description of the `KssModifier` is returned. + */ + description(description) { + if (typeof description === 'undefined') { + return this.data.description; + } -/** - * Gets or sets the description of the `KssModifier`. - * - * If the `description` is provided, the description of this `KssModifier` is set. - * Otherwise, the description of the `KssModifier` is returned. - * - * @param {string} [description] Optional. The description of the `KssModifier`. - * @returns {string|KssModifier} If description is given, the current - * `KssModifier` object is returned to allow chaining of methods. Otherwise, - * the description of the `KssModifier` is returned. - */ -KssModifier.prototype.description = function(description) { - if (typeof description === 'undefined') { - return this.data.description; + this.data.description = description; + // Allow chaining. + return this; } - this.data.description = description; - // Allow chaining. - return this; -}; - -/** - * Gets or sets CSS class(es) suitable to insert into a markup sample to display - * the modifier's design. - * - * By default, the CSS classes the className() method returns are based on the - * modifier's name. If the modifier's name includes a pseudo-class, e.g. - * `:hover`, this method will replace the ":" with "pseudo-class-", which - * matches the selector expected by the kss.js script and its KssStateGenerator. - * - * ``` - * modifier.name('.primary:hover'); - * modifier.className(); // Returns "primary pseudo-class-hover" - * ``` - * - * To override, the default behavior the class(es) can also be set manually; if - * the `className` parameter is provided, the className of this `KssModifier` - * is set and will later be returned as-is instead of calculated based on the - * `name()`. - * - * @param {string} [className] Optional. The class(es) of the `KssModifier`. - * @returns {string|KssModifier} If the className parameter is given, the - * current `KssModifier` object is returned to allow chaining of methods. - * Otherwise, the class name(s) of the `KssModifier` are returned. - */ -KssModifier.prototype.className = function(className) { - if (typeof className === 'undefined') { - if (this.data.className) { - return this.data.className; - } else { - var name = this.name().replace(/:/g, '.pseudo-class-'); - - // If the name includes child selectors, we only want the first parent - // selector. Markup should not be multiple elements deep at this stage. - name = name.split(/\s/)[0]; - - // Split into space-separated classes. - name = name - .replace(/\./g, ' ') - .replace(/^\s*/g, ''); - - return name; + /** + * Gets or sets CSS class(es) suitable to insert into a markup sample to display + * the modifier's design. + * + * By default, the CSS classes the className() method returns are based on the + * modifier's name. If the modifier's name includes a pseudo-class, e.g. + * `:hover`, this method will replace the ":" with "pseudo-class-", which + * matches the selector expected by the kss.js script and its KssStateGenerator. + * + * ``` + * modifier.name('.primary:hover'); + * modifier.className(); // Returns "primary pseudo-class-hover" + * ``` + * + * To override, the default behavior the class(es) can also be set manually; if + * the `className` parameter is provided, the className of this `KssModifier` + * is set and will later be returned as-is instead of calculated based on the + * `name()`. + * + * @param {string} [className] Optional. The class(es) of the `KssModifier`. + * @returns {string|KssModifier} If the className parameter is given, the + * current `KssModifier` object is returned to allow chaining of methods. + * Otherwise, the class name(s) of the `KssModifier` are returned. + */ + className(className) { + if (typeof className === 'undefined') { + if (this.data.className) { + return this.data.className; + } else { + let name = this.name().replace(/:/g, '.pseudo-class-'); + + // If the name includes child selectors, we only want the first parent + // selector. Markup should not be multiple elements deep at this stage. + name = name.split(/\s/)[0]; + + // Split into space-separated classes. + name = name + .replace(/\./g, ' ') + .replace(/^\s*/g, ''); + + return name; + } } + + this.data.className = className; + // Allow chaining. + return this; } - this.data.className = className; - // Allow chaining. - return this; -}; + /** + * Returns the HTML markup used to render this modifier. + * + * The markup is retrieved from the KssModifier's section. See + * `KssSection.markup()` to see how to set the markup. + * + * @returns {string} The markup of the modifier. + */ + markup() { + if (!this.section()) { + return ''; + } -/** - * Returns the HTML markup used to render this modifier. - * - * The markup is retrieved from the KssModifier's section. See - * `KssSection.markup()` to see how to set the markup. - * - * @returns {string} The markup of the modifier. - */ -KssModifier.prototype.markup = function() { - if (!this.section()) { - return ''; + return (this.section().markup() || ''); } - return (this.section().markup() || ''); -}; - -/** - * Return the `KssModifier` as a JSON object. - * - * @returns {Object} A JSON object representation of the `KssModifier`. - */ -KssModifier.prototype.toJSON = function() { - return { - name: this.name(), - description: this.description(), - className: this.className() - }; -}; + /** + * Return the `KssModifier` as a JSON object. + * + * @returns {Object} A JSON object representation of the `KssModifier`. + */ + toJSON() { + return { + name: this.name(), + description: this.description(), + className: this.className() + }; + } +} module.exports = KssModifier; diff --git a/lib/kss_parameter.js b/lib/kss_parameter.js index 0db3a499..d0e22b0d 100644 --- a/lib/kss_parameter.js +++ b/lib/kss_parameter.js @@ -2,124 +2,120 @@ /** * The `kss/lib/kss_parameter` module is normally accessed via the - * [`KssParameter()`]{@link module:kss.KssParameter} constructor of the `kss` - * module: + * [`KssParameter()`]{@link module:kss.KssParameter} class of the `kss` module: * ``` - * var KssParameter = require('kss').KssParameter; + * const KssParameter = require('kss').KssParameter; * ``` * @private * @module kss/lib/kss_parameter */ -var KssParameter; +class KssParameter { -/** - * An instance of this class is returned on calling `KssSection.parameter`. - * Exposes convenience methods for interpreting data. - * - * @constructor - * @alias module:kss.KssParameter - * @param {Object} [data] A part of the data object passed on by `KssSection`. - */ -KssParameter = function(data) { - if (!(this instanceof KssParameter)) { - return new KssParameter(data); - } + /** + * An instance of this class is returned on calling `KssSection.parameter`. + * Exposes convenience methods for interpreting data. + * + * @constructor + * @alias module:kss.KssParameter + * @param {Object} [data] A part of the data object passed on by `KssSection`. + */ + constructor(data) { + data = data || {}; - data = data || {}; + this.meta = { + section: null + }; - this.meta = { - section: null - }; + this.data = { + name: '', + description: '' + }; - this.data = { - name: '', - description: '' - }; - - // Loop through the given properties. - for (var name in data) { - // If the property is defined in this.data or this.meta, add it via our API. - if (data.hasOwnProperty(name) && (this.data.hasOwnProperty(name) || this.meta.hasOwnProperty(name))) { - this[name](data[name]); + // Loop through the given properties. + for (let name in data) { + // If the property is defined in this.data or this.meta, add it via our API. + if (data.hasOwnProperty(name) && (this.data.hasOwnProperty(name) || this.meta.hasOwnProperty(name))) { + this[name](data[name]); + } } } -}; -/** - * Gets or sets the `KssSection` object this `KssParameter` is associated with. - * - * If the `section` value is provided, the `KssSection` for this parameter is - * set. Otherwise, the `KssSection` of the parameter is returned. - * - * @param {KssSection} [section] Optional. The `KssSection` that owns the - * `KssParameter`. - * @returns {KssSection|KssParameter} If section is given, the current - * `KssParameter` object is returned to allow chaining of methods. Otherwise, - * the `KssSection` object the parameter belongs to is returned. - */ -KssParameter.prototype.section = function(section) { - if (typeof section === 'undefined') { - return this.meta.section; + /** + * Gets or sets the `KssSection` object this `KssParameter` is associated with. + * + * If the `section` value is provided, the `KssSection` for this parameter is + * set. Otherwise, the `KssSection` of the parameter is returned. + * + * @param {KssSection} [section] Optional. The `KssSection` that owns the + * `KssParameter`. + * @returns {KssSection|KssParameter} If section is given, the current + * `KssParameter` object is returned to allow chaining of methods. Otherwise, + * the `KssSection` object the parameter belongs to is returned. + */ + section(section) { + if (typeof section === 'undefined') { + return this.meta.section; + } + + this.meta.section = section; + // Allow chaining. + return this; } - this.meta.section = section; - // Allow chaining. - return this; -}; + /** + * Gets or sets the name of the `KssParameter`. + * + * If the `name` value is provided, the name of this `KssParameter` is set. + * Otherwise, the name of the `KssParameter` is returned. + * + * @param {string} [name] Optional. The name of the `KssParameter`. + * @returns {string|KssParameter} If name is given, the current `KssParameter` + * object is returned to allow chaining of methods. Otherwise, the name of the + * `KssParameter` is returned. + */ + name(name) { + if (typeof name === 'undefined') { + return this.data.name; + } -/** - * Gets or sets the name of the `KssParameter`. - * - * If the `name` value is provided, the name of this `KssParameter` is set. - * Otherwise, the name of the `KssParameter` is returned. - * - * @param {string} [name] Optional. The name of the `KssParameter`. - * @returns {string|KssParameter} If name is given, the current `KssParameter` - * object is returned to allow chaining of methods. Otherwise, the name of the - * `KssParameter` is returned. - */ -KssParameter.prototype.name = function(name) { - if (typeof name === 'undefined') { - return this.data.name; + this.data.name = name; + // Allow chaining. + return this; } - this.data.name = name; - // Allow chaining. - return this; -}; + /** + * Gets or sets the description of the `KssParameter`. + * + * If the `description` is provided, the description of this `KssParameter` is set. + * Otherwise, the description of the `KssParameter` is returned. + * + * @param {string} [description] Optional. The description of the `KssParameter`. + * @returns {string|KssParameter} If description is given, the current + * `KssParameter` object is returned to allow chaining of methods. Otherwise, + * the description of the `KssParameter` is returned. + */ + description(description) { + if (typeof description === 'undefined') { + return this.data.description; + } -/** - * Gets or sets the description of the `KssParameter`. - * - * If the `description` is provided, the description of this `KssParameter` is set. - * Otherwise, the description of the `KssParameter` is returned. - * - * @param {string} [description] Optional. The description of the `KssParameter`. - * @returns {string|KssParameter} If description is given, the current - * `KssParameter` object is returned to allow chaining of methods. Otherwise, - * the description of the `KssParameter` is returned. - */ -KssParameter.prototype.description = function(description) { - if (typeof description === 'undefined') { - return this.data.description; + this.data.description = description; + // Allow chaining. + return this; } - this.data.description = description; - // Allow chaining. - return this; -}; - -/** - * Return the `KssParameter` as a JSON object. - * - * @returns {Object} A JSON object representation of the `KssParameter`. - */ -KssParameter.prototype.toJSON = function() { - return { - name: this.name(), - description: this.description() - }; -}; + /** + * Return the `KssParameter` as a JSON object. + * + * @returns {Object} A JSON object representation of the `KssParameter`. + */ + toJSON() { + return { + name: this.name(), + description: this.description() + }; + } +} module.exports = KssParameter; diff --git a/lib/kss_section.js b/lib/kss_section.js index 244d6cd9..62d1c379 100644 --- a/lib/kss_section.js +++ b/lib/kss_section.js @@ -1,520 +1,515 @@ 'use strict'; -var KssModifier = require('./kss_modifier'), +const KssModifier = require('./kss_modifier'), KssParameter = require('./kss_parameter'); /** * The `kss/lib/kss_section` module is normally accessed via the - * [`KssSection()`]{@link module:kss.KssSection} constructor of the `kss` - * module: + * [`KssSection()`]{@link module:kss.KssSection} class of the `kss` module: * ``` - * var KssSection = require('kss').KssSection; + * const KssSection = require('kss').KssSection; * ``` * @private * @module kss/lib/kss_section */ -var KssSection; - -/** - * Creates one section of a style guide. - * - * @constructor - * @alias module:kss.KssSection - * @param {Object} [data] The data to use to initialize the `KssSection` object. - */ -KssSection = function(data) { - if (!(this instanceof KssSection)) { - return new KssSection(data); - } +class KssSection { + + /** + * Creates one section of a style guide. + * + * @constructor + * @alias module:kss.KssSection + * @param {Object} [data] The data to use to initialize the `KssSection` object. + */ + constructor(data) { + if (!(this instanceof KssSection)) { + return new KssSection(data); + } - data = data || {}; - - this.meta = { - styleGuide: data.styleGuide || null, - raw: data.raw || '', - customPropertyNames: [], - depth: data.depth || 0 - }; - - this.data = { - header: '', - description: '', - deprecated: false, - experimental: false, - reference: '', - referenceNumber: '', - referenceURI: '', - weight: 0, - markup: '', - modifiers: [], - parameters: [] - }; - - // Loop through the given properties. - for (var name in data) { - // istanbul ignore else - if (data.hasOwnProperty(name)) { - // If the property is defined in this.data, add it via our API. - if (this.data.hasOwnProperty(name)) { - this[name](data[name]); - - // If the property isn't defined in meta or data, add a custom property. - } else if (!this.meta.hasOwnProperty(name)) { - this.custom(name, data[name]); + data = data || {}; + + this.meta = { + styleGuide: data.styleGuide || null, + raw: data.raw || '', + customPropertyNames: [], + depth: data.depth || 0 + }; + + this.data = { + header: '', + description: '', + deprecated: false, + experimental: false, + reference: '', + referenceNumber: '', + referenceURI: '', + weight: 0, + markup: '', + modifiers: [], + parameters: [] + }; + + // Loop through the given properties. + for (let name in data) { + // istanbul ignore else + if (data.hasOwnProperty(name)) { + // If the property is defined in this.data, add it via our API. + if (this.data.hasOwnProperty(name)) { + this[name](data[name]); + + // If the property isn't defined in meta or data, add a custom property. + } else if (!this.meta.hasOwnProperty(name)) { + this.custom(name, data[name]); + } } } } -}; -/** - * Return the `KssSection` as a JSON object. - * - * @returns {Object} A JSON object representation of the KssSection. - */ -KssSection.prototype.toJSON = function() { - var returnObject; - - /* eslint-disable key-spacing */ - returnObject = { - header: this.header(), - description: this.description(), - deprecated: this.deprecated(), - experimental: this.experimental(), - reference: this.reference(), - referenceNumber: this.referenceNumber(), - referenceURI: this.referenceURI(), - weight: this.weight(), - markup: this.markup(), - // Include meta as well. - depth: this.depth() - }; - /* eslint-enable key-spacing */ - - returnObject.modifiers = this.modifiers().map(function(modifier) { - return modifier.toJSON(); - }); - returnObject.parameters = this.parameters().map(function(parameter) { - return parameter.toJSON(); - }); - - // Add custom properties to the JSON object. - for (var i = 0; i < this.meta.customPropertyNames.length; i++) { - // istanbul ignore else - if (typeof this.custom(this.meta.customPropertyNames[i]) !== 'undefined') { - returnObject[this.meta.customPropertyNames[i]] = this.custom(this.meta.customPropertyNames[i]); - } - } + /** + * Return the `KssSection` as a JSON object. + * + * @returns {Object} A JSON object representation of the KssSection. + */ + toJSON() { + /* eslint-disable key-spacing */ + let returnObject = { + header: this.header(), + description: this.description(), + deprecated: this.deprecated(), + experimental: this.experimental(), + reference: this.reference(), + referenceNumber: this.referenceNumber(), + referenceURI: this.referenceURI(), + weight: this.weight(), + markup: this.markup(), + // Include meta as well. + depth: this.depth() + }; + /* eslint-enable key-spacing */ + + returnObject.modifiers = this.modifiers().map(modifier => { + return modifier.toJSON(); + }); + returnObject.parameters = this.parameters().map(parameter => { + return parameter.toJSON(); + }); - return returnObject; -}; + // Add custom properties to the JSON object. + for (let i = 0; i < this.meta.customPropertyNames.length; i++) { + // istanbul ignore else + if (typeof this.custom(this.meta.customPropertyNames[i]) !== 'undefined') { + returnObject[this.meta.customPropertyNames[i]] = this.custom(this.meta.customPropertyNames[i]); + } + } -/** - * Gets or sets the `KssStyleGuide` object this `KssSection` is associated with. - * - * If the `styleGuide` value is provided, the `KssStyleGuide` for this section - * is set. Otherwise, the `KssStyleGuide` of the section is returned. - * - * @param {KssStyleGuide} [styleGuide] Optional. The `KssStyleGuide` that owns the - * `KssSection`. - * @returns {KssStyleGuide|KssSection} If styleGuide is given, the current - * `KssSection` object is returned to allow chaining of methods. Otherwise, - * the `KssStyleGuide` object the section belongs to is returned. - */ -KssSection.prototype.styleGuide = function(styleGuide) { - if (typeof styleGuide === 'undefined') { - return this.meta.styleGuide; + return returnObject; } - this.meta.styleGuide = styleGuide; - // Tell the style guide about this section's custom property names. - this.meta.styleGuide.customPropertyNames(this.customPropertyNames()); - // Allow chaining. - return this; -}; + /** + * Gets or sets the `KssStyleGuide` object this `KssSection` is associated with. + * + * If the `styleGuide` value is provided, the `KssStyleGuide` for this section + * is set. Otherwise, the `KssStyleGuide` of the section is returned. + * + * @param {KssStyleGuide} [styleGuide] Optional. The `KssStyleGuide` that owns the + * `KssSection`. + * @returns {KssStyleGuide|KssSection} If styleGuide is given, the current + * `KssSection` object is returned to allow chaining of methods. Otherwise, + * the `KssStyleGuide` object the section belongs to is returned. + */ + styleGuide(styleGuide) { + if (typeof styleGuide === 'undefined') { + return this.meta.styleGuide; + } -/** - * Gets or sets the header of the section, i.e. the first line in the description. - * - * If the `header` value is provided, the `header` for this section is set. - * Otherwise, the `header` of the section is returned. - * - * @param {string} [header] Optional. The header of the section. - * @returns {KssSection|string} If `header` is given, the `KssSection` object is - * returned to allow chaining of methods. Otherwise, the header of the section - * is returned. - */ -KssSection.prototype.header = function(header) { - if (typeof header === 'undefined') { - return this.data.header; + this.meta.styleGuide = styleGuide; + // Tell the style guide about this section's custom property names. + this.meta.styleGuide.customPropertyNames(this.customPropertyNames()); + // Allow chaining. + return this; } - this.data.header = header; - // Allow chaining. - return this; -}; + /** + * Gets or sets the header of the section, i.e. the first line in the description. + * + * If the `header` value is provided, the `header` for this section is set. + * Otherwise, the `header` of the section is returned. + * + * @param {string} [header] Optional. The header of the section. + * @returns {KssSection|string} If `header` is given, the `KssSection` object is + * returned to allow chaining of methods. Otherwise, the header of the section + * is returned. + */ + header(header) { + if (typeof header === 'undefined') { + return this.data.header; + } -/** - * Gets or sets the description of the section. - * - * If the `description` value is provided, the `description` for this section is - * set. Otherwise, the `description` of the section is returned. - * - * @param {string} [description] Optional. The description of the section. - * @returns {KssSection|string} If `description` is given, the `KssSection` - * object is returned to allow chaining of methods. Otherwise, the description - * of the section is returned. - */ -KssSection.prototype.description = function(description) { - if (typeof description === 'undefined') { - return this.data.description; + this.data.header = header; + // Allow chaining. + return this; } - this.data.description = description; - // Allow chaining. - return this; -}; - -/** - * Gets the list of custom properties of the section. - * - * Note that this method will return the actual custom properties set for this - * section, and not all of the custom properties available for the entire style - * guide. Use KssStyleGuide.customPropertyNames() for that list. - * - * @returns {string[]} An array of the section's custom property names. - */ -KssSection.prototype.customPropertyNames = function() { - return this.meta.customPropertyNames; -}; - -/** - * Gets or sets a custom property of the section. - * - * If the `value` is provided, the requested custom property of the section is - * set. Otherwise, the section's custom property with the name specified in the - * `name` parameter is returned. - * - * @param {string} name The name of the section's custom property. - * @param {*} [value] Optional. The value of the section's custom property. - * @returns {KssSection|*} If `value` is given, the `KssSection` object is - * returned to allow chaining of methods. Otherwise, the section's custom - * property, `name`, is returned. - */ -KssSection.prototype.custom = function(name, value) { - if (typeof value === 'undefined') { - /* eslint-disable no-undefined */ - return this.meta.customPropertyNames.indexOf(name) === -1 ? undefined : this.data[name]; - } + /** + * Gets or sets the description of the section. + * + * If the `description` value is provided, the `description` for this section is + * set. Otherwise, the `description` of the section is returned. + * + * @param {string} [description] Optional. The description of the section. + * @returns {KssSection|string} If `description` is given, the `KssSection` + * object is returned to allow chaining of methods. Otherwise, the description + * of the section is returned. + */ + description(description) { + if (typeof description === 'undefined') { + return this.data.description; + } - if (this.styleGuide()) { - this.styleGuide().customPropertyNames(name); + this.data.description = description; + // Allow chaining. + return this; } - this.meta.customPropertyNames.push(name); - this.data[name] = value; - // Allow chaining. - return this; -}; -/** - * Gets or sets the deprecated flag for the section. - * - * If the `deprecated` value is provided, the `deprecated` flag for this section - * is set. Otherwise, the `deprecated` flag for the section is returned. - * - * @param {boolean} [deprecated] Optional. The deprecated flag for the section. - * @returns {KssSection|boolean} If `deprecated` is given, the `KssSection` - * object is returned to allow chaining of methods. Otherwise, the deprecated - * flag for the section is returned. - */ -KssSection.prototype.deprecated = function(deprecated) { - if (typeof deprecated === 'undefined') { - return this.data.deprecated; + /** + * Gets the list of custom properties of the section. + * + * Note that this method will return the actual custom properties set for this + * section, and not all of the custom properties available for the entire style + * guide. Use KssStyleGuide.customPropertyNames() for that list. + * + * @returns {string[]} An array of the section's custom property names. + */ + customPropertyNames() { + return this.meta.customPropertyNames; } - this.data.deprecated = deprecated ? true : false; - // Allow chaining. - return this; -}; + /** + * Gets or sets a custom property of the section. + * + * If the `value` is provided, the requested custom property of the section is + * set. Otherwise, the section's custom property with the name specified in the + * `name` parameter is returned. + * + * @param {string} name The name of the section's custom property. + * @param {*} [value] Optional. The value of the section's custom property. + * @returns {KssSection|*} If `value` is given, the `KssSection` object is + * returned to allow chaining of methods. Otherwise, the section's custom + * property, `name`, is returned. + */ + custom(name, value) { + if (typeof value === 'undefined') { + /* eslint-disable no-undefined */ + return this.meta.customPropertyNames.indexOf(name) === -1 ? undefined : this.data[name]; + } -/** - * Gets or sets the experimental flag for the section. - * - * If the `experimental` value is provided, the `experimental` flag for this - * section is set. Otherwise, the `deprecated` flag for the section is returned. - * - * @param {boolean} [experimental] Optional. The experimental flag for the - * section. - * @returns {KssSection|boolean} If `experimental` is given, the `KssSection` - * object is returned to allow chaining of methods. Otherwise, the - * experimental flag for the section is returned. - */ -KssSection.prototype.experimental = function(experimental) { - if (typeof experimental === 'undefined') { - return this.data.experimental; + if (this.styleGuide()) { + this.styleGuide().customPropertyNames(name); + } + this.meta.customPropertyNames.push(name); + this.data[name] = value; + // Allow chaining. + return this; } - this.data.experimental = experimental ? true : false; - // Allow chaining. - return this; -}; + /** + * Gets or sets the deprecated flag for the section. + * + * If the `deprecated` value is provided, the `deprecated` flag for this section + * is set. Otherwise, the `deprecated` flag for the section is returned. + * + * @param {boolean} [deprecated] Optional. The deprecated flag for the section. + * @returns {KssSection|boolean} If `deprecated` is given, the `KssSection` + * object is returned to allow chaining of methods. Otherwise, the deprecated + * flag for the section is returned. + */ + deprecated(deprecated) { + if (typeof deprecated === 'undefined') { + return this.data.deprecated; + } -/** - * Gets or sets the reference for the section. - * - * If the `reference` value is provided, the `reference` for this section is - * set. Otherwise, the `reference` for the section is returned. - * - * @param {string} [reference] Optional. The reference of the section. - * @returns {KssSection|string} If `reference` is given, the `KssSection` object - * is returned to allow chaining of methods. Otherwise, the reference for the - * section is returned. - */ -KssSection.prototype.reference = function(reference) { - if (typeof reference === 'undefined') { - return this.data.reference; + this.data.deprecated = !!deprecated; + // Allow chaining. + return this; } - // @TODO: Tell the KssStyleGuide about the update. - - // Normalize any " - " delimeters. - reference = reference.replace(/\s+\-\s+/g, ' - '); - // Remove trailing dot-zeros and periods. - reference = reference.replace(/\.$|(\.0){1,}$/g, ''); + /** + * Gets or sets the experimental flag for the section. + * + * If the `experimental` value is provided, the `experimental` flag for this + * section is set. Otherwise, the `deprecated` flag for the section is returned. + * + * @param {boolean} [experimental] Optional. The experimental flag for the + * section. + * @returns {KssSection|boolean} If `experimental` is given, the `KssSection` + * object is returned to allow chaining of methods. Otherwise, the + * experimental flag for the section is returned. + */ + experimental(experimental) { + if (typeof experimental === 'undefined') { + return this.data.experimental; + } - this.data.reference = reference; - // Allow chaining. - return this; -}; + this.data.experimental = !!experimental; + // Allow chaining. + return this; + } -/** - * Gets or sets a numeric reference number for the section. - * - * If the `referenceNumber` value is provided, the `referenceNumber` for this - * section is set. - * - * If no parameters are given, this method returns a numeric reference number; - * if the style guide's references are already numeric (e.g. 2, 2.1.3, 3.2), - * then this method returns the same value as reference() does. Otherwise, an - * auto-incremented reference number will be returned. - * - * @param {string} [referenceNumber] Optional. The auto-incremented reference - * number of the section. - * @returns {KssSection|string} If `referenceNumber` is given, the `KssSection` - * object is returned to allow chaining of methods. Otherwise, the reference - * number of the section is returned. - */ -KssSection.prototype.referenceNumber = function(referenceNumber) { - if (typeof referenceNumber === 'undefined') { - if (this.styleGuide() && this.styleGuide().hasNumericReferences()) { + /** + * Gets or sets the reference for the section. + * + * If the `reference` value is provided, the `reference` for this section is + * set. Otherwise, the `reference` for the section is returned. + * + * @param {string} [reference] Optional. The reference of the section. + * @returns {KssSection|string} If `reference` is given, the `KssSection` object + * is returned to allow chaining of methods. Otherwise, the reference for the + * section is returned. + */ + reference(reference) { + if (typeof reference === 'undefined') { return this.data.reference; - } else { - return this.data.referenceNumber; } - } - this.data.referenceNumber = referenceNumber; - // Allow chaining. - return this; -}; + // @TODO: Tell the KssStyleGuide about the update. -/** - * Gets or sets the reference of the section, encoded as a valid URI fragment. - * - * If the `referenceURI` value is provided, the `referenceURI` for this section - * is set. Otherwise, the `referenceURI` of the section is returned. - * - * @param {string} [referenceURI] Optional. The referenceURI of the section. - * @returns {KssSection|string} If `referenceURI` is given, the `KssSection` - * object is returned to allow chaining of methods. Otherwise, the - * referenceURI of the section is returned. - */ -KssSection.prototype.referenceURI = function(referenceURI) { - if (typeof referenceURI === 'undefined') { - if (!this.data.referenceURI) { - this.data.referenceURI = encodeURI( - this.reference() - .replace(/ \- /g, '-') - .replace(/[^\w-]+/g, '-') - .toLowerCase() - ); - } - return this.data.referenceURI; + // Normalize any " - " delimiters. + reference = reference.replace(/\s+\-\s+/g, ' - '); + // Remove trailing dot-zeros and periods. + reference = reference.replace(/\.$|(\.0){1,}$/g, ''); + + this.data.reference = reference; + // Allow chaining. + return this; } - this.data.referenceURI = referenceURI; - // Allow chaining. - return this; -}; + /** + * Gets or sets a numeric reference number for the section. + * + * If the `referenceNumber` value is provided, the `referenceNumber` for this + * section is set. + * + * If no parameters are given, this method returns a numeric reference number; + * if the style guide's references are already numeric (e.g. 2, 2.1.3, 3.2), + * then this method returns the same value as reference() does. Otherwise, an + * auto-incremented reference number will be returned. + * + * @param {string} [referenceNumber] Optional. The auto-incremented reference + * number of the section. + * @returns {KssSection|string} If `referenceNumber` is given, the `KssSection` + * object is returned to allow chaining of methods. Otherwise, the reference + * number of the section is returned. + */ + referenceNumber(referenceNumber) { + if (typeof referenceNumber === 'undefined') { + if (this.styleGuide() && this.styleGuide().hasNumericReferences()) { + return this.data.reference; + } else { + return this.data.referenceNumber; + } + } -/** - * Gets or sets the weight of the section. - * - * If the `weight` value is provided, the `weight` for this section is set. - * Otherwise, the `weight` of the section is returned. - * - * @param {number} [weight] Optional. The weight of the section as an integer. - * @returns {KssSection|number} If `weight` is given, the `KssSection` object - * is returned to allow chaining of methods. Otherwise, the weight of the - * section is returned. - */ -KssSection.prototype.weight = function(weight) { - if (typeof weight === 'undefined') { - return this.data.weight; + this.data.referenceNumber = referenceNumber; + // Allow chaining. + return this; } - // @TODO: The weight needs to bubble-up to the KssStyleGuide weightMap. - this.data.weight = weight; - // Allow chaining. - return this; -}; + /** + * Gets or sets the reference of the section, encoded as a valid URI fragment. + * + * If the `referenceURI` value is provided, the `referenceURI` for this section + * is set. Otherwise, the `referenceURI` of the section is returned. + * + * @param {string} [referenceURI] Optional. The referenceURI of the section. + * @returns {KssSection|string} If `referenceURI` is given, the `KssSection` + * object is returned to allow chaining of methods. Otherwise, the + * referenceURI of the section is returned. + */ + referenceURI(referenceURI) { + if (typeof referenceURI === 'undefined') { + if (!this.data.referenceURI) { + this.data.referenceURI = encodeURI( + this.reference() + .replace(/ \- /g, '-') + .replace(/[^\w-]+/g, '-') + .toLowerCase() + ); + } + return this.data.referenceURI; + } -/** - * Gets or sets the depth of the section. - * - * If the `depth` value is provided, the `depth` for this section is set. - * Otherwise, the `depth` of the section is returned. - * - * @param {number} [depth] Optional. The depth of the section as a positive - * integer. - * @returns {KssSection|number} If `depth` is given, the `KssSection` object is - * returned to allow chaining of methods. Otherwise, the depth of the section - * is returned. - */ -KssSection.prototype.depth = function(depth) { - if (typeof depth === 'undefined') { - return this.meta.depth; + this.data.referenceURI = referenceURI; + // Allow chaining. + return this; } - this.meta.depth = depth; - // Allow chaining. - return this; -}; + /** + * Gets or sets the weight of the section. + * + * If the `weight` value is provided, the `weight` for this section is set. + * Otherwise, the `weight` of the section is returned. + * + * @param {number} [weight] Optional. The weight of the section as an integer. + * @returns {KssSection|number} If `weight` is given, the `KssSection` object + * is returned to allow chaining of methods. Otherwise, the weight of the + * section is returned. + */ + weight(weight) { + if (typeof weight === 'undefined') { + return this.data.weight; + } -/** - * Gets or sets the markup of the section. - * - * If the `markup` value is provided, the `markup` for this section is set. - * Otherwise, the `markup` of the section is returned. - * - * @param {string} [markup] Optional. The markup of the section. - * @returns {KssSection|string|false} If `markup` is given, the `KssSection` object is - * returned to allow chaining of methods. Otherwise, the markup of the section - * is returned, or `false` if none. - */ -KssSection.prototype.markup = function(markup) { - if (typeof markup === 'undefined') { - return this.data.markup; + // @TODO: The weight needs to bubble-up to the KssStyleGuide weightMap. + this.data.weight = weight; + // Allow chaining. + return this; } - this.data.markup = markup; - // Allow chaining. - return this; -}; - -/** - * Gets or adds nested objects of the section. - * - * A common helper for `.modifiers()` and `.parameters()` methods. - * - * Different types of arguments for `properties` will yield different results: - * - `Object|Array`: If the value is an array of objects or an object, the - * `properties` are added to this section. - * - `undefined`: Pass nothing to return all of the section's properties in an - * array. - * - `integer`: Use a 0-based index to return the section's Nth property. - * - `string`: Use a string to return a specific modifier by name. - * - * @private - * @param {string} propertyName The name of property in `KssSection`. - * @param {Constructor} objectConstructor The constructor function for the type - * of object the property is. - * @param {*} [properties] Optional. The properties to set for the section. - * @returns {*} If `properties` is given, the `KssSection` object is returned to - * allow chaining of methods. Otherwise, the requested properties of the - * section are returned. - */ -KssSection.prototype._propertyHelper = function(propertyName, objectConstructor, properties) { - var self = this, - query, index; + /** + * Gets or sets the depth of the section. + * + * If the `depth` value is provided, the `depth` for this section is set. + * Otherwise, the `depth` of the section is returned. + * + * @param {number} [depth] Optional. The depth of the section as a positive + * integer. + * @returns {KssSection|number} If `depth` is given, the `KssSection` object is + * returned to allow chaining of methods. Otherwise, the depth of the section + * is returned. + */ + depth(depth) { + if (typeof depth === 'undefined') { + return this.meta.depth; + } - if (typeof properties === 'undefined') { - return this.data[propertyName]; + this.meta.depth = depth; + // Allow chaining. + return this; } - // If we are given an object, assign the properties. - if (typeof properties === 'object') { - if (!(properties instanceof Array)) { - properties = [properties]; + /** + * Gets or sets the markup of the section. + * + * If the `markup` value is provided, the `markup` for this section is set. + * Otherwise, the `markup` of the section is returned. + * + * @param {string} [markup] Optional. The markup of the section. + * @returns {KssSection|string|boolean} If `markup` is given, the `KssSection` object is + * returned to allow chaining of methods. Otherwise, the markup of the section + * is returned, or `false` if none. + */ + markup(markup) { + if (typeof markup === 'undefined') { + return this.data.markup; } - properties.forEach(function(property) { - var newProperty = (property instanceof objectConstructor) ? property : new objectConstructor(property); - newProperty.section(self); - self.data[propertyName].push(newProperty); - }); + + this.data.markup = markup; // Allow chaining. return this; } - // Otherwise, we should search for the requested property. - query = properties; - index = parseInt(query); - if (typeof query === 'number' || typeof query === 'string' && query === (index + '')) { - return (index < this.data[propertyName].length) ? this.data[propertyName][index] : false; - // If the query can be converted to an integer, search by index instead. - } else { - // Otherwise, search for the property by name. - for (var i = 0; i < this.data[propertyName].length; i++) { - if (this.data[propertyName][i].name() === query) { - return this.data[propertyName][i]; + /** + * Gets or adds nested objects of the section. + * + * A common helper for `.modifiers()` and `.parameters()` methods. + * + * Different types of arguments for `properties` will yield different results: + * - `Object|Array`: If the value is an array of objects or an object, the + * `properties` are added to this section. + * - `undefined`: Pass nothing to return all of the section's properties in an + * array. + * - `integer`: Use a 0-based index to return the section's Nth property. + * - `string`: Use a string to return a specific modifier by name. + * + * @private + * @param {string} propertyName The name of property in `KssSection`. + * @param {Constructor} objectConstructor The constructor function for the type + * of object the property is. + * @param {*} [properties] Optional. The properties to set for the section. + * @returns {*} If `properties` is given, the `KssSection` object is returned to + * allow chaining of methods. Otherwise, the requested properties of the + * section are returned. + */ + _propertyHelper(propertyName, objectConstructor, properties) { + if (typeof properties === 'undefined') { + return this.data[propertyName]; + } + + // If we are given an object, assign the properties. + if (typeof properties === 'object') { + if (!(properties instanceof Array)) { + properties = [properties]; } + properties.forEach(property => { + let newProperty = (property instanceof objectConstructor) ? property : new objectConstructor(property); + newProperty.section(this); + this.data[propertyName].push(newProperty); + }); + // Allow chaining. + return this; } - } - // No matching property found. - return false; -}; + // Otherwise, we should search for the requested property. + let query = properties, + index = parseInt(query); + if (typeof query === 'number' || typeof query === 'string' && query === (index + '')) { + return (index < this.data[propertyName].length) ? this.data[propertyName][index] : false; + // If the query can be converted to an integer, search by index instead. + } else { + // Otherwise, search for the property by name. + for (let i = 0; i < this.data[propertyName].length; i++) { + if (this.data[propertyName][i].name() === query) { + return this.data[propertyName][i]; + } + } + } -/** - * Gets or adds modifiers of the section. - * - * Different types of arguments will yield different results: - * - `modifiers(Object|Array)`: If the value is an array of objects or an - * object, the `modifiers` are added to this section. - * - `modifiers()`: Pass nothing to return all of the section's modifiers in an - * array. - * - `modifiers(Integer)`: Use a 0-based index to return the section's Nth - * modifier. - * - `modifiers(String)`: Use a string to return a specific modifier by name. - * - * @param {*} [modifiers] Optional. The modifiers of the section. - * @returns {KssSection|KssModifier|KssModifier[]|false} If `modifiers` is - * given, the `KssSection` object is returned to allow chaining of methods. - * Otherwise, the requested modifiers of the section are returned. - */ -KssSection.prototype.modifiers = function(modifiers) { - return this._propertyHelper('modifiers', KssModifier, modifiers); -}; + // No matching property found. + return false; + } -/** - * Gets or adds parameters if the section is a CSS preprocessor function/mixin. - * - * Different types of arguments will yield different results: - * - `parameters(Object|Array)`: If the value is an array of objects or an - * object, the `parameters` are added to this section. - * - `parameters()`: Pass nothing to return all of the section's parameters in - * an array. - * - `parameters(Integer)`: Use a 0-based index to return the section's Nth - * parameter. - * - `parameters(String)`: Use a string to return a specific parameter by name. - * - * @param {*} [parameters] Optional. The parameters of the section. - * @returns {KssSection|KssParameter|KssParameter[]|false} If `parameters` is - * given, the `KssSection` object is returned to allow chaining of methods. - * Otherwise, the requested parameters of the section are returned. - */ -KssSection.prototype.parameters = function(parameters) { - return this._propertyHelper('parameters', KssParameter, parameters); -}; + /** + * Gets or adds modifiers of the section. + * + * Different types of arguments will yield different results: + * - `modifiers(Object|Array)`: If the value is an array of objects or an + * object, the `modifiers` are added to this section. + * - `modifiers()`: Pass nothing to return all of the section's modifiers in an + * array. + * - `modifiers(Integer)`: Use a 0-based index to return the section's Nth + * modifier. + * - `modifiers(String)`: Use a string to return a specific modifier by name. + * + * @param {*} [modifiers] Optional. The modifiers of the section. + * @returns {KssSection|KssModifier|KssModifier[]|boolean} If `modifiers` is + * given, the `KssSection` object is returned to allow chaining of methods. + * Otherwise, the requested modifiers of the section are returned. + */ + modifiers(modifiers) { + return this._propertyHelper('modifiers', KssModifier, modifiers); + } + + /** + * Gets or adds parameters if the section is a CSS preprocessor function/mixin. + * + * Different types of arguments will yield different results: + * - `parameters(Object|Array)`: If the value is an array of objects or an + * object, the `parameters` are added to this section. + * - `parameters()`: Pass nothing to return all of the section's parameters in + * an array. + * - `parameters(Integer)`: Use a 0-based index to return the section's Nth + * parameter. + * - `parameters(String)`: Use a string to return a specific parameter by name. + * + * @param {*} [parameters] Optional. The parameters of the section. + * @returns {KssSection|KssParameter|KssParameter[]|boolean} If `parameters` is + * given, the `KssSection` object is returned to allow chaining of methods. + * Otherwise, the requested parameters of the section are returned. + */ + parameters(parameters) { + return this._propertyHelper('parameters', KssParameter, parameters); + } +} module.exports = KssSection; diff --git a/lib/kss_styleguide.js b/lib/kss_styleguide.js index a1fc1a79..fa469a62 100644 --- a/lib/kss_styleguide.js +++ b/lib/kss_styleguide.js @@ -1,418 +1,415 @@ 'use strict'; -var KssSection = require('./kss_section'); +const KssSection = require('./kss_section'); /** * The `kss/lib/kss_styleguide` module is normally accessed via the - * [`KssStyleGuide()`]{@link module:kss.KssStyleGuide} constructor of the `kss` + * [`KssStyleGuide()`]{@link module:kss.KssStyleGuide} class of the `kss` * module: * ``` - * var KssStyleGuide = require('kss').KssStyleGuide; + * const KssStyleGuide = require('kss').KssStyleGuide; * ``` * @private * @module kss/lib/kss_styleguide */ -var KssStyleGuide; - -/** - * An instance of this class is returned on finishing `kss.traverse`. It has a - * few convenience methods for interpreting data, the most important of which is - * sections() for searching for specific sections of the style guide. - * - * @constructor - * @alias module:kss.KssStyleGuide - * @param {Object} [data] The data object generated by traverse. - */ -KssStyleGuide = function(data) { - if (!(this instanceof KssStyleGuide)) { - return new KssStyleGuide(data); - } +class KssStyleGuide { + + /** + * An instance of this class is returned on finishing `kss.traverse`. It has a + * few convenience methods for interpreting data, the most important of which is + * sections() for searching for specific sections of the style guide. + * + * @constructor + * @alias module:kss.KssStyleGuide + * @param {Object} [data] The data object generated by traverse. + */ + constructor(data) { + if (!(this instanceof KssStyleGuide)) { + return new KssStyleGuide(data); + } - data = data || {}; - - this.meta = { - autoInit: false, - files: data.files || [], - hasNumericReferences: true, - needsDepth: false, - needsReferenceNumber: false, - needsSort: false, - referenceDelimiter: '.', - referenceMap: [], - weightMap: {} - }; - - this.data = { - customPropertyNames: [], - sections: [] - }; - - if (data.customPropertyNames) { - this.customPropertyNames(data.customPropertyNames); - } + data = data || {}; + + this.meta = { + autoInit: false, + files: data.files || [], + hasNumericReferences: true, + needsDepth: false, + needsReferenceNumber: false, + needsSort: false, + referenceDelimiter: '.', + referenceMap: [], + weightMap: {} + }; + + this.data = { + customPropertyNames: [], + sections: [] + }; + + if (data.customPropertyNames) { + this.customPropertyNames(data.customPropertyNames); + } - if (data.sections) { - // Note that auto-initialization is temporarily off since we don't want to - // init this new object until after these sections are added. - this.sections(data.sections); - } + if (data.sections) { + // Note that auto-initialization is temporarily off since we don't want to + // init this new object until after these sections are added. + this.sections(data.sections); + } - // Now that all sections are added, turn on auto-initialization. But allow a - // flag passed to the constructor to turn off auto-initialization. - if (data.autoInit !== false) { - this.meta.autoInit = true; - } + // Now that all sections are added, turn on auto-initialization. But allow a + // flag passed to the constructor to turn off auto-initialization. + if (data.autoInit !== false) { + this.meta.autoInit = true; + } - if (this.meta.autoInit) { - this.init(); + if (this.meta.autoInit) { + this.init(); + } } -}; - -/** - * Return the `KssStyleGuide` as a JSON object. - * - * @returns {Object} A JSON object representation of the KssStyleGuide. - */ -KssStyleGuide.prototype.toJSON = function() { - var returnObject; - returnObject = { - customPropertyNames: this.customPropertyNames(), - hasNumericReferences: this.meta.hasNumericReferences, - referenceDelimiter: this.meta.referenceDelimiter - }; - - returnObject.sections = this.sections().map(function(section) { - return section.toJSON(); - }); - - return returnObject; -}; - -/** - * Toggles the auto-initialization setting of this style guide. - * - * If a `false` value is provided, auto-initialization is disabled and users - * will be required to call `init()` manually after adding sections via - * `sections()`. If a `true' value is provided, auto-initialization will be - * enabled and the `init()` method will immediately be called. - * - * @param {boolean} autoInit The new setting for auto-initialization. - * @returns {KssStyleGuide} The `KssStyleGuide` object is returned to allow - * chaining of methods. - */ -KssStyleGuide.prototype.autoInit = function(autoInit) { - this.meta.autoInit = autoInit ? true : false; + /** + * Return the `KssStyleGuide` as a JSON object. + * + * @returns {Object} A JSON object representation of the KssStyleGuide. + */ + toJSON() { + let returnObject; + + returnObject = { + customPropertyNames: this.customPropertyNames(), + hasNumericReferences: this.meta.hasNumericReferences, + referenceDelimiter: this.meta.referenceDelimiter + }; + + returnObject.sections = this.sections().map(section => { + return section.toJSON(); + }); - if (this.meta.autoInit) { - this.init(); + return returnObject; } - // Allow chaining. - return this; -}; - -/** - * Sorts the style guides sections and (re-)initializes some section values. - * - * Some section data is dependent on the state of the KssStyleGuide. When - * sections are added with `sections()`, it determines what updates are needed. - * If needed, this method: - * - Calculates the depth of the reference for each section. e.g. Section 2.1.7 - * has a depth of 3. - * - Sorts all the sections by reference. - * - Calculates a reference number if the style guide uses - * word-based references. - * - * By default this method is called automatically whenever new sections are - * added to the style guide. This - * - * @returns {KssStyleGuide} Returns the `KssStyleGuide` object to allow chaining - * of methods. - */ -KssStyleGuide.prototype.init = function() { - var self = this, i, numSections, getWeight, incrementIndex, autoIncrement = [0], ref, previousRef = [], index; + /** + * Toggles the auto-initialization setting of this style guide. + * + * If a `false` value is provided, auto-initialization is disabled and users + * will be required to call `init()` manually after adding sections via + * `sections()`. If a `true' value is provided, auto-initialization will be + * enabled and the `init()` method will immediately be called. + * + * @param {boolean} autoInit The new setting for auto-initialization. + * @returns {KssStyleGuide} The `KssStyleGuide` object is returned to allow + * chaining of methods. + */ + autoInit(autoInit) { + this.meta.autoInit = !!autoInit; + + if (this.meta.autoInit) { + this.init(); + } - if (this.data.sections.length) { - numSections = this.data.sections.length; + // Allow chaining. + return this; + } - // The delimiter has changed, so recalculate the depth of each section's - // reference. - if (this.meta.needsDepth) { - for (i = 0; i < numSections; i++) { - this.data.sections[i].depth(this.data.sections[i].reference().split(this.meta.referenceDelimiter).length); + /** + * Sorts the style guides sections and (re-)initializes some section values. + * + * Some section data is dependent on the state of the KssStyleGuide. When + * sections are added with `sections()`, it determines what updates are needed. + * If needed, this method: + * - Calculates the depth of the reference for each section. e.g. Section 2.1.7 + * has a depth of 3. + * - Sorts all the sections by reference. + * - Calculates a reference number if the style guide uses + * word-based references. + * + * By default this method is called automatically whenever new sections are + * added to the style guide. This + * + * @returns {KssStyleGuide} Returns the `KssStyleGuide` object to allow chaining + * of methods. + */ + init() { + if (this.data.sections.length) { + let numSections = this.data.sections.length; + + // The delimiter has changed, so recalculate the depth of each section's + // reference. + if (this.meta.needsDepth) { + for (let i = 0; i < numSections; i++) { + this.data.sections[i].depth(this.data.sections[i].reference().split(this.meta.referenceDelimiter).length); + } + this.meta.needsDepth = false; } - this.meta.needsDepth = false; - } - // Sort all the sections. - if (this.meta.needsSort) { - // Sorting helper function that gets the weight of the given reference at - // the given depth. e.g. `getWeight('4.3.2.2', 2)` will return the weight - // for section 4.3. - getWeight = function(reference, depth) { - reference = reference.toLowerCase(); - reference = reference.split(self.meta.referenceDelimiter, depth).join(self.meta.referenceDelimiter); - - return self.meta.weightMap[reference] ? self.meta.weightMap[reference] : 0; - }; - - // Sort sections based on the references. - this.data.sections.sort(function(a, b) { - // Split the 2 references into chunks by their period or dash separators. - var refsA = a.reference().toLowerCase().split(self.meta.referenceDelimiter), - refsB = b.reference().toLowerCase().split(self.meta.referenceDelimiter), - weightA, weightB, - j, l = Math.max(refsA.length, refsB.length); - - // Compare each set of chunks until we know which reference should be listed first. - for (j = 0; j < l; j++) { - if (refsA[j] && refsB[j]) { - // If the 2 chunks are unequal, compare them. - if (refsA[j] !== refsB[j]) { - // If the chunks have different weights, sort by weight. - weightA = getWeight(a.reference(), j + 1); - weightB = getWeight(b.reference(), j + 1); - if (weightA !== weightB) { - return weightA - weightB; - } else if (refsA[j].match(/^\d+$/) && refsB[j].match(/^\d+$/)) { - // If both chunks are digits, use numeric sorting. - return refsA[j] - refsB[j]; - } else { - // Otherwise, use alphabetical string sorting. - return (refsA[j] > refsB[j]) ? 1 : -1; + // Sort all the sections. + if (this.meta.needsSort) { + let delimiter = this.meta.referenceDelimiter; + let self = this; + // Sorting helper function that gets the weight of the given reference at + // the given depth. e.g. `getWeight('4.3.2.2', 2)` will return the weight + // for section 4.3. + let getWeight = function(reference, depth) { + reference = reference.toLowerCase().split(delimiter, depth).join(delimiter); + + return self.meta.weightMap[reference] ? self.meta.weightMap[reference] : 0; + }; + + // Sort sections based on the references. + this.data.sections.sort((a, b) => { + // Split the 2 references into chunks by their period or dash separators. + let refsA = a.reference().toLowerCase().split(delimiter), + refsB = b.reference().toLowerCase().split(delimiter), + weightA, weightB, + maxRefLength = Math.max(refsA.length, refsB.length); + + // Compare each set of chunks until we know which reference should be listed first. + for (let i = 0; i < maxRefLength; i++) { + if (refsA[i] && refsB[i]) { + // If the 2 chunks are unequal, compare them. + if (refsA[i] !== refsB[i]) { + // If the chunks have different weights, sort by weight. + weightA = getWeight(a.reference(), i + 1); + weightB = getWeight(b.reference(), i + 1); + if (weightA !== weightB) { + return weightA - weightB; + } else if (refsA[i].match(/^\d+$/) && refsB[i].match(/^\d+$/)) { + // If both chunks are digits, use numeric sorting. + return refsA[i] - refsB[i]; + } else { + // Otherwise, use alphabetical string sorting. + return (refsA[i] > refsB[i]) ? 1 : -1; + } } + } else { + // If 1 of the chunks is empty, it goes first. + return refsA[i] ? 1 : -1; } - } else { - // If 1 of the chunks is empty, it goes first. - return refsA[j] ? 1 : -1; } - } - return 0; - }); - this.meta.needsSort = false; - } + return 0; + }); + this.meta.needsSort = false; + } - // Create an auto-incremented reference number if the references are not - // number-based references. - if (this.meta.needsReferenceNumber) { - for (i = 0; i < numSections; i++) { - ref = this.data.sections[i].reference(); - - // Compare the previous Ref to the new Ref. - ref = ref.split(this.meta.referenceDelimiter); - // If they are already equal, we don't need to increment the section number. - if (previousRef.join(this.meta.referenceDelimiter) !== ref.join(this.meta.referenceDelimiter)) { - incrementIndex = 0; - for (index = 0; index < previousRef.length; index += 1) { - // Find the index where the refs differ. - if (index >= ref.length || previousRef[index] !== ref[index]) { - break; + // Create an auto-incremented reference number if the references are not + // number-based references. + if (this.meta.needsReferenceNumber) { + let autoIncrement = [0], ref, previousRef = []; + for (let i = 0; i < numSections; i++) { + ref = this.data.sections[i].reference(); + + // Compare the previous Ref to the new Ref. + ref = ref.split(this.meta.referenceDelimiter); + // If they are already equal, we don't need to increment the section number. + if (previousRef.join(this.meta.referenceDelimiter) !== ref.join(this.meta.referenceDelimiter)) { + let incrementIndex = 0; + for (let index = 0; index < previousRef.length; index += 1) { + // Find the index where the refs differ. + if (index >= ref.length || previousRef[index] !== ref[index]) { + break; + } + incrementIndex = index + 1; + } + if (incrementIndex < autoIncrement.length) { + // Increment the part where the refs started to differ. + autoIncrement[incrementIndex]++; + // Trim off the extra parts of the autoincrement where the refs differed. + autoIncrement = autoIncrement.slice(0, incrementIndex + 1); + } + // Add parts to the autoincrement to ensure it is the same length as the new ref. + for (let index = autoIncrement.length; index < ref.length; index += 1) { + autoIncrement[index] = 1; } - incrementIndex = index + 1; - } - if (incrementIndex < autoIncrement.length) { - // Increment the part where the refs started to differ. - autoIncrement[incrementIndex]++; - // Trim off the extra parts of the autoincrement where the refs differed. - autoIncrement = autoIncrement.slice(0, incrementIndex + 1); - } - // Add parts to the autoincrement to ensure it is the same length as the new ref. - for (index = autoIncrement.length; index < ref.length; index += 1) { - autoIncrement[index] = 1; } + this.data.sections[i].referenceNumber(autoIncrement.join('.')); + previousRef = ref; } - this.data.sections[i].referenceNumber(autoIncrement.join('.')); - previousRef = ref; + this.meta.needsReferenceNumber = false; } - this.meta.needsReferenceNumber = false; } - } - - // Allow chaining. - return this; -}; -/** - * Gets or sets the list of custom properties of the style guide. - * - * If the `names` value is provided, the names are added to the style guide's - * list of custom properties. Otherwise, the style guide's list of custom - * properties is returned. - * - * @param {string|string[]} [names] Optional. The names of of the section. - * @returns {KssStyleGuide|string[]} If `names` is given, the `KssStyleGuide` - * object is returned to allow chaining of methods. Otherwise, the list of - * custom properties of the style guide is returned. - */ -KssStyleGuide.prototype.customPropertyNames = function(names) { - if (typeof names === 'undefined') { - return this.data.customPropertyNames; + // Allow chaining. + return this; } - if (!(names instanceof Array)) { - names = [names]; - } - for (var i = 0; i < names.length; i++) { - if (this.data.customPropertyNames.indexOf(names[i]) === -1) { - this.data.customPropertyNames.push(names[i]); + /** + * Gets or sets the list of custom properties of the style guide. + * + * If the `names` value is provided, the names are added to the style guide's + * list of custom properties. Otherwise, the style guide's list of custom + * properties is returned. + * + * @param {string|string[]} [names] Optional. The names of of the section. + * @returns {KssStyleGuide|string[]} If `names` is given, the `KssStyleGuide` + * object is returned to allow chaining of methods. Otherwise, the list of + * custom properties of the style guide is returned. + */ + customPropertyNames(names) { + if (typeof names === 'undefined') { + return this.data.customPropertyNames; } - } - // Allow chaining. - return this; -}; -/** - * Returns whether the style guide has numeric references or not. - * - * @returns {boolean} Whether the style guide has numeric references or not. - */ -KssStyleGuide.prototype.hasNumericReferences = function() { - return this.meta.hasNumericReferences; -}; + if (!(names instanceof Array)) { + names = [names]; + } + for (let i = 0; i < names.length; i++) { + if (this.data.customPropertyNames.indexOf(names[i]) === -1) { + this.data.customPropertyNames.push(names[i]); + } + } + // Allow chaining. + return this; + } -/** - * Gets or sets the sections of the style guide. - * - * If `sections` objects are provided, the sections are added to the style - * guide. Otherwise, a search is performed to return the desired sections. - * - * There's a few ways to use search with this method: - * - `sections()` returns all of the sections. - * - * Using strings: - * - `sections('2')` returns Section 2. - * - `sections('2.*')` returns Section 2 and all of its descendants. - * - `sections('2.x')` returns Section 2's children only. - * - `sections('2.x.x')` returns Section 2's children, and their children too. - * - * Or Regular Expressions: - * - `sections(/2\.[1-5]/)` returns Sections 2.1 through to 2.5. - * - * @param {Object|Object[]|string|Regexp} [sections] Optional. A section object - * or array of secction objects to add to the style guide. Or a string or - * Regexp object to match a KssSection's style guide reference. - * @returns {KssStyleGuide|KssSection|KssSection[]|false} If `sections` is - * given, the `KssStyleGuide` object is returned to allow chaining of methods. - * Otherwise, the exact KssSection requested, an array of KssSection objects - * matching the query, or false is returned. - */ -KssStyleGuide.prototype.sections = function(sections) { - var self = this, - query, - i, - delim, - matchedSections = [], - match; - - if (typeof sections === 'undefined') { - return this.data.sections; + /** + * Returns whether the style guide has numeric references or not. + * + * @returns {boolean} Whether the style guide has numeric references or not. + */ + hasNumericReferences() { + return this.meta.hasNumericReferences; } - // If we are given an object, assign the properties. - if (typeof sections === 'object' && !(sections instanceof RegExp)) { - if (!(sections instanceof Array)) { - sections = [sections]; + /** + * Gets or sets the sections of the style guide. + * + * If `sections` objects are provided, the sections are added to the style + * guide. Otherwise, a search is performed to return the desired sections. + * + * There's a few ways to use search with this method: + * - `sections()` returns all of the sections. + * + * Using strings: + * - `sections('2')` returns Section 2. + * - `sections('2.*')` returns Section 2 and all of its descendants. + * - `sections('2.x')` returns Section 2's children only. + * - `sections('2.x.x')` returns Section 2's children, and their children too. + * + * Or Regular Expressions: + * - `sections(/2\.[1-5]/)` returns Sections 2.1 through to 2.5. + * + * @param {Object|Object[]|string|RegExp} [sections] Optional. A section object + * or array of secction objects to add to the style guide. Or a string or + * Regexp object to match a KssSection's style guide reference. + * @returns {KssStyleGuide|KssSection|KssSection[]|boolean} If `sections` is + * given, the `KssStyleGuide` object is returned to allow chaining of methods. + * Otherwise, the exact KssSection requested, an array of KssSection objects + * matching the query, or false is returned. + */ + sections(sections) { + let query, + matchedSections = []; + + if (typeof sections === 'undefined') { + return this.data.sections; } - sections.forEach(function(section) { - var originalDelimiter = self.meta.referenceDelimiter; - if (!(section instanceof KssSection)) { - section = new KssSection(section); + // If we are given an object, assign the properties. + if (typeof sections === 'object' && !(sections instanceof RegExp)) { + if (!(sections instanceof Array)) { + sections = [sections]; } + sections.forEach(section => { + let originalDelimiter = this.meta.referenceDelimiter; - // Set the style guide for each section. - section.styleGuide(self); - - // Determine if the references are number-based or word-based. - self.meta.hasNumericReferences = self.meta.hasNumericReferences && /^[\.\d]+$/.test(section.reference()); - // Store the reference for quick searching later. - self.meta.referenceMap[section.reference()] = section; - // Store the section's weight. - self.meta.weightMap[section.reference().toLowerCase()] = section.weight(); - // Determine the separator used in references; e.g. 'a - b' or 'a.b'. - if (section.reference().indexOf(' - ') > -1) { - self.meta.referenceDelimiter = ' - '; - } + if (!(section instanceof KssSection)) { + section = new KssSection(section); + } - // Add the section to the style guide. - self.data.sections.push(section); + // Set the style guide for each section. + section.styleGuide(this); + + // Determine if the references are number-based or word-based. + this.meta.hasNumericReferences = this.meta.hasNumericReferences && /^[\.\d]+$/.test(section.reference()); + // Store the reference for quick searching later. + this.meta.referenceMap[section.reference()] = section; + // Store the section's weight. + this.meta.weightMap[section.reference().toLowerCase()] = section.weight(); + // Determine the separator used in references; e.g. 'a - b' or 'a.b'. + if (section.reference().indexOf(' - ') > -1) { + this.meta.referenceDelimiter = ' - '; + } - // If the delimiter changed, flag the depths as needing recalculation. - if (originalDelimiter !== self.meta.referenceDelimiter) { - self.meta.needsDepth = true; - } else { - // Set the depth of this section's reference. - section.depth(section.reference().split(self.meta.referenceDelimiter).length); - } + // Add the section to the style guide. + this.data.sections.push(section); - // Determine if all sections need their reference number recalculated. - if (!self.meta.hasNumericReferences) { - self.meta.needsReferenceNumber = true; - } + // If the delimiter changed, flag the depths as needing recalculation. + if (originalDelimiter !== this.meta.referenceDelimiter) { + this.meta.needsDepth = true; + } else { + // Set the depth of this section's reference. + section.depth(section.reference().split(this.meta.referenceDelimiter).length); + } - // A new section means all sections need to be sorted. - self.meta.needsSort = true; - }); + // Determine if all sections need their reference number recalculated. + if (!this.meta.hasNumericReferences) { + this.meta.needsReferenceNumber = true; + } - // Automatically re-initialize the style guide. - if (this.autoInit) { - this.init(); + // A new section means all sections need to be sorted. + this.meta.needsSort = true; + }); + + // Automatically re-initialize the style guide. + if (this.autoInit) { + this.init(); + } + // Allow chaining. + return this; } - // Allow chaining. - return this; - } - // Otherwise, we should search for the requested section. - query = sections; - - // Exact queries. - if (typeof query === 'string') { - // If the query is '*', 'x', or ends with '.*', ' - *', '.x', or ' - x', - // then it is not an exact query. - if (!(/(^[x\*]$|\s\-\s[x\*]$|\.[x\*]$)/.test(query))) { - if (this.meta.referenceMap[query]) { - return this.meta.referenceMap[query]; - } else { - return false; + // Otherwise, we should search for the requested section. + query = sections; + + // Exact queries. + if (typeof query === 'string') { + // If the query is '*', 'x', or ends with '.*', ' - *', '.x', or ' - x', + // then it is not an exact query. + if (!(/(^[x\*]$|\s\-\s[x\*]$|\.[x\*]$)/.test(query))) { + if (this.meta.referenceMap[query]) { + return this.meta.referenceMap[query]; + } else { + return false; + } } } - } - // Convert regex strings into proper JavaScript RegExp objects. - if (!(query instanceof RegExp)) { - delim = this.meta.referenceDelimiter === '.' ? '\\.' : '\\ \\-\\ '; - query = new RegExp( - query + // Convert regex strings into proper JavaScript RegExp objects. + if (!(query instanceof RegExp)) { + let delim = this.meta.referenceDelimiter === '.' ? '\\.' : '\\ \\-\\ '; + query = new RegExp( + query // Convert '*' to a simple .+ regex. - .replace(/^\*$/, '.+') - // Convert 'x' to a regex matching one level of reference. - .replace(/^x$/, '^.+?(?=($|' + delim + '))') - // Convert '.*' or ' - *' to a ([delim].+){0,1} regex. - .replace(/(\.|\s+\-\s+)\*$/g, '(' + delim + '.+){0,1}') - // Convert the first '.x' or ' - x' to a regex matching one sub-level - // of a reference. - .replace(/(\.|\s+\-\s+)x\b/, delim + '.+?(?=($|' + delim + '))') - // Convert any remaining '.x' or ' - x' to a regex matching zero or one - // sub-levels of a reference. - .replace(/(\.|\s+\-\s+)x\b/g, '(' + delim + '.+?(?=($|' + delim + '))){0,1}') - // Convert any remaining '-' into '\-' - .replace(/([^\\])\-/g, '$1\\-') - ); - } + .replace(/^\*$/, '.+') + // Convert 'x' to a regex matching one level of reference. + .replace(/^x$/, '^.+?(?=($|' + delim + '))') + // Convert '.*' or ' - *' to a ([delim].+){0,1} regex. + .replace(/(\.|\s+\-\s+)\*$/g, '(' + delim + '.+){0,1}') + // Convert the first '.x' or ' - x' to a regex matching one sub-level + // of a reference. + .replace(/(\.|\s+\-\s+)x\b/, delim + '.+?(?=($|' + delim + '))') + // Convert any remaining '.x' or ' - x' to a regex matching zero or one + // sub-levels of a reference. + .replace(/(\.|\s+\-\s+)x\b/g, '(' + delim + '.+?(?=($|' + delim + '))){0,1}') + // Convert any remaining '-' into '\-' + .replace(/([^\\])\-/g, '$1\\-') + ); + } - // General (regex) search - for (i = 0; i < this.data.sections.length; i += 1) { - match = this.data.sections[i].reference().match(query); - // The regex must match the full reference. - if (match && match[0] === this.data.sections[i].reference()) { - matchedSections.push(this.data.sections[i]); + // General (regex) search + for (let i = 0; i < this.data.sections.length; i += 1) { + let match = this.data.sections[i].reference().match(query); + // The regex must match the full reference. + if (match && match[0] === this.data.sections[i].reference()) { + matchedSections.push(this.data.sections[i]); + } } - } - return matchedSections; -}; + return matchedSections; + } +} module.exports = KssStyleGuide; diff --git a/lib/parse.js b/lib/parse.js index 2161e0eb..40af3584 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -1,33 +1,31 @@ -/* eslint-disable camelcase */ - 'use strict'; /** * The `kss/lib/parse` module is normally accessed via the * [`parse()`]{@link module:kss.parse} method of the `kss` module: * ``` - * var kss = require('kss'); + * const kss = require('kss'); * kss.parse(input, options, callback); * ``` * @private * @module kss/lib/parse */ -var KssStyleGuide = require('./kss_styleguide.js'), +const KssStyleGuide = require('./kss_styleguide.js'), KssSection = require('./kss_section.js'), marked = require('marked'), natural = require('natural'); -var inlineRenderer, - parse, parseChunk, createModifiers, createParameters, checkReference, findBlocks, processProperty, - isDeprecated, isExperimental, hasPrefix; - // Create a MarkDown renderer that does not output a wrapping paragraph. -inlineRenderer = new marked.Renderer(); +const inlineRenderer = new marked.Renderer(); inlineRenderer.paragraph = function(text) { return text; }; +let parse, parseChunk, findBlocks, + createModifiers, createParameters, + checkReference, processProperty, hasPrefix; + /** * Parse an array/string of documented CSS, or an object of files * and their content. @@ -38,32 +36,31 @@ inlineRenderer.paragraph = function(text) { * accessible as well. * * @alias module:kss.parse - * @param {Mixed} input The input to parse + * @param {*} input The input to parse * @param {Object} options Options to alter the output content. Same as the options in [`traverse()`]{@link module:kss.traverse}. * @param {Function} callback Called when parsing is complete */ parse = function(input, options, callback) { - var data = {}, fileName, files, - i, l; - // If supplied a string, just make it an Array. if (typeof input === 'string') { input = [input]; } + let styleGuide = {}; + // Otherwise assume the input supplied is a JSON object, as specified above. if (!Array.isArray(input)) { - files = input; + let files = input; input = []; - data.files = []; - for (fileName in files) { + styleGuide.files = []; + for (let fileName in files) { // istanbul ignore else if (files.hasOwnProperty(fileName)) { input.push(files[fileName]); - data.files.push(fileName); + styleGuide.files.push(fileName); } } - data.files.sort(); + styleGuide.files.sort(); } // Default parsing options @@ -77,14 +74,12 @@ parse = function(input, options, callback) { options.custom = options.custom || []; // Actually parse the input (parseChunk is the key function here.) - l = input.length; - data.sections = []; - - for (i = 0; i < l; i += 1) { - data = parseChunk(data, input[i], options); + styleGuide.sections = []; + for (let i = 0; i < input.length; i++) { + styleGuide = parseChunk(styleGuide, input[i], options); } - callback(null, new KssStyleGuide(data)); + callback(null, new KssStyleGuide(styleGuide)); }; /** @@ -99,18 +94,15 @@ parse = function(input, options, callback) { * @returns {Object} The raw style guide data from the newly parsed text. */ parseChunk = function(styleGuide, input, options) { - /* jshint loopfunc: true */ - - var currSection, i, l, blocks = [], paragraphs, j, m, hasModifiers, lastModifier; + /* eslint-disable no-loop-func */ // Retrieve an array of "comment block" strings, and then evaluate each one. - blocks = findBlocks(input); - l = blocks.length; + let blocks = findBlocks(input); - for (i = 0; i < l; i += 1) { + for (let i = 0; i < blocks.length; i++) { // Create a new, temporary section object with some default values. // "raw" is a comment block from the array above. - currSection = { + let currSection = { raw: blocks[i], header: '', description: '', @@ -120,7 +112,7 @@ parseChunk = function(styleGuide, input, options) { }; // Split the comment block into paragraphs. - paragraphs = currSection.raw + let paragraphs = currSection.raw .replace(/\r\n/g, '\n') // Convert Windows CRLF linebreaks. .replace(/\r/g, '\n') // Convert Classic Mac CR linebreaks too. .replace(/\n\s+\n/g, '\n\n') // Trim whitespace-only lines. @@ -130,15 +122,13 @@ parseChunk = function(styleGuide, input, options) { // Before anything else, process the properties that are clearly labeled and // can be found right away and then removed. currSection = processProperty('Markup', paragraphs, options, currSection); - /* eslint-disable no-loop-func */ currSection = processProperty('Weight', paragraphs, options, currSection, function(value) { return isNaN(value) ? 0 : parseFloat(value); }); // Process custom properties. - options.custom.forEach(function(name) { + options.custom.forEach(name => { currSection = processProperty(name, paragraphs, options, currSection); }); - /* eslint-enable no-loop-func */ // Ignore this block if a style guide reference number is not listed. currSection.reference = checkReference(paragraphs, options) || ''; @@ -159,20 +149,20 @@ parseChunk = function(styleGuide, input, options) { // The modifiers will be split into an array of lines. currSection.header = paragraphs[0]; currSection.description = paragraphs.slice(0, paragraphs.length - 2).join('\n\n'); - currSection.modifiers = paragraphs[paragraphs.length - 2] - .split('\n'); + currSection.modifiers = paragraphs[paragraphs.length - 2].split('\n'); // Check the modifiers paragraph. Does it look like it's a list of // modifiers, or just another paragraph of the description? - m = currSection.modifiers.length; - hasModifiers = true; - for (j = 0; j < m; j += 1) { + let numModifierLines = currSection.modifiers.length, + hasModifiers = true, + lastModifier = 0; + for (let j = 0; j < numModifierLines; j += 1) { if (currSection.modifiers[j].match(/^\s*.+?\s+\-\s/g)) { lastModifier = j; } else if (j === 0) { // The paragraph doesn't start with a modifier, so bail out. hasModifiers = false; - j = m; + j = numModifierLines; } else { // If the current line doesn't match a modifier, it must be a // multi-line modifier description. @@ -182,9 +172,7 @@ parseChunk = function(styleGuide, input, options) { } } // Remove any blank lines added. - /* eslint-disable no-loop-func */ - currSection.modifiers = currSection.modifiers.filter(function(line) { return line !== ''; }); - /* eslint-enable no-loop-func */ + currSection.modifiers = currSection.modifiers.filter(line => { return line !== ''; }); // If it's a modifiers paragraph, turn each one into a modifiers object. // Otherwise, add it back to the description. @@ -207,8 +195,8 @@ parseChunk = function(styleGuide, input, options) { currSection.header = currSection.header.replace(/\n/g, ' '); // Check the section's status. - currSection.deprecated = isDeprecated(currSection.description, options); - currSection.experimental = isExperimental(currSection.description, options); + currSection.deprecated = hasPrefix(currSection.description, options, 'Deprecated'); + currSection.experimental = hasPrefix(currSection.description, options, 'Experimental'); // If a separate header is requested, remove the first paragraph from the // description. @@ -229,66 +217,11 @@ parseChunk = function(styleGuide, input, options) { currSection = new KssSection(currSection); styleGuide.sections.push(currSection); } + /* eslint-enable no-loop-func */ return styleGuide; }; -/** - * Takes an array of modifier lines, and turns it into instances of KssModifier. - * - * @private - * @param {Array} lines Modifier lines, which should all be strings. - * @param {Object} options Any options passed on by the functions above. - * @returns {Array} The modifier instances created. - */ -createModifiers = function(lines, options) { - return lines.map(function(entry) { - var modifier, description; - - // Split modifier name and the description. - modifier = entry.split(/\s+\-\s+/, 1)[0]; - description = entry.replace(modifier, '', 1).replace(/^\s+\-\s+/, ''); - - // Markdown parsing. - if (options.markdown) { - description = marked(description, {renderer: inlineRenderer}); - } - - return { - name: modifier, - description: description - }; - }); -}; - -/** - * Takes an array of parameter lines, and turns it into instances of KssParameter. - * - * @private - * @param {Array} lines Parameter lines, which should all be strings. - * @param {Object} options Any options passed on by the functions above. - * @returns {Array} The parameter instances created. - */ -createParameters = function(lines, options) { - return lines.map(function(entry) { - var parameter, description; - - // Split parameter name and the description. - parameter = entry.split(/\s+\-\s+/, 1)[0]; - description = entry.replace(parameter, '', 1).replace(/^\s+\-\s+/, ''); - - // Markdown parsing. - if (options.markdown) { - description = marked(description, {renderer: inlineRenderer}); - } - - return { - name: parameter, - description: description - }; - }); -}; - /** * Returns an array of comment blocks found within a string. * @@ -298,25 +231,25 @@ createParameters = function(lines, options) { */ findBlocks = function(input) { /* eslint-disable key-spacing */ - var currentBlock = '', - insideSingleBlock = false, insideMultiBlock = false, insideDocblock = false, - indentAmount = false, - blocks = [], - lines, line, i, l, - commentExpressions = { - single: /^\s*\/\/.*$/, - docblockStart: /^\s*\/\*\*\s*$/, - multiStart: /^\s*\/\*+\s*$/, - multiFinish: /^\s*\*\/\s*$/ - }; + const commentExpressions = { + single: /^\s*\/\/.*$/, + docblockStart: /^\s*\/\*\*\s*$/, + multiStart: /^\s*\/\*+\s*$/, + multiFinish: /^\s*\*\/\s*$/ + }; /* eslint-enable key-spacing */ input = input.replace(/\r\n/g, '\n').replace(/\r/g, '\n'); - lines = input.split(/\n|$/g); + const lines = input.split(/\n|$/g); - l = lines.length; - for (i = 0; i < l; i += 1) { - line = lines[i]; + let blocks = [], + currentBlock = '', + indentAmount = false, + insideSingleBlock = false, + insideMultiBlock = false, + insideDocblock = false; + for (let i = 0; i < lines.length; i += 1) { + let line = lines[i]; // Remove trailing space. line = line.replace(/\s*$/, ''); @@ -378,7 +311,6 @@ findBlocks = function(input) { currentBlock += '\n'; // Always strip same indentation amount from each line. currentBlock += line.replace(new RegExp('^' + indentAmount), '', 1); - continue; } } @@ -390,6 +322,58 @@ findBlocks = function(input) { return blocks; }; +/** + * Takes an array of modifier lines, and turns it into a JSON equivalent of KssModifier. + * + * @private + * @param {Array} lines Modifier lines, which should all be strings. + * @param {Object} options Any options passed on by the functions above. + * @returns {Array} The modifier instances created. + */ +createModifiers = function(lines, options) { + return lines.map(entry => { + // Split modifier name and the description. + let modifier = entry.split(/\s+\-\s+/, 1)[0]; + let description = entry.replace(modifier, '', 1).replace(/^\s+\-\s+/, ''); + + // Markdown parsing. + if (options.markdown) { + description = marked(description, {renderer: inlineRenderer}); + } + + return { + name: modifier, + description: description + }; + }); +}; + +/** + * Takes an array of parameter lines, and turns it into instances of KssParameter. + * + * @private + * @param {Array} lines Parameter lines, which should all be strings. + * @param {Object} options Any options passed on by the functions above. + * @returns {Array} The parameter instances created. + */ +createParameters = function(lines, options) { + return lines.map(entry => { + // Split parameter name and the description. + let parameter = entry.split(/\s+\-\s+/, 1)[0]; + let description = entry.replace(parameter, '', 1).replace(/^\s+\-\s+/, ''); + + // Markdown parsing. + if (options.markdown) { + description = marked(description, {renderer: inlineRenderer}); + } + + return { + name: parameter, + description: description + }; + }); +}; + /** * Check a section for the reference number it may or may not have. * @@ -399,10 +383,8 @@ findBlocks = function(input) { * @returns {Boolean|String} False if not found, otherwise returns the reference number as a string. */ checkReference = function(paragraphs, options) { - var lastParagraph = paragraphs[paragraphs.length - 1].trim(), - words = lastParagraph.split(/\s+/), - keyword = false, - reference = false; + let lastParagraph = paragraphs[paragraphs.length - 1].trim(), + words = lastParagraph.split(/\s+/); // If is only one word in the last paragraph, it can't be a style guide ref. if (words.length < 2) { @@ -410,9 +392,10 @@ checkReference = function(paragraphs, options) { } // Search for the "styleguide" (or "style guide") keyword at the start of the paragraph. - [words[0], words[0] + words[1]].forEach(function(value, index) { + let keyword = false; + [words[0], words[0] + words[1]].forEach((value, index) => { if (!keyword) { - value = value.replace(/[-\:]?$/, ''); + value = value.replace(/[-:]?$/, ''); if (value.toLowerCase() === 'styleguide' || options.typos && natural.Metaphone.compare('Styleguide', value.replace('-', ''))) { keyword = words.shift(); if (index === 1) { @@ -422,11 +405,7 @@ checkReference = function(paragraphs, options) { } }); - if (keyword) { - reference = words.join(' '); - } - - return reference; + return keyword ? words.join(' ') : false; }; /** @@ -441,11 +420,11 @@ checkReference = function(paragraphs, options) { * @returns {Object} A new data object for the section. */ processProperty = function(propertyName, paragraphs, options, sectionData, processValue) { - var indexToRemove = 'not found'; + let indexToRemove = false; propertyName = propertyName.toLowerCase(); - paragraphs.map(function(paragraph, index) { + paragraphs.map((paragraph, index) => { if (hasPrefix(paragraph, options, propertyName)) { sectionData[propertyName] = paragraph.replace(new RegExp('^\\s*' + propertyName + '\\:\\s+?', 'gmi'), ''); if (typeof processValue === 'function') { @@ -457,37 +436,13 @@ processProperty = function(propertyName, paragraphs, options, sectionData, proce return paragraph; }); - if (indexToRemove !== 'not found') { + if (indexToRemove !== false) { paragraphs.splice(indexToRemove, 1); } return sectionData; }; -/** - * Check if the description indicates that a section is deprecated. - * - * @private - * @param {String} description The description of that section - * @param {Object} options The options passed on from previous functions - * @returns {Boolean} Whether the description indicates the section is deprecated. - */ -isDeprecated = function(description, options) { - return hasPrefix(description, options, 'Deprecated'); -}; - -/** - * Check if the description indicates that a section is experimental. - * - * @private - * @param {String} description The description of that section - * @param {Object} options The options passed on from previous functions - * @returns {Boolean} Whether the description indicates the section is experimental. - */ -isExperimental = function(description, options) { - return hasPrefix(description, options, 'Experimental'); -}; - /** * Essentially this function checks if a string is prefixed by a particular attribute, * e.g. 'Deprecated:' and 'Markup:' @@ -502,12 +457,11 @@ isExperimental = function(description, options) { * @returns {Boolean} Whether the description contains the specified prefix. */ hasPrefix = function(description, options, prefix) { - var words; if (!options.typos) { - return !!description.match(new RegExp('^\\s*' + prefix + '\\:', 'gmi')); + return (new RegExp('^\\s*' + prefix + '\\:', 'gmi')).test(description); } - words = description.replace(/^\s*/, '').match(/^\s*([a-z ]*)\:/gmi); + let words = description.replace(/^\s*/, '').match(/^\s*([a-z ]*):/gmi); if (!words) { return false; } diff --git a/lib/traverse.js b/lib/traverse.js index a9bffd38..a5732e76 100644 --- a/lib/traverse.js +++ b/lib/traverse.js @@ -6,19 +6,17 @@ * The `kss/lib/traverse` module is normally accessed via the * [`traverse()`]{@link module:kss.traverse} method of the `kss` module: * ``` - * var kss = require('kss'); + * const kss = require('kss'); * kss.traverse(directory, options, callback); * ``` * @private * @module kss/lib/traverse */ -var parse = require('./parse.js'), +const parse = require('./parse.js'), path = require('path'), fs = require('fs'); -var traverse; - /** * Traverse a directory, parse its contents, and create a KssStyleGuide. * @@ -61,14 +59,7 @@ var traverse; * @param {Object} options Options to alter the output content (optional) * @param {Function} callback Called when traversal AND parsing is complete */ -traverse = function(directory, options, callback) { - var fileNames = [], - fileCounter = 0, - filesRemaining = 0, - loopsRemaining = 0, - walkFinished, - walk; - +let traverse = function(directory, options, callback) { options = options || {}; if (typeof options === 'function') { callback = options; @@ -92,46 +83,22 @@ traverse = function(directory, options, callback) { if (!Array.isArray(directory)) { directory = [directory]; } - for (var key in directory) { + for (let key in directory) { // istanbul ignore else if (directory.hasOwnProperty(key)) { directory[key] = path.normalize(directory[key]); } } - // Callback for walk() when it has finished traversing all directories. - walkFinished = function() { - /* eslint-disable no-loop-func */ - var i, l = fileNames.length, files = [], orderedObject = {}; - - fileNames.sort(); - for (i = 0; i < l; i += 1) { - (function(j) { - fs.readFile(fileNames[j], 'utf8', function(error, contents) { - // istanbul ignore if - if (error) { callback(error); return; } - - files[j] = contents; - fileCounter -= 1; - - if (fileCounter === 0) { - files.map(function(fileContent, index) { - var filename = fileNames[index]; - orderedObject[filename] = fileContent; - return ''; - }); - parse(orderedObject, options, callback); - } - }); - }(i)); - } - }; + let fileNames = [], + fileCounter = 0, + filesRemaining = 0, + loopsRemaining = 0; // Courtesy of [stygstra](https://gist.github.com/514983) // istanbul ignore next - walk = function(directories, opts, cb) { + let walk = function(directories, opts, cb) { opts = opts || {}; - if (typeof cb !== 'function') { cb = function() {}; } if (!Array.isArray(directories)) { directories = [directories]; @@ -161,9 +128,9 @@ traverse = function(directory, options, callback) { } // Otherwise, if readdir() has results, loop through them. - relnames.forEach(function(relname) { + relnames.forEach(relname => { loopsRemaining -= 1; - var name = path.join(dir, relname); + let name = path.join(dir, relname); // Start an asynchronous stat of this file system item. filesRemaining += 1; @@ -199,7 +166,33 @@ traverse = function(directory, options, callback) { // Get each file in the target directory, order them alphabetically and then // parse their output. - walk(directory, options, walkFinished); + walk(directory, options, function() { + /* eslint-disable no-loop-func */ + fileNames.sort(); + let numFileNames = fileNames.length, + files = [], + orderedObject = {}; + for (let i = 0; i < numFileNames; i += 1) { + (function(j) { + fs.readFile(fileNames[j], 'utf8', function(error, contents) { + // istanbul ignore if + if (error) { callback(error); return; } + + files[j] = contents; + fileCounter -= 1; + + if (fileCounter === 0) { + files.map((fileContent, index) => { + let filename = fileNames[index]; + orderedObject[filename] = fileContent; + return ''; + }); + parse(orderedObject, options, callback); + } + }); + }(i)); + } + }); }; module.exports = traverse; diff --git a/package.json b/package.json index 78d8a522..d2e6d0c4 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,6 @@ "kss-node": "./bin/kss-node" }, "engines": { - "node": ">=0.12.0" + "node": ">=4.0" } } diff --git a/test/helper.js b/test/helper.js index 5d0e7d90..513506bb 100644 --- a/test/helper.js +++ b/test/helper.js @@ -11,7 +11,7 @@ global.helperUtils = { // Returns the full path to the test fixtures in test/fixtures or sub-directory. fixtures: function() { // Add the fixtures path to the start our list of paths. - var args = Array.prototype.slice.call(arguments); + let args = Array.prototype.slice.call(arguments); args.unshift('fixtures'); args.unshift(__dirname); return path.join.apply(this, args); @@ -31,7 +31,7 @@ global.helperUtils = { before(function() { // Add custom assertions. chai.use(function(chai) { - var Assertion = chai.Assertion; + let Assertion = chai.Assertion; // .containFixture(string) asserts that a given file should be in an array. Assertion.addMethod('containFixture', function(file) { diff --git a/test/test_cli.js b/test/test_cli.js index bd2d797a..1592f855 100644 --- a/test/test_cli.js +++ b/test/test_cli.js @@ -2,18 +2,16 @@ 'use strict'; -var cli = require('../lib/cli'), +const cli = require('../lib/cli'), fs = require('fs'), mockStream = require('mock-utf8-stream'), path = require('path'), wrench = require('wrench'); -var kssNode; - // Instead of child_process.exec, we use the lib/cli.js module and feed it mock // stdout, stderr and argv. -kssNode = function(args, cb) { - var argv = ['node', 'bin/kss-node'], +const kssNode = function(args, cb) { + let argv = ['node', 'bin/kss-node'], stdout = new mockStream.MockWritableStream(), stderr = new mockStream.MockWritableStream(); @@ -33,7 +31,7 @@ kssNode = function(args, cb) { }; describe('Command Line Interface', function() { - var noHomepageWarning = 'no homepage content found', + let noHomepageWarning = 'no homepage content found', successMessage = 'Style guide generation completed successfully'; after(function(done) { @@ -57,7 +55,7 @@ describe('Command Line Interface', function() { describe('given --source option', function() { it('should read from source directory', function(done) { - var source = helperUtils.fixtures('with-include'); + let source = helperUtils.fixtures('with-include'); kssNode('--verbose --source ' + source + ' --destination test/output/nested', function(error, stdout) { expect(error).to.not.exist; @@ -69,7 +67,7 @@ describe('Command Line Interface', function() { }); it('should not declare success if source directory is empty', function(done) { - var source = helperUtils.fixtures('empty-source'); + let source = helperUtils.fixtures('empty-source'); kssNode('--verbose --source ' + source + ' --destination test/output/nested', function(error, stdout, stderr) { expect(error).to.exist; @@ -93,7 +91,7 @@ describe('Command Line Interface', function() { }); it('should read multiple source directories', function(done) { - var source = helperUtils.fixtures('with-include'), + let source = helperUtils.fixtures('with-include'), source2 = helperUtils.fixtures('empty-source'); kssNode('--verbose --source ' + source + ' --source ' + source2 + ' --destination test/output/nested', function(error, stdout) { @@ -108,7 +106,7 @@ describe('Command Line Interface', function() { describe('given --destination option', function() { it('should read destination directory', function(done) { - var source = helperUtils.fixtures('with-include'), + let source = helperUtils.fixtures('with-include'), destination = helperUtils.fixtures('../output/nested'); kssNode('--verbose ' + source + ' --destination ' + destination, function(error, stdout) { @@ -122,7 +120,7 @@ describe('Command Line Interface', function() { describe('given unnamed option', function() { it('should use the first unnamed as the source directory', function(done) { - var source = helperUtils.fixtures('with-include'), + let source = helperUtils.fixtures('with-include'), destination = helperUtils.fixtures('../output/nested'); kssNode('--verbose ' + source + ' --destination ' + destination, function(error, stdout) { @@ -135,7 +133,7 @@ describe('Command Line Interface', function() { }); it('should use the second unnamed as the destination directory', function(done) { - var source = helperUtils.fixtures('with-include'), + let source = helperUtils.fixtures('with-include'), destination = helperUtils.fixtures('../output/nested'); kssNode('--verbose ' + source + ' ' + destination, function(error, stdout) { @@ -193,7 +191,7 @@ describe('Command Line Interface', function() { it('should use a default path', function(done) { // This test is long. this.timeout(4000); - var defaultPath = path.resolve('custom-template'); + let defaultPath = path.resolve('custom-template'); kssNode('--clone', function(error, stdout, stderr) { expect(error).to.not.exist; @@ -208,7 +206,7 @@ describe('Command Line Interface', function() { }); it('should error if the destination folder exists', function(done) { - var existingFolder = path.resolve('test/fixtures/template'); + let existingFolder = path.resolve('test/fixtures/template'); kssNode('--clone ' + existingFolder, function(error) { expect(error).to.exist; diff --git a/test/test_cli_handlebars.js b/test/test_cli_handlebars.js index c4cbc527..e73875b2 100644 --- a/test/test_cli_handlebars.js +++ b/test/test_cli_handlebars.js @@ -2,24 +2,37 @@ 'use strict'; -var cli = require('../lib/cli'), +const cli = require('../lib/cli'), fs = require('fs'), mockStream = require('mock-utf8-stream'), path = require('path'); describe('Handlebars template', function() { before(function(done) { - var self = this, - files, - fileReader, - fileCounter, + let self = this, stdout = new mockStream.MockWritableStream(), stderr = new mockStream.MockWritableStream(); - self.files = {}; stdout.startCapture(); stderr.startCapture(); + // Create a closure with the file name stored. + let fileCounter; + self.files = {}; + let fileReader = function(fileName) { + return function(error, data) { + if (error) { + throw error; + } + + self.files[fileName] = data; + fileCounter -= 1; + if (!fileCounter) { + done(); + } + }; + }; + cli({ stdout: stdout, stderr: stderr, @@ -27,31 +40,16 @@ describe('Handlebars template', function() { }, function(error) { expect(error).to.not.exist; self.stdout = stdout.capturedData; - files = [ + let files = [ 'index', 'section-2', 'section-3' ]; fileCounter = files.length; - files.map(function(file) { + files.forEach(function(file) { fs.readFile(path.join(__dirname, 'output/nested', file + '.html'), 'utf8', fileReader(file)); }); }); - - // Create a closure with the file name stored. - fileReader = function(fileName) { - return function(error, data) { - if (error) { - throw error; - } - - self.files[fileName] = data; - fileCounter -= 1; - if (!fileCounter) { - done(); - } - }; - }; }); describe('given --helpers option', function() { diff --git a/test/test_kss.js b/test/test_kss.js index 0bc430ae..b2593d84 100644 --- a/test/test_kss.js +++ b/test/test_kss.js @@ -26,9 +26,8 @@ describe('kss object API', function() { ].forEach(function(method) { it('has ' + method + '() constructor', function(done) { expect(kss).to.itself.respondTo(method); - var Constructor = require('../lib/kss_' + method.replace('Kss', '').toLowerCase()); - var obj = new kss[method](); - expect(obj).to.be.an.instanceof(Constructor); + let Constructor = require('../lib/kss_' + method.replace('Kss', '').toLowerCase()); + expect(new kss[method]()).to.be.an.instanceof(Constructor); done(); }); }); diff --git a/test/test_kss_config.js b/test/test_kss_config.js index 45ee297d..c3b1057c 100644 --- a/test/test_kss_config.js +++ b/test/test_kss_config.js @@ -2,8 +2,9 @@ 'use strict'; -var KssGenerator = require('../generator/kss_generator'); -var pathToJSON = helperUtils.fixtures('cli-option-config.json'); +const KssGenerator = require('../generator/kss_generator'); + +let pathToJSON = helperUtils.fixtures('cli-option-config.json'); describe('KssConfig object API', function() { /* eslint-disable guard-for-in,no-loop-func */ @@ -23,7 +24,7 @@ describe('KssConfig object API', function() { describe('KssConfig constructor', function() { it('should initialize the data', function(done) { - var kssConfig = new kss.KssConfig(); + let kssConfig = new kss.KssConfig(); expect(kssConfig).to.have.property('config'); expect(kssConfig).to.have.property('options'); expect(kssConfig.options).to.have.property('css'); @@ -33,17 +34,9 @@ describe('KssConfig object API', function() { done(); }); - it('should return a KssConfig object when called normally', function(done) { - /* eslint-disable new-cap */ - var kssConfig = kss.KssConfig(); - expect(kssConfig).to.be.an.instanceof(kss.KssConfig); - done(); - /* eslint-enable new-cap */ - }); - it('should set config when given an object', function(done) { - var opts = require(pathToJSON); - var kssConfig = new kss.KssConfig(opts); + let opts = require(pathToJSON); + let kssConfig = new kss.KssConfig(opts); expect(kssConfig.config.source).to.equal('with-include'); done(); }); @@ -51,14 +44,14 @@ describe('KssConfig object API', function() { describe('.set()', function() { it('should set this.config', function(done) { - var kssConfig = new kss.KssConfig(); + let kssConfig = new kss.KssConfig(); kssConfig.set({source: 'isSet'}); expect(kssConfig.config.source).to.equal('isSet'); done(); }); it('should not unset this.config', function(done) { - var kssConfig = new kss.KssConfig(require(pathToJSON)); + let kssConfig = new kss.KssConfig(require(pathToJSON)); kssConfig.set({source: 'isSet'}); expect(kssConfig.config.destination).to.equal('../output/nested'); done(); @@ -67,11 +60,9 @@ describe('KssConfig object API', function() { describe('.get()', function() { it('should return this.config', function(done) { - var key, - config, - kssConfig = new kss.KssConfig(require(pathToJSON)); - config = kssConfig.get(); - for (key in config) { + let kssConfig = new kss.KssConfig(require(pathToJSON)); + let config = kssConfig.get(); + for (let key in config) { if (config.hasOwnProperty(key)) { expect(config[key]).to.equal(kssConfig.config[key]); } @@ -80,9 +71,8 @@ describe('KssConfig object API', function() { }); it('should return this.config.key given key', function(done) { - var key, - kssConfig = new kss.KssConfig(require(pathToJSON)); - for (key in kssConfig.config) { + let kssConfig = new kss.KssConfig(require(pathToJSON)); + for (let key in kssConfig.config) { if (kssConfig.config.hasOwnProperty(key)) { expect(kssConfig.get(key)).to.equal(kssConfig.config[key]); } @@ -93,7 +83,7 @@ describe('KssConfig object API', function() { describe('.addOptions()', function() { it('should add to this.options', function(done) { - var kssConfig = new kss.KssConfig(require(pathToJSON)); + let kssConfig = new kss.KssConfig(require(pathToJSON)); kssConfig.addOptions({ candy: { description: 'I want candy.' @@ -107,7 +97,7 @@ describe('KssConfig object API', function() { describe('.loadJSON()', function() { it('should load config from a JSON file', function(done) { - var kssConfig = new kss.KssConfig(); + let kssConfig = new kss.KssConfig(); kssConfig.loadJSON(pathToJSON); expect(kssConfig.config.source).to.exist; expect(kssConfig.config.source).to.equal('with-include'); @@ -115,14 +105,14 @@ describe('KssConfig object API', function() { }); it('should store the absolute path to the JSON file', function(done) { - var kssConfig = new kss.KssConfig(); + let kssConfig = new kss.KssConfig(); kssConfig.loadJSON('test/fixtures/cli-option-config.json'); expect(kssConfig.config.config).to.equal(helperUtils.fixtures('cli-option-config.json')); done(); }); it('should store keys in the JSON file', function(done) { - var kssConfig = new kss.KssConfig(); + let kssConfig = new kss.KssConfig(); kssConfig.loadJSON(pathToJSON); expect(kssConfig.config.configFileKeys).to.deep.equal(['//', 'source', 'destination', 'template']); done(); @@ -131,7 +121,7 @@ describe('KssConfig object API', function() { describe('.normalize()', function() { it('should normalize a "multiple" option to an array of values', function(done) { - var kssConfig = new kss.KssConfig(); + let kssConfig = new kss.KssConfig(); kssConfig.set({source: 'with-include'}); kssConfig.normalize(); expect(kssConfig.config.source).to.be.an.instanceOf(Array); @@ -147,7 +137,7 @@ describe('KssConfig object API', function() { }); it('should normalize a non-"multiple" option to a single value', function(done) { - var kssConfig = new kss.KssConfig(); + let kssConfig = new kss.KssConfig(); kssConfig.set({template: ['empty-source', 'with-include', 'template']}); kssConfig.normalize(); expect(kssConfig.config.template).to.be.a('string'); @@ -155,7 +145,7 @@ describe('KssConfig object API', function() { }); it('should resolve paths relative to the current working directory', function(done) { - var kssConfig = new kss.KssConfig(require(pathToJSON)); + let kssConfig = new kss.KssConfig(require(pathToJSON)); kssConfig.normalize(); expect(kssConfig.config.source[0]).to.equal(path.resolve('with-include')); done(); @@ -163,9 +153,9 @@ describe('KssConfig object API', function() { it('should resolve paths relative to the given config file', function(done) { // Simulate how yargs outputs its --config option. - var opts = require(pathToJSON); + let opts = require(pathToJSON); opts['config'] = pathToJSON; - var kssConfig = new kss.KssConfig(opts); + let kssConfig = new kss.KssConfig(opts); kssConfig.normalize(); expect(kssConfig.config.source[0]).to.equal(path.resolve(helperUtils.fixtures(), 'with-include')); // The normal way to add JSON config. @@ -177,7 +167,7 @@ describe('KssConfig object API', function() { }); it('should not try to resolve a null path', function(done) { - var kssConfig = new kss.KssConfig(require(pathToJSON)); + let kssConfig = new kss.KssConfig(require(pathToJSON)); kssConfig.set({destination: null}); kssConfig.normalize(); expect(kssConfig.config.destination).to.equal(null); @@ -187,36 +177,31 @@ describe('KssConfig object API', function() { describe('.loadGenerator()', function() { it('should return KssGenerator object', function(done) { - var generator, - kssConfig = new kss.KssConfig(); + let kssConfig = new kss.KssConfig(); kssConfig.set({template: 'generator/handlebars/template'}); - generator = kssConfig.loadGenerator(); + let generator = kssConfig.loadGenerator(); expect(generator).to.be.an.instanceof(KssGenerator); done(); }); it('should return KssGenerator object even if the template does not specify one', function(done) { - var generator, - kssConfig = new kss.KssConfig({template: helperUtils.fixtures('template')}); - generator = kssConfig.loadGenerator(); + let kssConfig = new kss.KssConfig({template: helperUtils.fixtures('template')}); + let generator = kssConfig.loadGenerator(); expect(generator).to.be.an.instanceof(KssGenerator); done(); }); it('should load the generator\'s options', function(done) { - var generator, - kssConfig = new kss.KssConfig({template: 'generator/handlebars/template'}); - generator = kssConfig.loadGenerator(); + let kssConfig = new kss.KssConfig({template: 'generator/handlebars/template'}); + let generator = kssConfig.loadGenerator(); expect(generator).to.be.an.instanceof(KssGenerator); expect(kssConfig.options['placeholder']).to.exist; done(); }); it('should load the template\'s options', function(done) { - var generator, - kssConfig; - kssConfig = new kss.KssConfig({template: 'generator/handlebars/template'}); - generator = kssConfig.loadGenerator(); + let kssConfig = new kss.KssConfig({template: 'generator/handlebars/template'}); + let generator = kssConfig.loadGenerator(); expect(generator).to.be.an.instanceof(KssGenerator); expect(kssConfig.options['nav-depth']).to.exist; done(); diff --git a/test/test_kss_modifier.js b/test/test_kss_modifier.js index e4665d13..7da594fb 100644 --- a/test/test_kss_modifier.js +++ b/test/test_kss_modifier.js @@ -4,7 +4,7 @@ describe('KssModifier object API', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: '*.less|*.css'}, function(styleGuide) { self.styleGuide = styleGuide; done(); @@ -28,7 +28,7 @@ describe('KssModifier object API', function() { describe('KssModifier constructor', function() { it('should initialize the data', function(done) { - var obj = new kss.KssModifier(); + let obj = new kss.KssModifier(); expect(obj).to.have.property('meta'); expect(obj.meta).to.have.property('section'); expect(obj).to.have.property('data'); @@ -37,15 +37,6 @@ describe('KssModifier object API', function() { expect(obj.data).to.have.property('className'); done(); }); - - it('should return a KssModifier object when called normally', function(done) { - /* eslint-disable new-cap */ - var obj = kss.KssModifier({name: '.modifier'}); - expect(obj).to.be.an.instanceof(kss.KssModifier); - expect(obj.name()).to.equal('.modifier'); - done(); - /* eslint-enable new-cap */ - }); }); describe('.section()', function() { @@ -59,7 +50,7 @@ describe('KssModifier object API', function() { }); it('should set meta.section if given a value', function(done) { - var section = new kss.KssSection({header: 'Section'}), + let section = new kss.KssSection({header: 'Section'}), modifier = new kss.KssModifier({name: 'original'}); modifier.section(section); expect(modifier.meta.section).to.deep.equal(section); @@ -68,7 +59,7 @@ describe('KssModifier object API', function() { }); it('should return itself if given a value', function(done) { - var section = new kss.KssSection({header: 'Section'}), + let section = new kss.KssSection({header: 'Section'}), modifier = new kss.KssModifier({name: 'original'}); expect(modifier.section(section)).to.deep.equal(modifier); done(); @@ -86,7 +77,7 @@ describe('KssModifier object API', function() { }); it('should set data.name if given a value', function(done) { - var modifier = new kss.KssModifier({name: 'original'}); + let modifier = new kss.KssModifier({name: 'original'}); modifier.name('new'); expect(modifier.data.name).to.equal('new'); expect(modifier.name()).to.equal(modifier.data.name); @@ -94,7 +85,7 @@ describe('KssModifier object API', function() { }); it('should return itself if given a value', function(done) { - var modifier = new kss.KssModifier({name: 'original'}); + let modifier = new kss.KssModifier({name: 'original'}); expect(modifier.name('new')).to.deep.equal(modifier); done(); }); @@ -111,7 +102,7 @@ describe('KssModifier object API', function() { }); it('should set data.description if given a value', function(done) { - var modifier = new kss.KssModifier({description: 'original'}); + let modifier = new kss.KssModifier({description: 'original'}); modifier.description('new'); expect(modifier.data.description).to.equal('new'); expect(modifier.description()).to.equal(modifier.data.description); @@ -119,7 +110,7 @@ describe('KssModifier object API', function() { }); it('should return itself if given a value', function(done) { - var modifier = new kss.KssModifier({description: 'original'}); + let modifier = new kss.KssModifier({description: 'original'}); expect(modifier.description('new')).to.deep.equal(modifier); done(); }); @@ -145,7 +136,7 @@ describe('KssModifier object API', function() { }); it('should set data.className if given a value', function(done) { - var modifier = new kss.KssModifier({name: '.original'}); + let modifier = new kss.KssModifier({name: '.original'}); modifier.className('new'); expect(modifier.data.className).to.equal('new'); expect(modifier.className()).to.equal(modifier.data.className); @@ -153,7 +144,7 @@ describe('KssModifier object API', function() { }); it('should return itself if given a value', function(done) { - var modifier = new kss.KssModifier({name: '.original'}); + let modifier = new kss.KssModifier({name: '.original'}); expect(modifier.className('new')).to.deep.equal(modifier); done(); }); @@ -173,14 +164,14 @@ describe('KssModifier object API', function() { }); it('should return empty string if it does not have any associated markup', function(done) { - var modifier = new kss.KssModifier(); + let modifier = new kss.KssModifier(); modifier.section(new kss.KssSection()); expect(modifier.markup()).to.be.string(''); done(); }); it('should return empty string if it does not have an associated kssSection', function(done) { - var modifier = new kss.KssModifier(); + let modifier = new kss.KssModifier(); expect(modifier.markup()).to.be.string(''); done(); }); @@ -190,10 +181,9 @@ describe('KssModifier object API', function() { it('should return valid JSON object', function(done) { this.styleGuide.data.sections.map(function(section) { section.modifiers().map(function(modifier) { - var str; expect(modifier.toJSON()).to.be.an.instanceOf(Object); // Verify it converts to a JSON string. - str = JSON.stringify(modifier.toJSON()); + let str = JSON.stringify(modifier.toJSON()); expect(str).to.be.string; // Compare JSON string to original. expect(JSON.parse(str)).to.deep.equal(modifier.toJSON()); @@ -205,7 +195,7 @@ describe('KssModifier object API', function() { it('should return data as a JSON object', function(done) { this.styleGuide.data.sections.map(function(section) { section.modifiers().map(function(modifier) { - var json = modifier.toJSON(); + let json = modifier.toJSON(); expect(json.name).to.equal(modifier.data.name); expect(json.description).to.equal(modifier.data.description); expect(json.className).to.equal(modifier.className()); diff --git a/test/test_kss_parameter.js b/test/test_kss_parameter.js index 18b2c95f..10f00ac4 100644 --- a/test/test_kss_parameter.js +++ b/test/test_kss_parameter.js @@ -4,7 +4,7 @@ describe('KssParameter object API', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: '*.less|*.css'}, function(styleGuide) { self.styleGuide = styleGuide; done(); @@ -26,7 +26,7 @@ describe('KssParameter object API', function() { describe('KssParameter constructor', function() { it('should initialize the data', function(done) { - var obj = new kss.KssParameter(); + let obj = new kss.KssParameter(); expect(obj).to.have.property('meta'); expect(obj.meta).to.have.property('section'); expect(obj).to.have.property('data'); @@ -34,15 +34,6 @@ describe('KssParameter object API', function() { expect(obj.data).to.have.property('description'); done(); }); - - it('should return a KssParameter object when called normally', function(done) { - /* eslint-disable new-cap */ - var obj = kss.KssParameter({name: '$variable'}); - expect(obj).to.be.an.instanceof(kss.KssParameter); - expect(obj.name()).to.equal('$variable'); - done(); - /* eslint-enable new-cap */ - }); }); describe('.section()', function() { @@ -56,7 +47,7 @@ describe('KssParameter object API', function() { }); it('should set meta.section if given a value', function(done) { - var section = new kss.KssSection({header: 'Section'}), + let section = new kss.KssSection({header: 'Section'}), parameter = new kss.KssParameter({name: 'original'}); parameter.section(section); expect(parameter.meta.section).to.deep.equal(section); @@ -65,7 +56,7 @@ describe('KssParameter object API', function() { }); it('should return itself if given a value', function(done) { - var section = new kss.KssSection({header: 'Section'}), + let section = new kss.KssSection({header: 'Section'}), parameter = new kss.KssParameter({name: 'original'}); expect(parameter.section(section)).to.deep.equal(parameter); done(); @@ -83,7 +74,7 @@ describe('KssParameter object API', function() { }); it('should set data.name if given a value', function(done) { - var parameter = new kss.KssParameter({name: 'original'}); + let parameter = new kss.KssParameter({name: 'original'}); parameter.name('new'); expect(parameter.data.name).to.equal('new'); expect(parameter.name()).to.equal(parameter.data.name); @@ -91,7 +82,7 @@ describe('KssParameter object API', function() { }); it('should return itself if given a value', function(done) { - var parameter = new kss.KssParameter({name: 'original'}); + let parameter = new kss.KssParameter({name: 'original'}); expect(parameter.name('new')).to.deep.equal(parameter); done(); }); @@ -108,7 +99,7 @@ describe('KssParameter object API', function() { }); it('should set data.description if given a value', function(done) { - var parameter = new kss.KssParameter({description: 'original'}); + let parameter = new kss.KssParameter({description: 'original'}); parameter.description('new'); expect(parameter.data.description).to.equal('new'); expect(parameter.description()).to.equal(parameter.data.description); @@ -116,7 +107,7 @@ describe('KssParameter object API', function() { }); it('should return itself if given a value', function(done) { - var parameter = new kss.KssParameter({description: 'original'}); + let parameter = new kss.KssParameter({description: 'original'}); expect(parameter.description('new')).to.deep.equal(parameter); done(); }); @@ -126,10 +117,9 @@ describe('KssParameter object API', function() { it('should return valid JSON object', function(done) { this.styleGuide.data.sections.map(function(section) { section.parameters().map(function(parameter) { - var str; expect(parameter.toJSON()).to.be.an.instanceOf(Object); // Verify it converts to a JSON string. - str = JSON.stringify(parameter.toJSON()); + let str = JSON.stringify(parameter.toJSON()); expect(str).to.be.string; // Compare JSON string to original. expect(JSON.parse(str)).to.deep.equal(parameter.toJSON()); @@ -141,7 +131,7 @@ describe('KssParameter object API', function() { it('should return data as a JSON object', function(done) { this.styleGuide.data.sections.map(function(section) { section.parameters().map(function(parameter) { - var json = parameter.toJSON(); + let json = parameter.toJSON(); expect(json.name).to.equal(parameter.data.name); expect(json.description).to.equal(parameter.data.description); }); diff --git a/test/test_kss_section.js b/test/test_kss_section.js index 8fe41ef0..4a117c80 100644 --- a/test/test_kss_section.js +++ b/test/test_kss_section.js @@ -2,11 +2,11 @@ 'use strict'; -var custom = ['custom', 'custom2', 'custom3']; +let custom = ['custom', 'custom2', 'custom3']; describe('KssSection object API', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: '*.less|*.css', custom: custom}, function(styleGuide) { self.styleGuide = styleGuide; done(); @@ -38,7 +38,7 @@ describe('KssSection object API', function() { describe('KssSection constructor', function() { it('should initialize the data', function(done) { - var obj = new kss.KssSection(); + let obj = new kss.KssSection(); expect(obj).to.have.property('meta'); expect(obj.meta).to.have.property('styleGuide'); expect(obj.meta).to.have.property('raw'); @@ -59,17 +59,8 @@ describe('KssSection object API', function() { done(); }); - it('should return a KssSection object when called normally', function(done) { - /* eslint-disable new-cap */ - var obj = kss.KssSection({header: 'Section'}); - expect(obj).to.be.an.instanceof(kss.KssSection); - expect(obj.header()).to.equal('Section'); - done(); - /* eslint-enable new-cap */ - }); - it('should set itself as parent of modifier and parameter objects', function(done) { - var section, + let section, modifier = new kss.KssModifier({name: 'modifier'}), parameter = new kss.KssParameter({name: '$parameter'}); section = new kss.KssSection({ @@ -88,10 +79,9 @@ describe('KssSection object API', function() { describe('.toJSON()', function() { it('should return valid JSON object', function(done) { this.styleGuide.sections().map(function(section) { - var str; expect(section.toJSON()).to.be.an.instanceOf(Object); // Verify it converts to a JSON string. - str = JSON.stringify(section.toJSON()); + let str = JSON.stringify(section.toJSON()); expect(str).to.be.string; // Compare JSON string to original. expect(JSON.parse(str)).to.deep.equal(section.toJSON()); @@ -101,15 +91,14 @@ describe('KssSection object API', function() { it('should output the same data given to constructor', function(done) { // Note: no custom properties, please. (for testing code coverage.) - var data, property, section; - data = { + let data = { header: 'example', description: 'lorem ipsum', reference: '1.1', markup: '
lorem ipsum
' }; - section = new kss.KssSection(data); - for (property in data) { + let section = new kss.KssSection(data); + for (let property in data) { if (data.hasOwnProperty(property)) { expect(section.toJSON()[property]).to.equal(data[property]); } @@ -119,7 +108,7 @@ describe('KssSection object API', function() { it('should return custom properties', function(done) { this.styleGuide.sections().map(function(section) { - var json = section.toJSON(); + let json = section.toJSON(); custom.map(function(name) { if (typeof section.custom(name) !== 'undefined') { expect(json).to.have.property(name); @@ -133,7 +122,7 @@ describe('KssSection object API', function() { describe('.styleGuide()', function() { it('should return meta.styleGuide', function(done) { - var self = this; + let self = this; this.styleGuide.sections().map(function(section) { expect(section.styleGuide()).to.deep.equal(section.meta.styleGuide).and.deep.equal(self.styleGuide); }); @@ -141,7 +130,7 @@ describe('KssSection object API', function() { }); it('should set meta.styleGuide if given a value', function(done) { - var styleGuide = new kss.KssStyleGuide(), + let styleGuide = new kss.KssStyleGuide(), section = new kss.KssSection({header: 'Section'}); section.styleGuide(styleGuide); expect(section.meta.styleGuide).to.deep.equal(styleGuide); @@ -150,7 +139,7 @@ describe('KssSection object API', function() { }); it('should return itself if given a value', function(done) { - var styleGuide = new kss.KssStyleGuide(), + let styleGuide = new kss.KssStyleGuide(), section = new kss.KssSection({header: 'Section'}); expect(section.styleGuide(styleGuide)).to.deep.equal(section); done(); @@ -166,7 +155,7 @@ describe('KssSection object API', function() { }); it('should set data.header if given a value', function(done) { - var section = new kss.KssSection({header: 'original'}); + let section = new kss.KssSection({header: 'original'}); section.header('new'); expect(section.data.header).to.equal('new'); expect(section.header()).to.equal(section.data.header); @@ -174,7 +163,7 @@ describe('KssSection object API', function() { }); it('should return itself if given a value', function(done) { - var section = new kss.KssSection({header: 'original'}); + let section = new kss.KssSection({header: 'original'}); expect(section.header('new')).to.deep.equal(section); done(); }); @@ -189,7 +178,7 @@ describe('KssSection object API', function() { }); it('should set data.description if given a value', function(done) { - var section = new kss.KssSection({description: 'original'}); + let section = new kss.KssSection({description: 'original'}); section.description('new'); expect(section.data.description).to.equal('new'); expect(section.description()).to.equal(section.data.description); @@ -197,7 +186,7 @@ describe('KssSection object API', function() { }); it('should return itself if given a value', function(done) { - var section = new kss.KssSection({description: 'original'}); + let section = new kss.KssSection({description: 'original'}); expect(section.description('new')).to.deep.equal(section); done(); }); @@ -223,7 +212,7 @@ describe('KssSection object API', function() { }); it('should set data[name] and update meta.customPropertyNames[] if given a value', function(done) { - var section = new kss.KssSection({originalCustom: 'original'}); + let section = new kss.KssSection({originalCustom: 'original'}); section.custom('newCustom', 'new'); expect(section.data.newCustom).to.equal('new'); expect(section.customPropertyNames()).to.deep.equal(['originalCustom', 'newCustom']); @@ -231,7 +220,7 @@ describe('KssSection object API', function() { }); it('should set update the style guide\'s meta.customPropertyNames[] if given a value', function(done) { - var styleGuide = new kss.KssStyleGuide(), + let styleGuide = new kss.KssStyleGuide(), section = new kss.KssSection(); section.styleGuide(styleGuide); section.custom('newCustom', 'new'); @@ -240,7 +229,7 @@ describe('KssSection object API', function() { }); it('should return itself if given a value', function(done) { - var section = new kss.KssSection({newCustom: 'original'}); + let section = new kss.KssSection({newCustom: 'original'}); expect(section.custom('newCustom', 'new')).to.deep.equal(section); done(); }); @@ -255,7 +244,7 @@ describe('KssSection object API', function() { }); it('should set data.deprecated if given a value', function(done) { - var section = new kss.KssSection({deprecated: false}); + let section = new kss.KssSection({deprecated: false}); expect(section.data.deprecated).to.equal(false); section.deprecated(true); expect(section.data.deprecated).to.equal(true); @@ -264,13 +253,13 @@ describe('KssSection object API', function() { }); it('should return itself if given true', function(done) { - var section = new kss.KssSection({deprecated: false}); + let section = new kss.KssSection({deprecated: false}); expect(section.deprecated(true)).to.deep.equal(section); done(); }); it('should return itself if given false', function(done) { - var section = new kss.KssSection({deprecated: true}); + let section = new kss.KssSection({deprecated: true}); expect(section.deprecated(false)).to.deep.equal(section); done(); }); @@ -285,7 +274,7 @@ describe('KssSection object API', function() { }); it('should set data.experimental if given a value', function(done) { - var section = new kss.KssSection({experimental: false}); + let section = new kss.KssSection({experimental: false}); expect(section.data.experimental).to.equal(false); section.experimental(true); expect(section.data.experimental).to.equal(true); @@ -294,13 +283,13 @@ describe('KssSection object API', function() { }); it('should return itself if given true', function(done) { - var section = new kss.KssSection({experimental: false}); + let section = new kss.KssSection({experimental: false}); expect(section.experimental(true)).to.deep.equal(section); done(); }); it('should return itself if given false', function(done) { - var section = new kss.KssSection({experimental: true}); + let section = new kss.KssSection({experimental: true}); expect(section.experimental(false)).to.deep.equal(section); done(); }); @@ -315,7 +304,7 @@ describe('KssSection object API', function() { }); it('should set data.reference if given a value', function(done) { - var section = new kss.KssSection({reference: 'original'}); + let section = new kss.KssSection({reference: 'original'}); section.reference('new'); expect(section.data.reference).to.equal('new'); expect(section.reference()).to.equal(section.data.reference); @@ -323,7 +312,7 @@ describe('KssSection object API', function() { }); it('should return itself if given a value', function(done) { - var section = new kss.KssSection({reference: 'original'}); + let section = new kss.KssSection({reference: 'original'}); expect(section.reference('new')).to.deep.equal(section); done(); }); @@ -344,12 +333,12 @@ describe('KssSection object API', function() { }); it('should replace all runs of non-word characters with a hyphen', function() { - var section = new kss.KssSection({reference: 'test - section - with.multiple.runs..of--non-word.characters'}); + let section = new kss.KssSection({reference: 'test - section - with.multiple.runs..of--non-word.characters'}); expect(section.referenceURI()).to.equal('test-section-with-multiple-runs-of--non-word-characters'); }); it('should set data.referenceURI if given a value', function(done) { - var section = new kss.KssSection({reference: 'original.ref'}); + let section = new kss.KssSection({reference: 'original.ref'}); section.referenceURI('newRef'); expect(section.data.referenceURI).to.equal('newRef'); expect(section.referenceURI()).to.equal(section.data.referenceURI); @@ -357,7 +346,7 @@ describe('KssSection object API', function() { }); it('should return itself if given a value', function(done) { - var section = new kss.KssSection({reference: 'original.ref'}); + let section = new kss.KssSection({reference: 'original.ref'}); expect(section.referenceURI('newRef')).to.deep.equal(section); done(); }); @@ -373,7 +362,7 @@ describe('KssSection object API', function() { }); it('should set data.weight if given a value', function(done) { - var section = new kss.KssSection({weight: 2}); + let section = new kss.KssSection({weight: 2}); section.weight(3); expect(section.data.weight).to.equal(3); expect(section.weight()).to.equal(section.data.weight); @@ -381,7 +370,7 @@ describe('KssSection object API', function() { }); it('should return itself if given a value', function(done) { - var section = new kss.KssSection({weight: 2}); + let section = new kss.KssSection({weight: 2}); expect(section.weight(3)).to.deep.equal(section); done(); }); @@ -398,7 +387,7 @@ describe('KssSection object API', function() { }); it('should set meta.depth if given a value', function(done) { - var section = new kss.KssSection({depth: 2}); + let section = new kss.KssSection({depth: 2}); section.depth(3); expect(section.meta.depth).to.equal(3); expect(section.depth()).to.equal(section.meta.depth); @@ -406,7 +395,7 @@ describe('KssSection object API', function() { }); it('should return itself if given a value', function(done) { - var section = new kss.KssSection({depth: 2}); + let section = new kss.KssSection({depth: 2}); expect(section.depth(3)).to.deep.equal(section); done(); }); @@ -421,7 +410,7 @@ describe('KssSection object API', function() { }); it('should set data.markup if given a value', function(done) { - var section = new kss.KssSection({markup: 'original'}); + let section = new kss.KssSection({markup: 'original'}); section.markup('new'); expect(section.data.markup).to.equal('new'); expect(section.markup()).to.equal(section.data.markup); @@ -429,7 +418,7 @@ describe('KssSection object API', function() { }); it('should return itself if given a value', function(done) { - var section = new kss.KssSection({markup: 'original'}); + let section = new kss.KssSection({markup: 'original'}); expect(section.markup('new')).to.deep.equal(section); done(); }); @@ -454,7 +443,7 @@ describe('KssSection object API', function() { it('should return data.modifiers[n] given an integer as number or string', function(done) { this.styleGuide.sections().map(function(section) { - var i = 0; + let i = 0; section.data.modifiers.map(function(modifier) { expect(section.modifiers(i)).to.deep.equal(modifier); expect(section.modifiers(i.toString())).to.deep.equal(modifier); @@ -473,14 +462,12 @@ describe('KssSection object API', function() { it('should search by name when given a string', function(done) { this.styleGuide.sections().map(function(section) { - var i, j, queries = ['.red', '.yellow', ':hover', ':disabled'], - q = queries.length, - l = section.data.modifiers.length; + let queries = ['.red', '.yellow', ':hover', ':disabled']; // Loop through each modifier. - for (i = 0; i < l; i += 1) { + for (let i = 0; i < section.data.modifiers.length; i += 1) { // If a modifier is equal to a query, run the search. - for (j = 0; j < q; j += 1) { + for (let j = 0; j < queries.length; j += 1) { if (section.data.modifiers[i].data.name === queries[j]) { expect(section.modifiers(queries[j])).to.deep.equal(section.data.modifiers[i]); } @@ -498,7 +485,7 @@ describe('KssSection object API', function() { }); it('should add to data.modifiers if given a value', function(done) { - var section = new kss.KssSection({header: 'original'}), + let section = new kss.KssSection({header: 'original'}), modifier = new kss.KssModifier({name: '.modifier'}); section.modifiers(modifier); expect(section.data.modifiers[0]).to.deep.equal(modifier); @@ -507,7 +494,7 @@ describe('KssSection object API', function() { }); it('should add to data.modifiers if given an array of values', function(done) { - var section = new kss.KssSection({header: 'original'}), + let section = new kss.KssSection({header: 'original'}), modifier = new kss.KssModifier({name: '.modifier'}), modifier2 = new kss.KssModifier({name: '.modifier'}); section.modifiers([modifier, modifier2]); @@ -518,7 +505,7 @@ describe('KssSection object API', function() { }); it('should return itself if given a value', function(done) { - var section = new kss.KssSection({header: 'original'}), + let section = new kss.KssSection({header: 'original'}), modifier = new kss.KssModifier(); expect(section.modifiers(modifier)).to.deep.equal(section); done(); @@ -543,7 +530,7 @@ describe('KssSection object API', function() { }); it('should add to data.parameters if given a value', function(done) { - var section = new kss.KssSection({header: 'original'}), + let section = new kss.KssSection({header: 'original'}), parameter = new kss.KssParameter({name: '$var'}); section.parameters(parameter); expect(section.data.parameters[0]).to.deep.equal(parameter); @@ -552,7 +539,7 @@ describe('KssSection object API', function() { }); it('should add to data.parameters if given an array of values', function(done) { - var section = new kss.KssSection({header: 'original'}), + let section = new kss.KssSection({header: 'original'}), parameter = new kss.KssParameter({name: '$var1'}), parameter2 = new kss.KssParameter({name: '$var2'}); section.parameters([parameter, parameter2]); @@ -563,7 +550,7 @@ describe('KssSection object API', function() { }); it('should return itself if given a value', function(done) { - var section = new kss.KssSection({header: 'original'}), + let section = new kss.KssSection({header: 'original'}), parameter = new kss.KssModifier(); expect(section.parameters(parameter)).to.deep.equal(section); done(); diff --git a/test/test_kss_styleguide.js b/test/test_kss_styleguide.js index c441cfa4..aae0fb85 100644 --- a/test/test_kss_styleguide.js +++ b/test/test_kss_styleguide.js @@ -4,7 +4,7 @@ describe('KssStyleGuide object API', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: /(sections\-queries|sections\-order|property\-styleguide\-word\-keys)\.less/}, function(styleGuide) { self.styleGuide = styleGuide; helperUtils.traverseFixtures({mask: /.*\-word\-phrases\.less/}, function(styleGuide) { @@ -34,7 +34,7 @@ describe('KssStyleGuide object API', function() { describe('KssStyleGuide constructor', function() { it('should initialize the data', function(done) { - var obj = new kss.KssStyleGuide(); + let obj = new kss.KssStyleGuide(); expect(obj).to.have.property('meta'); expect(obj.meta).to.have.property('autoInit'); expect(obj.meta).to.have.property('files'); @@ -50,22 +50,13 @@ describe('KssStyleGuide object API', function() { expect(obj.data).to.have.property('sections'); done(); }); - - it('should return a KssStyleGuide object when called normally', function(done) { - /* eslint-disable new-cap */ - var obj = kss.KssStyleGuide(); - expect(obj).to.be.an.instanceof(kss.KssStyleGuide); - done(); - /* eslint-enable new-cap */ - }); }); describe('.toJSON()', function() { it('should return valid JSON object', function(done) { - var str; expect(this.styleGuide.toJSON()).to.be.an.instanceOf(Object); // Verify it converts to a JSON string. - str = JSON.stringify(this.styleGuide.toJSON()); + let str = JSON.stringify(this.styleGuide.toJSON()); expect(str).to.be.string; // Compare JSON string to original. expect(JSON.parse(str)).to.deep.equal(this.styleGuide.toJSON()); @@ -73,8 +64,7 @@ describe('KssStyleGuide object API', function() { }); it('should output the same data given to constructor', function(done) { - var data, styleGuide; - data = { + let data = { customPropertyNames: ['custom1', 'custom2'], hasNumericReferences: true, referenceDelimiter: '.', @@ -95,7 +85,7 @@ describe('KssStyleGuide object API', function() { } ] }; - styleGuide = new kss.KssStyleGuide(data); + let styleGuide = new kss.KssStyleGuide(data); expect(styleGuide.toJSON()).to.deep.equal(data); done(); }); @@ -103,21 +93,21 @@ describe('KssStyleGuide object API', function() { describe('.autoInit()', function() { it('should update meta.autoInit if given true', function(done) { - var styleGuide = new kss.KssStyleGuide({autoInit: false}); + let styleGuide = new kss.KssStyleGuide({autoInit: false}); styleGuide.autoInit(true); expect(styleGuide.meta.autoInit).to.be.true; done(); }); it('should update meta.autoInit if given false', function(done) { - var styleGuide = new kss.KssStyleGuide(); + let styleGuide = new kss.KssStyleGuide(); styleGuide.autoInit(false); expect(styleGuide.meta.autoInit).to.be.false; done(); }); it('should return itself', function(done) { - var styleGuide = new kss.KssStyleGuide({autoInit: false}); + let styleGuide = new kss.KssStyleGuide({autoInit: false}); expect(styleGuide.autoInit(true)).to.deep.equal(styleGuide); done(); }); @@ -134,21 +124,21 @@ describe('KssStyleGuide object API', function() { }); it('should update data.customPropertyNames if given a string', function(done) { - var styleGuide = new kss.KssStyleGuide({customPropertyNames: ['original']}); + let styleGuide = new kss.KssStyleGuide({customPropertyNames: ['original']}); styleGuide.customPropertyNames('new'); expect(styleGuide.data.customPropertyNames).to.deep.equal(['original', 'new']); done(); }); it('should update data.customPropertyNames if given an array', function(done) { - var styleGuide = new kss.KssStyleGuide({customPropertyNames: ['original']}); + let styleGuide = new kss.KssStyleGuide({customPropertyNames: ['original']}); styleGuide.customPropertyNames(['new', 'new2']); expect(styleGuide.data.customPropertyNames).to.deep.equal(['original', 'new', 'new2']); done(); }); it('should return itself if given a value', function(done) { - var styleGuide = new kss.KssStyleGuide({customPropertyNames: ['original']}); + let styleGuide = new kss.KssStyleGuide({customPropertyNames: ['original']}); expect(styleGuide.customPropertyNames('new')).to.deep.equal(styleGuide); done(); }); @@ -170,7 +160,7 @@ describe('KssStyleGuide object API', function() { context('given no arguments', function() { it('should return all referenced sections', function(done) { - var results = [], + let results = [], expected = [ '4', '4.1', '4.1.1', '4.1.1.1', '4.1.1.2', @@ -190,7 +180,7 @@ describe('KssStyleGuide object API', function() { context('given exact references', function() { it('should find a reference with depth 1', function(done) { - var section = this.styleGuide.sections('4'); + let section = this.styleGuide.sections('4'); expect(section.header()).to.equal('DEPTH OF 1'); expect(section.depth()).to.equal(1); expect(section.reference()).to.equal('4'); @@ -198,7 +188,7 @@ describe('KssStyleGuide object API', function() { }); it('should find a reference with depth 3 and no modifiers', function(done) { - var section = this.styleGuide.sections('4.1.1'); + let section = this.styleGuide.sections('4.1.1'); expect(section.header()).to.equal('DEPTH OF 3, NO MODIFIERS'); expect(section.reference()).to.equal('4.1.1'); expect(section.depth()).to.equal(3); @@ -206,7 +196,7 @@ describe('KssStyleGuide object API', function() { }); it('should find a reference with depth 3 and modifiers', function(done) { - var section = this.styleGuide.sections('4.1.2'); + let section = this.styleGuide.sections('4.1.2'); expect(section.header()).to.equal('DEPTH OF 3, MODIFIERS'); expect(section.depth()).to.equal(3); expect(section.reference()).to.equal('4.1.2'); @@ -219,7 +209,7 @@ describe('KssStyleGuide object API', function() { }); it('should find a reference with depth 4 (A)', function(done) { - var section = this.styleGuide.sections('4.1.1.1'); + let section = this.styleGuide.sections('4.1.1.1'); expect(section.header()).to.equal('DEPTH OF 4 (A)'); expect(section.depth()).to.equal(4); expect(section.reference()).to.equal('4.1.1.1'); @@ -227,7 +217,7 @@ describe('KssStyleGuide object API', function() { }); it('should find a reference with depth 4 (B)', function(done) { - var section = this.styleGuide.sections('4.1.1.2'); + let section = this.styleGuide.sections('4.1.1.2'); expect(section.header()).to.equal('DEPTH OF 4 (B)'); expect(section.depth()).to.equal(4); expect(section.reference()).to.equal('4.1.1.2'); @@ -235,7 +225,7 @@ describe('KssStyleGuide object API', function() { }); it('should find a reference with depth 4 (C)', function(done) { - var section = this.styleGuide.sections('4.1.2.2'); + let section = this.styleGuide.sections('4.1.2.2'); expect(section.header()).to.equal('DEPTH OF 4 (C)'); expect(section.depth()).to.equal(4); expect(section.reference()).to.equal('4.1.2.2'); @@ -245,7 +235,7 @@ describe('KssStyleGuide object API', function() { context('given string queries', function() { it('should return 1 level of descendants when given "4.x"', function(done) { - var sections = this.styleGuide.sections('4.x'); + let sections = this.styleGuide.sections('4.x'); sections.map(function(section) { expect(section.reference()).to.equal('4.1'); expect(section.header()).to.equal('DEPTH OF 2'); @@ -255,9 +245,8 @@ describe('KssStyleGuide object API', function() { }); it('should return 1 level of descendants when given "4.1.x"', function(done) { - var results, - expected = ['4.1.1', '4.1.2']; - results = this.styleGuide.sections('4.1.x').map(function(section) { + let expected = ['4.1.1', '4.1.2']; + let results = this.styleGuide.sections('4.1.x').map(function(section) { return section.reference(); }); expect(results).to.deep.equal(expected); @@ -265,9 +254,8 @@ describe('KssStyleGuide object API', function() { }); it('should return 2 levels of descendants when given "4.x.x"', function(done) { - var results, - expected = ['4.1', '4.1.1', '4.1.2']; - results = this.styleGuide.sections('4.x.x').map(function(section) { + let expected = ['4.1', '4.1.1', '4.1.2']; + let results = this.styleGuide.sections('4.x.x').map(function(section) { return section.reference(); }); expect(results).to.deep.equal(expected); @@ -275,7 +263,7 @@ describe('KssStyleGuide object API', function() { }); it('should return "4.1" and all levels of descendants when given "4.1.*"', function(done) { - var results, + let results, expected = ['4.1', '4.1.1', '4.1.1.1', '4.1.1.2', '4.1.2', '4.1.2.2']; results = this.styleGuide.sections('4.1.*').map(function(section) { return section.reference(); @@ -297,9 +285,8 @@ describe('KssStyleGuide object API', function() { }); it('should return numeric sections in order', function(done) { - var results, - expected = ['9.1', '9.2', '9.3', '9.4', '9.5', '9.10', '9.11', '9.100']; - results = this.styleGuide.sections('9.x').map(function(section) { + let expected = ['9.1', '9.2', '9.3', '9.4', '9.5', '9.10', '9.11', '9.100']; + let results = this.styleGuide.sections('9.x').map(function(section) { return section.reference(); }); expect(results).to.deep.equal(expected); @@ -307,9 +294,8 @@ describe('KssStyleGuide object API', function() { }); it('should return "word key" sections in order', function(done) { - var results, - expected = ['alpha.alpha', 'alpha.beta', 'alpha.delta', 'alpha.epsilon', 'alpha.gamma']; - results = this.styleGuide.sections('alpha.x').map(function(section) { + let expected = ['alpha.alpha', 'alpha.beta', 'alpha.delta', 'alpha.epsilon', 'alpha.gamma']; + let results = this.styleGuide.sections('alpha.x').map(function(section) { return section.reference(); }); expect(results).to.deep.equal(expected); @@ -317,7 +303,7 @@ describe('KssStyleGuide object API', function() { }); it('should return "word key" sections with dashes in the name', function(done) { - var sections = this.styleGuide.sections('alpha-bet.*'); + let sections = this.styleGuide.sections('alpha-bet.*'); sections.map(function(section) { expect(section.reference()).to.equal('alpha-bet'); }); @@ -326,9 +312,8 @@ describe('KssStyleGuide object API', function() { }); it('should return "word phrase" sections in order', function(done) { - var results, - expected = ['beta - alpha', 'beta - beta', 'beta - delta', 'beta - epsilon', 'beta - gamma']; - results = this.styleGuideWordPhrases.sections('beta.x').map(function(section) { + let expected = ['beta - alpha', 'beta - beta', 'beta - delta', 'beta - epsilon', 'beta - gamma']; + let results = this.styleGuideWordPhrases.sections('beta.x').map(function(section) { return section.reference(); }); expect(results).to.deep.equal(expected); @@ -343,9 +328,8 @@ describe('KssStyleGuide object API', function() { }); it('should return "4" and all levels of descendants when given /4.*/', function(done) { - var results, - expected = ['4', '4.1', '4.1.1', '4.1.1.1', '4.1.1.2', '4.1.2', '4.1.2.2']; - results = this.styleGuide.sections(/4.*/).map(function(section) { + let expected = ['4', '4.1', '4.1.1', '4.1.1.1', '4.1.1.2', '4.1.2', '4.1.2.2']; + let results = this.styleGuide.sections(/4.*/).map(function(section) { return section.reference(); }); expect(results).to.deep.equal(expected); @@ -353,7 +337,7 @@ describe('KssStyleGuide object API', function() { }); it('should return "4" when given /4/', function(done) { - var sections = this.styleGuide.sections(/4/); + let sections = this.styleGuide.sections(/4/); sections.map(function(section) { expect(section.reference()).to.equal('4'); }); @@ -362,9 +346,8 @@ describe('KssStyleGuide object API', function() { }); it('should return numeric sections in order', function(done) { - var results, - expected = ['9', '9.1', '9.1.1', '9.2', '9.3', '9.4', '9.5', '9.10', '9.11', '9.100']; - results = this.styleGuide.sections(/9.*/).map(function(section) { + let expected = ['9', '9.1', '9.1.1', '9.2', '9.3', '9.4', '9.5', '9.10', '9.11', '9.100']; + let results = this.styleGuide.sections(/9.*/).map(function(section) { return section.reference(); }); expect(results).to.deep.equal(expected); @@ -372,9 +355,8 @@ describe('KssStyleGuide object API', function() { }); it('should return "word key" sections in order', function(done) { - var results, - expected = ['alpha.alpha', 'alpha.alpha.alpha', 'alpha.beta', 'alpha.delta', 'alpha.epsilon', 'alpha.gamma']; - results = this.styleGuide.sections(/alpha\..*/).map(function(section) { + let expected = ['alpha.alpha', 'alpha.alpha.alpha', 'alpha.beta', 'alpha.delta', 'alpha.epsilon', 'alpha.gamma']; + let results = this.styleGuide.sections(/alpha\..*/).map(function(section) { return section.reference(); }); expect(results).to.deep.equal(expected); @@ -382,9 +364,8 @@ describe('KssStyleGuide object API', function() { }); it('should return "word phrase" sections in order', function(done) { - var results, - expected = ['beta - alpha', 'beta - alpha - alpha', 'beta - beta', 'beta - delta', 'beta - epsilon', 'beta - gamma']; - results = this.styleGuideWordPhrases.sections(/beta - .*/).map(function(section) { + let expected = ['beta - alpha', 'beta - alpha - alpha', 'beta - beta', 'beta - delta', 'beta - epsilon', 'beta - gamma']; + let results = this.styleGuideWordPhrases.sections(/beta - .*/).map(function(section) { return section.reference(); }); expect(results).to.deep.equal(expected); @@ -392,9 +373,8 @@ describe('KssStyleGuide object API', function() { }); it('should return weighted "word phrase" sections in order', function(done) { - var results, - expected = ['gamma - alpha', 'gamma - alpha - delta', 'gamma - alpha - gamma', 'gamma - alpha - beta', 'gamma - alpha - alpha', 'gamma - beta', 'gamma - gamma', 'gamma - delta', 'gamma - epsilon']; - results = this.styleGuideWordPhrases.sections(/gamma - .*/).map(function(section) { + let expected = ['gamma - alpha', 'gamma - alpha - delta', 'gamma - alpha - gamma', 'gamma - alpha - beta', 'gamma - alpha - alpha', 'gamma - beta', 'gamma - gamma', 'gamma - delta', 'gamma - epsilon']; + let results = this.styleGuideWordPhrases.sections(/gamma - .*/).map(function(section) { return section.reference(); }); expect(results).to.deep.equal(expected); @@ -402,9 +382,8 @@ describe('KssStyleGuide object API', function() { }); it('should return referenceNumber values for "word phrase" sections in order', function(done) { - var results, - expected = ['2.1', '2.1.1', '2.1.2', '2.1.3', '2.1.4', '2.2', '2.3', '2.4', '2.5']; - results = this.styleGuideWordPhrases.sections(/gamma - .*/).map(function(section) { + let expected = ['2.1', '2.1.1', '2.1.2', '2.1.3', '2.1.4', '2.2', '2.3', '2.4', '2.5']; + let results = this.styleGuideWordPhrases.sections(/gamma - .*/).map(function(section) { return section.referenceNumber(); }); expect(results).to.deep.equal(expected); diff --git a/test/test_parse.js b/test/test_parse.js index 4cb62d53..9f4270e1 100644 --- a/test/test_parse.js +++ b/test/test_parse.js @@ -3,7 +3,7 @@ 'use strict'; -var fs = require('fs'), +const fs = require('fs'), marked = require('marked'); describe('kss.parse()', function() { @@ -37,7 +37,7 @@ describe('kss.parse()', function() { describe('given different comment syntax:', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: 'sections-comment-syntax.less'}, function(styleGuide) { self.styleGuide = styleGuide; done(); @@ -100,7 +100,7 @@ describe('kss.parse()', function() { describe('.sections():', function() { describe('.raw', function() { before(function(done) { - var self = this, + let self = this, fileCounter; helperUtils.traverseFixtures({}, function(styleGuide) { @@ -124,7 +124,7 @@ describe('kss.parse()', function() { }); it('should contain a copy of comment blocks that are from the original files (disregarding whitespace and asterisks)', function() { - var filteredFileText = this.fileContents.replace(/\/\/|\/\*+|\*\/|\s|\*/g, ''); + let filteredFileText = this.fileContents.replace(/\/\/|\/\*+|\*\/|\s|\*/g, ''); this.styleGuide.sections().map(function(section) { expect(filteredFileText).to.include(section.meta.raw.replace(/\s|\*/g, '')); @@ -134,7 +134,7 @@ describe('kss.parse()', function() { describe('.header / .description', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: 'property-header.less', markdown: false}, function(styleGuide) { self.styleGuide = styleGuide; done(); @@ -142,21 +142,21 @@ describe('kss.parse()', function() { }); it('should find a one line header, no description or modifiers', function(done) { - var section = this.styleGuide.sections('header.one-line.no-modifiers'); + let section = this.styleGuide.sections('header.one-line.no-modifiers'); expect(section.header()).to.equal('ONE LINE, NO MODIFIERS'); expect(section.description()).to.equal(''); done(); }); it('should find a one line header, multiple modifiers', function(done) { - var section = this.styleGuide.sections('header.one-line.multiple-modifiers'); + let section = this.styleGuide.sections('header.one-line.multiple-modifiers'); expect(section.header()).to.equal('ONE LINE, MULTIPLE MODIFIERS'); expect(section.description()).to.equal(''); done(); }); it('should find a header, description and multiple modifiers', function(done) { - var section = this.styleGuide.sections('header.description'); + let section = this.styleGuide.sections('header.description'); expect(section.header()).to.equal('HEADER DETECTION'); expect(section.description()).to.equal('SEPARATE PARAGRAPH'); expect(section.modifiers().length).to.equal(2); @@ -164,14 +164,14 @@ describe('kss.parse()', function() { }); it('should find a two-line header, multiple modifiers and no description', function(done) { - var section = this.styleGuide.sections('header.two-lines'); + let section = this.styleGuide.sections('header.two-lines'); expect(section.header()).to.equal('TWO LINES, MULTIPLE MODIFIERS LIKE SO'); expect(section.description()).to.equal(''); done(); }); it('should find a header, 3-paragraph description and no modifiers', function(done) { - var section = this.styleGuide.sections('header.three-paragraphs'); + let section = this.styleGuide.sections('header.three-paragraphs'); expect(section.header()).to.equal('THREE PARAGRAPHS, NO MODIFIERS'); expect(section.description()).to.equal('ANOTHER PARAGRAPH\n\nAND ANOTHER'); done(); @@ -188,7 +188,7 @@ describe('kss.parse()', function() { describe('.modifiers', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: 'property-modifiers.less', markdown: false}, function(styleGuide) { self.styleGuide = styleGuide; done(); @@ -196,13 +196,13 @@ describe('kss.parse()', function() { }); it('should find no modifiers', function(done) { - var modifiers = this.styleGuide.sections('no-modifiers').modifiers(); + let modifiers = this.styleGuide.sections('no-modifiers').modifiers(); expect(modifiers.length).to.equal(0); done(); }); it('should find modifiers with a single white space', function(done) { - var modifiers = this.styleGuide.sections('modifiers.single-white-space').modifiers(); + let modifiers = this.styleGuide.sections('modifiers.single-white-space').modifiers(); expect(modifiers.length).to.equal(2); expect(modifiers[0].name()).to.equal(':hover'); expect(modifiers[0].description()).to.equal('HOVER'); @@ -212,7 +212,7 @@ describe('kss.parse()', function() { }); it('should find modifiers with variable white space', function(done) { - var modifiers = this.styleGuide.sections('modifiers.variable-white-space').modifiers(); + let modifiers = this.styleGuide.sections('modifiers.variable-white-space').modifiers(); expect(modifiers.length).to.equal(4); expect(modifiers[0].name()).to.equal(':hover'); expect(modifiers[0].description()).to.equal('HOVER'); @@ -226,7 +226,7 @@ describe('kss.parse()', function() { }); it('should find modifiers with CSS classes', function(done) { - var modifiers = this.styleGuide.sections('modifiers.classes').modifiers(); + let modifiers = this.styleGuide.sections('modifiers.classes').modifiers(); expect(modifiers.length).to.equal(3); expect(modifiers[0].name()).to.equal('.red'); expect(modifiers[0].description()).to.equal('MAKE IT RED'); @@ -238,7 +238,7 @@ describe('kss.parse()', function() { }); it('should find modifiers with CSS classes containing dashes', function(done) { - var modifiers = this.styleGuide.sections('modifiers.dashes-in-classes').modifiers(); + let modifiers = this.styleGuide.sections('modifiers.dashes-in-classes').modifiers(); expect(modifiers.length).to.equal(3); expect(modifiers[0].name()).to.equal('.red'); expect(modifiers[0].description()).to.equal('MAKE IT RED'); @@ -250,7 +250,7 @@ describe('kss.parse()', function() { }); it('should find modifiers with HTML elements', function(done) { - var modifiers = this.styleGuide.sections('modifiers.elements').modifiers(); + let modifiers = this.styleGuide.sections('modifiers.elements').modifiers(); expect(modifiers.length).to.equal(3); expect(modifiers[0].name()).to.equal('a'); expect(modifiers[0].description()).to.equal('Contains the image replacement'); @@ -262,13 +262,13 @@ describe('kss.parse()', function() { }); it('should find modifiers with mixed classes and elements', function(done) { - var modifiers = this.styleGuide.sections('modifiers.classes-elements').modifiers(); + let modifiers = this.styleGuide.sections('modifiers.classes-elements').modifiers(); expect(modifiers.length).to.equal(5); done(); }); it('should find modifiers with more than one dash', function(done) { - var modifiers = this.styleGuide.sections('modifiers.multiple-dashes').modifiers(); + let modifiers = this.styleGuide.sections('modifiers.multiple-dashes').modifiers(); expect(modifiers.length).to.equal(3); expect(modifiers[0].name()).to.equal('.red'); expect(modifiers[0].description()).to.equal('Color - red'); @@ -280,7 +280,7 @@ describe('kss.parse()', function() { }); it('should find modifiers after description', function(done) { - var modifiers = this.styleGuide.sections('modifiers.after-description').modifiers(); + let modifiers = this.styleGuide.sections('modifiers.after-description').modifiers(); expect(modifiers.length).to.equal(2); done(); }); @@ -288,7 +288,7 @@ describe('kss.parse()', function() { describe('.deprecated/.experimental', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: 'property-deprecated-experimental.less', markdown: false, header: true}, function(styleGuide) { self.styleGuide = styleGuide; done(); @@ -356,7 +356,7 @@ describe('kss.parse()', function() { context('given options', function() { describe('.custom', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({ mask: 'options-custom.less', markdown: false, @@ -396,7 +396,7 @@ describe('kss.parse()', function() { describe('.markup', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: 'property-markup.less', markdown: false}, function(styleGuide) { self.styleGuide = styleGuide; done(); @@ -404,7 +404,7 @@ describe('kss.parse()', function() { }); it('should find markup property', function(done) { - var section = this.styleGuide.sections('markup.second-paragraph'); + let section = this.styleGuide.sections('markup.second-paragraph'); expect(section.markup()).to.equal('Hello World'); expect(section.description()).to.equal(''); expect(section.modifiers().length).to.equal(3); @@ -412,14 +412,14 @@ describe('kss.parse()', function() { }); it('should find markup property below modifiers', function(done) { - var section = this.styleGuide.sections('markup.below-modifiers'); + let section = this.styleGuide.sections('markup.below-modifiers'); expect(section.markup()).to.equal('Lorem Ipsum'); expect(section.modifiers().length).to.equal(1); done(); }); it('should not interfere with content when at the top', function(done) { - var section = this.styleGuide.sections('markup.at-top'); + let section = this.styleGuide.sections('markup.at-top'); expect(section.header()).to.equal('Don\'t be the header'); expect(section.markup()).to.equal('

Header

'); expect(section.modifiers()[0].name()).to.equal('.title'); @@ -460,7 +460,7 @@ describe('kss.parse()', function() { describe('.typos:', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: 'options-typos.less', typos: true}, function(styleGuide) { self.styleGuide = styleGuide; helperUtils.traverseFixtures({mask: 'property-deprecated-experimental.less', typos: true}, function(styleGuide2) { diff --git a/test/test_traverse.js b/test/test_traverse.js index f4493f94..4019269b 100644 --- a/test/test_traverse.js +++ b/test/test_traverse.js @@ -39,7 +39,7 @@ describe('kss.traverse()', function() { describe('.mask:', function() { describe('default mask', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({}, function(styleGuide) { self.styleGuide = styleGuide; done(); @@ -82,7 +82,7 @@ describe('kss.traverse()', function() { describe('/\\.js/ (regex)', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: /\.js/}, function(styleGuide) { self.styleGuide = styleGuide; done(); @@ -105,7 +105,7 @@ describe('kss.traverse()', function() { describe("'*.js' (string)", function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: '*.js'}, function(styleGuide) { self.styleGuide = styleGuide; done(); @@ -128,7 +128,7 @@ describe('kss.traverse()', function() { describe('/\.js|\.less|\.css/ (regex)', function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: /\.js|\.less|\.css/}, function(styleGuide) { self.styleGuide = styleGuide; done(); @@ -151,7 +151,7 @@ describe('kss.traverse()', function() { describe("'*.js|*.less|*.css' (string)", function() { before(function(done) { - var self = this; + let self = this; helperUtils.traverseFixtures({mask: '*.js|*.less|*.css'}, function(styleGuide) { self.styleGuide = styleGuide; done();