diff --git a/lib/builder.js b/lib/builder.js index 1b10ba5e..7c7af1d2 100644 --- a/lib/builder.js +++ b/lib/builder.js @@ -3,9 +3,9 @@ Copyright (c) 2011, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://yuilibrary.com/license/ */ -var marked = require("marked"), +var marked = require('marked'), fs = require('graceful-fs'), - noop = function() {}, + noop = function () {}, path = require('path'), TEMPLATE; @@ -16,35 +16,37 @@ based templates to generate static HTML content * @module yuidoc */ -YUI.add('doc-builder', function(Y) { +YUI.add('doc-builder', function (Y) { + /*jshint onevar:false */ var fixType = Y.Lang.fixType, - print = function(items) { - var out = '
` tags and adds the __prettyprint__ `className` to them
- * @method _parseCode
- * @private
- * @param {HTML} html The HTML to parse
- * @return {HTML} The parsed HTML
- */
+ * Parses `` tags and adds the __prettyprint__ `className` to them
+ * @method _parseCode
+ * @private
+ * @param {HTML} html The HTML to parse
+ * @return {HTML} The parsed HTML
+ */
_parseCode: function (html) {
html = html || '';
//html = html.replace(//g, '');
@@ -755,7 +775,7 @@ YUI.add('doc-builder', function(Y) {
* @param {HTML} html The HTML to parse
* @return {HTML} The parsed HTML
*/
- _inlineCode: function(html) {
+ _inlineCode: function (html) {
html = html.replace(/\\`/g, '__{{SELLECK_BACKTICK}}__');
html = html.replace(/`(.+?)`/g, function (match, code) {
@@ -778,12 +798,12 @@ YUI.add('doc-builder', function(Y) {
* @param {Error} callback.err
* @param {HTML} callback.html The assembled template markup
*/
- render: function(source, view, layout, partials, callback) {
+ render: function (source, view, layout, partials, callback) {
var html = [];
- function buffer(line) {
- html.push(line);
- }
+ // function buffer(line) {
+ // html.push(line);
+ // }
// Allow callback as third or fourth param.
if (typeof partials === 'function') {
@@ -793,8 +813,10 @@ YUI.add('doc-builder', function(Y) {
callback = layout;
layout = null;
}
- var parts = Y.merge(partials || {}, { layout_content: source });
- Y.each(parts, function(source, name) {
+ var parts = Y.merge(partials || {}, {
+ layout_content: source
+ });
+ Y.each(parts, function (source, name) {
Y.Handlebars.registerPartial(name, source);
});
@@ -810,27 +832,27 @@ YUI.add('doc-builder', function(Y) {
} else {
_v[k] = view[k];
}
- };
+ }
html = TEMPLATE(_v);
//html = html.replace(/{{//g, '{{/');
-
+
//html = (Y.Handlebars.compile(html))({});
html = this._inlineCode(html);
callback(null, html);
},
/**
- * Render the index file
- * @method renderIndex
- * @param {Function} cb The callback fired when complete
- * @param {String} cb.html The HTML to render this view
- * @param {Object} cv.view The View Data
- */
- renderIndex: function(cb) {
+ * Render the index file
+ * @method renderIndex
+ * @param {Function} cb The callback fired when complete
+ * @param {String} cb.html The HTML to render this view
+ * @param {Object} cv.view The View Data
+ */
+ renderIndex: function (cb) {
var self = this;
- Y.prepare([DEFAULT_THEME, themeDir], self.getProjectMeta(), function(err, opts) {
+ Y.prepare([DEFAULT_THEME, themeDir], self.getProjectMeta(), function (err, opts) {
opts.meta.title = self.data.project.name;
opts.meta.projectRoot = './';
opts.meta.projectAssets = './assets';
@@ -838,24 +860,24 @@ YUI.add('doc-builder', function(Y) {
opts = self.populateClasses(opts);
opts = self.populateModules(opts);
- var view = new Y.DocView(opts.meta);
- self.render('{{>index}}', view, opts.layouts.main, opts.partials, function(err, html) {
+ var view = new Y.DocView(opts.meta);
+ self.render('{{>index}}', view, opts.layouts.main, opts.partials, function (err, html) {
self.files++;
cb(html, view);
});
});
},
/**
- * Generates the index.html file
- * @method writeIndex
- * @param {Callback} cb The callback to execute after it's completed
- */
- writeIndex: function(cb) {
+ * Generates the index.html file
+ * @method writeIndex
+ * @param {Callback} cb The callback to execute after it's completed
+ */
+ writeIndex: function (cb) {
var self = this,
stack = new Y.Parallel();
Y.log('Preparing index.html', 'info', 'builder');
- self.renderIndex(stack.add(function(html, view) {
+ self.renderIndex(stack.add(function (html, view) {
stack.html = html;
stack.view = view;
if (self.options.dumpview) {
@@ -864,25 +886,25 @@ YUI.add('doc-builder', function(Y) {
Y.Files.writeFile(path.join(self.options.outdir, 'index.html'), html, stack.add(noop));
}));
- stack.done(function(html, view) {
+ stack.done(function ( /* html, view */ ) {
Y.log('Writing index.html', 'info', 'builder');
cb(stack.html, stack.view);
});
},
/**
- * Render a module
- * @method renderModule
- * @param {Function} cb The callback fired when complete
- * @param {String} cb.html The HTML to render this view
- * @param {Object} cv.view The View Data
- */
- renderModule: function(cb, data, layout) {
+ * Render a module
+ * @method renderModule
+ * @param {Function} cb The callback fired when complete
+ * @param {String} cb.html The HTML to render this view
+ * @param {Object} cv.view The View Data
+ */
+ renderModule: function (cb, data, layout) {
var self = this;
var stack = new Y.Parallel();
data.displayName = data.name;
data.name = self.filterFileName(data.name);
- Y.prepare([DEFAULT_THEME, themeDir], self.getProjectMeta(), function(err, opts) {
+ Y.prepare([DEFAULT_THEME, themeDir], self.getProjectMeta(), function (err, opts) {
opts.meta = Y.merge(opts.meta, data);
//opts.meta.htmlTitle = v.name + ': ' + self.data.project.name;
@@ -902,10 +924,13 @@ YUI.add('doc-builder', function(Y) {
if (data.classes && Object.keys(data.classes).length) {
opts.meta.moduleClasses = [];
- Y.each(Object.keys(data.classes), function(name) {
+ Y.each(Object.keys(data.classes), function (name) {
var i = self.data.classes[name];
if (i) {
- opts.meta.moduleClasses.push({ name: i.name, displayName: i.name });
+ opts.meta.moduleClasses.push({
+ name: i.name,
+ displayName: i.name
+ });
}
});
opts.meta.moduleClasses.sort(self.nameSort);
@@ -913,85 +938,94 @@ YUI.add('doc-builder', function(Y) {
if (data.example && data.example.length) {
if (data.example.forEach) {
var e = '';
- data.example.forEach(function(v) {
+ data.example.forEach(function (v) {
e += self._parseCode(self.markdown(v));
});
data.example = e;
} else {
- data.example = self._parseCode(self.markdown(i.example));
+ data.example = self._parseCode(self.markdown(data.example));
}
opts.meta.example = data.example;
}
if (data.submodules && Object.keys(data.submodules).length) {
opts.meta.subModules = [];
- Y.each(Object.keys(data.submodules), function(name) {
+ Y.each(Object.keys(data.submodules), function (name) {
var i = self.data.modules[name];
if (i) {
- opts.meta.subModules.push({ name: i.name, displayName: i.name, description: i.description });
+ opts.meta.subModules.push({
+ name: i.name,
+ displayName: i.name,
+ description: i.description
+ });
}
});
opts.meta.subModules.sort(self.nameSort);
}
- var view = new Y.DocView(opts.meta);
+ var view = new Y.DocView(opts.meta);
var mainLayout = opts.layouts[layout];
- self.render('{{>module}}', view, mainLayout, opts.partials, stack.add(function(err, html) {
+ self.render('{{>module}}', view, mainLayout, opts.partials, stack.add(function (err, html) {
self.files++;
stack.html = html;
stack.view = view;
}));
});
- stack.done(function() {
+ stack.done(function () {
cb(stack.html, stack.view);
});
-
},
/**
- * Generates the module files under "out"/modules/
- * @method writeModules
- * @param {Callback} cb The callback to execute after it's completed
- */
- writeModules: function(cb, layout) {
+ * Generates the module files under "out"/modules/
+ * @method writeModules
+ * @param {Callback} cb The callback to execute after it's completed
+ */
+ writeModules: function (cb, layout) {
layout = layout || 'main';
var self = this,
stack = new Y.Parallel();
stack.html = [];
stack.view = [];
-
+
var counter = 0;
- Object.keys(self.data.modules).forEach(function(k) {
- if (!self.data.modules[k].external) {
- counter++;
- }
- });
+ Object.keys(self.data.modules).forEach(function (k) {
+ if (!self.data.modules[k].external) {
+ counter++;
+ }
+ });
Y.log('Rendering and writing ' + counter + ' modules pages.', 'info', 'builder');
- Y.each(self.data.modules, function(v) {
- if (v.external) { return }
- self.renderModule(function(html, view) {
+ Y.each(self.data.modules, function (v) {
+ if (v.external) {
+ return;
+ }
+ self.renderModule(function (html, view) {
stack.html.push(html);
stack.view.push(view);
if (self.options.dumpview) {
- Y.Files.writeFile(path.join(self.options.outdir, 'json', 'module_' + v.name + '.json'), JSON.stringify(view), stack.add(noop));
+ Y.Files.writeFile(
+ path.join(self.options.outdir, 'json', 'module_' + v.name + '.json'),
+ JSON.stringify(view),
+ stack.add(noop)
+ );
}
Y.Files.writeFile(path.join(self.options.outdir, 'modules', v.name + '.html'), html, stack.add(noop));
}, v, layout);
});
- stack.done(function() {
+ stack.done(function () {
Y.log('Finished writing module files', 'info', 'builder');
cb(stack.html, stack.view);
});
},
/**
- * Checks an array of items (class items) to see if an item is in that list
- * @method hasProperty
- * @param {Array} a The Array of items to check
- * @param {Object} b The object to find
- * @return Boolean
- */
- hasProperty: function(a, b) {
+ * Checks an array of items (class items) to see if an item is in that list
+ * @method hasProperty
+ * @param {Array} a The Array of items to check
+ * @param {Object} b The object to find
+ * @return Boolean
+ */
+ hasProperty: function (a, b) {
var other = false;
- var h = Y.some(a, function(i, k) {
+ Y.some(a, function (i, k) {
if ((i.itemtype === b.itemtype) && (i.name === b.name)) {
other = k;
return true;
@@ -1000,48 +1034,49 @@ YUI.add('doc-builder', function(Y) {
return other;
},
/**
- * Counter for stepping into merges
- * @private
- * @property _mergeCounter
- * @type Number
- */
+ * Counter for stepping into merges
+ * @private
+ * @property _mergeCounter
+ * @type Number
+ */
_mergeCounter: null,
/**
- * Merge superclass data into a child class
- * @method mergeExtends
- * @param {Object} info The item to extend
- * @param {Array} classItems The list of items to merge in
- * @param {Boolean} first Set for the first call
- */
- mergeExtends: function(info, classItems, first) {
+ * Merge superclass data into a child class
+ * @method mergeExtends
+ * @param {Object} info The item to extend
+ * @param {Array} classItems The list of items to merge in
+ * @param {Boolean} first Set for the first call
+ */
+ mergeExtends: function (info, classItems, first) {
var self = this;
self._mergeCounter = (first) ? 0 : (self._mergeCounter + 1);
if (self._mergeCounter === 100) {
- throw('YUIDoc detected a loop extending class ' + info.name);
+ throw ('YUIDoc detected a loop extending class ' + info.name);
}
if (info.extends || info.uses) {
var hasItems = {};
hasItems[info.extends] = 1;
if (info.uses) {
- info.uses.forEach(function(v) {
+ info.uses.forEach(function (v) {
hasItems[v] = 1;
});
}
- self.data.classitems.forEach(function(v) {
+ self.data.classitems.forEach(function (v) {
//console.error(v.class, '==', info.extends);
if (hasItems[v.class]) {
if (!v.static) {
- var override = self.hasProperty(classItems, v);
+ var q,
+ override = self.hasProperty(classItems, v);
if (override === false) {
//This method was extended from the parent class but not over written
//console.error('Merging extends from', v.class, 'onto', info.name);
- var q = Y.merge({}, v);
+ q = Y.merge({}, v);
q.extended_from = v.class;
classItems.push(q);
} else {
//This method was extended from the parent and overwritten in this class
- var q = Y.merge({}, v);
+ q = Y.merge({}, v);
q = self.augmentData(q);
classItems[override].overwritten_from = q;
}
@@ -1058,17 +1093,17 @@ YUI.add('doc-builder', function(Y) {
return classItems;
},
/**
- * Render the class file
- * @method renderClass
- * @param {Function} cb The callback fired when complete
- * @param {String} cb.html The HTML to render this view
- * @param {Object} cv.view The View Data
- */
- renderClass: function(cb, data, layout) {
+ * Render the class file
+ * @method renderClass
+ * @param {Function} cb The callback fired when complete
+ * @param {String} cb.html The HTML to render this view
+ * @param {Object} cv.view The View Data
+ */
+ renderClass: function (cb, data, layout) {
var self = this;
var stack = new Y.Parallel();
- Y.prepare([DEFAULT_THEME, themeDir], self.getProjectMeta(), function(err, opts) {
+ Y.prepare([DEFAULT_THEME, themeDir], self.getProjectMeta(), function (err, opts) {
//console.log(opts);
if (err) {
console.log(err);
@@ -1107,7 +1142,7 @@ YUI.add('doc-builder', function(Y) {
}
var classItems = [];
- self.data.classitems.forEach(function(i) {
+ self.data.classitems.forEach(function (i) {
if (i.class === data.name) {
classItems.push(i);
}
@@ -1120,10 +1155,10 @@ YUI.add('doc-builder', function(Y) {
i = self.augmentData(i);
i.paramsList = [];
if (i.params) {
- i.params.forEach(function(p, v) {
+ i.params.forEach(function (p) {
var name = p.name;
if (p.optional) {
- name = '[' + name + ((p.optdefault) ? '=' + p.optdefault : '') + ']'
+ name = '[' + name + ((p.optdefault) ? '=' + p.optdefault : '') + ']';
}
i.paramsList.push(name);
});
@@ -1137,16 +1172,16 @@ YUI.add('doc-builder', function(Y) {
i.paramsList = ' ';
}
i.returnType = ' ';
- if (i.return) {
+ if (i["return"]) {
i.hasReturn = true;
- i.returnType = i.return.type;
+ i.returnType = i["return"].type;
}
//console.error(i);
opts.meta.is_constructor = [i];
if (i.example && i.example.length) {
if (i.example.forEach) {
var e = '';
- i.example.forEach(function(v) {
+ i.example.forEach(function (v) {
e += self._parseCode(self.markdown(v));
});
i.example = e;
@@ -1156,157 +1191,158 @@ YUI.add('doc-builder', function(Y) {
}
}
- classItems.forEach(function(i) {
+ classItems.forEach(function (i) {
+ var e;
switch (i.itemtype) {
- case 'method':
- i = self.augmentData(i);
- i.paramsList = [];
- if (i.params && i.params.forEach) {
- i.params.forEach(function(p, v) {
- var name = p.name;
- if (p.optional) {
- name = '[' + name + ((p.optdefault) ? '=' + p.optdefault : '') + ']'
- }
- i.paramsList.push(name);
- });
- }
- //i.methodDescription = self._parseCode(markdown(i.description || ''));
- i.methodDescription = self._parseCode(i.description);
- if (i.example && i.example.length) {
- if (i.example.forEach) {
- var e = '';
- i.example.forEach(function(v) {
- e += self._parseCode(self.markdown(v));
- });
- i.example = e;
- } else {
- i.example = self._parseCode(self.markdown(i.example));
+ case 'method':
+ i = self.augmentData(i);
+ i.paramsList = [];
+ if (i.params && i.params.forEach) {
+ i.params.forEach(function (p) {
+ var name = p.name;
+ if (p.optional) {
+ name = '[' + name + ((p.optdefault) ? '=' + p.optdefault : '') + ']';
}
- }
- i.hasAccessType = i.access;
- i.hasParams = i.paramsList.length;
- if (i.paramsList.length) {
- i.paramsList = i.paramsList.join(', ');
+ i.paramsList.push(name);
+ });
+ }
+ //i.methodDescription = self._parseCode(markdown(i.description || ''));
+ i.methodDescription = self._parseCode(i.description);
+ if (i.example && i.example.length) {
+ if (i.example.forEach) {
+ e = '';
+ i.example.forEach(function (v) {
+ e += self._parseCode(self.markdown(v));
+ });
+ i.example = e;
} else {
- i.paramsList = ' ';
- }
- i.returnType = ' ';
- if (i.return) {
- i.hasReturn = true;
- i.returnType = i.return.type;
+ i.example = self._parseCode(self.markdown(i.example));
}
+ }
+ i.hasAccessType = i.access;
+ i.hasParams = i.paramsList.length;
+ if (i.paramsList.length) {
+ i.paramsList = i.paramsList.join(', ');
+ } else {
+ i.paramsList = ' ';
+ }
+ i.returnType = ' ';
+ if (i["return"]) {
+ i.hasReturn = true;
+ i.returnType = i["return"].type;
+ }
- // If this item is provided by a module other
- // than the module that provided the original
- // class, add the original module name to the
- // item's `providedBy` property so we can
- // indicate the relationship.
- if ((i.submodule || i.module) !== (data.submodule || data.module)) {
- i.providedBy = (i.submodule || i.module);
- }
+ // If this item is provided by a module other
+ // than the module that provided the original
+ // class, add the original module name to the
+ // item's `providedBy` property so we can
+ // indicate the relationship.
+ if ((i.submodule || i.module) !== (data.submodule || data.module)) {
+ i.providedBy = (i.submodule || i.module);
+ }
- opts.meta.methods.push(i);
- break;
- case 'property':
- i = self.augmentData(i);
- //i.propertyDescription = self._parseCode(markdown(i.description || ''));
- i.propertyDescription = self._parseCode(i.description);
- if (!i.type) {
- i.type = 'unknown';
- }
- if (i.final === '') {
- i.final = true;
- }
- if (i.example && i.example.length) {
- if (i.example.forEach) {
- var e = '';
- i.example.forEach(function(v) {
- e += self._parseCode(self.markdown(v));
- });
- i.example = e;
- } else {
- i.example = self._parseCode(self.markdown(i.example));
- }
+ opts.meta.methods.push(i);
+ break;
+ case 'property':
+ i = self.augmentData(i);
+ //i.propertyDescription = self._parseCode(markdown(i.description || ''));
+ i.propertyDescription = self._parseCode(i.description);
+ if (!i.type) {
+ i.type = 'unknown';
+ }
+ if (i.final === '') {
+ i.final = true;
+ }
+ if (i.example && i.example.length) {
+ if (i.example.forEach) {
+ e = '';
+ i.example.forEach(function (v) {
+ e += self._parseCode(self.markdown(v));
+ });
+ i.example = e;
+ } else {
+ i.example = self._parseCode(self.markdown(i.example));
}
+ }
- // If this item is provided by a module other
- // than the module that provided the original
- // class, add the original module name to the
- // item's `providedBy` property so we can
- // indicate the relationship.
- if ((i.submodule || i.module) !== (data.submodule || data.module)) {
- i.providedBy = (i.submodule || i.module);
- }
+ // If this item is provided by a module other
+ // than the module that provided the original
+ // class, add the original module name to the
+ // item's `providedBy` property so we can
+ // indicate the relationship.
+ if ((i.submodule || i.module) !== (data.submodule || data.module)) {
+ i.providedBy = (i.submodule || i.module);
+ }
- opts.meta.properties.push(i);
- break;
+ opts.meta.properties.push(i);
+ break;
- case 'attribute': // fallthru
- case 'config':
- i = self.augmentData(i);
- //i.attrDescription = self._parseCode(markdown(i.description || ''));
- i.attrDescription = self._parseCode(i.description);
+ case 'attribute': // fallthru
+ case 'config':
+ i = self.augmentData(i);
+ //i.attrDescription = self._parseCode(markdown(i.description || ''));
+ i.attrDescription = self._parseCode(i.description);
- if (i.itemtype === 'config') {
- i.config = true;
- } else {
- i.emit = self.options.attributesEmit;
- }
- if (i.readonly === '') {
- i.readonly = true;
- }
+ if (i.itemtype === 'config') {
+ i.config = true;
+ } else {
+ i.emit = self.options.attributesEmit;
+ }
+ if (i.readonly === '') {
+ i.readonly = true;
+ }
- if (i.example && i.example.length) {
- if (i.example.forEach) {
- var e = '';
- i.example.forEach(function(v) {
- e += self._parseCode(self.markdown(v));
- });
- i.example = e;
- } else {
- i.example = self._parseCode(self.markdown(i.example));
- }
+ if (i.example && i.example.length) {
+ if (i.example.forEach) {
+ e = '';
+ i.example.forEach(function (v) {
+ e += self._parseCode(self.markdown(v));
+ });
+ i.example = e;
+ } else {
+ i.example = self._parseCode(self.markdown(i.example));
}
+ }
- // If this item is provided by a module other
- // than the module that provided the original
- // class, add the original module name to the
- // item's `providedBy` property so we can
- // indicate the relationship.
- if ((i.submodule || i.module) !== (data.submodule || data.module)) {
- i.providedBy = (i.submodule || i.module);
- }
+ // If this item is provided by a module other
+ // than the module that provided the original
+ // class, add the original module name to the
+ // item's `providedBy` property so we can
+ // indicate the relationship.
+ if ((i.submodule || i.module) !== (data.submodule || data.module)) {
+ i.providedBy = (i.submodule || i.module);
+ }
- opts.meta.attrs.push(i);
- break;
- case 'event':
- i = self.augmentData(i);
- //i.eventDescription = self._parseCode(markdown(i.description || ''));
- i.eventDescription = self._parseCode(i.description);
-
- if (i.example && i.example.length) {
- if (i.example.forEach) {
- var e = '';
- i.example.forEach(function(v) {
- e += self._parseCode(self.markdown(v));
- });
- i.example = e;
- } else {
- i.example = self._parseCode(self.markdown(i.example));
- }
+ opts.meta.attrs.push(i);
+ break;
+ case 'event':
+ i = self.augmentData(i);
+ //i.eventDescription = self._parseCode(markdown(i.description || ''));
+ i.eventDescription = self._parseCode(i.description);
+
+ if (i.example && i.example.length) {
+ if (i.example.forEach) {
+ e = '';
+ i.example.forEach(function (v) {
+ e += self._parseCode(self.markdown(v));
+ });
+ i.example = e;
+ } else {
+ i.example = self._parseCode(self.markdown(i.example));
}
+ }
- // If this item is provided by a module other
- // than the module that provided the original
- // class, add the original module name to the
- // item's `providedBy` property so we can
- // indicate the relationship.
- if ((i.submodule || i.module) !== (data.submodule || data.module)) {
- i.providedBy = (i.submodule || i.module);
- }
+ // If this item is provided by a module other
+ // than the module that provided the original
+ // class, add the original module name to the
+ // item's `providedBy` property so we can
+ // indicate the relationship.
+ if ((i.submodule || i.module) !== (data.submodule || data.module)) {
+ i.providedBy = (i.submodule || i.module);
+ }
- opts.meta.events.push(i);
- break;
+ opts.meta.events.push(i);
+ break;
}
});
@@ -1328,9 +1364,9 @@ YUI.add('doc-builder', function(Y) {
delete opts.meta.events;
}
- var view = new Y.DocView(opts.meta);
+ var view = new Y.DocView(opts.meta);
var mainLayout = opts.layouts[layout];
- self.render('{{>classes}}', view, mainLayout, opts.partials, stack.add(function(err, html) {
+ self.render('{{>classes}}', view, mainLayout, opts.partials, stack.add(function (err, html) {
self.files++;
stack.html = html;
stack.view = view;
@@ -1338,16 +1374,16 @@ YUI.add('doc-builder', function(Y) {
}));
});
- stack.done(function() {
+ stack.done(function () {
cb(stack.html, stack.view, stack.opts);
});
},
/**
- * Generates the class files under "out"/classes/
- * @method writeClasses
- * @param {Callback} cb The callback to execute after it's completed
- */
- writeClasses: function(cb, layout) {
+ * Generates the class files under "out"/classes/
+ * @method writeClasses
+ * @param {Callback} cb The callback to execute after it's completed
+ */
+ writeClasses: function (cb, layout) {
layout = layout || 'main';
var self = this,
stack = new Y.Parallel();
@@ -1355,36 +1391,42 @@ YUI.add('doc-builder', function(Y) {
stack.view = [];
var counter = 0;
- Object.keys(self.data.classes).forEach(function(k) {
- if (!self.data.classes[k].external) {
- counter++;
- }
- });
+ Object.keys(self.data.classes).forEach(function (k) {
+ if (!self.data.classes[k].external) {
+ counter++;
+ }
+ });
Y.log('Rendering and writing ' + counter + ' class pages.', 'info', 'builder');
- Y.each(self.data.classes, function(v) {
- if (v.external) { return }
- self.renderClass(stack.add(function(html, view) {
+ Y.each(self.data.classes, function (v) {
+ if (v.external) {
+ return;
+ }
+ self.renderClass(stack.add(function (html, view) {
stack.html.push(html);
stack.view.push(view);
if (self.options.dumpview) {
- Y.Files.writeFile(path.join(self.options.outdir, 'json', 'classes_' + v.name + '.json'), JSON.stringify(view), stack.add(noop));
+ Y.Files.writeFile(
+ path.join(self.options.outdir, 'json', 'classes_' + v.name + '.json'),
+ JSON.stringify(view),
+ stack.add(noop)
+ );
}
Y.Files.writeFile(path.join(self.options.outdir, 'classes', v.name + '.html'), html, stack.add(noop));
}), v, layout);
});
- stack.done(function() {
+ stack.done(function () {
Y.log('Finished writing class files', 'info', 'builder');
cb(stack.html, stack.view);
});
},
/**
- * Sort method of array of objects with a property called __name__
- * @method nameSort
- * @param {Object} a First object to compare
- * @param {Object} b Second object to compare
- * @return {Number} 1, -1 or 0 for sorting.
- */
- nameSort: function(a, b) {
+ * Sort method of array of objects with a property called __name__
+ * @method nameSort
+ * @param {Object} a First object to compare
+ * @param {Object} b Second object to compare
+ * @return {Number} 1, -1 or 0 for sorting.
+ */
+ nameSort: function (a, b) {
if (!a.name || !b.name) {
return 0;
}
@@ -1396,16 +1438,16 @@ YUI.add('doc-builder', function(Y) {
ret = -1;
}
if (an > bn) {
- ret = 1
+ ret = 1;
}
return ret;
},
/**
- * Generates the syntax files under `"out"/files/`
- * @method writeFiles
- * @param {Callback} cb The callback to execute after it's completed
- */
- writeFiles: function(cb, layout) {
+ * Generates the syntax files under `"out"/files/`
+ * @method writeFiles
+ * @param {Callback} cb The callback to execute after it's completed
+ */
+ writeFiles: function (cb, layout) {
layout = layout || 'main';
var self = this,
stack = new Y.Parallel();
@@ -1413,42 +1455,52 @@ YUI.add('doc-builder', function(Y) {
stack.view = [];
var counter = 0;
- Object.keys(self.data.files).forEach(function(k) {
- if (!self.data.files[k].external) {
- counter++;
- }
- });
+ Object.keys(self.data.files).forEach(function (k) {
+ if (!self.data.files[k].external) {
+ counter++;
+ }
+ });
Y.log('Rendering and writing ' + counter + ' source files.', 'info', 'builder');
- Y.each(self.data.files, function(v) {
- if (v.external) { return }
- self.renderFile(stack.add(function(html, view, data) {
+ Y.each(self.data.files, function (v) {
+ if (v.external) {
+ return;
+ }
+ self.renderFile(stack.add(function (html, view, data) {
if (!view || !data) {
return;
}
stack.html.push(html);
stack.view.push(view);
if (self.options.dumpview) {
- Y.Files.writeFile(path.join(self.options.outdir, 'json', 'files_' + self.filterFileName(data.name) + '.json'), JSON.stringify(view), stack.add(noop));
+ Y.Files.writeFile(
+ path.join(self.options.outdir, 'json', 'files_' + self.filterFileName(data.name) + '.json'),
+ JSON.stringify(view),
+ stack.add(noop)
+ );
}
- Y.Files.writeFile(path.join(self.options.outdir, 'files', self.filterFileName(data.name) + '.html'), html, stack.add(noop));
+ Y.Files.writeFile(
+ path.join(self.options.outdir, 'files', self.filterFileName(data.name) + '.html'),
+ html,
+ stack.add(noop)
+ );
}), v, layout);
});
- stack.done(function() {
+ stack.done(function () {
Y.log('Finished writing source files', 'info', 'builder');
cb(stack.html, stack.view);
});
},
/**
- * Render the source file
- * @method renderFile
- * @param {Function} cb The callback fired when complete
- * @param {String} cb.html The HTML to render this view
- * @param {Object} cv.view The View Data
- */
- renderFile: function(cb, data, layout) {
+ * Render the source file
+ * @method renderFile
+ * @param {Function} cb The callback fired when complete
+ * @param {String} cb.html The HTML to render this view
+ * @param {Object} cv.view The View Data
+ */
+ renderFile: function (cb, data, layout) {
var self = this;
-
- Y.prepare([DEFAULT_THEME, themeDir], self.getProjectMeta(), function(err, opts) {
+
+ Y.prepare([DEFAULT_THEME, themeDir], self.getProjectMeta(), function (err, opts) {
if (err) {
console.log(err);
}
@@ -1469,7 +1521,7 @@ YUI.add('doc-builder', function(Y) {
opts = self.populateFiles(opts);
opts.meta.fileName = data.name;
- fs.readFile(opts.meta.fileName, Y.charset, Y.rbind(function(err, str, opts, data) {
+ fs.readFile(opts.meta.fileName, Y.charset, Y.rbind(function (err, str, opts, data) {
if (err) {
Y.log(err, 'error', 'builder');
cb(err);
@@ -1479,11 +1531,11 @@ YUI.add('doc-builder', function(Y) {
if (typeof self.options.tabspace === 'string') {
str = str.replace(/\t/g, self.options.tabspace);
}
-
+
opts.meta.fileData = str;
var view = new Y.DocView(opts.meta, 'index');
var mainLayout = opts.layouts[layout];
- self.render('{{>files}}', view, mainLayout, opts.partials, function(err, html) {
+ self.render('{{>files}}', view, mainLayout, opts.partials, function (err, html) {
self.files++;
cb(html, view, data);
});
@@ -1493,42 +1545,44 @@ YUI.add('doc-builder', function(Y) {
},
/**
- * Write the API meta data used for the AutoComplete widget
- * @method writeAPIMeta
- * @param {Callback} cb The callback to execute when complete
- * @async
- */
- writeAPIMeta: function(cb) {
+ * Write the API meta data used for the AutoComplete widget
+ * @method writeAPIMeta
+ * @param {Callback} cb The callback to execute when complete
+ * @async
+ */
+ writeAPIMeta: function (cb) {
Y.log('Writing API Meta Data', 'info', 'builder');
var self = this;
- this.renderAPIMeta(function(js) {
+ this.renderAPIMeta(function (js) {
fs.writeFile(path.join(self.options.outdir, 'api.js'), js, Y.charset, cb);
});
},
/**
- * Render the API meta and return the Javascript
- * @method renderAPIMeta
- * @param {Callback} cb The callback
- * @async
- */
- renderAPIMeta: function(cb) {
-
- var opts = { meta: {} }, self = this;
+ * Render the API meta and return the Javascript
+ * @method renderAPIMeta
+ * @param {Callback} cb The callback
+ * @async
+ */
+ renderAPIMeta: function (cb) {
+
+ var opts = {
+ meta: {}
+ };
opts = this.populateClasses(opts);
opts = this.populateModules(opts);
- ['classes', 'modules'].forEach(function(id) {
- opts.meta[id].forEach(function(v, k) {
+ ['classes', 'modules'].forEach(function (id) {
+ opts.meta[id].forEach(function (v, k) {
opts.meta[id][k] = v.name;
if (v.submodules) {
- v.submodules.forEach(function(s) {
+ v.submodules.forEach(function (s) {
opts.meta[id].push(s.displayName);
});
}
});
opts.meta[id].sort();
});
-
+
var apijs = 'YUI.add("yuidoc-meta", function(Y) {\n' +
' Y.YUIDoc = { meta: ' + JSON.stringify(opts.meta, null, 4) + ' };\n' +
'});';
@@ -1536,63 +1590,71 @@ YUI.add('doc-builder', function(Y) {
cb(apijs);
},
/**
- * Normalizes a file path to a writable filename:
- *
- * var path = 'lib/file.js';
- * returns 'lib_file.js';
- *
- * @method filterFileName
- * @param {String} f The filename to normalize
- * @return {String} The filtered file path
- */
- filterFileName: function(f) {
+ * Normalizes a file path to a writable filename:
+ *
+ * var path = 'lib/file.js';
+ * returns 'lib_file.js';
+ *
+ * @method filterFileName
+ * @param {String} f The filename to normalize
+ * @return {String} The filtered file path
+ */
+ filterFileName: function (f) {
return f.replace(/[\/\\]/g, '_');
},
/**
- * Compiles the templates from the meta-data provided by DocParser
- * @method compile
- * @param {Callback} cb The callback to execute after it's completed
- */
- compile: function(cb) {
+ * Compiles the templates from the meta-data provided by DocParser
+ * @method compile
+ * @param {Callback} cb The callback to execute after it's completed
+ */
+ compile: function (cb) {
var self = this;
var starttime = (new Date()).getTime();
Y.log('Compiling Templates', 'info', 'builder');
- this.mixExternal(function() {
- self.makeDirs(function() {
+ this.mixExternal(function () {
+ self.makeDirs(function () {
Y.log('Copying Assets', 'info', 'builder');
if (!Y.Files.isDirectory(path.join(self.options.outdir, 'assets'))) {
fs.mkdirSync(path.join(self.options.outdir, 'assets'), 0777);
}
- Y.Files.copyAssets([path.join(DEFAULT_THEME, 'assets'), path.join(themeDir, 'assets')], path.join(self.options.outdir, 'assets'), false, function() {
- var cstack = new Y.Parallel();
-
- self.writeModules(cstack.add(function() {
- self.writeClasses(cstack.add(function() {
- if (!self.options.nocode) {
- self.writeFiles(cstack.add(noop));
- }
+ Y.Files.copyAssets([
+ path.join(DEFAULT_THEME, 'assets'),
+ path.join(themeDir, 'assets')
+ ],
+ path.join(self.options.outdir, 'assets'),
+ false,
+ function () {
+ var cstack = new Y.Parallel();
+
+ self.writeModules(cstack.add(function () {
+ self.writeClasses(cstack.add(function () {
+ if (!self.options.nocode) {
+ self.writeFiles(cstack.add(noop));
+ }
+ }));
}));
- }));
- /*
+ /*
self.writeModules(cstack.add(noop));
self.writeClasses(cstack.add(noop));
if (!self.options.nocode) {
self.writeFiles(cstack.add(noop));
}
*/
- self.writeIndex(cstack.add(noop));
- self.writeAPIMeta(cstack.add(noop));
-
- cstack.done(function() {
- var endtime = (new Date()).getTime();
- var timer = ((endtime - starttime) / 1000) + ' seconds';
- Y.log('Finished writing ' + self.files + ' files in ' + timer, 'info', 'builder');
- if (cb) { cb(); }
+ self.writeIndex(cstack.add(noop));
+ self.writeAPIMeta(cstack.add(noop));
+
+ cstack.done(function () {
+ var endtime = (new Date()).getTime();
+ var timer = ((endtime - starttime) / 1000) + ' seconds';
+ Y.log('Finished writing ' + self.files + ' files in ' + timer, 'info', 'builder');
+ if (cb) {
+ cb();
+ }
+ });
});
- });
});
});
}
- }
+ };
});
diff --git a/lib/cli.js b/lib/cli.js
index f6d63d82..aacf3cd9 100755
--- a/lib/cli.js
+++ b/lib/cli.js
@@ -1,4 +1,5 @@
#!/usr/bin/env node
+
/*
Copyright (c) 2011, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
@@ -6,19 +7,19 @@ http://yuilibrary.com/license/
*/
/**
-* Parses the arguments, creates the options and passes them to `Y.YUIDoc` and then `Y.DocBuilder`.
-* @class CLI
-* @module yuidoc
-*/
+ * Parses the arguments, creates the options and passes them to `Y.YUIDoc` and then `Y.DocBuilder`.
+ * @class CLI
+ * @module yuidoc
+ */
-var Y = require('./index'),
- path = require('path');
+/*global Y:true */
+var Y = require('./index');
var options = Y.Options(Y.Array(process.argv, 2));
Y.log('Starting YUIDoc@' + Y.packageInfo.version + ' using YUI@' + Y.version + ' with NodeJS@' + process.versions.node, 'info', 'yuidoc');
-var starttime = (new Date).getTime();
+var starttime = (new Date()).getTime();
options = Y.Project.init(options);
@@ -32,7 +33,6 @@ Y.log(opts, 'info', 'yuidoc');
if (options.server) {
Y.Server.start(options);
} else {
-
var json = (new Y.YUIDoc(options)).run();
if (json === null) {
return;
@@ -41,9 +41,9 @@ if (options.server) {
if (!options.parseOnly) {
var builder = new Y.DocBuilder(options, json);
- builder.compile(function() {
- var endtime = (new Date).getTime();
- Y.log('Completed in ' + ((endtime - starttime) / 1000) + ' seconds' , 'info', 'yuidoc');
+ builder.compile(function () {
+ var endtime = (new Date()).getTime();
+ Y.log('Completed in ' + ((endtime - starttime) / 1000) + ' seconds', 'info', 'yuidoc');
});
}
}
diff --git a/lib/docparser.js b/lib/docparser.js
index 435cfef5..68835398 100644
--- a/lib/docparser.js
+++ b/lib/docparser.js
@@ -3,737 +3,742 @@ Copyright (c) 2011, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://yuilibrary.com/license/
*/
-YUI.add('docparser', function(Y) {
+YUI.add('docparser', function (Y) {
var Lang = Y.Lang,
- trim = Lang.trim,
- stringify = Y.JSON.stringify,
- fixType = Y.Lang.fixType,
- /**
- * Parses the JSON data and formats it into a nice log string for filename and line number:
- `/file/name.js:123`
- * @method stringlog
- * @private
- * @param {Object} data The data block from the parser
- * @return {String} The formatted string.
- * @for DocParser
- */
- stringlog = function(data) {
- var line, file;
-
- if (data.file && data.line) {
- file = data.file;
- line = data.line;
- } else {
- data.forEach(function(d) {
- if (d.tag === 'file') {
- file = d.value;
- }
- if (d.tag === 'line') {
- line = d.value;
- }
- });
- }
- return ' ' + file + ':' + line;
- },
- /*
- * Flatted a string, remove all line breaks and replace them with a token
- * @method implodeString
- * @private
- * @param {String} str The string to operate on
- * @return {String} The modified string
- */
- implodeString = function(str) {
- return str.replace(REGEX_GLOBAL_LINES, '!~YUIDOC_LINE~!');
- },
- /*
- * Un-flatted a string, replace tokens injected with `implodeString`
- * @method implodeString
- * @private
- * @param {String} str The string to operate on
- * @return {String} The modified string
- */
- explodeString = function(str) {
- return str.replace(/!~YUIDOC_LINE~!/g, '\n');
- },
- CURRENT_NAMESPACE = 'currentnamespace',
- CURRENT_MODULE = 'currentmodule',
- MAIN_MODULE = 'mainmodule',
- CURRENT_SUBMODULE = 'currentsubmodule',
- CURRENT_FILE = 'currentfile',
- CURRENT_CLASS = 'currentclass',
-
- REGEX_TYPE = /(.*?)\{(.*?)\}(.*)/,
- REGEX_FIRSTWORD = /^\s*?([^\s]+)(.*)/,
- REGEX_OPTIONAL = /\[(.*?)\]/,
- REGEX_START_COMMENT = {
- js: /^\s*\/\*\*/,
- coffee: /^\s*###\*/
- },
- REGEX_END_COMMENT = {
- js: /\*\/\s*$/,
- coffee: /###\s*$/
- },
- REGEX_LINE_HEAD_CHAR = {
- js: /^\s*\*/,
- coffee: /^\s*#/
- },
- REGEX_LINES = /\r\n|\n/,
- REGEX_GLOBAL_LINES = /\r\n|\n/g,
-
- SHORT_TAGS = {
- 'async': 1,
- 'beta': 1,
- 'chainable': 1,
- 'extends': 1,
- 'final': 1,
- 'static': 1,
- 'optional': 1,
- 'required': 1
- },
-
- /**
- * A list of known tags. This populates a member variable
- * during initialization, and will be updated if additional
- * digesters are added.
- * @property TAGLIST
- * @type Array
- * @final
- * @for DocParser
- */
- TAGLIST = [
- "async", // bool, custom events can fire the listeners in a setTimeout
- "author", // author best for projects and modules, but can be used anywhere // multi
- "attribute", // YUI attributes -- get/set with change notification, etc
- "beta", // module maturity identifier
- "broadcast", // bool, events
- "bubbles", // custom events that bubble
- "category", // modules can be in multiple categories
- "chainable", // methods that return the host object
- "class", // pseudo class
- "conditional", // conditional module
- "config", // a config param (not an attribute, so no change events)
- "const", // not standardized yet, converts to final property
- "constructs", // factory methods (not yet used)
- "constructor", // this is a constructor
- "contributor", // like author
- "default", // property/attribute default value
- "deprecated", // please specify what to use instead
- "description", // can also be free text at the beginning of a comment is
- "emitfacade", // bool, YUI custom event can have a dom-like event facade
- "event", // YUI custom event
- "evil", // uses eval
- "extension", // this is an extension for [entity]
- "extensionfor", // this is an extension for [entity]
- "extension_for", // this is an extension for [entity]
- "example", // 0..n code snippets. snippets can also be embedded in the desc
- "experimental", // module maturity identifier
- "extends", // pseudo inheritance
- "file", // file name (used by the parser)
- "final", // not meant to be changed
- "fireonce", // bool, YUI custom event config allows
- "for", // used to change class context
- "global", // declare your globals
- "icon", // project icon(s)
- "in", // indicates module this lives in (obsolete now)
- "initonly", // attribute writeonce value
- "injects", // injects {HTML|script|CSS}
- "knownissue", // 0..n known issues for your consumption
- "line", // line number for the comment block (used by the parser)
- "method", // a method
- "module", // YUI module name
- "main", // Description for the module
- "namespace", // Y.namespace, used to fully qualify class names
- "optional", // For optional attributes
- "required", // For required attributes
- "param", // member param
- "plugin", // this is a plugin for [entityl]
- "preventable", // YUI custom events can be preventable ala DOM events
- "private", // > access
- "project", // project definition, one per source tree allowed
- "property", // a regular-ole property
- "protected", // > access
- "public", // > access
- "queuable", // bool, events
- "readonly", // YUI attribute config
- "requires", // YUI module requirements
- "return", // {type} return desc -- returns is converted to this
- "see", // 0..n things to look at
- "since", // when it was introduced
- "static", // static
- "submodule", // YUI submodule
- "throws", // {execption type} description
- "title", // this should be something for the project description
- "todo", // 0..n things to revisit eventually (hopefully)
- "type", // the var type
- "url", // project url(s)
- "uses", // 0..n compents mixed (usually, via augment) into the prototype
- "value", // the value of a constant
- "writeonce" // YUI attribute config
- ],
-
- /**
- * Common errors will get scrubbed instead of being ignored.
- * @property CORRECTIONS
- * @type Object
- * @final
- * @for DocParser
- */
- CORRECTIONS = {
- 'augments': 'uses', // YUI convention for prototype mixins
- 'depreciated': 'deprecated', // subtle difference
- 'desciption': 'description', // shouldn't need the @description tag at all
- 'extend': 'extends', // typo
- 'function': 'method', // we may want standalone inner functions at some point
- 'member': 'method', // probably meant method
- 'parm': 'param', // typo
- 'params': 'param', // typo
- 'pamra': 'param', // typo
- 'parma': 'param', // typo
- 'propery': 'property', // typo
- 'prop': 'property', // probably meant property
- 'returns': 'return' // need to standardize on one or the other
- },
-
- /**
- * A map of the default tag processors, keyed by the
- * tag name. Multiple tags can use the same digester
- * by supplying the string name that points to the
- * implementation rather than a function.
- * @property DIGESTERS
- * @type Object
- * @final
- * @for DocParser
- */
- DIGESTERS = {
-
- // "params": [
- // {
- // "name": "optionalandmultiple",
- // "description": "my desc",
- // "type": "string",
- // "optional": true, // [surroundedbybrackets]
- // "optdefault": "if specified, this is always string to avoid syntax errors @TODO",
- // "multiple": true // endswith*
- // }
- // ],
- // @param {type} name description -or-
- // @param name {type} description
- // #2173362 optional w/ or w/o default
- // @param {type} [optvar=default] description
- // #12 document config objects
- // @param {object|config} config description
- // @param {type} config.prop1 description
- // @param {type} config.prop2 description
- // #11 document callback argument signature
- // @param {callback|function} callback description
- // @param {type} callback.arg1 description
- // @param {type} callback.arg2 description
- // #2173362 document event facade decorations for custom events
- // @param {event} event description
- // @param {type} event.child description
- // @param {type} event.index description
- // @param name* {type} 1..n description
- // @param [name]* {type} 0..n description
- 'param': function(tagname, value, target, block) {
- // Y.log('param digester' + value);
- target.params = target.params || [];
-
- if (!value) {
- this.warnings.push({
- message: 'param name/type/descript missing',
- line: stringlog(block)
+ trim = Lang.trim,
+ fixType = Y.Lang.fixType,
+ /**
+ * Parses the JSON data and formats it into a nice log string for
+ * filename and line number: `/file/name.js:123`
+ * @method stringlog
+ * @private
+ * @param {Object} data The data block from the parser
+ * @return {String} The formatted string.
+ * @for DocParser
+ */
+ stringlog = function (data) {
+ var line, file;
+
+ if (data.file && data.line) {
+ file = data.file;
+ line = data.line;
+ } else {
+ data.forEach(function (d) {
+ if (d.tag === 'file') {
+ file = d.value;
+ }
+ if (d.tag === 'line') {
+ line = d.value;
+ }
});
- Y.log('param name/type/descript missing: ' + stringlog(block), 'warn', 'docparser');
- return;
}
+ return ' ' + file + ':' + line;
+ },
+ /**
+ * Flatten a string, remove all line breaks and replace them with a token
+ * @method implodeString
+ * @private
+ * @param {String} str The string to operate on
+ * @return {String} The modified string
+ */
+ implodeString = function (str) {
+ return str.replace(REGEX_GLOBAL_LINES, '!~YUIDOC_LINE~!');
+ },
+ /**
+ * Un-flatten a string, replace tokens injected with `implodeString`
+ * @method implodeString
+ * @private
+ * @param {String} str The string to operate on
+ * @return {String} The modified string
+ */
+ explodeString = function (str) {
+ return str.replace(/!~YUIDOC_LINE~!/g, '\n');
+ },
+ CURRENT_NAMESPACE = 'currentnamespace',
+ CURRENT_MODULE = 'currentmodule',
+ MAIN_MODULE = 'mainmodule',
+ CURRENT_SUBMODULE = 'currentsubmodule',
+ CURRENT_FILE = 'currentfile',
+ CURRENT_CLASS = 'currentclass',
+
+ REGEX_TYPE = /(.*?)\{(.*?)\}(.*)/,
+ REGEX_FIRSTWORD = /^\s*?([^\s]+)(.*)/,
+ REGEX_OPTIONAL = /\[(.*?)\]/,
+ REGEX_START_COMMENT = {
+ js: /^\s*\/\*\*/,
+ coffee: /^\s*###\*/
+ },
+ REGEX_END_COMMENT = {
+ js: /\*\/\s*$/,
+ coffee: /###\s*$/
+ },
+ REGEX_LINE_HEAD_CHAR = {
+ js: /^\s*\*/,
+ coffee: /^\s*#/
+ },
+ REGEX_LINES = /\r\n|\n/,
+ REGEX_GLOBAL_LINES = /\r\n|\n/g,
+
+ SHORT_TAGS = {
+ 'async': 1,
+ 'beta': 1,
+ 'chainable': 1,
+ 'extends': 1,
+ 'final': 1,
+ 'static': 1,
+ 'optional': 1,
+ 'required': 1
+ },
- var type, name, optional, optdefault, parent, multiple, len,
- desc = implodeString(trim(value)),
- match = REGEX_TYPE.exec(desc),
- host = target.params;
-
- // Extract {type}
- if (match) {
- type = fixType(trim(match[2]));
- desc = trim(match[1] + match[3]);
- }
+ /**
+ * A list of known tags. This populates a member variable
+ * during initialization, and will be updated if additional
+ * digesters are added.
+ * @property TAGLIST
+ * @type Array
+ * @final
+ * @for DocParser
+ */
+ TAGLIST = [
+ "async", // bool, custom events can fire the listeners in a setTimeout
+ "author", // author best for projects and modules, but can be used anywhere // multi
+ "attribute", // YUI attributes -- get/set with change notification, etc
+ "beta", // module maturity identifier
+ "broadcast", // bool, events
+ "bubbles", // custom events that bubble
+ "category", // modules can be in multiple categories
+ "chainable", // methods that return the host object
+ "class", // pseudo class
+ "conditional", // conditional module
+ "config", // a config param (not an attribute, so no change events)
+ "const", // not standardized yet, converts to final property
+ "constructs", // factory methods (not yet used)
+ "constructor", // this is a constructor
+ "contributor", // like author
+ "default", // property/attribute default value
+ "deprecated", // please specify what to use instead
+ "description", // can also be free text at the beginning of a comment is
+ "emitfacade", // bool, YUI custom event can have a dom-like event facade
+ "event", // YUI custom event
+ "evil", // uses eval
+ "extension", // this is an extension for [entity]
+ "extensionfor", // this is an extension for [entity]
+ "extension_for",// this is an extension for [entity]
+ "example", // 0..n code snippets. snippets can also be embedded in the desc
+ "experimental", // module maturity identifier
+ "extends", // pseudo inheritance
+ "file", // file name (used by the parser)
+ "final", // not meant to be changed
+ "fireonce", // bool, YUI custom event config allows
+ "for", // used to change class context
+ "global", // declare your globals
+ "icon", // project icon(s)
+ "in", // indicates module this lives in (obsolete now)
+ "initonly", // attribute writeonce value
+ "injects", // injects {HTML|script|CSS}
+ "knownissue", // 0..n known issues for your consumption
+ "line", // line number for the comment block (used by the parser)
+ "method", // a method
+ "module", // YUI module name
+ "main", // Description for the module
+ "namespace", // Y.namespace, used to fully qualify class names
+ "optional", // For optional attributes
+ "required", // For required attributes
+ "param", // member param
+ "plugin", // this is a plugin for [entityl]
+ "preventable", // YUI custom events can be preventable ala DOM events
+ "private", // > access
+ "project", // project definition, one per source tree allowed
+ "property", // a regular-ole property
+ "protected", // > access
+ "public", // > access
+ "queuable", // bool, events
+ "readonly", // YUI attribute config
+ "requires", // YUI module requirements
+ "return", // {type} return desc -- returns is converted to this
+ "see", // 0..n things to look at
+ "since", // when it was introduced
+ "static", // static
+ "submodule", // YUI submodule
+ "throws", // {execption type} description
+ "title", // this should be something for the project description
+ "todo", // 0..n things to revisit eventually (hopefully)
+ "type", // the var type
+ "url", // project url(s)
+ "uses", // 0..n compents mixed (usually, via augment) into the prototype
+ "value", // the value of a constant
+ "writeonce" // YUI attribute config
+ ],
- // extract the first word, this is the param name
- match = REGEX_FIRSTWORD.exec(desc);
- if (match) {
- name = trim(match[1]);
- desc = trim(match[2]);
- }
+ /**
+ * Common errors will get scrubbed instead of being ignored.
+ * @property CORRECTIONS
+ * @type Object
+ * @final
+ * @for DocParser
+ */
+ CORRECTIONS = {
+ 'augments': 'uses', // YUI convention for prototype mixins
+ 'depreciated': 'deprecated', // subtle difference
+ 'desciption': 'description', // shouldn't need the @description tag at all
+ 'extend': 'extends', // typo
+ 'function': 'method', // we may want standalone inner functions at some point
+ 'member': 'method', // probably meant method
+ 'parm': 'param', // typo
+ 'params': 'param', // typo
+ 'pamra': 'param', // typo
+ 'parma': 'param', // typo
+ 'propery': 'property', // typo
+ 'prop': 'property', // probably meant property
+ 'returns': 'return' // need to standardize on one or the other
+ },
- if (!name) {
- if (value && value.match(/callback/i)) {
- this.warnings.push({
- message: 'Fixing missing name for callback',
- line: stringlog(block)
- });
- Y.log('Fixing missing name for callback:' + stringlog(block), 'warn', 'docparser');
- name = 'callback';
- type = 'Callback';
- } else {
+ /**
+ * A map of the default tag processors, keyed by the
+ * tag name. Multiple tags can use the same digester
+ * by supplying the string name that points to the
+ * implementation rather than a function.
+ * @property DIGESTERS
+ * @type Object
+ * @final
+ * @for DocParser
+ */
+ DIGESTERS = {
+ // "params": [
+ // {
+ // "name": "optionalandmultiple",
+ // "description": "my desc",
+ // "type": "string",
+ // "optional": true, // [surroundedbybrackets]
+ // "optdefault": "if specified, this is always string to avoid syntax errors @TODO",
+ // "multiple": true // endswith*
+ // }
+ // ],
+ // @param {type} name description -or-
+ // @param name {type} description
+ // #2173362 optional w/ or w/o default
+ // @param {type} [optvar=default] description
+ // #12 document config objects
+ // @param {object|config} config description
+ // @param {type} config.prop1 description
+ // @param {type} config.prop2 description
+ // #11 document callback argument signature
+ // @param {callback|function} callback description
+ // @param {type} callback.arg1 description
+ // @param {type} callback.arg2 description
+ // #2173362 document event facade decorations for custom events
+ // @param {event} event description
+ // @param {type} event.child description
+ // @param {type} event.index description
+ // @param name* {type} 1..n description
+ // @param [name]* {type} 0..n description
+ 'param': function (tagname, value, target, block) {
+ // Y.log('param digester' + value);
+ target.params = target.params || [];
+
+ if (!value) {
this.warnings.push({
- message: 'param name missing: ' + value,
+ message: 'param name/type/descript missing',
line: stringlog(block)
});
- Y.log('param name missing: ' + value + ':' + stringlog(block), 'warn', 'docparser');
- name = 'UNKNOWN';
+ Y.log('param name/type/descript missing: ' + stringlog(block), 'warn', 'docparser');
+ return;
}
- }
- len = name.length - 1;
+ var type, name, parts, optional, optdefault, parent, multiple, len, result,
+ desc = implodeString(trim(value)),
+ match = REGEX_TYPE.exec(desc),
+ host = target.params;
- if (name.charAt(len) == '*') {
- multiple = true;
- name = name.substr(0, len);
- }
+ // Extract {type}
+ if (match) {
+ type = fixType(trim(match[2]));
+ desc = trim(match[1] + match[3]);
+ }
- // extract [name], optional param
- if (name.indexOf('[') > -1) {
- match = REGEX_OPTIONAL.exec(name);
+ // extract the first word, this is the param name
+ match = REGEX_FIRSTWORD.exec(desc);
if (match) {
- optional = true;
name = trim(match[1]);
- // extract optional=defaultvalue
- parts = name.split('=');
- if (parts.length > 1) {
- name = parts[0];
- optdefault = parts[1];
- //Add some shortcuts for object/array defaults
- if (optdefault.toLowerCase() == 'object') {
- optdefault = '{}';
- }
- if (optdefault.toLowerCase() == 'array') {
- optdefault = '[]';
- }
- }
+ desc = trim(match[2]);
}
- }
- // parse object.prop, indicating a child property for object
- if (name.indexOf('.') > -1) {
- match = name.split('.');
- parent = trim(match[0]);
- Y.each(target.params, function(param) {
- if (param.name == parent) {
- param.props = param.props || [];
- host = param.props;
- match.shift();
- name = trim(match.join('.'));
- if (match.length > 1) {
- var pname = name.split('.')[0],
- par;
- Y.each(param.props, function(o) {
- if (o.name === pname) {
- par = o;
- }
- });
- if (par) {
- match = name.split('.');
- match.shift();
- name = match.join('.');
- par.props = par.props || [];
- host = par.props;
- }
- }
+ if (!name) {
+ if (value && value.match(/callback/i)) {
+ this.warnings.push({
+ message: 'Fixing missing name for callback',
+ line: stringlog(block)
+ });
+ Y.log('Fixing missing name for callback:' + stringlog(block), 'warn', 'docparser');
+ name = 'callback';
+ type = 'Callback';
+ } else {
+ this.warnings.push({
+ message: 'param name missing: ' + value,
+ line: stringlog(block)
+ });
+ Y.log('param name missing: ' + value + ':' + stringlog(block), 'warn', 'docparser');
+ name = 'UNKNOWN';
}
- });
-
- }
-
- result = {
- name: name,
- description: explodeString(desc)
- };
+ }
- if (type) {
- result.type = type;
- }
+ len = name.length - 1;
- if (optional) {
- result.optional = true;
- if (optdefault) {
- result.optdefault = optdefault;
+ if (name.charAt(len) === '*') {
+ multiple = true;
+ name = name.substr(0, len);
}
- }
- if (multiple) {
- result.multiple = true;
- }
- host.push(result);
+ // extract [name], optional param
+ if (name.indexOf('[') > -1) {
+ match = REGEX_OPTIONAL.exec(name);
+ if (match) {
+ optional = true;
+ name = trim(match[1]);
+ // extract optional=defaultvalue
+ parts = name.split('=');
+ if (parts.length > 1) {
+ name = parts[0];
+ optdefault = parts[1];
+ //Add some shortcuts for object/array defaults
+ if (optdefault.toLowerCase() === 'object') {
+ optdefault = '{}';
+ }
+ if (optdefault.toLowerCase() === 'array') {
+ optdefault = '[]';
+ }
+ }
+ }
+ }
+ // parse object.prop, indicating a child property for object
+ if (name.indexOf('.') > -1) {
+ match = name.split('.');
+ parent = trim(match[0]);
+ Y.each(target.params, function (param) {
+ if (param.name === parent) {
+ param.props = param.props || [];
+ host = param.props;
+ match.shift();
+ name = trim(match.join('.'));
+ if (match.length > 1) {
+ var pname = name.split('.')[0],
+ par;
+ Y.each(param.props, function (o) {
+ if (o.name === pname) {
+ par = o;
+ }
+ });
+ if (par) {
+ match = name.split('.');
+ match.shift();
+ name = match.join('.');
+ par.props = par.props || [];
+ host = par.props;
+ }
+ }
+ }
+ });
- },
+ }
- // @return {type} description // methods
- // @returns {type} description // methods
- // @throws {type} an error #2173342
- // @injects {HTML|CSS|script} description
- // can be used by anthing that has an optional {type} and a description
- 'return': function(tagname, value, target, block) {
-
- var desc = implodeString(trim(value)), type,
- match = REGEX_TYPE.exec(desc),
- result = {};
- if (match) {
- type = fixType(trim(match[2]));
- desc = trim(match[1] + match[3]);
- }
+ result = {
+ name: name,
+ description: explodeString(desc)
+ };
- result = {
- description: explodeString(desc)
- };
+ if (type) {
+ result.type = type;
+ }
- if (type) {
- result.type = type;
- }
+ if (optional) {
+ result.optional = true;
+ if (optdefault) {
+ result.optdefault = optdefault;
+ }
+ }
- target[tagname] = result;
+ if (multiple) {
+ result.multiple = true;
+ }
- },
- 'throws': 'return',
- 'injects': 'return',
+ host.push(result);
+ },
- // trying to overwrite the constructor value is a bad idea
- 'constructor': function(tagname, value, target, block) {
- target.is_constructor = 1;
- },
+ // @return {type} description // methods
+ // @returns {type} description // methods
+ // @throws {type} an error #2173342
+ // @injects {HTML|CSS|script} description
+ // can be used by anthing that has an optional {type} and a description
+ 'return': function (tagname, value, target, block) {
- // @author {twitter: @arthurdent | github: ArthurDent}
- // Arthur Dent adent@h2g2.earth #23, multiple // modules/class/method
- // 'author': function(tagname, value, target, block) {
- // // Y.log('author digester');
- // },
-
- // A key bock type for declaring modules and submodules
- // subsequent class and member blocks will be assigned
- // to this module.
- 'module': function(tagname, value, target, block) {
- this.set(CURRENT_MODULE, value);
- var go = true;
- Y.some(block, function(o) {
- if (trim(o.tag) == 'submodule') {
- go = false;
- return true;
- }
- });
- if (go) {
- if (!this.get(MAIN_MODULE)) {
- var o = {
- tag: tagname,
- name: value,
- file: target.file,
- line: target.line,
- description: target.description
- };
- this.set(MAIN_MODULE, o);
+ var desc = implodeString(trim(value)),
+ type,
+ match = REGEX_TYPE.exec(desc),
+ result = {};
+ if (match) {
+ type = fixType(trim(match[2]));
+ desc = trim(match[1] + match[3]);
}
- host = this.modules[value];
- return host;
- }
- return null;
- },
- //Setting the description for the module..
- 'main': function(tagname, value, target, block) {
- var o = target;
- o.mainName = value;
- o.tag = tagname;
- o.itemtype = 'main';
- o._main = true;
- this.set(MAIN_MODULE, o);
- },
+ result = {
+ description: explodeString(desc)
+ };
- // accepts a single project definition for the source tree
- 'project': function(tagname, value, target, block) {
- return this.project;
- },
+ if (type) {
+ result.type = type;
+ }
- // A key bock type for declaring submodules. subsequent class and
- // member blocks will be assigned to this submodule.
- 'submodule': function(tagname, value, target, block) {
- //console.log('Setting current submodule: ', value, 'on class');
- this.set(CURRENT_SUBMODULE, value);
- var host = this.modules[value],
- clazz = this.get(CURRENT_CLASS),
- parent = this.get(CURRENT_MODULE);
+ target[tagname] = result;
+
+ },
+ 'throws': 'return',
+ 'injects': 'return',
+
+ // trying to overwrite the constructor value is a bad idea
+ 'constructor': function (tagname, value, target, block) {
+ target.is_constructor = 1;
+ },
+
+ // @author {twitter: @arthurdent | github: ArthurDent}
+ // Arthur Dent adent@h2g2.earth #23, multiple // modules/class/method
+ // 'author': function(tagname, value, target, block) {
+ // // Y.log('author digester');
+ // },
+
+ // A key bock type for declaring modules and submodules
+ // subsequent class and member blocks will be assigned
+ // to this module.
+ 'module': function (tagname, value, target, block) {
+ this.set(CURRENT_MODULE, value);
+ var go = true;
+ Y.some(block, function (o) {
+ if (trim(o.tag) === 'submodule') {
+ go = false;
+ return true;
+ }
+ });
+ if (go) {
+ if (!this.get(MAIN_MODULE)) {
+ this.set(MAIN_MODULE, {
+ tag: tagname,
+ name: value,
+ file: target.file,
+ line: target.line,
+ description: target.description
+ });
+ }
+ return this.modules[value];
+ }
+ return null;
+ },
+
+ //Setting the description for the module..
+ 'main': function (tagname, value, target, block) {
+ var o = target;
+ o.mainName = value;
+ o.tag = tagname;
+ o.itemtype = 'main';
+ o._main = true;
+ this.set(MAIN_MODULE, o);
+ },
+
+ // accepts a single project definition for the source tree
+ 'project': function (tagname, value, target, block) {
+ return this.project;
+ },
+
+ // A key bock type for declaring submodules. subsequent class and
+ // member blocks will be assigned to this submodule.
+ 'submodule': function (tagname, value, target, block) {
+ //console.log('Setting current submodule: ', value, 'on class');
+ this.set(CURRENT_SUBMODULE, value);
+ var host = this.modules[value],
+ clazz = this.get(CURRENT_CLASS),
+ parent = this.get(CURRENT_MODULE);
if (parent) {
host.module = parent;
}
if (clazz && this.classes[clazz]) {
//console.log('Adding submodule', value , 'to class', clazz, ' it has submodule', this.classes[clazz].submodule);
//if (!this.classes[clazz].submodule) {
- //console.log('REALLY Adding submodule', value , 'to class', clazz);
- this.classes[clazz].submodule = value;
+ //console.log('REALLY Adding submodule', value , 'to class', clazz);
+ this.classes[clazz].submodule = value;
//}
}
- return host;
- },
-
- // A key bock type for declaring classes, subsequent
- // member blocks will be assigned to this class
- 'class': function(tagname, value, target, block) {
- var _namespace, _value = value;
-
- block.forEach(function(def) {
- if (def.tag === 'namespace') {
- //We have a namespace, augment the name
- var name = trim(def.value) + '.' + value;
- if (value.indexOf(trim(def.value) + '.') === -1) {
- value = name;
- _namespace = trim(def.value);
+ return host;
+ },
+
+ // A key bock type for declaring classes, subsequent
+ // member blocks will be assigned to this class
+ 'class': function (tagname, value, target, block) {
+ var namespace, fullname, host, parent;
+
+ block.forEach(function (def) {
+ if (def.tag === 'namespace') {
+ //We have a namespace, augment the name
+ var name = trim(def.value) + '.' + value;
+ if (value.indexOf(trim(def.value) + '.') === -1) {
+ value = name;
+ namespace = trim(def.value);
+ }
}
+ });
+
+ if (namespace) {
+ this.set(CURRENT_NAMESPACE, namespace);
}
- });
+ this.set(CURRENT_CLASS, value);
- if (_namespace) {
- this.set(CURRENT_NAMESPACE, _namespace);
- }
- this.set(CURRENT_CLASS, value);
- var fullname = this.get(CURRENT_CLASS);
- var host = this.classes[fullname],
+ fullname = this.get(CURRENT_CLASS);
+ host = this.classes[fullname];
parent = this.get(CURRENT_MODULE);
- if (_namespace) {
- host.namespace = _namespace;
- }
- if (parent) {
- host.module = parent;
- }
-
- //Merge host and target in case the class was defined in a "for" tag
- //before it was defined in a "class" tag
- host = Y.merge(host, target);
- this.classes[fullname] = host;
- parent = this.get(CURRENT_SUBMODULE);
- if (parent) {
- //this.set(CURRENT_SUBMODULE, parent);
- host.submodule = parent;
- }
- return host;
- },
-
- // change 'const' to final property
- 'const': function(tagname, value, target, block) {
- target.itemtype = 'property';
- target.name = value;
- target['final'] = '';
- },
-
- // supported classitems
- 'property': function(tagname, value, target, block) {
- var match, name, desc;
+ if (namespace) {
+ host.namespace = namespace;
+ }
+ if (parent) {
+ host.module = parent;
+ }
- target.itemtype = tagname;
- target.name = value;
- if (!target.type) {
- desc = implodeString(trim(value)),
- match = REGEX_TYPE.exec(desc);
-
- // Extract {type}
- if (match) {
- type = fixType(trim(match[2]));
- name = trim(match[1] + match[3]);
- target.type = type;
- target.name = name;
+ //Merge host and target in case the class was defined in a "for" tag
+ //before it was defined in a "class" tag
+ host = Y.merge(host, target);
+ this.classes[fullname] = host;
+ parent = this.get(CURRENT_SUBMODULE);
+ if (parent) {
+ //this.set(CURRENT_SUBMODULE, parent);
+ host.submodule = parent;
}
-
- }
- if (target.type && target.type.toLowerCase() === 'object') {
- block.forEach(function(i, k) {
- if (i.tag === 'property') {
- i.value = trim(i.value);
- i.tag = 'param';
- block[k] = i;
+ return host;
+ },
+
+ // change 'const' to final property
+ 'const': function (tagname, value, target, block) {
+ target.itemtype = 'property';
+ target.name = value;
+ /*jshint sub:true */
+ target['final'] = '';
+ },
+
+ // supported classitems
+ 'property': function (tagname, value, target, block) {
+ var match, name, desc, type;
+
+ target.itemtype = tagname;
+ target.name = value;
+ if (!target.type) {
+ desc = implodeString(trim(value));
+ match = REGEX_TYPE.exec(desc);
+
+ // Extract {type}
+ if (match) {
+ type = fixType(trim(match[2]));
+ name = trim(match[1] + match[3]);
+ target.type = type;
+ target.name = name;
}
- });
- }
- },
- 'method': 'property',
- 'attribute': 'property',
- 'config': 'property',
- 'event': 'property',
-
- // access fields
- 'public': function(tagname, value, target, block) {
- target.access = tagname;
- target.tagname = value;
- },
- 'private': 'public',
- 'protected': 'public',
- 'inner': 'public',
-
- // tags that can have multiple occurances in a single block
- 'todo': function(tagname, value, target, block) {
- if (!Lang.isArray(target[tagname])) {
- target[tagname] = [];
- }
- //If the item is @tag one,two
- if (value.indexOf(',') > -1) {
- value = value.split(',');
- } else {
- value = [value];
- }
-
- value.forEach(function(v) {
- v = trim(v);
- target[tagname].push(v);
- });
- },
- 'extension_for': 'extensionfor',
- 'extensionfor': function(tagname, value, target, block) {
- if (this.classes[this.get(CURRENT_CLASS)]) {
- this.classes[this.get(CURRENT_CLASS)].extension_for.push(value);
- }
- },
- 'example': function(tagname, value, target, block) {
- if (!Lang.isArray(target[tagname])) {
- target[tagname] = [];
- }
- var e = value;
- block.forEach(function(v) {
- if (v.tag == 'example') {
- if (v.value.indexOf(value) > -1) {
- e = v.value;
- }
}
- });
-
- target[tagname].push(e);
- },
- 'url': 'todo',
- 'icon': 'todo',
- 'see': 'todo',
- 'throws': 'todo',
- 'requires': 'todo',
- 'knownissue': 'todo',
- 'uses': 'todo',
- 'category': 'todo',
- 'unimplemented': 'todo',
-
- genericValueTag: function (tagname, value, target, block) {
- target[tagname] = value;
- },
-
- 'author' : 'genericValueTag',
- 'contributor': 'genericValueTag',
- 'since' : 'genericValueTag',
+ if (target.type && target.type.toLowerCase() === 'object') {
+ block.forEach(function (i, k) {
+ if (i.tag === 'property') {
+ i.value = trim(i.value);
+ i.tag = 'param';
+ block[k] = i;
+ }
+ });
+ }
+ },
+ 'method': 'property',
+ 'attribute': 'property',
+ 'config': 'property',
+ 'event': 'property',
+
+ // access fields
+ 'public': function (tagname, value, target, block) {
+ target.access = tagname;
+ target.tagname = value;
+ },
+ 'private': 'public',
+ 'protected': 'public',
+ 'inner': 'public',
+
+ // tags that can have multiple occurances in a single block
+ 'todo': function (tagname, value, target, block) {
+ if (!Lang.isArray(target[tagname])) {
+ target[tagname] = [];
+ }
+ //If the item is @tag one,two
+ if (value.indexOf(',') > -1) {
+ value = value.split(',');
+ } else {
+ value = [value];
+ }
- 'deprecated': function (tagname, value, target, block) {
- target.deprecated = true;
+ value.forEach(function (v) {
+ v = trim(v);
+ target[tagname].push(v);
+ });
+ },
+ 'extension_for': 'extensionfor',
+ 'extensionfor': function (tagname, value, target, block) {
+ if (this.classes[this.get(CURRENT_CLASS)]) {
+ this.classes[this.get(CURRENT_CLASS)].extension_for.push(value);
+ }
+ },
+ 'example': function (tagname, value, target, block) {
+ if (!Lang.isArray(target[tagname])) {
+ target[tagname] = [];
+ }
- if (typeof value === 'string' && value.length) {
- target.deprecationMessage = value;
- }
- },
+ var e = value;
+ block.forEach(function (v) {
+ if (v.tag === 'example') {
+ if (v.value.indexOf(value) > -1) {
+ e = v.value;
+ }
+ }
+ });
- // updates the current namespace
- 'namespace': function(tagname, value, target, block) {
- this.set(CURRENT_NAMESPACE, value);
- if (value === '') {
- //Shortcut this if namespace is an empty string.
- return;
- }
- var file = this.get(CURRENT_FILE);
- if (file) {
- this.files[file].namespaces[value] = 1;
- }
- var mod = this.get(CURRENT_MODULE);
- if (mod) {
- this.modules[mod].namespaces[value] = 1;
- }
+ target[tagname].push(e);
+ },
+ 'url': 'todo',
+ 'icon': 'todo',
+ 'see': 'todo',
+ 'requires': 'todo',
+ 'knownissue': 'todo',
+ 'uses': 'todo',
+ 'category': 'todo',
+ 'unimplemented': 'todo',
+
+ genericValueTag: function (tagname, value, target, block) {
+ target[tagname] = value;
+ },
+
+ 'author': 'genericValueTag',
+ 'contributor': 'genericValueTag',
+ 'since': 'genericValueTag',
+
+ 'deprecated': function (tagname, value, target, block) {
+ target.deprecated = true;
+
+ if (typeof value === 'string' && value.length) {
+ target.deprecationMessage = value;
+ }
+ },
- var mod = this.get(CURRENT_SUBMODULE);
- if (mod) {
- this.modules[mod].namespaces[value] = 1;
- }
+ // updates the current namespace
+ 'namespace': function (tagname, value, target, block) {
+ this.set(CURRENT_NAMESPACE, value);
+ if (value === '') {
+ //Shortcut this if namespace is an empty string.
+ return;
+ }
+ var m,
+ mod,
+ name,
+ lastNS,
+ file = this.get(CURRENT_FILE);
+ if (file) {
+ this.files[file].namespaces[value] = 1;
+ }
+ mod = this.get(CURRENT_MODULE);
+ if (mod) {
+ this.modules[mod].namespaces[value] = 1;
+ }
- var mod = this.get(CURRENT_CLASS);
- if (mod) {
- var lastNS = this.get('lastnamespace');
- if (lastNS && lastNS !== value && (value.indexOf(lastNS + '.') !== 0)) {
- if (this.classes[mod]) {
- var m = this.classes[mod];
- delete this.classes[mod];
- mod = value + '.' + mod.replace(lastNS + '.', '');
- m.name = mod;
- m.namespace = value;
- this.classes[mod] = m;
- this.set(CURRENT_CLASS, m.name);
- }
+ mod = this.get(CURRENT_SUBMODULE);
+ if (mod) {
+ this.modules[mod].namespaces[value] = 1;
}
- if (this.classes[mod]) {
- this.classes[mod].namespace = value;
- if (mod === value) {
- return;
- }
- if (mod.indexOf(value + '.') === -1) {
- if (mod.indexOf('.') === -1) {
- var m = this.classes[mod];
+
+ mod = this.get(CURRENT_CLASS);
+ if (mod) {
+ lastNS = this.get('lastnamespace');
+ if (lastNS && lastNS !== value && (value.indexOf(lastNS + '.') !== 0)) {
+ if (this.classes[mod]) {
+ m = this.classes[mod];
delete this.classes[mod];
- var name = m.namespace + '.' + m.name;
- m.name = name;
- this.classes[name] = m;
- this.set(CURRENT_CLASS, name);
- } else {
- if (mod.indexOf(this.classes[mod].namespace + '.') === -1) {
- var m = this.classes[mod];
+ mod = value + '.' + mod.replace(lastNS + '.', '');
+ m.name = mod;
+ m.namespace = value;
+ this.classes[mod] = m;
+ this.set(CURRENT_CLASS, m.name);
+ }
+ }
+ if (this.classes[mod]) {
+ this.classes[mod].namespace = value;
+ if (mod === value) {
+ return;
+ }
+ if (mod.indexOf(value + '.') === -1) {
+ if (mod.indexOf('.') === -1) {
+ m = this.classes[mod];
delete this.classes[mod];
- var name = m.namespace + '.' + m.shortname;
+ name = m.namespace + '.' + m.name;
m.name = name;
this.classes[name] = m;
this.set(CURRENT_CLASS, name);
+ } else {
+ if (mod.indexOf(this.classes[mod].namespace + '.') === -1) {
+ m = this.classes[mod];
+ delete this.classes[mod];
+ name = m.namespace + '.' + m.shortname;
+ m.name = name;
+ this.classes[name] = m;
+ this.set(CURRENT_CLASS, name);
+ }
}
}
}
}
- }
- },
+ },
- // updates the current class only (doesn't create
- // a new class definition)
- 'for': function(tagname, value, target, block) {
- value = this._resolveFor(value);
- this.set(CURRENT_CLASS, value);
- var ns = ((this.classes[value]) ? this.classes[value].namespace : '');
- this.set(CURRENT_NAMESPACE, ns);
- var file = this.get(CURRENT_FILE);
- if (file) {
- this.files[file].fors[value] = 1;
- }
- var mod = this.get(CURRENT_MODULE);
- if (mod) {
- this.modules[mod].fors[value] = 1;
- }
+ // updates the current class only (doesn't create
+ // a new class definition)
+ 'for': function (tagname, value, target, block) {
+ var ns, file, mod;
+
+ value = this._resolveFor(value);
+ this.set(CURRENT_CLASS, value);
- var mod = this.get(CURRENT_SUBMODULE);
- if (mod) {
- this.modules[mod].fors[value];
+ ns = ((this.classes[value]) ? this.classes[value].namespace : '');
+ this.set(CURRENT_NAMESPACE, ns);
+
+ file = this.get(CURRENT_FILE);
+ if (file) {
+ this.files[file].fors[value] = 1;
+ }
+
+ mod = this.get(CURRENT_MODULE);
+ if (mod) {
+ this.modules[mod].fors[value] = 1;
+ }
+
+ mod = this.get(CURRENT_SUBMODULE);
+ if (mod) {
+ this.modules[mod].fors[value] = 1;
+ }
}
- }
+ },
- },
-
- /**
- * The doc parser accepts a **map** of files to file content.
- * Once `parse()` is called, various properties will be populated
- * with the parsers data (aggregated in the `'data'` property).
- * @class DocParser
- * @extends Base
- * @constructor
- * @param {Object} o the config object
- * @module yuidoc
- */
- DocParser = function(o) {
- this.digesters = Y.merge(DocParser.DIGESTERS);
- this.knowntags = Y.Array.hash(DocParser.TAGLIST);
- DocParser.superclass.constructor.apply(this, arguments);
- };
+ /**
+ * The doc parser accepts a **map** of files to file content.
+ * Once `parse()` is called, various properties will be populated
+ * with the parsers data (aggregated in the `'data'` property).
+ * @class DocParser
+ * @extends Base
+ * @constructor
+ * @param {Object} o the config object
+ * @module yuidoc
+ */
+ DocParser = function (o) {
+ this.digesters = Y.merge(DocParser.DIGESTERS);
+ this.knowntags = Y.Array.hash(DocParser.TAGLIST);
+ DocParser.superclass.constructor.apply(this, arguments);
+ };
DocParser.NAME = 'DocParser';
@@ -742,7 +747,7 @@ YUI.add('docparser', function(Y) {
DocParser.CORRECTIONS = CORRECTIONS;
DocParser.ATTRS = {
-
+
lint: {
value: false
},
@@ -762,7 +767,7 @@ YUI.add('docparser', function(Y) {
* @attribute digesters
*/
digesters: {
- setter: function(val) {
+ setter: function (val) {
Y.mix(this.digesters, val, true);
Y.mix(this.knowntags, val, true);
return val;
@@ -775,13 +780,13 @@ YUI.add('docparser', function(Y) {
* @attribute emitters
*/
emitters: {
- setter: function(val) {
+ setter: function (val) {
Y.mix(this.emitters, val, true);
}
},
/**
- * Comment syntax type.
+ * Comment syntax type.
* @attribute syntaxtype
* @type String
*/
@@ -794,7 +799,7 @@ YUI.add('docparser', function(Y) {
* @attribute filemap
*/
filemap: {
- writeOnce : true
+ writeOnce: true
},
/**
@@ -804,7 +809,7 @@ YUI.add('docparser', function(Y) {
* @attribute dirmap
*/
dirmap: {
- writeOnce : true
+ writeOnce: true
},
/**
@@ -813,7 +818,7 @@ YUI.add('docparser', function(Y) {
* @type String
*/
currentfile: {
- setter: function(val) {
+ setter: function (val) {
val = trim(val);
// this.set(CURRENT_NAMESPACE, '');
if (!(val in this.files)) {
@@ -829,19 +834,19 @@ YUI.add('docparser', function(Y) {
}
},
/**
- * The main documentation block for the module itself.
- * @attribute mainmodule
+ * The main documentation block for the module itself.
+ * @attribute mainmodule
* @type String
- */
+ */
mainmodule: {
- setter: function(o) {
+ setter: function (o) {
if (!o) {
return;
}
- //console.log('Main Module Setter: ', o);
+ //console.log('Main Module Setter: ', o);
var write = true,
name = o.mainName || o.name;
- if (this.get(CURRENT_MODULE) === name) {
+ if (this.get(CURRENT_MODULE) === name) {
if (name in this.modules) {
//console.log('In Global Modules', this.modules[name]);
@@ -852,12 +857,12 @@ YUI.add('docparser', function(Y) {
}
}
if (write) {
- //console.log('Writing');
+ //console.log('Writing');
this.modules[name] = Y.merge(this.modules[name], o);
}
} else {
if (o._main) {
- //console.log('Writing');
+ //console.log('Writing');
this.modules[name] = o;
}
}
@@ -870,18 +875,23 @@ YUI.add('docparser', function(Y) {
* @type String
*/
currentmodule: {
- setter: function(val) {
+ setter: function (val) {
if (!val) {
return val;
}
val = trim(val);
+
+ var modMain, clazz;
+
this.set(CURRENT_SUBMODULE, '');
this.set(CURRENT_NAMESPACE, '');
- var m = this.get(MAIN_MODULE);
- if (m && m.name !== val) {
- this.set(MAIN_MODULE, '');
- }
- var clazz = this.classes[this.get(CURRENT_CLASS)];
+
+ modMain = this.get(MAIN_MODULE);
+ if (modMain && modMain.name !== val) {
+ this.set(MAIN_MODULE, '');
+ }
+
+ clazz = this.classes[this.get(CURRENT_CLASS)];
if (clazz) {
//Handles case where @module comes after @class in a new directory of files
if (clazz.module !== val) {
@@ -903,6 +913,7 @@ YUI.add('docparser', function(Y) {
}
}
}
+
if (!(val in this.modules)) {
this.modules[val] = {
name: val,
@@ -912,6 +923,7 @@ YUI.add('docparser', function(Y) {
namespaces: {}
};
}
+
return val;
}
},
@@ -922,7 +934,7 @@ YUI.add('docparser', function(Y) {
* @type String
*/
currentsubmodule: {
- setter: function(val) {
+ setter: function (val) {
if (!val) {
return val;
}
@@ -945,7 +957,7 @@ YUI.add('docparser', function(Y) {
}
},
currentnamespace: {
- setter: function(val) {
+ setter: function (val) {
this.set('lastnamespace', this.get(CURRENT_NAMESPACE));
return val;
}
@@ -962,24 +974,28 @@ YUI.add('docparser', function(Y) {
* @type String
*/
currentclass: {
- setter: function(val) {
+ setter: function (val) {
if (!val) {
return val;
}
this.set('lastclass', this.get(CURRENT_CLASS));
val = trim(val);
+ var name = val,
+ ns, clazz;
if (!(val in this.classes)) {
- var ns = this.get(CURRENT_NAMESPACE),
- name = (ns && ns !== '' && (val.indexOf(ns + '.') !== 0)) ? ns + '.' + val : val,
- clazz = this.classes[name] = {
- name: name,
- shortname: val,
- classitems: [],
- plugins: [],
- extensions: [],
- plugin_for: [],
- extension_for: []
- };
+ ns = this.get(CURRENT_NAMESPACE);
+ if (ns && ns !== '' && (val.indexOf(ns + '.') !== 0)) {
+ name = ns + '.' + val;
+ }
+ clazz = this.classes[name] = {
+ name: name,
+ shortname: val,
+ classitems: [],
+ plugins: [],
+ extensions: [],
+ plugin_for: [],
+ extension_for: []
+ };
clazz.module = this.get(CURRENT_MODULE);
if (this.get(CURRENT_SUBMODULE)) {
clazz.submodule = this.get(CURRENT_SUBMODULE);
@@ -993,15 +1009,15 @@ YUI.add('docparser', function(Y) {
Y.extend(DocParser, Y.Base, {
/**
- * Takes a non-namespaced classname and resolves it to a namespace (to support `@for`)
- * @private
- * @method _resolveFor
- * @param {String} value The classname to resolve
- * @return {String} The resolved namespace + classname
- */
- _resolveFor: function(value) {
+ * Takes a non-namespaced classname and resolves it to a namespace (to support `@for`)
+ * @private
+ * @method _resolveFor
+ * @param {String} value The classname to resolve
+ * @return {String} The resolved namespace + classname
+ */
+ _resolveFor: function (value) {
if (value.indexOf('.') === -1) {
- Y.each(this.classes, function(i) {
+ Y.each(this.classes, function (i) {
if (i.shortname === value) {
if (i.namespace) {
value = i.namespace + '.' + i.shortname;
@@ -1012,37 +1028,38 @@ YUI.add('docparser', function(Y) {
return value;
},
- initializer: function() {
-
+ initializer: function () {
this.warnings = [];
var self = this;
- self.after('currentfileChange', function(e) {
+ self.after('currentfileChange', function (e) {
/*
- * File changed, so we reset class and submodule.
- * You should use @for if you want to reference another class
- * in different file.
- */
+ * File changed, so we reset class and submodule.
+ * You should use @for if you want to reference another class
+ * in different file.
+ */
self.set(CURRENT_SUBMODULE, '');
self.set(CURRENT_CLASS, '');
});
- self.after('currentmoduleChange', function(e) {
- var mod = e.newVal, classes = self.classes;
- Y.each(classes, function(clazz) {
+ self.after('currentmoduleChange', function (e) {
+ var mod = e.newVal,
+ classes = self.classes;
+ Y.each(classes, function (clazz) {
if (!(clazz.module)) {
clazz.module = mod;
}
});
});
- self.after('currentsubmoduleChange', function(e) {
- var mod = e.newVal, classes = self.classes,
+ self.after('currentsubmoduleChange', function (e) {
+ var mod = e.newVal,
+ classes = self.classes,
parent;
if (mod) {
parent = self.modules[mod].module;
- Y.each(classes, function(clazz) {
+ Y.each(classes, function (clazz) {
if (!(clazz.submodule)) {
//if ((!clazz.module) || clazz.module == parent) {
if (!clazz.module) {
@@ -1054,17 +1071,17 @@ YUI.add('docparser', function(Y) {
}
});
- self.after('currentclassChange', function(e) {
+ self.after('currentclassChange', function (e) {
var clazz = e.newVal;
- Y.each(self.classitems, function(item) {
+ Y.each(self.classitems, function (item) {
if (!(item["class"])) {
item["class"] = clazz;
}
});
// Y.log(self.classitems);
});
-
},
+
/**
Normalizes the initial indentation of the given _content_ so that the first line
is unindented, and all other lines are unindented to the same degree as the
@@ -1076,8 +1093,7 @@ YUI.add('docparser', function(Y) {
@return {String} Unindented text.
@private
**/
-
- unindent: function(content) {
+ unindent: function (content) {
var indent = content.match(/^(\s+)/);
if (indent) {
@@ -1088,36 +1104,41 @@ YUI.add('docparser', function(Y) {
},
/**
- Transforms a JavaDoc style comment block (less the start
- and end of it) into a list
- of tag/text pairs. The leading space and '*' are removed,
- but the remaining whitespace is preserved so that the
- output should be friendly for both markdown and html
- parsers.
-
- @method handlecomment
- @param {String} comment The comment to parse
- @param {String} file The file it was parsed from
- @param {String} line The line number it was found on
- */
- handlecomment: function(comment, file, line) {
+ Transforms a JavaDoc style comment block (less the start and end of it)
+ into a list of tag/text pairs. The leading space and '*' are removed,
+ but the remaining whitespace is preserved so that the output should be
+ friendly for both markdown and html parsers.
+
+ @method handlecomment
+ @param {String} comment The comment to parse
+ @param {String} file The file it was parsed from
+ @param {String} line The line number it was found on
+ **/
+ handlecomment: function (comment, file, line) {
var lines = comment.split(REGEX_LINES),
- len = lines.length, i,
+ len = lines.length,
+ i,
parts, part, peek, skip,
- results = [{tag: 'file', value: file},
- {tag: 'line', value: line}],
+ tag, value,
+ results = [{
+ tag: 'file',
+ value: file
+ }, {
+ tag: 'line',
+ value: line
+ }],
syntaxtype = this.get('syntaxtype'),
lineHeadCharRegex = REGEX_LINE_HEAD_CHAR[syntaxtype],
- hasLineHeadChar = lines[0] && lineHeadCharRegex.test(lines[0]);
+ hasLineHeadChar = lines[0] && lineHeadCharRegex.test(lines[0]);
-// trim leading line head char(star or harp) if there are any
+ // trim leading line head char(star or harp) if there are any
if (hasLineHeadChar) {
for (i = 0; i < len; i++) {
lines[i] = lines[i].replace(lineHeadCharRegex, '');
}
}
-// reconsitute and tokenize the comment block
+ // reconsitute and tokenize the comment block
comment = this.unindent(lines.join('\n'));
parts = comment.split(/(?:^|\n)\s*(@\w*)/);
len = parts.length;
@@ -1129,7 +1150,7 @@ YUI.add('docparser', function(Y) {
}
skip = false;
-// the first token may be the description, otherwise it should be a tag
+ // the first token may be the description, otherwise it should be a tag
if (i === 0 && part.substr(0, 1) !== '@') {
if (part) {
tag = '@description';
@@ -1171,20 +1192,21 @@ YUI.add('docparser', function(Y) {
* @return {Object} A map of filenames to an array of extracted
* comment text.
*/
- extract: function(filemap, dirmap) {
+ extract: function (filemap, dirmap) {
filemap = filemap || this.get('filemap');
dirmap = dirmap || this.get('dirmap');
- var syntaxtype = this.get('syntaxtype');
- var commentmap = {};
- Y.each(filemap, function(code, filename) {
+ var syntaxtype = this.get('syntaxtype'),
+ commentmap = {};
+ Y.each(filemap, function (code, filename) {
- var commentlines, comment,
+ var commentlines, comment, line,
lines = code.split(REGEX_LINES),
- len = lines.length, i, linenum;
+ len = lines.length,
+ i, linenum;
for (i = 0; i < len; i++) {
line = lines[i];
- if(REGEX_START_COMMENT[syntaxtype].test(line)) {
+ if (REGEX_START_COMMENT[syntaxtype].test(line)) {
commentlines = [];
linenum = i + 1;
@@ -1203,7 +1225,7 @@ YUI.add('docparser', function(Y) {
comment = commentlines.join('\n');
commentmap[filename] = commentmap[filename] || [];
commentmap[filename]
- .push(this.handlecomment(comment, filename, linenum));
+ .push(this.handlecomment(comment, filename, linenum));
}
}
}, this);
@@ -1217,19 +1239,17 @@ YUI.add('docparser', function(Y) {
* @method processblock
* @param {Array} an array of the tag/text pairs
*/
- processblock: function(block) {
+ processblock: function (block) {
var target = {},
- clazz,
- module,
- submodule,
digestname,
digester,
host;
+
// Y.log(block);
- Y.each(block, function(tag) {
+ Y.each(block, function (tag) {
var name = trim(tag.tag),
value = trim(tag.value),
- parent, ret;
+ ret;
//Convert empty values to a 1 for JSON data parsing later
if (SHORT_TAGS[name] && value === '') {
@@ -1237,7 +1257,6 @@ YUI.add('docparser', function(Y) {
}
if (tag && tag.tag) {
-
if (!(name in this.knowntags)) {
if (name in CORRECTIONS) {
this.warnings.push({
@@ -1254,6 +1273,7 @@ YUI.add('docparser', function(Y) {
Y.log('unknown tag: ' + name + ',' + stringlog(block), 'warn', 'docparser');
}
}
+
digestname = name;
if (digestname in this.digesters) {
digester = this.digesters[digestname];
@@ -1266,7 +1286,6 @@ YUI.add('docparser', function(Y) {
target[name] = value;
}
}
-
}, this);
if (host) {
@@ -1275,10 +1294,12 @@ YUI.add('docparser', function(Y) {
this.classitems.push(target);
target['class'] = this.get(CURRENT_CLASS);
target.module = this.get(CURRENT_MODULE);
+
host = this.get(CURRENT_SUBMODULE);
if (host) {
target.submodule = host;
}
+
host = this.get(CURRENT_NAMESPACE);
if (host) {
target.namespace = host;
@@ -1294,34 +1315,35 @@ YUI.add('docparser', function(Y) {
* @param {object} commentmap The hash of files and parsed comment blocks
* @return {object} The transformed data for the project
*/
- transform: function(commentmap) {
+ transform: function (commentmap) {
var self = this,
project = self.project = {},
files = self.files = {},
modules = self.modules = {},
classes = self.classes = {},
- classitems = self.classitems = [],
- data = self.data = {
- project: project,
- files: files,
- modules: modules,
- classes: classes,
- classitems: classitems
- };
+ classitems = self.classitems = [];
+
+ self.data = {
+ project: project,
+ files: files,
+ modules: modules,
+ classes: classes,
+ classitems: classitems
+ };
commentmap = commentmap || self.commentmap;
// process
- Y.each(commentmap, function(blocks, file) {
+ Y.each(commentmap, function (blocks, file) {
//Y.log('transform: ' + file, 'info', 'docparser');
self.set(CURRENT_FILE, file);
- Y.each(blocks, function(block) {
+ Y.each(blocks, function (block) {
self.processblock(block);
});
});
// cross reference
- Y.each(modules, function(module, name) {
+ Y.each(modules, function (module, name) {
if (module.file) {
files[module.file].modules[name] = 1;
}
@@ -1333,7 +1355,7 @@ YUI.add('docparser', function(Y) {
delete module._main;
});
- Y.each(classes, function(clazz, name) {
+ Y.each(classes, function (clazz, name) {
if (clazz.module) {
modules[clazz.module].classes[name] = 1;
}
@@ -1360,7 +1382,7 @@ YUI.add('docparser', function(Y) {
}
}
if (clazz.uses && clazz.uses.length) {
- clazz.uses.forEach(function(u) {
+ clazz.uses.forEach(function (u) {
var c = classes[u];
if (c) {
c.extension_for.push(clazz.name);
@@ -1369,11 +1391,11 @@ YUI.add('docparser', function(Y) {
}
});
- Y.each(classitems, function(v) {
+ Y.each(classitems, function (v) {
if (!v.itemtype) {
self.warnings.push({
message: 'Missing item type' + (v.description ? '\n' + v.description : ''),
- line: stringlog(v)
+ line: stringlog(v)
});
Y.log('Missing item type: ' + stringlog(v), 'warn', 'DocParser');
if (v.description) {
@@ -1382,7 +1404,7 @@ YUI.add('docparser', function(Y) {
}
if (v.itemtype === 'property' && v.params) {
v.subprops = v.params;
- v.subprops.forEach(function(i) {
+ v.subprops.forEach(function (i) {
//Remove top level prop name from sub props (should have been done in the @param parser
i.name = i.name.replace(v.name + '.', '');
});
@@ -1390,7 +1412,7 @@ YUI.add('docparser', function(Y) {
}
});
- Y.each(modules, function(mod) {
+ Y.each(modules, function (mod) {
if (!mod.file || !mod.line || !mod.name) {
console.log('Failed to find lines for', mod);
}
@@ -1407,15 +1429,15 @@ YUI.add('docparser', function(Y) {
* @return {DocParser} this parser instance. The total results
* are available in parser.data.
*/
- parse: function(filemap, dirmap) {
+ parse: function (filemap, dirmap) {
filemap = filemap || this.get('filemap');
dirmap = dirmap || this.get('dirmap');
return this.transform(this.extract(filemap, dirmap));
}
-
});
Y.DocParser = DocParser;
-}, '0.1.0', { requires: ['base-base', 'json-stringify'] });
-
+}, '0.1.0', {
+ requires: ['base-base']
+});
diff --git a/lib/docview.js b/lib/docview.js
index 0b34316c..adcbd4bf 100644
--- a/lib/docview.js
+++ b/lib/docview.js
@@ -3,14 +3,13 @@ Copyright (c) 2011, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://yuilibrary.com/license/
*/
-YUI.add('docview', function(Y) {
+YUI.add('docview', function (Y) {
-
-/*
-Selleck
-Copyright (c) 2011 Yahoo! Inc.
-Licensed under the BSD License.
-*/
+ /*
+ Selleck
+ Copyright (c) 2011 Yahoo! Inc.
+ Licensed under the BSD License.
+ */
/**
View class borrowed from [Selleck](https://github.com/rgrove/selleck)
@@ -19,7 +18,7 @@ Licensed under the BSD License.
@constructor
@param {Object} data Meta data to use in this template
@param {String} templateName The name of the template file to render.
- */
+ **/
function DocView(data, templateName) {
this.templateName = templateName;
Y.mix(this, data);
@@ -27,11 +26,11 @@ Licensed under the BSD License.
DocView.prototype = {
/**
- * **Mustache** `lambda` method for setting the HTML title
- * @method htmlTitle
- */
+ * **Mustache** `lambda` method for setting the HTML title
+ * @method htmlTitle
+ */
htmlTitle: function () {
- var name = this.displayName || this.name,
+ var name = this.displayName || this.name,
title = name;
if (title) {
@@ -46,11 +45,11 @@ Licensed under the BSD License.
},
/**
- * **Mustache** `lambda` method for setting the title
- * @method title
- */
+ * **Mustache** `lambda` method for setting the title
+ * @method title
+ */
title: function () {
- var name = this.displayName || this.name,
+ var name = this.displayName || this.name,
title = this.projectName;
if (name) {
diff --git a/lib/files.js b/lib/files.js
index a9a033b6..4bc93929 100644
--- a/lib/files.js
+++ b/lib/files.js
@@ -1,451 +1,480 @@
-YUI.add('files', function(Y) {
+YUI.add('files', function (Y) {
-/**
-* Ported fileutils methods from [Selleck](http://github.com/rgrove/selleck)
-* @class Files
-* @module yuidoc
-*/
+ /**
+ * Ported fileutils methods from [Selleck](http://github.com/rgrove/selleck)
+ * @class Files
+ * @module yuidoc
+ */
-Y.Files = {};
+ Y.Files = {};
+ /*
+ Selleck
+ Copyright (c) 2011 Yahoo! Inc.
+ Licensed under the BSD License.
+ */
-/*
-Selleck
-Copyright (c) 2011 Yahoo! Inc.
-Licensed under the BSD License.
-*/
+ var fs = require('graceful-fs'),
+ fsPath = require('path'),
+ useFS = (fs.exists) ? fs : fsPath;
-var fs = require('graceful-fs');
- fsPath = require('path'),
- useFS = (fs.exists) ? fs : fsPath;
-
-
-
-var exists = function(file, cb) {
- if (cb) {
- useFS.exists(file, cb);
- } else {
- return useFS.existsSync(file);
- }
-};
-
-Y.Files.exists = exists;
-
-
-/**
-* Copy a directory from one location to another
-* @method copyDirectory
-* @param {Path} source The source directory
-* @param {Path} dest The destination directory
-* @param {Boolean} [overwrite=false] Whether or not to overwrite destination files
- if they already exist.
-* @param {Function} callback The callback to be executed when complete.
-**/
-function copyDirectory(source, dest, overwrite, callback) {
- // Allow callback as third arg.
- if (typeof overwrite === 'function') {
- callback = overwrite;
- overwrite = null;
+ function exists(file, cb) {
+ if (cb) {
+ useFS.exists(file, cb);
+ } else {
+ return useFS.existsSync(file);
+ }
}
+ Y.Files.exists = exists;
+
+
+ /**
+ Copy a directory from one location to another
+ @method copyDirectory
+ @param {Path} source The source directory
+ @param {Path} dest The destination directory
+ @param {Boolean} [overwrite=false] Whether or not to overwrite destination files
+ if they already exist.
+ @param {Function} callback The callback to be executed when complete.
+ **/
+ function copyDirectory(source, dest, overwrite, callback) {
+ // Allow callback as third arg.
+ if (typeof overwrite === 'function') {
+ callback = overwrite;
+ overwrite = null;
+ }
- fs.stat(source, afterSourceStat);
+ fs.stat(source, afterSourceStat);
- function afterSourceStat(err, stats) {
- if (err) { return callback(err); }
+ function afterSourceStat(err, stats) {
+ if (err) {
+ return callback(err);
+ }
- if (!stats.isDirectory()) {
- return callback(new Error("Source is not a directory: " + source));
+ if (!stats.isDirectory()) {
+ return callback(new Error("Source is not a directory: " + source));
+ }
+
+ fs.lstat(dest, afterDestStat);
}
- fs.lstat(dest, afterDestStat);
- }
+ function afterDestStat(err, stats) {
+ if (err && err.code !== 'ENOENT') {
+ return callback(err);
+ }
- function afterDestStat(err, stats) {
- if (err && err.code !== 'ENOENT') { return callback(err); }
-
- if (stats) {
- // If the destination is a file or a link, either delete it or
- // bubble an error if overwrite isn't true.
- if (stats.isFile() || stats.isSymbolicLink()) {
- if (overwrite) {
- deletePath(dest); // TODO: make this async
- } else {
- callback(new Error("Destination already exists: " + dest));
- return;
+ if (stats) {
+ // If the destination is a file or a link, either delete it or
+ // bubble an error if overwrite isn't true.
+ if (stats.isFile() || stats.isSymbolicLink()) {
+ if (overwrite) {
+ deletePath(dest); // TODO: make this async
+ } else {
+ callback(new Error("Destination already exists: " + dest));
+ return;
+ }
}
- }
- afterMkDir();
- } else {
- fs.mkdir(dest, 0755, afterMkDir);
+ afterMkDir();
+ } else {
+ fs.mkdir(dest, 0755, afterMkDir);
+ }
}
- }
- function afterMkDir(err) {
- if (err && err.code !== 'EEXIST') { return callback(err); }
- fs.readdir(source, afterReadDir);
- }
+ function afterMkDir(err) {
+ if (err && err.code !== 'EEXIST') {
+ return callback(err);
+ }
+ fs.readdir(source, afterReadDir);
+ }
- function afterReadDir(err, files) {
- if (err) { return callback(err); }
+ function afterReadDir(err, files) {
+ if (err) {
+ return callback(err);
+ }
- var pending = files.length,
- filename;
+ var pending = files.length,
+ filename;
- if (!pending) { return callback(); }
+ if (!pending) {
+ return callback();
+ }
- while ((filename = files.shift())) {
- copyPath(fsPath.join(source, filename), fsPath.join(dest, filename), overwrite, function (err) {
- if (err) { return callback(err); }
+ while ((filename = files.shift())) {
+ /*jshint loopfunc:true */
+ copyPath(fsPath.join(source, filename), fsPath.join(dest, filename), overwrite, function (err) {
+ if (err) {
+ return callback(err);
+ }
- pending -= 1;
+ pending -= 1;
- if (!pending) {
- callback();
- }
- });
+ if (!pending) {
+ callback();
+ }
+ });
+ }
}
}
-}
-Y.Files.copyDirectory = copyDirectory;
-
-/**
-* Copy a file from one location to another
-* @method copyFile
-* @param {Path} source The source file
-* @param {Path} dest The destination file
-* @param {Boolean} [overwrite=false] Whether or not to overwrite destination files
- if they already exist.
-* @param {Callback} callback The callback to be executed when complete.
-* @param {Error} callback.err The Error returned from Node
-**/
-function copyFile(source, dest, overwrite, callback) {
- // Allow callback as third arg.
- if (typeof overwrite === 'function') {
- callback = overwrite;
- overwrite = null;
- }
+ Y.Files.copyDirectory = copyDirectory;
+
+ /**
+ Copy a file from one location to another
+ @method copyFile
+ @param {Path} source The source file
+ @param {Path} dest The destination file
+ @param {Boolean} [overwrite=false] Whether or not to overwrite destination files
+ if they already exist.
+ @param {Callback} callback The callback to be executed when complete.
+ @param {Error} callback.err The Error returned from Node
+ **/
+ function copyFile(source, dest, overwrite, callback) {
+ // Allow callback as third arg.
+ if (typeof overwrite === 'function') {
+ callback = overwrite;
+ overwrite = null;
+ }
- fs.lstat(source, function (err, sourceStats) {
- if (err) { return callback(err); }
+ fs.lstat(source, function (err, sourceStats) {
+ if (err) {
+ return callback(err);
+ }
- if (!sourceStats.isFile()) {
- return callback(new Error("Source is not a file: " + source));
- }
+ if (!sourceStats.isFile()) {
+ return callback(new Error("Source is not a file: " + source));
+ }
- fs.lstat(dest, function (err, destStats) {
- var rs;
+ fs.lstat(dest, function (err, destStats) {
+ var rs;
- if (err && err.code !== 'ENOENT') { return callback(err); }
+ if (err && err.code !== 'ENOENT') {
+ return callback(err);
+ }
- if (destStats) {
- if (overwrite) {
- deletePath(dest); // TODO: make this async
- } else {
- callback(new Error("Destination already exists: " + dest));
- return;
+ if (destStats) {
+ if (overwrite) {
+ deletePath(dest); // TODO: make this async
+ } else {
+ callback(new Error("Destination already exists: " + dest));
+ return;
+ }
}
- }
- rs = fs.createReadStream(source);
- rs.pipe(fs.createWriteStream(dest, {mode: 0655}));
- rs.on('end', callback);
+ rs = fs.createReadStream(source);
+ rs.pipe(fs.createWriteStream(dest, {
+ mode: 0655
+ }));
+ rs.on('end', callback);
+ });
});
- });
-}
-Y.Files.copyFile = copyFile;
-
-/**
-If _source_ is a file, copies it to _dest_. If it's a directory, recursively
-copies it and all files and directories it contains to _dest_.
-
-Note that when attempting to copy a file into a directory, you should specify
-the full path to the new file (including the new filename). Otherwise, it will
-be interpreted as an attempt to copy the _source_ file *over* the _dest_
-directory instead of *into* it.
-
-Known issues:
-- Doesn't preserve ownership or permissions on copied files/directories.
-
-@method copyPath
-@param {String} source Source path.
-@param {String} dest Destination path.
-@param {Boolean} [overwrite=false] Whether or not to overwrite destination files
-if they already exist.
-@param {Callback} callback The callback to execute when completed.
-@param {Error} callback.err
-**/
-function copyPath(source, dest, overwrite, callback) {
- var destStats = statSync(dest),
- sourceStats = statSync(source);
-
- // Allow callback as third arg.
- if (typeof overwrite === 'function') {
- callback = overwrite;
- overwrite = null;
}
+ Y.Files.copyFile = copyFile;
+
+
+ /**
+ If _source_ is a file, copies it to _dest_. If it's a directory, recursively
+ copies it and all files and directories it contains to _dest_.
+
+ Note that when attempting to copy a file into a directory, you should specify
+ the full path to the new file (including the new filename). Otherwise, it will
+ be interpreted as an attempt to copy the _source_ file *over* the _dest_
+ directory instead of *into* it.
+
+ Known issues:
+ - Doesn't preserve ownership or permissions on copied files/directories.
+
+ @method copyPath
+ @param {String} source Source path.
+ @param {String} dest Destination path.
+ @param {Boolean} [overwrite=false] Whether or not to overwrite destination files
+ if they already exist.
+ @param {Callback} callback The callback to execute when completed.
+ @param {Error} callback.err
+ **/
+ function copyPath(source, dest, overwrite, callback) {
+ var sourceStats = statSync(source);
+
+ // Allow callback as third arg.
+ if (typeof overwrite === 'function') {
+ callback = overwrite;
+ overwrite = null;
+ }
- if (!sourceStats) {
- callback(new Error("Source not found: " + source));
- return;
- }
+ if (!sourceStats) {
+ callback(new Error("Source not found: " + source));
+ return;
+ }
- if (sourceStats.isFile()) {
- copyFile(source, dest, overwrite, callback);
- } else if (sourceStats.isDirectory()) {
- copyDirectory(source, dest, overwrite, callback);
- } else {
- callback(new Error("Source is neither a file nor a directory: " + source));
+ if (sourceStats.isFile()) {
+ copyFile(source, dest, overwrite, callback);
+ } else if (sourceStats.isDirectory()) {
+ copyDirectory(source, dest, overwrite, callback);
+ } else {
+ callback(new Error("Source is neither a file nor a directory: " + source));
+ }
}
-}
-Y.Files.copyPath = copyPath;
+ Y.Files.copyPath = copyPath;
-// TODO: copySymbolicLink()?
+ // TODO: copySymbolicLink()?
-/**
-If _path_ is a file, deletes it. If _path_ is a directory, recursively deletes
-it and all files and directories it contains.
+ /**
+ If _path_ is a file, deletes it. If _path_ is a directory, recursively deletes
+ it and all files and directories it contains.
-This method is synchronous.
+ This method is synchronous.
-@method deletePath
-@param {String} path File or directory to delete.
-**/
-function deletePath(path) {
- var stats = fs.lstatSync(path);
+ @method deletePath
+ @param {String} path File or directory to delete.
+ **/
+ function deletePath(path) {
+ var stats = fs.lstatSync(path);
- if (stats.isFile() || stats.isSymbolicLink()) {
- fs.unlinkSync(path);
- } else if (stats.isDirectory()) {
- fs.readdirSync(path).forEach(function (filename) {
- deletePath(fsPath.join(path, filename));
- });
+ if (stats.isFile() || stats.isSymbolicLink()) {
+ fs.unlinkSync(path);
+ } else if (stats.isDirectory()) {
+ fs.readdirSync(path).forEach(function (filename) {
+ deletePath(fsPath.join(path, filename));
+ });
- fs.rmdirSync(path);
- }
-}
-Y.Files.deletePath = deletePath;
-
-/**
-Check to see if this is a directory
-@method isDirectory
-@param {Path} path The path to check
-@param {Boolean} [link=false] Also validate a symlink
-@return {Boolean} True if it is a directory
-**/
-function isDirectory(path, link) {
- var i = false;
- link = (link === false) ? false : true;
- try {
- var stat = fs.lstatSync(path);
-
- if (stat) {
- if (stat.isSymbolicLink() && link) {
- stat = fs.statSync(path);
- }
- i = stat.isDirectory();
+ fs.rmdirSync(path);
}
- } catch (e) {
- i = false;
}
+ Y.Files.deletePath = deletePath;
+
+
+ /**
+ Check to see if this is a directory
+
+ @method isDirectory
+ @param {Path} path The path to check
+ @param {Boolean} [link=false] Also validate a symlink
+ @return {Boolean} True if it is a directory
+ **/
+ function isDirectory(path, link) {
+ var stat,
+ result = false;
- return i;
-};
-
-Y.Files.isDirectory = isDirectory;
-
-/**
-Check to see if this is a File
-@method isFile
-@param {Path} path The path to check
-@param {Boolean} [link=false] Also validate a symlink
-@return {Boolean} True if it is a file
-**/
-function isFile(path, link) {
- var i = false;
- try {
- var stat = fs.lstatSync(path);
-
- if (stat) {
- if (stat.isSymbolicLink() && link) {
- stat = fs.statSync(path);
+ link = (link === false) ? false : true;
+
+ try {
+ stat = fs.lstatSync(path);
+ if (stat) {
+ if (stat.isSymbolicLink() && link) {
+ stat = fs.statSync(path);
+ }
+ result = stat.isDirectory();
}
- i = stat.isFile();
+ } catch (e) {
+ result = false;
}
- } catch (e) {
- i = false;
- }
- return i;
-}
-Y.Files.isFile = isFile;
-
-/**
-Check to see if this is a SymLink
-@method isSymbolicLink
-@param {Path} path The path to check
-@return {Boolean} True if it is a link
-**/
-function isSymbolicLink(path) {
- var stats = lstatSync(path);
- return stats ? stats.isSymbolicLink() : false;
-}
-Y.Files.isSymbolicLink = isSymbolicLink;
-
-/**
-Like `fs.lstatSync()`, but returns `null` instead of throwing when _path_
-doesn't exist. Will still throw on other types of errors.
-
-@method lstatSync
-@param {String} path Path to stat.
-@return {fs.Stats|null} `fs.Stats` object, or `null` if _path_ doesn't exist.
-**/
-function lstatSync(path) {
- try {
- return fs.lstatSync(path);
- } catch (ex) {
- if (ex.code === 'ENOENT') {
- return null;
+ return result;
+ }
+ Y.Files.isDirectory = isDirectory;
+
+
+ /**
+ Check to see if this is a File
+
+ @method isFile
+ @param {Path} path The path to check
+ @param {Boolean} [link=false] Also validate a symlink
+ @return {Boolean} True if it is a file
+ **/
+ function isFile(path, link) {
+ var stat,
+ result = false;
+
+ try {
+ stat = fs.lstatSync(path);
+ if (stat) {
+ if (stat.isSymbolicLink() && link) {
+ stat = fs.statSync(path);
+ }
+ result = stat.isFile();
+ }
+ } catch (e) {
+ result = false;
}
- throw ex;
+ return result;
}
-}
-Y.Files.lstatSync = lstatSync;
-
-/**
-Like `fs.statSync()`, but returns `null` instead of throwing when _path_
-doesn't exist. Will still throw on other types of errors.
-
-@method statSync
-@param {String} path Path to stat.
-@return {fs.Stats|null} `fs.Stats` object, or `null` if _path_ doesn't exist.
-**/
-function statSync(path) {
- try {
- return fs.statSync(path);
- } catch (ex) {
- if (ex.code === 'ENOENT') {
- return null;
- }
+ Y.Files.isFile = isFile;
+
- throw ex;
+ /**
+ Check to see if this is a SymLink
+
+ @method isSymbolicLink
+ @param {Path} path The path to check
+ @return {Boolean} True if it is a link
+ **/
+ function isSymbolicLink(path) {
+ var stats = lstatSync(path);
+ return stats ? stats.isSymbolicLink() : false;
}
-}
-Y.Files.statSync = statSync;
-
-/**
-Copy the theme assets directory
-@method copyAssets
-@param {Path} from The source directory
-@param {Path} dest The destination directory
-@param {Boolean} deleteFirst Should the directory be deleted if it exists
-@param {Function} callback The callback to be executed
-*/
-function copyAssets() {
- var args = Array.prototype.slice.call(arguments),
- callback = args.pop(),
- from = args.shift(),
- to = args.shift(),
- deleteFirst = args.shift();
-
- if (from[0] === from[1]) {
- if (isDirectory(from[0])) {
- if (deleteFirst && isDirectory(to)) {
- deletePath(to);
+ Y.Files.isSymbolicLink = isSymbolicLink;
+
+
+ /**
+ Like `fs.lstatSync()`, but returns `null` instead of throwing when _path_
+ doesn't exist. Will still throw on other types of errors.
+
+ @method lstatSync
+ @param {String} path Path to stat.
+ @return {fs.Stats|null} `fs.Stats` object, or `null` if _path_ doesn't exist.
+ **/
+ function lstatSync(path) {
+ try {
+ return fs.lstatSync(path);
+ } catch (ex) {
+ if (ex.code === 'ENOENT') {
+ return null;
}
- copyPath(from[0], to, true, callback);
- } else {
- callback();
+ throw ex;
}
- } else {
- if (isDirectory(from[0])) {
- if (deleteFirst && isDirectory(to)) {
- deletePath(to);
+ }
+ Y.Files.lstatSync = lstatSync;
+
+
+ /**
+ Like `fs.statSync()`, but returns `null` instead of throwing when _path_
+ doesn't exist. Will still throw on other types of errors.
+
+ @method statSync
+ @param {String} path Path to stat.
+ @return {fs.Stats|null} `fs.Stats` object, or `null` if _path_ doesn't exist.
+ **/
+ function statSync(path) {
+ try {
+ return fs.statSync(path);
+ } catch (ex) {
+ if (ex.code === 'ENOENT') {
+ return null;
}
- copyPath(from[0], to, true, function() {
- if (isDirectory(from[1])) {
- copyPath(from[1], to, true, callback)
- } else {
- callback();
+ throw ex;
+ }
+ }
+ Y.Files.statSync = statSync;
+
+ /**
+ Copy the theme assets directory
+
+ @method copyAssets
+ @param {Path} from The source directory
+ @param {Path} dest The destination directory
+ @param {Boolean} deleteFirst Should the directory be deleted if it exists
+ @param {Function} callback The callback to be executed
+ */
+ function copyAssets() {
+ var args = Array.prototype.slice.call(arguments),
+ callback = args.pop(),
+ from = args.shift(),
+ to = args.shift(),
+ deleteFirst = args.shift();
+
+ if (from[0] === from[1]) {
+ if (isDirectory(from[0])) {
+ if (deleteFirst && isDirectory(to)) {
+ deletePath(to);
}
- });
+
+ copyPath(from[0], to, true, callback);
+ } else {
+ callback();
+ }
} else {
- callback();
+ if (isDirectory(from[0])) {
+ if (deleteFirst && isDirectory(to)) {
+ deletePath(to);
+ }
+
+ copyPath(from[0], to, true, function () {
+ if (isDirectory(from[1])) {
+ copyPath(from[1], to, true, callback);
+ } else {
+ callback();
+ }
+ });
+ } else {
+ callback();
+ }
+
}
-
}
-}
+ Y.Files.copyAssets = copyAssets;
-Y.Files.copyAssets = copyAssets;
+ /**
+ Helper method for getting JSON data from a local file
-/**
-* Helper method for getting JSON data from a local file
-* @method getJSON
-* @param {Path} filename The filename to parse JSON from
-* @return {Object} The JSON data
-*/
-Y.Files.getJSON = function(filename) {
- var data = {};
- if (exists(filename)) {
- data = JSON.parse(fs.readFileSync(filename, 'utf8'));
+ @method getJSON
+ @param {Path} filename The filename to parse JSON from
+ @return {Object} The JSON data
+ **/
+ Y.Files.getJSON = function (filename) {
+ var data = {};
+ if (exists(filename)) {
+ data = JSON.parse(fs.readFileSync(filename, 'utf8'));
+ }
+ return data;
};
- return data;
-};
-
-/**
-* Helper method for writing files to disk. It wraps the NodeJS file API
-* @method writeFile
-* @param {Path} file The filename to write to
-* @param {String} data The data to write
-* @param {Callback} callback*
-*/
-
-var writeFileTimer = 100,
- readFileTimer = 100;
-
-var writeFile = function(file, data, cb) {
- var flags = {
- flags: "w", encoding: Y.charset, mode: 0644
+
+ /**
+ Helper method for writing files to disk. It wraps the NodeJS file API
+
+ @method writeFile
+ @param {Path} file The filename to write to
+ @param {String} data The data to write
+ @param {Callback} callback*
+ **/
+ function writeFile(file, data, cb) {
+ var out,
+ args = arguments,
+ flags = {
+ flags: "w",
+ encoding: Y.charset,
+ mode: 0644
+ };
+
+ if (cb) {
+ fs.writeFile(file, data, flags, function (err) {
+ if (err && err.message.match(/^EMFILE, Too many open files/)) {
+ Y.log('Writefile failed, too many open files (' + args[0] + '). Trying again.', 'warn', 'files');
+ writeFile.timer++;
+ Y.later(writeFile.timer, Y, writeFile, args);
+ return;
+ }
+ cb();
+ });
+ } else {
+ out = fs.createWriteStream(file, flags);
+ out.write(data);
+ out.end();
+ }
}
- var args = arguments;
- if (cb) {
- fs.writeFile(file, data, flags, function(err) {
+ writeFile.timer = 100;
+
+ Y.Files.writeFile = writeFile;
+
+
+ function readFile(file, enc, cb) {
+ var args = arguments;
+ fs.readFile(file, enc, function (err, data) {
if (err && err.message.match(/^EMFILE, Too many open files/)) {
- Y.log('Writefile failed, too many open files (' + args[0] + '). Trying again.', 'warn', 'files');
- writeFileTimer++;
- Y.later(writeFileTimer, Y, writeFile, args);
+ Y.log('Readfile failed, too many open files (' + args[0] + '). Trying again.', 'warn', 'files');
+ readFile.timer++;
+ Y.later(readFile.timer, Y, readFile, args);
return;
}
- cb();
+ cb(err, data);
});
- } else {
- var out = fs.createWriteStream(file, flags);
- out.write(data);
- out.end();
}
-};
-
-Y.Files.writeFile = writeFile;
-
-
-var readFile = function(file, enc, cb) {
- var args = arguments;
- fs.readFile(file, enc, function(err, data) {
- if (err && err.message.match(/^EMFILE, Too many open files/)) {
- Y.log('Readfile failed, too many open files (' + args[0] + '). Trying again.', 'warn', 'files');
- readFileTimer++;
- Y.later(readFileTimer, Y, readFile, args);
- return;
- }
- cb(err, data);
- });
-};
+ readFile.timer = 100;
-Y.Files.readFile = readFile;
+ Y.Files.readFile = readFile;
});
diff --git a/lib/help.js b/lib/help.js
index 3de4dd5a..6e59133b 100644
--- a/lib/help.js
+++ b/lib/help.js
@@ -3,20 +3,20 @@ Copyright (c) 2011, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://yuilibrary.com/license/
*/
-YUI.add('help', function(Y) {
-
+YUI.add('help', function (Y) {
+
/**
- * Shows the help text
- * @module yuidoc
- * @class Help
- */
+ * Shows the help text
+ * @module yuidoc
+ * @class Help
+ */
/**
- * The help text to display
- * @private
- * @property help
- * @type Array
- */
+ * The help text to display
+ * @private
+ * @property help
+ * @type Array
+ */
var help = [
"",
"YUI Doc generates API documentation from a modified JavaDoc syntax.",
@@ -56,23 +56,23 @@ YUI.add('help', function(Y) {
" Supply a list of paths (shell globbing is handy here)",
"",
].join('\n');
-
+
/**
- * Render the help message as a string
- * @method renderHelp
- * @return {String} The help screen to display
- */
- Y.renderHelp = function() {
+ * Render the help message as a string
+ * @method renderHelp
+ * @return {String} The help screen to display
+ */
+ Y.renderHelp = function () {
return Y.Lang.sub(help, {
VERSION: Y.packageInfo.version
});
};
/**
- * Display the help message, write it to the screen and exit
- * @method showHelp
- */
- Y.showHelp = function() {
+ * Display the help message, write it to the screen and exit
+ * @method showHelp
+ */
+ Y.showHelp = function () {
console.error(Y.renderHelp());
process.exit(0); //Shouldn't exit one on help
- }
+ };
});
diff --git a/lib/index.js b/lib/index.js
index c6bd6a49..3fc62548 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -3,6 +3,7 @@ Copyright (c) 2011, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://yuilibrary.com/license/
*/
+/*global YUI:true, Y:true */
/**
Module creates the YUI instance with the required modules, uses them and exports the **Y** to be used
by the _CLI class_ or by extenders: `require('yuidocjs');`
@@ -24,7 +25,7 @@ You can use it like this:
var args = process.argv.slice(2);
var debug = false;
-args.forEach(function(item) {
+args.forEach(function (item) {
if (item.toLowerCase() === '--debug') {
debug = true;
}
@@ -36,7 +37,7 @@ var YUI = require('yui' + (debug ? '/debug' : '')).YUI,
metaPath = path.join(__dirname, '../', 'package.json');
-process.on('uncaughtException', function(msg) {
+process.on('uncaughtException', function (msg) {
var meta = JSON.parse(fs.readFileSync(metaPath)),
inst = YUI(),
useColor = (Y ? Y.config.useColor : false);
@@ -44,7 +45,7 @@ process.on('uncaughtException', function(msg) {
inst.applyConfig({
debug: true,
useColor: useColor
- });
+ });
inst.log('--------------------------------------------------------------------------', 'error');
inst.log('An uncaught YUIDoc error has occurred, stack trace given below', 'error');
diff --git a/lib/options.js b/lib/options.js
index 1b262d43..39a89ec7 100644
--- a/lib/options.js
+++ b/lib/options.js
@@ -1,21 +1,22 @@
-YUI.add('options', function(Y) {
-
+YUI.add('options', function (Y) {
+
var path = require('path');
/**
- * Handles argument parsing
- * @module yuidoc
- * @class Options
- */
+ * Handles argument parsing
+ * @module yuidoc
+ * @class Options
+ */
/**
- * Parses arguments and returns an Object of config options
- * @method Options
- * @param {Array} args Arguments to parse
- * @return {Object} The config object
- */
- Y.Options = function(args) {
-
+ * Parses arguments and returns an Object of config options
+ * @method Options
+ * @param {Array} args Arguments to parse
+ * @return {Object} The config object
+ */
+ Y.Options = function (args) {
+ /*jshint onevar:false */
+
var options = {
port: 3000,
nocode: false
@@ -25,141 +26,145 @@ YUI.add('options', function(Y) {
var v = args.shift();
// options.* defined in ./builder.js
switch (v) {
- case '--lint':
- options.lint = true;
- options.parseOnly = true;
- options.writeJSON = false;
- options.quiet = true;
- break;
- case "--debug":
- Y.applyConfig({ debug: true, filter: 'debug' });
- break;
- case "--charset":
- Y.charset = args.shift() || 'utf8';
- Y.log('Setting default charset to ' + Y.charset, 'yuidoc', 'warn');
- break;
- case "-c":
- case "--config":
- case "--configfile":
- options.configfile = args.shift();
- break;
- case "-e":
- case "--extension":
- options.extension = args.shift();
- break;
- case "-x":
- case "--exclude":
- options.exclude = args.shift();
- break;
- case "-v":
- case "--version":
- console.error(Y.packageInfo.version);
- process.exit(1);
- break;
- case "--project-version":
- options.version = args.shift();
- break;
- case "-N":
- case "--no-color":
- Y.config.useColor = false;
- options.nocolor = true;
- break;
- case "-D":
- case "--no-delete-out":
- options.nodeleteout = true;
- break;
- case "-C":
- case "--no-code":
- options.nocode = true;
- break;
- case "-n":
- case "--norecurse":
- options.norecurse = true;
- break;
- case "-S":
- case "--selleck":
- options.selleck = true;
- break;
- case "-V":
- case "--view":
- options.dumpview = true;
- break;
- case "-p":
- case "--parse-only":
- options.parseOnly = true;
- break;
- case "-o":
- case "--outdir":
- options.outdir = args.shift();
- break;
- case "-t":
- case "--themedir":
- options.themedir = args.shift();
- break;
- case "--server":
- options.server = true;
- var a = args.shift();
- var p = parseInt(a, 10);
- if (isNaN(p) || !p) {
- if (a) {
- args.unshift(a);
- }
- Y.log('Failed to extract port, setting to the default :3000', 'warn', 'yuidoc');
- } else {
- options.port = p;
- }
- break;
- case "-h":
- case "--help":
- Y.showHelp();
- break;
- case "-H":
- case "--helpers":
- var list = args.shift();
- if (list) {
- options.helpers = list.split(',');
- } else {
- throw('Failed to pass a helper file.');
- }
- break;
- case "-T":
- case "--theme":
- var theme = args.shift();
- options.themedir = path.join(__dirname, '../', 'themes', theme);
- break;
- case "-q":
- case "--quiet":
- options.quiet = true;
- break;
- case "--syntaxtype":
- options.syntaxtype = args.shift();
- break;
- case "--tab-to-space":
- options.tabtospace = parseInt(args.shift(), 10);
- if (typeof options.tabtospace === 'number') {
- options.tabspace = '';
- for (var s = 0; s < options.tabtospace; s++) {
- options.tabspace += ' ';
- }
+ case '--lint':
+ options.lint = true;
+ options.parseOnly = true;
+ options.writeJSON = false;
+ options.quiet = true;
+ break;
+ case "--debug":
+ Y.applyConfig({
+ debug: true,
+ filter: 'debug'
+ });
+ break;
+ case "--charset":
+ Y.charset = args.shift() || 'utf8';
+ Y.log('Setting default charset to ' + Y.charset, 'yuidoc', 'warn');
+ break;
+ case "-c":
+ case "--config":
+ case "--configfile":
+ options.configfile = args.shift();
+ break;
+ case "-e":
+ case "--extension":
+ options.extension = args.shift();
+ break;
+ case "-x":
+ case "--exclude":
+ options.exclude = args.shift();
+ break;
+ case "-v":
+ case "--version":
+ console.error(Y.packageInfo.version);
+ process.exit(1);
+ break;
+ case "--project-version":
+ options.version = args.shift();
+ break;
+ case "-N":
+ case "--no-color":
+ Y.config.useColor = false;
+ options.nocolor = true;
+ break;
+ case "-D":
+ case "--no-delete-out":
+ options.nodeleteout = true;
+ break;
+ case "-C":
+ case "--no-code":
+ options.nocode = true;
+ break;
+ case "-n":
+ case "--norecurse":
+ options.norecurse = true;
+ break;
+ case "-S":
+ case "--selleck":
+ options.selleck = true;
+ break;
+ case "-V":
+ case "--view":
+ options.dumpview = true;
+ break;
+ case "-p":
+ case "--parse-only":
+ options.parseOnly = true;
+ break;
+ case "-o":
+ case "--outdir":
+ options.outdir = args.shift();
+ break;
+ case "-t":
+ case "--themedir":
+ options.themedir = args.shift();
+ break;
+ case "--server":
+ options.server = true;
+ var a = args.shift();
+ var p = parseInt(a, 10);
+ if (isNaN(p) || !p) {
+ if (a) {
+ args.unshift(a);
}
- break;
- default:
- if (!options.paths) {
- options.paths = [];
+ Y.log('Failed to extract port, setting to the default :3000', 'warn', 'yuidoc');
+ } else {
+ options.port = p;
+ }
+ break;
+ case "-h":
+ case "--help":
+ Y.showHelp();
+ break;
+ case "-H":
+ case "--helpers":
+ var list = args.shift();
+ if (list) {
+ options.helpers = list.split(',');
+ } else {
+ throw ('Failed to pass a helper file.');
+ }
+ break;
+ case "-T":
+ case "--theme":
+ var theme = args.shift();
+ options.themedir = path.join(__dirname, '../', 'themes', theme);
+ break;
+ case "-q":
+ case "--quiet":
+ options.quiet = true;
+ break;
+ case "--syntaxtype":
+ options.syntaxtype = args.shift();
+ break;
+ case "--tab-to-space":
+ options.tabtospace = parseInt(args.shift(), 10);
+ if (typeof options.tabtospace === 'number') {
+ options.tabspace = '';
+ for (var s = 0; s < options.tabtospace; s++) {
+ options.tabspace += ' ';
}
- if (v && v.indexOf('-') === 0) {
- throw('Unknown option: ' + v);
- }
- options.paths.push(v);
+ }
+ break;
+ default:
+ if (!options.paths) {
+ options.paths = [];
+ }
+ if (v && v.indexOf('-') === 0) {
+ throw ('Unknown option: ' + v);
+ }
+ options.paths.push(v);
}
}
if (options.quiet) {
- Y.applyConfig({ debug: false });
+ Y.applyConfig({
+ debug: false
+ });
}
-
- return options;
+ return options;
};
});
diff --git a/lib/project.js b/lib/project.js
index c66f31d7..0eabb7fe 100644
--- a/lib/project.js
+++ b/lib/project.js
@@ -1,16 +1,18 @@
-YUI.add('project', function(Y) {
-
+YUI.add('project', function (Y) {
+
Y.Project = {
- mix: function(json, options) {
+ mix: function (json, options) {
if (json.project) {
options = Y.merge(options, json.project);
}
+
if (options.title && !options.name) {
options.name = options.title;
}
+
return options;
},
- init: function(options) {
+ init: function (options) {
var project = {};
if (options.configfile) {
project = Y.Files.getJSON(options.configfile);
@@ -22,7 +24,6 @@ YUI.add('project', function(Y) {
}
}
-
if (project.options && Object.keys(project.options).length) {
options = Y.merge(project.options, options);
delete project.options;
@@ -45,8 +46,9 @@ YUI.add('project', function(Y) {
Y.showHelp();
process.exit(1);
}
-
+
if (typeof options.tabtospace === 'number') {
+ /*jshint onevar:false */
options.tabspace = '';
for (var s = 0; s < options.tabtospace; s++) {
options.tabspace += ' ';
@@ -54,7 +56,7 @@ YUI.add('project', function(Y) {
}
return options;
-
}
};
+
});
diff --git a/lib/server.js b/lib/server.js
index 907ea6b6..90e765f5 100644
--- a/lib/server.js
+++ b/lib/server.js
@@ -1,228 +1,230 @@
-YUI.add('server', function(Y) {
-
- var path = require('path');
- /**
- * Provides the `--server` server option for YUIDoc
- * @class Server
- * @module yuidoc
- */
- var Server = {
- /**
- * Cache for external mixed in data.
- * @property _externalData
- * @private
- * @type Object
- */
- _externalData: null,
- /**
- * Middleware to parse the API docs per request
- * @method parse
- * @param {Request} req Express request object
- * @param {Response} res Express response object
- * @param {Function} next Express next callback
- */
- parse: function(req, res, next) {
- var json = (new Y.YUIDoc(Server.options)).run();
- Server.options = Y.Project.mix(json, Server.options);
- Server.builder = new Y.DocBuilder(Server.options, json);
- if (Server._externalData) {
- Server.options.externalData = Server._externalData;
- Server.builder._mixExternal();
- }
+YUI.add('server', function (Y) {
- next();
- },
+ var path = require('path'),
/**
- * Create the routes used to serve YUIDoc files dynamically
- * @method routes
- */
- routes: function() {
- var app = Server.app;
-
- app.get('/', Server.parse, function(req, res) {
- Server.home(req, res);
- });
- app.get('/api.js', function(req, res) {
- Server.builder.renderAPIMeta(function(js) {
- res.contentType('.js');
- res.send(js);
+ * Provides the `--server` server option for YUIDoc
+ * @class Server
+ * @module yuidoc
+ */
+ Server = {
+ /**
+ * Cache for external mixed in data.
+ * @property _externalData
+ * @private
+ * @type Object
+ */
+ _externalData: null,
+ /**
+ * Middleware to parse the API docs per request
+ * @method parse
+ * @param {Request} req Express request object
+ * @param {Response} res Express response object
+ * @param {Function} next Express next callback
+ */
+ parse: function (req, res, next) {
+ var json = (new Y.YUIDoc(Server.options)).run();
+ Server.options = Y.Project.mix(json, Server.options);
+ Server.builder = new Y.DocBuilder(Server.options, json);
+ if (Server._externalData) {
+ Server.options.externalData = Server._externalData;
+ Server.builder._mixExternal();
+ }
+
+ next();
+ },
+ /**
+ * Create the routes used to serve YUIDoc files dynamically
+ * @method routes
+ */
+ routes: function () {
+ var app = Server.app;
+
+ app.get('/', Server.parse, function (req, res) {
+ Server.home(req, res);
+ });
+ app.get('/api.js', function (req, res) {
+ Server.builder.renderAPIMeta(function (js) {
+ res.contentType('.js');
+ res.send(js);
+ });
});
- });
- app.get('/classes/:class.html', Server.parse, function(req, res, next) {
- Server.clazz(req, res, next);
- });
+ app.get('/classes/:class.html', Server.parse, function (req, res, next) {
+ Server.clazz(req, res, next);
+ });
- app.get('/modules/:module.html', Server.parse, function(req, res, next) {
- Server.module(req, res, next);
- });
+ app.get('/modules/:module.html', Server.parse, function (req, res, next) {
+ Server.module(req, res, next);
+ });
- app.get('/files/:file.html', Server.parse, function(req, res, next) {
- Server.files(req, res, next);
- });
-
- //These routes are special catch routes..
+ app.get('/files/:file.html', Server.parse, function (req, res, next) {
+ Server.files(req, res, next);
+ });
- app.get('//api.js', function(req, res) {
- res.redirect('/api.js');
- });
- app.get('//classes/:class.html', Server.parse, function(req, res, next) {
- Server.clazz(req, res, next);
- });
+ //These routes are special catch routes..
- app.get('//modules/:module.html', Server.parse, function(req, res, next) {
- Server.module(req, res, next);
- });
+ app.get('//api.js', function (req, res) {
+ res.redirect('/api.js');
+ });
+ app.get('//classes/:class.html', Server.parse, function (req, res, next) {
+ Server.clazz(req, res, next);
+ });
- app.get('//files/:file.html', Server.parse, function(req, res, next) {
- Server.files(req, res, next);
- });
+ app.get('//modules/:module.html', Server.parse, function (req, res, next) {
+ Server.module(req, res, next);
+ });
- app.get('*', function(req, res) {
- var type = req.url.split('/')[1],
- oType = type;
- var html = ['Item Not Found in internal meta-data
'];
+ app.get('//files/:file.html', Server.parse, function (req, res, next) {
+ Server.files(req, res, next);
+ });
- if (type === 'class') {
- type = 'classes';
- }
- if (Server.builder && Server.builder.data && Server.builder.data[type]) {
- if (Object.keys(Server.builder.data[type]).length) {
- html.push('But I know about these? Misname your module?
');
- html.push('');
- Object.keys(Server.builder.data[type]).forEach(function(item) {
- html.push('- ' + item + '
');
- });
- html.push('
');
- }
- }
+ app.get('*', function (req, res) {
+ var type = req.url.split('/')[1],
+ html = ['Item Not Found in internal meta-data
'];
+ if (type === 'class') {
+ type = 'classes';
+ }
+ if (Server.builder && Server.builder.data && Server.builder.data[type]) {
+ if (Object.keys(Server.builder.data[type]).length) {
+ html.push('But I know about these? Misname your module?
');
+ html.push('');
+ Object.keys(Server.builder.data[type]).forEach(function (item) {
+ html.push('- ' + item + '
');
+ });
+ html.push('
');
+ }
+ }
- res.send(html.join('\n'), 404);
- });
- },
- /**
- * `/files` endpoint
- * @method files
- * @param {Request} req Express request object
- * @param {Response} res Express response object
- */
- files: function(req, res, next) {
- var fileName = req.params.file;
- var data;
- Object.keys(Server.builder.data.files).forEach(function(file) {
- if (fileName === Server.builder.filterFileName(file)) {
- data = Server.builder.data.files[file];
- }
- });
-
- if (!data) {
- return next();
- }
+ res.send(html.join('\n'), 404);
+ });
- Y.log('Serving /files/' + data.name, 'info', 'server');
+ },
+ /**
+ * `/files` endpoint
+ * @method files
+ * @param {Request} req Express request object
+ * @param {Response} res Express response object
+ */
+ files: function (req, res, next) {
+ var fileName = req.params.file,
+ data;
+ Object.keys(Server.builder.data.files).forEach(function (file) {
+ if (fileName === Server.builder.filterFileName(file)) {
+ data = Server.builder.data.files[file];
+ }
+ });
+ if (!data) {
+ return next();
+ }
- Server.builder.renderFile(function(html) {
- res.send(html);
- }, data, (req.xhr ? 'xhr' : 'main'));
- },
- /**
- * `/classes` endpoint
- * @method clazz
- * @param {Request} req Express request object
- * @param {Response} res Express response object
- */
- clazz: function(req, res, next) {
- var className = req.params['class'];
- Y.log('Serving /classes/' + className + '.html', 'info', 'server');
- if (!Server.builder.data.classes[className]) {
- return next();
- }
- Server.builder.renderClass(function(html) {
- res.send(html);
- }, Server.builder.data.classes[className], (req.xhr ? 'xhr' : 'main'));
- },
- /**
- * `/modules` endpoint
- * @method modules
- * @param {Request} req Express request object
- * @param {Response} res Express response object
- */
- module: function(req, res, next) {
- var modName = req.params.module;
- Y.log('Serving /modules/' + modName + '.html', 'info', 'server');
- if (!Server.builder.data.modules[modName]) {
- return next();
- }
- Server.builder.renderModule(function(html) {
- res.send(html);
- }, Server.builder.data.modules[modName], (req.xhr ? 'xhr' : 'main'));
- },
- /**
- * `/` endpoint
- * @method home
- * @param {Request} req Express request object
- * @param {Response} res Express response object
- */
- home: function(req, res, next) {
- Y.log('Serving index.html', 'info', 'server');
- Server.builder.renderIndex(function(html) {
- res.send(html);
- });
- },
- /**
- * Creates the Express server and prep's YUI for serving
- * @method init
- */
- init: function() {
- var express = require('express'),
- path = require('path');
-
-
- Server.app = express();
- //console.log(Server.options);
- var stat = Server.options.themedir || path.join(__dirname, '../', 'themes', 'default');
- Server.app.use(express.static(stat));
- Server.routes();
- Server.app.listen(Server.options.port);
-
- Y.log('Starting server: http:/'+'/127.0.0.1:' + Server.options.port, 'info', 'server');
- },
- /**
- * Start the server with the supplied options.
- * @method start
- * @param {Object} options Server options
- */
- start: function(options) {
- options = Y.Project.init(options);
- Server.options = options;
-
- Server.options.cacheTemplates = false; //Don't cache the Handlebars templates
- Server.options.writeJSON = false; //Don't write the JSON file out
-
- Y.config.logExclude.yuidoc = true;
- Y.config.logExclude.docparser = true;
- Y.config.logExclude.builder = true;
-
- if (Server.options.external) {
- Y.log('Fetching external data, this may take a minute', 'warn', 'server');
- var json = (new Y.YUIDoc(Server.options)).run();
- Server.options = Y.Project.mix(json, Server.options);
- var builder = new Y.DocBuilder(Server.options, json);
- builder.mixExternal(function() {
- Y.log('External data fetched, launching server..', 'info', 'server');
- Server._externalData = builder.options.externalData;
- Server.init();
+ Y.log('Serving /files/' + data.name, 'info', 'server');
+
+
+ Server.builder.renderFile(function (html) {
+ res.send(html);
+ }, data, (req.xhr ? 'xhr' : 'main'));
+ },
+ /**
+ * `/classes` endpoint
+ * @method clazz
+ * @param {Request} req Express request object
+ * @param {Response} res Express response object
+ */
+ clazz: function (req, res, next) {
+ var className = req.params['class'];
+ Y.log('Serving /classes/' + className + '.html', 'info', 'server');
+ if (!Server.builder.data.classes[className]) {
+ return next();
+ }
+ Server.builder.renderClass(function (html) {
+ res.send(html);
+ }, Server.builder.data.classes[className], (req.xhr ? 'xhr' : 'main'));
+ },
+ /**
+ * `/modules` endpoint
+ * @method modules
+ * @param {Request} req Express request object
+ * @param {Response} res Express response object
+ */
+ module: function (req, res, next) {
+ var modName = req.params.module;
+ Y.log('Serving /modules/' + modName + '.html', 'info', 'server');
+ if (!Server.builder.data.modules[modName]) {
+ return next();
+ }
+ Server.builder.renderModule(function (html) {
+ res.send(html);
+ }, Server.builder.data.modules[modName], (req.xhr ? 'xhr' : 'main'));
+ },
+ /**
+ * `/` endpoint
+ * @method home
+ * @param {Request} req Express request object
+ * @param {Response} res Express response object
+ */
+ home: function (req, res, next) {
+ Y.log('Serving index.html', 'info', 'server');
+ Server.builder.renderIndex(function (html) {
+ res.send(html);
});
-
- } else {
- Server.init();
+ },
+ /**
+ * Creates the Express server and prep's YUI for serving
+ * @method init
+ */
+ init: function () {
+ var express = require('express'),
+ path = require('path'),
+ stat;
+
+ Server.app = express();
+ //console.log(Server.options);
+ stat = Server.options.themedir || path.join(__dirname, '../', 'themes', 'default');
+ Server.app.use(express.static(stat));
+ Server.routes();
+ Server.app.listen(Server.options.port);
+
+ Y.log('Starting server: http:/' + '/127.0.0.1:' + Server.options.port, 'info', 'server');
+ },
+ /**
+ * Start the server with the supplied options.
+ * @method start
+ * @param {Object} options Server options
+ */
+ start: function (options) {
+ options = Y.Project.init(options);
+ Server.options = options;
+
+ Server.options.cacheTemplates = false; //Don't cache the Handlebars templates
+ Server.options.writeJSON = false; //Don't write the JSON file out
+
+ Y.config.logExclude.yuidoc = true;
+ Y.config.logExclude.docparser = true;
+ Y.config.logExclude.builder = true;
+
+ if (Server.options.external) {
+ Y.log('Fetching external data, this may take a minute', 'warn', 'server');
+ var json, builder;
+
+ json = (new Y.YUIDoc(Server.options)).run();
+ Server.options = Y.Project.mix(json, Server.options);
+
+ builder = new Y.DocBuilder(Server.options, json);
+ builder.mixExternal(function () {
+ Y.log('External data fetched, launching server..', 'info', 'server');
+ Server._externalData = builder.options.externalData;
+ Server.init();
+ });
+
+ } else {
+ Server.init();
+ }
}
- }
- };
+ };
Y.Server = Server;
});
diff --git a/lib/utils.js b/lib/utils.js
index 251538e8..9976dded 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -3,30 +3,30 @@ Copyright (c) 2011, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://yuilibrary.com/license/
*/
+/*jshint onevar:false */
var path = require('path'),
- util = require('util'),
minimatch = require('minimatch'),
fs = require('graceful-fs');
/**
-* Utilities Class
-* @class Utils
-* @module yuidoc
-*/
+ * Utilities Class
+ * @class Utils
+ * @module yuidoc
+ */
+
+YUI.add('utils', function (Y) {
-YUI.add('utils', function(Y) {
-
Y.charset = 'utf8';
-var HTML_CHARS = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": ''',
- '/': '/',
- '`': '`'
-};
+ var HTML_CHARS = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '/': '/',
+ '`': '`'
+ };
/**
Escapes HTML characters in _html_.
@@ -35,7 +35,7 @@ var HTML_CHARS = {
@param {String} html String to escape.
@return {String} Escaped string.
**/
- Y.escapeHTML = function(html) {
+ Y.escapeHTML = function (html) {
return html.replace(/[&<>"'\/`]/g, function (match) {
return HTML_CHARS[match];
});
@@ -52,7 +52,7 @@ var HTML_CHARS = {
@return {String} Unindented text.
@private
**/
- Y.unindent = function(content) {
+ Y.unindent = function (content) {
var indent = content.match(/^(\s+)/);
if (indent) {
@@ -61,410 +61,416 @@ var HTML_CHARS = {
return content;
};
-
-/**
-Like `getPages()`, but returns only the files under the `layout/` subdirectory
-of the specified _dir_.
-
-@method getLayouts
-@param {String} dir Directory path.
-@return {Object} Mapping of layout names to layout content.
-**/
-function getLayouts(dir) {
- return getPages(path.join(dir, 'layouts'));
-}
-Y.getLayouts = getLayouts;
-/**
-Loads and returns the content of the specified page file.
-
-@method getPage
-@param {String} pagePath Path to a single `.handlebars` page.
-@return {String|null} Page content, or `null` if not found.
-**/
-function getPage(pagePath) {
- if (!Y.Files.isFile(pagePath)) { return null; }
- return fs.readFileSync(pagePath, Y.charset);
-}
-Y.getPage = getPage;
+ /**
+ Like `getPages()`, but returns only the files under the `layout/` subdirectory
+ of the specified _dir_.
-/**
-Loads pages (files with a `.handlebars` extension) in the specified directory and
-returns an object containing a mapping of page names (the part of the filename)
-preceding the `.handlebars` extension) to page content.
-
-@method getPages
-@param {String} dir Directory path.
-@return {Object} Mapping of page names to page content.
-**/
-var cache = {};
-function getPages(dir) {
- if (cache[dir]) {
- return cache[dir];
+ @method getLayouts
+ @param {String} dir Directory path.
+ @return {Object} Mapping of layout names to layout content.
+ **/
+ function getLayouts(dir) {
+ return getPages(path.join(dir, 'layouts'));
}
- var pages = {};
+ Y.getLayouts = getLayouts;
- if (!Y.Files.isDirectory(dir)) { return pages; }
-
- fs.readdirSync(dir).forEach(function (filename) {
- var filePath = path.join(dir, filename);
+ /**
+ Loads and returns the content of the specified page file.
- if (path.extname(filename) === '.handlebars' && Y.Files.isFile(filePath)) {
- pages[path.basename(filename, '.handlebars')] = fs.readFileSync(filePath, Y.charset);
+ @method getPage
+ @param {String} pagePath Path to a single `.handlebars` page.
+ @return {String|null} Page content, or `null` if not found.
+ **/
+ function getPage(pagePath) {
+ if (!Y.Files.isFile(pagePath)) {
+ return null;
}
- });
- cache[dir] = pages;
+ return fs.readFileSync(pagePath, Y.charset);
+ }
+ Y.getPage = getPage;
- return pages;
-}
-Y.getPages = getPages;
+ /**
+ Loads pages (files with a `.handlebars` extension) in the specified directory and
+ returns an object containing a mapping of page names (the part of the filename)
+ preceding the `.handlebars` extension) to page content.
-/**
-Like `getPages()`, but returns only the files under the `partial/` subdirectory
-of the specified _dir_.
+ @method getPages
+ @param {String} dir Directory path.
+ @return {Object} Mapping of page names to page content.
+ **/
+ var cache = {};
+ function getPages(dir) {
+ if (cache[dir]) {
+ return cache[dir];
+ }
+ var pages = {};
-@method getPartials
-@param {String} dir Directory path.
-@return {Object} Mapping of partial names to partial content.
-**/
-function getPartials(dir) {
- return getPages(path.join(dir, 'partials'));
-}
-Y.getPartials = getPartials;
+ if (!Y.Files.isDirectory(dir)) {
+ return pages;
+ }
+ fs.readdirSync(dir).forEach(function (filename) {
+ var filePath = path.join(dir, filename);
-/**
-Mix/merge/munge data into the template.
-@method prepare
-@param {String} inDir The starting directory
-@param {Object} options The `options` for the meta data.
-@param {callback} callback The callback to excecute when complete
-@param {Error} callback.err
-@param {Object} callback.options Merged options.
-**/
-function prepare(inDirs, options, callback) {
- var compiled = {},
- meta = {},
- type = 'project';
-
- if (options && options.skipLoad) {
- // Skip loading layouts, metadata, pages, and partials and assume that
- // the caller has provided them if they want them.
- options = Y.merge({
- layouts : {},
- meta : {},
- pages : {},
- partials : {},
- viewClass: Y.DocView
- }, options);
- } else {
-
- // Gather layouts, metadata, pages, and partials from the specified
- // input directory, then merge them into the provided options (if any).
- //
- // Gathered data will override provided data if there are conflicts, in
- // order to support a use case where global data are provided by the
- // caller and overridden by more specific component-level data gathered
- // from the input directory.
- //
- // The metadata inheritance chain looks like this:
- //
- // - override metadata specified via CLI (highest precedence)
- // - component metadata (if this is a component)
- // - project-level component default metadata (if specified and this is a component)
- // - theme-level component default metadata (if specified and this is a component)
- // - project metadata
- // - theme metadata (lowest precedence)
-
- try {
- if (inDirs[0] === inDirs[1]) {
- layouts = getLayouts(inDirs[0]);
- partials = getPartials(inDirs[0]);
- } else {
- layouts = Y.merge(getLayouts(inDirs[0]), getLayouts(inDirs[1]));
- partials = Y.merge(getPartials(inDirs[0]), getPartials(inDirs[1]));
+ if (path.extname(filename) === '.handlebars' && Y.Files.isFile(filePath)) {
+ pages[path.basename(filename, '.handlebars')] = fs.readFileSync(filePath, Y.charset);
}
- options = Y.merge(
- {viewClass: Y.DocView},
- options || {},
- {
- layouts : layouts,
- meta : options.meta,
- partials: partials
- }
- );
- } catch (ex) {
- return callback(ex);
- }
+ });
+ cache[dir] = pages;
+
+ return pages;
}
+ Y.getPages = getPages;
- // Mix in the override metadata, if any. It takes precedence over everything
- // else.
- Y.mix(options.meta, options.overrideMeta);
+ /**
+ Like `getPages()`, but returns only the files under the `partial/` subdirectory
+ of the specified _dir_.
- // Set a default asset path if one isn't specified in the metadata.
- if (!options.meta.projectAssets) {
- options.meta.projectAssets = options.component ? '../assets' : 'assets';
+ @method getPartials
+ @param {String} dir Directory path.
+ @return {Object} Mapping of partial names to partial content.
+ **/
+ function getPartials(dir) {
+ return getPages(path.join(dir, 'partials'));
}
+ Y.getPartials = getPartials;
- if (!options.meta.componentAssets && options.component) {
- options.meta.componentAssets = '../assets/' + options.meta.name;
- }
- if (typeof options.meta.layout === 'undefined') {
- options.meta.layout = options.layouts[type] ? type : 'main';
- }
-
- callback(null, options);
-}
+ /**
+ Mix/merge/munge data into the template.
+
+ @method prepare
+ @param {String} inDir The starting directory
+ @param {Object} options The `options` for the meta data.
+ @param {callback} callback The callback to excecute when complete
+ @param {Error} callback.err
+ @param {Object} callback.options Merged options.
+ **/
+ function prepare(inDirs, options, callback) {
+ var layouts,
+ partials,
+ type = 'project';
+
+ if (options && options.skipLoad) {
+ // Skip loading layouts, metadata, pages, and partials and assume that
+ // the caller has provided them if they want them.
+ options = Y.merge({
+ layouts: {},
+ meta: {},
+ pages: {},
+ partials: {},
+ viewClass: Y.DocView
+ }, options);
+ } else {
+ // Gather layouts, metadata, pages, and partials from the specified
+ // input directory, then merge them into the provided options (if any).
+ //
+ // Gathered data will override provided data if there are conflicts, in
+ // order to support a use case where global data are provided by the
+ // caller and overridden by more specific component-level data gathered
+ // from the input directory.
+ //
+ // The metadata inheritance chain looks like this:
+ //
+ // - override metadata specified via CLI (highest precedence)
+ // - component metadata (if this is a component)
+ // - project-level component default metadata (if specified and this is a component)
+ // - theme-level component default metadata (if specified and this is a component)
+ // - project metadata
+ // - theme metadata (lowest precedence)
+ try {
+ if (inDirs[0] === inDirs[1]) {
+ layouts = getLayouts(inDirs[0]);
+ partials = getPartials(inDirs[0]);
+ } else {
+ layouts = Y.merge(getLayouts(inDirs[0]), getLayouts(inDirs[1]));
+ partials = Y.merge(getPartials(inDirs[0]), getPartials(inDirs[1]));
+ }
+ options = Y.merge({
+ viewClass: Y.DocView
+ },
+ options || {}, {
+ layouts: layouts,
+ meta: options.meta,
+ partials: partials
+ }
+ );
+ } catch (ex) {
+ return callback(ex);
+ }
+ }
-Y.prepare = prepare;
+ // Mix in the override metadata, if any. It takes precedence over everything
+ // else.
+ Y.mix(options.meta, options.overrideMeta);
-/**
-* Walk the directory tree to locate the yuidoc.json file.
-* @method getProjectData
-* @param {Path} [dir=process.cwd()] The directory to start from
-*/
-var getProjectData = function(dir) {
- var dirs = [dir || process.cwd()];
- var projectData, packageData;
- var dirCount = 0;
- // keep looping until
- // * data is found
- // * there are no more dirs to process
- // * we abort due to failsafe
- while (dirs.length && !projectData) {
- if (dirCount++ > 5000) {
- Y.log('Scanned ' + dirCount + ' directories looking for a yuidoc.json file, something is probably wrong here..', 'error', 'yuidoc');
- process.exit(1);
+ // Set a default asset path if one isn't specified in the metadata.
+ if (!options.meta.projectAssets) {
+ options.meta.projectAssets = options.component ? '../assets' : 'assets';
+ }
+
+ if (!options.meta.componentAssets && options.component) {
+ options.meta.componentAssets = '../assets/' + options.meta.name;
}
- // accumulator for directories at this level
- var childDirs = [];
- // for each directory at the previous level
- dirs.forEach(function(dir) {
- // abort iterating if we have project data
- if (projectData) {
- return;
+
+ if (typeof options.meta.layout === 'undefined') {
+ options.meta.layout = options.layouts[type] ? type : 'main';
+ }
+
+ callback(null, options);
+ }
+
+ Y.prepare = prepare;
+
+ /**
+ * Walk the directory tree to locate the yuidoc.json file.
+ * @method getProjectData
+ * @param {Path} [dir=process.cwd()] The directory to start from
+ */
+ var getProjectData = function (dir) {
+ var dirs = [dir || process.cwd()];
+ var projectData, packageData;
+ var dirCount = 0;
+ // keep looping until
+ // * data is found
+ // * there are no more dirs to process
+ // * we abort due to failsafe
+ while (dirs.length && !projectData) {
+ /*jshint loopfunc:true */
+ if (dirCount++ > 5000) {
+ Y.log('Scanned ' + dirCount + ' directories looking for a yuidoc.json file, something is probably wrong here..', 'error', 'yuidoc');
+ process.exit(1);
}
- // squelch (but log) any complaints about this particular directory
- try {
- // for each item in this directory
- var names = fs.readdirSync(dir);
- names.forEach(function(name) {
- // abort iterating a folder if we have found both data
- if (projectData && packageData) {
- return;
- }
- // build a full path
- var p = path.join(dir, name);
- // acquire project data from this item if possible
- if (Y.Files.isFile(p)) {
- projectData = getFileData(p, name, 'yuidoc.json');
- // 'package.json' is used for auxilliary configuration
- // if it's found. Formerly, it was only found if it
- // came _before_'yuidoc.json' in the folder tree
- // (never in the same folder).
- // This code will find 'package.json' in the same
- // folder as 'yuidoc.json'.
- // If there is no 'yuidoc.json', former algorithm would
- // use the deepest 'package.json' it can find, this one
- // will use the first (most shallow) one.
- packageData = packageData || getFileData(p, name, 'package.json');
- }
- // if we are a folder, but not ., .., or node_modules,
- // then add to directory accumulator
- if (Y.Files.isDirectory(p)) {
- if (name.indexOf('.') === 0) {
+ // accumulator for directories at this level
+ var childDirs = [];
+ // for each directory at the previous level
+ dirs.forEach(function (dir) {
+ // abort iterating if we have project data
+ if (projectData) {
+ return;
+ }
+ // squelch (but log) any complaints about this particular directory
+ try {
+ // for each item in this directory
+ var names = fs.readdirSync(dir);
+ names.forEach(function (name) {
+ // abort iterating a folder if we have found both data
+ if (projectData && packageData) {
return;
}
- if (name === 'node_modules') {
- Y.log('Skipping node_modules directory while scanning for yuidoc.json', 'warn', 'yuidoc');
- return;
+ // build a full path
+ var p = path.join(dir, name);
+ // acquire project data from this item if possible
+ if (Y.Files.isFile(p)) {
+ projectData = getFileData(p, name, 'yuidoc.json');
+ // 'package.json' is used for auxilliary configuration
+ // if it's found. Formerly, it was only found if it
+ // came _before_'yuidoc.json' in the folder tree
+ // (never in the same folder).
+ // This code will find 'package.json' in the same
+ // folder as 'yuidoc.json'.
+ // If there is no 'yuidoc.json', former algorithm would
+ // use the deepest 'package.json' it can find, this one
+ // will use the first (most shallow) one.
+ packageData = packageData || getFileData(p, name, 'package.json');
}
- childDirs.push(p);
- }
- });
- } catch (dirPerm) {
- Y.log('Accessing dir (' + dir + ') threw an error', 'warn', 'yuidoc');
+ // if we are a folder, but not ., .., or node_modules,
+ // then add to directory accumulator
+ if (Y.Files.isDirectory(p)) {
+ if (name.indexOf('.') === 0) {
+ return;
+ }
+ if (name === 'node_modules') {
+ Y.log('Skipping node_modules directory while scanning for yuidoc.json', 'warn', 'yuidoc');
+ return;
+ }
+ childDirs.push(p);
+ }
+ });
+ } catch (dirPerm) {
+ Y.log('Accessing dir (' + dir + ') threw an error', 'warn', 'yuidoc');
+ }
+ });
+ // iterate over new set of folders
+ dirs = childDirs;
+ }
+ if ((packageData && projectData) || (packageData && packageData.yuidoc)) {
+ projectData = mergeData(packageData, projectData);
+ }
+ return projectData;
+ };
+
+ var getFileData = function (p, name, file) {
+ if (name === file) {
+ Y.log('Loading ' + name + ' data from: ' + p, 'info', 'yuidoc');
+ try {
+ return Y.Files.getJSON(p);
+ } catch (e) {
+ var err = 'Failed to parse ' + name + ' file, please make sure it is valid JSON';
+ Y.log(err, 'error', 'yuidoc');
+ throw (e + '');
}
- });
- // iterate over new set of folders
- dirs = childDirs;
- }
- if ((packageData && projectData) || (packageData && packageData.yuidoc)) {
- projectData = mergeData(packageData, projectData);
- }
- return projectData;
-};
-
-var getFileData = function(p, name, file) {
- if (name === file) {
- Y.log('Loading ' + name + ' data from: ' + p, 'info', 'yuidoc');
- try {
- return Y.Files.getJSON(p);
- } catch (e) {
- var err = 'Failed to parse ' + name + ' file, please make sure it is valid JSON';
- Y.log(err, 'error', 'yuidoc');
- throw(e+'');
}
- }
-};
+ };
-var mergeData = function(pack, project) {
- project = project || {};
+ var mergeData = function (pack, project) {
+ project = project || {};
- if (pack.yuidoc) {
- Object.keys(pack.yuidoc).forEach(function(key) {
- if (!project[key]) {
- project[key] = pack.yuidoc[key];
+ if (pack.yuidoc) {
+ Object.keys(pack.yuidoc).forEach(function (key) {
+ if (!project[key]) {
+ project[key] = pack.yuidoc[key];
+ }
+ });
+ }
+
+ ['name', 'description', 'version', 'url'].forEach(function (key) {
+ if (pack[key] && !project[key]) {
+ project[key] = pack[key];
}
});
- }
- ['name', 'description', 'version', 'url'].forEach(function(key) {
- if (pack[key] && !project[key]) {
- project[key] = pack[key];
- }
- });
+ return project;
+ };
- return project;
-};
+ Y.getProjectData = getProjectData;
-Y.getProjectData = getProjectData;
+ /**
+ * Walks the tree from this dir and returns all the subdirs
+ * @method getDirs
+ * @param {String} dir The dir to begin at
+ * @return {Array} The array of directories..
+ */
+ var getDirs = function (dir) {
+ var dirs = fs.readdirSync(dir),
+ paths = [];
+
+ dirs.forEach(function (d) {
+ var _dir = path.join(dir, d),
+ stat = fs.lstatSync(_dir);
+
+ if (stat.isDirectory()) {
+ if (_dir.indexOf('.') !== 0) {
+ paths = [].concat(paths, _dir, getDirs(_dir));
+ }
+ }
+ });
-/**
-* Walks the tree from this dir and returns all the subdirs
-* @method getDirs
-* @param {String} dir The dir to begin at
-* @return {Array} The array of directories..
-*/
+ return paths;
+ };
-var getDirs = function(dir) {
- var dirs = fs.readdirSync(dir),
- paths = [];
+ Y.getDirs = getDirs;
- dirs.forEach(function(d) {
- var _dir = path.join(dir, d),
- stat = fs.lstatSync(_dir);
+ /**
+ * Make sure all the paths passed are directories and that they are not in the ignore list.
+ * @method validatePaths
+ * @param {Array} paths The array of paths to validate
+ * @param {String} [ignore=false] A string to call `.indexOf` on a path to determine if it should be ignored
+ */
+ var validatePaths = function (paths, ignore) {
+ var newpaths = [];
+ //Shortcut the *, . & ./ shortcuts that shall globbing fixes for us
+ if (paths === '*' || paths === '.' || paths === './') {
+ paths = [process.cwd()];
+ }
- if (stat.isDirectory()) {
- if (_dir.indexOf('.') !== 0) {
- paths = [].concat(paths, _dir, getDirs(_dir));
- }
+ // Ensure that we always have an array of some kind.
+ paths = paths || [];
+ if (!Y.Lang.isArray(paths)) {
+ paths = [paths];
}
- });
+ paths.forEach(function (path) {
+ var glob = path || '';
- return paths;
-};
+ if (process.platform === 'win32') {
+ glob = path.replace(/\//g, '\\\\');
+ }
-Y.getDirs = getDirs;
+ var glob_paths = getDirs('.'),
+ is_globbed = false;
-/**
-* Make sure all the paths passed are directories and that they are not in the ignore list.
-* @method validatePaths
-* @param {Array} paths The array of paths to validate
-* @param {String} [ignore=false] A string to call `.indexOf` on a path to determine if it should be ignored
-*/
+ glob_paths.forEach(function (dir) {
+ //Don't scan things in node_modules
+ if (dir.indexOf('node_modules') > -1) {
+ return;
+ }
+ if (minimatch(dir, glob, {
+ period: true
+ })) {
+ newpaths.push(dir);
+ is_globbed = true;
+ }
+ });
-var validatePaths = function(paths, ignore) {
- var newpaths = [];
- //Shortcut the *, . & ./ shortcuts that shall globbing fixes for us
- if (paths === '*' || paths === '.' || paths === './') {
- paths = [process.cwd()];
- }
+ if (!is_globbed && (Y.Files.isDirectory(glob))) {
+ //If minimatch fails, check to see if it's a relative directory
+ // if it is, add it directly
+ newpaths.push(glob);
+ }
+ });
- // Ensure that we always have an array of some kind.
- paths = paths || [];
- if (!Y.Lang.isArray(paths)) {
- paths = [ paths ];
- }
- paths.forEach(function(path) {
- var glob = path || '';
+ paths = newpaths;
+ paths.forEach(function (p) {
+ try {
+ if (!Y.Files.isDirectory(p)) {
+ throw ('Path not a directory: ' + p);
+ }
+ } catch (e) {}
+ });
- if (process.platform === 'win32') {
- glob = path.replace(/\//g, '\\\\');
+ if (!paths || !paths.forEach) {
+ throw ('Paths should be an array of paths');
}
- var glob_paths = getDirs('.'), is_globbed = false;
- glob_paths.forEach(function(dir) {
- //Don't scan things in node_modules
- if (dir.indexOf('node_modules') > -1) {
- return;
+ if (ignore) {
+ if (!(ignore instanceof Array)) {
+ ignore = [ignore];
}
- if (minimatch(dir, glob, { period: true })) {
- newpaths.push(dir);
- is_globbed = true;
- }
- });
- if (!is_globbed && (Y.Files.isDirectory(glob))) {
- //If minimatch fails, check to see if it's a relative directory
- // if it is, add it directly
- newpaths.push(glob);
- }
- });
-
- paths = newpaths;
- paths.forEach(function(p) {
- try {
- if (!Y.Files.isDirectory(p)) {
- throw('Path not a directory: ' + p);
- }
- } catch (e) {}
- });
- if (!paths || !paths.forEach) {
- throw('Paths should be an array of paths');
- }
- if (ignore) {
- if (!(ignore instanceof Array)) {
- ignore = [ignore];
- }
- var p = [],
- shouldIgnore = false;
-
- paths.forEach(function(v) {
- shouldIgnore = false;
- ignore.forEach(function(i) {
- if (!shouldIgnore && v.indexOf(i) !== -1) {
- shouldIgnore = true;
+ var p = [],
+ shouldIgnore = false;
+
+ paths.forEach(function (v) {
+ shouldIgnore = false;
+ ignore.forEach(function (i) {
+ if (!shouldIgnore && v.indexOf(i) !== -1) {
+ shouldIgnore = true;
+ }
+ });
+ if (!shouldIgnore) {
+ p.push(v);
}
});
- if (!shouldIgnore) {
- p.push(v);
- }
- });
- paths = p;
- }
- paths = paths.sort();
- return paths;
-};
-
-Y.validatePaths = validatePaths;
+ paths = p;
+ }
+ paths = paths.sort();
+ return paths;
+ };
+ Y.validatePaths = validatePaths;
-/**
-* Takes a type string and converts it to a "First letter upper cased" type. e.g. `(string -> String, object -> Object)`
-* @method fixType
-* @param {String} t The type string to convert
-* @return {String} The fixed string
-*/
-var fixType = function(t) {
-
- if (t && t.indexOf('.') === -1) {
- t = t.replace(/{/g, '').replace(/}/g, '');
- var firstChar = t.charAt(0),
- upperFirstChar = firstChar.toUpperCase();
-
- if (firstChar !== upperFirstChar) {
- return upperFirstChar + t.substring(1);
+ /**
+ * Takes a type string and converts it to a "First letter upper cased" type. e.g. `(string -> String, object -> Object)`
+ * @method fixType
+ * @param {String} t The type string to convert
+ * @return {String} The fixed string
+ */
+ var fixType = function (t) {
+ if (t && t.indexOf('.') === -1) {
+ t = t.replace(/{/g, '').replace(/}/g, '');
+ var firstChar = t.charAt(0),
+ upperFirstChar = firstChar.toUpperCase();
+
+ if (firstChar !== upperFirstChar) {
+ return upperFirstChar + t.substring(1);
+ }
}
- }
- return t;
-};
+ return t;
+ };
-Y.Lang.fixType = fixType;
+ Y.Lang.fixType = fixType;
});
-
diff --git a/lib/yuidoc.js b/lib/yuidoc.js
index ff7827c1..3d354047 100755
--- a/lib/yuidoc.js
+++ b/lib/yuidoc.js
@@ -3,9 +3,9 @@ Copyright (c) 2011, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://yuilibrary.com/license/
*/
-var fs = require("fs"),
+var fs = require('graceful-fs'),
rimraf = require('rimraf'),
- path = require("path");
+ path = require('path');
/**
This is the __module__ description for the `YUIDoc` module.
@@ -23,7 +23,7 @@ This is the __module__ description for the `YUIDoc` module.
*/
-YUI.add('yuidoc', function(Y) {
+YUI.add('yuidoc', function (Y) {
/**
@@ -33,17 +33,16 @@ YUI.add('yuidoc', function(Y) {
* @final
* @for YUIDoc
*/
-
var OPTIONS = {
quiet: false,
writeJSON: true,
- outdir: path.join(process.cwd(), 'out'),
+ outdir: path.join(process.cwd(), 'out'),
extension: '.js',
exclude: '.DS_Store,.svn,CVS,.git,build_rollup_tmp,build_tmp,node_modules',
norecurse: false,
version: '0.1.0',
paths: [],
- themedir: path.join(__dirname, 'themes', 'default'),
+ themedir: path.join(__dirname, 'themes', 'default'),
syntaxtype: 'js'
};
@@ -63,7 +62,7 @@ YUI.add('yuidoc', function(Y) {
* @constructor
* @param config The config object
*/
- Y.YUIDoc = function(config) {
+ Y.YUIDoc = function (config) {
/**
* Holds the number of files that we are processing.
* @property filecount
@@ -115,54 +114,61 @@ YUI.add('yuidoc', function(Y) {
* @method _setDefaultExcludes
* @private
*/
- _setDefaultExcludes: function() {
+ _setDefaultExcludes: function () {
//These should always be excluded
var excludes = '.DS_Store,.svn,CVS,.git,build_rollup_tmp,build_tmp,node_modules'.split(','),
self = this;
- excludes.forEach(function(item) {
+ excludes.forEach(function (item) {
self.options.excludes[item] = true;
});
},
+
/**
* Does post process on self.options.
* @method _processConfig
* @private
*/
- _processConfig: function() {
+ _processConfig: function () {
this.options.extensions = Y.Array.hash(this.options.extension.split(','));
this.options.excludes = Y.Array.hash(this.options.exclude.split(','));
this._setDefaultExcludes();
},
+
/**
* Walks the paths and parses the directory contents
* @method walk
* @private
*/
- walk: function() {
- Y.each(this.options.paths, function(dir) {
+ walk: function () {
+ Y.each(this.options.paths, function (dir) {
this.parsedir(dir);
}, this);
},
+
/**
* Walks the passed directory and grabs all the files recursively.
* @method parsedir
* @param {String} dir The directory to parse the contents of.
* @private
*/
- parsedir: function(dir) {
+ parsedir: function (dir) {
if (!Y.Files.isDirectory(dir)) {
- throw('Can not find directory: ' + dir);
+ throw ('Can not find directory: ' + dir);
}
- var allfiles = fs.readdirSync(dir), stats,
- files = [], fullpath, self = this;
-
+
+ var allfiles = fs.readdirSync(dir),
+ stats,
+ files = [],
+ fullpath, self = this;
+
if (dir in self.options.excludes) {
return;
}
+
allfiles = allfiles.sort();
- Y.each(allfiles, function(filename) {
+ Y.each(allfiles, function (filename) {
if (!(filename in self.options.excludes)) {
fullpath = path.join(dir, filename);
@@ -175,10 +181,12 @@ YUI.add('yuidoc', function(Y) {
}
}
});
+
if (!(dir in self.options.excludes)) {
this.parsefiles(dir, files);
}
},
+
/**
* Gathers all the file data and populates the filemap and dirmap hashes.
* @method parsefiles
@@ -186,11 +194,14 @@ YUI.add('yuidoc', function(Y) {
* @param {Array} files List of files to parse.
* @private
*/
- parsefiles: function(dir, files) {
+ parsefiles: function (dir, files) {
var self = this;
- files = files.sort();
- Y.each(files, function(filename) {
- var ext = path.extname(filename), text, fullpath;
+ files = files.sort();
+
+ Y.each(files, function (filename) {
+ var ext = path.extname(filename),
+ text,
+ fullpath;
if (ext) {
if (ext in self.options.extensions) {
@@ -211,9 +222,12 @@ YUI.add('yuidoc', function(Y) {
}
});
},
- getSelleck: function(fullpath) {
+
+ getSelleck: function (fullpath) {
var self = this,
- base, comp, json;
+ base,
+ comp,
+ json;
if (self.options.selleck) {
base = path.dirname(fullpath);
@@ -221,7 +235,7 @@ YUI.add('yuidoc', function(Y) {
//Y.log('Checking for Selleck data: ' + comp, 'info', 'yuidoc');
if (Y.Files.exists(comp)) {
try {
- var json = JSON.parse(fs.readFileSync(comp, 'utf8'));
+ json = JSON.parse(fs.readFileSync(comp, 'utf8'));
delete json.examples; //Remove the selleck example data, we only want the comp info
self.selleck[fullpath] = json;
} catch (e) {
@@ -230,6 +244,7 @@ YUI.add('yuidoc', function(Y) {
}
}
},
+
/**
* Writes the parser JSON data to disk.
* @method writeJSON
@@ -237,21 +252,23 @@ YUI.add('yuidoc', function(Y) {
* @private
* @return {Object} The JSON data returned from the DocParser
*/
- writeJSON: function(parser) {
+ writeJSON: function (parser) {
var self = this,
- data;
+ data,
+ file,
+ out;
data = parser.data;
data.warnings = parser.warnings;
if (self.selleck && self.options.selleck && data.files && data.modules) {
- Object.keys(self.selleck).forEach(function(file) {
- Object.keys(data.files).forEach(function(f) {
+ Object.keys(self.selleck).forEach(function (file) {
+ Object.keys(data.files).forEach(function (f) {
if (file === f) {
var mods = data.files[f].modules;
if (mods) {
- Object.keys(mods).forEach(function(mod) {
+ Object.keys(mods).forEach(function (mod) {
if (data.modules[mod]) {
if (!data.modules[mod].extra) {
data.modules[mod].extra = {};
@@ -271,11 +288,13 @@ YUI.add('yuidoc', function(Y) {
if (self.options.writeJSON) {
// Y.log(Y.JSON.stringify(parser.data, null, 4));
- var file = path.join(self.options.outdir, 'data.json'), out;
+ file = path.join(self.options.outdir, 'data.json');
+
if (Y.Files.exists(self.options.outdir) && !self.options.nodeleteout) {
Y.log('Found out dir, deleting: ' + self.options.outdir, 'warn', 'yuidoc');
rimraf.sync(self.options.outdir);
}
+
if (!Y.Files.exists(self.options.outdir)) {
Y.log('Making out dir: ' + self.options.outdir, 'info', 'yuidoc');
try {
@@ -284,9 +303,11 @@ YUI.add('yuidoc', function(Y) {
Y.log('Outdir creation failed', 'warn', 'yuidoc');
}
}
-
+
out = fs.createWriteStream(file, {
- flags: "w", encoding: Y.charset, mode: 0644
+ flags: "w",
+ encoding: Y.charset,
+ mode: 0644
});
out.write(JSON.stringify(data, null, 4));
out.end();
@@ -294,26 +315,28 @@ YUI.add('yuidoc', function(Y) {
return data;
},
- lint: function(warnings) {
+
+ lint: function (warnings) {
var code = 0,
count = 0;
if (warnings && warnings.length) {
code = 1;
console.log('YUIDoc found', warnings.length, 'lint errors in your docs');
- warnings.forEach(function(item) {
+ warnings.forEach(function (item) {
count++;
console.log('#' + count, item.message, item.line + '\n');
});
process.exit(code);
}
},
+
/**
* Process the config, walk the file tree and write out the JSON data.
* @method run
* @return {Object} The JSON data returned from the DocParser
*/
- run: function() {
+ run: function () {
/**
* Timestamp holder so we know when YUIDoc started the parse process.
* @property starttime
@@ -322,15 +345,13 @@ YUI.add('yuidoc', function(Y) {
Y.log('YUIDoc Starting from: ' + this.options.paths.join(','), 'info', 'yuidoc');
this.starttime = new Date().getTime();
- var self = this;
-
this._processConfig();
this.walk();
var json = this.writeJSON(new Y.DocParser({
- syntaxtype: self.options.syntaxtype,
- filemap: self.filemap,
- dirmap: self.dirmap
+ syntaxtype: this.options.syntaxtype,
+ filemap: this.filemap,
+ dirmap: this.dirmap
}).parse());
if (this.options.lint) {
diff --git a/package.json b/package.json
index fcdb2e4e..e0faf059 100644
--- a/package.json
+++ b/package.json
@@ -41,12 +41,14 @@
"express": "~3.1.2"
},
"devDependencies": {
+ "jshint": "2.4.x",
"ytestrunner": "~0.3.3",
"yuitest": ">=0.7.3",
"selleck": "~0.1",
"istanbul": "0.2.x"
},
"scripts": {
+ "pretest": "jshint ./lib/*.js ./tests/*.js",
"test": "istanbul cover --print=both --yui ytestrunner -- --include ./tests/options.js --include ./tests/builder.js --include ./tests/parser.js --include ./tests/parser_coffee.js --include ./tests/files.js"
},
"preferGlobal": "true",
@@ -60,6 +62,27 @@
"type":"git",
"url":"http://github.com/yui/yuidoc.git"
},
+ "jshintConfig": {
+ "bitwise" : true,
+ "browser" : true,
+ "curly" : true,
+ "eqeqeq" : true,
+ "forin" : true,
+ "immed" : true,
+ "latedef" : "nofunc",
+ "laxbreak" : true,
+ "maxerr" : 500,
+ "maxlen" : 150,
+ "newcap" : true,
+ "noarg" : true,
+ "node" : true,
+ "noempty" : true,
+ "onevar" : true,
+ "trailing" : true,
+ "undef" : true,
+ "unused" : "vars",
+ "yui" : true
+ },
"yuidoc": {
"name": "YUIDoc",
"logo": "http://yuilibrary.com/img/yui-logo.png",
diff --git a/tests/builder.js b/tests/builder.js
index 628699dd..1de640e3 100644
--- a/tests/builder.js
+++ b/tests/builder.js
@@ -1,6 +1,6 @@
+/*global Y:true */
var YUITest = require('yuitest'),
Assert = YUITest.Assert,
- ArrayAssert = YUITest.ArrayAssert,
path = require('path'),
fs = require('fs'),
Y = require(path.join(__dirname, '../', 'lib', 'index'));
@@ -10,11 +10,11 @@ process.chdir(__dirname);
var suite = new YUITest.TestSuite({
name: 'Builder Test Suite',
- findByName: function(name, cl) {
+ findByName: function (name, cl) {
var items = this.data.classitems,
ret;
- items.forEach(function(i) {
+ items.forEach(function (i) {
if (i.name === name && i.class === cl) {
ret = i;
}
@@ -22,11 +22,12 @@ var suite = new YUITest.TestSuite({
return ret;
},
- setUp: function() {
- var test = this;
- var options = {
+ setUp: function () {
+ var options, json, builder;
+
+ options = {
quiet: true,
- paths: [ 'input/' ],
+ paths: ['input/'],
outdir: './out',
helpers: [
path.join(__dirname, 'lib/davglass.js')
@@ -35,13 +36,13 @@ var suite = new YUITest.TestSuite({
langPrefix: "language-"
}
};
- var json = (new Y.YUIDoc(options)).run();
+ json = (new Y.YUIDoc(options)).run();
this.project = json.project;
this.data = json;
-
- var builder = new Y.DocBuilder(options, json);
- builder.compile(function() {
+
+ builder = new Y.DocBuilder(options, json);
+ builder.compile(function () {
suite._setupComplete = true;
});
this.builder = builder;
@@ -53,7 +54,7 @@ var exists = fs.existsSync || path.existsSync;
suite.add(new YUITest.TestCase({
name: 'Builder setup',
- 'test: prep': function() {
+ 'test: prep': function () {
this.project = suite.project;
this.data = suite.data;
/*
@@ -62,69 +63,68 @@ suite.add(new YUITest.TestCase({
so I have to check it in the first test to make sure my
async task in the setup is complete before I can test against it.
*/
- var test = this;
- var timer = setInterval(function() {
- if (suite._setupComplete) {
- clearInterval(timer);
- test.resume(function() {
- Assert.isTrue(suite._setupComplete);
- });
- }
- },10);
+ var test = this,
+ timer = setInterval(function () {
+ if (suite._setupComplete) {
+ clearInterval(timer);
+ test.resume(function () {
+ Assert.isTrue(suite._setupComplete);
+ });
+ }
+ }, 10);
this.wait();
},
- 'test: Directories': function() {
+ 'test: Directories': function () {
var dirs = ['assets', 'classes', 'files', 'modules'];
- dirs.forEach(function(d) {
+ dirs.forEach(function (d) {
var p = path.join(__dirname, 'out', d);
Assert.isTrue(exists(p), 'Failed to find: ' + p);
});
},
- 'test: Assets Directories': function() {
+ 'test: Assets Directories': function () {
var dirs = ['css', 'js', 'img', 'vendor', 'index.html'];
- dirs.forEach(function(d) {
+ dirs.forEach(function (d) {
var p = path.join(__dirname, 'out', 'assets', d);
Assert.isTrue(exists(p), 'Failed to find: ' + p);
});
},
- 'test: index.html': function() {
+ 'test: index.html': function () {
var p = path.join(__dirname, 'out', 'index.html');
- Assert.isTrue(exists(p), 'Failed to find: ' + p)
+ Assert.isTrue(exists(p), 'Failed to find: ' + p);
},
- 'test: data.json': function() {
+ 'test: data.json': function () {
var p = path.join(__dirname, 'out', 'data.json');
- Assert.isTrue(exists(p), 'Failed to find: ' + p)
+ Assert.isTrue(exists(p), 'Failed to find: ' + p);
},
- 'test: api.js': function() {
+ 'test: api.js': function () {
var p = path.join(__dirname, 'out', 'api.js');
- Assert.isTrue(exists(p), 'Failed to find: ' + p)
+ Assert.isTrue(exists(p), 'Failed to find: ' + p);
},
- 'test: classes/JSON.html': function() {
+ 'test: classes/JSON.html': function () {
var p = path.join(__dirname, 'out', 'classes', 'JSON.html');
- Assert.isTrue(exists(p), 'Failed to find: ' + p)
+ Assert.isTrue(exists(p), 'Failed to find: ' + p);
},
- 'test: files name filter': function() {
+ 'test: files name filter': function () {
var dir = path.join(__dirname, 'out', 'files');
- var files = fs.readdirSync(dir);
- files.forEach(function(file) {
- Assert.isTrue(((file.indexOf('input_') ===0) || file.indexOf('index.html') === 0), 'Filed to parse: ' + file);
+ fs.readdirSync(dir).forEach(function (file) {
+ Assert.isTrue(((file.indexOf('input_') === 0) || file.indexOf('index.html') === 0), 'Filed to parse: ' + file);
});
},
- 'test: module files': function() {
+ 'test: module files': function () {
var mods = this.data.modules;
- Object.keys(mods).forEach(function(name) {
- var m = mods[name];
- var p = path.join(__dirname, 'out', 'modules', m.name + '.html');
+ Object.keys(mods).forEach(function (name) {
+ var m = mods[name],
+ p = path.join(__dirname, 'out', 'modules', m.name + '.html');
Assert.isTrue(exists(p), 'Failed to render: ' + m.name + '.html');
});
},
- 'test: class files': function() {
+ 'test: class files': function () {
var mods = this.data.classes;
- Object.keys(mods).forEach(function(name) {
- var m = mods[name];
- var p = path.join(__dirname, 'out', 'classes', m.name + '.html');
+ Object.keys(mods).forEach(function (name) {
+ var m = mods[name],
+ p = path.join(__dirname, 'out', 'classes', m.name + '.html');
Assert.isTrue(exists(p), 'Failed to render: ' + m.name + '.html');
});
}
@@ -132,12 +132,12 @@ suite.add(new YUITest.TestCase({
suite.add(new YUITest.TestCase({
name: 'Builder Augmentation Tests',
- 'test: inherited methods': function() {
+ 'test: inherited methods': function () {
var item = suite.data.classes['mywidget.SubWidget'];
Assert.isObject(item, 'Failed to parse class');
- suite.builder.renderClass(function(html, view, opts) {
+ suite.builder.renderClass(function (html, view, opts) {
var method;
- opts.meta.methods.forEach(function(i) {
+ opts.meta.methods.forEach(function (i) {
if (i.name === 'myMethod' && i.class === 'mywidget.SubWidget') {
method = i;
}
@@ -147,12 +147,12 @@ suite.add(new YUITest.TestCase({
Assert.isObject(method.overwritten_from, 'Failed to find overwritten data');
}, item);
},
- 'test: helper methods': function() {
+ 'test: helper methods': function () {
var item = suite.data.classes['mywidget.SuperWidget'];
Assert.isObject(item, 'Failed to parse class');
- suite.builder.renderClass(function(html, view, opts) {
+ suite.builder.renderClass(function (html, view, opts) {
var method;
- opts.meta.methods.forEach(function(i) {
+ opts.meta.methods.forEach(function (i) {
if (i.name === 'getTargets2' && i.class === 'mywidget.SuperWidget') {
method = i;
}
@@ -163,12 +163,12 @@ suite.add(new YUITest.TestCase({
}, item);
},
- 'test: markdown options': function() {
+ 'test: markdown options': function () {
var item = suite.data.classes['mywidget.SuperWidget'];
Assert.isObject(item, 'Failed to parse class');
- suite.builder.renderClass(function(html, view, opts) {
+ suite.builder.renderClass(function (html, view, opts) {
var method;
- opts.meta.methods.forEach(function(i) {
+ opts.meta.methods.forEach(function (i) {
if (i.name === 'getTargets3' && i.class === 'mywidget.SuperWidget') {
method = i;
}
diff --git a/tests/files.js b/tests/files.js
index e243ff1d..df132eae 100644
--- a/tests/files.js
+++ b/tests/files.js
@@ -1,3 +1,4 @@
+/*global Y:true */
var YUITest = require('yuitest'),
Assert = YUITest.Assert,
path = require('path'),
diff --git a/tests/options.js b/tests/options.js
index 81cb8d38..4190cce2 100644
--- a/tests/options.js
+++ b/tests/options.js
@@ -1,8 +1,7 @@
+/*global Y:true */
var YUITest = require('yuitest'),
Assert = YUITest.Assert,
- ArrayAssert = YUITest.ArrayAssert,
path = require('path'),
- fs = require('fs'),
Y = require(path.join(__dirname, '../', 'lib', 'index'));
//Move to the test dir before running the tests.
@@ -12,7 +11,7 @@ var suite = new YUITest.TestSuite('Options Test Suite');
suite.add(new YUITest.TestCase({
name: "Server Options",
- 'test: server': function() {
+ 'test: server': function () {
var options = Y.Options([
'--server'
]);
@@ -20,7 +19,7 @@ suite.add(new YUITest.TestCase({
Assert.isTrue(options.server, 'Failed to set server option');
Assert.areSame(3000, options.port, 'Failed to set default port');
},
- 'test: server with port': function() {
+ 'test: server with port': function () {
var options = Y.Options([
'--server',
'5000'
@@ -29,7 +28,7 @@ suite.add(new YUITest.TestCase({
Assert.isTrue(options.server, 'Failed to set server option');
Assert.areSame(5000, options.port, 'Failed to set port');
},
- 'test: server with default port and following argument': function() {
+ 'test: server with default port and following argument': function () {
var options = Y.Options([
'--server',
'./foo'
@@ -40,7 +39,7 @@ suite.add(new YUITest.TestCase({
Assert.isArray(options.paths, 'Failed to set path');
Assert.areSame('./foo', options.paths[0], 'Failed to set path after empty --server');
},
- 'test: tab-to-space': function() {
+ 'test: tab-to-space': function () {
var options, value;
// Test that --tab-to-space gives the correct number.
@@ -95,238 +94,217 @@ suite.add(new YUITest.TestCase({
suite.add(new YUITest.TestCase({
name: "Various Options",
- "test: long quiet option": function() {
+ "test: long quiet option": function () {
var options = Y.Options([
'--quiet'
]);
-
Assert.isTrue(options.quiet, 'Failed to set long quiet');
},
- "test: short quiet option": function() {
+ "test: short quiet option": function () {
var options = Y.Options([
'-q'
]);
-
Assert.isTrue(options.quiet, 'Failed to set short quiet');
},
- "test: short config": function() {
+ "test: short config": function () {
var options = Y.Options([
'-c',
'./foo.json'
]);
-
Assert.areSame('./foo.json', options.configfile, 'Failed to set config');
},
- 'test: --config': function() {
+ 'test: --config': function () {
var options = Y.Options([
'--config',
'./foo.json'
]);
-
Assert.areSame('./foo.json', options.configfile, 'Failed to set config');
},
- 'test: --configfile': function() {
+ 'test: --configfile': function () {
var options = Y.Options([
'--configfile',
'./foo.json'
]);
-
Assert.areSame('./foo.json', options.configfile, 'Failed to set config');
},
- 'test: -e': function() {
+ 'test: -e': function () {
var options = Y.Options([
'-e',
'.foo'
]);
-
Assert.areSame('.foo', options.extension, 'Failed to set extension');
},
- 'test: --extension': function() {
+ 'test: --extension': function () {
var options = Y.Options([
'--extension',
'.foo'
]);
-
Assert.areSame('.foo', options.extension, 'Failed to set extension');
},
- 'test: -x': function() {
+ 'test: -x': function () {
var options = Y.Options([
'-x',
'foo,bar,baz'
]);
-
Assert.areSame('foo,bar,baz', options.exclude, 'Failed to set exclude');
},
- 'test: --exclude': function() {
+ 'test: --exclude': function () {
var options = Y.Options([
'--exclude',
'foo,bar,baz'
]);
-
Assert.areSame('foo,bar,baz', options.exclude, 'Failed to set exclude');
},
- 'test: --project-version': function() {
+ 'test: --project-version': function () {
var options = Y.Options([
'--project-version',
'6.6.6'
]);
-
Assert.areSame('6.6.6', options.version, 'Failed to set version');
},
- 'test: --no-color': function() {
+ 'test: --no-color': function () {
var options = Y.Options([
'--no-color',
]);
-
Assert.isTrue(options.nocolor, 'Failed to set nocolor');
Assert.isFalse(Y.config.useColor, 'Failed to set Y.config.useColor');
},
- 'test: -N': function() {
+ 'test: -N': function () {
var options = Y.Options([
'-N',
]);
-
Assert.isTrue(options.nocolor, 'Failed to set nocolor');
Assert.isFalse(Y.config.useColor, 'Failed to set Y.config.useColor');
},
- 'test: --no-code': function() {
+ 'test: --no-code': function () {
var options = Y.Options([
'--no-code',
]);
-
Assert.isTrue(options.nocode, 'Failed to set nocode');
},
- 'test: -C': function() {
+ 'test: -C': function () {
var options = Y.Options([
'-C',
]);
-
Assert.isTrue(options.nocode, 'Failed to set nocode');
},
- 'test: --norecurse': function() {
+ 'test: --norecurse': function () {
var options = Y.Options([
'--norecurse',
]);
-
Assert.isTrue(options.norecurse, 'Failed to set norecurse');
},
- 'test: -n': function() {
+ 'test: -n': function () {
var options = Y.Options([
'-n',
]);
-
Assert.isTrue(options.norecurse, 'Failed to set norecurse');
},
- 'test: --selleck': function() {
+ 'test: --selleck': function () {
var options = Y.Options([
'--selleck',
]);
-
Assert.isTrue(options.selleck, 'Failed to set selleck');
},
- 'test: -S': function() {
+ 'test: -S': function () {
var options = Y.Options([
'-S',
]);
-
Assert.isTrue(options.selleck, 'Failed to set selleck');
},
- 'test: -T simple': function() {
+ 'test: -T simple': function () {
var options = Y.Options([
'-T',
'simple'
]);
- var p = path.join(__dirname, '../themes/simple');
- Assert.areEqual(p, options.themedir);
+ Assert.areEqual(path.join(__dirname, '../themes/simple'), options.themedir);
},
- 'test: --theme simple': function() {
+ 'test: --theme simple': function () {
var options = Y.Options([
'--theme',
'simple'
]);
- var p = path.join(__dirname, '../themes/simple');
- Assert.areEqual(p, options.themedir);
+ Assert.areEqual(path.join(__dirname, '../themes/simple'), options.themedir);
},
- 'test: --theme foobar': function() {
+ 'test: --theme foobar': function () {
var options = Y.Options([
'--theme',
'foobar'
]);
- var p = path.join(__dirname, '../themes/foobar');
- Assert.areEqual(p, options.themedir);
+ Assert.areEqual(path.join(__dirname, '../themes/foobar'), options.themedir);
},
- 'test: -t ./foobar': function() {
+ 'test: -t ./foobar': function () {
var options = Y.Options([
'-t',
'./foobar'
]);
Assert.areEqual('./foobar', options.themedir);
},
- 'test: --themedir ./foobar': function() {
+ 'test: --themedir ./foobar': function () {
var options = Y.Options([
'--themedir',
'./foobar'
]);
Assert.areEqual('./foobar', options.themedir);
},
- 'test: --syntaxtype coffee': function() {
+ 'test: --syntaxtype coffee': function () {
var options = Y.Options([
'--syntaxtype',
'coffee'
]);
Assert.areEqual('coffee', options.syntaxtype);
},
- 'test: --view': function() {
+ 'test: --view': function () {
var options = Y.Options([
'--view'
]);
Assert.isTrue(options.dumpview);
},
- 'test: -V': function() {
+ 'test: -V': function () {
var options = Y.Options([
'-V'
]);
Assert.isTrue(options.dumpview);
},
- 'test: -p': function() {
+ 'test: -p': function () {
var options = Y.Options([
'-p'
]);
Assert.isTrue(options.parseOnly);
},
- 'test: --parse-only': function() {
+ 'test: --parse-only': function () {
var options = Y.Options([
'--parse-only'
]);
Assert.isTrue(options.parseOnly);
},
- 'test: -o ': function() {
+ 'test: -o ': function () {
var options = Y.Options([
'-o',
'/foo/bar'
]);
Assert.areEqual('/foo/bar', options.outdir);
},
- 'test: --outdir ': function() {
+ 'test: --outdir ': function () {
var options = Y.Options([
'--outdir',
'/foo/bar'
]);
Assert.areEqual('/foo/bar', options.outdir);
},
- 'test: -D': function() {
+ 'test: -D': function () {
var options = Y.Options([
'-D'
]);
Assert.isTrue(options.nodeleteout);
},
- 'test: --no-delete-out': function() {
+ 'test: --no-delete-out': function () {
var options = Y.Options([
'--no-delete-out'
]);
Assert.isTrue(options.nodeleteout);
},
- 'test: --lint': function() {
+ 'test: --lint': function () {
var options = Y.Options([
'--lint'
]);
@@ -335,9 +313,9 @@ suite.add(new YUITest.TestCase({
Assert.isTrue(options.quiet);
Assert.isFalse(options.writeJSON);
},
- 'test --debug': function() {
+ 'test --debug': function () {
Assert.isFalse(Y.config.debug);
- var options = Y.Options([
+ Y.Options([
'--debug'
]);
Assert.isTrue(Y.config.debug);
@@ -346,22 +324,22 @@ suite.add(new YUITest.TestCase({
debug: false
});
},
- 'test: --charset': function() {
- var options = Y.Options([
+ 'test: --charset': function () {
+ Y.Options([
'--charset'
]);
Assert.areEqual('utf8', Y.charset);
-
+
},
- 'test: --charset foo': function() {
- var options = Y.Options([
+ 'test: --charset foo': function () {
+ Y.Options([
'--charset',
'foo'
]);
Assert.areEqual('foo', Y.charset);
Y.charset = 'utf8';
},
- 'test: --tab-to-space 8': function() {
+ 'test: --tab-to-space 8': function () {
var options = Y.Options([
'--tab-to-space',
'8'
@@ -373,4 +351,3 @@ suite.add(new YUITest.TestCase({
YUITest.TestRunner.add(suite);
-
diff --git a/tests/parser.js b/tests/parser.js
index 8b682e2e..e149bde4 100644
--- a/tests/parser.js
+++ b/tests/parser.js
@@ -1,3 +1,4 @@
+/*global Y:true */
var YUITest = require('yuitest'),
Assert = YUITest.Assert,
ArrayAssert = YUITest.ArrayAssert,
@@ -12,10 +13,10 @@ var existsSync = fs.existsSync || path.existsSync;
var suite = new YUITest.TestSuite({
name: 'Parser Test Suite',
- setUp: function() {
+ setUp: function () {
var json = (new Y.YUIDoc({
quiet: true,
- paths: [ 'input/' ],
+ paths: ['input/'],
outdir: './out'
})).run();
@@ -26,15 +27,15 @@ var suite = new YUITest.TestSuite({
suite.add(new YUITest.TestCase({
name: "Project Data",
- setUp: function() {
+ setUp: function () {
this.project = suite.project;
this.data = suite.data;
},
- findByName: function(name, cl) {
+ findByName: function (name, cl) {
var items = this.data.classitems,
ret;
- items.forEach(function(i) {
+ items.forEach(function (i) {
if (i.name === name && i.class === cl) {
ret = i;
}
@@ -42,18 +43,18 @@ suite.add(new YUITest.TestCase({
return ret;
},
- 'test: out directory': function() {
+ 'test: out directory': function () {
Assert.isTrue(existsSync(path.join(__dirname, 'out')), 'Out directory was not created');
},
- 'test: data.json creation': function() {
+ 'test: data.json creation': function () {
Assert.isTrue(existsSync(path.join(__dirname, 'out', 'data.json')), 'data.json file was not created');
},
- 'test: parser': function() {
+ 'test: parser': function () {
var keys = Object.keys(this.data);
Assert.areEqual(6, keys.length, 'Failed to populate all fields');
- ArrayAssert.itemsAreSame([ 'project', 'files', 'modules', 'classes', 'classitems', 'warnings' ], keys, 'Object keys are wrong');
+ ArrayAssert.itemsAreSame(['project', 'files', 'modules', 'classes', 'classitems', 'warnings'], keys, 'Object keys are wrong');
},
- 'test: project data': function() {
+ 'test: project data': function () {
Assert.areSame(path.normalize('input/test/test.js'), this.project.file, 'Project data loaded from wrong file');
Assert.areSame(2, this.project.line, 'Line number is off');
Assert.areSame('The test project', this.project.description, 'Description not set properly');
@@ -66,35 +67,36 @@ suite.add(new YUITest.TestCase({
Assert.areSame('http://one.url', this.project.url[0], 'URL #1 is wrong');
Assert.areSame('http://two.url', this.project.url[1], 'URL #2 is wrong');
},
- 'test: files parsing': function() {
- var files = this.data.files;
-
+ 'test: files parsing': function () {
+ var files = this.data.files,
+ one, two, three, four;
+
// 1 module, 3 classes
- var one = files[path.normalize('input/test/anim.js')];
+ one = files[path.normalize('input/test/anim.js')];
Assert.isObject(one, 'Failed to parse input/test/anim.js');
Assert.areSame(1, Object.keys(one.modules).length, '1 module should be found');
Assert.areSame(3, Object.keys(one.classes).length, '3 classes should be found');
// 2 modules, 3 classes
- var two = files[path.normalize('input/test/test.js')];
+ two = files[path.normalize('input/test/test.js')];
Assert.isObject(two, 'Failed to parse input/test/test.js');
Assert.areSame(2, Object.keys(two.modules).length, '2 modules should be found');
Assert.areSame(3, Object.keys(two.classes).length, '3 classes should be found');
//Module -> class association
- var three = files[path.normalize('input/test2/dump/dump.js')];
+ three = files[path.normalize('input/test2/dump/dump.js')];
Assert.isObject(three, 'Failed to parse input/test2/dump/dump.js');
Assert.areSame(1, three.modules.dump, 'dump module not found');
Assert.areSame(1, three.classes['YUI~dump'], 'YUI~dump class not found');
//Module -> class association
- var four = files[path.normalize('input/test2/oop/oop.js')];
+ four = files[path.normalize('input/test2/oop/oop.js')];
Assert.isObject(four, 'Failed to parse input/test2/oop/oop.js');
Assert.areSame(1, four.modules.oop, 'oop module not found');
Assert.areSame(1, four.classes['YUI~oop'], 'YUI~oop class not found');
},
- 'test: namespace parsing': function() {
+ 'test: namespace parsing': function () {
var item = this.data.files[path.normalize('input/test2/namespace.js')];
Assert.isObject(item, 'Failed to parse input/test2/namespace.js');
Assert.areSame(3, Object.keys(item.classes).length, 'Failed to parse all classes');
@@ -102,7 +104,7 @@ suite.add(new YUITest.TestCase({
ArrayAssert.itemsAreSame(['P.storage', 'P'], Object.keys(item.namespaces), 'Namespace failed to parse');
ArrayAssert.itemsAreSame(['P.storage.Store', 'P.storage.LocalStore', 'P.storage'], Object.keys(item.classes), 'Classes failed to parse');
},
- 'test: module parsing': function() {
+ 'test: module parsing': function () {
var mods = this.data.modules;
//anim Module
@@ -113,7 +115,7 @@ suite.add(new YUITest.TestCase({
Assert.areSame('main', mods.anim.itemtype, 'Failed to parse @main itemtype');
Assert.areSame('module', mods.anim.tag, 'Tag parse failed');
},
- 'test: main module association': function() {
+ 'test: main module association': function () {
var mod = this.data.modules.charts,
d = 'The Charts widget provides an api for displaying data\ngraphically.';
@@ -122,34 +124,36 @@ suite.add(new YUITest.TestCase({
Assert.areSame('main', mod.tag, 'Tagname is not main');
Assert.areSame('main', mod.itemtype, 'ItemType should be main');
},
- 'test: submodule parsing': function() {
- var mods = this.data.modules;
+ 'test: submodule parsing': function () {
+ var mods = this.data.modules,
+ m, desc;
//anim-easing submodule
- var m = mods['anim-easing'];
+ m = mods['anim-easing'];
Assert.isObject(m, 'Failed to parse anim-easing module');
- var desc = 'The easing module provides methods for customizing\nhow an animation behaves during each run.';
+ desc = 'The easing module provides methods for customizing\nhow an animation behaves during each run.';
Assert.areSame(desc, m.description, 'Failed to parse submodule description');
Assert.areSame(0, Object.keys(m.submodules).length, 'Should have 0 submodules');
Assert.areSame(1, Object.keys(m.classes).length, 'Should have 1 class');
- Assert.areSame(1, m['is_submodule'], 'Submodule association failed');
+ Assert.areSame(1, m.is_submodule, 'Submodule association failed');
Assert.areSame('anim', m.module, 'Failed to associate module');
//anim-easing-foo submodule
- var m = mods['anim-easing-foo'];
+ m = mods['anim-easing-foo'];
Assert.isObject(m, 'Failed to parse anim-easing-foo module');
- var desc = 'FOO FOO FOO FOO FOO The easing module provides methods for customizing';
+ desc = 'FOO FOO FOO FOO FOO The easing module provides methods for customizing';
Assert.areSame(desc, m.description, 'Failed to parse submodule description');
Assert.areSame(0, Object.keys(m.submodules).length, 'Should have 0 submodules');
Assert.areSame(1, Object.keys(m.classes).length, 'Should have 1 class');
- Assert.areSame(1, m['is_submodule'], 'Submodule association failed');
+ Assert.areSame(1, m.is_submodule, 'Submodule association failed');
Assert.areSame('anim', m.module, 'Failed to associate module');
},
- 'test: extra module data parsing': function() {
- var mods = this.data.modules;
-
- var m = mods.mymodule;
+ 'test: extra module data parsing': function () {
+ var mods = this.data.modules,
+ m;
+
+ m = mods.mymodule;
Assert.isObject(m, 'Failed to parse mymodule module');
Assert.areSame(1, Object.keys(m.submodules).length, 'Should have 1 submodules');
Assert.areSame(3, Object.keys(m.classes).length, 'Should have 3 class');
@@ -158,89 +162,106 @@ suite.add(new YUITest.TestCase({
ArrayAssert.itemsAreSame(['one', 'two'], m.requires, 'Requires parsing failed');
ArrayAssert.itemsAreSame(['three', 'four'], m.uses, 'Uses parsing failed');
- var m = mods.mysubmodule;
+ m = mods.mysubmodule;
Assert.isObject(m, 'Failed to parse mysubmodule module');
Assert.areSame(0, Object.keys(m.submodules).length, 'Should have 0 submodules');
Assert.areSame(3, Object.keys(m.classes).length, 'Should have 3 class');
- Assert.areSame(1, m['is_submodule'], 'Submodule association failed');
+ Assert.areSame(1, m.is_submodule, 'Submodule association failed');
ArrayAssert.itemsAreSame(['three', 'four'], m.category, 'Category parsing failed');
//Testing modules with slashes in them
- var m = mods['myapp/views/index'];
+ m = mods['myapp/views/index'];
Assert.isObject(m, 'Failed to parse myapp/views/index module');
Assert.areSame(1, Object.keys(m.classes).length, 'Should have 1 class');
-
- var m = mods['P.storage'];
+
+ m = mods['P.storage'];
Assert.isObject(m, 'Failed to parse P.storage module');
ArrayAssert.itemsAreSame(['P.storage.Store', 'P.storage.LocalStore', 'P.storage'], Object.keys(m.classes), 'Failed to parse classes');
ArrayAssert.itemsAreSame(['P.storage', 'P'], Object.keys(m.namespaces), 'Namespace failed to parse');
-
+
},
- 'test: class parsing': function() {
- var cl = this.data.classes;
+ 'test: class parsing': function () {
+ var cl = this.data.classes,
+ anim, easing, my, other, m;
- var anim = cl.Anim;
+ anim = cl.Anim;
Assert.isObject(anim, 'Failed to find Anim class');
Assert.areSame('Anim', anim.name, 'Failed to set name');
Assert.areSame('Anim', anim.shortname, 'Failed to set shortname');
Assert.areSame('anim', anim.module, 'Failed to test module.');
- var easing = cl.Easing;
+ easing = cl.Easing;
Assert.isObject(easing, 'Failed to find Easing class');
Assert.areSame('Easing', easing.name, 'Failed to set name');
Assert.areSame('Easing', easing.shortname, 'Failed to set shortname');
Assert.areSame('anim', easing.module, 'Failed to test module.');
Assert.areSame('anim-easing', easing.submodule, 'Failed to test submodule.');
- var my = cl.myclass;
+ my = cl.myclass;
Assert.isObject(my, 'Failed to find myclass class');
Assert.areSame('myclass', my.name, 'Failed to set name');
Assert.areSame('myclass', my.shortname, 'Failed to set shortname');
Assert.areSame('mymodule', my.module, 'Failed to test module.');
Assert.areSame('mysubmodule', my.submodule, 'Failed to test submodule.');
- Assert.areSame(1, my['is_constructor'], 'Failed to register constructor.');
+ Assert.areSame(1, my.is_constructor, 'Failed to register constructor.');
- var other = cl.OtherClass;
+ other = cl.OtherClass;
Assert.isObject(other, 'Failed to find myclass class');
Assert.areSame('OtherClass', other.name, 'Failed to set name');
Assert.areSame('OtherClass', other.shortname, 'Failed to set shortname');
Assert.areSame('mymodule', other.module, 'Failed to test module.');
Assert.areSame('mysubmodule', other.submodule, 'Failed to test submodule.');
- Assert.areSame(1, Object.keys(other['extension_for']).length, 'Failed to assign extension_for');
- Assert.areSame('myclass', other['extension_for'][0], 'Failed to assign extension_for');
-
- var m = cl['P.storage.P.storage'];
+ Assert.areSame(1, Object.keys(other.extension_for).length, 'Failed to assign extension_for');
+ Assert.areSame('myclass', other.extension_for[0], 'Failed to assign extension_for');
+
+ m = cl['P.storage.P.storage'];
Assert.isUndefined(m, 'Should not have double namespaces');
Assert.isNotUndefined(cl['P.storage'], 'Should not have double namespaces');
Assert.isNotUndefined(cl['P.storage.Store'], 'Should not have double namespaces');
Assert.isNotUndefined(cl['P.storage.LocalStore'], 'Should not have double namespaces');
},
- 'test: classitems parsing': function() {
+ 'test: classitems parsing': function () {
Assert.isArray(this.data.classitems, 'Failed to populate classitems array');
-
- var item = this.findByName('testoptional', 'myclass');
+ var keys, item, item2;
+
+ item = this.findByName('testoptional', 'myclass');
Assert.areSame('testoptional', item.name, 'Failed to find item: testoptional');
Assert.areSame('myclass', item.class, 'Failed to find class: testoptional');
Assert.areSame('mymodule', item.module, 'Failed to find module: testoptional');
Assert.areSame('mysubmodule', item.submodule, 'Failed to find submodule: testoptional');
Assert.areSame('method', item.itemtype, 'Should be a method');
- var keys = [ 'file', 'line', 'description', 'itemtype', 'name', 'params', 'evil', 'injects', 'return', 'example', 'class', 'module', 'submodule' ];
-
+ keys = [
+ 'file',
+ 'line',
+ 'description',
+ 'itemtype',
+ 'name',
+ 'params',
+ 'evil',
+ 'injects',
+ 'return',
+ 'example',
+ 'class',
+ 'module',
+ 'submodule'
+ ];
+
ArrayAssert.itemsAreSame(keys, Object.keys(item), 'Item missing from output');
Assert.areSame('', item.evil, 'Single tag not found');
Assert.areSame('HTML', item.injects.type, 'Injection type not found');
- Assert.isUndefined(item.return.type, 'Type should be missing');
+ Assert.isUndefined(item["return"].type, 'Type should be missing');
Assert.areSame(2, item.example.length, 'Should have 2 example snippets');
- var item2 = this.findByName('testobjectparam', 'myclass');
- Assert.areSame('String', item2.return.type, 'Type should not be missing');
+ item2 = this.findByName('testobjectparam', 'myclass');
+ Assert.areSame('String', item2["return"].type, 'Type should not be missing');
},
- 'test: parameter parsing': function() {
- var item = this.findByName('testoptional', 'myclass');
+ 'test: parameter parsing': function () {
+ var item, item2;
+ item = this.findByName('testoptional', 'myclass');
Assert.isArray(item.params, 'Params should be an array');
Assert.areSame(5, item.params.length, 'Failed to parse all 5 parameters');
@@ -259,24 +280,25 @@ suite.add(new YUITest.TestCase({
Assert.isTrue(item.params[4].optional, 'Parameter should be optional');
Assert.areSame('"defaultval"', item.params[4].optdefault, 'Optional Default value is incorrect');
- var item2 = this.findByName('test0ton', 'myclass');
+ item2 = this.findByName('test0ton', 'myclass');
Assert.isArray(item2.params, 'Params should be an array');
Assert.areSame(1, item2.params.length, 'Failed to parse all 5 parameters');
Assert.isTrue(item2.params[0].optional, 'Optional not set');
Assert.isTrue(item2.params[0].multiple, 'Multiple not set');
- Assert.isUndefined(item2.return.type, 'Type should be missing');
+ Assert.isUndefined(item2["return"].type, 'Type should be missing');
- var item2 = this.findByName('test1ton', 'myclass');
+ item2 = this.findByName('test1ton', 'myclass');
Assert.isArray(item2.params, 'Params should be an array');
Assert.areSame(1, item2.params.length, 'Failed to parse all 5 parameters');
Assert.isUndefined(item2.params[0].optional, 'Optional should not be set');
Assert.isTrue(item2.params[0].multiple, 'Multiple not set');
- Assert.isUndefined(item2.return.type, 'Type should be missing');
+ Assert.isUndefined(item2["return"].type, 'Type should be missing');
},
- 'test: object parameters': function() {
- var item = this.findByName('testobjectparam', 'myclass');
+ 'test: object parameters': function () {
+ var item, props;
+ item = this.findByName('testobjectparam', 'myclass');
Assert.areSame('testobjectparam', item.name, 'Failed to find item: testobjectparam');
Assert.areSame('myclass', item.class, 'Failed to find class: testobjectparam');
Assert.areSame('mymodule', item.module, 'Failed to find module: testobjectparam');
@@ -284,7 +306,7 @@ suite.add(new YUITest.TestCase({
Assert.areSame('method', item.itemtype, 'Should be a method');
Assert.areSame(1, item.params.length, 'More than one param found');
- var props = item.params[0].props;
+ props = item.params[0].props;
Assert.areSame(2, props.length, 'First param should have props');
Assert.areSame('prop1', props[0].name, 'Invalid item');
Assert.areSame('prop1', props[0].description, 'Invalid item');
@@ -294,11 +316,11 @@ suite.add(new YUITest.TestCase({
Assert.areSame('prop2', props[1].description, 'Invalid item');
Assert.areSame('Bool', props[1].type, 'Invalid item');
},
- 'test: tag fixing': function() {
+ 'test: tag fixing': function () {
var item = this.findByName('testoptional', 'myclass');
-
+
Assert.isObject(item, 'failed to find item');
- Assert.isNotUndefined(item.return, 'Failed to replace returns with return');
+ Assert.isNotUndefined(item["return"], 'Failed to replace returns with return');
item = this.findByName('_positionChangeHandler', 'Axis');
Assert.isObject(item, 'failed to find item');
@@ -307,62 +329,60 @@ suite.add(new YUITest.TestCase({
item = this.findByName('crashTest', 'OtherClass2');
Assert.isObject(item, 'failed to find item');
Assert.areEqual(1, item.params.length, 'Failed to replace params with param');
-
-
},
- 'test: double namespaces': function() {
- var cls = this.data.classes;
- var mod_bad = cls['Foo.Bar.Foo.Bar'];
- var mod_good = cls['Foo.Bar'];
+ 'test: double namespaces': function () {
+ var cls = this.data.classes,
+ mod_bad = cls['Foo.Bar.Foo.Bar'],
+ mod_good = cls['Foo.Bar'];
Assert.isUndefined(mod_bad, 'Found class Foo.Bar.Foo.Bar');
Assert.isObject(mod_good, 'Failed to parse Foo.Bar namespace');
},
- 'test: inherited methods': function() {
+ 'test: inherited methods': function () {
var item = this.findByName('myMethod', 'mywidget.SubWidget');
Assert.isObject(item, 'Failed to parse second method');
},
- 'test: case tags': function() {
+ 'test: case tags': function () {
var item = this.findByName('testMethod', 'OtherClass2');
Assert.isObject(item, 'Failed to parse second method');
Assert.areSame('method', item.itemtype, 'Failed to parse Cased Method tag');
Assert.isArray(item.params, 'Failed to parse Cased Params');
Assert.areSame(1, item.params.length, 'Failed to parse number of cased params');
},
- 'test: required attribute': function() {
+ 'test: required attribute': function () {
var item = this.findByName('requiredAttr', 'OtherClass2');
Assert.isObject(item, 'Failed to parse attribute');
Assert.areSame('attribute', item.itemtype, 'Failed to parse itemtype');
Assert.areSame(1, item.required, 'Failed to find required short tag');
},
- 'test: optional attribute': function() {
+ 'test: optional attribute': function () {
var item = this.findByName('optionalAttr', 'OtherClass2');
Assert.isObject(item, 'Failed to parse attribute');
Assert.areSame('attribute', item.itemtype, 'Failed to parse itemtype');
Assert.areSame(1, item.optional, 'Failed to find optional short tag');
},
- 'test: module with example meta': function() {
+ 'test: module with example meta': function () {
var item = this.data.modules.ExampleModule;
Assert.isObject(item, 'Failed to parse module');
Assert.isArray(item.example, 'Failed to parse module example data');
},
- 'test: class with example meta': function() {
+ 'test: class with example meta': function () {
var item = this.data.classes['mywidget.SuperWidget'];
Assert.isObject(item, 'Failed to parse class');
Assert.isArray(item.example, 'Failed to parse class example data');
},
- 'test: event with optional items': function() {
+ 'test: event with optional items': function () {
var item = this.findByName('changeWithOptional', 'OtherClass2');
Assert.isObject(item, 'Failed to locate event object');
- var params = item.params;
- Assert.isArray(params);
- var ev = params[0];
- Assert.areSame(ev.name, 'ev');
- Assert.areSame(ev.type, 'EventFacade');
- var props = ev.props;
- Assert.isArray(props);
- Assert.areSame(props[0].name, 'name');
- Assert.isTrue(props[0].optional);
-
+
+ Assert.isArray(item.params);
+
+ Assert.areSame(item.params[0].name, 'ev');
+ Assert.areSame(item.params[0].type, 'EventFacade');
+
+ Assert.isArray(item.params[0].props);
+ Assert.areSame(item.params[0].props[0].name, 'name');
+ Assert.isTrue(item.params[0].props[0].optional);
+
}
}));
diff --git a/tests/parser_coffee.js b/tests/parser_coffee.js
index 9e778bfa..08d96795 100644
--- a/tests/parser_coffee.js
+++ b/tests/parser_coffee.js
@@ -1,21 +1,18 @@
+/*global Y:true */
var YUITest = require('yuitest'),
Assert = YUITest.Assert,
- ArrayAssert = YUITest.ArrayAssert,
path = require('path'),
- fs = require('fs'),
Y = require(path.join(__dirname, '../', 'lib', 'index'));
//Move to the test dir before running the tests.
process.chdir(__dirname);
-var existsSync = fs.existsSync || path.existsSync;
-
var suite = new YUITest.TestSuite({
name: 'Coffee Parser Test Suite',
- setUp: function() {
+ setUp: function () {
var json = (new Y.YUIDoc({
quiet: true,
- paths: [ 'input/' ],
+ paths: ['input/'],
outdir: './out',
extension: '.coffee',
syntaxtype: 'coffee'
@@ -28,15 +25,15 @@ var suite = new YUITest.TestSuite({
suite.add(new YUITest.TestCase({
name: "Project Data",
- setUp: function() {
+ setUp: function () {
this.project = suite.project;
this.data = suite.data;
},
- findByName: function(name, cl) {
+ findByName: function (name, cl) {
var items = this.data.classitems,
ret;
- items.forEach(function(i) {
+ items.forEach(function (i) {
if (i.name === name && i.class === cl) {
ret = i;
}
@@ -44,7 +41,7 @@ suite.add(new YUITest.TestCase({
return ret;
},
- 'test: project data': function() {
+ 'test: project data': function () {
Assert.areSame(path.normalize('input/coffee/test.coffee'), this.project.file, 'Project data loaded from wrong file');
Assert.areSame(2, this.project.line, 'Line number is off');
Assert.areSame('The test project', this.project.description, 'Description not set properly');
diff --git a/tests/utils.js b/tests/utils.js
index 4f146437..981bd88d 100644
--- a/tests/utils.js
+++ b/tests/utils.js
@@ -1,44 +1,44 @@
+/*global Y:true */
var YUITest = require('yuitest'),
- Assert = YUITest.Assert,
- path = require('path')
- Y = require(path.join(__dirname, '../', 'lib', 'index'))
- ;
+ Assert = YUITest.Assert,
+ path = require('path'),
+ Y = require(path.join(__dirname, '../', 'lib', 'index'));
var suite = new YUITest.TestSuite({
- name: 'Utils Test Suite'
+ name: 'Utils Test Suite'
});
suite.add(new YUITest.TestCase({
- name: 'getProjectData Folder Priority',
- 'test: Nearest Folder Priority': function() {
- var d = Y.getProjectData('input/folders1');
- Assert.areEqual('yuidoc-root', d.name, 'must use nearest yuidoc.json first');
- },
- 'test: Finds package.json': function() {
- var d = Y.getProjectData('input/folders2');
- Assert.areEqual('yuidoc-two', d.name, 'used deep yuidoc.json');
- Assert.areEqual('package-root', d.description, 'used shallow package.json');
- },
- 'test: Finds package.json in same folder as yuidoc.json': function() {
- var d = Y.getProjectData('input/folders3');
- Assert.areEqual('yuidoc-root', d.name, 'used deep yuidoc.json');
- Assert.areEqual('package-root', d.description, 'used deep package.json');
- },
- 'test: Ignores package.json in deeper folder than yuidoc.json': function() {
- var d = Y.getProjectData('input/folders4');
- Assert.areEqual('yuidoc-one', d.name, 'used deep yuidoc.json');
- Assert.isUndefined(d.description, 'used deep package.json');
- },
- 'test: Must be breadth-first': function() {
- var d = Y.getProjectData('input/folders5');
- Assert.areEqual('yuidoc-two', d.name, 'used wrong yuidoc.json');
- Assert.areEqual('package-two', d.description, 'used wrong package.json');
- }
+ name: 'getProjectData Folder Priority',
+ 'test: Nearest Folder Priority': function () {
+ var d = Y.getProjectData('input/folders1');
+ Assert.areEqual('yuidoc-root', d.name, 'must use nearest yuidoc.json first');
+ },
+ 'test: Finds package.json': function () {
+ var d = Y.getProjectData('input/folders2');
+ Assert.areEqual('yuidoc-two', d.name, 'used deep yuidoc.json');
+ Assert.areEqual('package-root', d.description, 'used shallow package.json');
+ },
+ 'test: Finds package.json in same folder as yuidoc.json': function () {
+ var d = Y.getProjectData('input/folders3');
+ Assert.areEqual('yuidoc-root', d.name, 'used deep yuidoc.json');
+ Assert.areEqual('package-root', d.description, 'used deep package.json');
+ },
+ 'test: Ignores package.json in deeper folder than yuidoc.json': function () {
+ var d = Y.getProjectData('input/folders4');
+ Assert.areEqual('yuidoc-one', d.name, 'used deep yuidoc.json');
+ Assert.isUndefined(d.description, 'used deep package.json');
+ },
+ 'test: Must be breadth-first': function () {
+ var d = Y.getProjectData('input/folders5');
+ Assert.areEqual('yuidoc-two', d.name, 'used wrong yuidoc.json');
+ Assert.areEqual('package-two', d.description, 'used wrong package.json');
+ }
}));
suite.add(new YUITest.TestCase({
- name: 'validatePaths',
- 'test: path globs': function() {
+ name: 'validatePaths',
+ 'test: path globs': function () {
var options;
process.chdir(path.join(__dirname, 'input/globbing'));
@@ -73,7 +73,7 @@ suite.add(new YUITest.TestCase({
Assert.isArray(options.paths, 'Failed to set path');
Assert.areSame(3, options.paths.length, 'Failed to retrieve all path options');
- }
+ }
}));
YUITest.TestRunner.add(suite);
diff --git a/themes/default/assets/js/apidocs.js b/themes/default/assets/js/apidocs.js
index c64bb463..e00591c1 100644
--- a/themes/default/assets/js/apidocs.js
+++ b/themes/default/assets/js/apidocs.js
@@ -284,7 +284,7 @@ pjax.handleClasses = function (req, res, next) {
var status = res.ioResponse.status;
// Handles success and local filesystem XHRs.
- if (!status || (status >= 200 && status < 300)) {
+ if (res.ioResponse.readyState === 4 && (!status || (status >= 200 && status < 300))) {
pjax.initClassTabView();
}
@@ -295,7 +295,7 @@ pjax.handleFiles = function (req, res, next) {
var status = res.ioResponse.status;
// Handles success and local filesystem XHRs.
- if (!status || (status >= 200 && status < 300)) {
+ if (res.ioResponse.readyState === 4 && (!status || (status >= 200 && status < 300))) {
pjax.initLineNumbers();
}