UNPKG

patternlab-node

Version:

Pattern Lab is a collection of tools to help you create atomic design systems. This is the node command line interface (CLI).

190 lines (150 loc) 6.88 kB
"use strict"; var patternEngines = require('./pattern_engines'); var path = require('path'); var extend = require('util')._extend; // patternPrefixMatcher is intended to match the leading maybe-underscore, // zero or more digits, and maybe-dash at the beginning of a pattern file name we can hack them // off and get at the good part. var patternPrefixMatcher = /^_?(\d+-)?/; // Pattern properties var Pattern = function (relPath, data, patternlab) { // We expect relPath to be the path of the pattern template, relative to the // root of the pattern tree. Parse out the path parts and save the useful ones. var pathObj = path.parse(path.normalize(relPath)); this.relPath = path.normalize(relPath); // '00-atoms/00-global/00-colors.mustache' this.fileName = pathObj.name; // '00-colors' this.subdir = pathObj.dir; // '00-atoms/00-global' this.fileExtension = pathObj.ext; // '.mustache' // this is the unique name, subDir + fileName (sans extension) this.name = this.subdir.replace(path.sep, '-') + '-' + this.fileName.replace('~', '-'); // '00-atoms-00-global-00-colors' // the JSON used to render values in the pattern this.jsonFileData = data || {}; // strip leading "00-" from the file name and flip tildes to dashes this.patternBaseName = this.fileName.replace(patternPrefixMatcher, '').replace('~', '-'); // 'colors' // Fancy name. No idea how this works. 'Colors' this.patternName = this.patternBaseName.split('-').reduce(function (val, working) { return val.charAt(0).toUpperCase() + val.slice(1) + ' ' + working.charAt(0).toUpperCase() + working.slice(1); }, '').trim(); //this is the display name for the ui. strip numeric + hyphen prefixes // the top-level pattern group this pattern belongs to. 'atoms' this.patternGroup = this.subdir.split(path.sep)[0].replace(patternPrefixMatcher, ''); //00-atoms if needed this.patternType = this.subdir.split(path.sep)[0]; // the sub-group this pattern belongs to. this.patternSubGroup = path.basename(this.subdir).replace(patternPrefixMatcher, ''); // 'global' //00-colors if needed this.patternSubType = path.basename(this.subdir); // the joined pattern group and subgroup directory this.flatPatternPath = this.subdir.replace(/[\/\\]/g, '-'); // '00-atoms-00-global' // calculated path from the root of the public directory to the generated // (rendered!) html file for this pattern, to be shown in the iframe this.patternLink = patternlab ? this.getPatternLink(patternlab, 'rendered') : null; // The canonical "key" by which this pattern is known. This is the callable // name of the pattern. UPDATE: this.key is now known as this.patternPartial this.patternPartial = this.patternGroup + '-' + this.patternBaseName; // Let's calculate the verbose name ahead of time! We don't use path.sep here // on purpose. This isn't a file name! this.verbosePartial = this.subdir.split(path.sep).join('/') + '/' + this.fileName; this.isPattern = true; this.isFlatPattern = this.patternGroup === this.patternSubGroup; this.patternState = ''; this.template = ''; this.patternPartialCode = ''; this.lineage = []; this.lineageIndex = []; this.lineageR = []; this.lineageRIndex = []; this.isPseudoPattern = false; this.order = Number.MAX_SAFE_INTEGER; this.engine = patternEngines.getEngineForPattern(this); /** * Determines if this pattern needs to be recompiled. * * @ee {@link CompileState}*/ this.compileState = null; /** * Timestamp in milliseconds when the pattern template or auxilary file (e.g. json) were modified. * If multiple files are affected, this is the timestamp of the most recent change. * * @see {@link pattern} */ this.lastModified = null; }; // Pattern methods Pattern.prototype = { // render method on oPatterns; this acts as a proxy for the PatternEngine's // render function render: function (data, partials) { if (this.engine) { return this.engine.renderPattern(this, data || this.jsonFileData, partials); } return null; }, registerPartial: function () { if (this.engine && typeof this.engine.registerPartial === 'function') { this.engine.registerPartial(this); } }, // calculated path from the root of the public directory to the generated html // file for this pattern. // Should look something like '00-atoms-00-global-00-colors/00-atoms-00-global-00-colors.html' getPatternLink: function (patternlab, suffixType, customfileExtension) { // if no suffixType is provided, we default to rendered var suffixConfig = patternlab.config.outputFileSuffixes; var suffix = suffixType ? suffixConfig[suffixType] : suffixConfig.rendered; if (suffixType === 'rawTemplate') { return this.name + path.sep + this.name + suffix + this.fileExtension; } if (suffixType === 'custom') { return this.name + path.sep + this.name + customfileExtension; } return this.name + path.sep + this.name + suffix + '.html'; }, // the finders all delegate to the PatternEngine, which also encapsulates all // appropriate regexes findPartials: function () { return this.engine.findPartials(this); }, findPartialsWithStyleModifiers: function () { return this.engine.findPartialsWithStyleModifiers(this); }, findPartialsWithPatternParameters: function () { return this.engine.findPartialsWithPatternParameters(this); }, findListItems: function () { return this.engine.findListItems(this); }, findPartial: function (partialString) { return this.engine.findPartial(partialString); } }; // Pattern static methods // factory: creates an empty Pattern for miscellaneous internal use, such as // by list_item_hunter Pattern.createEmpty = function (customProps, patternlab) { let relPath = ''; if (customProps) { if (customProps.relPath) { relPath = customProps.relPath; } else if (customProps.subdir && customProps.filename) { relPath = customProps.subdir + path.sep + customProps.filename; } } var pattern = new Pattern(relPath, null, patternlab); return extend(pattern, customProps); }; // factory: creates an Pattern object on-demand from a hash; the hash accepts // parameters that replace the positional parameters that the Pattern // constructor takes. Pattern.create = function (relPath, data, customProps, patternlab) { var newPattern = new Pattern(relPath || '', data || null, patternlab); return extend(newPattern, customProps); }; var CompileState = { NEEDS_REBUILD: "needs rebuild", BUILDING: "building", CLEAN: "clean" }; module.exports = { Pattern: Pattern, CompileState: CompileState };