Skip to content

Commit d1220d5

Browse files
committed
Merge branch 'recursive-partial-include' of https://github.com/e2tha-e/patternlab-node into e2tha-e-recursive-partial-include
2 parents 6fc72a2 + 0d1082c commit d1220d5

File tree

8 files changed

+213
-24
lines changed

8 files changed

+213
-24
lines changed

builder/object_factory.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111
(function () {
1212
"use strict";
1313

14-
var oPattern = function(subdir, filename, data){
14+
var oPattern = function(abspath, subdir, filename, data){
1515
this.fileName = filename.substring(0, filename.indexOf('.'));
16+
this.abspath = abspath;
1617
this.subdir = subdir;
1718
this.name = subdir.replace(/[\/\\]/g, '-') + '-' + this.fileName; //this is the unique name with the subDir
1819
this.jsonFileData = data || {};
19-
this.patternName = this.fileName.substring(this.fileName.indexOf('-') + 1); //this is the display name for the ui
20+
this.patternName = this.fileName.replace(/^\d*\-/, ''); //this is the display name for the ui. strip numeric + hyphen prefixes
2021
this.patternLink = this.name + '/' + this.name + '.html';
2122
this.patternGroup = this.name.substring(this.name.indexOf('-') + 1, this.name.indexOf('-', 4) + 1 - this.name.indexOf('-') + 1);
2223
this.patternSubGroup = subdir.substring(subdir.indexOf('/') + 4);

builder/pattern_assembler.js

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,22 @@
4444

4545
function addPattern(pattern, patternlab){
4646
patternlab.data.link[pattern.patternGroup + '-' + pattern.patternName] = '/patterns/' + pattern.patternLink;
47-
patternlab.patterns.push(pattern);
47+
48+
//only push to array if the array doesn't contain this pattern
49+
var isNew = true;
50+
for(var i = 0; i < patternlab.patterns.length; i++){
51+
//so we need the identifier to be unique, which patterns[i].abspath is
52+
if(pattern.abspath === patternlab.patterns[i].abspath){
53+
//if abspath already exists, overwrite that element
54+
patternlab.patterns[i] = pattern;
55+
isNew = false;
56+
break;
57+
}
58+
}
59+
//if the pattern is new, just push to the array
60+
if(isNew){
61+
patternlab.patterns.push(pattern);
62+
}
4863
}
4964

5065
function renderPattern(template, data, partials) {
@@ -58,23 +73,38 @@
5873
}
5974
}
6075

61-
function processPatternFile(file, patternlab){
76+
function processPatternIterative(file, patternlab){
6277
var fs = require('fs-extra'),
6378
of = require('./object_factory'),
6479
path = require('path');
6580

6681
//extract some information
67-
var abspath = file.substring(2);
6882
var subdir = path.dirname(path.relative(patternlab.config.patterns.source, file)).replace('\\', '/');
6983
var filename = path.basename(file);
84+
var ext = path.extname(filename);
7085

71-
//ignore _underscored patterns, json (for now), and dotfiles
72-
if(filename.charAt(0) === '_' || path.extname(filename) === '.json' || filename.charAt(0) === '.'){
86+
//ignore dotfiles and non-variant .json files
87+
if(filename.charAt(0) === '.' || (ext === '.json' && filename.indexOf('~') === -1)){
7388
return;
7489
}
7590

7691
//make a new Pattern Object
77-
var currentPattern = new of.oPattern(subdir, filename);
92+
var currentPattern = new of.oPattern(file, subdir, filename);
93+
94+
//if file is named in the syntax for variants
95+
if(ext === '.json' && filename.indexOf('~') > -1){
96+
//add current pattern to patternlab object with minimal data
97+
//processPatternRecursive() will run find_pseudopatterns() to fill out
98+
//the object in the next diveSync
99+
addPattern(currentPattern, patternlab);
100+
//no need to process further
101+
return;
102+
}
103+
104+
//can ignore all non-mustache files at this point
105+
if(ext !== '.mustache'){
106+
return;
107+
}
78108

79109
//see if this file has a state
80110
setState(currentPattern, patternlab);
@@ -98,13 +128,13 @@
98128
}
99129

100130
//add the raw template to memory
101-
currentPattern.template = fs.readFileSync(abspath, 'utf8');
131+
currentPattern.template = fs.readFileSync(file, 'utf8');
102132

103-
//our helper function that does a lot of heavy lifting
104-
processPattern(currentPattern, patternlab);
133+
//add currentPattern to patternlab.patterns array
134+
addPattern(currentPattern, patternlab);
105135
}
106136

107-
function processPattern(currentPattern, patternlab, additionalData){
137+
function processPatternRecursive(file, patternlab, additionalData){
108138

109139
var fs = require('fs-extra'),
110140
mustache = require('mustache'),
@@ -119,6 +149,21 @@
119149
list_item_hunter = new lih(),
120150
pseudopattern_hunter = new pph();
121151

152+
//find current pattern in patternlab object using var file as a key
153+
var currentPattern,
154+
i;
155+
156+
for(i = 0; i < patternlab.patterns.length; i++){
157+
if(patternlab.patterns[i].abspath === file){
158+
currentPattern = patternlab.patterns[i];
159+
}
160+
}
161+
162+
//return if processing an ignored file
163+
if(typeof currentPattern === 'undefined'){
164+
return;
165+
}
166+
122167
currentPattern.extendedTemplate = currentPattern.template;
123168

124169
//find how many partials there may be for the given pattern
@@ -137,8 +182,23 @@
137182
parameter_hunter.find_parameters(currentPattern, patternlab);
138183

139184
//do something with the regular old partials
140-
for(var i = 0; i < foundPatternPartials.length; i++){
185+
for(i = 0; i < foundPatternPartials.length; i++){
141186
var partialKey = foundPatternPartials[i].replace(/{{>([ ])?([\w\-\.\/~]+)(?:\:[A-Za-z0-9-]+)?(?:(| )\(.*)?([ ])?}}/g, '$2');
187+
var partialPath;
188+
189+
//identify which pattern this partial corresponds to
190+
for(var j = 0; j < patternlab.patterns.length; j++){
191+
if(patternlab.patterns[j].key === partialKey ||
192+
patternlab.patterns[j].abspath.indexOf(partialKey) > -1)
193+
{
194+
partialPath = patternlab.patterns[j].abspath;
195+
}
196+
}
197+
198+
//recurse through nested partials to fill out this extended template.
199+
processPatternRecursive(partialPath, patternlab);
200+
201+
//complete assembly of extended template
142202
var partialPattern = getpatternbykey(partialKey, patternlab);
143203
currentPattern.extendedTemplate = currentPattern.extendedTemplate.replace(foundPatternPartials[i], partialPattern.extendedTemplate);
144204
}
@@ -248,11 +308,11 @@
248308
renderPattern: function(template, data, partials){
249309
return renderPattern(template, data, partials);
250310
},
251-
process_pattern_file: function(file, patternlab){
252-
processPatternFile(file, patternlab);
311+
process_pattern_iterative: function(file, patternlab){
312+
processPatternIterative(file, patternlab);
253313
},
254-
process_pattern: function(pattern, patternlab, additionalData){
255-
processPattern(pattern, patternlab, additionalData);
314+
process_pattern_recursive: function(file, patternlab, additionalData){
315+
processPatternRecursive(file, patternlab, additionalData);
256316
},
257317
get_pattern_by_key: function(key, patternlab){
258318
return getpatternbykey(key, patternlab);

builder/patternlab.js

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ var patternlab_engine = function () {
7070

7171
pattern_assembler.combine_listItems(patternlab);
7272

73+
//diveSync once to perform iterative populating of patternlab object
7374
diveSync(patterns_dir, {
7475
filter: function(path, dir) {
7576
if(dir){
@@ -87,7 +88,29 @@ var patternlab_engine = function () {
8788
return;
8889
}
8990

90-
pattern_assembler.process_pattern_file(file, patternlab);
91+
pattern_assembler.process_pattern_iterative(file.substring(2), patternlab);
92+
});
93+
94+
//diveSync again to recursively include partials, filling out the
95+
//extendedTemplate property of the patternlab.patterns elements
96+
diveSync(patterns_dir, {
97+
filter: function(path, dir) {
98+
if(dir){
99+
var remainingPath = path.replace(patterns_dir, '');
100+
var isValidPath = remainingPath.indexOf('/_') === -1;
101+
return isValidPath;
102+
}
103+
return true;
104+
}
105+
},
106+
function(err, file){
107+
//log any errors
108+
if(err){
109+
console.log(err);
110+
return;
111+
}
112+
113+
pattern_assembler.process_pattern_recursive(file.substring(2), patternlab);
91114
});
92115

93116
//delete the contents of config.patterns.public before writing
@@ -142,6 +165,11 @@ var patternlab_engine = function () {
142165
i;
143166

144167
for (i = 0; i < patternlab.patterns.length; i++) {
168+
// skip underscore-prefixed files
169+
if (path.basename(patternlab.patterns[i].abspath).charAt(0) === '_') {
170+
continue;
171+
}
172+
145173
var pattern = patternlab.patterns[i];
146174

147175
// check if the current sub section is different from the previous one
@@ -170,6 +198,11 @@ var patternlab_engine = function () {
170198
//loop through all patterns.to build the navigation
171199
//todo: refactor this someday
172200
for(var i = 0; i < patternlab.patterns.length; i++){
201+
// skip underscore-prefixed files
202+
if (path.basename(patternlab.patterns[i].abspath).charAt(0) === '_') {
203+
continue;
204+
}
205+
173206
var pattern = patternlab.patterns[i];
174207
var bucketName = pattern.name.replace(/\\/g, '-').split('-')[1];
175208

@@ -239,7 +272,10 @@ var patternlab_engine = function () {
239272
var bucket = patternlab.buckets[bucketIndex];
240273

241274
//get the navItem
242-
var navItemName = pattern.subdir.split('-').pop();
275+
//if there is one or more slashes in the subdir, get everything after
276+
//the last slash. if no slash, get the whole subdir string and strip
277+
//any numeric + hyphen prefix
278+
var navItemName = pattern.subdir.split('/').pop().replace(/^\d*\-/, '');
243279

244280
//get the navSubItem
245281
var navSubItemName = pattern.patternName.replace(/-/g, ' ');

builder/pseudopattern_hunter.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@
4848
variantFileData = pattern_assembler.merge_data(currentPattern.jsonFileData, variantFileData);
4949

5050
var variantName = pseudoPatterns[i].substring(pseudoPatterns[i].indexOf('~') + 1).split('.')[0];
51-
var patternVariant = new of.oPattern(currentPattern.subdir, currentPattern.fileName + '-' + variantName + '.mustache', variantFileData);
51+
var variantFilePath = 'source/_patterns/' + currentPattern.subdir + '/' + currentPattern.fileName + '~' + variantName + '.json';
52+
var variantFileName = currentPattern.fileName + '-' + variantName + '.';
53+
var patternVariant = new of.oPattern(variantFilePath, currentPattern.subdir, variantFileName, variantFileData);
5254

5355
//see if this file has a state
5456
pattern_assembler.setPatternState(patternVariant, patternlab);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{> test-bar }}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
bar

test/object_factory_tests.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55

66
exports['oPattern initialization'] = {
77
'test oPattern initializes correctly' : function(test){
8-
var p = new of.oPattern('00-atoms/00-global', '00-colors.mustache', { d: 123});
8+
var p = new of.oPattern('source/_patterns/00-atoms/00-global/00-colors.mustache', '00-atoms/00-global', '00-colors.mustache', { d: 123});
99
test.equals(p.name, '00-atoms-00-global-00-colors');
10+
test.equals(p.abspath, 'source/_patterns/00-atoms/00-global/00-colors.mustache');
1011
test.equals(p.subdir, '00-atoms/00-global');
1112
test.equals(p.fileName, '00-colors');
1213
test.equals(p.jsonFileData.d, 123);
@@ -59,4 +60,4 @@
5960
}
6061
};
6162

62-
}());
63+
}());

test/pattern_assembler_tests.js

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,95 @@
3636
test.equals(results[1], '{{> 01-molecules/06-components/02-single-comment(description: \'A life is like a garden. Perfect moments can be had, but not preserved, except in memory.\') }}');
3737

3838
test.done();
39-
}
39+
},
4040

41-
};
41+
'process_pattern_recursive recursively includes partials' : function(test){
42+
43+
//tests inclusion of partial that will be discovered by diveSync later in iteration than parent
44+
//prepare to diveSync
45+
var diveSync = require('diveSync');
46+
var fs = require('fs-extra');
47+
var pa = require('../builder/pattern_assembler');
48+
var pattern_assembler = new pa();
49+
var patterns_dir = './test/files/_patterns';
50+
var patternlab = {};
51+
patternlab.config = fs.readJSONSync('./config.json');
52+
patternlab.config.patterns = {source: patterns_dir};
53+
patternlab.data = fs.readJSONSync('./source/_data/data.json');
54+
patternlab.listitems = fs.readJSONSync('./source/_data/listitems.json');
55+
patternlab.header = fs.readFileSync('./source/_patternlab-files/pattern-header-footer/header.html', 'utf8');
56+
patternlab.footer = fs.readFileSync('./source/_patternlab-files/pattern-header-footer/footer.html', 'utf8');
57+
patternlab.patterns = [];
58+
patternlab.data.link = {};
59+
patternlab.partials = {};
60+
61+
//diveSync once to perform iterative populating of patternlab object
62+
diveSync(patterns_dir,
63+
{
64+
filter: function(path, dir){
65+
if(dir){
66+
var remainingPath = path.replace(patterns_dir, '');
67+
var isValidPath = remainingPath.indexOf('/_') === -1;
68+
return isValidPath;
69+
}
70+
return true;
71+
}
72+
},
73+
function(err, file){
74+
//log any errors
75+
if(err){
76+
console.log(err);
77+
return;
78+
}
79+
80+
pattern_assembler.process_pattern_iterative(file.substring(2), patternlab);
81+
}
82+
);
83+
84+
//diveSync again to recursively include partials, filling out the
85+
//extendedTemplate property of the patternlab.patterns elements
86+
diveSync(patterns_dir,
87+
{
88+
filter: function(path, dir){
89+
if(dir){
90+
var remainingPath = path.replace(patterns_dir, '');
91+
var isValidPath = remainingPath.indexOf('/_') === -1;
92+
return isValidPath;
93+
}
94+
return true;
95+
}
96+
},
97+
function(err, file){
98+
//log any errors
99+
if(err){
100+
console.log(err);
101+
return;
102+
}
42103

104+
pattern_assembler.process_pattern_recursive(file.substring(2), patternlab);
105+
}
106+
);
107+
108+
//get test output for comparison
109+
var foo = fs.readFileSync(patterns_dir + '/00-test/00-foo.mustache', 'utf8').trim();
110+
var bar = fs.readFileSync(patterns_dir + '/00-test/01-bar.mustache', 'utf8').trim();
111+
var fooExtended;
112+
113+
//get extended pattern
114+
for(var i = 0; i < patternlab.patterns.length; i++){
115+
if(patternlab.patterns[i].fileName === '00-foo'){
116+
fooExtended = patternlab.patterns[i].extendedTemplate.trim();
117+
break;
118+
}
119+
}
120+
121+
//check initial values
122+
test.equals(foo, '{{> test-bar }}');
123+
test.equals(bar, 'bar');
124+
//test that 00-foo.mustache included partial 01-bar.mustache
125+
test.equals(fooExtended, 'bar');
126+
127+
test.done();
128+
}
129+
};
43130
}());

0 commit comments

Comments
 (0)