UNPKG

kss

Version:

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

202 lines (180 loc) 5.93 kB
'use strict'; /** * The `kss/lib/kss_modifier` module is normally accessed via the * [`KssModifier()`]{@link module:kss.KssModifier} class of the `kss` module: * ``` * const KssModifier = require('kss').KssModifier; * ``` * @private * @module kss/lib/kss_modifier */ /** * A KssModifier object represents a single modifier of a `KssSection`. * * This class is normally accessed via the [`kss`]{@link module:kss} module: * ``` * const KssModifier = require('kss').KssModifier; * ``` * * @alias module:kss.KssModifier */ class KssModifier { /** * Creates a KssModifier object and stores the given data. * * If passed an object, it will add `section`, `name`, `description`, and * `className` properties. * * @param {Object} [data] An object of data. */ 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]); } } } /** * 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; } 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; } 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; } 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. */ 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; } /** * 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 ''; } return (this.section().markup() || ''); } /** * 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;