diff options
Diffstat (limited to 'docs/src/ngdoc.js')
| -rw-r--r-- | docs/src/ngdoc.js | 266 |
1 files changed, 175 insertions, 91 deletions
diff --git a/docs/src/ngdoc.js b/docs/src/ngdoc.js index 70411052..def665fa 100644 --- a/docs/src/ngdoc.js +++ b/docs/src/ngdoc.js @@ -5,7 +5,9 @@ var Showdown = require('../../lib/showdown').Showdown; var DOM = require('./dom.js').DOM; var htmlEscape = require('./dom.js').htmlEscape; +var Example = require('./example.js').Example; var NEW_LINE = /\n\r?/; +var globalID = 0; exports.trim = trim; exports.metadata = metadata; @@ -98,72 +100,85 @@ Doc.prototype = { if (!text) return text; var self = this, - IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:|\.|\/)/, - IS_ANGULAR = /^(api\/)?angular\./, - IS_HASH = /^#/, - parts = trim(text).split(/(<pre>[\s\S]*?<\/pre>|<doc:(\S*).*?>[\s\S]*?<\/doc:\2>)/); + IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:|\.|\/)/, + IS_ANGULAR = /^(api\/)?angular\./, + IS_HASH = /^#/, + parts = trim(text).split(/(<pre>[\s\S]*?<\/pre>|<doc:example(\S*).*?>[\s\S]*?<\/doc:example>|<example[^>]*>[\s\S]*?<\/example>)/), + seq = 0, + placeholderMap = {}; + + function placeholder(text) { + var id = 'REPLACEME' + (seq++); + placeholderMap[id] = text; + return id; + } parts.forEach(function(text, i) { + parts[i] = (text || ''). + replace(/<example(?:\s+module="([^"]*)")?(?:\s+deps="([^"]*)")?>([\s\S]*?)<\/example>/gmi, function(_, module, deps, content) { + var example = new Example(self.scenarios); + + example.setModule(module); + example.addDeps(deps); + content.replace(/<file\s+name="([^"]*)"\s*>([\s\S]*?)<\/file>/gmi, function(_, name, content) { + example.addSource(name, content); + }); + return placeholder(example.toHtml()); + }). + replace(/^<doc:example(\s+[^>]*)?>([\s\S]*)<\/doc:example>/mi, function(_, attrs, content) { + var html, script, scenario, + example = new Example(self.scenarios); + + example.setModule((attrs||'module=""').match(/^\s*module=["'](.*)["']\s*$/)[1]); + content. + replace(/<doc:source(\s+[^>]*)?>([\s\S]*)<\/doc:source>/mi, function(_, attrs, content) { + example.addSource('index.html', content. + replace(/<script>([\s\S]*)<\/script>/mi, function(_, script) { + example.addSource('script.js', script); + return ''; + }). + replace(/<style>([\s\S]*)<\/style>/mi, function(_, style) { + example.addSource('style.css', style); + return ''; + }) + ); + }). + replace(/(<doc:scenario>)([\s\S]*)(<\/doc:scenario>)/mi, function(_, before, content){ + example.addSource('scenario.js', content); + }); - 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; - } - - if (text.match(/^<pre>/)) { - text = text.replace(/^<pre>([\s\S]*)<\/pre>/mi, function(_, content){ - var clazz = 'brush: js;'; - if (content.match(/\<\w/)) { - // we are HTML - clazz += ' html-script: true;'; - } - return '<div ng:non-bindable><pre class="' + clazz +'">' + - content.replace(/</g, '<').replace(/>/g, '>') + - '</pre></div>'; + return placeholder(example.toHtml()); + }). + replace(/^<pre>([\s\S]*?)<\/pre>/mi, function(_, content){ + return placeholder( + '<pre class="prettyprint linenums">' + + content.replace(/</g, '<').replace(/>/g, '>') + + '</pre>'); + }). + replace(/<div([^>]*)><\/div>/, '<div$1>\n<\/div>'). + replace(/{@link\s+([^\s}]+)\s*([^}]*?)\s*}/g, function(_all, url, title){ + var isFullUrl = url.match(IS_URL), + isAngular = url.match(IS_ANGULAR), + isHash = url.match(IS_HASH), + absUrl = isHash + ? url + : (isFullUrl ? url : self.convertUrlToAbsolute(url)); + + if (!isFullUrl) self.links.push(absUrl); + + return '<a href="' + absUrl + '">' + + (isAngular ? '<code>' : '') + + (title || url).replace(/^#/g, '').replace(/\n/g, ' ') + + (isAngular ? '</code>' : '') + + '</a>'; }); - } else if (isDocWidget('example')) { - text = text.replace(/<doc:source(\s+[^>]*)?>([\s\S]*)<\/doc:source>/mi, - function(_, attrs, content){ - return '<pre class="doc-source"' + (attrs || '') +'>' + - htmlEscape(content) + - '</pre>'; - }); - text = text.replace(/(<doc:scenario>)([\s\S]*)(<\/doc:scenario>)/mi, - function(_, before, content){ - self.scenarios.push(content); - return '<pre class="doc-scenario">' + htmlEscape(content) + '</pre>'; - }); - } else if (!isDocWidget()) { - text = text.replace(/<angular\/>/gm, '<tt><angular/></tt>'); - text = text.replace(/{@link\s+([^\s}]+)\s*([^}]*?)\s*}/g, - function(_all, url, title){ - var isFullUrl = url.match(IS_URL), - isAngular = url.match(IS_ANGULAR), - isHash = url.match(IS_HASH), - absUrl = isHash - ? url - : (isFullUrl ? url : self.convertUrlToAbsolute(url)); - - if (!isFullUrl) self.links.push(absUrl); - - return '<a href="' + absUrl + '">' + - (isAngular ? '<code>' : '') + - (title || url).replace(/^#/g, '').replace(/\n/g, ' ') + - (isAngular ? '</code>' : '') + - '</a>'; - }); - text = new Showdown.converter().makeHtml(text); - } - parts[i] = text; }); - return parts.join(''); + text = parts.join(''); + text = new Showdown.converter().makeHtml(text); + text = text.replace(/(?:<p>)?(REPLACEME\d+)(?:<\/p>)?/g, function(_, id) { + return placeholderMap[id]; + }); + return text; }, parse: function() { @@ -200,7 +215,7 @@ Doc.prototype = { var text = trim(atText.join('\n')), match; if (atName == 'param') { match = text.match(/^\{([^}=]+)(=)?\}\s+(([^\s=]+)|\[(\S+)=([^\]]+)\])\s+(.*)/); - // 1 12 2 34 4 5 5 6 6 3 7 7 + // 1 12 2 34 4 5 5 6 6 3 7 7 if (!match) { throw new Error("Not a valid 'param' format: " + text); } @@ -233,11 +248,11 @@ Doc.prototype = { throw new Error("Not a valid 'property' format: " + text); } var property = new Doc({ - type: match[1], - name: match[2], - shortName: match[2], - description: self.markdown(text.replace(match[0], match[4])) - }); + type: match[1], + name: match[2], + shortName: match[2], + description: self.markdown(text.replace(match[0], match[4])) + }); self.properties.push(property); } else if(atName == 'eventType') { match = text.match(/^([^\s]*)\s+on\s+([\S\s]*)/); @@ -252,9 +267,9 @@ Doc.prototype = { html: function() { var dom = new DOM(), - self = this; + self = this; - dom.h(this.name, function() { + dom.h(title(this.name), function() { notice('deprecated', 'Deprecated API', self.deprecated); if (self.ngdoc != 'overview') { @@ -336,9 +351,11 @@ Doc.prototype = { html_usage_function: function(dom){ var self = this; + var name = self.name.match(/^angular(\.mock)?\.(\w+)$/) ? self.name : self.name.split(/\./).pop() + dom.h('Usage', function() { dom.code(function() { - dom.text(self.name.split(/\./).pop()); + dom.text(name); dom.text('('); self.parameters(dom, ', '); dom.text(');'); @@ -549,12 +566,12 @@ Doc.prototype = { dom.div({class:'member property'}, function(){ dom.h('Properties', self.properties, function(property){ dom.h(property.shortName, function() { - dom.html(property.description); - if (!property.html_usage_returns) { - console.log(property); - } - property.html_usage_returns(dom); - dom.h('Example', property.example, dom.html); + dom.html(property.description); + if (!property.html_usage_returns) { + console.log(property); + } + property.html_usage_returns(dom); + dom.h('Example', property.example, dom.html); }); }); }); @@ -605,6 +622,74 @@ Doc.prototype = { ////////////////////////////////////////////////////////// +var GLOBALS = /^angular\.([^\.]*)$/, + MODULE = /^angular\.module\.([^\.]*)$/, + MODULE_MOCK = /^angular\.mock\.([^\.]*)$/, + MODULE_DIRECTIVE = /^angular\.module\.([^\.]*)(?:\.\$compileProvider)?\.directive\.([^\.]*)$/, + MODULE_DIRECTIVE_INPUT = /^angular\.module\.([^\.]*)\.\$compileProvider\.directive\.input\.([^\.]*)$/, + MODULE_FILTER = /^angular\.module\.([^\.]*)\.\$?filter\.([^\.]*)$/, + MODULE_SERVICE = /^angular\.module\.([^\.]*)\.([^\.]*?)(Provider)?$/, + MODULE_TYPE = /^angular\.module\.([^\.]*)\..*\.([A-Z][^\.]*)$/; + +function title(text) { + if (!text) return text; + var match, + module, + type, + name; + + if (text == 'angular.Module') { + module = 'ng'; + name = 'Module'; + type = 'Type'; + } else if (match = text.match(GLOBALS)) { + module = 'ng'; + name = 'angular.' + match[1]; + type = 'API'; + } else if (match = text.match(MODULE)) { + module = match[1]; + } else if (match = text.match(MODULE_MOCK)) { + module = 'ng'; + name = 'angular.mock.' + match[1]; + type = 'API'; + } else if (match = text.match(MODULE_DIRECTIVE)) { + module = match[1]; + name = match[2]; + type = 'directive'; + } else if (match = text.match(MODULE_DIRECTIVE_INPUT)) { + module = match[1]; + name = 'input [' + match[2] + ']'; + type = 'directive'; + } else if (match = text.match(MODULE_FILTER)) { + module = match[1]; + name = match[2]; + type = 'filter'; + } else if (match = text.match(MODULE_SERVICE)) { + module = match[1]; + name = match[2] + (match[3] || ''); + type = 'service'; + } else if (match = text.match(MODULE_TYPE)) { + module = match[1]; + name = match[2]; + type = 'type'; + } else { + return text; + } + return function() { + this.tag('code', name); + this.tag('span', { class: 'hint'}, function() { + if (type) { + this.text('('); + this.text(type); + this.text(' in module '); + this.tag('code', module); + this.text(')'); + } + }); + }; +} + + function scenarios(docs){ var specs = []; @@ -629,7 +714,7 @@ function scenarios(docs){ specs.push(' });'); specs.push(' '); doc.scenarios.forEach(function(scenario){ - specs.push(indent(trim(scenario), 4)); + specs.push(indentCode(trim(scenario), 4)); specs.push(''); }); specs.push('});'); @@ -647,13 +732,16 @@ function metadata(docs){ for ( var i = 1; i < path.length; i++) { path.splice(i, 1); } - var depth = path.length - 1; var shortName = path.pop(); + + if (path.pop() == 'input') { + shortName = 'input [' + shortName + ']'; + } + words.push({ section: doc.section, id: doc.id, - name: doc.name, - depth: depth, + name: title(doc.name), shortName: shortName, type: doc.ngdoc, keywords:doc.keywords() @@ -669,12 +757,8 @@ var KEYWORD_PRIORITY = { '.angular': 7, '.angular.Module': 7, '.angular.module': 8, - '.angular.module.ng.$filter': 7, - '.angular.module.ng.$rootScope.Scope': 7, - '.angular.module.ng': 7, - '.angular.mock': 8, - '.angular.directive': 6, - '.angular.module.ngMock': 8, + '.angular.module.ng': 2, + '.angular.module.AUTO': 1, '.dev_guide.overview': 1, '.dev_guide.bootstrap': 2, '.dev_guide.bootstrap.auto_bootstrap': 1, @@ -718,7 +802,7 @@ function trim(text) { 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 + // ignore first line if it has no indentation and there is more than one line lines.forEach(function(line){ if (ignoreLine) { @@ -750,10 +834,10 @@ function trim(text) { return lines.join('\n'); } -function indent(text, spaceCount) { +function indentCode(text, spaceCount) { var lines = text.split('\n'), - indent = '', - fixedLines = []; + indent = '', + fixedLines = []; while(spaceCount--) indent += ' '; @@ -802,7 +886,7 @@ function merge(docs){ var parent = byFullId['api/' + parentName]; if (!parent) throw new Error("No parent named '" + parentName + "' for '" + - doc.name + "' in @" + name + "Of."); + doc.name + "' in @" + name + "Of."); var listName = (name + 's').replace(/ys$/, 'ies'); var list = parent[listName] = (parent[listName] || []); |
