From 22373013b0bb56df76b6c4070fd3799e22b1324a Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Sun, 12 Apr 2020 02:20:00 +0200 Subject: [PATCH 01/16] Update object_factory and view all page behavior --- .prettierrc | 3 +- packages/core/src/lib/object_factory.js | 156 ++++++++++-------- packages/core/src/lib/ui_builder.js | 84 ++++------ packages/core/test/object_factory_tests.js | 40 ++--- .../src/scripts/components/pl-nav/pl-nav.js | 2 +- 5 files changed, 141 insertions(+), 144 deletions(-) diff --git a/.prettierrc b/.prettierrc index c1a6f6671..d81dbaeb5 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,5 @@ { "singleQuote": true, - "trailingComma": "es5" + "trailingComma": "es5", + "endOfLine": "auto" } diff --git a/packages/core/src/lib/object_factory.js b/packages/core/src/lib/object_factory.js index 83524a9c7..27cf771b1 100644 --- a/packages/core/src/lib/object_factory.js +++ b/packages/core/src/lib/object_factory.js @@ -1,18 +1,27 @@ 'use strict'; -const patternEngines = require('./pattern_engines'); + +const _ = require('lodash'); const path = require('path'); +const patternEngines = require('./pattern_engines'); -// patternPrefixMatcher is intended to match the leading maybe-underscore, +// prefixMatcher 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. -const patternPrefixMatcher = /^_?(\d+-)?/; +const prefixMatcher = /^_?(\d+-)?/; -// Pattern properties /** - * Pattern constructor + * Pattern constructor / Pattern properties + * + * Before changing functionalities of the pattern object please read the following pull requests + * to get more details about the behavior of the folder structure + * https://github.com/pattern-lab/patternlab-node/pull/992 + * https://github.com/pattern-lab/patternlab-node/pull/1016 + * * @constructor */ const Pattern = function(relPath, data, patternlab) { + this.relPath = path.normalize(relPath); // '00-atoms/00-global/00-colors.mustache' + /** * 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. @@ -20,89 +29,49 @@ const Pattern = function(relPath, data, patternlab) { * @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)); - const info = {}; - // 00-colors(.mustache) is subbed in 00-atoms-/00-global/00-colors - info.hasDir = - path.basename(pathObj.dir).replace(patternPrefixMatcher, '') === - pathObj.name.replace(patternPrefixMatcher, '') || - path.basename(pathObj.dir).replace(patternPrefixMatcher, '') === - pathObj.name.split('~')[0].replace(patternPrefixMatcher, ''); - - info.dir = info.hasDir ? pathObj.dir.split(path.sep).pop() : ''; - info.dirLevel = pathObj.dir.split(path.sep).length; + const pathObj = path.parse(this.relPath); + + const info = this.getPatternInfo(pathObj); - 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' - if ((this.subdir.match(/\w(?=\\)|\w(?=\/)/g) || []).length > 1) { - this.subdir = this.subdir.split(/\/|\\/, 2).join(path.sep); // '00-atoms/03-controls/00-button' -> '00-atoms/03-controls' - } this.fileExtension = pathObj.ext; // '.mustache' // this is the unique name, subDir + fileName (sans extension) - this.name = ''; - if (info.hasDir && info.dirLevel > 2) { - let variant = ''; - - if (this.fileName.indexOf('~') !== -1) { - variant = '-' + this.fileName.split('~')[1]; - } - this.name = this.subdir.replace(/[\/\\]/g, '-') + variant; - } else { - this.name = - this.subdir.replace(/[\/\\]/g, '-') + - '-' + - this.fileName.replace('~', '-'); // '00-atoms-00-global-00-colors' - } + // '00-atoms-00-global-00-colors' + this.name = `${info.shortNotation}-${this.fileName.replace('~', '-')}`; // the JSON used to render values in the pattern this.jsonFileData = data || {}; // strip leading "00-" from the file name and flip tildes to dashes this.patternBaseName = this.fileName - .replace(patternPrefixMatcher, '') + .replace(prefixMatcher, '') .replace('~', '-'); // 'colors' - // Fancy name. No idea how this works. 'Colors' - this.patternName = this.patternBaseName - .split('-') - .reduce(function(val, working) { - return ( - val.charAt(0).toUpperCase() + - val.slice(1) + - ' ' + - working.charAt(0).toUpperCase() + - working.slice(1) - ); - }, '') - .trim(); //this is the display name for the ui. strip numeric + hyphen prefixes + // Fancy name - Uppercase letters of pattern name partials. + // global-colors -> 'Global Colors' + // this is the display name for the ui. strip numeric + hyphen prefixes + this.patternName = _.startCase(this.patternBaseName); //00-atoms if needed - this.patternType = this.getDirLevel(0); + this.patternType = this.getDirLevel(0, info); // the top-level pattern group this pattern belongs to. 'atoms' - this.patternGroup = this.patternType.replace(patternPrefixMatcher, ''); + this.patternGroup = this.patternType.replace(prefixMatcher, ''); //00-colors if needed - this.patternSubType = this.getDirLevel(1); + this.patternSubType = this.getDirLevel(1, info); // the sub-group this pattern belongs to. - this.patternSubGroup = this.patternSubType.replace(patternPrefixMatcher, ''); // 'global' + this.patternSubGroup = this.patternSubType.replace(prefixMatcher, ''); // 'global' // the joined pattern group and subgroup directory - this.flatPatternPath = - info.hasDir && info.dirLevel > 2 - ? this.subdir - .replace(/[/\\]/g, '-') - .replace(new RegExp('-' + info.dir + '$'), '') - : this.subdir.replace(/[\/\\]/g, '-'); // '00-atoms-00-global' + this.flatPatternPath = info.shortNotation; // '00-atoms-00-global' // calculated path from the root of the public directory to the generated // (rendered!) html file for this pattern, to be shown in the iframe - this.patternLink = this.patternSectionSubtype - ? `$${this.name}/index.html` - : patternlab + this.patternLink = patternlab ? this.getPatternLink(patternlab, 'rendered') : null; @@ -112,11 +81,25 @@ const Pattern = function(relPath, data, patternlab) { // Let's calculate the verbose name ahead of time! We don't use path.sep here // on purpose. This isn't a file name! - this.verbosePartial = - this.subdir.split(path.sep).join('/') + '/' + this.fileName; + this.verbosePartial = `${info.shortNotation.split('-').join('/')}/${ + this.fileName + }`; - this.isPattern = true; + /** + * Definition of flat pattern: + * The flat pattern is a high level pattern which is attached directly to + * the main root folder or to a root directory. + * --- This --- + * root + * flatpattern + * --- OR That --- + * root + * molecules + * flatpattern + */ this.isFlatPattern = this.patternGroup === this.patternSubGroup; + + this.isPattern = true; this.patternState = ''; this.template = ''; this.patternPartialCode = ''; @@ -218,16 +201,55 @@ Pattern.prototype = { return this.engine.findPartial(partialString); }, - getDirLevel: function(level) { + getDirLevel: function(level, pathInfo) { const items = this.subdir.split(path.sep); + pathInfo.patternHasOwnDir && items.pop(); if (items[level]) { return items[level]; } else if (items[level - 1]) { return items[level - 1]; } else { - return ''; + // Im Not quite shure about that but its better than empty node + return 'root'; + } + }, + + /** + * Info contains information about pattern structure if it is a nested pattern + * or if it just a subbed folder structure. Its just used for internal purposes. + * Remember every pattern infomarion based on "this.*" will be used by other functions + * + * @param pathObj path.parse() object containing usefull path information + */ + getPatternInfo: pathObj => { + const info = { + // 00-colors(.mustache) is subbed in 00-atoms-/00-global/00-colors + patternHasOwnDir: + path.basename(pathObj.dir).replace(prefixMatcher, '') === + pathObj.name.replace(prefixMatcher, '') || + path.basename(pathObj.dir).replace(prefixMatcher, '') === + pathObj.name.split('~')[0].replace(prefixMatcher, ''), + }; + + info.dir = info.patternHasOwnDir ? pathObj.dir.split(path.sep).pop() : ''; + info.dirLevel = pathObj.dir.split(path.sep).filter(s => !!s).length; + + if (info.dirLevel === 0 || (info.dirLevel === 1 && info.patternHasOwnDir)) { + // -> ./ + info.shortNotation = 'root'; + } else if (info.dirLevel === 2 && info.patternHasOwnDir) { + // -> ./folder + info.shortNotation = path.dirname(pathObj.dir); + } else { + // -> ./folder/folder + info.shortNotation = pathObj.dir + .split(/\/|\\/, 2) + .join('-') + .replace(new RegExp(`-${info.dir}$`), ''); } + + return info; }, }; @@ -241,7 +263,7 @@ Pattern.createEmpty = function(customProps, patternlab) { if (customProps.relPath) { relPath = customProps.relPath; } else if (customProps.subdir && customProps.filename) { - relPath = customProps.subdir + path.sep + customProps.filename; + relPath = path.join(customProps.subdir, customProps.filename); } } diff --git a/packages/core/src/lib/ui_builder.js b/packages/core/src/lib/ui_builder.js index 5dcb36986..8b92b656c 100644 --- a/packages/core/src/lib/ui_builder.js +++ b/packages/core/src/lib/ui_builder.js @@ -3,8 +3,7 @@ const path = require('path'); const _ = require('lodash'); -const of = require('./object_factory'); -const Pattern = of.Pattern; +const Pattern = require('./object_factory').Pattern; const logger = require('./log'); const uikitExcludePattern = require('./uikitExcludePattern'); @@ -57,7 +56,7 @@ const ui_builder = function() { //add all if it does not exist yet if (!patternlab.viewAllPaths[pattern.patternGroup].all) { - patternlab.viewAllPaths[pattern.patternGroup].all = pattern.patternType; + patternlab.viewAllPaths[pattern.patternGroup].all = pattern.patternGroup; } } @@ -139,7 +138,7 @@ const ui_builder = function() { ]; if (docPattern) { docPattern.isDocPattern = true; - docPattern.order = -Number.MAX_SAFE_INTEGER; + docPattern.order = Number.MIN_SAFE_INTEGER; return docPattern; } @@ -147,21 +146,20 @@ const ui_builder = function() { docPattern = new Pattern.createEmpty( { name: pattern.flatPatternPath, - patternName: isSubtypePattern - ? pattern.patternSubGroup - : pattern.patternGroup, + patternName: _.startCase( + isSubtypePattern ? pattern.patternSubGroup : pattern.patternGroup + ), patternDesc: '', - patternPartial: - 'viewall-' + - pattern.patternGroup + - (isSubtypePattern ? '-' + pattern.patternSubGroup : ''), + patternPartial: `viewall-${pattern.patternGroup}${ + isSubtypePattern ? '-' + pattern.patternSubGroup : '' + }`, patternSectionSubtype: isSubtypePattern, - patternLink: pattern.flatPatternPath + path.sep + 'index.html', + patternLink: path.join(pattern.flatPatternPath, 'index.html'), isPattern: false, engine: null, flatPatternPath: pattern.flatPatternPath, isDocPattern: true, - order: -Number.MAX_SAFE_INTEGER, + order: Number.MIN_SAFE_INTEGER, }, patternlab ); @@ -177,9 +175,7 @@ const ui_builder = function() { function addPatternType(patternlab, pattern) { patternlab.patternTypes.push({ patternTypeLC: pattern.patternGroup.toLowerCase(), - patternTypeUC: - pattern.patternGroup.charAt(0).toUpperCase() + - pattern.patternGroup.slice(1), + patternTypeUC: _.startCase(pattern.patternGroup), patternType: pattern.patternType, patternTypeDash: pattern.patternGroup, //todo verify patternTypeItems: [], @@ -238,9 +234,7 @@ const ui_builder = function() { function addPatternSubType(patternlab, pattern) { const newSubType = { patternSubtypeLC: pattern.patternSubGroup.toLowerCase(), - patternSubtypeUC: - pattern.patternSubGroup.charAt(0).toUpperCase() + - pattern.patternSubGroup.slice(1), + patternSubtypeUC: _.startCase(pattern.patternSubGroup), patternSubtype: pattern.patternSubType, patternSubtypeDash: pattern.patternSubGroup, //todo verify patternSubtypeItems: [], @@ -258,31 +252,14 @@ const ui_builder = function() { * Creates a patternSubTypeItem object from a pattern * This is a menu item you click on * @param pattern - the pattern to derive the subtypeitem from - * @returns {{patternPartial: string, patternName: (*|string), patternState: string, patternSrcPath: string, patternPath: string}} + * @returns {{patternPartial: string, patternName: (*|string), patternState: string, patternPath: string}} */ function createPatternSubTypeItem(pattern) { - let patternPath = ''; - if (pattern.isFlatPattern) { - patternPath = - pattern.flatPatternPath + - '-' + - pattern.fileName + - '/' + - pattern.flatPatternPath + - '-' + - pattern.fileName + - '.html'; - } else { - patternPath = - pattern.flatPatternPath + '/' + pattern.flatPatternPath + '.html'; - } - return { patternPartial: pattern.patternPartial, patternName: pattern.patternName, patternState: pattern.patternState, - patternSrcPath: encodeURI(pattern.subdir + '/' + pattern.fileName), - patternPath: patternPath, + patternPath: pattern.patternLink, order: pattern.order, }; } @@ -336,18 +313,16 @@ const ui_builder = function() { ); } - if (!patternType.patternItems) { - patternType.patternItems = []; - } + patternType.patternItems = patternType.patternItems || []; if (isViewAllVariant) { if (!pattern.isFlatPattern) { //todo: it'd be nice if we could get this into createPatternSubTypeItem someday patternType.patternItems.push({ - patternPartial: 'viewall-' + pattern.patternGroup + '-all', - patternName: 'View All', - patternPath: encodeURI(pattern.patternType + '/index.html'), - order: -Number.MAX_SAFE_INTEGER, + patternPartial: `viewall-${pattern.patternGroup}-all`, + patternName: `View All ${_.startCase(pattern.patternGroup)}`, + patternPath: encodeURI(pattern.patternGroup + '/index.html'), + order: Number.MIN_SAFE_INTEGER, }); } } else { @@ -454,7 +429,7 @@ const ui_builder = function() { } //continue building navigation for nested patterns - if (pattern.patternGroup !== pattern.patternSubGroup) { + if (!pattern.isFlatPattern) { if ( !groupedPatterns.patternGroups[pattern.patternGroup][ pattern.patternSubGroup @@ -545,6 +520,7 @@ const ui_builder = function() { const styleGuideExcludes = patternlab.config.styleGuideExcludes || patternlab.config.styleguideExcludes; + const subTypePromises = _.map( _.values(patternGroup), (patternSubtypes, patternSubtype, originalPatternGroup) => { @@ -609,9 +585,10 @@ const ui_builder = function() { path.join( process.cwd(), uikit.outputDir, - paths.public.patterns + - p.flatPatternPath + - '/index.html' + path.join( + `${paths.public.patterns}${p.flatPatternPath}`, + 'index.html' + ) ), mainPageHeadHtml + viewAllHTML + footerHTML ); @@ -667,9 +644,10 @@ const ui_builder = function() { path.join( process.cwd(), uikit.outputDir, - paths.public.patterns + - anyPatternOfType.patternType + - '/index.html' + path.join( + `${paths.public.patterns}${patternType}`, + 'index.html' + ) ), mainPageHeadHtml + viewAllHTML + footerHTML ); @@ -740,7 +718,7 @@ const ui_builder = function() { const paths = patternlab.config.paths; const uikitPromises = _.map(patternlab.uikits, uikit => { - //determine which patterns should be included in the front-end rendering + // determine which patterns should be included in the front-end rendering const styleguidePatterns = groupPatterns(patternlab, uikit); return new Promise(resolve => { diff --git a/packages/core/test/object_factory_tests.js b/packages/core/test/object_factory_tests.js index 910c02d89..c41d3ba6e 100644 --- a/packages/core/test/object_factory_tests.js +++ b/packages/core/test/object_factory_tests.js @@ -79,8 +79,8 @@ tap.test( path.sep + 'colors.mustache' ); - test.equals(p.name, '00-atoms-00-global'); - test.equals(p.subdir, '00-atoms' + path.sep + '00-global'); + test.equals(p.name, '00-atoms-00-global-00-colors'); + test.equals(p.subdir, path.join('00-atoms', '00-global', '00-colors')); test.equals(p.fileName, 'colors'); test.equals(p.fileExtension, '.mustache'); test.equals(p.jsonFileData.d, 123); @@ -88,10 +88,12 @@ tap.test( test.equals(p.patternName, 'Colors'); test.equals( p.getPatternLink(pl), - '00-atoms-00-global' + path.sep + '00-atoms-00-global.rendered.html' + '00-atoms-00-global-00-colors' + + path.sep + + '00-atoms-00-global-00-colors.rendered.html' ); test.equals(p.patternGroup, 'atoms'); - test.equals(p.patternSubGroup, 'global'); //because of p.info.hasDir + test.equals(p.patternSubGroup, 'global'); test.equals(p.flatPatternPath, '00-atoms-00-global'); test.equals(p.patternPartial, 'atoms-colors'); test.equals(p.template, ''); @@ -106,14 +108,17 @@ tap.test( ); tap.test('test Pattern name for variants correctly initialzed', function(test) { - var p1 = new Pattern('00-atoms/00-global/colors~variant.mustache', { - d: 123, - }); - var p2 = new Pattern('00-atoms/00-global/colors~variant-minus.json', { + var p1 = new Pattern('00-atoms/00-global/00-colors/colors~variant.mustache', { d: 123, }); - test.equals(p1.name, '00-atoms-00-global-colors-variant'); - test.equals(p2.name, '00-atoms-00-global-colors-variant-minus'); + var p2 = new Pattern( + '00-atoms/00-global/00-colors/colors~variant-minus.json', + { + d: 123, + } + ); + test.equals(p1.name, '00-atoms-00-global-00-colors-variant'); + test.equals(p2.name, '00-atoms-00-global-00-colors-variant-minus'); test.end(); }); @@ -205,20 +210,11 @@ tap.test( d: 123, }); test.equals(p.getDirLevel(0, { hasDir: true, dirLevel: 2 }), '00-atoms'); - test.equals( - p.getDirLevel(1, { hasDir: true, dirLevel: 2 }), - '00-colors-alt' - ); + test.equals(p.getDirLevel(1, { hasDir: true, dirLevel: 2 }), '00-colors'); test.equals(p.getDirLevel(3, { hasDir: true, dirLevel: 2 }), ''); var p = new Pattern('00-colors-alt/colors-alt.mustache', { d: 123 }); - test.equals( - p.getDirLevel(0, { hasDir: true, dirLevel: 1 }), - '00-colors-alt' - ); - test.equals( - p.getDirLevel(1, { hasDir: true, dirLevel: 1 }), - '00-colors-alt' - ); + test.equals(p.getDirLevel(0, { hasDir: true, dirLevel: 1 }), ''); + test.equals(p.getDirLevel(1, { hasDir: true, dirLevel: 1 }), ''); test.equals(p.getDirLevel(3, { hasDir: true, dirLevel: 1 }), ''); test.end(); } diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js b/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js index af3d0bf26..15e89203d 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js @@ -415,7 +415,7 @@ class Nav extends BaseComponent { return ( {patternSubtype.patternSubtypeItems} From edc4b0cb22b78d1019395c3f228b59ec230ca03d Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Sun, 12 Apr 2020 21:35:29 +0200 Subject: [PATCH 02/16] Various changes to file and pattern creation - Fixed test cases incorrect - Fixed view all pages not generated - Fixed view all page could not be loaded - Fixed pattern ordering - Fixed subfolder patterns have invalid data - Fixed subfolder patterns are not rendered properly --- .prettierrc | 3 +- packages/core/patternlab-config.json | 4 + packages/core/src/lib/object_factory.js | 198 +++++--- packages/core/src/lib/parameter_hunter.js | 2 +- packages/core/src/lib/ui_builder.js | 447 +++++++++--------- packages/core/test/object_factory_tests.js | 124 +++-- packages/core/test/ui_builder_tests.js | 113 +++-- packages/edition-node/patternlab-config.json | 4 + .../engine-mustache/lib/engine_mustache.js | 24 +- .../scss/04-components/_pattern-category.scss | 11 +- .../src/scripts/components/pl-nav/pl-nav.js | 2 +- 11 files changed, 526 insertions(+), 406 deletions(-) diff --git a/.prettierrc b/.prettierrc index c1a6f6671..d81dbaeb5 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,5 @@ { "singleQuote": true, - "trailingComma": "es5" + "trailingComma": "es5", + "endOfLine": "auto" } diff --git a/packages/core/patternlab-config.json b/packages/core/patternlab-config.json index 39eed54fd..265e98b65 100644 --- a/packages/core/patternlab-config.json +++ b/packages/core/patternlab-config.json @@ -75,6 +75,10 @@ "patternExportPatternPartials": [], "patternExportPreserveDirectoryStructure": true, "patternExportRaw": false, + "patternTranslations": { + "view-all": "View all {groupName}", + "root-name": "Root" + }, "serverOptions": { "wait": 1000 }, diff --git a/packages/core/src/lib/object_factory.js b/packages/core/src/lib/object_factory.js index 83524a9c7..90c30112d 100644 --- a/packages/core/src/lib/object_factory.js +++ b/packages/core/src/lib/object_factory.js @@ -1,18 +1,27 @@ 'use strict'; -const patternEngines = require('./pattern_engines'); + +const _ = require('lodash'); const path = require('path'); +const patternEngines = require('./pattern_engines'); -// patternPrefixMatcher is intended to match the leading maybe-underscore, +// prefixMatcher 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. -const patternPrefixMatcher = /^_?(\d+-)?/; +const prefixMatcher = /^_?(\d+-)?/; -// Pattern properties /** - * Pattern constructor + * Pattern constructor / Pattern properties + * + * Before changing functionalities of the pattern object please read the following pull requests + * to get more details about the behavior of the folder structure + * https://github.com/pattern-lab/patternlab-node/pull/992 + * https://github.com/pattern-lab/patternlab-node/pull/1016 + * * @constructor */ const Pattern = function(relPath, data, patternlab) { + this.relPath = path.normalize(relPath); // '00-atoms/00-global/00-colors.mustache' + /** * 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. @@ -20,40 +29,26 @@ const Pattern = function(relPath, data, patternlab) { * @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)); - const info = {}; - // 00-colors(.mustache) is subbed in 00-atoms-/00-global/00-colors - info.hasDir = - path.basename(pathObj.dir).replace(patternPrefixMatcher, '') === - pathObj.name.replace(patternPrefixMatcher, '') || - path.basename(pathObj.dir).replace(patternPrefixMatcher, '') === - pathObj.name.split('~')[0].replace(patternPrefixMatcher, ''); - - info.dir = info.hasDir ? pathObj.dir.split(path.sep).pop() : ''; - info.dirLevel = pathObj.dir.split(path.sep).length; + const pathObj = path.parse(this.relPath); + + const info = this.getPatternInfo(pathObj, patternlab); - 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' - if ((this.subdir.match(/\w(?=\\)|\w(?=\/)/g) || []).length > 1) { - this.subdir = this.subdir.split(/\/|\\/, 2).join(path.sep); // '00-atoms/03-controls/00-button' -> '00-atoms/03-controls' - } this.fileExtension = pathObj.ext; // '.mustache' - // this is the unique name, subDir + fileName (sans extension) - this.name = ''; - if (info.hasDir && info.dirLevel > 2) { - let variant = ''; - - if (this.fileName.indexOf('~') !== -1) { - variant = '-' + this.fileName.split('~')[1]; - } - this.name = this.subdir.replace(/[\/\\]/g, '-') + variant; + // TODO: Remove if when droping ordering by prefix and keep else code + if (info.patternHasOwnDir) { + // Since there is still the requirement of having the numbers provided for sorting + // this will be required to keep the folder prefix and the variant name + // /00-atoms/00-global/00-colors/colors~varian.hbs + // -> 00-atoms-00-global-00-colors + this.name = `${info.shortNotation}-${path.parse(pathObj.dir).base}${ + this.fileName.indexOf('~') !== -1 ? '-' + this.fileName.split('~')[1] : '' + }`; } else { - this.name = - this.subdir.replace(/[\/\\]/g, '-') + - '-' + - this.fileName.replace('~', '-'); // '00-atoms-00-global-00-colors' + // this is the unique name, subDir + fileName (sans extension) + this.name = `${info.shortNotation}-${this.fileName.replace('~', '-')}`; } // the JSON used to render values in the pattern @@ -61,48 +56,32 @@ const Pattern = function(relPath, data, patternlab) { // strip leading "00-" from the file name and flip tildes to dashes this.patternBaseName = this.fileName - .replace(patternPrefixMatcher, '') + .replace(prefixMatcher, '') .replace('~', '-'); // 'colors' - // Fancy name. No idea how this works. 'Colors' - this.patternName = this.patternBaseName - .split('-') - .reduce(function(val, working) { - return ( - val.charAt(0).toUpperCase() + - val.slice(1) + - ' ' + - working.charAt(0).toUpperCase() + - working.slice(1) - ); - }, '') - .trim(); //this is the display name for the ui. strip numeric + hyphen prefixes + // Fancy name - Uppercase letters of pattern name partials. + // global-colors -> 'Global Colors' + // this is the display name for the ui. strip numeric + hyphen prefixes + this.patternName = _.startCase(this.patternBaseName); //00-atoms if needed - this.patternType = this.getDirLevel(0); + this.patternType = this.getDirLevel(0, info); // the top-level pattern group this pattern belongs to. 'atoms' - this.patternGroup = this.patternType.replace(patternPrefixMatcher, ''); + this.patternGroup = this.patternType.replace(prefixMatcher, ''); //00-colors if needed - this.patternSubType = this.getDirLevel(1); + this.patternSubType = this.getDirLevel(1, info); // the sub-group this pattern belongs to. - this.patternSubGroup = this.patternSubType.replace(patternPrefixMatcher, ''); // 'global' + this.patternSubGroup = this.patternSubType.replace(prefixMatcher, ''); // 'global' // the joined pattern group and subgroup directory - this.flatPatternPath = - info.hasDir && info.dirLevel > 2 - ? this.subdir - .replace(/[/\\]/g, '-') - .replace(new RegExp('-' + info.dir + '$'), '') - : this.subdir.replace(/[\/\\]/g, '-'); // '00-atoms-00-global' + this.flatPatternPath = info.shortNotation; // '00-atoms-00-global' // calculated path from the root of the public directory to the generated // (rendered!) html file for this pattern, to be shown in the iframe - this.patternLink = this.patternSectionSubtype - ? `$${this.name}/index.html` - : patternlab + this.patternLink = patternlab ? this.getPatternLink(patternlab, 'rendered') : null; @@ -112,11 +91,24 @@ const Pattern = function(relPath, data, patternlab) { // Let's calculate the verbose name ahead of time! We don't use path.sep here // on purpose. This isn't a file name! - this.verbosePartial = - this.subdir.split(path.sep).join('/') + '/' + this.fileName; + this.verbosePartial = `${info.shortNotation}/${this.fileName}`; + + /** + * Definition of flat pattern: + * The flat pattern is a high level pattern which is attached directly to + * the main root folder or to a root directory. + * --- This --- + * root + * flatpattern + * --- OR That --- + * root + * molecules + * flatpattern + */ + this.isFlatPattern = + this.patternGroup === this.patternSubGroup || !this.patternSubGroup; this.isPattern = true; - this.isFlatPattern = this.patternGroup === this.patternSubGroup; this.patternState = ''; this.template = ''; this.patternPartialCode = ''; @@ -125,7 +117,7 @@ const Pattern = function(relPath, data, patternlab) { this.lineageR = []; this.lineageRIndex = []; this.isPseudoPattern = false; - this.order = Number.MAX_SAFE_INTEGER; + this.order = 0; this.engine = patternEngines.getEngineForPattern(this); /** @@ -218,30 +210,86 @@ Pattern.prototype = { return this.engine.findPartial(partialString); }, - getDirLevel: function(level) { + getDirLevel: function(level, pathInfo) { const items = this.subdir.split(path.sep); + pathInfo.patternHasOwnDir && items.pop(); if (items[level]) { return items[level]; - } else if (items[level - 1]) { - return items[level - 1]; - } else { + } else if (level >= 1) { return ''; + } else { + // Im Not quite shure about that but its better than empty node + // TODO: verify + return pathInfo.patternlab && + pathInfo.patternlab.config.patternTranslations && + pathInfo.patternlab.config.patternTranslations['root-name'] + ? _.kebabCase( + pathInfo.patternlab.config.patternTranslations['root-name'] + ) + : 'root'; + } + }, + + /** + * Info contains information about pattern structure if it is a nested pattern + * or if it just a subbed folder structure. Its just used for internal purposes. + * Remember every pattern infomarion based on "this.*" will be used by other functions + * + * @param pathObj path.parse() object containing usefull path information + */ + getPatternInfo: (pathObj, patternlab) => { + const info = { + // 00-colors(.mustache) is subbed in 00-atoms-/00-global/00-colors + patternlab: patternlab, + patternHasOwnDir: + path.basename(pathObj.dir).replace(prefixMatcher, '') === + pathObj.name.replace(prefixMatcher, '') || + path.basename(pathObj.dir).replace(prefixMatcher, '') === + pathObj.name.split('~')[0].replace(prefixMatcher, ''), + }; + + info.dir = info.patternHasOwnDir ? pathObj.dir.split(path.sep).pop() : ''; + info.dirLevel = pathObj.dir.split(path.sep).filter(s => !!s).length; + + if (info.dirLevel === 0 || (info.dirLevel === 1 && info.patternHasOwnDir)) { + // -> ./ + info.shortNotation = 'root'; + } else if (info.dirLevel === 2 && info.patternHasOwnDir) { + // -> ./folder + info.shortNotation = path.dirname(pathObj.dir); + } else { + // -> ./folder/folder + info.shortNotation = pathObj.dir + .split(/\/|\\/, 2) + .join('-') + .replace(new RegExp(`-${info.dir}$`), ''); + info.verbosePartial = pathObj.dir + .split(/\/|\\/, 2) + .join('/') + .replace(new RegExp(`-${info.dir}$`), ''); } + + return info; }, }; // Pattern static methods -// factory: creates an empty Pattern for miscellaneous internal use, such as -// by list_item_hunter +/** + * factory: creates an empty Pattern for miscellaneous internal use, such as + * by list_item_hunter + * + * @param {Object} customProps Properties to apply to new pattern + * @param {Patternlab} patternlab Current patternlab instance + */ Pattern.createEmpty = function(customProps, patternlab) { let relPath = ''; if (customProps) { if (customProps.relPath) { relPath = customProps.relPath; } else if (customProps.subdir && customProps.filename) { - relPath = customProps.subdir + path.sep + customProps.filename; + relPath = path.join(customProps.subdir, customProps.filename); } } @@ -249,9 +297,11 @@ Pattern.createEmpty = function(customProps, patternlab) { return Object.assign(pattern, customProps); }; -// factory: creates an Pattern object on-demand from a hash; the hash accepts -// parameters that replace the positional parameters that the Pattern -// constructor takes. +/** + * factory: creates an Pattern object on-demand from a hash; the hash accepts + * parameters that replace the positional parameters that the Pattern + * constructor takes. + */ Pattern.create = function(relPath, data, customProps, patternlab) { const newPattern = new Pattern(relPath || '', data || null, patternlab); return Object.assign(newPattern, customProps); diff --git a/packages/core/src/lib/parameter_hunter.js b/packages/core/src/lib/parameter_hunter.js index eeec121dc..aa2ce38dc 100644 --- a/packages/core/src/lib/parameter_hunter.js +++ b/packages/core/src/lib/parameter_hunter.js @@ -248,7 +248,7 @@ const parameter_hunter = function() { //compile this partial immeadiately, essentially consuming it. function findparameters(pattern, patternlab) { if (pattern.parameteredPartials && pattern.parameteredPartials.length > 0) { - logger.debug(`processing patternParameters for ${pattern.partialName}`); + logger.debug(`processing patternParameters for ${pattern.patternName}`); return pattern.parameteredPartials.reduce((previousPromise, pMatch) => { return previousPromise diff --git a/packages/core/src/lib/ui_builder.js b/packages/core/src/lib/ui_builder.js index 5dcb36986..148a872aa 100644 --- a/packages/core/src/lib/ui_builder.js +++ b/packages/core/src/lib/ui_builder.js @@ -3,12 +3,11 @@ const path = require('path'); const _ = require('lodash'); -const of = require('./object_factory'); -const Pattern = of.Pattern; +const Pattern = require('./object_factory').Pattern; const logger = require('./log'); const uikitExcludePattern = require('./uikitExcludePattern'); -//these are mocked in unit tests, so let them be overridden +// these are mocked in unit tests, so let them be overridden let render = require('./render'); //eslint-disable-line prefer-const let fs = require('fs-extra'); //eslint-disable-line prefer-const let buildFooter = require('./buildFooter'); //eslint-disable-line prefer-const @@ -26,7 +25,7 @@ const ui_builder = function() { patternlab.patternPaths[pattern.patternGroup] = {}; } - //only add real patterns + // only add real patterns if (pattern.isPattern && !pattern.isDocPattern) { patternlab.patternPaths[pattern.patternGroup][pattern.patternBaseName] = pattern.name; @@ -44,20 +43,18 @@ const ui_builder = function() { } if ( - !patternlab.viewAllPaths[pattern.patternGroup][pattern.patternSubGroup] + !patternlab.viewAllPaths[pattern.patternGroup][pattern.patternSubGroup] && + pattern.patternSubGroup ) { + // note these retain any number prefixes if present, because these paths match the filesystem patternlab.viewAllPaths[pattern.patternGroup][ pattern.patternSubGroup - ] = {}; + ] = `${pattern.patternType}-${pattern.patternSubType}`; } - //note these retain any number prefixes if present, because these paths match the filesystem - patternlab.viewAllPaths[pattern.patternGroup][pattern.patternSubGroup] = - pattern.patternType + '-' + pattern.patternSubType; - - //add all if it does not exist yet + // add all if it does not exist yet if (!patternlab.viewAllPaths[pattern.patternGroup].all) { - patternlab.viewAllPaths[pattern.patternGroup].all = pattern.patternType; + patternlab.viewAllPaths[pattern.patternGroup].all = pattern.patternGroup; } } @@ -89,7 +86,7 @@ const ui_builder = function() { return true; } - //this is meant to be a homepage that is not present anywhere else + // this is meant to be a homepage that is not present anywhere else isOmitted = pattern.patternPartial === patternlab.config.defaultPattern; if (isOmitted) { logger.info( @@ -99,7 +96,7 @@ const ui_builder = function() { return true; } - //this pattern is contained with a directory prefixed with an underscore (a handy way to hide whole directories from the nav + // this pattern is contained with a directory prefixed with an underscore (a handy way to hide whole directories from the nav isOmitted = pattern.relPath.charAt(0) === '_' || pattern.relPath.indexOf(path.sep + '_') > -1; @@ -110,7 +107,7 @@ const ui_builder = function() { return true; } - //this pattern is a head or foot pattern + // this pattern is a head or foot pattern isOmitted = pattern.isMetaPattern; if (isOmitted) { logger.info( @@ -119,7 +116,7 @@ const ui_builder = function() { return true; } - //yay, let's include this on the front end + // yay, let's include this on the front end return isOmitted; } @@ -131,7 +128,7 @@ const ui_builder = function() { * @returns the found or created pattern object */ function injectDocumentationBlock(pattern, patternlab, isSubtypePattern) { - //first see if loadPattern processed one already + // first see if loadPattern processed one already let docPattern = patternlab.subtypePatterns[ pattern.patternGroup + @@ -139,29 +136,31 @@ const ui_builder = function() { ]; if (docPattern) { docPattern.isDocPattern = true; - docPattern.order = -Number.MAX_SAFE_INTEGER; + docPattern.order = Number.MIN_SAFE_INTEGER; return docPattern; } - //if not, create one now + // if not, create one now docPattern = new Pattern.createEmpty( { name: pattern.flatPatternPath, - patternName: isSubtypePattern - ? pattern.patternSubGroup - : pattern.patternGroup, + patternName: _.startCase( + isSubtypePattern ? pattern.patternSubGroup : pattern.patternGroup + ), patternDesc: '', - patternPartial: - 'viewall-' + - pattern.patternGroup + - (isSubtypePattern ? '-' + pattern.patternSubGroup : ''), - patternSectionSubtype: isSubtypePattern, - patternLink: pattern.flatPatternPath + path.sep + 'index.html', + patternPartial: `viewall-${pattern.patternGroup}-${ + isSubtypePattern ? pattern.patternSubGroup : 'all' + }`, + patternSectionSubtype: true, + patternLink: path.join( + isSubtypePattern ? pattern.flatPatternPath : pattern.patternGroup, + 'index.html' + ), isPattern: false, engine: null, flatPatternPath: pattern.flatPatternPath, isDocPattern: true, - order: -Number.MAX_SAFE_INTEGER, + order: Number.MIN_SAFE_INTEGER, }, patternlab ); @@ -177,9 +176,7 @@ const ui_builder = function() { function addPatternType(patternlab, pattern) { patternlab.patternTypes.push({ patternTypeLC: pattern.patternGroup.toLowerCase(), - patternTypeUC: - pattern.patternGroup.charAt(0).toUpperCase() + - pattern.patternGroup.slice(1), + patternTypeUC: _.startCase(pattern.patternGroup), patternType: pattern.patternType, patternTypeDash: pattern.patternGroup, //todo verify patternTypeItems: [], @@ -238,9 +235,7 @@ const ui_builder = function() { function addPatternSubType(patternlab, pattern) { const newSubType = { patternSubtypeLC: pattern.patternSubGroup.toLowerCase(), - patternSubtypeUC: - pattern.patternSubGroup.charAt(0).toUpperCase() + - pattern.patternSubGroup.slice(1), + patternSubtypeUC: _.startCase(pattern.patternSubGroup), patternSubtype: pattern.patternSubType, patternSubtypeDash: pattern.patternSubGroup, //todo verify patternSubtypeItems: [], @@ -258,32 +253,16 @@ const ui_builder = function() { * Creates a patternSubTypeItem object from a pattern * This is a menu item you click on * @param pattern - the pattern to derive the subtypeitem from - * @returns {{patternPartial: string, patternName: (*|string), patternState: string, patternSrcPath: string, patternPath: string}} + * @returns {{patternPartial: string, patternName: (*|string), patternState: string, patternPath: string}} */ function createPatternSubTypeItem(pattern) { - let patternPath = ''; - if (pattern.isFlatPattern) { - patternPath = - pattern.flatPatternPath + - '-' + - pattern.fileName + - '/' + - pattern.flatPatternPath + - '-' + - pattern.fileName + - '.html'; - } else { - patternPath = - pattern.flatPatternPath + '/' + pattern.flatPatternPath + '.html'; - } - return { patternPartial: pattern.patternPartial, patternName: pattern.patternName, patternState: pattern.patternState, - patternSrcPath: encodeURI(pattern.subdir + '/' + pattern.fileName), - patternPath: patternPath, - order: pattern.order, + patternPath: pattern.patternLink, + name: pattern.name, + order: Number(pattern.order) || 0, // Failsave is someone entered a string }; } @@ -309,7 +288,8 @@ const ui_builder = function() { patternPath: encodeURI(pattern.flatPatternPath + '/index.html'), patternType: pattern.patternType, patternSubtype: pattern.patternSubtype, - order: 0, + name: pattern.flatPatternPath, + order: Number.MAX_SAFE_INTEGER, }; } else { newSubTypeItem = createPatternSubTypeItem(pattern); @@ -336,20 +316,22 @@ const ui_builder = function() { ); } - if (!patternType.patternItems) { - patternType.patternItems = []; - } - + patternType.patternItems = patternType.patternItems || []; if (isViewAllVariant) { - if (!pattern.isFlatPattern) { - //todo: it'd be nice if we could get this into createPatternSubTypeItem someday - patternType.patternItems.push({ - patternPartial: 'viewall-' + pattern.patternGroup + '-all', - patternName: 'View All', - patternPath: encodeURI(pattern.patternType + '/index.html'), - order: -Number.MAX_SAFE_INTEGER, - }); - } + patternType.patternItems.push({ + patternPartial: `viewall-${pattern.patternGroup}-all`, + patternName: + patternlab.config.patternTranslations && + patternlab.config.patternTranslations['view-all'] + ? patternlab.config.patternTranslations['view-all'].replace( + '{groupName}', + _.startCase(pattern.patternGroup) + ) + : `View all ${_.startCase(pattern.patternGroup)}`, + patternPath: encodeURI(pattern.patternGroup + '/index.html'), + name: pattern.patternGroup, + order: Number.MAX_SAFE_INTEGER, + }); } else { patternType.patternItems.push(createPatternSubTypeItem(pattern)); } @@ -359,14 +341,6 @@ const ui_builder = function() { ]); } - // function getPatternItems(patternlab, patternType) { - // var patternType = _.find(patternlab.patternTypes, ['patternTypeLC', patternType]); - // if (patternType) { - // return patternType.patternItems; - // } - // return []; - // } - /** * Sorts patterns based on order property found within pattern markdown, falling back on name. * @param patternsArray - patterns to sort @@ -385,7 +359,7 @@ const ui_builder = function() { aOrder = Number.MAX_SAFE_INTEGER; } - //alwasy return a docPattern first + // alwasy return a docPattern first if (a.isDocPattern && !b.isDocPattern) { return -1; } @@ -394,8 +368,8 @@ const ui_builder = function() { 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 + // 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 @@ -408,7 +382,7 @@ const ui_builder = function() { } } - //if we get this far, we can sort safely + // if we get this far, we can sort safely if (aOrder && bOrder) { if (aOrder > bOrder) { return 1; @@ -433,7 +407,7 @@ const ui_builder = function() { }; _.forEach(patternlab.patterns, function(pattern) { - //ignore patterns we can omit from rendering directly + // ignore patterns we can omit from rendering directly pattern.omitFromStyleguide = isPatternExcluded( pattern, patternlab, @@ -447,14 +421,12 @@ const ui_builder = function() { groupedPatterns.patternGroups[pattern.patternGroup] = {}; pattern.isSubtypePattern = false; addPatternType(patternlab, pattern); - - //todo: Pattern Type View All and Documentation - //groupedPatterns.patternGroups[pattern.patternGroup]['viewall-' + pattern.patternGroup] = injectDocumentationBlock(pattern, patternlab, false); addPatternItem(patternlab, pattern, true); + addToViewAllPaths(patternlab, pattern); } - //continue building navigation for nested patterns - if (pattern.patternGroup !== pattern.patternSubGroup) { + // continue building navigation for nested patterns + if (!pattern.isFlatPattern) { if ( !groupedPatterns.patternGroups[pattern.patternGroup][ pattern.patternSubGroup @@ -491,6 +463,23 @@ const ui_builder = function() { return groupedPatterns; } + /** + * Search all flat patterns of a specific pattern type + * + * @param {Patternlab} patternlab Current patternlab instance + * @param {String} patternType indicator which patterns to search for + */ + function getFlatPatternItems(patternlab, patternType) { + const patterns = _.filter( + patternlab.patterns, + pattern => pattern.patternGroup === patternType && pattern.isFlatPattern + ); + if (patterns) { + return sortPatterns(patterns); + } + return []; + } + /** * Takes a set of patterns and builds a viewall HTML page for them * Used by the type and subtype viewall sets @@ -501,15 +490,15 @@ const ui_builder = function() { */ function buildViewAllHTML(patternlab, patterns, patternPartial, uikit) { return render( - Pattern.createEmpty({ extendedTemplate: uikit.viewAll }), + Pattern.createEmpty({ extendedTemplate: uikit.viewAll }, patternlab), { - //data + // data partials: patterns, patternPartial: 'viewall-' + patternPartial, cacheBuster: patternlab.cacheBuster, }, { - //templates + // templates patternSection: uikit.patternSection, patternSectionSubtype: uikit.patternSectionSubType, } @@ -534,57 +523,59 @@ const ui_builder = function() { ) { const paths = patternlab.config.paths; let patterns = []; - let writeViewAllFile = true; - //loop through the grouped styleguide patterns, building at each level + // loop through the grouped styleguide patterns, building at each level const allPatternTypePromises = _.map( styleguidePatterns.patternGroups, (patternGroup, patternType) => { let typePatterns = []; let styleguideTypePatterns = []; - const styleGuideExcludes = - patternlab.config.styleGuideExcludes || - patternlab.config.styleguideExcludes; + const styleGuideExcludes = patternlab.config.styleGuideExcludes || []; + + /** + * View all pages for subgroups + */ const subTypePromises = _.map( _.values(patternGroup), (patternSubtypes, patternSubtype, originalPatternGroup) => { let p; - const samplePattern = _.find(patternSubtypes, st => { - return !st.patternPartial.startsWith('viewall-'); - }); + const samplePattern = _.find( + patternSubtypes, + st => !st.patternPartial.startsWith('viewall-') + ); const patternName = Object.keys( _.values(originalPatternGroup)[patternSubtype] )[1]; const patternPartial = patternType + '-' + samplePattern.patternSubType; - //do not create a viewall page for flat patterns + // do not create a viewall page for flat patterns if (patternType === patternName) { - writeViewAllFile = false; logger.debug( `skipping ${patternType} as flat patterns do not have view all pages` ); return Promise.resolve(); } - //render the footer needed for the viewall template + // render the footer needed for the viewall template return buildFooter(patternlab, `viewall-${patternPartial}`, uikit) .then(footerHTML => { - //render the viewall template by finding these smallest subtype-grouped patterns + // render the viewall template by finding these smallest subtype-grouped patterns const subtypePatterns = sortPatterns(_.values(patternSubtypes)); - //determine if we should write at this time by checking if these are flat patterns or grouped patterns + // determine if we should write at this time by checking if these are flat patterns or grouped patterns p = _.find(subtypePatterns, function(pat) { return pat.isDocPattern; }); - //determine if we should omit this subpatterntype completely from the viewall page + // determine if we should omit this subpatterntype completely from the viewall page const omitPatternType = styleGuideExcludes && styleGuideExcludes.length && - _.some(styleGuideExcludes, function(exclude) { - return exclude === patternType + '/' + patternName; - }); + _.some( + styleGuideExcludes, + exclude => exclude === `${patternType}/${patternName}` + ); if (omitPatternType) { logger.debug( `Omitting ${patternType}/${patternName} from building a viewall page because its patternSubGroup is specified in styleguideExcludes.` @@ -597,7 +588,7 @@ const ui_builder = function() { typePatterns = typePatterns.concat(subtypePatterns); - //render the viewall template for the subtype + // render the viewall template for the subtype return buildViewAllHTML( patternlab, subtypePatterns, @@ -609,9 +600,10 @@ const ui_builder = function() { path.join( process.cwd(), uikit.outputDir, - paths.public.patterns + - p.flatPatternPath + - '/index.html' + path.join( + `${paths.public.patterns}${p.flatPatternPath}`, + 'index.html' + ) ), mainPageHeadHtml + viewAllHTML + footerHTML ); @@ -621,96 +613,92 @@ const ui_builder = function() { logger.error('Error building ViewAllHTML'); }); }) - .then(() => { - //do not create a viewall page for flat patterns - if (!writeViewAllFile || !p) { + .catch(reason => { + console.log(reason); + logger.error('Error building footer HTML'); + }); + } + ); + + /** + * View all pages for goups + */ + return Promise.all(subTypePromises) + .then(() => { + // render the footer needed for the viewall template + return buildFooter(patternlab, `viewall-${patternType}-all`, uikit) + .then(footerHTML => { + const sortedFlatPatterns = getFlatPatternItems( + patternlab, + patternType + ); + + // Check if this is a flat pattern group + typePatterns = sortedFlatPatterns.concat(typePatterns); + + // get the appropriate patternType + const anyPatternOfType = _.find(typePatterns, function(pat) { + return pat.patternType && pat.patternType !== ''; + }); + + if (!anyPatternOfType) { logger.debug( `skipping ${patternType} as flat patterns do not have view all pages` ); - return Promise.resolve(); + return Promise.resolve([]); } - //render the footer needed for the viewall template - return buildFooter( + // render the viewall template for the type + return buildViewAllHTML( patternlab, - 'viewall-' + patternType + '-all', + typePatterns, + patternType, uikit ) - .then(footerHTML => { - //add any flat patterns - //todo this isn't quite working yet - //typePatterns = typePatterns.concat(getPatternItems(patternlab, patternType)); - - //get the appropriate patternType - const anyPatternOfType = _.find(typePatterns, function( - pat - ) { - return pat.patternType && pat.patternType !== ''; - }); - - if (!anyPatternOfType) { + .then(viewAllHTML => { + fs.outputFileSync( + path.join( + process.cwd(), + uikit.outputDir, + path.join( + `${paths.public.patterns}${patternType}`, + 'index.html' + ) + ), + mainPageHeadHtml + viewAllHTML + footerHTML + ); + + // determine if we should omit this patterntype completely from the viewall page + const omitPatternType = + styleGuideExcludes && + styleGuideExcludes.length && + _.some(styleGuideExcludes, function(exclude) { + return exclude === patternType; + }); + if (omitPatternType) { logger.debug( - `skipping ${patternType} as flat patterns do not have view all pages` + `Omitting ${patternType} from building a viewall page because its patternGroup is specified in styleguideExcludes.` ); - return Promise.resolve(); + } else { + patterns = sortedFlatPatterns; + patterns = patterns.concat(styleguideTypePatterns); } - - //render the viewall template for the type - return buildViewAllHTML( - patternlab, - typePatterns, - patternType, - uikit - ) - .then(viewAllHTML => { - fs.outputFileSync( - path.join( - process.cwd(), - uikit.outputDir, - paths.public.patterns + - anyPatternOfType.patternType + - '/index.html' - ), - mainPageHeadHtml + viewAllHTML + footerHTML - ); - - //determine if we should omit this patterntype completely from the viewall page - const omitPatternType = - styleGuideExcludes && - styleGuideExcludes.length && - _.some(styleGuideExcludes, function(exclude) { - return exclude === patternType; - }); - if (omitPatternType) { - logger.debug( - `Omitting ${patternType} from building a viewall page because its patternGroup is specified in styleguideExcludes.` - ); - } else { - patterns = patterns.concat(styleguideTypePatterns); - } - return Promise.resolve(patterns); - }) - .catch(reason => { - console.log(reason); - logger.error('Error building ViewAllHTML'); - }); + return Promise.resolve(patterns); }) .catch(reason => { console.log(reason); - logger.error('Error building footerHTML'); + logger.error('Error building ViewAllHTML'); }); }) .catch(reason => { console.log(reason); - logger.error('Error building footer HTML'); + logger.error('Error building footerHTML'); }); - } - ); - - return Promise.all(subTypePromises).catch(reason => { - console.log(reason); - logger.error('Error during buildViewAllPages'); - }); + }) + .catch(reason => { + console.log(reason); + logger.error('Error during buildViewAllPages'); + }); } ); @@ -722,6 +710,8 @@ const ui_builder = function() { /** * Reset any global data we use between builds to guard against double adding things + * + * @param {Patternlab} patternlab Actual patternlab instance */ function resetUIBuilderState(patternlab) { patternlab.patternPaths = {}; @@ -729,8 +719,32 @@ const ui_builder = function() { patternlab.patternTypes = []; } + /** + * Uniques all generated patterns and groups, also adds a group document pattern before + * each group. Used for generating view all page and all its pattern. + * + * @param {[Pattern[]]} allPatterns All generated patterns + * @param {Patternlab} patternlab Actual patternlab instance + */ + function uniqueAllPatterns(allPatterns, patternlab) { + return _.uniq( + _.flatMapDeep( + _.map(allPatterns, patterns => [ + injectDocumentationBlock( + _.find(patterns, p => !p.patternPartial.startsWith('viewall-')), + patternlab, + false + ), + ...patterns, + ]), + pattern => pattern + ) + ); + } + /** * The main entry point for ui_builder + * * @param patternlab - global data store * @returns {Promise} a promise fulfilled when build is complete */ @@ -740,13 +754,13 @@ const ui_builder = function() { const paths = patternlab.config.paths; const uikitPromises = _.map(patternlab.uikits, uikit => { - //determine which patterns should be included in the front-end rendering + // determine which patterns should be included in the front-end rendering const styleguidePatterns = groupPatterns(patternlab, uikit); return new Promise(resolve => { - //set the pattern-specific header by compiling the general-header with data, and then adding it to the meta header + // set the pattern-specific header by compiling the general-header with data, and then adding it to the meta header const headerPromise = render( - Pattern.createEmpty({ extendedTemplate: uikit.header }), + Pattern.createEmpty({ extendedTemplate: uikit.header }, patternlab), { cacheBuster: patternlab.cacheBuster, } @@ -762,9 +776,9 @@ const ui_builder = function() { logger.error('error during header render()'); }); - //set the pattern-specific footer by compiling the general-footer with data, and then adding it to the meta footer + // set the pattern-specific footer by compiling the general-footer with data, and then adding it to the meta footer const footerPromise = render( - Pattern.createEmpty({ extendedTemplate: uikit.footer }), + Pattern.createEmpty({ extendedTemplate: uikit.footer }, patternlab), { patternData: '{}', cacheBuster: patternlab.cacheBuster, @@ -782,7 +796,7 @@ const ui_builder = function() { return Promise.all([headerPromise, footerPromise]).then( headFootPromiseResults => { - //build the viewall pages + // build the viewall pages return buildViewAllPages( headFootPromiseResults[0], @@ -791,24 +805,26 @@ const ui_builder = function() { uikit ) .then(allPatterns => { - //todo track down why we need to make this unique in the first place - const uniquePatterns = _.uniq( - _.flatMapDeep(allPatterns, pattern => { - return pattern; - }) + // todo track down why we need to make this unique in the first place + const uniquePatterns = uniqueAllPatterns( + allPatterns, + patternlab ); - //add the defaultPattern if we found one + // add the defaultPattern if we found one if (patternlab.defaultPattern) { uniquePatterns.push(patternlab.defaultPattern); addToPatternPaths(patternlab, patternlab.defaultPattern); } - //build the main styleguide page + // build the main styleguide page return render( - Pattern.createEmpty({ - extendedTemplate: uikit.viewAll, - }), + Pattern.createEmpty( + { + extendedTemplate: uikit.viewAll, + }, + patternlab + ), { partials: uniquePatterns, }, @@ -834,7 +850,7 @@ const ui_builder = function() { logger.info('Built Pattern Lab front end'); - //move the index file from its asset location into public root + // move the index file from its asset location into public root let patternlabSiteHtml; try { patternlabSiteHtml = fs.readFileSync( @@ -864,7 +880,7 @@ const ui_builder = function() { patternlabSiteHtml ); - //write out patternlab.data object to be read by the client + // write out patternlab.data object to be read by the client exportData(patternlab); resolve(); }) @@ -885,31 +901,12 @@ const ui_builder = function() { } return { - buildFrontend: function(patternlab) { - return buildFrontend(patternlab); - }, - isPatternExcluded: function(pattern, patternlab, uikit) { - return isPatternExcluded(pattern, patternlab, uikit); - }, - groupPatterns: function(patternlab, uikit) { - return groupPatterns(patternlab, uikit); - }, - resetUIBuilderState: function(patternlab) { - resetUIBuilderState(patternlab); - }, - buildViewAllPages: function( - mainPageHeadHtml, - patternlab, - styleguidePatterns, - uikit - ) { - return buildViewAllPages( - mainPageHeadHtml, - patternlab, - styleguidePatterns, - uikit - ); - }, + buildFrontend: buildFrontend, + isPatternExcluded: isPatternExcluded, + groupPatterns: groupPatterns, + resetUIBuilderState: resetUIBuilderState, + uniqueAllPatterns: uniqueAllPatterns, + buildViewAllPages: buildViewAllPages, }; }; diff --git a/packages/core/test/object_factory_tests.js b/packages/core/test/object_factory_tests.js index 910c02d89..b5835f417 100644 --- a/packages/core/test/object_factory_tests.js +++ b/packages/core/test/object_factory_tests.js @@ -79,8 +79,8 @@ tap.test( path.sep + 'colors.mustache' ); - test.equals(p.name, '00-atoms-00-global'); - test.equals(p.subdir, '00-atoms' + path.sep + '00-global'); + test.equals(p.name, '00-atoms-00-global-00-colors'); + test.equals(p.subdir, path.join('00-atoms', '00-global', '00-colors')); test.equals(p.fileName, 'colors'); test.equals(p.fileExtension, '.mustache'); test.equals(p.jsonFileData.d, 123); @@ -88,10 +88,12 @@ tap.test( test.equals(p.patternName, 'Colors'); test.equals( p.getPatternLink(pl), - '00-atoms-00-global' + path.sep + '00-atoms-00-global.rendered.html' + '00-atoms-00-global-00-colors' + + path.sep + + '00-atoms-00-global-00-colors.rendered.html' ); test.equals(p.patternGroup, 'atoms'); - test.equals(p.patternSubGroup, 'global'); //because of p.info.hasDir + test.equals(p.patternSubGroup, 'global'); test.equals(p.flatPatternPath, '00-atoms-00-global'); test.equals(p.patternPartial, 'atoms-colors'); test.equals(p.template, ''); @@ -106,14 +108,17 @@ tap.test( ); tap.test('test Pattern name for variants correctly initialzed', function(test) { - var p1 = new Pattern('00-atoms/00-global/colors~variant.mustache', { - d: 123, - }); - var p2 = new Pattern('00-atoms/00-global/colors~variant-minus.json', { + var p1 = new Pattern('00-atoms/00-global/00-colors/colors~variant.mustache', { d: 123, }); - test.equals(p1.name, '00-atoms-00-global-colors-variant'); - test.equals(p2.name, '00-atoms-00-global-colors-variant-minus'); + var p2 = new Pattern( + '00-atoms/00-global/00-colors/colors~variant-minus.json', + { + d: 123, + } + ); + test.equals(p1.name, '00-atoms-00-global-00-colors-variant'); + test.equals(p2.name, '00-atoms-00-global-00-colors-variant-minus'); test.end(); }); @@ -177,17 +182,17 @@ tap.test('test Pattern get dir level no separated pattern directory', function( ) { var p = new Pattern('00-atoms/00-global/00-colors-alt.mustache', { d: 123 }); console.log(p); - test.equals(p.getDirLevel(0, { hasDir: false, dirLevel: 2 }), '00-atoms'); - test.equals(p.getDirLevel(1, { hasDir: false, dirLevel: 2 }), '00-global'); - test.equals(p.getDirLevel(3, { hasDir: false, dirLevel: 2 }), ''); + test.equals(p.getDirLevel(0, { patternHasOwnDir: false }), '00-atoms'); + test.equals(p.getDirLevel(1, { patternHasOwnDir: false }), '00-global'); + test.equals(p.getDirLevel(2, { patternHasOwnDir: false }), ''); // There is no third level var p = new Pattern('00-atoms/00-colors-alt.mustache', { d: 123 }); - test.equals(p.getDirLevel(0, { hasDir: false, dirLevel: 1 }), '00-atoms'); - test.equals(p.getDirLevel(1, { hasDir: false, dirLevel: 1 }), '00-atoms'); - test.equals(p.getDirLevel(3, { hasDir: false, dirLevel: 1 }), ''); + test.equals(p.getDirLevel(0, { patternHasOwnDir: false }), '00-atoms'); + test.equals(p.getDirLevel(1, { patternHasOwnDir: false }), ''); // There is no second level + test.equals(p.getDirLevel(2, { patternHasOwnDir: false }), ''); // There is no third level var p = new Pattern('00-colors-alt.mustache', { d: 123 }); - test.equals(p.getDirLevel(0, { hasDir: false, dirLevel: 0 }), ''); - test.equals(p.getDirLevel(1, { hasDir: false, dirLevel: 0 }), ''); - test.equals(p.getDirLevel(3, { hasDir: false, dirLevel: 0 }), ''); + test.equals(p.getDirLevel(0, { patternHasOwnDir: false }), 'root'); // No first level means root + test.equals(p.getDirLevel(1, { patternHasOwnDir: false }), ''); // There is no second level + test.equals(p.getDirLevel(2, { patternHasOwnDir: false }), ''); // There is no third leveL test.end(); }); @@ -198,32 +203,79 @@ tap.test( '00-atoms/00-global/00-colors-alt/colors-alt.mustache', { d: 123 } ); - test.equals(p.getDirLevel(0, { hasDir: true, dirLevel: 3 }), '00-atoms'); - test.equals(p.getDirLevel(1, { hasDir: true, dirLevel: 3 }), '00-global'); - test.equals(p.getDirLevel(3, { hasDir: true, dirLevel: 3 }), ''); + test.equals(p.getDirLevel(0, { patternHasOwnDir: true }), '00-atoms'); + test.equals(p.getDirLevel(1, { patternHasOwnDir: true }), '00-global'); + test.equals(p.getDirLevel(2, { patternHasOwnDir: true }), ''); // There is no third level + var p = new Pattern('00-atoms/00-colors-alt/colors-alt.mustache', { d: 123, }); - test.equals(p.getDirLevel(0, { hasDir: true, dirLevel: 2 }), '00-atoms'); - test.equals( - p.getDirLevel(1, { hasDir: true, dirLevel: 2 }), - '00-colors-alt' - ); - test.equals(p.getDirLevel(3, { hasDir: true, dirLevel: 2 }), ''); + test.equals(p.getDirLevel(0, { patternHasOwnDir: true }), '00-atoms'); + test.equals(p.getDirLevel(1, { patternHasOwnDir: true }), ''); // There is no second level + test.equals(p.getDirLevel(2, { patternHasOwnDir: true }), ''); // There is no third level + var p = new Pattern('00-colors-alt/colors-alt.mustache', { d: 123 }); - test.equals( - p.getDirLevel(0, { hasDir: true, dirLevel: 1 }), - '00-colors-alt' - ); - test.equals( - p.getDirLevel(1, { hasDir: true, dirLevel: 1 }), - '00-colors-alt' + test.equals(p.getDirLevel(0, { patternHasOwnDir: true }), 'root'); // No first level means root + test.equals(p.getDirLevel(1, { patternHasOwnDir: true }), ''); // There is no second level + test.equals(p.getDirLevel(2, { patternHasOwnDir: true }), ''); // There is no third leveL + + var p = new Pattern( + '00-atoms/00-global/00-colors-alt/colors-alt~variant.mustache', + { d: 123 } ); - test.equals(p.getDirLevel(3, { hasDir: true, dirLevel: 1 }), ''); + test.equals(p.name, '00-atoms-00-global-00-colors-alt-variant'); + test.equals(p.flatPatternPath, '00-atoms-00-global'); + test.equals(p.patternBaseName, 'colors-alt-variant'); + test.end(); } ); +tap.test('test Patterns that are nested deeper without own directory', function( + test +) { + var p = new Pattern( + '00-atoms/00-global/00-random-folder/00-colors-alt.mustache', + { + d: 123, + } + ); + test.equals(p.name, '00-atoms-00-global-00-colors-alt'); + test.equals(p.flatPatternPath, '00-atoms-00-global'); + + var p = new Pattern( + '00-atoms/00-global/00-random-folder/00-another-folder/00-colors-alt.mustache', + { + d: 123, + } + ); + test.equals(p.name, '00-atoms-00-global-00-colors-alt'); + test.equals(p.flatPatternPath, '00-atoms-00-global'); + + var p = new Pattern( + '00-atoms/00-global/00-random-folder/00-another-folder/00-some-folder/00-colors-alt.mustache', + { d: 123 } + ); + test.equals(p.name, '00-atoms-00-global-00-colors-alt'); + test.equals(p.flatPatternPath, '00-atoms-00-global'); + + var p = new Pattern( + '00-atoms/00-global/00-random-folder/00-another-folder/00-colors-alt/colors-alt.mustache', + { d: 123 } + ); + test.equals(p.name, '00-atoms-00-global-00-colors-alt'); + test.equals(p.flatPatternPath, '00-atoms-00-global'); + + var p = new Pattern( + '00-atoms/00-global/00-random-folder/00-another-folder/00-some-folder/00-colors-alt~variant.mustache', + { d: 123 } + ); + test.equals(p.name, '00-atoms-00-global-00-colors-alt-variant'); + test.equals(p.flatPatternPath, '00-atoms-00-global'); + test.equals(p.patternBaseName, 'colors-alt-variant'); + test.end(); +}); + tap.test('The forms of Pattern.getPatternLink() work as expected', function( test ) { diff --git a/packages/core/test/ui_builder_tests.js b/packages/core/test/ui_builder_tests.js index 607d9fd95..3ac42f2f1 100644 --- a/packages/core/test/ui_builder_tests.js +++ b/packages/core/test/ui_builder_tests.js @@ -183,6 +183,7 @@ tap.test('groupPatterns - creates pattern groups correctly', function(test) { }); patternlab.patterns.push( + new Pattern('foobar.mustache'), new Pattern('00-test/bar.mustache'), new Pattern('00-test/foo.mustache'), new Pattern('patternType1/patternSubType1/blue.mustache'), @@ -222,13 +223,19 @@ tap.test('groupPatterns - creates pattern groups correctly', function(test) { 'patternType1-white' ); + // Flat patterns test.equals( patternlab.patternTypes[0].patternItems[0].patternPartial, + 'root-foobar', + 'flat pattern foobar on root' + ); + test.equals( + patternlab.patternTypes[1].patternItems[0].patternPartial, 'test-bar', 'first pattern item should be test-bar' ); test.equals( - patternlab.patternTypes[0].patternItems[1].patternPartial, + patternlab.patternTypes[1].patternItems[1].patternPartial, 'test-foo', 'second pattern item should be test-foo' ); @@ -248,13 +255,15 @@ tap.test('groupPatterns - orders patterns when provided from md', function( subtypePatterns: {}, }); + // Should be sorted by order and secondly by name patternlab.patterns.push( - new Pattern('patternType1/patternSubType1/blue.mustache'), + new Pattern('patternType1/patternSubType1/yellow.mustache'), new Pattern('patternType1/patternSubType1/red.mustache'), - new Pattern('patternType1/patternSubType1/yellow.mustache') + new Pattern('patternType1/patternSubType1/blue.mustache') ); ui.resetUIBuilderState(patternlab); + // Set order of red to 1 to sort it after the others patternlab.patterns[1].order = 1; //act @@ -270,10 +279,10 @@ tap.test('groupPatterns - orders patterns when provided from md', function( ]); 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'); + // Viewall should come last since it shows all patterns that are above + test.equals(items[0].patternPartial, 'patternType1-blue'); + test.equals(items[1].patternPartial, 'patternType1-yellow'); + test.equals(items[2].patternPartial, 'patternType1-red'); test.end(); }); @@ -310,10 +319,10 @@ tap.test( ]); 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'); + // Viewall should come last since it shows all patterns that are above + test.equals(items[0].patternPartial, 'patternType1-blue'); + test.equals(items[1].patternPartial, 'patternType1-red'); + test.equals(items[2].patternPartial, 'patternType1-yellow'); test.end(); } @@ -353,14 +362,14 @@ tap.test( ]); var items = patternSubType.patternSubtypeItems; - //zero is viewall + // Viewall should come last since it shows all patterns that are above test.equals( - items[0].patternPartial, + items[3].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.equals(items[0].patternPartial, 'patternType1-blue'); + test.equals(items[1].patternPartial, 'patternType1-yellow'); + test.equals(items[2].patternPartial, 'patternType1-red'); test.end(); } @@ -546,40 +555,42 @@ tap.test( const styleguidePatterns = ui.groupPatterns(patternlab, uikit); //act - ui - .buildViewAllPages( - mainPageHeadHtml, - patternlab, - styleguidePatterns, - uikit - ) - .then(allPatterns => { - //assert - //this was a nuanced one. buildViewAllPages() had return false; statements - //within _.forOwn(...) loops, causing premature termination of the entire loop - //when what was intended was a continue - //we expect 8 here because: - // - foo.mustache is flat and therefore does not have a viewall page - // - the colors.mustache files make 6 - // - patternSubType1 and patternSubType2 make 8 - //while most of that heavy lifting occurs inside groupPatterns and not buildViewAllPages, - //it's important to ensure that this method does not get prematurely terminated - //we choose to do that by checking it's return number of patterns - - //todo: this workaround matches the code at the moment - const uniquePatterns = _.uniq( - _.flatMapDeep(allPatterns, pattern => { - return pattern; - }) - ); - - test.equals( - uniquePatterns.length, - 8, - '2 viewall pages should be added' - ); - - test.end(); - }); + ui.buildViewAllPages( + mainPageHeadHtml, + patternlab, + styleguidePatterns, + uikit + ).then(allPatterns => { + // assert + // this was a nuanced one. buildViewAllPages() had return false; statements + // within _.forOwn(...) loops, causing premature termination of the entire loop + // when what was intended was a continue + // we expect 8 here because: + // - foo.mustache is flat and therefore does not have a viewall page + // - the colors.mustache files make 6 + // - patternSubType1 and patternSubType2 make 8 + // while most of that heavy lifting occurs inside groupPatterns and not buildViewAllPages, + // it's important to ensure that this method does not get prematurely terminated + // we choose to do that by checking it's return number of patterns + + const uniquePatterns = ui.uniqueAllPatterns(allPatterns, patternlab); + + /** + * - viewall-test-all + * -- test-foo + * - view-patternType1-all + * -- viewall-patternType1-patternSubType1 + * --- blue + * --- red + * --- yellow + * -- viewall-patternType1-patternSubType2 + * --- black + * --- grey + * --- white + */ + test.equals(uniquePatterns.length, 11, '4 viewall pages should be added'); + + test.end(); + }); } ); diff --git a/packages/edition-node/patternlab-config.json b/packages/edition-node/patternlab-config.json index e5cef6811..2db440279 100644 --- a/packages/edition-node/patternlab-config.json +++ b/packages/edition-node/patternlab-config.json @@ -75,6 +75,10 @@ "patternExportPatternPartials": [], "patternExportPreserveDirectoryStructure": true, "patternExportRaw": false, + "patternTranslations": { + "view-all": "View all {groupName}", + "root-name": "Root" + }, "serverOptions": { "wait": 1000 }, diff --git a/packages/engine-mustache/lib/engine_mustache.js b/packages/engine-mustache/lib/engine_mustache.js index dc0838cfd..59aa04501 100644 --- a/packages/engine-mustache/lib/engine_mustache.js +++ b/packages/engine-mustache/lib/engine_mustache.js @@ -29,7 +29,7 @@ const utilMustache = require('./util_mustache'); // it does, so we're cool, right? let patternLabConfig = {}; -var engine_mustache = { +const engine_mustache = { engine: Mustache, engineName: 'mustache', engineFileExtension: '.mustache', @@ -69,7 +69,7 @@ var engine_mustache = { * @returns {array|null} An array if a match is found, null if not. */ patternMatcher: function patternMatcher(pattern, regex) { - var matches; + let matches; if (typeof pattern === 'string') { matches = pattern.match(regex); } else if ( @@ -110,43 +110,35 @@ var engine_mustache = { // find and return any {{> template-name }} within pattern findPartials: function findPartials(pattern) { - var matches = this.patternMatcher(pattern, this.findPartialsRE); - return matches; + return this.patternMatcher(pattern, this.findPartialsRE); }, findPartialsWithStyleModifiers: function(pattern) { - var matches = this.patternMatcher( - pattern, - this.findPartialsWithStyleModifiersRE - ); - return matches; + return this.patternMatcher(pattern, this.findPartialsWithStyleModifiersRE); }, // returns any patterns that match {{> value(foo:"bar") }} or {{> // value:mod(foo:"bar") }} within the pattern findPartialsWithPatternParameters: function(pattern) { - var matches = this.patternMatcher( + return this.patternMatcher( pattern, this.findPartialsWithPatternParametersRE ); - return matches; }, findListItems: function(pattern) { - var matches = this.patternMatcher(pattern, this.findListItemsRE); - return matches; + return this.patternMatcher(pattern, this.findListItemsRE); }, // given a pattern, and a partial string, tease out the "pattern key" and // return it. findPartial_new: function(partialString) { - var partial = partialString.replace(this.findPartialRE, '$1'); - return partial; + return partialString.replace(this.findPartialRE, '$1'); }, // GTP: the old implementation works better. We might not need // this.findPartialRE anymore if it works in all cases! findPartial: function(partialString) { //strip out the template cruft - var foundPatternPartial = partialString + let foundPatternPartial = partialString .replace('{{> ', '') .replace(' }}', '') .replace('{{>', '') diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_pattern-category.scss b/packages/uikit-workshop/src/sass/scss/04-components/_pattern-category.scss index abe9d6142..fbca575bb 100644 --- a/packages/uikit-workshop/src/sass/scss/04-components/_pattern-category.scss +++ b/packages/uikit-workshop/src/sass/scss/04-components/_pattern-category.scss @@ -10,11 +10,15 @@ */ .pl-c-category { margin-top: 6rem; - font: $pl-font !important; + font-family: $pl-font !important; &:first-of-type { margin-top: 2rem; } + + & + & { + margin-top: 2rem; + } } /** @@ -25,6 +29,10 @@ color: $pl-color-gray-87 !important; margin: 0 0 0.2rem; text-transform: capitalize; + + &:hover { + color: $pl-color-gray-70 !important; + } } /** @@ -32,6 +40,7 @@ */ .pl-c-category__title-link { transition: color $pl-animate-quick ease-out; + color: inherit; } /** diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js b/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js index af3d0bf26..15e89203d 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js @@ -415,7 +415,7 @@ class Nav extends BaseComponent { return ( {patternSubtype.patternSubtypeItems} From c94531b8fbaa80dc44a2a87582a53869a35d4e4e Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Mon, 13 Apr 2020 02:51:07 +0200 Subject: [PATCH 03/16] Ability for viewall page links and updated test to realworld --- packages/core/src/lib/parseLink.js | 71 +++++++---- .../test/files/_patterns/00-test/nav.json | 32 +++-- packages/core/test/parseAllLinks_tests.js | 118 ++++++++++++++---- 3 files changed, 168 insertions(+), 53 deletions(-) diff --git a/packages/core/src/lib/parseLink.js b/packages/core/src/lib/parseLink.js index d3d0c455e..368ce4cc8 100644 --- a/packages/core/src/lib/parseLink.js +++ b/packages/core/src/lib/parseLink.js @@ -20,37 +20,64 @@ module.exports = function(patternlab, obj, key) { const linkMatches = dataObjAsString.match(linkRE); if (linkMatches) { - for (let i = 0; i < linkMatches.length; i++) { - const dataLink = linkMatches[i]; + linkMatches.forEach(dataLink => { if (dataLink && dataLink.split('.').length >= 2) { //get the partial the link refers to - const linkPatternPartial = dataLink - .split('.')[1] - .replace('"', '') - .replace("'", ''); - const pattern = getPartial(linkPatternPartial, patternlab); - if (pattern !== undefined) { - //get the full built link and replace it - let fullLink = patternlab.data.link[linkPatternPartial]; - if (fullLink) { - fullLink = path.normalize(fullLink).replace(/\\/g, '/'); + const linkPatternPartial = dataLink.split('.')[1].replace(/'|"/g, ''); + const rawLink = `link.${linkPatternPartial}`; + let replacement = null; - logger.debug( - `expanded data link from ${dataLink} to ${fullLink} inside ${key}` - ); + if (linkPatternPartial.match(/viewall\-.+\-all/)) { + // Reverse engineer viewall-group-all link (if there is a pattern with that + // group there will be a view all page for that group) + const partial = linkPatternPartial + .replace('viewall-', '') + .replace('-all', ''); + const pattern = patternlab.patterns.find( + p => p.patternGroup === partial + ); - //also make sure our global replace didn't mess up a protocol - fullLink = fullLink.replace(/:\//g, '://'); - dataObjAsString = dataObjAsString.replace( - 'link.' + linkPatternPartial, - fullLink - ); + if (pattern) { + replacement = `/patterns/${partial}/index.html`; } + } else if (linkPatternPartial.match(/viewall\-.+/)) { + // Reverse engineer viewall-group-subgroup link (if there is a pattern with that + // group and subgroup there will be a view all page for that group) + const partial = linkPatternPartial.replace('viewall-', ''); + const pattern = patternlab.patterns.find( + p => `${p.patternGroup}-${p.patternSubGroup}` === partial + ); + + if (pattern) { + replacement = `/patterns/${pattern.flatPatternPath}/index.html`; + } + } else { + // Just search for the pattern partial + const pattern = getPartial(linkPatternPartial, patternlab); + + if (pattern) { + // get the full built link and replace it + let fullLink = patternlab.data.link[linkPatternPartial]; + if (fullLink) { + fullLink = path.normalize(fullLink).replace(/\\/g, '/'); + + logger.debug( + `expanded data link from ${dataLink} to ${fullLink} inside ${key}` + ); + + // also make sure our global replace didn't mess up a protocol + replacement = fullLink.replace(/:\//g, '://'); + } + } + } + + if (replacement) { + dataObjAsString = dataObjAsString.replace(rawLink, replacement); } else { logger.warning(`pattern not found for ${dataLink} inside ${key}`); } } - } + }); } let dataObj; diff --git a/packages/core/test/files/_patterns/00-test/nav.json b/packages/core/test/files/_patterns/00-test/nav.json index 32a6c0952..8d47a2491 100644 --- a/packages/core/test/files/_patterns/00-test/nav.json +++ b/packages/core/test/files/_patterns/00-test/nav.json @@ -1,11 +1,29 @@ { - "brad" : { - "url" : "link.twitter-brad" + "brad": { + "url": "link.twitter-brad" }, - "dave" : { - "url" : "link.twitter-dave" + "dave": { + "url": "link.twitter-dave" }, - "brian" : { - "url" : "link.twitter-brian" + "brian": { + "url": "link.twitter-brian" + }, + "someone": { + "url": "link.twitter-someone" + }, + "someone2": { + "url": "link.facebook-someone2" + }, + "viewall-twitter": { + "url": "link.viewall-twitter-all" + }, + "viewall-twitter-people": { + "url": "link.viewall-twitter-people" + }, + "viewall-facebook": { + "url": "link.viewall-facebook-all" + }, + "viewall-facebook-people": { + "url": "link.viewall-facebook-people" } -} +} \ No newline at end of file diff --git a/packages/core/test/parseAllLinks_tests.js b/packages/core/test/parseAllLinks_tests.js index 271b3ee5b..1d52c4276 100644 --- a/packages/core/test/parseAllLinks_tests.js +++ b/packages/core/test/parseAllLinks_tests.js @@ -22,15 +22,21 @@ tap.test( const patternlab = util.fakePatternLab(patterns_dir); patternlab.graph = PatternGraph.empty(); - patternlab.patterns = [ - Pattern.createEmpty({ patternPartial: 'twitter-brad' }, patternlab), - Pattern.createEmpty({ patternPartial: 'twitter-dave' }, patternlab), - Pattern.createEmpty({ patternPartial: 'twitter-brian' }, patternlab), - ]; - patternlab.data.link = {}; + addPattern(new Pattern('twitter/brad.hbs', {}, patternlab), patternlab); + addPattern(new Pattern('twitter/dave.hbs', {}, patternlab), patternlab); + addPattern(new Pattern('twitter/brian.hbs', {}, patternlab), patternlab); + addPattern( + new Pattern('twitter/people/someone.hbs', {}, patternlab), + patternlab + ); + // Test with pattern prefix + addPattern( + new Pattern('01-facebook/02-people/03-someone2.hbs', {}, patternlab), + patternlab + ); // copies essential logic from loadPattern - const navPattern = new Pattern('00-test/nav.mustache'); + const navPattern = new Pattern('00-test/nav.mustache', {}, patternlab); const patternData = dataLoader.loadDataFromFile( path.resolve( __dirname, @@ -43,21 +49,15 @@ tap.test( navPattern.jsonFileData = patternData; addPattern(navPattern, patternlab); - //for the sake of the test, also imagining I have the following pages... - patternlab.data.link['twitter-brad'] = 'https://twitter.com/brad_frost'; - patternlab.data.link['twitter-dave'] = 'https://twitter.com/dmolsen'; - patternlab.data.link['twitter-brian'] = 'https://twitter.com/bmuenzenmeyer'; - patternlab.data.brad = { url: 'link.twitter-brad' }; patternlab.data.dave = { url: 'link.twitter-dave' }; patternlab.data.brian = { url: 'link.twitter-brian' }; + patternlab.data.someone = { url: 'link.twitter-someone' }; + patternlab.data.someone2 = { url: 'link.facebook-someone2' }; - let pattern; - for (let i = 0; i < patternlab.patterns.length; i++) { - if (patternlab.patterns[i].patternPartial === 'test-nav') { - pattern = patternlab.patterns[i]; - } - } + let pattern = patternlab.patterns.find( + p => p.patternPartial === 'test-nav' + ); //assert before test.equals( @@ -75,6 +75,36 @@ tap.test( 'link.twitter-brian', 'brian pattern data should be found' ); + test.equals( + pattern.jsonFileData.someone.url, + 'link.twitter-someone', + 'brian pattern data should be found' + ); + test.equals( + pattern.jsonFileData.someone2.url, + 'link.facebook-someone2', + 'brian pattern data should be found' + ); + test.equals( + pattern.jsonFileData['viewall-twitter'].url, + 'link.viewall-twitter-all', + 'view all twitter link should be found' + ); + test.equals( + pattern.jsonFileData['viewall-twitter-people'].url, + 'link.viewall-twitter-people', + 'view all twitter people link should be found' + ); + test.equals( + pattern.jsonFileData['viewall-facebook'].url, + 'link.viewall-facebook-all', + 'view all facebook link should be found' + ); + test.equals( + pattern.jsonFileData['viewall-facebook-people'].url, + 'link.viewall-facebook-people', + 'view all facebook people link should be found' + ); //act parseAllLinks(patternlab); @@ -82,35 +112,75 @@ tap.test( //assert after test.equals( pattern.jsonFileData.brad.url, - 'https://twitter.com/brad_frost', + '/patterns/twitter-brad/twitter-brad.rendered.html', 'brad pattern data should be replaced' ); test.equals( pattern.jsonFileData.dave.url, - 'https://twitter.com/dmolsen', + '/patterns/twitter-dave/twitter-dave.rendered.html', 'dave pattern data should be replaced' ); test.equals( pattern.jsonFileData.brian.url, - 'https://twitter.com/bmuenzenmeyer', + '/patterns/twitter-brian/twitter-brian.rendered.html', 'brian pattern data should be replaced' ); + test.equals( + pattern.jsonFileData.someone.url, + '/patterns/twitter-people-someone/twitter-people-someone.rendered.html', + 'twitter people someone pattern data should be replaced' + ); + test.equals( + pattern.jsonFileData.someone2.url, + '/patterns/01-facebook-02-people-03-someone2/01-facebook-02-people-03-someone2.rendered.html', + 'facebook people someone2 pattern data should be replaced with prefix pattern' + ); + test.equals( + pattern.jsonFileData['viewall-twitter'].url, + '/patterns/twitter/index.html', + 'view all twitter link should be replaced' + ); + test.equals( + pattern.jsonFileData['viewall-twitter-people'].url, + '/patterns/twitter-people/index.html', + 'view all twitter people link should be replaced' + ); + test.equals( + pattern.jsonFileData['viewall-facebook'].url, + '/patterns/facebook/index.html', + 'view all facebook link should be replaced' + ); + test.equals( + pattern.jsonFileData['viewall-facebook-people'].url, + '/patterns/01-facebook-02-people/index.html', + 'view all facebook people link should be replaced' + ); test.equals( patternlab.data.brad.url, - 'https://twitter.com/brad_frost', + '/patterns/twitter-brad/twitter-brad.rendered.html', 'global brad data should be replaced' ); test.equals( patternlab.data.dave.url, - 'https://twitter.com/dmolsen', + '/patterns/twitter-dave/twitter-dave.rendered.html', 'global dave data should be replaced' ); test.equals( patternlab.data.brian.url, - 'https://twitter.com/bmuenzenmeyer', + '/patterns/twitter-brian/twitter-brian.rendered.html', 'global brian data should be replaced' ); + test.equals( + patternlab.data.someone.url, + '/patterns/twitter-people-someone/twitter-people-someone.rendered.html', + 'twitter people someone pattern data should be replaced' + ); + test.equals( + patternlab.data.someone2.url, + '/patterns/01-facebook-02-people-03-someone2/01-facebook-02-people-03-someone2.rendered.html', + 'facebook people someone2 pattern data should be replaced with prefix pattern' + ); test.end(); } ); From e39a881dd828a8ebb142b225e29d939a4d1ad3cc Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Mon, 13 Apr 2020 17:03:38 +0200 Subject: [PATCH 04/16] Fix "Open In New Tab" incorrect link --- .../src/scripts/lit-components/pl-viewport/pl-viewport.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.js b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.js index 99a456810..8fd02933a 100644 --- a/packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.js +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.js @@ -491,6 +491,10 @@ class IFrame extends BaseLitComponent { this.sanitizePatternName(event.data.patternpartial) || this.getPatternParam(); + store.dispatch( + updateCurrentUrl(urlHandler.getFileName(currentPattern)) + ); + document.title = 'Pattern Lab - ' + currentPattern; const addressReplacement = From e72b8b4d9e72a934ac35af62bdeb646c6edcd6c0 Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Fri, 17 Apr 2020 20:21:07 +0200 Subject: [PATCH 05/16] #1143: Add func. to specify if pattern has own dir --- packages/core/src/lib/markdown_parser.js | 5 +- packages/core/src/lib/object_factory.js | 81 +++++++++++++++------- packages/core/src/lib/readDocumentation.js | 5 ++ 3 files changed, 64 insertions(+), 27 deletions(-) diff --git a/packages/core/src/lib/markdown_parser.js b/packages/core/src/lib/markdown_parser.js index c940a5f67..224d8012a 100644 --- a/packages/core/src/lib/markdown_parser.js +++ b/packages/core/src/lib/markdown_parser.js @@ -13,8 +13,9 @@ const markdown_parser = function() { let returnObject = {}; try { - //for each block process the yaml frontmatter and markdown - const frontmatterRE = /---\r?\n{1}([\s\S]*)---\r?\n{1}([\s\S]*)+/gm; + // for each block process the yaml frontmatter and markdown + // even if the pattern only has pattern data without further documentation + const frontmatterRE = /---\r?\n{1}([\s\S]*)---([\s\S]*)+/gm; const chunks = frontmatterRE.exec(block); if (chunks) { diff --git a/packages/core/src/lib/object_factory.js b/packages/core/src/lib/object_factory.js index 90c30112d..3f004828c 100644 --- a/packages/core/src/lib/object_factory.js +++ b/packages/core/src/lib/object_factory.js @@ -16,22 +16,23 @@ const prefixMatcher = /^_?(\d+-)?/; * to get more details about the behavior of the folder structure * https://github.com/pattern-lab/patternlab-node/pull/992 * https://github.com/pattern-lab/patternlab-node/pull/1016 + * https://github.com/pattern-lab/patternlab-node/pull/1143 * - * @constructor + * @param {String} relPath relative directory + * @param {Object} jsonFileData The JSON used to render values in the pattern. + * @param {Patternlab} patternlab The actual patternlab instance + * @param {Boolean} isUnsubRun specifies if the pattern needs to be unsubbed from its folder */ -const Pattern = function(relPath, data, patternlab) { +const Pattern = function(relPath, jsonFileData, patternlab, isUnsubRun) { this.relPath = path.normalize(relPath); // '00-atoms/00-global/00-colors.mustache' /** * 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(this.relPath); - const info = this.getPatternInfo(pathObj, patternlab); + const info = this.getPatternInfo(pathObj, patternlab, isUnsubRun); this.fileName = pathObj.name; // '00-colors' this.subdir = pathObj.dir; // '00-atoms/00-global' @@ -41,8 +42,8 @@ const Pattern = function(relPath, data, patternlab) { if (info.patternHasOwnDir) { // Since there is still the requirement of having the numbers provided for sorting // this will be required to keep the folder prefix and the variant name - // /00-atoms/00-global/00-colors/colors~varian.hbs - // -> 00-atoms-00-global-00-colors + // /00-atoms/00-global/00-colors/colors~variant.hbs + // -> 00-atoms-00-global-00-colors-variant this.name = `${info.shortNotation}-${path.parse(pathObj.dir).base}${ this.fileName.indexOf('~') !== -1 ? '-' + this.fileName.split('~')[1] : '' }`; @@ -52,7 +53,7 @@ const Pattern = function(relPath, data, patternlab) { } // the JSON used to render values in the pattern - this.jsonFileData = data || {}; + this.jsonFileData = jsonFileData || {}; // strip leading "00-" from the file name and flip tildes to dashes this.patternBaseName = this.fileName @@ -188,8 +189,10 @@ Pattern.prototype = { return this.name + path.sep + this.name + suffix + '.html'; }, - // the finders all delegate to the PatternEngine, which also encapsulates all - // appropriate regexes + /** + * The finders all delegate to the PatternEngine, which also + * encapsulates all appropriate regexes + */ findPartials: function() { return this.engine.findPartials(this); }, @@ -210,9 +213,15 @@ Pattern.prototype = { return this.engine.findPartial(partialString); }, - getDirLevel: function(level, pathInfo) { + /** + * Get a directory on a specific level of the pattern path + * + * @param {Number} level Level of folder to get + * @param {Object} pInfo general information about the pattern + */ + getDirLevel: function(level, pInfo) { const items = this.subdir.split(path.sep); - pathInfo.patternHasOwnDir && items.pop(); + pInfo && pInfo.patternHasOwnDir && items.pop(); if (items[level]) { return items[level]; @@ -221,16 +230,37 @@ Pattern.prototype = { } else { // Im Not quite shure about that but its better than empty node // TODO: verify - return pathInfo.patternlab && - pathInfo.patternlab.config.patternTranslations && - pathInfo.patternlab.config.patternTranslations['root-name'] - ? _.kebabCase( - pathInfo.patternlab.config.patternTranslations['root-name'] - ) + return pInfo.patternlab && + pInfo.patternlab.config.patternTranslations && + pInfo.patternlab.config.patternTranslations['root-name'] + ? _.kebabCase(pInfo.patternlab.config.patternTranslations['root-name']) : 'root'; } }, + /** + * Reset the information that the pattern has it's own directory, + * so that this pattern will not be handled as flat pattern if it + * is located on a top level folder. + * + * @param {Patternlab} patternlab Current patternlab instance + */ + resetSubbing: function(patternlab) { + const p = new Pattern(this.relPath, this.jsonFileData, patternlab, true); + // Only reset the specific fields, not everything + Object.assign(this, { + patternLink: p.patternLink, + patternGroup: p.patternGroup, + patternType: p.patternType, + patternSubGroup: p.patternSubGroup, + patternSubType: p.patternSubType, + isFlatPattern: p.isFlatPattern, + flatPatternPath: p.flatPatternPath, + patternPartial: p.patternPartial, + verbosePartial: p.verbosePartial, + }); + }, + /** * Info contains information about pattern structure if it is a nested pattern * or if it just a subbed folder structure. Its just used for internal purposes. @@ -238,15 +268,16 @@ Pattern.prototype = { * * @param pathObj path.parse() object containing usefull path information */ - getPatternInfo: (pathObj, patternlab) => { + getPatternInfo: (pathObj, patternlab, isUnsubRun) => { const info = { // 00-colors(.mustache) is subbed in 00-atoms-/00-global/00-colors patternlab: patternlab, - patternHasOwnDir: - path.basename(pathObj.dir).replace(prefixMatcher, '') === - pathObj.name.replace(prefixMatcher, '') || - path.basename(pathObj.dir).replace(prefixMatcher, '') === - pathObj.name.split('~')[0].replace(prefixMatcher, ''), + patternHasOwnDir: !isUnsubRun + ? path.basename(pathObj.dir).replace(prefixMatcher, '') === + pathObj.name.replace(prefixMatcher, '') || + path.basename(pathObj.dir).replace(prefixMatcher, '') === + pathObj.name.split('~')[0].replace(prefixMatcher, '') + : false, }; info.dir = info.patternHasOwnDir ? pathObj.dir.split(path.sep).pop() : ''; diff --git a/packages/core/src/lib/readDocumentation.js b/packages/core/src/lib/readDocumentation.js index 2670bb307..bfe35b983 100644 --- a/packages/core/src/lib/readDocumentation.js +++ b/packages/core/src/lib/readDocumentation.js @@ -54,6 +54,11 @@ module.exports = function(pattern, patternlab) { if (markdownObject.links) { pattern.links = markdownObject.links; } + + if (markdownObject.hasOwnProperty('subbed') && !markdownObject.subbed) { + // Reset to pattern without own pattern-directory + pattern.resetSubbing(patternlab); + } } else { logger.warning(`error processing markdown for ${pattern.patternPartial}`); } From 5003a6a8b3bbe19cc278849580b25c73e86e0ad1 Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Fri, 17 Apr 2020 21:28:23 +0200 Subject: [PATCH 06/16] #1143: Add test and fix remaining errors --- packages/core/src/lib/object_factory.js | 14 ++++++++-- packages/core/test/object_factory_tests.js | 32 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/packages/core/src/lib/object_factory.js b/packages/core/src/lib/object_factory.js index 3f004828c..f5fe162a2 100644 --- a/packages/core/src/lib/object_factory.js +++ b/packages/core/src/lib/object_factory.js @@ -168,9 +168,16 @@ Pattern.prototype = { } }, - // calculated path from the root of the public directory to the generated html - // file for this pattern. - // Should look something like '00-atoms-00-global-00-colors/00-atoms-00-global-00-colors.html' + /** + * calculated path from the root of the public directory to the generated html + * file for this pattern. + * + * Should look something like '00-atoms-00-global-00-colors/00-atoms-00-global-00-colors.html' + * + * @param {Patternlab} patternlab Current patternlab instance + * @param {String} suffixType File suffix + * @param {String} customfileExtension Custom extension + */ getPatternLink: function(patternlab, suffixType, customfileExtension) { // if no suffixType is provided, we default to rendered const suffixConfig = patternlab.config.outputFileSuffixes; @@ -249,6 +256,7 @@ Pattern.prototype = { const p = new Pattern(this.relPath, this.jsonFileData, patternlab, true); // Only reset the specific fields, not everything Object.assign(this, { + name: p.name, patternLink: p.patternLink, patternGroup: p.patternGroup, patternType: p.patternType, diff --git a/packages/core/test/object_factory_tests.js b/packages/core/test/object_factory_tests.js index b5835f417..6c7b704df 100644 --- a/packages/core/test/object_factory_tests.js +++ b/packages/core/test/object_factory_tests.js @@ -149,6 +149,38 @@ tap.test('test Pattern with one-directory subdir works as expected', function( test.end(); }); +tap.test('test Pattern with own-directory gets resetted as expected', function( + test +) { + var p = new Pattern('00-atoms/00-button/button.mustache', { d: 123 }, pl); + p.resetSubbing(pl); + + test.equals(p.relPath, path.join('00-atoms', '00-button', 'button.mustache')); + test.equals(p.name, '00-atoms-00-button-button'); + test.equals(p.subdir, path.join('00-atoms', '00-button')); + test.equals(p.fileName, 'button'); + test.equals(p.fileExtension, '.mustache'); + test.equals(p.jsonFileData.d, 123); + test.equals(p.patternBaseName, 'button'); + test.equals(p.patternName, 'Button'); + test.equals( + p.getPatternLink(pl), + path.join( + '00-atoms-00-button-button', + '00-atoms-00-button-button.rendered.html' + ) + ); + test.equals(p.patternGroup, 'atoms'); + test.equals(p.flatPatternPath, '00-atoms-00-button'); + test.equals(p.patternPartial, 'atoms-button'); + test.equals(p.template, ''); + test.equals(p.lineage.length, 0); + test.equals(p.lineageIndex.length, 0); + test.equals(p.lineageR.length, 0); + test.equals(p.lineageRIndex.length, 0); + test.end(); +}); + tap.test( 'test Pattern with no numbers in pattern group works as expected', function(test) { From ffcd61571124b5292b0e982b68df759964b1c026 Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Sat, 25 Apr 2020 16:46:23 +0200 Subject: [PATCH 07/16] #1143: Fix translations causing nav bug --- packages/core/patternlab-config.json | 6 ++- packages/core/src/lib/object_factory.js | 4 +- packages/core/src/lib/ui_builder.js | 15 ++++-- packages/edition-node/patternlab-config.json | 6 ++- .../src/scripts/components/pl-nav/pl-nav.js | 53 +++++++++---------- 5 files changed, 46 insertions(+), 38 deletions(-) diff --git a/packages/core/patternlab-config.json b/packages/core/patternlab-config.json index 265e98b65..31fcbf748 100644 --- a/packages/core/patternlab-config.json +++ b/packages/core/patternlab-config.json @@ -76,8 +76,10 @@ "patternExportPreserveDirectoryStructure": true, "patternExportRaw": false, "patternTranslations": { - "view-all": "View all {groupName}", - "root-name": "Root" + "ViewAllSubGroup": "View all {sgName}", + "viewAllGroup": "View All", + "viewAllRoot": "All", + "rootName": "Root" }, "serverOptions": { "wait": 1000 diff --git a/packages/core/src/lib/object_factory.js b/packages/core/src/lib/object_factory.js index f5fe162a2..3df0d3b2c 100644 --- a/packages/core/src/lib/object_factory.js +++ b/packages/core/src/lib/object_factory.js @@ -239,8 +239,8 @@ Pattern.prototype = { // TODO: verify return pInfo.patternlab && pInfo.patternlab.config.patternTranslations && - pInfo.patternlab.config.patternTranslations['root-name'] - ? _.kebabCase(pInfo.patternlab.config.patternTranslations['root-name']) + pInfo.patternlab.config.patternTranslations.rootName + ? _.kebabCase(pInfo.patternlab.config.patternTranslations.rootName) : 'root'; } }, diff --git a/packages/core/src/lib/ui_builder.js b/packages/core/src/lib/ui_builder.js index 148a872aa..4d4c371e4 100644 --- a/packages/core/src/lib/ui_builder.js +++ b/packages/core/src/lib/ui_builder.js @@ -262,6 +262,7 @@ const ui_builder = function() { patternState: pattern.patternState, patternPath: pattern.patternLink, name: pattern.name, + isDocPattern: false, order: Number(pattern.order) || 0, // Failsave is someone entered a string }; } @@ -284,11 +285,16 @@ const ui_builder = function() { newSubTypeItem = { patternPartial: 'viewall-' + pattern.patternGroup + '-' + pattern.patternSubGroup, - patternName: 'View All', + patternName: + patternlab.config.patternTranslations && + patternlab.config.patternTranslations.viewAllGroup + ? patternlab.config.patternTranslations.viewAllGroup + : `View all`, patternPath: encodeURI(pattern.flatPatternPath + '/index.html'), patternType: pattern.patternType, patternSubtype: pattern.patternSubtype, name: pattern.flatPatternPath, + isDocPattern: true, order: Number.MAX_SAFE_INTEGER, }; } else { @@ -322,14 +328,15 @@ const ui_builder = function() { patternPartial: `viewall-${pattern.patternGroup}-all`, patternName: patternlab.config.patternTranslations && - patternlab.config.patternTranslations['view-all'] - ? patternlab.config.patternTranslations['view-all'].replace( - '{groupName}', + patternlab.config.patternTranslations.ViewAllSubGroup + ? patternlab.config.patternTranslations.ViewAllSubGroup.replace( + '{sgName}', _.startCase(pattern.patternGroup) ) : `View all ${_.startCase(pattern.patternGroup)}`, patternPath: encodeURI(pattern.patternGroup + '/index.html'), name: pattern.patternGroup, + isDocPattern: true, order: Number.MAX_SAFE_INTEGER, }); } else { diff --git a/packages/edition-node/patternlab-config.json b/packages/edition-node/patternlab-config.json index 2db440279..67472a021 100644 --- a/packages/edition-node/patternlab-config.json +++ b/packages/edition-node/patternlab-config.json @@ -76,8 +76,10 @@ "patternExportPreserveDirectoryStructure": true, "patternExportRaw": false, "patternTranslations": { - "view-all": "View all {groupName}", - "root-name": "Root" + "ViewAllSubGroup": "View all {sgName}", + "viewAllGroup": "View All", + "viewAllRoot": "All", + "rootName": "Root" }, "serverOptions": { "wait": 1000 diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js b/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js index 15e89203d..744138743 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js @@ -14,15 +14,10 @@ const SubSubList = props => { const { children, category, elem } = props; const reorderedChildren = []; - const nonViewAllItems = elem.noViewAll - ? children.filter(item => item.patternName !== 'View All') - : children.filter( - item => - item.patternName !== 'View All' && !item.patternName.includes(' Docs') - ); + const nonViewAllItems = children.filter(item => !item.isDocPattern); const viewAllItems = elem.noViewAll ? [] - : children.filter(item => item.patternName === 'View All'); + : children.filter(item => item.isDocPattern); reorderedChildren.push(...viewAllItems, ...nonViewAllItems); @@ -35,7 +30,7 @@ const SubSubList = props => { href={`patterns/${patternSubtypeItem.patternPath}`} className={`pl-c-nav__link pl-c-nav__link--sublink ${ - patternSubtypeItem.patternName === 'View All' + patternSubtypeItem.isDocPattern ? 'pl-c-nav__link--overview pl-js-link-overview' : 'pl-c-nav__link--subsublink' } @@ -45,7 +40,7 @@ const SubSubList = props => { } data-patternpartial={patternSubtypeItem.patternPartial} > - {patternSubtypeItem.patternName === 'View All' + {patternSubtypeItem.isDocPattern ? `${category}` : patternSubtypeItem.patternName} {patternSubtypeItem.patternState && ( @@ -84,7 +79,7 @@ const SubSubList = props => { href={`patterns/${patternSubtypeItem.patternPath}`} className={`pl-c-nav__link pl-c-nav__link--sublink ${ - patternSubtypeItem.patternName === 'View All' + patternSubtypeItem.isDocPattern ? 'pl-c-nav__link--overview' : 'pl-c-nav__link--subsublink' } @@ -94,7 +89,7 @@ const SubSubList = props => { } data-patternpartial={patternSubtypeItem.patternPartial} > - {patternSubtypeItem.patternName === 'View All' + {patternSubtypeItem.isDocPattern ? `${category} Overview` : patternSubtypeItem.patternName} {patternSubtypeItem.patternState && ( @@ -438,9 +433,7 @@ class Nav extends BaseComponent { data-patternpartial={patternItem.patternPartial} tabindex="0" > - {patternItem.patternName === 'View All' - ? patternItem.patternName + ' ' + item.patternTypeUC - : patternItem.patternName} + {patternItem.patternName} {patternItem.patternState && ( - this.handleClick(e, 'all')} - href="styleguide/html/styleguide.html" - class="pl-c-nav__link pl-c-nav__link--pattern" - data-patternpartial="all" - tabindex="0" - > - All - - - )} + (!window.ishControls.ishControlsHide['views-all'] && + !window.ishControls.ishControlsHide.all)) && + !this.noViewAll && ( +
  • + this.handleClick(e, 'all')} + href="styleguide/html/styleguide.html" + class="pl-c-nav__link pl-c-nav__link--pattern" + data-patternpartial="all" + tabindex="0" + > + {window.config.patternTranslations && + window.config.patternTranslations.viewAllRoot + ? window.config.patternTranslations.viewAllRoot + : 'All'} + +
  • + )} ); } From 2475cacc542ecb33bdaf1e61d38a9d24e8509f46 Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Sat, 25 Apr 2020 16:50:37 +0200 Subject: [PATCH 08/16] #1143: Change property to proper name --- packages/core/src/lib/object_factory.js | 6 +++--- packages/core/src/lib/readDocumentation.js | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/core/src/lib/object_factory.js b/packages/core/src/lib/object_factory.js index 3df0d3b2c..36bcb9c6a 100644 --- a/packages/core/src/lib/object_factory.js +++ b/packages/core/src/lib/object_factory.js @@ -21,7 +21,7 @@ const prefixMatcher = /^_?(\d+-)?/; * @param {String} relPath relative directory * @param {Object} jsonFileData The JSON used to render values in the pattern. * @param {Patternlab} patternlab The actual patternlab instance - * @param {Boolean} isUnsubRun specifies if the pattern needs to be unsubbed from its folder + * @param {Boolean} isUnsubRun specifies if the pattern needs to be removed from its subfolder */ const Pattern = function(relPath, jsonFileData, patternlab, isUnsubRun) { this.relPath = path.normalize(relPath); // '00-atoms/00-global/00-colors.mustache' @@ -271,14 +271,14 @@ Pattern.prototype = { /** * Info contains information about pattern structure if it is a nested pattern - * or if it just a subbed folder structure. Its just used for internal purposes. + * or if it just a subfolder structure. Its just used for internal purposes. * Remember every pattern infomarion based on "this.*" will be used by other functions * * @param pathObj path.parse() object containing usefull path information */ getPatternInfo: (pathObj, patternlab, isUnsubRun) => { const info = { - // 00-colors(.mustache) is subbed in 00-atoms-/00-global/00-colors + // 00-colors(.mustache) is subfolder in 00-atoms-/00-global/00-colors patternlab: patternlab, patternHasOwnDir: !isUnsubRun ? path.basename(pathObj.dir).replace(prefixMatcher, '') === diff --git a/packages/core/src/lib/readDocumentation.js b/packages/core/src/lib/readDocumentation.js index bfe35b983..2d66a7a7f 100644 --- a/packages/core/src/lib/readDocumentation.js +++ b/packages/core/src/lib/readDocumentation.js @@ -55,7 +55,10 @@ module.exports = function(pattern, patternlab) { pattern.links = markdownObject.links; } - if (markdownObject.hasOwnProperty('subbed') && !markdownObject.subbed) { + if ( + markdownObject.hasOwnProperty('subfolder') && + !markdownObject.subfolder + ) { // Reset to pattern without own pattern-directory pattern.resetSubbing(patternlab); } From fec2492c9bf2df563909932fc2db353a7d3d2d12 Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Sun, 26 Apr 2020 21:50:33 +0200 Subject: [PATCH 09/16] #1143: Revert translation attempt --- packages/core/patternlab-config.json | 6 ------ packages/core/src/lib/object_factory.js | 6 +----- packages/core/src/lib/ui_builder.js | 15 ++------------- packages/edition-node/patternlab-config.json | 6 ------ .../src/scripts/components/pl-nav/src/NavLink.js | 4 ++-- .../src/scripts/components/pl-nav/src/NavList.js | 7 +++---- 6 files changed, 8 insertions(+), 36 deletions(-) diff --git a/packages/core/patternlab-config.json b/packages/core/patternlab-config.json index 31fcbf748..39eed54fd 100644 --- a/packages/core/patternlab-config.json +++ b/packages/core/patternlab-config.json @@ -75,12 +75,6 @@ "patternExportPatternPartials": [], "patternExportPreserveDirectoryStructure": true, "patternExportRaw": false, - "patternTranslations": { - "ViewAllSubGroup": "View all {sgName}", - "viewAllGroup": "View All", - "viewAllRoot": "All", - "rootName": "Root" - }, "serverOptions": { "wait": 1000 }, diff --git a/packages/core/src/lib/object_factory.js b/packages/core/src/lib/object_factory.js index 36bcb9c6a..06e572527 100644 --- a/packages/core/src/lib/object_factory.js +++ b/packages/core/src/lib/object_factory.js @@ -237,11 +237,7 @@ Pattern.prototype = { } else { // Im Not quite shure about that but its better than empty node // TODO: verify - return pInfo.patternlab && - pInfo.patternlab.config.patternTranslations && - pInfo.patternlab.config.patternTranslations.rootName - ? _.kebabCase(pInfo.patternlab.config.patternTranslations.rootName) - : 'root'; + return 'root'; } }, diff --git a/packages/core/src/lib/ui_builder.js b/packages/core/src/lib/ui_builder.js index 4d4c371e4..e8707b97d 100644 --- a/packages/core/src/lib/ui_builder.js +++ b/packages/core/src/lib/ui_builder.js @@ -285,11 +285,7 @@ const ui_builder = function() { newSubTypeItem = { patternPartial: 'viewall-' + pattern.patternGroup + '-' + pattern.patternSubGroup, - patternName: - patternlab.config.patternTranslations && - patternlab.config.patternTranslations.viewAllGroup - ? patternlab.config.patternTranslations.viewAllGroup - : `View all`, + patternName: `View All`, patternPath: encodeURI(pattern.flatPatternPath + '/index.html'), patternType: pattern.patternType, patternSubtype: pattern.patternSubtype, @@ -326,14 +322,7 @@ const ui_builder = function() { if (isViewAllVariant) { patternType.patternItems.push({ patternPartial: `viewall-${pattern.patternGroup}-all`, - patternName: - patternlab.config.patternTranslations && - patternlab.config.patternTranslations.ViewAllSubGroup - ? patternlab.config.patternTranslations.ViewAllSubGroup.replace( - '{sgName}', - _.startCase(pattern.patternGroup) - ) - : `View all ${_.startCase(pattern.patternGroup)}`, + patternName: `View all ${_.startCase(pattern.patternGroup)}`, patternPath: encodeURI(pattern.patternGroup + '/index.html'), name: pattern.patternGroup, isDocPattern: true, diff --git a/packages/edition-node/patternlab-config.json b/packages/edition-node/patternlab-config.json index 67472a021..e5cef6811 100644 --- a/packages/edition-node/patternlab-config.json +++ b/packages/edition-node/patternlab-config.json @@ -75,12 +75,6 @@ "patternExportPatternPartials": [], "patternExportPreserveDirectoryStructure": true, "patternExportRaw": false, - "patternTranslations": { - "ViewAllSubGroup": "View all {sgName}", - "viewAllGroup": "View All", - "viewAllRoot": "All", - "rootName": "Root" - }, "serverOptions": { "wait": 1000 }, diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavLink.js b/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavLink.js index 80f3b26d9..7a7c742de 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavLink.js +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavLink.js @@ -7,7 +7,7 @@ export const NavLink = props => { href={`patterns/${props.item.patternPath}`} className={`pl-c-nav__link pl-c-nav__link--sublink ${ - props.item.patternName === 'View All' + props.item.isDocPattern ? 'pl-c-nav__link--overview' : 'pl-c-nav__link--subsublink' } @@ -15,7 +15,7 @@ export const NavLink = props => { onClick={e => props.elem.handleClick(e, props.item.patternPartial)} data-patternpartial={props.item.patternPartial} > - {props.item.patternName === 'View All' && props.category + {props.item.isDocPattern && props.category ? `${props.category}` : props.item.patternName} {props.item.patternState && ( diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavList.js b/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavList.js index 0f5269041..adac59281 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavList.js +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavList.js @@ -8,14 +8,13 @@ export const NavList = props => { const reorderedChildren = []; const nonViewAllItems = elem.noViewAll - ? children.filter(item => item.patternName !== 'View All') + ? children.filter(item => !item.isDocPattern) : children.filter( - item => - item.patternName !== 'View All' && !item.patternName.includes(' Docs') + item => !item.isDocPattern && !item.patternName.includes(' Docs') ); const viewAllItems = elem.noViewAll ? [] - : children.filter(item => item.patternName === 'View All'); + : children.filter(item => item.isDocPattern); reorderedChildren.push(...viewAllItems, ...nonViewAllItems); From 7dd18f9a39b12f9e644153e5957c6d018a58b321 Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Sun, 26 Apr 2020 22:16:47 +0200 Subject: [PATCH 10/16] #1143: Fix naming of view-all links --- packages/core/src/lib/ui_builder.js | 4 ++-- .../src/scripts/components/pl-nav/pl-nav.js | 1 + .../src/scripts/components/pl-nav/src/NavLink.js | 2 +- .../src/scripts/components/pl-nav/src/NavList.js | 8 +++++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/core/src/lib/ui_builder.js b/packages/core/src/lib/ui_builder.js index e8707b97d..4fa560bfa 100644 --- a/packages/core/src/lib/ui_builder.js +++ b/packages/core/src/lib/ui_builder.js @@ -175,7 +175,7 @@ const ui_builder = function() { */ function addPatternType(patternlab, pattern) { patternlab.patternTypes.push({ - patternTypeLC: pattern.patternGroup.toLowerCase(), + patternTypeLC: _.kebabCase(pattern.patternGroup), patternTypeUC: _.startCase(pattern.patternGroup), patternType: pattern.patternType, patternTypeDash: pattern.patternGroup, //todo verify @@ -234,7 +234,7 @@ const ui_builder = function() { */ function addPatternSubType(patternlab, pattern) { const newSubType = { - patternSubtypeLC: pattern.patternSubGroup.toLowerCase(), + patternSubtypeLC: _.kebabCase(pattern.patternSubGroup), patternSubtypeUC: _.startCase(pattern.patternSubGroup), patternSubtype: pattern.patternSubType, patternSubtypeDash: pattern.patternSubGroup, //todo verify diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js b/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js index b169bb54d..9a2226841 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js @@ -276,6 +276,7 @@ class Nav extends BaseComponent { {patternSubtype.patternSubtypeItems} diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavLink.js b/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavLink.js index 7a7c742de..6a55dabb3 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavLink.js +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavLink.js @@ -16,7 +16,7 @@ export const NavLink = props => { data-patternpartial={props.item.patternPartial} > {props.item.isDocPattern && props.category - ? `${props.category}` + ? `${props.categoryName}` : props.item.patternName} {props.item.patternState && ( diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavList.js b/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavList.js index adac59281..df3665ff0 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavList.js +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/src/NavList.js @@ -4,7 +4,7 @@ import { NavLink } from './NavLink'; import { NavItem } from './NavItem'; export const NavList = props => { - const { children, category, elem } = props; + const { children, category, categoryName, elem } = props; const reorderedChildren = []; const nonViewAllItems = elem.noViewAll @@ -25,6 +25,7 @@ export const NavList = props => { )) ) : ( )} @@ -55,6 +56,7 @@ export const NavList = props => { From cf4f09276a9943f252b87648dd93ce43a3b4c9ec Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Mon, 27 Apr 2020 16:45:18 +0200 Subject: [PATCH 11/16] #1143 don't show all page if noViewall is active --- .../src/scripts/components/pl-nav/pl-nav.js | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js b/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js index 2dbb2409e..8c93d59ed 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.js @@ -307,19 +307,20 @@ class Nav extends BaseComponent { {(window.ishControls === undefined || window.ishControls.ishControlsHide === undefined || (window.ishControls.ishControlsHide['views-all'] !== true && - window.ishControls.ishControlsHide.all !== true)) && ( - - this.handleClick(e, 'all')} - href="styleguide/html/styleguide.html" - class="pl-c-nav__link pl-c-nav__link--pattern" - data-patternpartial="all" - tabindex="0" - > - All - - - )} + window.ishControls.ishControlsHide.all !== true)) && + !this.noViewAll && ( + + this.handleClick(e, 'all')} + href="styleguide/html/styleguide.html" + class="pl-c-nav__link pl-c-nav__link--pattern" + data-patternpartial="all" + tabindex="0" + > + All + + + )} ); } From c27907ff64f01f9f2a3491ae236fad3d0f2d5623 Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Wed, 6 May 2020 17:53:05 +0200 Subject: [PATCH 12/16] #1143: Fix some spell-check errors --- packages/core/src/lib/object_factory.js | 55 +++++++++++++--------- packages/core/src/lib/readDocumentation.js | 2 +- packages/core/src/lib/ui_builder.js | 10 ++-- packages/core/test/object_factory_tests.js | 2 +- 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/packages/core/src/lib/object_factory.js b/packages/core/src/lib/object_factory.js index 06e572527..c9014dfd4 100644 --- a/packages/core/src/lib/object_factory.js +++ b/packages/core/src/lib/object_factory.js @@ -14,16 +14,22 @@ const prefixMatcher = /^_?(\d+-)?/; * * Before changing functionalities of the pattern object please read the following pull requests * to get more details about the behavior of the folder structure + * https://patternlab.io/docs/overview-of-patterns/#heading-deeper-nesting * https://github.com/pattern-lab/patternlab-node/pull/992 * https://github.com/pattern-lab/patternlab-node/pull/1016 * https://github.com/pattern-lab/patternlab-node/pull/1143 * - * @param {String} relPath relative directory + * @param {string} relPath relative directory * @param {Object} jsonFileData The JSON used to render values in the pattern. - * @param {Patternlab} patternlab The actual patternlab instance - * @param {Boolean} isUnsubRun specifies if the pattern needs to be removed from its subfolder + * @param {Patternlab} patternlab The actual pattern lab instance + * @param {boolean} isPromoteToFlatPatternRun specifies if the pattern needs to be removed from its deep nesting folder */ -const Pattern = function(relPath, jsonFileData, patternlab, isUnsubRun) { +const Pattern = function( + relPath, + jsonFileData, + patternlab, + isPromoteToFlatPatternRun +) { this.relPath = path.normalize(relPath); // '00-atoms/00-global/00-colors.mustache' /** @@ -32,13 +38,17 @@ const Pattern = function(relPath, jsonFileData, patternlab, isUnsubRun) { */ const pathObj = path.parse(this.relPath); - const info = this.getPatternInfo(pathObj, patternlab, isUnsubRun); + const info = this.getPatternInfo( + pathObj, + patternlab, + isPromoteToFlatPatternRun + ); this.fileName = pathObj.name; // '00-colors' this.subdir = pathObj.dir; // '00-atoms/00-global' this.fileExtension = pathObj.ext; // '.mustache' - // TODO: Remove if when droping ordering by prefix and keep else code + // TODO: Remove if when dropping ordering by prefix and keep else code if (info.patternHasOwnDir) { // Since there is still the requirement of having the numbers provided for sorting // this will be required to keep the folder prefix and the variant name @@ -80,7 +90,7 @@ const Pattern = function(relPath, jsonFileData, patternlab, isUnsubRun) { // the joined pattern group and subgroup directory this.flatPatternPath = info.shortNotation; // '00-atoms-00-global' - // calculated path from the root of the public directory to the generated + // Calculated path from the root of the public directory to the generated // (rendered!) html file for this pattern, to be shown in the iframe this.patternLink = patternlab ? this.getPatternLink(patternlab, 'rendered') @@ -128,7 +138,7 @@ const Pattern = function(relPath, jsonFileData, patternlab, isUnsubRun) { this.compileState = null; /** - * Timestamp in milliseconds when the pattern template or auxilary file (e.g. json) were modified. + * Timestamp in milliseconds when the pattern template or auxiliary file (e.g. json) were modified. * If multiple files are affected, this is the timestamp of the most recent change. * * @see {@link pattern} @@ -175,8 +185,8 @@ Pattern.prototype = { * Should look something like '00-atoms-00-global-00-colors/00-atoms-00-global-00-colors.html' * * @param {Patternlab} patternlab Current patternlab instance - * @param {String} suffixType File suffix - * @param {String} customfileExtension Custom extension + * @param {string} suffixType File suffix + * @param {string} customfileExtension Custom extension */ getPatternLink: function(patternlab, suffixType, customfileExtension) { // if no suffixType is provided, we default to rendered @@ -216,8 +226,8 @@ Pattern.prototype = { return this.engine.findListItems(this); }, - findPartial: function(partialString) { - return this.engine.findPartial(partialString); + findPartial: function(partialstring) { + return this.engine.findPartial(partialstring); }, /** @@ -235,7 +245,7 @@ Pattern.prototype = { } else if (level >= 1) { return ''; } else { - // Im Not quite shure about that but its better than empty node + // I'm not quite sure about that but its better than empty node // TODO: verify return 'root'; } @@ -248,7 +258,7 @@ Pattern.prototype = { * * @param {Patternlab} patternlab Current patternlab instance */ - resetSubbing: function(patternlab) { + promoteFromDirectoryToFlatPattern: function(patternlab) { const p = new Pattern(this.relPath, this.jsonFileData, patternlab, true); // Only reset the specific fields, not everything Object.assign(this, { @@ -266,17 +276,18 @@ Pattern.prototype = { }, /** - * Info contains information about pattern structure if it is a nested pattern - * or if it just a subfolder structure. Its just used for internal purposes. - * Remember every pattern infomarion based on "this.*" will be used by other functions + * The "info" object contains information about pattern structure if it is + * a nested pattern or if it just a sub folder structure. It's just used for + * internal purposes. Remember every pattern information based on "this.*" + * will be used by other functions * - * @param pathObj path.parse() object containing usefull path information + * @param pathObj path.parse() object containing useful path information */ - getPatternInfo: (pathObj, patternlab, isUnsubRun) => { + getPatternInfo: (pathObj, patternlab, isPromoteToFlatPatternRun) => { const info = { - // 00-colors(.mustache) is subfolder in 00-atoms-/00-global/00-colors + // 00-colors(.mustache) is deeply nested in 00-atoms-/00-global/00-colors patternlab: patternlab, - patternHasOwnDir: !isUnsubRun + patternHasOwnDir: !isPromoteToFlatPatternRun ? path.basename(pathObj.dir).replace(prefixMatcher, '') === pathObj.name.replace(prefixMatcher, '') || path.basename(pathObj.dir).replace(prefixMatcher, '') === @@ -333,7 +344,7 @@ Pattern.createEmpty = function(customProps, patternlab) { }; /** - * factory: creates an Pattern object on-demand from a hash; the hash accepts + * factory: creates a Pattern object on-demand from a hash; the hash accepts * parameters that replace the positional parameters that the Pattern * constructor takes. */ diff --git a/packages/core/src/lib/readDocumentation.js b/packages/core/src/lib/readDocumentation.js index 2d66a7a7f..c28a307cf 100644 --- a/packages/core/src/lib/readDocumentation.js +++ b/packages/core/src/lib/readDocumentation.js @@ -60,7 +60,7 @@ module.exports = function(pattern, patternlab) { !markdownObject.subfolder ) { // Reset to pattern without own pattern-directory - pattern.resetSubbing(patternlab); + pattern.promoteFromDirectoryToFlatPattern(patternlab); } } else { logger.warning(`error processing markdown for ${pattern.patternPartial}`); diff --git a/packages/core/src/lib/ui_builder.js b/packages/core/src/lib/ui_builder.js index 4fa560bfa..ed53764a7 100644 --- a/packages/core/src/lib/ui_builder.js +++ b/packages/core/src/lib/ui_builder.js @@ -263,7 +263,7 @@ const ui_builder = function() { patternPath: pattern.patternLink, name: pattern.name, isDocPattern: false, - order: Number(pattern.order) || 0, // Failsave is someone entered a string + order: Number(pattern.order) || 0, // Failsafe is someone entered a string }; } @@ -355,7 +355,7 @@ const ui_builder = function() { aOrder = Number.MAX_SAFE_INTEGER; } - // alwasy return a docPattern first + // always return a docPattern first if (a.isDocPattern && !b.isDocPattern) { return -1; } @@ -395,7 +395,7 @@ const ui_builder = function() { * Returns an object representing how the front end styleguide and navigation is structured * @param patternlab - global data store * @param uikit - the current uikit being built - * @returns ptterns grouped by type -> subtype like atoms -> global -> pattern, pattern, pattern + * @returns patterns grouped by type -> subtype like atoms -> global -> pattern, pattern, pattern */ function groupPatterns(patternlab, uikit) { const groupedPatterns = { @@ -463,7 +463,7 @@ const ui_builder = function() { * Search all flat patterns of a specific pattern type * * @param {Patternlab} patternlab Current patternlab instance - * @param {String} patternType indicator which patterns to search for + * @param {string} patternType indicator which patterns to search for */ function getFlatPatternItems(patternlab, patternType) { const patterns = _.filter( @@ -617,7 +617,7 @@ const ui_builder = function() { ); /** - * View all pages for goups + * View all pages for groups */ return Promise.all(subTypePromises) .then(() => { diff --git a/packages/core/test/object_factory_tests.js b/packages/core/test/object_factory_tests.js index 6c7b704df..e00dbe9c0 100644 --- a/packages/core/test/object_factory_tests.js +++ b/packages/core/test/object_factory_tests.js @@ -153,7 +153,7 @@ tap.test('test Pattern with own-directory gets resetted as expected', function( test ) { var p = new Pattern('00-atoms/00-button/button.mustache', { d: 123 }, pl); - p.resetSubbing(pl); + p.promoteFromDirectoryToFlatPattern(pl); test.equals(p.relPath, path.join('00-atoms', '00-button', 'button.mustache')); test.equals(p.name, '00-atoms-00-button-button'); From 49c098c181b1ec069ce03ef159808ed73e8d8b21 Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Sat, 9 May 2020 20:30:24 +0200 Subject: [PATCH 13/16] #1143: Remove set current url as it gets fixed in #1202 --- .../pl-viewport-size-list.js | 147 ++++++++++++++++++ .../lit-components/pl-viewport/pl-viewport.js | 4 - 2 files changed, 147 insertions(+), 4 deletions(-) diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size-list/pl-viewport-size-list.js b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size-list/pl-viewport-size-list.js index a93c5fb0e..337540892 100644 --- a/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size-list/pl-viewport-size-list.js +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size-list/pl-viewport-size-list.js @@ -93,6 +93,153 @@ class ViewportSizes extends BaseComponent { } } + /** + * Get a random number between minViewportWidth and maxViewportWidth + */ + getRangeRandomNumber() { + return getRandom( + minViewportWidth, + // Do not evaluate a number higher than the clientWidth of the Iframe + // to prevent having max size multiple times + maxViewportWidth > this.iframe.clientWidth + ? this.iframe.clientWidth + : maxViewportWidth + ); + } + + /** + * Start the disco mode, which means in a specific interval resize + * the iframe random between minViewportWidth and maxViewportWidth + */ + startDisco() { + this.discoMode = true; + this.discoId = setInterval(this.disco.bind(this), 1000); + } + + /** + * Stop the disco mode + */ + killDisco() { + this.discoMode = false; + clearInterval(this.discoId); + this.discoID = null; + } + + /** + * Action to resize the Iframe in disco mode + */ + disco() { + this.iframe.sizeiframe(this.getRangeRandomNumber(), true); + } + + /** + * Start the Hay! mode, which means the iframe is growing slowly + * from minViewportWidth to maxViewportWidth + */ + startHay() { + this.hayMode = true; + this.hayId = setInterval(this.hay.bind(this), 100); + } + + /** + * Stop the Hay! Mode + */ + killHay() { + this.hayMode = false; + clearInterval(this.hayId); + this.hayId = null; + } + + /** + * Action to resize the Iframe in Hay! mode + */ + hay() { + this.iframe.sizeiframe(store.getState().app.viewportPx + 1, true); + } + + /** + * Litte workaround for Firefox Bug. + * + * On QWERTZ keyboards the e.altKey and e.ctrlKey will + * not be set if you click on a key that has a specific + * secondary or third char at ALT + ... + * + * @param {KeyboardEvent} e the keyevent + */ + handleKeyDownEvent(e) { + if (e.key === 'Control') { + this.controlIsPressed = true; + } + if (e.key === 'Alt') { + this.altIsPressed = true; + } + } + + /** + * https://patternlab.io/docs/advanced-keyboard-shortcuts.html + * + * Why use these specific key combinations? + * Works on QUERTZ, QUERTY and AZERTY keyboard and they are no + * reserved browser functionality key combinations. + * + * QUERTY https://en.wikipedia.org/wiki/QWERTY + * QUERTZ https://en.wikipedia.org/wiki/QWERTZ + * AZERTY https://en.wikipedia.org/wiki/AZERTY + * + * Chromium + * https://support.google.com/chrome/answer/157179?hl=en + * + * Firefox + * https://support.mozilla.org/en-US/kb/keyboard-shortcuts-perform-firefox-tasks-quickly + * + * @param {KeyboardEvent} e the keyevent + + */ + handleKeyCombination(e) { + const ctrlKey = this.controlIsPressed; + const altKey = this.altIsPressed; + + if (ctrlKey && altKey && (e.code === 'Digit0' || e.code === 'Numpad0')) { + this.resizeViewport(this.sizes.ZERO); + } else if (ctrlKey && altKey && e.code === 'KeyS') { + this.resizeViewport(this.sizes.SMALL); + } else if (ctrlKey && altKey && e.code === 'KeyM') { + this.resizeViewport(this.sizes.MEDIUM); + } else if (ctrlKey && altKey && e.code === 'KeyL') { + this.resizeViewport(this.sizes.LARGE); + } else if (ctrlKey && altKey && e.code === 'KeyF') { + this.resizeViewport(this.sizes.FULL); + } else if (ctrlKey && altKey && e.code === 'KeyR') { + this.resizeViewport(this.sizes.RANDOM); + } else if (ctrlKey && altKey && e.code === 'KeyD') { + this.resizeViewport(this.sizes.DISCO); + } else if (ctrlKey && altKey && e.code === 'KeyH') { + this.resizeViewport(this.sizes.HAY); + } + + if (e.key === 'Control') { + this.controlIsPressed = false; + } + if (e.key === 'Alt') { + this.altIsPressed = false; + } + } + + /** + * Interpret and handle the received message input + * + * @param {MessageEvent} e A message received by a target object. + */ + receiveIframeMessage(e) { + const data = iframeMsgDataExtraction(e); + + if (data.event && data.event === 'patternLab.iframeKeyDownEvent') { + this.handleKeyDownEvent(data); + } else if (data.event && data.event === 'patternLab.iframeKeyUpEvent') { + this.handleKeyCombination(data); + } + } + rendered() { this.iframe = document.querySelector('pl-iframe'); this.iframeElem = document.querySelector('pl-iframe iframe'); diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.js b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.js index 8fd02933a..99a456810 100644 --- a/packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.js +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.js @@ -491,10 +491,6 @@ class IFrame extends BaseLitComponent { this.sanitizePatternName(event.data.patternpartial) || this.getPatternParam(); - store.dispatch( - updateCurrentUrl(urlHandler.getFileName(currentPattern)) - ); - document.title = 'Pattern Lab - ' + currentPattern; const addressReplacement = From 2022f642e6c0f809d019b613bd863ac1fa9dbf23 Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Wed, 1 Jul 2020 19:30:48 +0200 Subject: [PATCH 14/16] #1143: Make flat patterns on view all pages optional --- .../cli/test/fixtures/patternlab-config.json | 1 + packages/core/patternlab-config.json | 1 + packages/core/src/lib/ui_builder.js | 35 ++++++--- packages/core/test/ui_builder_tests.js | 74 ++++++++++++++++++- .../core/test/util/patternlab-config.json | 1 + .../patternlab-config.json | 3 +- .../patternlab-config.json | 1 + .../patternlab-config.json | 1 + .../docs/src/docs/advanced-config-options.md | 13 ++++ .../edition-node-gulp/patternlab-config.json | 1 + packages/edition-node/patternlab-config.json | 1 + packages/edition-twig/patternlab-config.json | 1 + 12 files changed, 121 insertions(+), 12 deletions(-) diff --git a/packages/cli/test/fixtures/patternlab-config.json b/packages/cli/test/fixtures/patternlab-config.json index 4bd371e26..b59f39961 100644 --- a/packages/cli/test/fixtures/patternlab-config.json +++ b/packages/cli/test/fixtures/patternlab-config.json @@ -73,6 +73,7 @@ "patternExportDirectory": "./pattern_exports/", "patternExportPatternPartials": [], "patternMergeVariantArrays": true, + "renderFlatPatternsOnViewAllPages": false, "serverOptions": { "wait": 1000 }, diff --git a/packages/core/patternlab-config.json b/packages/core/patternlab-config.json index 28d62a2d0..519282d2c 100644 --- a/packages/core/patternlab-config.json +++ b/packages/core/patternlab-config.json @@ -76,6 +76,7 @@ "patternExportPreserveDirectoryStructure": true, "patternExportRaw": false, "patternMergeVariantArrays": true, + "renderFlatPatternsOnViewAllPages": false, "serverOptions": { "wait": 1000 }, diff --git a/packages/core/src/lib/ui_builder.js b/packages/core/src/lib/ui_builder.js index ed53764a7..4a077a613 100644 --- a/packages/core/src/lib/ui_builder.js +++ b/packages/core/src/lib/ui_builder.js @@ -417,7 +417,12 @@ const ui_builder = function() { groupedPatterns.patternGroups[pattern.patternGroup] = {}; pattern.isSubtypePattern = false; addPatternType(patternlab, pattern); - addPatternItem(patternlab, pattern, true); + if ( + !pattern.isFlatPattern || + patternlab.config.renderFlatPatternsOnViewAllPages + ) { + addPatternItem(patternlab, pattern, true); + } addToViewAllPaths(patternlab, pattern); } @@ -629,15 +634,17 @@ const ui_builder = function() { patternType ); - // Check if this is a flat pattern group - typePatterns = sortedFlatPatterns.concat(typePatterns); + if (patternlab.config.renderFlatPatternsOnViewAllPages) { + // Check if this is a flat pattern group + typePatterns = sortedFlatPatterns.concat(typePatterns); + } // get the appropriate patternType const anyPatternOfType = _.find(typePatterns, function(pat) { return pat.patternType && pat.patternType !== ''; }); - if (!anyPatternOfType) { + if (!anyPatternOfType || !typePatterns.length) { logger.debug( `skipping ${patternType} as flat patterns do not have view all pages` ); @@ -676,8 +683,12 @@ const ui_builder = function() { `Omitting ${patternType} from building a viewall page because its patternGroup is specified in styleguideExcludes.` ); } else { - patterns = sortedFlatPatterns; - patterns = patterns.concat(styleguideTypePatterns); + if (patternlab.config.renderFlatPatternsOnViewAllPages) { + patterns = sortedFlatPatterns; + patterns = patterns.concat(styleguideTypePatterns); + } else { + patterns = styleguideTypePatterns; + } } return Promise.resolve(patterns); }) @@ -698,10 +709,14 @@ const ui_builder = function() { } ); - return Promise.all(allPatternTypePromises).catch(reason => { - console.log(reason); - logger.error('Error during buildViewAllPages'); - }); + return Promise.all(allPatternTypePromises) + .then(allPatterns => + Promise.resolve(_.filter(allPatterns, p => p.length)) + ) + .catch(reason => { + console.log(reason); + logger.error('Error during buildViewAllPages'); + }); } /** diff --git a/packages/core/test/ui_builder_tests.js b/packages/core/test/ui_builder_tests.js index 3ac42f2f1..00fd29ec0 100644 --- a/packages/core/test/ui_builder_tests.js +++ b/packages/core/test/ui_builder_tests.js @@ -527,7 +527,7 @@ tap.test('resetUIBuilderState - reset global objects', function(test) { }); tap.test( - 'buildViewAllPages - adds viewall page for each type and subtype', + 'buildViewAllPages - adds viewall page for each type and subtype NOT! for flat patterns', function(test) { //arrange const mainPageHeadHtml = ''; @@ -554,6 +554,76 @@ tap.test( const styleguidePatterns = ui.groupPatterns(patternlab, uikit); + //act + ui.buildViewAllPages( + mainPageHeadHtml, + patternlab, + styleguidePatterns, + uikit + ).then(allPatterns => { + // assert + // this was a nuanced one. buildViewAllPages() had return false; statements + // within _.forOwn(...) loops, causing premature termination of the entire loop + // when what was intended was a continue + // we expect 10 here because: + // - foo.mustache is flat and therefore does not have a viewall page + // - the colors.mustache files make 6 + // - patternSubType1 and patternSubType2 make 8 + // - the general view all page make 9 + // while most of that heavy lifting occurs inside groupPatterns and not buildViewAllPages, + // it's important to ensure that this method does not get prematurely terminated + // we choose to do that by checking it's return number of patterns + + const uniquePatterns = ui.uniqueAllPatterns(allPatterns, patternlab); + + /** + * - view-patternType1-all + * -- viewall-patternType1-patternSubType1 + * --- blue + * --- red + * --- yellow + * -- viewall-patternType1-patternSubType2 + * --- black + * --- grey + * --- white + */ + test.equals(uniquePatterns.length, 9, '3 viewall pages should be added'); + + test.end(); + }); + } +); + +tap.test( + 'buildViewAllPages - adds viewall page for each type and subtype FOR! flat patterns', + function(test) { + //arrange + const mainPageHeadHtml = ''; + const patternlab = createFakePatternLab({ + patterns: [], + patternGroups: {}, + subtypePatterns: {}, + footer: {}, + userFoot: {}, + cacheBuster: 1234, + }); + + patternlab.config.renderFlatPatternsOnViewAllPages = true; + + patternlab.patterns.push( + //this flat pattern is found and causes trouble for the rest of the crew + new Pattern('00-test/foo.mustache'), + new Pattern('patternType1/patternSubType1/blue.mustache'), + new Pattern('patternType1/patternSubType1/red.mustache'), + new Pattern('patternType1/patternSubType1/yellow.mustache'), + new Pattern('patternType1/patternSubType2/black.mustache'), + new Pattern('patternType1/patternSubType2/grey.mustache'), + new Pattern('patternType1/patternSubType2/white.mustache') + ); + ui.resetUIBuilderState(patternlab); + + const styleguidePatterns = ui.groupPatterns(patternlab, uikit); + //act ui.buildViewAllPages( mainPageHeadHtml, @@ -569,6 +639,8 @@ tap.test( // - foo.mustache is flat and therefore does not have a viewall page // - the colors.mustache files make 6 // - patternSubType1 and patternSubType2 make 8 + // - the general view all page make 9 + // - the view-all page of test and test-foo make 11 // while most of that heavy lifting occurs inside groupPatterns and not buildViewAllPages, // it's important to ensure that this method does not get prematurely terminated // we choose to do that by checking it's return number of patterns diff --git a/packages/core/test/util/patternlab-config.json b/packages/core/test/util/patternlab-config.json index 904e37afd..f4f1396c5 100644 --- a/packages/core/test/util/patternlab-config.json +++ b/packages/core/test/util/patternlab-config.json @@ -58,6 +58,7 @@ "patternExportDirectory": "./pattern_exports/", "patternExtension": "mustache", "patternMergeVariantArrays": true, + "renderFlatPatternsOnViewAllPages": false, "cacheBust": true, "outputFileSuffixes": { "rendered": ".rendered", diff --git a/packages/development-edition-engine-handlebars/patternlab-config.json b/packages/development-edition-engine-handlebars/patternlab-config.json index 141f35a47..0ba471dd2 100644 --- a/packages/development-edition-engine-handlebars/patternlab-config.json +++ b/packages/development-edition-engine-handlebars/patternlab-config.json @@ -70,7 +70,8 @@ "patternExportPatternPartials": [], "patternExportPreserveDirectoryStructure": true, "patternExportRaw": false, - "patternMergeVariantArrays": true, + "patternMergeVariantArrays": false, + "renderFlatPatternsOnViewAllPages": false, "serverOptions": { "wait": 1000 }, diff --git a/packages/development-edition-engine-react/patternlab-config.json b/packages/development-edition-engine-react/patternlab-config.json index dd4efbd24..106d0f983 100644 --- a/packages/development-edition-engine-react/patternlab-config.json +++ b/packages/development-edition-engine-react/patternlab-config.json @@ -76,6 +76,7 @@ "patternExportDirectory": "./pattern_exports/", "patternExportPatternPartials": [], "patternMergeVariantArrays": true, + "renderFlatPatternsOnViewAllPages": false, "serverOptions": { "wait": 1000 }, diff --git a/packages/development-edition-engine-twig/patternlab-config.json b/packages/development-edition-engine-twig/patternlab-config.json index 55fed5c95..77377bab0 100644 --- a/packages/development-edition-engine-twig/patternlab-config.json +++ b/packages/development-edition-engine-twig/patternlab-config.json @@ -81,6 +81,7 @@ "patternExportDirectory": "pattern_exports", "patternExportPatternPartials": [], "patternMergeVariantArrays": true, + "renderFlatPatternsOnViewAllPages": false, "serverOptions": { "wait": 1000 }, diff --git a/packages/docs/src/docs/advanced-config-options.md b/packages/docs/src/docs/advanced-config-options.md index bba2d18df..026393be6 100644 --- a/packages/docs/src/docs/advanced-config-options.md +++ b/packages/docs/src/docs/advanced-config-options.md @@ -199,6 +199,19 @@ Used to override the merge behavior of pattern variants. For more information se **default**: `true` | `undefined` +### renderFlatPatternsOnViewAllPages + +Used to activate rendering flat patterns on view all pages and generate view all pages if only flat patterns are available + +- `true` will render flat patterns on view all pages +- `false` will make flat patterns available only in the menu + +```javascript +"renderFlatPatternsOnViewAllPages": true, +``` + +**default**: `false` | `undefined` + ### serverOptions Sets live-server options. See the [live-server documentation](https://github.com/pattern-lab/live-server#usage-from-node) for more details. diff --git a/packages/edition-node-gulp/patternlab-config.json b/packages/edition-node-gulp/patternlab-config.json index e24473a02..02d705683 100644 --- a/packages/edition-node-gulp/patternlab-config.json +++ b/packages/edition-node-gulp/patternlab-config.json @@ -76,6 +76,7 @@ "patternExportPreserveDirectoryStructure": true, "patternExportRaw": false, "patternMergeVariantArrays": true, + "renderFlatPatternsOnViewAllPages": false, "serverOptions": { "wait": 1000 }, diff --git a/packages/edition-node/patternlab-config.json b/packages/edition-node/patternlab-config.json index 3112f5ac0..70fe58eca 100644 --- a/packages/edition-node/patternlab-config.json +++ b/packages/edition-node/patternlab-config.json @@ -76,6 +76,7 @@ "patternExportPreserveDirectoryStructure": true, "patternExportRaw": false, "patternMergeVariantArrays": true, + "renderFlatPatternsOnViewAllPages": false, "serverOptions": { "wait": 1000 }, diff --git a/packages/edition-twig/patternlab-config.json b/packages/edition-twig/patternlab-config.json index ee6acd691..3dddbfa29 100644 --- a/packages/edition-twig/patternlab-config.json +++ b/packages/edition-twig/patternlab-config.json @@ -140,6 +140,7 @@ "patternExportPreserveDirectoryStructure": true, "patternExportRaw": false, "patternMergeVariantArrays": true, + "renderFlatPatternsOnViewAllPages": false, "serverOptions": { "wait": 1000 }, From dff100097b343dedfd979f91c8316677660479f1 Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Wed, 1 Jul 2020 20:32:04 +0200 Subject: [PATCH 15/16] #1143 update deeper nesting See https://patternlab.io/docs/overview-of-patterns/#heading-deeper-nesting --- packages/core/src/lib/object_factory.js | 2 +- packages/core/src/lib/readDocumentation.js | 7 ++++--- packages/docs/src/docs/pattern-organization.md | 9 +++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/core/src/lib/object_factory.js b/packages/core/src/lib/object_factory.js index c9014dfd4..e4523d9bd 100644 --- a/packages/core/src/lib/object_factory.js +++ b/packages/core/src/lib/object_factory.js @@ -258,7 +258,7 @@ Pattern.prototype = { * * @param {Patternlab} patternlab Current patternlab instance */ - promoteFromDirectoryToFlatPattern: function(patternlab) { + promoteFromFlatPatternToDirectory: function(patternlab) { const p = new Pattern(this.relPath, this.jsonFileData, patternlab, true); // Only reset the specific fields, not everything Object.assign(this, { diff --git a/packages/core/src/lib/readDocumentation.js b/packages/core/src/lib/readDocumentation.js index c28a307cf..edd11de6e 100644 --- a/packages/core/src/lib/readDocumentation.js +++ b/packages/core/src/lib/readDocumentation.js @@ -56,11 +56,12 @@ module.exports = function(pattern, patternlab) { } if ( - markdownObject.hasOwnProperty('subfolder') && - !markdownObject.subfolder + !markdownObject.hasOwnProperty('deeplyNested') || + (markdownObject.hasOwnProperty('deeplyNested') && + !markdownObject.deeplyNested) ) { // Reset to pattern without own pattern-directory - pattern.promoteFromDirectoryToFlatPattern(patternlab); + pattern.promoteFromFlatPatternToDirectory(patternlab); } } else { logger.warning(`error processing markdown for ${pattern.patternPartial}`); diff --git a/packages/docs/src/docs/pattern-organization.md b/packages/docs/src/docs/pattern-organization.md index ff3cab5ad..d7839c7dd 100644 --- a/packages/docs/src/docs/pattern-organization.md +++ b/packages/docs/src/docs/pattern-organization.md @@ -50,3 +50,12 @@ Node versions support nesting of folders under `patternSubtype`. For example, yo In this example the `media-block/` directory is ignored for the purposes of generating breadcrumbs and navigation in the Pattern Lab front-end but the documentation, pattern and pseudo-patterns are still rendered. Folders can be nested under `media-block/` if desired but this is discouraged because of possible collisions when using the [shorthand partial syntax](/docs/including-patterns/). + +### Deeper Nesting Settings + +As documented in [Documenting Patterns](/docs/documenting-patterns/) there are several options to handle the patterns state or add additional information. + +The `deeplyNested` attribute is used to toggle the pattern building behavior and toggles the deeper nesting. + +- **deeplyNested not set or false** - Pattern won't be handled as a deeply nested pattern +- **deeplyNested: true** - Pattern will be handled like mentioned under [Deeper Nesting](#heading-deeper-nesting) From 243eef0f916037861c928c574ef4bab4db580597 Mon Sep 17 00:00:00 2001 From: Josef Bredreck Date: Wed, 1 Jul 2020 20:46:25 +0200 Subject: [PATCH 16/16] #1143 Fix test --- packages/core/test/object_factory_tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/test/object_factory_tests.js b/packages/core/test/object_factory_tests.js index e00dbe9c0..b561e8fa9 100644 --- a/packages/core/test/object_factory_tests.js +++ b/packages/core/test/object_factory_tests.js @@ -153,7 +153,7 @@ tap.test('test Pattern with own-directory gets resetted as expected', function( test ) { var p = new Pattern('00-atoms/00-button/button.mustache', { d: 123 }, pl); - p.promoteFromDirectoryToFlatPattern(pl); + p.promoteFromFlatPatternToDirectory(pl); test.equals(p.relPath, path.join('00-atoms', '00-button', 'button.mustache')); test.equals(p.name, '00-atoms-00-button-button');