|
1 | 1 | /*
|
2 |
| - * patternlab-node - v0.12.0 - 2015 |
| 2 | + * patternlab-node - v0.13.0 - 2015 |
3 | 3 | *
|
4 | 4 | * Brian Muenzenmeyer, and the web community.
|
5 | 5 | * Licensed under the MIT license.
|
|
44 | 44 |
|
45 | 45 | function addPattern(pattern, patternlab){
|
46 | 46 | 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 | + } |
48 | 63 | }
|
49 | 64 |
|
50 | 65 | function renderPattern(template, data, partials) {
|
|
58 | 73 | }
|
59 | 74 | }
|
60 | 75 |
|
61 |
| - function processPatternFile(file, patternlab){ |
| 76 | + function processPatternIterative(file, patternlab){ |
62 | 77 | var fs = require('fs-extra'),
|
63 | 78 | of = require('./object_factory'),
|
64 | 79 | path = require('path');
|
65 | 80 |
|
66 | 81 | //extract some information
|
67 |
| - var abspath = file.substring(2); |
68 | 82 | var subdir = path.dirname(path.relative(patternlab.config.patterns.source, file)).replace('\\', '/');
|
69 | 83 | var filename = path.basename(file);
|
| 84 | + var ext = path.extname(filename); |
70 | 85 |
|
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)){ |
73 | 88 | return;
|
74 | 89 | }
|
75 | 90 |
|
76 | 91 | //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 | + } |
78 | 108 |
|
79 | 109 | //see if this file has a state
|
80 | 110 | setState(currentPattern, patternlab);
|
|
83 | 113 | try {
|
84 | 114 | var jsonFilename = patternlab.config.patterns.source + currentPattern.subdir + '/' + currentPattern.fileName + ".json";
|
85 | 115 | currentPattern.jsonFileData = fs.readJSONSync(jsonFilename.substring(2));
|
86 |
| - console.log('found pattern-specific data.json for ' + currentPattern.key); |
| 116 | + if(patternlab.config.debug){ |
| 117 | + console.log('found pattern-specific data.json for ' + currentPattern.key); |
| 118 | + } |
87 | 119 | }
|
88 | 120 | catch(e) {
|
89 | 121 | }
|
|
92 | 124 | try {
|
93 | 125 | var listJsonFileName = patternlab.config.patterns.source + currentPattern.subdir + '/' + currentPattern.fileName + ".listitems.json";
|
94 | 126 | currentPattern.patternSpecificListJson = fs.readJSONSync(listJsonFileName.substring(2));
|
95 |
| - console.log('found pattern-specific listitems.json for ' + currentPattern.key); |
| 127 | + if(patternlab.config.debug){ |
| 128 | + console.log('found pattern-specific listitems.json for ' + currentPattern.key); |
| 129 | + } |
96 | 130 | }
|
97 | 131 | catch(e) {
|
98 |
| - } |
| 132 | + } |
99 | 133 |
|
100 | 134 | //add the raw template to memory
|
101 |
| - currentPattern.template = fs.readFileSync(abspath, 'utf8'); |
| 135 | + currentPattern.template = fs.readFileSync(file, 'utf8'); |
102 | 136 |
|
103 |
| - //our helper function that does a lot of heavy lifting |
104 |
| - processPattern(currentPattern, patternlab); |
| 137 | + //add currentPattern to patternlab.patterns array |
| 138 | + addPattern(currentPattern, patternlab); |
105 | 139 | }
|
106 | 140 |
|
107 |
| - function processPattern(currentPattern, patternlab, additionalData){ |
| 141 | + function processPatternRecursive(file, patternlab, additionalData){ |
108 | 142 |
|
109 | 143 | var fs = require('fs-extra'),
|
110 | 144 | mustache = require('mustache'),
|
|
119 | 153 | list_item_hunter = new lih(),
|
120 | 154 | pseudopattern_hunter = new pph();
|
121 | 155 |
|
| 156 | + //find current pattern in patternlab object using var file as a key |
| 157 | + var currentPattern, |
| 158 | + i; |
| 159 | + |
| 160 | + for(i = 0; i < patternlab.patterns.length; i++){ |
| 161 | + if(patternlab.patterns[i].abspath === file){ |
| 162 | + currentPattern = patternlab.patterns[i]; |
| 163 | + } |
| 164 | + } |
| 165 | + |
| 166 | + //return if processing an ignored file |
| 167 | + if(typeof currentPattern === 'undefined'){ |
| 168 | + return; |
| 169 | + } |
| 170 | + |
122 | 171 | currentPattern.extendedTemplate = currentPattern.template;
|
123 | 172 |
|
124 | 173 | //find how many partials there may be for the given pattern
|
|
137 | 186 | parameter_hunter.find_parameters(currentPattern, patternlab);
|
138 | 187 |
|
139 | 188 | //do something with the regular old partials
|
140 |
| - for(var i = 0; i < foundPatternPartials.length; i++){ |
| 189 | + for(i = 0; i < foundPatternPartials.length; i++){ |
141 | 190 | var partialKey = foundPatternPartials[i].replace(/{{>([ ])?([\w\-\.\/~]+)(?:\:[A-Za-z0-9-]+)?(?:(| )\(.*)?([ ])?}}/g, '$2');
|
| 191 | + var partialPath; |
| 192 | + |
| 193 | + //identify which pattern this partial corresponds to |
| 194 | + for(var j = 0; j < patternlab.patterns.length; j++){ |
| 195 | + if(patternlab.patterns[j].key === partialKey || |
| 196 | + patternlab.patterns[j].abspath.indexOf(partialKey) > -1) |
| 197 | + { |
| 198 | + partialPath = patternlab.patterns[j].abspath; |
| 199 | + } |
| 200 | + } |
| 201 | + |
| 202 | + //recurse through nested partials to fill out this extended template. |
| 203 | + processPatternRecursive(partialPath, patternlab); |
| 204 | + |
| 205 | + //complete assembly of extended template |
142 | 206 | var partialPattern = getpatternbykey(partialKey, patternlab);
|
143 | 207 | currentPattern.extendedTemplate = currentPattern.extendedTemplate.replace(foundPatternPartials[i], partialPattern.extendedTemplate);
|
144 | 208 | }
|
|
148 | 212 | //find pattern lineage
|
149 | 213 | lineage_hunter.find_lineage(currentPattern, patternlab);
|
150 | 214 |
|
151 |
| - //look for a pseudo pattern by checking if there is a file containing same name, with ~ in it, ending in .json |
152 |
| - pseudopattern_hunter.find_pseudopatterns(currentPattern, patternlab); |
153 |
| - |
154 | 215 | //add to patternlab object so we can look these up later.
|
155 | 216 | addPattern(currentPattern, patternlab);
|
| 217 | + |
| 218 | + //look for a pseudo pattern by checking if there is a file containing same name, with ~ in it, ending in .json |
| 219 | + pseudopattern_hunter.find_pseudopatterns(currentPattern, patternlab); |
156 | 220 | }
|
157 | 221 |
|
158 | 222 | function getpatternbykey(key, patternlab){
|
|
167 | 231 | throw 'Could not find pattern with key ' + key;
|
168 | 232 | }
|
169 | 233 |
|
170 |
| - |
171 |
| - var self = this; |
172 |
| - function mergeData(obj1, obj2) { |
173 |
| - for (var p in obj2) { |
| 234 | + /** |
| 235 | + * Recursively merge properties of two objects. |
| 236 | + * |
| 237 | + * @param {Object} obj1 If obj1 has properties obj2 doesn't, add to obj2. |
| 238 | + * @param {Object} obj2 This object's properties have priority over obj1. |
| 239 | + * @returns {Object} obj2 |
| 240 | + */ |
| 241 | + function mergeData(obj1, obj2){ |
| 242 | + if(typeof obj2 === 'undefined'){ |
| 243 | + obj2 = {}; |
| 244 | + } |
| 245 | + for(var p in obj1){ |
174 | 246 | try {
|
175 |
| - // Property in destination object set; update its value. |
176 |
| - if ( obj2[p].constructor == Object ) { |
177 |
| - obj1[p] = self.merge_data(obj1[p], obj2[p]); |
178 |
| - |
179 |
| - } else { |
180 |
| - obj1[p] = obj2[p]; |
| 247 | + // Only recurse if obj1[p] is an object. |
| 248 | + if(obj1[p].constructor === Object){ |
| 249 | + // Requires 2 objects as params; create obj2[p] if undefined. |
| 250 | + if(typeof obj2[p] === 'undefined'){ |
| 251 | + obj2[p] = {}; |
| 252 | + } |
| 253 | + obj2[p] = mergeData(obj1[p], obj2[p]); |
| 254 | + // Pop when recursion meets a non-object. If obj1[p] is a non-object, |
| 255 | + // only copy to undefined obj2[p]. This way, obj2 maintains priority. |
| 256 | + } else if(typeof obj2[p] === 'undefined'){ |
| 257 | + obj2[p] = obj1[p]; |
181 | 258 | }
|
182 | 259 | } catch(e) {
|
183 | 260 | // Property in destination object not set; create it and set its value.
|
184 |
| - obj1[p] = obj2[p]; |
| 261 | + if(typeof obj2[p] === 'undefined'){ |
| 262 | + obj2[p] = obj1[p]; |
| 263 | + } |
185 | 264 | }
|
186 | 265 | }
|
187 |
| - return obj1; |
| 266 | + return obj2; |
188 | 267 | }
|
189 | 268 |
|
190 | 269 | function buildListItems(patternlab){
|
|
233 | 312 | renderPattern: function(template, data, partials){
|
234 | 313 | return renderPattern(template, data, partials);
|
235 | 314 | },
|
236 |
| - process_pattern_file: function(file, patternlab){ |
237 |
| - processPatternFile(file, patternlab); |
| 315 | + process_pattern_iterative: function(file, patternlab){ |
| 316 | + processPatternIterative(file, patternlab); |
238 | 317 | },
|
239 |
| - process_pattern: function(pattern, patternlab, additionalData){ |
240 |
| - processPattern(pattern, patternlab, additionalData); |
| 318 | + process_pattern_recursive: function(file, patternlab, additionalData){ |
| 319 | + processPatternRecursive(file, patternlab, additionalData); |
241 | 320 | },
|
242 | 321 | get_pattern_by_key: function(key, patternlab){
|
243 | 322 | return getpatternbykey(key, patternlab);
|
|
0 commit comments