Skip to content
This repository
Browse code

change getProjectData algorithm to

* use a breadth-first search
* no longer be recursive or use status globals
* use auxiliary data from package.json when in the same folder a yuidoc.json
  • Loading branch information...
commit f207741fc273f852c348b631dbdca8ca96a08381 1 parent 3695df5
Scott J. Miles sjmiles authored

Showing 1 changed file with 71 additions and 46 deletions. Show diff stats Hide diff stats

  1. +71 46 lib/utils.js
117 lib/utils.js
@@ -220,71 +220,96 @@ function prepare(inDirs, options, callback) {
220 220
221 221 Y.prepare = prepare;
222 222
223   -
224   -var projectData, packageData, dirCount = 0;
225 223 /**
226 224 * Walk the directory tree to locate the yuidoc.json file.
227 225 * @method getProjectData
228 226 * @param {Path} [dir=process.cwd()] The directory to start from
229 227 */
230 228 var getProjectData = function(dir) {
231   - if (dirCount > 5000) {
232   - Y.log('Scanned ' + dirCount + ' directories looking for a yuidoc.json file, something is probably wrong here..', 'error', 'yuidoc');
233   - process.exit(1);
234   - }
235   - if (!dir) {
236   - dir = process.cwd();
237   - }
238   - try {
239   - var dirs = fs.readdirSync(dir);
240   - dirs.forEach(function(d) {
241   - var p = path.join(dir, d);
242   - if (d.indexOf('.') === 0) {
243   - return;
244   - }
245   - if (d === 'node_modules') {
246   - Y.log('Skipping node_modules directory while scanning for yuidoc.json', 'warn', 'yuidoc');
247   - return;
248   - }
  229 + var dirs = [dir || process.cwd()];
  230 + var projectData, packageData;
  231 + var dirCount = 0;
  232 + // keep looping until
  233 + // * data is found
  234 + // * there are no more dirs to process
  235 + // * we abort due to failsafe
  236 + while (dirs.length && !projectData) {
  237 + if (dirCount++ > 5000) {
  238 + Y.log('Scanned ' + dirCount + ' directories looking for a yuidoc.json file, something is probably wrong here..', 'error', 'yuidoc');
  239 + process.exit(1);
  240 + }
  241 + // accumulator for directories at this level
  242 + var childDirs = [];
  243 + // for each directory at the previous level
  244 + dirs.forEach(function(dir) {
  245 + // abort iterating if we have project data
249 246 if (projectData) {
250 247 return;
251 248 }
252   - if (Y.Files.isFile(p)) {
253   - if (d === 'yuidoc.json') {
254   - Y.log('Loading project data from: ' + p, 'info', 'yuidoc');
255   - try {
256   - projectData = Y.Files.getJSON(p);
257   - } catch (e) {
258   - var err = 'Failed to parse yuidoc.json file, please make sure it is valid JSON';
259   - Y.log(err, 'error', 'yuidoc');
260   - throw(e+'');
  249 + // squelch (but log) any complaints about this particular directory
  250 + try {
  251 + // for each item in this directory
  252 + var names = fs.readdirSync(dir);
  253 + names.forEach(function(name) {
  254 + // abort iterating a folder if we have found both data
  255 + if (projectData && packageData) {
  256 + return;
261 257 }
262   - }
263   - if (d === 'package.json') {
264   - Y.log('Loading project data from: ' + p, 'info', 'yuidoc');
265   - try {
266   - packageData = Y.Files.getJSON(p);
267   - } catch (e) {
268   - var err = 'Failed to parse package.json file, please make sure it is valid JSON';
269   - Y.log(err, 'error', 'yuidoc');
270   - throw(e+'');
  258 + // build a full path
  259 + var p = path.join(dir, name);
  260 + // acquire project data from this item if possible
  261 + if (Y.Files.isFile(p)) {
  262 + projectData = getFileData(p, name, 'yuidoc.json');
  263 + // 'package.json' is used for auxilliary configuration
  264 + // if it's found. Formerly, it was only found if it
  265 + // came _before_'yuidoc.json' in the folder tree
  266 + // (never in the same folder).
  267 + // This code will find 'package.json' in the same
  268 + // folder as 'yuidoc.json'.
  269 + // If there is no 'yuidoc.json', former algorithm would
  270 + // use the deepest 'package.json' it can find, this one
  271 + // will use the first (most shallow) one.
  272 + packageData = packageData || getFileData(p, name, 'package.json');
271 273 }
272   - }
273   - }
274   - if (!projectData && Y.Files.isDirectory(p)) {
275   - dirCount++
276   - projectData = getProjectData(p);
  274 + // if we are a folder, but not ., .., or node_modules,
  275 + // then add to directory accumulator
  276 + if (Y.Files.isDirectory(p)) {
  277 + if (name.indexOf('.') === 0) {
  278 + return;
  279 + }
  280 + if (name === 'node_modules') {
  281 + Y.log('Skipping node_modules directory while scanning for yuidoc.json', 'warn', 'yuidoc');
  282 + return;
  283 + }
  284 + childDirs.push(p);
  285 + }
  286 + });
  287 + } catch (dirPerm) {
  288 + Y.log('Accessing dir (' + dir + ') threw an error', 'warn', 'yuidoc');
277 289 }
278 290 });
279   - } catch (dirPerm) {
280   - Y.log('Accessing dir (' + dir + ') threw an error', 'warn', 'yuidoc');
  291 + // iterate over new set of folders
  292 + dirs = childDirs;
281 293 }
282   - if (packageData && projectData || (packageData && packageData.yuidoc)) {
  294 + if ((packageData && projectData) || (packageData && packageData.yuidoc)) {
283 295 projectData = mergeData(packageData, projectData);
284 296 }
285 297 return projectData;
286 298 };
287 299
  300 +var getFileData = function(p, name, file) {
  301 + if (name === file) {
  302 + Y.log('Loading ' + name + ' data from: ' + p, 'info', 'yuidoc');
  303 + try {
  304 + return Y.Files.getJSON(p);
  305 + } catch (e) {
  306 + var err = 'Failed to parse ' + name + ' file, please make sure it is valid JSON';
  307 + Y.log(err, 'error', 'yuidoc');
  308 + throw(e+'');
  309 + }
  310 + }
  311 +};
  312 +
288 313 var mergeData = function(pack, project) {
289 314 project = project || {};
290 315

0 comments on commit f207741

Please sign in to comment.
Something went wrong with that request. Please try again.