From 481a71527102b114563d1ec95150b925a553fad6 Mon Sep 17 00:00:00 2001 From: Brian Muenzenmeyer Date: Fri, 25 Nov 2016 13:57:30 -0600 Subject: [PATCH 1/3] rename files to align with unit tests that may someday read them --- .../patternType1/{patternType2 => patternSubType2}/black.mustache | 0 .../patternType1/{patternType2 => patternSubType2}/grey.mustache | 0 .../patternType1/{patternType2 => patternSubType2}/white.mustache | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename test/files/_patterns/patternType1/{patternType2 => patternSubType2}/black.mustache (100%) rename test/files/_patterns/patternType1/{patternType2 => patternSubType2}/grey.mustache (100%) rename test/files/_patterns/patternType1/{patternType2 => patternSubType2}/white.mustache (100%) diff --git a/test/files/_patterns/patternType1/patternType2/black.mustache b/test/files/_patterns/patternType1/patternSubType2/black.mustache similarity index 100% rename from test/files/_patterns/patternType1/patternType2/black.mustache rename to test/files/_patterns/patternType1/patternSubType2/black.mustache diff --git a/test/files/_patterns/patternType1/patternType2/grey.mustache b/test/files/_patterns/patternType1/patternSubType2/grey.mustache similarity index 100% rename from test/files/_patterns/patternType1/patternType2/grey.mustache rename to test/files/_patterns/patternType1/patternSubType2/grey.mustache diff --git a/test/files/_patterns/patternType1/patternType2/white.mustache b/test/files/_patterns/patternType1/patternSubType2/white.mustache similarity index 100% rename from test/files/_patterns/patternType1/patternType2/white.mustache rename to test/files/_patterns/patternType1/patternSubType2/white.mustache From 027a26d7a395941a3f34f34b187aa9ab05a7e170 Mon Sep 17 00:00:00 2001 From: Brian Muenzenmeyer Date: Fri, 25 Nov 2016 13:57:55 -0600 Subject: [PATCH 2/3] lint --- core/lib/patternlab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/patternlab.js b/core/lib/patternlab.js index 61443bf0b..f03974727 100644 --- a/core/lib/patternlab.js +++ b/core/lib/patternlab.js @@ -146,7 +146,7 @@ var patternlab_engine = function (config) { Pattern = require('./object_factory').Pattern, patternlab = {}; - patternlab.engines = patternEngines; + patternlab.engines = patternEngines; var pattern_assembler = new pa(), pattern_exporter = new pe(), From c5905ec8bd2bf568033ea8b221c45cb97eb44c51 Mon Sep 17 00:00:00 2001 From: Brian Muenzenmeyer Date: Fri, 25 Nov 2016 13:59:20 -0600 Subject: [PATCH 3/3] trump filename sort order with pattern.md frontmatter property "order" unit tests to coverage scenario support is only for patterns at this time, not type / subtype documentation / directories part of #376 --- core/lib/object_factory.js | 1 + core/lib/patternlab.js | 2 +- core/lib/ui_builder.js | 107 +++++++++++++++++++++++++------------ package.json | 2 +- test/ui_builder_tests.js | 107 +++++++++++++++++++++++++++++++++++-- 5 files changed, 180 insertions(+), 39 deletions(-) diff --git a/core/lib/object_factory.js b/core/lib/object_factory.js index 29b637e4d..efa97a8f8 100644 --- a/core/lib/object_factory.js +++ b/core/lib/object_factory.js @@ -71,6 +71,7 @@ var Pattern = function (relPath, data, patternlab) { this.lineageR = []; this.lineageRIndex = []; this.isPseudoPattern = false; + this.order = Number.MAX_SAFE_INTEGER; this.engine = patternEngines.getEngineForPattern(this); }; diff --git a/core/lib/patternlab.js b/core/lib/patternlab.js index f03974727..2efde4e49 100644 --- a/core/lib/patternlab.js +++ b/core/lib/patternlab.js @@ -1,5 +1,5 @@ /* - * patternlab-node - v2.6.2 - 2016 + * patternlab-node - v2.7.0 - 2016 * * Brian Muenzenmeyer, Geoff Pursell, and the web community. * Licensed under the MIT license. diff --git a/core/lib/ui_builder.js b/core/lib/ui_builder.js index 0195ab040..9f97d80ab 100644 --- a/core/lib/ui_builder.js +++ b/core/lib/ui_builder.js @@ -115,6 +115,7 @@ var ui_builder = function () { var docPattern = patternlab.subtypePatterns[pattern.patternGroup + (isSubtypePattern ? '-' + pattern.patternSubGroup : '')]; if (docPattern) { docPattern.isDocPattern = true; + docPattern.order = -Number.MAX_SAFE_INTEGER; return docPattern; } @@ -130,7 +131,8 @@ var ui_builder = function () { isPattern: false, engine: null, flatPatternPath: pattern.flatPatternPath, - isDocPattern: true + isDocPattern: true, + order: -Number.MAX_SAFE_INTEGER }, patternlab ); @@ -199,16 +201,16 @@ var ui_builder = function () { * @param pattern - the pattern to register */ function addPatternSubType(patternlab, pattern) { + let 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); - patternType.patternTypeItems.push( - { - patternSubtypeLC: pattern.patternSubGroup.toLowerCase(), - patternSubtypeUC: pattern.patternSubGroup.charAt(0).toUpperCase() + pattern.patternSubGroup.slice(1), - patternSubtype: pattern.patternSubType, - patternSubtypeDash: pattern.patternSubGroup, //todo verify - patternSubtypeItems: [] - } - ); + let insertIndex = _.sortedIndexBy(patternType.patternTypeItems, newSubType, 'patternSubtype'); + patternType.patternTypeItems.splice(insertIndex, 0, newSubType); } /** @@ -230,7 +232,8 @@ var ui_builder = function () { patternName: pattern.patternName, patternState: pattern.patternState, patternSrcPath: encodeURI(pattern.subdir + '/' + pattern.fileName), - patternPath: patternPath + patternPath: patternPath, + order: pattern.order }; } @@ -242,23 +245,25 @@ var ui_builder = function () { * @param createViewAllVariant - whether or not to create the special view all item */ function addPatternSubTypeItem(patternlab, pattern, createSubtypeViewAllVarient) { - var patternSubType = getPatternSubType(patternlab, pattern); + let newSubTypeItem; + if (createSubtypeViewAllVarient) { - patternSubType.patternSubtypeItems.push( - { - patternPartial: 'viewall-' + pattern.patternGroup + '-' + pattern.patternSubGroup, - patternName: 'View All', - patternPath: encodeURI(pattern.flatPatternPath + '/index.html'), - patternType: pattern.patternType, - patternSubtype: pattern.patternSubtype - } - ); + newSubTypeItem = { + patternPartial: 'viewall-' + pattern.patternGroup + '-' + pattern.patternSubGroup, + patternName: 'View All', + patternPath: encodeURI(pattern.flatPatternPath + '/index.html'), + patternType: pattern.patternType, + patternSubtype: pattern.patternSubtype, + order: 0 + }; } else { - patternSubType.patternSubtypeItems.push( - createPatternSubTypeItem(pattern) - ); + newSubTypeItem = createPatternSubTypeItem(pattern); } + + let patternSubType = getPatternSubType(patternlab, pattern); + patternSubType.patternSubtypeItems.push(newSubTypeItem); + patternSubType.patternSubtypeItems = _.sortBy(patternSubType.patternSubtypeItems, ['order', 'name']); } /** @@ -284,13 +289,15 @@ var ui_builder = function () { patternType.patternItems.push({ patternPartial: 'viewall-' + pattern.patternGroup + '-all', patternName: 'View All', - patternPath: encodeURI(pattern.patternType + '/index.html') + patternPath: encodeURI(pattern.patternType + '/index.html'), + order: -Number.MAX_SAFE_INTEGER }); } } else { patternType.patternItems.push(createPatternSubTypeItem(pattern)); } + patternType.patternItems = _.sortBy(patternType.patternItems, ['order', 'name']); } // function getPatternItems(patternlab, patternType) { @@ -302,20 +309,54 @@ var ui_builder = function () { // } /** - * Sorts patterns based on name. - * Will be expanded to use explicit order in the near future + * Sorts patterns based on order property found within pattern markdown, falling back on name. * @param patternsArray - patterns to sort * @returns sorted patterns */ function sortPatterns(patternsArray) { return patternsArray.sort(function (a, b) { - if (a.name > b.name) { - return 1; + let aOrder = parseInt(a.order, 10); + let bOrder = parseInt(b.order, 10); + + if (aOrder === NaN) { + aOrder = Number.MAX_SAFE_INTEGER; + } + + if (bOrder === NaN) { + aOrder = Number.MAX_SAFE_INTEGER; } - if (a.name < b.name) { + + //alwasy return a docPattern first + if (a.isDocPattern && !b.isDocPattern) { return -1; } + + if (!a.isDocPattern && b.isDocPattern) { + return 1; + } + + //use old alphabetical ordering if we have nothing else to use + //pattern.order will be Number.MAX_SAFE_INTEGER if never defined by markdown, or markdown parsing fails + if (aOrder === Number.MAX_SAFE_INTEGER && bOrder === Number.MAX_SAFE_INTEGER) { + + if (a.name > b.name) { + return 1; + } + if (a.name < b.name) { + return -1; + } + } + + //if we get this far, we can sort safely + if (aOrder && bOrder) { + if (aOrder > bOrder) { + return 1; + } + if (aOrder < bOrder) { + return -1; + } + } return 0; }); } @@ -330,7 +371,7 @@ var ui_builder = function () { patternGroups: {} }; - _.forEach(sortPatterns(patternlab.patterns), function (pattern) { + _.forEach(patternlab.patterns, function (pattern) { //ignore patterns we can omit from rendering directly pattern.omitFromStyleguide = isPatternExcluded(pattern, patternlab); @@ -459,8 +500,8 @@ var ui_builder = function () { //render the footer needed for the viewall template var footerHTML = buildFooterHTML(patternlab, 'viewall-' + patternPartial); - //render the viewall template - var subtypePatterns = _.values(patternSubtypes); + //render the viewall template by finding these smallest subtype-grouped patterns + var 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) { diff --git a/package.json b/package.json index 541de8e2e..4e68fa093 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "patternlab-node", "description": "Pattern Lab is a collection of tools to help you create atomic design systems. This is the node command line interface (CLI).", - "version": "2.6.2", + "version": "2.7.0", "main": "./core/lib/patternlab.js", "dependencies": { "diveSync": "^0.3.0", diff --git a/test/ui_builder_tests.js b/test/ui_builder_tests.js index b140452dd..38137c692 100644 --- a/test/ui_builder_tests.js +++ b/test/ui_builder_tests.js @@ -2,6 +2,7 @@ var tap = require('tap'); var rewire = require("rewire"); +var _ = require('lodash'); var eol = require('os').EOL; var Pattern = require('../core/lib/object_factory').Pattern; var extend = require('util')._extend; @@ -120,8 +121,8 @@ tap.test('groupPatterns - creates pattern groups correctly', function (test) { }); patternlab.patterns.push( - new Pattern('00-test/foo.mustache'), new Pattern('00-test/bar.mustache'), + new Pattern('00-test/foo.mustache'), new Pattern('patternType1/patternSubType1/blue.mustache'), new Pattern('patternType1/patternSubType1/red.mustache'), new Pattern('patternType1/patternSubType1/yellow.mustache'), @@ -134,7 +135,6 @@ tap.test('groupPatterns - creates pattern groups correctly', function (test) { //act var result = ui.groupPatterns(patternlab); - //assert test.equals(result.patternGroups.patternType1.patternSubType1.blue.patternPartial, 'patternType1-blue'); test.equals(result.patternGroups.patternType1.patternSubType1.red.patternPartial, 'patternType1-red'); test.equals(result.patternGroups.patternType1.patternSubType1.yellow.patternPartial, 'patternType1-yellow'); @@ -142,14 +142,113 @@ tap.test('groupPatterns - creates pattern groups correctly', function (test) { test.equals(result.patternGroups.patternType1.patternSubType2.grey.patternPartial, 'patternType1-grey'); test.equals(result.patternGroups.patternType1.patternSubType2.white.patternPartial, 'patternType1-white'); - test.equals(patternlab.patternTypes[0].patternItems[0].patternPartial, 'test-bar'); - test.equals(patternlab.patternTypes[0].patternItems[1].patternPartial, 'test-foo'); + test.equals(patternlab.patternTypes[0].patternItems[0].patternPartial, 'test-bar', 'first pattern item should be test-bar'); + test.equals(patternlab.patternTypes[0].patternItems[1].patternPartial, 'test-foo', 'second pattern item should be test-foo'); //todo: patternlab.patternTypes[0].patternItems[1] looks malformed test.end(); }); +tap.test('groupPatterns - orders patterns when provided from md', function (test) { + //arrange + var patternlab = createFakePatternLab({ + patterns: [], + patternGroups: {}, + subtypePatterns: {} + }); + + patternlab.patterns.push( + new Pattern('patternType1/patternSubType1/blue.mustache'), + new Pattern('patternType1/patternSubType1/red.mustache'), + new Pattern('patternType1/patternSubType1/yellow.mustache') + ); + ui.resetUIBuilderState(patternlab); + + patternlab.patterns[1].order = 1; + + //act + ui.groupPatterns(patternlab); + + let patternType = _.find(patternlab.patternTypes, ['patternType', 'patternType1']); + let patternSubType = _.find(patternType.patternTypeItems, ['patternSubtype', 'patternSubType1']); + var items = patternSubType.patternSubtypeItems; + + //zero is viewall + test.equals(items[1].patternPartial, 'patternType1-red'); + test.equals(items[2].patternPartial, 'patternType1-blue'); + test.equals(items[3].patternPartial, 'patternType1-yellow'); + + test.end(); +}); + +tap.test('groupPatterns - retains pattern order from name when order provided from md is malformed', function (test) { + //arrange + var patternlab = createFakePatternLab({ + patterns: [], + patternGroups: {}, + subtypePatterns: {} + }); + + patternlab.patterns.push( + new Pattern('patternType1/patternSubType1/blue.mustache'), + new Pattern('patternType1/patternSubType1/red.mustache'), + new Pattern('patternType1/patternSubType1/yellow.mustache') + ); + ui.resetUIBuilderState(patternlab); + + patternlab.patterns[1].order = 'notanumber!'; + + //act + ui.groupPatterns(patternlab); + + let patternType = _.find(patternlab.patternTypes, ['patternType', 'patternType1']); + let patternSubType = _.find(patternType.patternTypeItems, ['patternSubtype', 'patternSubType1']); + var items = patternSubType.patternSubtypeItems; + + //zero is viewall + test.equals(items[1].patternPartial, 'patternType1-blue'); + test.equals(items[2].patternPartial, 'patternType1-red'); + test.equals(items[3].patternPartial, 'patternType1-yellow'); + + test.end(); +}); + +tap.test('groupPatterns - sorts viewall subtype pattern to the beginning', function (test) { + //arrange + var patternlab = createFakePatternLab({ + patterns: [], + patternGroups: {}, + subtypePatterns: {} + }); + + patternlab.patterns.push( + new Pattern('patternType1/patternSubType1/blue.mustache'), + new Pattern('patternType1/patternSubType1/red.mustache'), + new Pattern('patternType1/patternSubType1/yellow.mustache') + ); + ui.resetUIBuilderState(patternlab); + + patternlab.patterns[0].order = 1; + patternlab.patterns[1].order = 3; + patternlab.patterns[2].order = 2; + + //act + ui.groupPatterns(patternlab); + + let patternType = _.find(patternlab.patternTypes, ['patternType', 'patternType1']); + let patternSubType = _.find(patternType.patternTypeItems, ['patternSubtype', 'patternSubType1']); + var items = patternSubType.patternSubtypeItems; + + //zero is viewall + test.equals(items[0].patternPartial, 'viewall-patternType1-patternSubType1'); + test.equals(items[1].patternPartial, 'patternType1-blue'); + test.equals(items[2].patternPartial, 'patternType1-yellow'); + test.equals(items[3].patternPartial, 'patternType1-red'); + + test.end(); +}); + tap.test('groupPatterns - creates documentation patterns for each type and subtype if not exists', function (test) { //arrange var patternlab = createFakePatternLab({