2010-12-22 23:44:27 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* All parsing/transformation code goes here. All code here should be sync to ease testing.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
var Showdown = require('showdown').Showdown;
|
|
|
|
|
|
var DOM = require('dom.js').DOM;
|
2011-01-26 05:55:11 +00:00
|
|
|
|
var htmlEscape = require('dom.js').htmlEscape;
|
2010-12-22 23:44:27 +00:00
|
|
|
|
var NEW_LINE = /\n\r?/;
|
|
|
|
|
|
|
|
|
|
|
|
exports.trim = trim;
|
|
|
|
|
|
exports.metadata = metadata;
|
|
|
|
|
|
exports.scenarios = scenarios;
|
|
|
|
|
|
exports.merge = merge;
|
|
|
|
|
|
exports.Doc = Doc;
|
|
|
|
|
|
|
2011-09-08 20:56:29 +00:00
|
|
|
|
var BOOLEAN_ATTR = {};
|
|
|
|
|
|
['multiple', 'selected', 'checked', 'disabled', 'readOnly', 'required'].forEach(function(value, key) {
|
|
|
|
|
|
BOOLEAN_ATTR[value] = true;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
//////////////////////////////////////////////////////////
|
|
|
|
|
|
function Doc(text, file, line) {
|
|
|
|
|
|
if (typeof text == 'object') {
|
|
|
|
|
|
for ( var key in text) {
|
|
|
|
|
|
this[key] = text[key];
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.text = text;
|
|
|
|
|
|
this.file = file;
|
|
|
|
|
|
this.line = line;
|
|
|
|
|
|
}
|
2011-02-01 00:21:29 +00:00
|
|
|
|
this.scenarios = this.scenarios || [];
|
|
|
|
|
|
this.requires = this.requires || [];
|
|
|
|
|
|
this.param = this.param || [];
|
|
|
|
|
|
this.properties = this.properties || [];
|
|
|
|
|
|
this.methods = this.methods || [];
|
2011-08-26 05:23:10 +00:00
|
|
|
|
this.events = this.events || [];
|
2011-05-17 20:12:23 +00:00
|
|
|
|
this.links = this.links || [];
|
2010-12-22 23:44:27 +00:00
|
|
|
|
}
|
2011-10-07 18:27:49 +00:00
|
|
|
|
Doc.METADATA_IGNORE = (function() {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
var words = require('fs').readFileSync(__dirname + '/ignore.words', 'utf8');
|
|
|
|
|
|
return words.toString().split(/[,\s\n\r]+/gm);
|
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Doc.prototype = {
|
2011-10-07 18:27:49 +00:00
|
|
|
|
keywords: function keywords() {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
var keywords = {};
|
|
|
|
|
|
Doc.METADATA_IGNORE.forEach(function(ignore){ keywords[ignore] = true; });
|
|
|
|
|
|
var words = [];
|
|
|
|
|
|
var tokens = this.text.toLowerCase().split(/[,\.\`\'\"\s]+/mg);
|
|
|
|
|
|
tokens.forEach(function(key){
|
2011-01-26 05:55:11 +00:00
|
|
|
|
var match = key.match(/^(([\$\_a-z]|ng\:)[\w\_\-]{2,})/);
|
2010-12-22 23:44:27 +00:00
|
|
|
|
if (match){
|
|
|
|
|
|
key = match[1];
|
|
|
|
|
|
if (!keywords[key]) {
|
|
|
|
|
|
keywords[key] = true;
|
|
|
|
|
|
words.push(key);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
words.sort();
|
|
|
|
|
|
return words.join(' ');
|
|
|
|
|
|
},
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2011-05-19 14:48:05 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Converts relative urls (without section) into absolute
|
|
|
|
|
|
* Absolute url means url with section
|
|
|
|
|
|
*
|
|
|
|
|
|
* @example
|
|
|
|
|
|
* - if the link is inside any api doc:
|
|
|
|
|
|
* angular.widget -> api/angular.widget
|
|
|
|
|
|
*
|
|
|
|
|
|
* - if the link is inside any guid doc:
|
|
|
|
|
|
* intro -> guide/intro
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} url Absolute or relative url
|
|
|
|
|
|
* @returns {string} Absolute url
|
2011-04-29 22:18:27 +00:00
|
|
|
|
*/
|
2011-05-19 14:48:05 +00:00
|
|
|
|
convertUrlToAbsolute: function(url) {
|
2011-05-19 19:14:41 +00:00
|
|
|
|
if (url.substr(-1) == '/') return url + 'index';
|
2011-04-29 22:18:27 +00:00
|
|
|
|
if (url.match(/\//)) return url;
|
2011-05-19 14:48:05 +00:00
|
|
|
|
return this.section + '/' + url;
|
2011-04-29 22:18:27 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
2011-10-07 18:27:49 +00:00
|
|
|
|
markdown: function(text) {
|
2011-02-01 00:21:29 +00:00
|
|
|
|
if (!text) return text;
|
2011-02-07 23:55:23 +00:00
|
|
|
|
|
2011-05-23 22:49:33 +00:00
|
|
|
|
var self = this,
|
|
|
|
|
|
IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:|\.|\/)/,
|
2011-06-06 17:45:22 +00:00
|
|
|
|
IS_ANGULAR = /^(api\/)?angular\./,
|
2011-05-23 22:49:33 +00:00
|
|
|
|
parts = trim(text).split(/(<pre>[\s\S]*?<\/pre>|<doc:(\S*).*?>[\s\S]*?<\/doc:\2>)/);
|
2011-02-07 23:55:23 +00:00
|
|
|
|
|
2011-05-23 22:49:33 +00:00
|
|
|
|
parts.forEach(function(text, i) {
|
|
|
|
|
|
|
|
|
|
|
|
function isDocWidget(name) {
|
|
|
|
|
|
if ((i + 1) % 3 != 2) return false;
|
|
|
|
|
|
if (name) return parts[i+1] == name;
|
|
|
|
|
|
return !!parts[i+1];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ignore each third item which is doc widget tag
|
|
|
|
|
|
if (!((i + 1) % 3)) {
|
|
|
|
|
|
parts[i] = '';
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2011-02-01 00:21:29 +00:00
|
|
|
|
|
|
|
|
|
|
if (text.match(/^<pre>/)) {
|
|
|
|
|
|
text = text.replace(/^<pre>([\s\S]*)<\/pre>/mi, function(_, content){
|
2011-04-29 22:18:27 +00:00
|
|
|
|
var clazz = 'brush: js;';
|
2011-04-29 21:43:43 +00:00
|
|
|
|
if (content.match(/\<\w/)) {
|
|
|
|
|
|
// we are HTML
|
|
|
|
|
|
clazz += ' html-script: true;';
|
|
|
|
|
|
}
|
|
|
|
|
|
return '<div ng:non-bindable><pre class="' + clazz +'">' +
|
2011-02-01 00:21:29 +00:00
|
|
|
|
content.replace(/</g, '<').replace(/>/g, '>') +
|
|
|
|
|
|
'</pre></div>';
|
|
|
|
|
|
});
|
2011-05-23 22:49:33 +00:00
|
|
|
|
} else if (isDocWidget('example')) {
|
2011-08-19 19:06:59 +00:00
|
|
|
|
text = text.replace(/<doc:source(\s+jsfiddle="[^"]+")?>([\s\S]*)<\/doc:source>/mi,
|
|
|
|
|
|
function(_, jsfiddle, content){
|
|
|
|
|
|
return '<pre class="doc-source"' + (jsfiddle || '') +'>' +
|
|
|
|
|
|
htmlEscape(content) +
|
|
|
|
|
|
'</pre>';
|
2011-02-01 00:21:29 +00:00
|
|
|
|
});
|
|
|
|
|
|
text = text.replace(/(<doc:scenario>)([\s\S]*)(<\/doc:scenario>)/mi,
|
|
|
|
|
|
function(_, before, content, after){
|
|
|
|
|
|
self.scenarios.push(content);
|
2011-02-22 22:48:53 +00:00
|
|
|
|
return '<pre class="doc-scenario">' + htmlEscape(content) + '</pre>';
|
2011-02-01 00:21:29 +00:00
|
|
|
|
});
|
2011-05-23 22:49:33 +00:00
|
|
|
|
} else if (!isDocWidget()) {
|
2011-02-01 00:21:29 +00:00
|
|
|
|
text = text.replace(/<angular\/>/gm, '<tt><angular/></tt>');
|
2011-02-18 18:24:30 +00:00
|
|
|
|
text = text.replace(/{@link\s+([^\s}]+)\s*([^}]*?)\s*}/g,
|
|
|
|
|
|
function(_all, url, title){
|
2011-05-17 20:12:23 +00:00
|
|
|
|
var isFullUrl = url.match(IS_URL),
|
2011-05-19 14:48:05 +00:00
|
|
|
|
isAngular = url.match(IS_ANGULAR),
|
|
|
|
|
|
absUrl = isFullUrl ? url : self.convertUrlToAbsolute(url);
|
2011-05-17 20:12:23 +00:00
|
|
|
|
|
2011-05-19 14:48:05 +00:00
|
|
|
|
if (!isFullUrl) self.links.push(absUrl);
|
2011-05-17 20:12:23 +00:00
|
|
|
|
|
2011-08-30 09:47:24 +00:00
|
|
|
|
return '<a href="' + absUrl + '">'
|
2011-05-17 20:12:23 +00:00
|
|
|
|
+ (isAngular ? '<code>' : '')
|
2011-02-18 18:24:30 +00:00
|
|
|
|
+ (title || url).replace(/\n/g, ' ')
|
2011-05-17 20:12:23 +00:00
|
|
|
|
+ (isAngular ? '</code>' : '')
|
2011-02-01 00:21:29 +00:00
|
|
|
|
+ '</a>';
|
|
|
|
|
|
});
|
|
|
|
|
|
text = new Showdown.converter().makeHtml(text);
|
|
|
|
|
|
}
|
|
|
|
|
|
parts[i] = text;
|
|
|
|
|
|
});
|
|
|
|
|
|
return parts.join('');
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2011-10-07 18:27:49 +00:00
|
|
|
|
parse: function() {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
var atName;
|
|
|
|
|
|
var atText;
|
|
|
|
|
|
var match;
|
|
|
|
|
|
var self = this;
|
|
|
|
|
|
self.text.split(NEW_LINE).forEach(function(line){
|
|
|
|
|
|
if (match = line.match(/^\s*@(\w+)(\s+(.*))?/)) {
|
|
|
|
|
|
// we found @name ...
|
|
|
|
|
|
// if we have existing name
|
|
|
|
|
|
flush();
|
|
|
|
|
|
atName = match[1];
|
|
|
|
|
|
atText = [];
|
|
|
|
|
|
if(match[3]) atText.push(match[3]);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (atName) {
|
|
|
|
|
|
atText.push(line);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
flush();
|
|
|
|
|
|
this.shortName = (this.name || '').split(/[\.#]/).pop();
|
2011-01-26 05:55:11 +00:00
|
|
|
|
this.id = this.id // if we have an id just use it
|
|
|
|
|
|
|| (((this.file||'').match(/.*\/([^\/]*)\.ngdoc/)||{})[1]) // try to extract it from file name
|
|
|
|
|
|
|| this.name; // default to name
|
2011-02-01 00:21:29 +00:00
|
|
|
|
this.description = this.markdown(this.description);
|
|
|
|
|
|
this.example = this.markdown(this.example);
|
|
|
|
|
|
this['this'] = this.markdown(this['this']);
|
2011-01-19 23:42:11 +00:00
|
|
|
|
return this;
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2011-10-07 18:27:49 +00:00
|
|
|
|
function flush() {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
if (atName) {
|
|
|
|
|
|
var text = trim(atText.join('\n'));
|
|
|
|
|
|
if (atName == 'param') {
|
|
|
|
|
|
var match = text.match(/^{([^}=]+)(=)?}\s+(([^\s=]+)|\[(\S+)=([^\]]+)\])\s+(.*)/);
|
|
|
|
|
|
// 1 12 2 34 4 5 5 6 6 3 7 7
|
|
|
|
|
|
if (!match) {
|
|
|
|
|
|
throw new Error("Not a valid 'param' format: " + text);
|
|
|
|
|
|
}
|
|
|
|
|
|
var param = {
|
|
|
|
|
|
name: match[5] || match[4],
|
2011-02-01 00:21:29 +00:00
|
|
|
|
description:self.markdown(text.replace(match[0], match[7])),
|
2010-12-22 23:44:27 +00:00
|
|
|
|
type: match[1],
|
|
|
|
|
|
optional: !!match[2],
|
|
|
|
|
|
'default':match[6]
|
|
|
|
|
|
};
|
|
|
|
|
|
self.param.push(param);
|
|
|
|
|
|
} else if (atName == 'returns') {
|
|
|
|
|
|
var match = text.match(/^{([^}=]+)}\s+(.*)/);
|
|
|
|
|
|
if (!match) {
|
|
|
|
|
|
throw new Error("Not a valid 'returns' format: " + text);
|
|
|
|
|
|
}
|
|
|
|
|
|
self.returns = {
|
|
|
|
|
|
type: match[1],
|
2011-02-01 00:21:29 +00:00
|
|
|
|
description: self.markdown(text.replace(match[0], match[2]))
|
2010-12-22 23:44:27 +00:00
|
|
|
|
};
|
|
|
|
|
|
} else if(atName == 'requires') {
|
2011-03-10 21:39:59 +00:00
|
|
|
|
var match = text.match(/^([^\s]*)\s*([\S\s]*)/);
|
|
|
|
|
|
self.requires.push({
|
|
|
|
|
|
name: match[1],
|
|
|
|
|
|
text: self.markdown(match[2])
|
|
|
|
|
|
});
|
2010-12-22 23:44:27 +00:00
|
|
|
|
} else if(atName == 'property') {
|
2011-02-07 04:44:55 +00:00
|
|
|
|
var match = text.match(/^{(\S+)}\s+(\S+)(\s+(.*))?/);
|
2010-12-22 23:44:27 +00:00
|
|
|
|
if (!match) {
|
|
|
|
|
|
throw new Error("Not a valid 'property' format: " + text);
|
|
|
|
|
|
}
|
|
|
|
|
|
var property = {
|
2011-02-07 04:44:55 +00:00
|
|
|
|
type: match[1],
|
|
|
|
|
|
name: match[2],
|
|
|
|
|
|
description: self.markdown(text.replace(match[0], match[4]))
|
2010-12-22 23:44:27 +00:00
|
|
|
|
};
|
|
|
|
|
|
self.properties.push(property);
|
2011-08-26 05:23:10 +00:00
|
|
|
|
} else if(atName == 'eventType') {
|
|
|
|
|
|
var match = text.match(/^([^\s]*)\s+on\s+([\S\s]*)/);
|
|
|
|
|
|
self.type = match[1];
|
2011-08-31 19:21:27 +00:00
|
|
|
|
self.target = match[2];
|
2010-12-22 23:44:27 +00:00
|
|
|
|
} else {
|
|
|
|
|
|
self[atName] = text;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2011-10-07 18:27:49 +00:00
|
|
|
|
html: function() {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
var dom = new DOM(),
|
|
|
|
|
|
self = this;
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.h(this.name, function() {
|
2011-01-19 20:16:21 +00:00
|
|
|
|
notice('workInProgress', 'Work in Progress',
|
2010-12-22 23:44:27 +00:00
|
|
|
|
'This page is currently being revised. It might be incomplete or contain inaccuracies.');
|
2011-01-26 06:54:02 +00:00
|
|
|
|
notice('deprecated', 'Deprecated API', self.deprecated);
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2011-03-10 21:39:59 +00:00
|
|
|
|
if (self.ngdoc != 'overview') {
|
|
|
|
|
|
dom.h('Description', self.description, dom.html);
|
|
|
|
|
|
}
|
|
|
|
|
|
dom.h('Dependencies', self.requires, function(require){
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.tag('code', function() {
|
2011-08-30 09:47:24 +00:00
|
|
|
|
dom.tag('a', {href: 'api/angular.service.' + require.name}, require.name);
|
2011-03-10 21:39:59 +00:00
|
|
|
|
});
|
|
|
|
|
|
dom.html(require.text);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2011-10-07 18:27:49 +00:00
|
|
|
|
(self['html_usage_' + self.ngdoc] || function() {
|
2011-01-26 05:55:11 +00:00
|
|
|
|
throw new Error("Don't know how to format @ngdoc: " + self.ngdoc);
|
|
|
|
|
|
}).call(self, dom);
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2011-02-01 00:21:29 +00:00
|
|
|
|
dom.h('Example', self.example, dom.html);
|
2010-12-22 23:44:27 +00:00
|
|
|
|
});
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
return dom.toString();
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
//////////////////////////
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
function notice(name, legend, msg){
|
|
|
|
|
|
if (self[name] == undefined) return;
|
|
|
|
|
|
dom.tag('fieldset', {'class':name}, function(dom){
|
|
|
|
|
|
dom.tag('legend', legend);
|
|
|
|
|
|
dom.text(msg);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
},
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
html_usage_parameters: function(dom) {
|
|
|
|
|
|
dom.h('Parameters', this.param, function(param){
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.tag('code', function() {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
dom.text(param.name);
|
|
|
|
|
|
if (param.optional) {
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.tag('i', function() {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
dom.text('(optional');
|
|
|
|
|
|
if(param['default']) {
|
|
|
|
|
|
dom.text('=' + param['default']);
|
|
|
|
|
|
}
|
|
|
|
|
|
dom.text(')');
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
dom.text(' – {');
|
|
|
|
|
|
dom.text(param.type);
|
|
|
|
|
|
dom.text('} – ');
|
|
|
|
|
|
});
|
|
|
|
|
|
dom.html(param.description);
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
html_usage_returns: function(dom) {
|
|
|
|
|
|
var self = this;
|
|
|
|
|
|
if (self.returns) {
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.h('Returns', function() {
|
2011-01-18 21:56:04 +00:00
|
|
|
|
dom.tag('code', '{' + self.returns.type + '}');
|
2010-12-22 23:44:27 +00:00
|
|
|
|
dom.text('– ');
|
|
|
|
|
|
dom.html(self.returns.description);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
|
|
|
|
|
html_usage_this: function(dom) {
|
|
|
|
|
|
var self = this;
|
|
|
|
|
|
if (self['this']) {
|
|
|
|
|
|
dom.h(function(dom){
|
|
|
|
|
|
dom.html("Method's <code>this</code>");
|
|
|
|
|
|
}, function(dom){
|
|
|
|
|
|
dom.html(self['this']);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
html_usage_function: function(dom){
|
|
|
|
|
|
var self = this;
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.h('Usage', function() {
|
|
|
|
|
|
dom.code(function() {
|
2011-07-16 00:19:57 +00:00
|
|
|
|
dom.text(self.name.split('service.').pop());
|
2010-12-22 23:44:27 +00:00
|
|
|
|
dom.text('(');
|
2011-01-13 18:35:26 +00:00
|
|
|
|
self.parameters(dom, ', ');
|
2010-12-22 23:44:27 +00:00
|
|
|
|
dom.text(');');
|
|
|
|
|
|
});
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
self.html_usage_parameters(dom);
|
2011-01-19 20:16:21 +00:00
|
|
|
|
self.html_usage_this(dom);
|
2010-12-22 23:44:27 +00:00
|
|
|
|
self.html_usage_returns(dom);
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2011-04-20 20:44:34 +00:00
|
|
|
|
html_usage_property: function(dom){
|
|
|
|
|
|
var self = this;
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.h('Usage', function() {
|
|
|
|
|
|
dom.code(function() {
|
2011-04-20 20:44:34 +00:00
|
|
|
|
dom.text(self.name);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
self.html_usage_returns(dom);
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
html_usage_directive: function(dom){
|
|
|
|
|
|
var self = this;
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.h('Usage', function() {
|
|
|
|
|
|
dom.tag('pre', {'class':"brush: js; html-script: true;"}, function() {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
dom.text('<' + self.element + ' ');
|
|
|
|
|
|
dom.text(self.shortName);
|
2011-01-26 05:55:11 +00:00
|
|
|
|
if (self.param.length) {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
dom.text('="' + self.param[0].name + '"');
|
|
|
|
|
|
}
|
|
|
|
|
|
dom.text('>\n ...\n');
|
|
|
|
|
|
dom.text('</' + self.element + '>');
|
|
|
|
|
|
});
|
|
|
|
|
|
self.html_usage_parameters(dom);
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
html_usage_filter: function(dom){
|
|
|
|
|
|
var self = this;
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.h('Usage', function() {
|
|
|
|
|
|
dom.h('In HTML Template Binding', function() {
|
|
|
|
|
|
dom.tag('code', function() {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
dom.text('{{ ');
|
|
|
|
|
|
dom.text(self.shortName);
|
|
|
|
|
|
dom.text('_expression | ');
|
|
|
|
|
|
dom.text(self.shortName);
|
2011-01-13 18:35:26 +00:00
|
|
|
|
self.parameters(dom, ':', true);
|
2010-12-22 23:44:27 +00:00
|
|
|
|
dom.text(' }}');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.h('In JavaScript', function() {
|
|
|
|
|
|
dom.tag('code', function() {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
dom.text('angular.filter.');
|
|
|
|
|
|
dom.text(self.shortName);
|
|
|
|
|
|
dom.text('(');
|
2011-01-13 18:35:26 +00:00
|
|
|
|
self.parameters(dom, ', ');
|
2010-12-22 23:44:27 +00:00
|
|
|
|
dom.text(')');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
self.html_usage_parameters(dom);
|
2011-01-19 20:16:21 +00:00
|
|
|
|
self.html_usage_this(dom);
|
2010-12-22 23:44:27 +00:00
|
|
|
|
self.html_usage_returns(dom);
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2011-09-08 20:56:29 +00:00
|
|
|
|
html_usage_inputType: function(dom){
|
2010-12-22 23:44:27 +00:00
|
|
|
|
var self = this;
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.h('Usage', function() {
|
|
|
|
|
|
dom.code(function() {
|
2011-09-08 20:56:29 +00:00
|
|
|
|
dom.text('<input type="' + self.shortName + '"');
|
|
|
|
|
|
(self.param||[]).forEach(function(param){
|
|
|
|
|
|
dom.text('\n ');
|
|
|
|
|
|
dom.text(param.optional ? ' [' : ' ');
|
|
|
|
|
|
dom.text(param.name);
|
|
|
|
|
|
dom.text(BOOLEAN_ATTR[param.name] ? '' : '="..."');
|
|
|
|
|
|
dom.text(param.optional ? ']' : '');
|
2010-12-22 23:44:27 +00:00
|
|
|
|
});
|
2011-09-08 20:56:29 +00:00
|
|
|
|
dom.text('>');
|
2010-12-22 23:44:27 +00:00
|
|
|
|
});
|
|
|
|
|
|
self.html_usage_parameters(dom);
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
html_usage_widget: function(dom){
|
|
|
|
|
|
var self = this;
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.h('Usage', function() {
|
|
|
|
|
|
dom.h('In HTML Template Binding', function() {
|
|
|
|
|
|
dom.code(function() {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
if (self.shortName.match(/^@/)) {
|
|
|
|
|
|
dom.text('<');
|
|
|
|
|
|
dom.text(self.element);
|
|
|
|
|
|
dom.text(' ');
|
|
|
|
|
|
dom.text(self.shortName.substring(1));
|
2011-01-26 05:55:11 +00:00
|
|
|
|
if (self.param.length) {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
dom.text('="');
|
|
|
|
|
|
dom.text(self.param[0].name);
|
|
|
|
|
|
dom.text('"');
|
|
|
|
|
|
}
|
|
|
|
|
|
dom.text('>\n ...\n</');
|
|
|
|
|
|
dom.text(self.element);
|
|
|
|
|
|
dom.text('>');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
dom.text('<');
|
|
|
|
|
|
dom.text(self.shortName);
|
|
|
|
|
|
(self.param||[]).forEach(function(param){
|
2011-09-08 20:56:29 +00:00
|
|
|
|
dom.text('\n ');
|
|
|
|
|
|
dom.text(param.optional ? ' [' : ' ');
|
|
|
|
|
|
dom.text(param.name);
|
|
|
|
|
|
dom.text(BOOLEAN_ATTR[param.name] ? '' : '="..."');
|
|
|
|
|
|
dom.text(param.optional ? ']' : '');
|
2010-12-22 23:44:27 +00:00
|
|
|
|
});
|
|
|
|
|
|
dom.text('></');
|
|
|
|
|
|
dom.text(self.shortName);
|
|
|
|
|
|
dom.text('>');
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
self.html_usage_parameters(dom);
|
|
|
|
|
|
self.html_usage_returns(dom);
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
html_usage_overview: function(dom){
|
2011-01-26 05:55:11 +00:00
|
|
|
|
dom.html(this.description);
|
2010-12-22 23:44:27 +00:00
|
|
|
|
},
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
html_usage_service: function(dom){
|
2011-02-07 05:17:58 +00:00
|
|
|
|
var self = this;
|
2011-01-26 05:55:11 +00:00
|
|
|
|
|
2011-02-07 05:17:58 +00:00
|
|
|
|
if (this.param.length) {
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.h('Usage', function() {
|
|
|
|
|
|
dom.code(function() {
|
2011-02-07 05:17:58 +00:00
|
|
|
|
dom.text(self.name.split('.').pop());
|
|
|
|
|
|
dom.text('(');
|
|
|
|
|
|
self.parameters(dom, ', ');
|
|
|
|
|
|
dom.text(');');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
self.html_usage_parameters(dom);
|
|
|
|
|
|
self.html_usage_this(dom);
|
|
|
|
|
|
self.html_usage_returns(dom);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-01-26 05:55:11 +00:00
|
|
|
|
dom.h('Methods', this.methods, function(method){
|
|
|
|
|
|
var signature = (method.param || []).map(property('name'));
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.h(method.shortName + '(' + signature.join(', ') + ')', method, function() {
|
2011-01-26 05:55:11 +00:00
|
|
|
|
dom.html(method.description);
|
|
|
|
|
|
method.html_usage_parameters(dom);
|
2011-07-16 00:20:54 +00:00
|
|
|
|
self.html_usage_this(dom);
|
|
|
|
|
|
method.html_usage_returns(dom);
|
|
|
|
|
|
|
2011-02-01 00:21:29 +00:00
|
|
|
|
dom.h('Example', method.example, dom.html);
|
2011-01-26 05:55:11 +00:00
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
dom.h('Properties', this.properties, function(property){
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.h(property.name, function() {
|
2011-02-07 04:44:55 +00:00
|
|
|
|
dom.html(property.description);
|
2011-02-01 00:21:29 +00:00
|
|
|
|
dom.h('Example', property.example, dom.html);
|
2011-01-26 05:55:11 +00:00
|
|
|
|
});
|
|
|
|
|
|
});
|
2011-08-26 05:23:10 +00:00
|
|
|
|
dom.h('Events', this.events, function(event){
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.h(event.shortName, event, function() {
|
2011-08-26 05:23:10 +00:00
|
|
|
|
dom.html(event.description);
|
2011-09-08 20:56:29 +00:00
|
|
|
|
if (event.type == 'listen') {
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.tag('div', {class:'inline'}, function() {
|
2011-09-08 20:56:29 +00:00
|
|
|
|
dom.h('Listen on:', event.target);
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.tag('div', {class:'inline'}, function() {
|
2011-09-08 20:56:29 +00:00
|
|
|
|
dom.h('Type:', event.type);
|
|
|
|
|
|
});
|
2011-10-07 18:27:49 +00:00
|
|
|
|
dom.tag('div', {class:'inline'}, function() {
|
2011-09-08 20:56:29 +00:00
|
|
|
|
dom.h('Target:', event.target);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2011-08-26 05:23:10 +00:00
|
|
|
|
event.html_usage_parameters(dom);
|
|
|
|
|
|
self.html_usage_this(dom);
|
|
|
|
|
|
|
|
|
|
|
|
dom.h('Example', event.example, dom.html);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
2011-01-13 18:35:26 +00:00
|
|
|
|
},
|
2010-12-22 23:44:27 +00:00
|
|
|
|
|
2011-01-13 18:35:26 +00:00
|
|
|
|
parameters: function(dom, separator, skipFirst, prefix) {
|
|
|
|
|
|
var sep = prefix ? separator : '';
|
|
|
|
|
|
(this.param||[]).forEach(function(param, i){
|
|
|
|
|
|
if (!(skipFirst && i==0)) {
|
|
|
|
|
|
if (param.optional) {
|
|
|
|
|
|
dom.text('[' + sep + param.name + ']');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
dom.text(sep + param.name);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
sep = separator;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
};
|
|
|
|
|
|
//////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////
|
|
|
|
|
|
function scenarios(docs){
|
|
|
|
|
|
var specs = [];
|
2011-07-15 01:28:15 +00:00
|
|
|
|
|
2011-09-01 05:59:47 +00:00
|
|
|
|
specs.push('describe("angular+jqlite", function() {');
|
2011-09-21 00:47:12 +00:00
|
|
|
|
appendSpecs('index-nocache.html#!/');
|
2011-07-15 01:28:15 +00:00
|
|
|
|
specs.push('});');
|
|
|
|
|
|
|
|
|
|
|
|
specs.push('');
|
|
|
|
|
|
specs.push('');
|
|
|
|
|
|
|
2011-09-01 05:59:47 +00:00
|
|
|
|
specs.push('describe("angular+jquery", function() {');
|
2011-09-21 00:47:12 +00:00
|
|
|
|
appendSpecs('index-jq-nocache.html#!/');
|
2011-07-15 01:28:15 +00:00
|
|
|
|
specs.push('});');
|
|
|
|
|
|
|
|
|
|
|
|
return specs.join('\n');
|
|
|
|
|
|
|
2011-08-30 09:47:24 +00:00
|
|
|
|
function appendSpecs(urlPrefix) {
|
2011-07-15 01:28:15 +00:00
|
|
|
|
docs.forEach(function(doc){
|
2011-10-07 18:27:49 +00:00
|
|
|
|
specs.push(' describe("' + doc.section + '/' + doc.id + '", function() {');
|
|
|
|
|
|
specs.push(' beforeEach(function() {');
|
2011-08-30 09:47:24 +00:00
|
|
|
|
specs.push(' browser().navigateTo("' + urlPrefix + doc.section + '/' + doc.id + '");');
|
2011-07-15 01:28:15 +00:00
|
|
|
|
specs.push(' });');
|
|
|
|
|
|
specs.push(' ');
|
|
|
|
|
|
doc.scenarios.forEach(function(scenario){
|
|
|
|
|
|
specs.push(indent(trim(scenario), 4));
|
|
|
|
|
|
specs.push('');
|
|
|
|
|
|
});
|
|
|
|
|
|
specs.push('});');
|
2011-01-26 05:55:11 +00:00
|
|
|
|
specs.push('');
|
|
|
|
|
|
});
|
2011-07-15 01:28:15 +00:00
|
|
|
|
}
|
2010-12-22 23:44:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////
|
|
|
|
|
|
function metadata(docs){
|
|
|
|
|
|
var words = [];
|
|
|
|
|
|
docs.forEach(function(doc){
|
2011-01-26 05:55:11 +00:00
|
|
|
|
var path = (doc.name || '').split(/(\.|\:\s+)/);
|
|
|
|
|
|
for ( var i = 1; i < path.length; i++) {
|
|
|
|
|
|
path.splice(i, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
var depth = path.length - 1;
|
|
|
|
|
|
var shortName = path.pop();
|
2010-12-22 23:44:27 +00:00
|
|
|
|
words.push({
|
2011-04-29 22:18:27 +00:00
|
|
|
|
section: doc.section,
|
2011-01-26 05:55:11 +00:00
|
|
|
|
id: doc.id,
|
|
|
|
|
|
name: doc.name,
|
|
|
|
|
|
depth: depth,
|
|
|
|
|
|
shortName: shortName,
|
2010-12-22 23:44:27 +00:00
|
|
|
|
type: doc.ngdoc,
|
|
|
|
|
|
keywords:doc.keywords()
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
words.sort(keywordSort);
|
|
|
|
|
|
return words;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-01-26 05:55:11 +00:00
|
|
|
|
var KEYWORD_PRIORITY = {
|
2011-04-29 22:18:27 +00:00
|
|
|
|
'.index': 1,
|
2011-02-01 18:01:02 +00:00
|
|
|
|
'.guide': 2,
|
2011-01-26 05:55:11 +00:00
|
|
|
|
'.angular': 7,
|
|
|
|
|
|
'.angular.Array': 7,
|
|
|
|
|
|
'.angular.Object': 7,
|
|
|
|
|
|
'.angular.directive': 7,
|
|
|
|
|
|
'.angular.filter': 7,
|
|
|
|
|
|
'.angular.scope': 7,
|
|
|
|
|
|
'.angular.service': 7,
|
2011-09-08 20:56:29 +00:00
|
|
|
|
'.angular.inputType': 7,
|
2011-06-07 00:22:05 +00:00
|
|
|
|
'.angular.widget': 7,
|
2011-06-07 14:44:49 +00:00
|
|
|
|
'.angular.mock': 8,
|
|
|
|
|
|
'.dev_guide.overview': 1,
|
|
|
|
|
|
'.dev_guide.bootstrap': 2,
|
|
|
|
|
|
'.dev_guide.mvc': 3,
|
|
|
|
|
|
'.dev_guide.scopes': 4,
|
|
|
|
|
|
'.dev_guide.compiler': 5,
|
|
|
|
|
|
'.dev_guide.templates': 6,
|
|
|
|
|
|
'.dev_guide.services': 7,
|
|
|
|
|
|
'.dev_guide.di': 8,
|
|
|
|
|
|
'.dev_guide.unit-testing': 9
|
2011-01-26 05:55:11 +00:00
|
|
|
|
};
|
|
|
|
|
|
function keywordSort(a, b){
|
|
|
|
|
|
function mangleName(doc) {
|
|
|
|
|
|
var path = doc.id.split(/\./);
|
|
|
|
|
|
var mangled = [];
|
|
|
|
|
|
var partialName = '';
|
|
|
|
|
|
path.forEach(function(name){
|
|
|
|
|
|
partialName += '.' + name;
|
|
|
|
|
|
mangled.push(KEYWORD_PRIORITY[partialName] || 5);
|
|
|
|
|
|
mangled.push(name);
|
|
|
|
|
|
});
|
2011-04-29 22:18:27 +00:00
|
|
|
|
return doc.section + '/' + mangled.join('.');
|
2010-12-22 23:44:27 +00:00
|
|
|
|
}
|
2011-01-26 05:55:11 +00:00
|
|
|
|
var nameA = mangleName(a);
|
|
|
|
|
|
var nameB = mangleName(b);
|
|
|
|
|
|
return nameA < nameB ? -1 : (nameA > nameB ? 1 : 0);
|
2010-12-22 23:44:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////
|
2011-02-07 23:55:23 +00:00
|
|
|
|
function trim(text) {
|
|
|
|
|
|
var MAX_INDENT = 9999;
|
2010-12-22 23:44:27 +00:00
|
|
|
|
var empty = RegExp.prototype.test.bind(/^\s*$/);
|
|
|
|
|
|
var lines = text.split('\n');
|
2011-02-07 23:55:23 +00:00
|
|
|
|
var minIndent = MAX_INDENT;
|
|
|
|
|
|
var indentRegExp;
|
|
|
|
|
|
var ignoreLine = (lines[0][0] != ' ' && lines.length > 1);
|
|
|
|
|
|
// ignore first line if it has no indentation and there is more than one line
|
|
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
lines.forEach(function(line){
|
2011-02-07 23:55:23 +00:00
|
|
|
|
if (ignoreLine) {
|
|
|
|
|
|
ignoreLine = false;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var indent = line.match(/^\s*/)[0].length;
|
|
|
|
|
|
if (indent > 0 || minIndent == MAX_INDENT) {
|
|
|
|
|
|
minIndent = Math.min(minIndent, indent);
|
|
|
|
|
|
}
|
2010-12-22 23:44:27 +00:00
|
|
|
|
});
|
2011-02-07 23:55:23 +00:00
|
|
|
|
|
|
|
|
|
|
indentRegExp = new RegExp('^\\s{0,' + minIndent + '}');
|
|
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
for ( var i = 0; i < lines.length; i++) {
|
2011-02-07 23:55:23 +00:00
|
|
|
|
lines[i] = lines[i].replace(indentRegExp, '');
|
2010-12-22 23:44:27 +00:00
|
|
|
|
}
|
2011-02-07 23:55:23 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
// remove leading lines
|
|
|
|
|
|
while (empty(lines[0])) {
|
|
|
|
|
|
lines.shift();
|
|
|
|
|
|
}
|
2011-02-07 23:55:23 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
// remove trailing
|
|
|
|
|
|
while (empty(lines[lines.length - 1])) {
|
|
|
|
|
|
lines.pop();
|
|
|
|
|
|
}
|
|
|
|
|
|
return lines.join('\n');
|
2011-02-07 23:55:23 +00:00
|
|
|
|
}
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2011-02-07 23:55:23 +00:00
|
|
|
|
function indent(text, spaceCount) {
|
|
|
|
|
|
var lines = text.split('\n'),
|
|
|
|
|
|
indent = '',
|
|
|
|
|
|
fixedLines = [];
|
|
|
|
|
|
|
|
|
|
|
|
while(spaceCount--) indent += ' ';
|
|
|
|
|
|
|
|
|
|
|
|
lines.forEach(function(line) {
|
|
|
|
|
|
fixedLines.push(indent + line);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return fixedLines.join('\n');
|
2010-12-22 23:44:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////
|
|
|
|
|
|
function merge(docs){
|
2011-05-18 11:31:26 +00:00
|
|
|
|
var byFullId = {};
|
2011-05-17 20:12:23 +00:00
|
|
|
|
|
2011-10-07 18:27:49 +00:00
|
|
|
|
docs.forEach(function(doc) {
|
2011-05-17 20:12:23 +00:00
|
|
|
|
byFullId[doc.section + '/' + doc.id] = doc;
|
2010-12-22 23:44:27 +00:00
|
|
|
|
});
|
2011-05-18 11:31:26 +00:00
|
|
|
|
|
|
|
|
|
|
for(var i = 0; i < docs.length;) {
|
|
|
|
|
|
var doc = docs[i];
|
|
|
|
|
|
|
|
|
|
|
|
// check links - do they exist ?
|
|
|
|
|
|
doc.links.forEach(function(link) {
|
2011-05-19 14:22:13 +00:00
|
|
|
|
if (!byFullId[link]) console.log('WARNING: In ' + doc.section + '/' + doc.id + ', non existing link: "' + link + '"');
|
2011-05-18 11:31:26 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// merge into parents
|
2011-08-26 05:23:10 +00:00
|
|
|
|
if (findParent(doc, 'method') || findParent(doc, 'property') || findParent(doc, 'event')) {
|
2010-12-22 23:44:27 +00:00
|
|
|
|
docs.splice(i, 1);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
i++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2011-05-18 09:13:46 +00:00
|
|
|
|
|
2011-05-18 11:31:26 +00:00
|
|
|
|
function findParent(doc, name) {
|
|
|
|
|
|
var parentName = doc[name + 'Of'];
|
2010-12-22 23:44:27 +00:00
|
|
|
|
if (!parentName) return false;
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2011-05-18 11:31:26 +00:00
|
|
|
|
var parent = byFullId['api/' + parentName];
|
2011-01-19 20:16:21 +00:00
|
|
|
|
if (!parent)
|
|
|
|
|
|
throw new Error("No parent named '" + parentName + "' for '" +
|
2010-12-22 23:44:27 +00:00
|
|
|
|
doc.name + "' in @" + name + "Of.");
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
var listName = (name + 's').replace(/ys$/, 'ies');
|
|
|
|
|
|
var list = parent[listName] = (parent[listName] || []);
|
|
|
|
|
|
list.push(doc);
|
|
|
|
|
|
list.sort(orderByName);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2011-01-19 20:16:21 +00:00
|
|
|
|
|
2010-12-22 23:44:27 +00:00
|
|
|
|
function orderByName(a, b){
|
|
|
|
|
|
return a.name < b.name ? -1 : (a.name > b.name ? 1 : 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
function property(name) {
|
2011-01-19 20:16:21 +00:00
|
|
|
|
return function(value){
|
2010-12-22 23:44:27 +00:00
|
|
|
|
return value[name];
|
|
|
|
|
|
};
|
2011-01-19 20:16:21 +00:00
|
|
|
|
}
|