From e6cf3b1b3b1425bd09ba06b1e723a68f4cf1b2fd Mon Sep 17 00:00:00 2001 From: Brian Muenzenmeyer Date: Tue, 7 Feb 2017 05:40:24 -0600 Subject: [PATCH] WIP deferred engine load! part of #610 part of the merge of #608 most unit tests working, only a few left - due to me hanging a property off the engine that @geoffp was not doing. still need to see how it behaves during actual builds --- .eslintrc | 6 +- core/lib/annotation_exporter.js | 48 +++++------ core/lib/changes_hunter.js | 18 ++-- core/lib/lineage_hunter.js | 46 +++++----- core/lib/list_item_hunter.js | 65 +++++++------- core/lib/markdown_parser.js | 18 ++-- core/lib/object_factory.js | 39 +++++---- core/lib/parameter_hunter.js | 59 +++++++------ core/lib/pattern_assembler.js | 34 ++++---- core/lib/pattern_engines.js | 128 ++++++++++++++-------------- core/lib/pattern_exporter.js | 10 +-- core/lib/pattern_graph.js | 26 +++--- core/lib/pattern_graph_dot.js | 12 +-- core/lib/pattern_registry.js | 8 +- core/lib/patternlab.js | 132 +++++++++++++++-------------- core/lib/plugin_manager.js | 18 ++-- core/lib/pseudopattern_hunter.js | 109 ++++++++++++++++-------- core/lib/starterkit_manager.js | 24 +++--- core/lib/style_modifier_hunter.js | 4 +- core/lib/ui_builder.js | 118 +++++++++++++------------- test/engine_handlebars_tests.js | 4 +- test/engine_mustache_tests.js | 1 + test/lineage_hunter_tests.js | 3 + test/list_item_hunter_tests.js | 5 +- test/object_factory_tests.js | 3 + test/parameter_hunter_tests.js | 3 +- test/pattern_assembler_tests.js | 3 + test/pattern_engines_tests.js | 3 +- test/pattern_graph_tests.js | 3 + test/pseudopattern_hunter_tests.js | 4 + test/ui_builder_tests.js | 3 + 31 files changed, 516 insertions(+), 441 deletions(-) diff --git a/.eslintrc b/.eslintrc index f2463e9b6..c445390a4 100644 --- a/.eslintrc +++ b/.eslintrc @@ -83,6 +83,10 @@ "space-infix-ops": 1, "valid-typeof": 2, "vars-on-top": 0, - "wrap-iife": [2, "inside"] + "wrap-iife": [2, "inside"], + "prefer-const": ["error", { + "destructuring": "any", + "ignoreReadBeforeAssign": false + }] } } diff --git a/core/lib/annotation_exporter.js b/core/lib/annotation_exporter.js index d12054145..a0333e2e7 100644 --- a/core/lib/annotation_exporter.js +++ b/core/lib/annotation_exporter.js @@ -1,15 +1,15 @@ -"use strict"; +'use strict'; +const path = require('path'); +const glob = require('glob'); +const fs = require('fs-extra'); +const JSON5 = require('json5'); +const _ = require('lodash'); +const mp = require('./markdown_parser'); -var path = require('path'), - glob = require('glob'), - fs = require('fs-extra'), - JSON5 = require('json5'), - _ = require('lodash'), - mp = require('./markdown_parser'); +const annotations_exporter = function (pl) { -var annotations_exporter = function (pl) { - - var paths = pl.config.paths; + const paths = pl.config.paths; + let oldAnnotations; /* Returns the array of comments that used to be wrapped in raw JS. @@ -17,7 +17,7 @@ var annotations_exporter = function (pl) { function parseAnnotationsJS() { //attempt to read the file try { - var oldAnnotations = fs.readFileSync(path.resolve(paths.source.annotations, 'annotations.js'), 'utf8'); + oldAnnotations = fs.readFileSync(path.resolve(paths.source.annotations, 'annotations.js'), 'utf8'); } catch (ex) { if (pl.config.debug) { console.log('annotations.js file missing from ' + paths.source.annotations + '. This may be expected.'); @@ -40,8 +40,8 @@ var annotations_exporter = function (pl) { } function buildAnnotationMD(annotationsYAML, markdown_parser) { - var annotation = {}; - var markdownObj = markdown_parser.parse(annotationsYAML); + const annotation = {}; + const markdownObj = markdown_parser.parse(annotationsYAML); annotation.el = markdownObj.el || markdownObj.selector; annotation.title = markdownObj.title; @@ -50,16 +50,16 @@ var annotations_exporter = function (pl) { } function parseMDFile(annotations, parser) { - var annotations = annotations; - var markdown_parser = parser; + //let annotations = annotations; + const markdown_parser = parser; return function (filePath) { - var annotationsMD = fs.readFileSync(path.resolve(filePath), 'utf8'); + const annotationsMD = fs.readFileSync(path.resolve(filePath), 'utf8'); //take the annotation snippets and split them on our custom delimiter - var annotationsYAML = annotationsMD.split('~*~'); - for (var i = 0; i < annotationsYAML.length; i++) { - var annotation = buildAnnotationMD(annotationsYAML[i], markdown_parser); + const annotationsYAML = annotationsMD.split('~*~'); + for (let i = 0; i < annotationsYAML.length; i++) { + const annotation = buildAnnotationMD(annotationsYAML[i], markdown_parser); annotations.push(annotation); } return false; @@ -70,17 +70,17 @@ var annotations_exporter = function (pl) { Converts the *.md file yaml list into an array of annotations */ function parseAnnotationsMD() { - var markdown_parser = new mp(); - var annotations = []; - var mdFiles = glob.sync(paths.source.annotations + '/*.md'); + const markdown_parser = new mp(); + const annotations = []; + const mdFiles = glob.sync(paths.source.annotations + '/*.md'); mdFiles.forEach(parseMDFile(annotations, markdown_parser)); return annotations; } function gatherAnnotations() { - var annotationsJS = parseAnnotationsJS(); - var annotationsMD = parseAnnotationsMD(); + const annotationsJS = parseAnnotationsJS(); + const annotationsMD = parseAnnotationsMD(); return _.unionBy(annotationsJS, annotationsMD, 'el'); } diff --git a/core/lib/changes_hunter.js b/core/lib/changes_hunter.js index 3b98f9a9c..f92666abd 100644 --- a/core/lib/changes_hunter.js +++ b/core/lib/changes_hunter.js @@ -1,12 +1,12 @@ -"use strict"; -const fs = require("fs-extra"), - CompileState = require('./object_factory').CompileState; +'use strict'; +const fs = require("fs-extra"); +const CompileState = require('./object_factory').CompileState; /** * For detecting changed patterns. * @constructor */ -let ChangesHunter = function () { +const ChangesHunter = function () { }; ChangesHunter.prototype = { @@ -24,11 +24,11 @@ ChangesHunter.prototype = { checkBuildState: function (pattern, patternlab) { //write the compiled template to the public patterns directory - let renderedTemplatePath = + const renderedTemplatePath = patternlab.config.paths.public.patterns + pattern.getPatternLink(patternlab, 'rendered'); //write the compiled template to the public patterns directory - let markupOnlyPath = + const markupOnlyPath = patternlab.config.paths.public.patterns + pattern.getPatternLink(patternlab, 'markupOnly'); if (!pattern.compileState) { @@ -45,7 +45,7 @@ ChangesHunter.prototype = { // Prevent error message if file does not exist fs.accessSync(renderedFile, fs.F_OK) ); - let outputLastModified = fs.statSync(renderedTemplatePath).mtime.getTime(); + const outputLastModified = fs.statSync(renderedTemplatePath).mtime.getTime(); if (pattern.lastModified && outputLastModified > pattern.lastModified) { pattern.compileState = CompileState.CLEAN; @@ -55,7 +55,7 @@ ChangesHunter.prototype = { pattern.compileState = CompileState.NEEDS_REBUILD; } - let node = patternlab.graph.node(pattern); + const node = patternlab.graph.node(pattern); // Make the pattern known to the PatternGraph and remember its compileState if (!node) { @@ -78,7 +78,7 @@ ChangesHunter.prototype = { checkLastModified: function (currentPattern, file) { if (file) { try { - let stat = fs.statSync(file); + const stat = fs.statSync(file); // Needs recompile whenever one of the patterns files (template, json, pseudopatterns) changed currentPattern.lastModified = diff --git a/core/lib/lineage_hunter.js b/core/lib/lineage_hunter.js index d20db5771..7c61be98d 100644 --- a/core/lib/lineage_hunter.js +++ b/core/lib/lineage_hunter.js @@ -1,30 +1,30 @@ -"use strict"; +'use strict'; +const extend = require("util")._extend; -var extend = require("util")._extend; +const lineage_hunter = function () { -var lineage_hunter = function () { + function findlineage(pattern, patternlab) { - var pa = require('./pattern_assembler'); + const pa = require('./pattern_assembler'); + const pattern_assembler = new pa(); - function findlineage(pattern, patternlab) { // As we are adding edges from pattern to ancestor patterns, ensure it is known to the graph patternlab.graph.add(pattern); - var pattern_assembler = new pa(); //find the {{> template-name }} within patterns - var matches = pattern.findPartials(); + const matches = pattern.findPartials(); if (matches !== null) { matches.forEach(function (match) { //get the ancestorPattern - var ancestorPattern = pattern_assembler.getPartial(pattern.findPartial(match), patternlab); + const ancestorPattern = pattern_assembler.getPartial(pattern.findPartial(match), patternlab); if (ancestorPattern && pattern.lineageIndex.indexOf(ancestorPattern.patternPartial) === -1) { //add it since it didnt exist pattern.lineageIndex.push(ancestorPattern.patternPartial); //create the more complex patternLineage object too - var l = { + const l = { "lineagePattern": ancestorPattern.patternPartial, "lineagePath": "../../patterns/" + ancestorPattern.patternLink }; @@ -44,7 +44,7 @@ var lineage_hunter = function () { ancestorPattern.lineageRIndex.push(pattern.patternPartial); //create the more complex patternLineage object in reverse - var lr = { + const lr = { "lineagePattern": pattern.patternPartial, "lineagePath": "../../patterns/" + pattern.patternLink }; @@ -69,7 +69,7 @@ var lineage_hunter = function () { * @param graph {PatternGraph} */ function setPatternState(direction, pattern, targetPattern, graph) { - var index = null; + let index = null; if (direction === 'fromPast') { index = graph.lineage(pattern); } else { @@ -77,7 +77,7 @@ var lineage_hunter = function () { } // if the request came from the past, apply target pattern state to current pattern lineage - for (var i = 0; i < index.length; i++) { + for (let i = 0; i < index.length; i++) { if (index[i].patternPartial === targetPattern.patternPartial) { index[i].lineageState = targetPattern.patternState; } @@ -87,36 +87,36 @@ var lineage_hunter = function () { function cascadePatternStates(patternlab) { - for (var i = 0; i < patternlab.patterns.length; i++) { - var pattern = patternlab.patterns[i]; + for (let i = 0; i < patternlab.patterns.length; i++) { + const pattern = patternlab.patterns[i]; //for each pattern with a defined state if (pattern.patternState) { - var lineage = patternlab.graph.lineage(pattern); + const lineage = patternlab.graph.lineage(pattern); if (lineage && lineage.length > 0) { //find all lineage - patterns being consumed by this one - for (var h = 0; h < lineage.length; h++) { + for (let h = 0; h < lineage.length; h++) { // Not needed, the graph already knows the concrete pattern - // var lineagePattern = pattern_assembler.getPartial(lineageIndex[h], patternlab); + // let lineagePattern = pattern_assembler.getPartial(lineageIndex[h], patternlab); setPatternState('fromFuture', lineage[h], pattern, patternlab.graph); } } - var lineageR = patternlab.graph.lineageR(pattern); + const lineageR = patternlab.graph.lineageR(pattern); if (lineageR && lineageR.length > 0) { //find all reverse lineage - that is, patterns consuming this one - for (var j = 0; j < lineageR.length; j++) { + for (let j = 0; j < lineageR.length; j++) { - var lineageRPattern = lineageR[j]; + const lineageRPattern = lineageR[j]; //only set patternState if pattern.patternState "is less than" the lineageRPattern.patternstate //or if lineageRPattern.patternstate (the consuming pattern) does not have a state //this makes patternlab apply the lowest common ancestor denominator - let patternStateCascade = patternlab.config.patternStateCascade; - let patternStateIndex = patternStateCascade.indexOf(pattern.patternState); - let patternReverseStateIndex = patternStateCascade.indexOf(lineageRPattern.patternState); + const patternStateCascade = patternlab.config.patternStateCascade; + const patternStateIndex = patternStateCascade.indexOf(pattern.patternState); + const patternReverseStateIndex = patternStateCascade.indexOf(lineageRPattern.patternState); if (lineageRPattern.patternState === '' || (patternStateIndex < patternReverseStateIndex)) { if (patternlab.config.debug) { diff --git a/core/lib/list_item_hunter.js b/core/lib/list_item_hunter.js index be55f35c5..7904d2561 100644 --- a/core/lib/list_item_hunter.js +++ b/core/lib/list_item_hunter.js @@ -1,21 +1,20 @@ "use strict"; -var list_item_hunter = function () { - - var extend = require('util')._extend, - JSON5 = require('json5'), - pa = require('./pattern_assembler'), - smh = require('./style_modifier_hunter'), - plutils = require('./utilities'), - Pattern = require('./object_factory').Pattern; - - var pattern_assembler = new pa(), - style_modifier_hunter = new smh(), - items = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty']; +const list_item_hunter = function () { + const extend = require('util')._extend; + const JSON5 = require('json5'); + const pa = require('./pattern_assembler'); + const smh = require('./style_modifier_hunter'); + const plutils = require('./utilities'); + const Pattern = require('./object_factory').Pattern; + + const pattern_assembler = new pa(); + const style_modifier_hunter = new smh(); + const items = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty']; function processListItemPartials(pattern, patternlab) { //find any listitem blocks - var matches = pattern.findListItems(); + const matches = pattern.findListItems(); if (matches !== null) { matches.forEach(function (liMatch) { @@ -25,14 +24,14 @@ var list_item_hunter = function () { } //find the boundaries of the block - var loopNumberString = liMatch.split('.')[1].split('}')[0].trim(); - var end = liMatch.replace('#', '/'); - var patternBlock = pattern.template.substring(pattern.template.indexOf(liMatch) + liMatch.length, pattern.template.indexOf(end)).trim(); + const loopNumberString = liMatch.split('.')[1].split('}')[0].trim(); + const end = liMatch.replace('#', '/'); + const patternBlock = pattern.template.substring(pattern.template.indexOf(liMatch) + liMatch.length, pattern.template.indexOf(end)).trim(); //build arrays that repeat the block, however large we need to - var repeatedBlockTemplate = []; - var repeatedBlockHtml = ''; - for (var i = 0; i < items.indexOf(loopNumberString); i++) { + const repeatedBlockTemplate = []; + let repeatedBlockHtml = ''; + for (let i = 0; i < items.indexOf(loopNumberString); i++) { if (patternlab.config.debug) { console.log('list item(s) in pattern', pattern.patternPartial, 'adding', patternBlock, 'to repeatedBlockTemplate'); } @@ -40,7 +39,7 @@ var list_item_hunter = function () { } //check for a local listitems.json file - var listData; + let listData; try { listData = JSON5.parse(JSON5.stringify(patternlab.listitems)); } catch (err) { @@ -52,15 +51,15 @@ var list_item_hunter = function () { listData = pattern_assembler.parse_data_links_specific(patternlab, listData, 'listitems.json + any pattern listitems.json'); //iterate over each copied block, rendering its contents along with pattenlab.listitems[i] - for (var i = 0; i < repeatedBlockTemplate.length; i++) { + for (let i = 0; i < repeatedBlockTemplate.length; i++) { - var thisBlockTemplate = repeatedBlockTemplate[i]; - var thisBlockHTML = ""; + let thisBlockTemplate = repeatedBlockTemplate[i]; + let thisBlockHTML = ""; //combine listItem data with pattern data with global data - var itemData = listData['' + items.indexOf(loopNumberString)]; //this is a property like "2" - var globalData; - var localData; + const itemData = listData['' + items.indexOf(loopNumberString)]; //this is a property like "2" + let globalData; + let localData; try { globalData = JSON5.parse(JSON5.stringify(patternlab.data)); localData = JSON5.parse(JSON5.stringify(pattern.jsonFileData)); @@ -69,23 +68,23 @@ var list_item_hunter = function () { console.log(err); } - var allData = plutils.mergeData(globalData, localData); + let allData = plutils.mergeData(globalData, localData); allData = plutils.mergeData(allData, itemData !== undefined ? itemData[i] : {}); //itemData could be undefined if the listblock contains no partial, just markup allData.link = extend({}, patternlab.data.link); //check for partials within the repeated block - var foundPartials = Pattern.createEmpty({'template': thisBlockTemplate}).findPartials(); + const foundPartials = Pattern.createEmpty({'template': thisBlockTemplate}).findPartials(); if (foundPartials && foundPartials.length > 0) { - for (var j = 0; j < foundPartials.length; j++) { + for (let j = 0; j < foundPartials.length; j++) { //get the partial - var partialName = foundPartials[j].match(/([\w\-\.\/~]+)/g)[0]; - var partialPattern = pattern_assembler.getPartial(partialName, patternlab); + const partialName = foundPartials[j].match(/([\w\-\.\/~]+)/g)[0]; + const partialPattern = pattern_assembler.getPartial(partialName, patternlab); //create a copy of the partial so as to not pollute it after the get_pattern_by_key call. - var cleanPartialPattern; + let cleanPartialPattern; try { cleanPartialPattern = JSON5.parse(JSON5.stringify(partialPattern)); } catch (err) { @@ -118,7 +117,7 @@ var list_item_hunter = function () { } //replace the block with our generated HTML - var repeatingBlock = pattern.extendedTemplate.substring(pattern.extendedTemplate.indexOf(liMatch), pattern.extendedTemplate.indexOf(end) + end.length); + const repeatingBlock = pattern.extendedTemplate.substring(pattern.extendedTemplate.indexOf(liMatch), pattern.extendedTemplate.indexOf(end) + end.length); pattern.extendedTemplate = pattern.extendedTemplate.replace(repeatingBlock, repeatedBlockHtml); //update the extendedTemplate in the partials object in case this pattern is consumed later diff --git a/core/lib/markdown_parser.js b/core/lib/markdown_parser.js index 495e0d181..0b09929ac 100644 --- a/core/lib/markdown_parser.js +++ b/core/lib/markdown_parser.js @@ -1,9 +1,8 @@ -"use strict"; +'use strict'; +const md = require('markdown-it')(); +const yaml = require('js-yaml'); -var md = require('markdown-it')(); -var yaml = require('js-yaml'); - -var markdown_parser = function () { +const markdown_parser = function () { /** * Converts a markdown block with frontmatter (each is optional, technically) to a well-formed object. @@ -11,24 +10,25 @@ var markdown_parser = function () { * @returns an object with any frontmatter keys, plus a .markdown key */ function parseMarkdownBlock(block) { - var returnObject = {}; + let returnObject = {}; try { //for each block process the yaml frontmatter and markdown - var frontmatterRE = /---\r?\n{1}([\s\S]*)---\r?\n{1}([\s\S]*)+/gm; - var chunks = frontmatterRE.exec(block); + const frontmatterRE = /---\r?\n{1}([\s\S]*)---\r?\n{1}([\s\S]*)+/gm; + const chunks = frontmatterRE.exec(block); if (chunks) { //we got some frontmatter if (chunks && chunks[1]) { //parse the yaml if we got it - var frontmatter = chunks[1]; + const frontmatter = chunks[1]; returnObject = yaml.safeLoad(frontmatter); } if (chunks[2]) { //parse the actual markdown if it exists returnObject.markdown = md.render(chunks[2]); + console.log('rendered markdown', returnObject.markdown); } else { returnObject.markdown = ''; } diff --git a/core/lib/object_factory.js b/core/lib/object_factory.js index 1263d80df..82e33021a 100644 --- a/core/lib/object_factory.js +++ b/core/lib/object_factory.js @@ -1,20 +1,27 @@ -"use strict"; - -var patternEngines = require('./pattern_engines'); -var path = require('path'); -var extend = require('util')._extend; +'use strict'; +const patternEngines = require('./pattern_engines'); +const path = require('path'); +const 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+-)?/; +const 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)); +/** + * Pattern constructor + * @constructor + */ +const 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. + * @param {relPath} relative directory + * @param {data} The JSON used to render values in the pattern. + * @param {patternlab} rendered html files for the pattern + */ + const 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' @@ -114,8 +121,8 @@ Pattern.prototype = { // 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; + const suffixConfig = patternlab.config.outputFileSuffixes; + const suffix = suffixType ? suffixConfig[suffixType] : suffixConfig.rendered; if (suffixType === 'rawTemplate') { return this.name + path.sep + this.name + suffix + this.fileExtension; @@ -165,7 +172,7 @@ Pattern.createEmpty = function (customProps, patternlab) { } } - var pattern = new Pattern(relPath, null, patternlab); + const pattern = new Pattern(relPath, null, patternlab); return extend(pattern, customProps); }; @@ -173,11 +180,11 @@ Pattern.createEmpty = function (customProps, patternlab) { // 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); + const newPattern = new Pattern(relPath || '', data || null, patternlab); return extend(newPattern, customProps); }; -var CompileState = { +const CompileState = { NEEDS_REBUILD: "needs rebuild", BUILDING: "building", CLEAN: "clean" diff --git a/core/lib/parameter_hunter.js b/core/lib/parameter_hunter.js index 6f2d50f1e..731f85dfd 100644 --- a/core/lib/parameter_hunter.js +++ b/core/lib/parameter_hunter.js @@ -1,14 +1,13 @@ -"use strict"; +'use strict'; -var parameter_hunter = function () { - - var extend = require('util')._extend, - JSON5 = require('json5'), - pa = require('./pattern_assembler'), - smh = require('./style_modifier_hunter'), - plutils = require('./utilities'), - style_modifier_hunter = new smh(), - pattern_assembler = new pa(); +const parameter_hunter = function () { + const extend = require('util')._extend; + const JSON5 = require('json5'); + const pa = require('./pattern_assembler'); + const smh = require('./style_modifier_hunter'); + const plutils = require('./utilities'); + const style_modifier_hunter = new smh(); + const pattern_assembler = new pa(); /** * This function is really to accommodate the lax JSON-like syntax allowed by @@ -53,14 +52,14 @@ var parameter_hunter = function () { * @returns {string} paramStringWellFormed */ function paramToJson(pString) { - var colonPos = -1; - var keys = []; - var paramString = pString; // to not reassign param - var paramStringWellFormed; - var quotePos = -1; - var regex; - var values = []; - var wrapper; + let colonPos = -1; + const keys = []; + let paramString = pString; // to not reassign param + let paramStringWellFormed; + let quotePos = -1; + let regex; + const values = []; + let wrapper; //replace all escaped double-quotes with escaped unicode paramString = paramString.replace(/\\"/g, '\\u0022'); @@ -169,7 +168,7 @@ var parameter_hunter = function () { //build paramStringWellFormed string for JSON parsing paramStringWellFormed = '{'; - for (var i = 0; i < keys.length; i++) { + for (let i = 0; i < keys.length; i++) { //keys //replace single-quote wrappers with double-quotes @@ -239,8 +238,8 @@ var parameter_hunter = function () { //compile this partial immeadiately, essentially consuming it. pattern.parameteredPartials.forEach(function (pMatch) { //find the partial's name and retrieve it - var partialName = pMatch.match(/([\w\-\.\/~]+)/g)[0]; - var partialPattern = pattern_assembler.getPartial(partialName, patternlab); + const partialName = pMatch.match(/([\w\-\.\/~]+)/g)[0]; + const partialPattern = pattern_assembler.getPartial(partialName, patternlab); //if we retrieved a pattern we should make sure that its extendedTemplate is reset. looks to fix #190 partialPattern.extendedTemplate = partialPattern.template; @@ -250,14 +249,14 @@ var parameter_hunter = function () { } //strip out the additional data, convert string to JSON. - var leftParen = pMatch.indexOf('('); - var rightParen = pMatch.lastIndexOf(')'); - var paramString = '{' + pMatch.substring(leftParen + 1, rightParen) + '}'; - var paramStringWellFormed = paramToJson(paramString); + const leftParen = pMatch.indexOf('('); + const rightParen = pMatch.lastIndexOf(')'); + const paramString = '{' + pMatch.substring(leftParen + 1, rightParen) + '}'; + const paramStringWellFormed = paramToJson(paramString); - var paramData = {}; - var globalData = {}; - var localData = {}; + let paramData = {}; + let globalData = {}; + let localData = {}; try { paramData = JSON5.parse(paramStringWellFormed); @@ -268,7 +267,7 @@ var parameter_hunter = function () { console.log(err); } - var allData = plutils.mergeData(globalData, localData); + let allData = plutils.mergeData(globalData, localData); allData = plutils.mergeData(allData, paramData); //if partial has style modifier data, replace the styleModifier value @@ -279,7 +278,7 @@ var parameter_hunter = function () { //extend pattern data links into link for pattern link shortcuts to work. we do this locally and globally allData.link = extend({}, patternlab.data.link); - var renderedPartial = pattern_assembler.renderPattern(partialPattern.extendedTemplate, allData, patternlab.partials); + const renderedPartial = pattern_assembler.renderPattern(partialPattern.extendedTemplate, allData, patternlab.partials); //remove the parameter from the partial and replace it with the rendered partial + paramData pattern.extendedTemplate = pattern.extendedTemplate.replace(pMatch, renderedPartial); diff --git a/core/lib/pattern_assembler.js b/core/lib/pattern_assembler.js index 342fe8e33..0576d0ff0 100644 --- a/core/lib/pattern_assembler.js +++ b/core/lib/pattern_assembler.js @@ -1,25 +1,25 @@ "use strict"; -var path = require('path'), - fs = require('fs-promise'), - _ = require('lodash'), - Pattern = require('./object_factory').Pattern, - CompileState = require('./object_factory').CompileState, - pph = require('./pseudopattern_hunter'), - mp = require('./markdown_parser'), - plutils = require('./utilities'), - patternEngines = require('./pattern_engines'), - lh = require('./lineage_hunter'), - lih = require('./list_item_hunter'), - smh = require('./style_modifier_hunter'), - ph = require('./parameter_hunter'), - _ = require('lodash'), - ch = require('./changes_hunter'), - JSON5 = require('json5'); - +const path = require('path'); +const _ = require('lodash'); +const Pattern = require('./object_factory').Pattern; +const CompileState = require('./object_factory').CompileState; +const pph = require('./pseudopattern_hunter'); +const mp = require('./markdown_parser'); +const plutils = require('./utilities'); +const patternEngines = require('./pattern_engines'); +const lh = require('./lineage_hunter'); +const lih = require('./list_item_hunter'); +const smh = require('./style_modifier_hunter'); +const ph = require('./parameter_hunter'); +const ch = require('./changes_hunter'); +const JSON5 = require('json5'); const markdown_parser = new mp(); const changes_hunter = new ch(); +//this is mocked in unit tests +let fs = require('fs-extra'); //eslint-disable-line prefer-const + const pattern_assembler = function () { // HELPER FUNCTIONS diff --git a/core/lib/pattern_engines.js b/core/lib/pattern_engines.js index c316cec9d..9b2249a2c 100644 --- a/core/lib/pattern_engines.js +++ b/core/lib/pattern_engines.js @@ -1,11 +1,10 @@ // special shoutout to Geoffrey Pursell for single-handedly making Pattern Lab Node Pattern Engines possible! 'use strict'; - -var path = require('path'); -var diveSync = require('diveSync'); +const path = require('path'); +const diveSync = require('diveSync'); const chalk = require('chalk'); -var engineMatcher = /^patternengine-node-(.*)$/; -var enginesDirectories = [ +const engineMatcher = /^patternengine-node-(.*)$/; +const enginesDirectories = [ { displayName: 'the core', path: path.resolve(__dirname, '..', '..', 'node_modules') @@ -15,31 +14,26 @@ var enginesDirectories = [ path: path.join(process.cwd(), 'node_modules') } ]; -var PatternEngines; // the main export object -var engineNameForExtension; // generated mapping of extension to engine name - - -// free "private" functions, for internal setup only // given a path: return the engine name if the path points to a valid engine // module directory, or false if it doesn't function isEngineModule(filePath) { - var baseName = path.basename(filePath); - var engineMatch = baseName.match(engineMatcher); + const baseName = path.basename(filePath); + const engineMatch = baseName.match(engineMatcher); if (engineMatch) { return engineMatch[1]; } return false; } function findEngineModulesInDirectory(dir) { - var foundEngines = []; + const foundEngines = []; diveSync(dir, { recursive: false, directories: true }, function (err, filePath) { if (err) { throw err; } - var foundEngineName = isEngineModule(filePath); + const foundEngineName = isEngineModule(filePath); if (foundEngineName) { foundEngines.push({ name: foundEngineName, @@ -51,50 +45,16 @@ function findEngineModulesInDirectory(dir) { return foundEngines; } -// Try to load engines! We scan for engines at each path specified above. This -// function is kind of a big deal. -function loadAllEngines(enginesObject) { - enginesDirectories.forEach(function (engineDirectory) { - var enginesInThisDir = findEngineModulesInDirectory(engineDirectory.path); - console.log(chalk.bold(`Loading engines from ${engineDirectory.displayName}...\n`)); - - // find all engine-named things in this directory and try to load them, - // unless it's already been loaded. - enginesInThisDir.forEach(function (engineDiscovery) { - var errorMessage; - var successMessage = chalk.green("good to go"); - - try { - // give it a try! load 'er up. But not if we already have, of course. - if (enginesObject[engineDiscovery.name]) { - throw new Error("already loaded, skipping."); - } - enginesObject[engineDiscovery.name] = require(engineDiscovery.modulePath); - } catch (err) { - errorMessage = err.message; - } finally { - // report on the status of the engine, one way or another! - console.log(` ${engineDiscovery.name}:`, errorMessage ? chalk.red(errorMessage) : successMessage); - } - }); - console.log(''); - }); - // Complain if for some reason we haven't loaded any engines. - if (Object.keys(enginesObject).length === 0) { - throw new Error('No engines loaded! Something is seriously wrong.'); - } - console.log(chalk.bold('Done loading engines.\n')); -} // produce a mapping between file extension and engine name for each of the // loaded engines function createFileExtensionToEngineNameMap(enginesObject) { - var mapping = {}; + const mapping = {}; Object.keys(enginesObject).forEach(function (engineName) { - var extensionForEngine = enginesObject[engineName].engineFileExtension; + const extensionForEngine = enginesObject[engineName].engineFileExtension; mapping[extensionForEngine] = engineName; }); @@ -117,13 +77,56 @@ function createFileExtensionToEngineNameMap(enginesObject) { // only the engine names so we can easily iterate over them; all the handy // methods and properites below should therefore be on its prototype. -PatternEngines = Object.create({ +const PatternEngines = Object.create({ + + loadAllEngines: function () { + var self = this; + + // Try to load engines! We scan for engines at each path specified above. This + // function is kind of a big deal. + enginesDirectories.forEach(function (engineDirectory) { + const enginesInThisDir = findEngineModulesInDirectory(engineDirectory.path); + console.log(chalk.bold(`Loading engines from ${engineDirectory.displayName}...\n`)); + + // find all engine-named things in this directory and try to load them, + // unless it's already been loaded. + enginesInThisDir.forEach(function (engineDiscovery) { + let errorMessage; + const successMessage = chalk.green("good to go"); + + try { + // give it a try! load 'er up. But not if we already have, of course. + if (self[engineDiscovery.name]) { + throw new Error("already loaded, skipping."); + } + self[engineDiscovery.name] = require(engineDiscovery.modulePath); + } catch (err) { + errorMessage = err.message; + } finally { + // report on the status of the engine, one way or another! + console.log(` ${engineDiscovery.name}:`, errorMessage ? chalk.red(errorMessage) : successMessage); + } + }); + console.log(''); + }); + + // Complain if for some reason we haven't loaded any engines. + if (Object.keys(self).length === 0) { + throw new Error('No engines loaded! Something is seriously wrong.'); + } + + // mapping of file extensions to engine names, for lookup use + self.engineNameForExtension = createFileExtensionToEngineNameMap(self); + + console.log(chalk.bold('Done loading engines.\n')); + }, + getEngineNameForPattern: function (pattern) { // avoid circular dependency by putting this in here. TODO: is this slow? - var of = require('./object_factory'); + const of = require('./object_factory'); if (pattern instanceof of.Pattern && typeof pattern.fileExtension === 'string' && pattern.fileExtension) { - return engineNameForExtension[pattern.fileExtension]; + return this.engineNameForExtension[pattern.fileExtension]; } // otherwise, assume it's a plain mustache template string and act @@ -135,27 +138,27 @@ PatternEngines = Object.create({ if (pattern.isPseudoPattern) { return this.getEngineForPattern(pattern.basePattern); } else { - var engineName = this.getEngineNameForPattern(pattern); + const engineName = this.getEngineNameForPattern(pattern); return this[engineName]; } }, getSupportedFileExtensions: function () { - var engineNames = Object.keys(PatternEngines); + const engineNames = Object.keys(PatternEngines); return engineNames.map(function (engineName) { return PatternEngines[engineName].engineFileExtension; }); }, isFileExtensionSupported: function (fileExtension) { - var supportedExtensions = PatternEngines.getSupportedFileExtensions(); + const supportedExtensions = PatternEngines.getSupportedFileExtensions(); return (supportedExtensions.lastIndexOf(fileExtension) !== -1); }, // given a filename, return a boolean: whether or not the filename indicates // that the file is pseudopattern JSON isPseudoPatternJSON: function (filename) { - var extension = path.extname(filename); + const extension = path.extname(filename); return (extension === '.json' && filename.indexOf('~') > -1); }, @@ -165,24 +168,17 @@ PatternEngines = Object.create({ // pattern files! isPatternFile: function (filename) { // skip hidden patterns/files without a second thought - var extension = path.extname(filename); + const extension = path.extname(filename); if (filename.charAt(0) === '.' || (extension === '.json' && !PatternEngines.isPseudoPatternJSON(filename))) { return false; } // not a hidden pattern, let's dig deeper - var supportedPatternFileExtensions = PatternEngines.getSupportedFileExtensions(); + const supportedPatternFileExtensions = PatternEngines.getSupportedFileExtensions(); return (supportedPatternFileExtensions.lastIndexOf(extension) !== -1 || PatternEngines.isPseudoPatternJSON(filename)); } }); - -// load up the engines we found -loadAllEngines(PatternEngines); - -// mapping of file extensions to engine names, for lookup use -engineNameForExtension = createFileExtensionToEngineNameMap(PatternEngines); - module.exports = PatternEngines; diff --git a/core/lib/pattern_exporter.js b/core/lib/pattern_exporter.js index 1b899a6a2..3d8d161c1 100644 --- a/core/lib/pattern_exporter.js +++ b/core/lib/pattern_exporter.js @@ -1,8 +1,8 @@ "use strict"; -var fs = require('fs-extra'); +const fs = require('fs-extra'); -var pattern_exporter = function () { +const pattern_exporter = function () { /** * Exports all pattern's final HTML as defined in patternlab-config.json to desired location. @@ -13,11 +13,11 @@ var pattern_exporter = function () { */ function exportPatterns(patternlab) { //read the config export options - var exportPartials = patternlab.config.patternExportPatternPartials; + const exportPartials = patternlab.config.patternExportPatternPartials; //find the chosen patterns to export - for (var i = 0; i < exportPartials.length; i++) { - for (var j = 0; j < patternlab.patterns.length; j++) { + for (let i = 0; i < exportPartials.length; i++) { + for (let j = 0; j < patternlab.patterns.length; j++) { if (exportPartials[i] === patternlab.patterns[j].patternPartial) { //write matches to the desired location fs.outputFileSync(patternlab.config.patternExportDirectory + patternlab.patterns[j].patternPartial + '.html', patternlab.patterns[j].patternPartialCode); diff --git a/core/lib/pattern_graph.js b/core/lib/pattern_graph.js index 5c28d3af1..c509ca406 100644 --- a/core/lib/pattern_graph.js +++ b/core/lib/pattern_graph.js @@ -125,9 +125,9 @@ PatternGraph.prototype = { * @throws {Error} If the pattern is unknown */ link: function (patternFrom, patternTo) { - let nameFrom = nodeName(patternFrom); - let nameTo = nodeName(patternTo); - for (let name of [nameFrom, nameTo]) { + const nameFrom = nodeName(patternFrom); + const nameTo = nodeName(patternTo); + for (const name of [nameFrom, nameTo]) { if (!this.patterns.has(name)) { throw new Error("Pattern not known: " + name); } @@ -144,8 +144,8 @@ PatternGraph.prototype = { * @return {boolean} */ hasLink: function (patternFrom, patternTo) { - let nameFrom = nodeName(patternFrom); - let nameTo = nodeName(patternTo); + const nameFrom = nodeName(patternFrom); + const nameTo = nodeName(patternTo); return this.graph.hasEdge(nameFrom, nameTo); }, @@ -170,22 +170,22 @@ PatternGraph.prototype = { * Edges are added in reverse order for topological sorting(e.g. atom -> molecule -> organism, * where "->" means "included by"). */ - let compileGraph = new Graph({ + const compileGraph = new Graph({ directed: true }); - let nodes = this.graph.nodes(); - let changedNodes = nodes.filter(n => compileStateFilter(this.patterns, n)); + const nodes = this.graph.nodes(); + const changedNodes = nodes.filter(n => compileStateFilter(this.patterns, n)); this.nodes2patterns(changedNodes).forEach(pattern => { - let patternNode = nodeName(pattern); + const patternNode = nodeName(pattern); if (!compileGraph.hasNode(patternNode)) { compileGraph.setNode(patternNode); } this.applyReverse(pattern, (from, to) => { from.compileState = CompileState.NEEDS_REBUILD; - let fromName = nodeName(from); - let toName = nodeName(to); - for (let name of [fromName, toName]) { + const fromName = nodeName(from); + const toName = nodeName(to); + for (const name of [fromName, toName]) { if (!compileGraph.hasNode(name)) { compileGraph.setNode(name); } @@ -212,7 +212,7 @@ PatternGraph.prototype = { * between patterns and node metadata. */ applyReverse: function (pattern, fn) { - for (let p of this.lineageR(pattern)) { + for (const p of this.lineageR(pattern)) { fn(p, pattern); this.applyReverse(p, fn); } diff --git a/core/lib/pattern_graph_dot.js b/core/lib/pattern_graph_dot.js index 5d87c383e..1b89060b9 100644 --- a/core/lib/pattern_graph_dot.js +++ b/core/lib/pattern_graph_dot.js @@ -88,11 +88,11 @@ const PatternGraphDot = {}; PatternGraphDot.generate = function (patternGraph) { const g = patternGraph.graph; const patterns = patternGraph.patterns; - let buckets = new Map(); + const buckets = new Map(); const colors = ["darkgreen", "firebrick", "slateblue", "darkgoldenrod", "black"]; const colorMap = new Map(); let colIdx = 0; - for (let p of patterns.partials.values()) { + for (const p of patterns.partials.values()) { if (p.isPseudoPattern || !p.patternType) { continue; } @@ -117,7 +117,7 @@ PatternGraphDot.generate = function (patternGraph) { let subGraphLines = []; - for (let key of sortedKeys) { + for (const key of sortedKeys) { const subPatterns = buckets.get(key); subGraphLines = subGraphLines.concat(subGraph(key, subPatterns)); } @@ -125,9 +125,9 @@ PatternGraphDot.generate = function (patternGraph) { res.push("edge[style=solid];"); - foo: for (let edge of g.edges()) { - let fromTo = patternGraph.nodes2patterns([edge.v, edge.w]); - for (let pattern of fromTo) { + foo: for (const edge of g.edges()) { + const fromTo = patternGraph.nodes2patterns([edge.v, edge.w]); + for (const pattern of fromTo) { if (pattern.isPseudoPattern || !pattern.patternType) { continue foo; } diff --git a/core/lib/pattern_registry.js b/core/lib/pattern_registry.js index eda22d0ae..8caeb5aa8 100644 --- a/core/lib/pattern_registry.js +++ b/core/lib/pattern_registry.js @@ -50,16 +50,16 @@ PatternRegistry.prototype = { */ // This previously has been a for loop over an array in pattern_ - let byPartialName = this.partials.get(partialName); + const byPartialName = this.partials.get(partialName); if (this.partials.has(partialName)) { return byPartialName; } - let patterns = this.allPatterns(); + const patterns = this.allPatterns(); //else look by verbose syntax - for (let thisPattern of patterns) { + for (const thisPattern of patterns) { switch (partialName) { case thisPattern.relPath: case thisPattern.subdir + '/' + thisPattern.fileName: @@ -68,7 +68,7 @@ PatternRegistry.prototype = { } //return the fuzzy match if all else fails - for (let thisPattern of patterns) { + for (const thisPattern of patterns) { const partialParts = partialName.split('-'), partialType = partialParts[0], partialNameEnd = partialParts.slice(1).join('-'); diff --git a/core/lib/patternlab.js b/core/lib/patternlab.js index 356adc16c..d02d7117d 100644 --- a/core/lib/patternlab.js +++ b/core/lib/patternlab.js @@ -10,19 +10,19 @@ "use strict"; -var diveSync = require('diveSync'), - dive = require('dive'), - glob = require('glob'), - _ = require('lodash'), - path = require('path'), - chalk = require('chalk'), - cleanHtml = require('js-beautify').html, - inherits = require('util').inherits, - pm = require('./plugin_manager'), - fs = require('fs-extra'), - packageInfo = require('../../package.json'), - plutils = require('./utilities'), - PatternGraph = require('./pattern_graph').PatternGraph; +const diveSync = require('diveSync'); +const dive = require('dive'); +const glob = require('glob'); +const _ = require('lodash'); +const path = require('path'); +const chalk = require('chalk'); +const cleanHtml = require('js-beautify').html; +const inherits = require('util').inherits; +const pm = require('./plugin_manager'); +const fs = require('fs-extra'); +const packageInfo = require('../../package.json'); +const plutils = require('./utilities'); +const PatternGraph = require('./pattern_graph').PatternGraph; //register our log events plutils.log.on('error', msg => console.log(msg)); @@ -36,14 +36,14 @@ console.log( chalk.bold(']====\n') ); -var patternEngines = require('./pattern_engines'); -var EventEmitter = require('events').EventEmitter; +const patternEngines = require('./pattern_engines'); +const EventEmitter = require('events').EventEmitter; function buildPatternData(dataFilesPath, fsDep) { - var dataFiles = glob.sync(dataFilesPath + '*.json', {"ignore" : [dataFilesPath + 'listitems.json']}); - var mergeObject = {}; + const dataFiles = glob.sync(dataFilesPath + '*.json', {"ignore" : [dataFilesPath + 'listitems.json']}); + let mergeObject = {}; dataFiles.forEach(function (filePath) { - var jsonData = fsDep.readJSONSync(path.resolve(filePath), 'utf8'); + const jsonData = fsDep.readJSONSync(path.resolve(filePath), 'utf8'); mergeObject = _.merge(mergeObject, jsonData); }); return mergeObject; @@ -51,10 +51,9 @@ function buildPatternData(dataFilesPath, fsDep) { // GTP: these two diveSync pattern processors factored out so they can be reused // from unit tests to reduce code dupe! -function processAllPatternsIterative(pattern_assembler, patterns_dir, patternlab){ - const async = require('async'); +function processAllPatternsIterative(pattern_assembler, patterns_dir, patternlab) { - const promiseAllPatternFiles = new Promise(function (resolve, reject) { + const promiseAllPatternFiles = new Promise(function (resolve) { dive( patterns_dir, (err, file) => { @@ -106,7 +105,7 @@ function processAllPatternsRecursive(pattern_assembler, patterns_dir, patternlab function checkConfiguration(patternlab) { //default the output suffixes if not present - var outputFileSuffixes = { + const outputFileSuffixes = { rendered: '.rendered', rawTemplate: '', markupOnly: '.markup-only' @@ -129,21 +128,21 @@ function initializePlugins(patternlab) { if (!patternlab.config.plugins) { return; } - var plugin_manager = new pm(patternlab.config, path.resolve(__dirname, '../../patternlab-config.json')); - var foundPlugins = plugin_manager.detect_plugins(); + const plugin_manager = new pm(patternlab.config, path.resolve(__dirname, '../../patternlab-config.json')); + const foundPlugins = plugin_manager.detect_plugins(); if (foundPlugins && foundPlugins.length > 0) { - for (var i = 0; i < foundPlugins.length; i++) { + for (let i = 0; i < foundPlugins.length; i++) { - let pluginKey = foundPlugins[i]; + const pluginKey = foundPlugins[i]; if (patternlab.config.debug) { console.log('Found plugin: ', pluginKey); console.log('Attempting to load and initialize plugin.'); } - var plugin = plugin_manager.load_plugin(pluginKey); + const plugin = plugin_manager.load_plugin(pluginKey); plugin(patternlab); } } @@ -155,9 +154,9 @@ function initializePlugins(patternlab) { */ function installPlugin(pluginName) { //get the config - var configPath = path.resolve(process.cwd(), 'patternlab-config.json'); - var config = fs.readJSONSync(path.resolve(configPath), 'utf8'); - var plugin_manager = new pm(config, configPath); + const configPath = path.resolve(process.cwd(), 'patternlab-config.json'); + const config = fs.readJSONSync(path.resolve(configPath), 'utf8'); + const plugin_manager = new pm(config, configPath); plugin_manager.install_plugin(pluginName); } @@ -167,25 +166,24 @@ function PatternLabEventEmitter() { } inherits(PatternLabEventEmitter, EventEmitter); - -var patternlab_engine = function (config) { +const patternlab_engine = function (config) { 'use strict'; - var JSON5 = require('json5'), - pa = require('./pattern_assembler'), - pe = require('./pattern_exporter'), - lh = require('./lineage_hunter'), - ui = require('./ui_builder'), - sm = require('./starterkit_manager'), - Pattern = require('./object_factory').Pattern, - CompileState = require('./object_factory').CompileState, - patternlab = {}; + const JSON5 = require('json5'); + const pa = require('./pattern_assembler'); + const pe = require('./pattern_exporter'); + const lh = require('./lineage_hunter'); + const ui = require('./ui_builder'); + const sm = require('./starterkit_manager'); + const Pattern = require('./object_factory').Pattern; + const CompileState = require('./object_factory').CompileState; + const patternlab = {}; patternlab.engines = patternEngines; - var pattern_assembler = new pa(), - pattern_exporter = new pe(), - lineage_hunter = new lh(); + const pattern_assembler = new pa(); + const pattern_exporter = new pe(); + const lineage_hunter = new lh(); patternlab.package = fs.readJSONSync(path.resolve(__dirname, '../../package.json')); patternlab.config = config || fs.readJSONSync(path.resolve(__dirname, '../../patternlab-config.json')); @@ -199,7 +197,7 @@ var patternlab_engine = function (config) { //todo: determine if this is the best place to wire up plugins initializePlugins(patternlab); - var paths = patternlab.config.paths; + const paths = patternlab.config.paths; function getVersion() { console.log(patternlab.package.version); @@ -290,12 +288,12 @@ var patternlab_engine = function (config) { } function listStarterkits() { - var starterkit_manager = new sm(patternlab.config); + const starterkit_manager = new sm(patternlab.config); return starterkit_manager.list_starterkits(); } function loadStarterKit(starterkitName, clean) { - var starterkit_manager = new sm(patternlab.config); + const starterkit_manager = new sm(patternlab.config); starterkit_manager.load_starterkit(starterkitName, clean); } @@ -304,8 +302,8 @@ var patternlab_engine = function (config) { */ function processHeadPattern() { try { - var headPath = path.resolve(paths.source.meta, '_00-head.mustache'); - var headPattern = new Pattern(headPath, null, patternlab); + const headPath = path.resolve(paths.source.meta, '_00-head.mustache'); + const headPattern = new Pattern(headPath, null, patternlab); headPattern.template = fs.readFileSync(headPath, 'utf8'); headPattern.isPattern = false; headPattern.isMetaPattern = true; @@ -324,8 +322,8 @@ var patternlab_engine = function (config) { */ function processFootPattern() { try { - var footPath = path.resolve(paths.source.meta, '_01-foot.mustache'); - var footPattern = new Pattern(footPath, null, patternlab); + const footPath = path.resolve(paths.source.meta, '_01-foot.mustache'); + const footPattern = new Pattern(footPath, null, patternlab); footPattern.template = fs.readFileSync(footPath, 'utf8'); footPattern.isPattern = false; footPattern.isMetaPattern = true; @@ -389,7 +387,7 @@ var patternlab_engine = function (config) { patternlab.events.emit('patternlab-pattern-before-data-merge', patternlab, pattern); //render the pattern, but first consolidate any data we may have - var allData; + let allData; try { allData = JSON5.parse(JSON5.stringify(patternlab.data)); } catch (err) { @@ -401,7 +399,7 @@ var patternlab_engine = function (config) { //re-rendering the headHTML each time allows pattern-specific data to influence the head of the pattern pattern.header = head; - var headHTML = pattern_assembler.renderPattern(pattern.header, allData); + const headHTML = pattern_assembler.renderPattern(pattern.header, allData); //render the extendedTemplate with all data pattern.patternPartialCode = pattern_assembler.renderPattern(pattern, allData); @@ -434,13 +432,13 @@ var patternlab_engine = function (config) { }); //set the pattern-specific footer by compiling the general-footer with data, and then adding it to the meta footer - var footerPartial = pattern_assembler.renderPattern(patternlab.footer, { + const footerPartial = pattern_assembler.renderPattern(patternlab.footer, { isPattern: pattern.isPattern, patternData: pattern.patternData, cacheBuster: patternlab.cacheBuster }); - var allFooterData; + let allFooterData; try { allFooterData = JSON5.parse(JSON5.stringify(patternlab.data)); } catch (err) { @@ -450,7 +448,7 @@ var patternlab_engine = function (config) { allFooterData = plutils.mergeData(allFooterData, pattern.jsonFileData); allFooterData.patternLabFoot = footerPartial; - var footerHTML = pattern_assembler.renderPattern(patternlab.userFoot, allFooterData); + const footerHTML = pattern_assembler.renderPattern(patternlab.userFoot, allFooterData); patternlab.events.emit('patternlab-pattern-write-begin', patternlab, pattern); @@ -486,9 +484,9 @@ var patternlab_engine = function (config) { function buildPatterns(deletePatternDir) { patternlab.events.emit('patternlab-build-pattern-start', patternlab); - let graph = patternlab.graph = loadPatternGraph(deletePatternDir); + const graph = patternlab.graph = loadPatternGraph(deletePatternDir); - let graphNeedsUpgrade = !PatternGraph.checkVersion(graph); + const graphNeedsUpgrade = !PatternGraph.checkVersion(graph); if (graphNeedsUpgrade) { plutils.log.info("Due to an upgrade, a complete rebuild is required and the public/patterns directory was deleted. " + @@ -499,7 +497,7 @@ var patternlab_engine = function (config) { } // Flags - let incrementalBuildsEnabled = !(deletePatternDir || graphNeedsUpgrade); + const incrementalBuildsEnabled = !(deletePatternDir || graphNeedsUpgrade); if (incrementalBuildsEnabled) { plutils.log.info("Incremental builds enabled."); @@ -545,6 +543,7 @@ var patternlab_engine = function (config) { // diveSync once to perform iterative populating of patternlab object return processAllPatternsIterative(pattern_assembler, paths.source.patterns, patternlab).then(() => { + patternlab.events.emit('patternlab-pattern-iteration-end', patternlab); //diveSync again to recursively include partials, filling out the @@ -564,7 +563,7 @@ var patternlab_engine = function (config) { lineage_hunter.cascade_pattern_states(patternlab); //set pattern-specific header if necessary - var head; + let head; if (patternlab.userHead) { head = patternlab.userHead; } else { @@ -580,6 +579,15 @@ var patternlab_engine = function (config) { // rebuild all patterns let patternsToBuild = null; + //set the pattern-specific header by compiling the general-header with data, and then adding it to the meta header + patternlab.data.patternLabHead = pattern_assembler.renderPattern(patternlab.header, { + cacheBuster: patternlab.cacheBuster + }); + + // If deletePatternDir == true or graph needs to be updated + // rebuild all patterns + patternsToBuild = null; + if (incrementalBuildsEnabled) { // When the graph was loaded from file, some patterns might have been moved/deleted between runs // so the graph data become out of sync @@ -588,13 +596,13 @@ var patternlab_engine = function (config) { }); // TODO Find created or deleted files - let now = new Date().getTime(); + const now = new Date().getTime(); pattern_assembler.mark_modified_patterns(now, patternlab); patternsToBuild = patternlab.graph.compileOrder(); } else { // build all patterns, mark all to be rebuilt patternsToBuild = patternlab.patterns; - for (let p of patternsToBuild) { + for (const p of patternsToBuild) { p.compileState = CompileState.NEEDS_REBUILD; } } diff --git a/core/lib/plugin_manager.js b/core/lib/plugin_manager.js index 136cc7324..b126f767c 100644 --- a/core/lib/plugin_manager.js +++ b/core/lib/plugin_manager.js @@ -1,9 +1,9 @@ "use strict"; -var plugin_manager = function (config, configPath) { - var path = require('path'), - fs = require('fs-extra'), - util = require('./utilities'); +const plugin_manager = function (config, configPath) { + const path = require('path'); + const fs = require('fs-extra'); + const util = require('./utilities'); /** * Loads a plugin @@ -22,7 +22,7 @@ var plugin_manager = function (config, configPath) { */ function installPlugin(pluginName) { try { - var pluginPath = path.resolve( + const pluginPath = path.resolve( path.join(process.cwd(), 'node_modules', pluginName) ); console.log('Attempting to load plugin from', pluginPath); @@ -33,10 +33,10 @@ var plugin_manager = function (config, configPath) { util.error(pluginName + ' not loaded.'); return; } - var pluginPathDirExists = pluginDirStats.isDirectory(); + const pluginPathDirExists = pluginDirStats.isDirectory(); if (pluginPathDirExists) { - var diskConfig = fs.readJSONSync(path.resolve(configPath), 'utf8'); + const diskConfig = fs.readJSONSync(path.resolve(configPath), 'utf8'); //add the plugin entry to patternlab-config.json if (!diskConfig.plugins) { @@ -66,9 +66,9 @@ var plugin_manager = function (config, configPath) { * @return {array} list of installed plugins */ function detectPlugins() { - var node_modules_path = path.join(process.cwd(), 'node_modules'); + const node_modules_path = path.join(process.cwd(), 'node_modules'); return fs.readdirSync(node_modules_path).filter(function (dir) { - var module_path = path.join(process.cwd(), 'node_modules', dir); + const module_path = path.join(process.cwd(), 'node_modules', dir); return fs.statSync(module_path).isDirectory() && dir.indexOf('plugin-node-') === 0; }); } diff --git a/core/lib/pseudopattern_hunter.js b/core/lib/pseudopattern_hunter.js index 8d5e3cac3..3c7c14edc 100644 --- a/core/lib/pseudopattern_hunter.js +++ b/core/lib/pseudopattern_hunter.js @@ -1,40 +1,34 @@ +"use strict"; +const ch = require('./changes_hunter'); +const glob = require('glob'); +const fs = require('fs-extra'); +const lh = require('./lineage_hunter'); +const Pattern = require('./object_factory').Pattern; +const plutils = require('./utilities'); +const path = require('path'); +const lineage_hunter = new lh(); +const changes_hunter = new ch(); -const ch = require('./changes_hunter'), - glob = require('glob'), - fs = require('fs-extra'), - Pattern = require('./object_factory').Pattern, - plutils = require('./utilities'), - path = require('path'); - -/** - * The only public API in this module. This will search for pseudo - * patterns and returns a Promise that resolves when it's done. It - * doesn't return anything; processPseudoPattern() just updates the - * global state. - * @param {Object} currentPattern - * @param {Object} patternlab - * @returns {Promise} - */ -function findPseudoPatterns(currentPattern, patternlab) { +const pseudopattern_hunter = function () {}; + +pseudopattern_hunter.prototype.find_pseudopatterns = function (currentPattern, patternlab) { const pa = require('./pattern_assembler'); - const lh = require('./lineage_hunter'); const pattern_assembler = new pa(); - const lineage_hunter = new lh(); - const changes_hunter = new ch(); + const paths = patternlab.config.paths; //look for a pseudo pattern by checking if there is a file containing same //name, with ~ in it, ending in .json - var needle = currentPattern.subdir + '/' + currentPattern.fileName + '~*.json'; - var pseudoPatterns = glob.sync(needle, { + const needle = currentPattern.subdir + '/' + currentPattern.fileName + '~*.json'; + const pseudoPatterns = glob.sync(needle, { cwd: paths.source.patterns, debug: false, nodir: true }); if (pseudoPatterns.length > 0) { - for (var i = 0; i < pseudoPatterns.length; i++) { + for (let i = 0; i < pseudoPatterns.length; i++) { if (patternlab.config.debug) { console.log('found pseudoPattern variant of ' + currentPattern.patternPartial); } @@ -51,10 +45,10 @@ function findPseudoPatterns(currentPattern, patternlab) { //extend any existing data with variant data variantFileData = plutils.mergeData(currentPattern.jsonFileData, variantFileData); - var variantName = pseudoPatterns[i].substring(pseudoPatterns[i].indexOf('~') + 1).split('.')[0]; - var variantFilePath = path.join(currentPattern.subdir, currentPattern.fileName + '~' + variantName + '.json'); - var lm = fs.statSync(variantFileFullPath); - var patternVariant = Pattern.create(variantFilePath, variantFileData, { + let variantName = pseudoPatterns[i].substring(pseudoPatterns[i].indexOf('~') + 1).split('.')[0]; + let variantFilePath = path.join(currentPattern.subdir, currentPattern.fileName + '~' + variantName + '.json'); + let lm = fs.statSync(variantFileFullPath); + let patternVariant = Pattern.create(variantFilePath, variantFileData, { //use the same template as the non-variant template: currentPattern.template, fileExtension: currentPattern.fileExtension, @@ -84,18 +78,59 @@ function findPseudoPatterns(currentPattern, patternlab) { //add to patternlab object so we can look these up later. pattern_assembler.addPattern(patternVariant, patternlab); - } - } - // GTP: this is to emulate the behavior of the stale asynced - // version; when we have time, we can make all the FS calls in here - // async and see if it helps any, but it didn't when I tried it. - return Promise.resolve(); -} + //we want to do everything we normally would here, except instead read the pseudoPattern data + try { + var variantFileFullPath = path.resolve(paths.source.patterns, pseudoPatterns[i]); + var variantFileData = fs.readJSONSync(variantFileFullPath); + } catch (err) { + console.log('There was an error parsing pseudopattern JSON for ' + currentPattern.relPath); + console.log(err); + } + + //extend any existing data with variant data + variantFileData = plutils.mergeData(currentPattern.jsonFileData, variantFileData); + + variantName = pseudoPatterns[i].substring(pseudoPatterns[i].indexOf('~') + 1).split('.')[0]; + variantFilePath = path.join(currentPattern.subdir, currentPattern.fileName + '~' + variantName + '.json'); + lm = fs.statSync(variantFileFullPath); + patternVariant = Pattern.create(variantFilePath, variantFileData, { + //use the same template as the non-variant + template: currentPattern.template, + fileExtension: currentPattern.fileExtension, + extendedTemplate: currentPattern.extendedTemplate, + isPseudoPattern: true, + basePattern: currentPattern, + stylePartials: currentPattern.stylePartials, + parameteredPartials: currentPattern.parameteredPartials, + + // Only regular patterns are discovered during iterative walks + // Need to recompile on data change or template change + lastModified: Math.max(currentPattern.lastModified, lm.mtime), + + // use the same template engine as the non-variant + engine: currentPattern.engine + }, patternlab); + + changes_hunter.checkBuildState(patternVariant, patternlab); + patternlab.graph.add(patternVariant); + patternlab.graph.link(patternVariant, currentPattern); + + //process the companion markdown file if it exists + pattern_assembler.parse_pattern_markdown(patternVariant, patternlab); + + //find pattern lineage + lineage_hunter.find_lineage(patternVariant, patternlab); + //add to patternlab object so we can look these up later. + pattern_assembler.addPattern(patternVariant, patternlab); + } -module.exports = { - find_pseudopatterns: function (pattern, patternlab) { - return findPseudoPatterns(pattern, patternlab); + // GTP: this is to emulate the behavior of the stale asynced + // version; when we have time, we can make all the FS calls in here + // async and see if it helps any, but it didn't when I tried it. } + return Promise.resolve(); }; + +module.exports = new pseudopattern_hunter(); diff --git a/core/lib/starterkit_manager.js b/core/lib/starterkit_manager.js index db4153486..24746316a 100644 --- a/core/lib/starterkit_manager.js +++ b/core/lib/starterkit_manager.js @@ -1,11 +1,11 @@ "use strict"; -var starterkit_manager = function (config) { - var path = require('path'), - fetch = require('node-fetch'), - fs = require('fs-extra'), - util = require('./utilities'), - paths = config.paths; +const starterkit_manager = function (config) { + const path = require('path'); + const fetch = require('node-fetch'); + const fs = require('fs-extra'); + const util = require('./utilities'); + const paths = config.paths; /** * Loads npm module identified by the starterkitName parameter. @@ -15,7 +15,7 @@ var starterkit_manager = function (config) { */ function loadStarterKit(starterkitName, clean) { try { - var kitPath = path.resolve( + const kitPath = path.resolve( path.join(process.cwd(), 'node_modules', starterkitName, config.starterkitSubDir) ); console.log('Attempting to load starterkit from', kitPath); @@ -26,7 +26,7 @@ var starterkit_manager = function (config) { util.error(starterkitName + ' not loaded.'); return; } - var kitPathDirExists = kitDirStats.isDirectory(); + const kitPathDirExists = kitDirStats.isDirectory(); if (kitPathDirExists) { if (clean) { @@ -60,7 +60,7 @@ var starterkit_manager = function (config) { 'Accept': 'application/json' } }).then(function (res) { - var contentType = res.headers.get('content-type'); + const contentType = res.headers.get('content-type'); if (contentType && contentType.indexOf('application/json') === -1) { throw new TypeError("StarterkitManager->listStarterkits: Not valid JSON"); } @@ -89,9 +89,9 @@ var starterkit_manager = function (config) { * @return {array} List of starter kits installed */ function detectStarterKits() { - var node_modules_path = path.join(process.cwd(), 'node_modules'); - var npm_modules = fs.readdirSync(node_modules_path).filter(function (dir) { - var module_path = path.join(process.cwd(), 'node_modules', dir); + const node_modules_path = path.join(process.cwd(), 'node_modules'); + const npm_modules = fs.readdirSync(node_modules_path).filter(function (dir) { + const module_path = path.join(process.cwd(), 'node_modules', dir); return fs.statSync(module_path).isDirectory() && dir.indexOf('starterkit-') === 0; }); return npm_modules; diff --git a/core/lib/style_modifier_hunter.js b/core/lib/style_modifier_hunter.js index f6f9f0596..af50fb155 100644 --- a/core/lib/style_modifier_hunter.js +++ b/core/lib/style_modifier_hunter.js @@ -1,6 +1,6 @@ "use strict"; -var style_modifier_hunter = function () { +const style_modifier_hunter = function () { /** * Modifies a patterns partial with any styleModifiers found on the supplied partial @@ -11,7 +11,7 @@ var style_modifier_hunter = function () { */ function consumestylemodifier(pattern, partial, patternlab) { //extract the classname from the stylemodifier which comes in the format of :className - var styleModifier = partial.match(/:([\w\-_|])+/g) ? partial.match(/:([\w\-_|])+/g)[0].slice(1) : null; + let styleModifier = partial.match(/:([\w\-_|])+/g) ? partial.match(/:([\w\-_|])+/g)[0].slice(1) : null; if (styleModifier) { //replace the special character pipe | used to separate multiple classes with a space diff --git a/core/lib/ui_builder.js b/core/lib/ui_builder.js index 22e4357fd..88ed1c19b 100644 --- a/core/lib/ui_builder.js +++ b/core/lib/ui_builder.js @@ -1,17 +1,19 @@ "use strict"; -var path = require('path'); -var JSON5 = require('json5'); -var fs = require('fs-extra'); -var ae = require('./annotation_exporter'); -var of = require('./object_factory'); -var Pattern = of.Pattern; -var pattern_assembler = require('./pattern_assembler')(); -var plutils = require('./utilities'); -var eol = require('os').EOL; -var _ = require('lodash'); - -var ui_builder = function () { +const path = require('path'); +const JSON5 = require('json5'); +const ae = require('./annotation_exporter'); +const of = require('./object_factory'); +const Pattern = of.Pattern; +const plutils = require('./utilities'); +const eol = require('os').EOL; +const _ = require('lodash'); + +//these are mocked in unit tests, so let them be overridden +let fs = require('fs-extra'); //eslint-disable-line prefer-const +let pattern_assembler = require('./pattern_assembler')(); //eslint-disable-line prefer-const + +const ui_builder = function () { /** * Registers the pattern to the patternPaths object for the appropriate patternGroup and basename @@ -60,7 +62,7 @@ var ui_builder = function () { * @returns boolean - whether or not the pattern is excluded */ function isPatternExcluded(pattern, patternlab) { - var isOmitted; + let isOmitted; // skip underscore-prefixed files isOmitted = pattern.isPattern && pattern.fileName.charAt(0) === '_'; @@ -112,7 +114,7 @@ var ui_builder = function () { */ function injectDocumentationBlock(pattern, patternlab, isSubtypePattern) { //first see if pattern_assembler processed one already - var docPattern = patternlab.subtypePatterns[pattern.patternGroup + (isSubtypePattern ? '-' + pattern.patternSubGroup : '')]; + let docPattern = patternlab.subtypePatterns[pattern.patternGroup + (isSubtypePattern ? '-' + pattern.patternSubGroup : '')]; if (docPattern) { docPattern.isDocPattern = true; docPattern.order = -Number.MAX_SAFE_INTEGER; @@ -164,7 +166,7 @@ var ui_builder = function () { * @returns the found pattern type object */ function getPatternType(patternlab, pattern) { - var patternType = _.find(patternlab.patternTypes, ['patternType', pattern.patternType]); + const patternType = _.find(patternlab.patternTypes, ['patternType', pattern.patternType]); if (!patternType) { plutils.error('Could not find patternType' + pattern.patternType + '. This is a critical error.'); @@ -182,8 +184,8 @@ var ui_builder = function () { * @returns the found patternSubType object */ function getPatternSubType(patternlab, pattern) { - var patternType = getPatternType(patternlab, pattern); - var patternSubType = _.find(patternType.patternTypeItems, ['patternSubtype', pattern.patternSubType]); + const patternType = getPatternType(patternlab, pattern); + const patternSubType = _.find(patternType.patternTypeItems, ['patternSubtype', pattern.patternSubType]); if (!patternSubType) { plutils.error('Could not find patternType ' + pattern.patternType + '-' + pattern.patternType + '. This is a critical error.'); @@ -201,15 +203,15 @@ var ui_builder = function () { * @param pattern - the pattern to register */ function addPatternSubType(patternlab, pattern) { - let newSubType = { + const newSubType = { patternSubtypeLC: pattern.patternSubGroup.toLowerCase(), patternSubtypeUC: pattern.patternSubGroup.charAt(0).toUpperCase() + pattern.patternSubGroup.slice(1), patternSubtype: pattern.patternSubType, patternSubtypeDash: pattern.patternSubGroup, //todo verify patternSubtypeItems: [] }; - var patternType = getPatternType(patternlab, pattern); - let insertIndex = _.sortedIndexBy(patternType.patternTypeItems, newSubType, 'patternSubtype'); + const patternType = getPatternType(patternlab, pattern); + const insertIndex = _.sortedIndexBy(patternType.patternTypeItems, newSubType, 'patternSubtype'); patternType.patternTypeItems.splice(insertIndex, 0, newSubType); } @@ -220,7 +222,7 @@ var ui_builder = function () { * @returns {{patternPartial: string, patternName: (*|string), patternState: string, patternSrcPath: string, patternPath: string}} */ function createPatternSubTypeItem(pattern) { - var patternPath = ''; + let patternPath = ''; if (pattern.isFlatPattern) { patternPath = pattern.flatPatternPath + '-' + pattern.fileName + '/' + pattern.flatPatternPath + '-' + pattern.fileName + '.html'; } else { @@ -261,7 +263,7 @@ var ui_builder = function () { newSubTypeItem = createPatternSubTypeItem(pattern); } - let patternSubType = getPatternSubType(patternlab, pattern); + const patternSubType = getPatternSubType(patternlab, pattern); patternSubType.patternSubtypeItems.push(newSubTypeItem); patternSubType.patternSubtypeItems = _.sortBy(patternSubType.patternSubtypeItems, ['order', 'name']); } @@ -272,7 +274,7 @@ var ui_builder = function () { * @param pattern - the pattern to add */ function addPatternItem(patternlab, pattern, isViewAllVariant) { - var patternType = getPatternType(patternlab, pattern); + const patternType = getPatternType(patternlab, pattern); if (!patternType) { plutils.error('Could not find patternType' + pattern.patternType + '. This is a critical error.'); console.trace(); @@ -317,7 +319,7 @@ var ui_builder = function () { return patternsArray.sort(function (a, b) { let aOrder = parseInt(a.order, 10); - let bOrder = parseInt(b.order, 10); + const bOrder = parseInt(b.order, 10); if (aOrder === NaN) { aOrder = Number.MAX_SAFE_INTEGER; @@ -367,7 +369,7 @@ var ui_builder = function () { * @returns ptterns grouped by type -> subtype like atoms -> global -> pattern, pattern, pattern */ function groupPatterns(patternlab) { - var groupedPatterns = { + const groupedPatterns = { patternGroups: {} }; @@ -426,14 +428,14 @@ var ui_builder = function () { */ function buildFooterHTML(patternlab, patternPartial) { //first render the general footer - var footerPartial = pattern_assembler.renderPattern(patternlab.footer, { + const footerPartial = pattern_assembler.renderPattern(patternlab.footer, { patternData: JSON.stringify({ patternPartial: patternPartial, }), cacheBuster: patternlab.cacheBuster }); - var allFooterData; + let allFooterData; try { allFooterData = JSON5.parse(JSON5.stringify(patternlab.data)); } catch (err) { @@ -443,7 +445,7 @@ var ui_builder = function () { allFooterData.patternLabFoot = footerPartial; //then add it to the user footer - var footerHTML = pattern_assembler.renderPattern(patternlab.userFoot, allFooterData); + const footerHTML = pattern_assembler.renderPattern(patternlab.userFoot, allFooterData); return footerHTML; } @@ -456,7 +458,7 @@ var ui_builder = function () { * @returns HTML */ function buildViewAllHTML(patternlab, patterns, patternPartial) { - var viewAllHTML = pattern_assembler.renderPattern(patternlab.viewAll, + const viewAllHTML = pattern_assembler.renderPattern(patternlab.viewAll, { partials: patterns, patternPartial: 'viewall-' + patternPartial, @@ -476,20 +478,20 @@ var ui_builder = function () { * @returns every built pattern and set of viewall patterns, so the styleguide can use it */ function buildViewAllPages(mainPageHeadHtml, patternlab, styleguidePatterns) { - var paths = patternlab.config.paths; - var patterns = []; - var writeViewAllFile = true; + const paths = patternlab.config.paths; + let patterns = []; + let writeViewAllFile = true; //loop through the grouped styleguide patterns, building at each level _.forEach(styleguidePatterns.patternGroups, function (patternTypeObj, patternType) { - var p; - var typePatterns = []; - var styleGuideExcludes = patternlab.config.styleGuideExcludes; + let p; + let typePatterns = []; + const styleGuideExcludes = patternlab.config.styleGuideExcludes; _.forOwn(patternTypeObj, function (patternSubtypes, patternSubtype) { - var patternPartial = patternType + '-' + patternSubtype; + const patternPartial = patternType + '-' + patternSubtype; //do not create a viewall page for flat patterns if (patternType === patternSubtype) { @@ -498,10 +500,10 @@ var ui_builder = function () { } //render the footer needed for the viewall template - var footerHTML = buildFooterHTML(patternlab, 'viewall-' + patternPartial); + const footerHTML = buildFooterHTML(patternlab, 'viewall-' + patternPartial); //render the viewall template by finding these smallest subtype-grouped patterns - var subtypePatterns = sortPatterns(_.values(patternSubtypes)); + const subtypePatterns = sortPatterns(_.values(patternSubtypes)); //determine if we should write at this time by checking if these are flat patterns or grouped patterns p = _.find(subtypePatterns, function (pat) { @@ -510,7 +512,7 @@ var ui_builder = function () { typePatterns = typePatterns.concat(subtypePatterns); - var viewAllHTML = buildViewAllHTML(patternlab, subtypePatterns, patternPartial); + const viewAllHTML = buildViewAllHTML(patternlab, subtypePatterns, patternPartial); fs.outputFileSync(paths.public.patterns + p.flatPatternPath + '/index.html', mainPageHeadHtml + viewAllHTML + footerHTML); }); @@ -520,22 +522,22 @@ var ui_builder = function () { } //render the footer needed for the viewall template - var footerHTML = buildFooterHTML(patternlab, 'viewall-' + patternType + '-all'); + const footerHTML = buildFooterHTML(patternlab, 'viewall-' + patternType + '-all'); //add any flat patterns //todo this isn't quite working yet //typePatterns = typePatterns.concat(getPatternItems(patternlab, patternType)); //get the appropriate patternType - var anyPatternOfType = _.find(typePatterns, function (pat) { + const anyPatternOfType = _.find(typePatterns, function (pat) { return pat.patternType && pat.patternType !== '';}); //render the viewall template for the type - var viewAllHTML = buildViewAllHTML(patternlab, typePatterns, patternType); + const viewAllHTML = buildViewAllHTML(patternlab, typePatterns, patternType); fs.outputFileSync(paths.public.patterns + anyPatternOfType.patternType + '/index.html', mainPageHeadHtml + viewAllHTML + footerHTML); //determine if we should omit this patterntype completely from the viewall page - var omitPatternType = styleGuideExcludes && styleGuideExcludes.length + const omitPatternType = styleGuideExcludes && styleGuideExcludes.length && _.some(styleGuideExcludes, function (exclude) { return exclude === patternType; }); @@ -555,11 +557,11 @@ var ui_builder = function () { * @param patternlab - global data store */ function exportData(patternlab) { - var annotation_exporter = new ae(patternlab); - var paths = patternlab.config.paths; + const annotation_exporter = new ae(patternlab); + const paths = patternlab.config.paths; //write out the data - var output = ''; + let output = ''; //config output += 'var config = ' + JSON.stringify(patternlab.config) + ';\n'; @@ -587,8 +589,8 @@ var ui_builder = function () { fs.outputFileSync(path.resolve(paths.public.data, 'patternlab-data.js'), output); //annotations - var annotationsJSON = annotation_exporter.gather(); - var annotations = 'var comments = { "comments" : ' + JSON.stringify(annotationsJSON) + '};'; + const annotationsJSON = annotation_exporter.gather(); + const annotations = 'var comments = { "comments" : ' + JSON.stringify(annotationsJSON) + '};'; fs.outputFileSync(path.resolve(paths.public.annotations, 'annotations.js'), annotations); } @@ -609,31 +611,31 @@ var ui_builder = function () { resetUIBuilderState(patternlab); - var paths = patternlab.config.paths; + const paths = patternlab.config.paths; //determine which patterns should be included in the front-end rendering - var styleguidePatterns = groupPatterns(patternlab); + const styleguidePatterns = groupPatterns(patternlab); //set the pattern-specific header by compiling the general-header with data, and then adding it to the meta header - var headerPartial = pattern_assembler.renderPattern(patternlab.header, { + const headerPartial = pattern_assembler.renderPattern(patternlab.header, { cacheBuster: patternlab.cacheBuster }); - var headFootData = patternlab.data; + const headFootData = patternlab.data; headFootData.patternLabHead = headerPartial; headFootData.cacheBuster = patternlab.cacheBuster; - var headerHTML = pattern_assembler.renderPattern(patternlab.userHead, headFootData); + const headerHTML = pattern_assembler.renderPattern(patternlab.userHead, headFootData); //set the pattern-specific footer by compiling the general-footer with data, and then adding it to the meta footer - var footerPartial = pattern_assembler.renderPattern(patternlab.footer, { + const footerPartial = pattern_assembler.renderPattern(patternlab.footer, { patternData: '{}', cacheBuster: patternlab.cacheBuster }); headFootData.patternLabFoot = footerPartial; - var footerHTML = pattern_assembler.renderPattern(patternlab.userFoot, headFootData); + const footerHTML = pattern_assembler.renderPattern(patternlab.userFoot, headFootData); //build the viewall pages - var allPatterns = buildViewAllPages(headerHTML, patternlab, styleguidePatterns); + const allPatterns = buildViewAllPages(headerHTML, patternlab, styleguidePatterns); //add the defaultPattern if we found one if (patternlab.defaultPattern) { @@ -642,7 +644,7 @@ var ui_builder = function () { } //build the main styleguide page - var styleguideHtml = pattern_assembler.renderPattern(patternlab.viewAll, + const styleguideHtml = pattern_assembler.renderPattern(patternlab.viewAll, { partials: allPatterns }, { @@ -652,7 +654,7 @@ var ui_builder = function () { fs.outputFileSync(path.resolve(paths.public.styleguide, 'html/styleguide.html'), headerHTML + styleguideHtml + footerHTML); //move the index file from its asset location into public root - var patternlabSiteHtml; + let patternlabSiteHtml; try { patternlabSiteHtml = fs.readFileSync(path.resolve(paths.source.styleguide, 'index.html'), 'utf8'); } catch (error) { diff --git a/test/engine_handlebars_tests.js b/test/engine_handlebars_tests.js index 7acda08d0..fd6720a3d 100644 --- a/test/engine_handlebars_tests.js +++ b/test/engine_handlebars_tests.js @@ -9,8 +9,10 @@ var PatternGraph = require('../core/lib/pattern_graph').PatternGraph; var testPatternsPath = path.resolve(__dirname, 'files', '_handlebars-test-patterns'); var eol = require('os').EOL; -// don't run these tests unless handlebars is installed var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(); + +// don't run these tests unless handlebars is installed if (!engineLoader.handlebars) { tap.test('Handlebars engine not installed, skipping tests.', function (test) { test.end(); diff --git a/test/engine_mustache_tests.js b/test/engine_mustache_tests.js index 30d2c3048..35d49eb5a 100644 --- a/test/engine_mustache_tests.js +++ b/test/engine_mustache_tests.js @@ -10,6 +10,7 @@ var eol = require('os').EOL; // don't run these tests unless mustache is installed var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(); if (!engineLoader.mustache) { tap.test('Mustache engine not installed, skipping tests.', function (test) { test.end(); diff --git a/test/lineage_hunter_tests.js b/test/lineage_hunter_tests.js index d1206c1e1..01ab483c0 100644 --- a/test/lineage_hunter_tests.js +++ b/test/lineage_hunter_tests.js @@ -8,6 +8,9 @@ var of = require('../core/lib/object_factory'); var Pattern = require('../core/lib/object_factory').Pattern; var PatternGraph = require('../core/lib/pattern_graph').PatternGraph; +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(); + var fs = require('fs-extra'); var path = require('path'); diff --git a/test/list_item_hunter_tests.js b/test/list_item_hunter_tests.js index 74b21cd74..ed8bf6b7e 100644 --- a/test/list_item_hunter_tests.js +++ b/test/list_item_hunter_tests.js @@ -9,6 +9,9 @@ var extend = require('util')._extend; var pa = require('../core/lib/pattern_assembler'); var pattern_assembler = new pa(); +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(); + // fake pattern creators function createFakeListPattern(customProps) { var inputs = { @@ -421,5 +424,3 @@ tap.test('process_list_item_partials - correctly ignores already processed parti test.equals(listPattern.extendedTemplate.replace(/\s\s+/g, ' ').replace(/\n/g, ' ').trim(), expectedValue.trim()); test.end(); }); - - diff --git a/test/object_factory_tests.js b/test/object_factory_tests.js index f20034f61..0e831a8f3 100644 --- a/test/object_factory_tests.js +++ b/test/object_factory_tests.js @@ -28,6 +28,9 @@ var Pattern = require('../core/lib/object_factory').Pattern; var path = require('path'); var pl = fakePatternLab(); +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(); + tap.test('test Pattern initializes correctly', function (test) { var p = new Pattern('00-atoms/00-global/00-colors.mustache', { d: 123}); test.equals(p.relPath, '00-atoms' + path.sep + '00-global' + path.sep + '00-colors.mustache'); diff --git a/test/parameter_hunter_tests.js b/test/parameter_hunter_tests.js index 092f44428..4d64fec93 100644 --- a/test/parameter_hunter_tests.js +++ b/test/parameter_hunter_tests.js @@ -1,8 +1,9 @@ "use strict"; var tap = require('tap'); - var ph = require('../core/lib/parameter_hunter'); +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(); //setup current pattern from what we would have during execution function currentPatternClosure() { diff --git a/test/pattern_assembler_tests.js b/test/pattern_assembler_tests.js index 252c97079..1e44efd53 100644 --- a/test/pattern_assembler_tests.js +++ b/test/pattern_assembler_tests.js @@ -8,6 +8,9 @@ var CompileState = require('../core/lib/object_factory').CompileState; var PatternGraph = require('../core/lib/pattern_graph').PatternGraph; var path = require('path'); +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(); + function emptyPatternLab() { return { graph: PatternGraph.empty() diff --git a/test/pattern_engines_tests.js b/test/pattern_engines_tests.js index dc55b6cf0..951743257 100644 --- a/test/pattern_engines_tests.js +++ b/test/pattern_engines_tests.js @@ -5,6 +5,8 @@ var tap = require('tap'); var patternEngines = require('../core/lib/pattern_engines'); var Pattern = require('../core/lib/object_factory').Pattern; +patternEngines.loadAllEngines(); + // the mustache test pattern, stolen from object_factory unit tests var mustacheTestPattern = new Pattern('source/_patterns/00-atoms/00-global/00-colors-alt.mustache', {d: 123}); var mustacheTestPseudoPatternBasePattern = new Pattern('source/_patterns/04-pages/00-homepage.mustache', {d: 123}); @@ -161,4 +163,3 @@ engineNames.forEach(function (engineName) { test.end(); }); }); - diff --git a/test/pattern_graph_tests.js b/test/pattern_graph_tests.js index 78980422b..8da4d9033 100644 --- a/test/pattern_graph_tests.js +++ b/test/pattern_graph_tests.js @@ -8,6 +8,9 @@ var CompileState = require('../core/lib/object_factory').CompileState; var tap = require('tap'); const posixPath = require('./util/test_utils.js').posixPath; +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(); + var patternlab = { config: { paths: { diff --git a/test/pseudopattern_hunter_tests.js b/test/pseudopattern_hunter_tests.js index cd1a71a11..2aa2af0a0 100644 --- a/test/pseudopattern_hunter_tests.js +++ b/test/pseudopattern_hunter_tests.js @@ -4,10 +4,14 @@ var tap = require('tap'); var path = require('path'); var pph = require('../core/lib/pseudopattern_hunter'); + var pa = require('../core/lib/pattern_assembler'); var Pattern = require('../core/lib/object_factory').Pattern; var PatternGraph = require('../core/lib/pattern_graph').PatternGraph; +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(); + var fs = require('fs-extra'); var pattern_assembler = new pa(); var patterns_dir = './test/files/_patterns/'; diff --git a/test/ui_builder_tests.js b/test/ui_builder_tests.js index 38137c692..7ed6ebf45 100644 --- a/test/ui_builder_tests.js +++ b/test/ui_builder_tests.js @@ -8,6 +8,9 @@ var Pattern = require('../core/lib/object_factory').Pattern; var extend = require('util')._extend; var uiModule = rewire('../core/lib/ui_builder'); +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(); + //set up a global mocks - we don't want to be writing/rendering any files right now var fsMock = { outputFileSync: function (path, data, cb) { }