/**
* All parsing/transformation code goes here. All code here should be sync to ease testing.
*/varShowdown=require('showdown').Showdown;varDOM=require('dom.js').DOM;varhtmlEscape=require('dom.js').htmlEscape;varNEW_LINE=/\n\r?/;exports.trim=trim;exports.metadata=metadata;exports.scenarios=scenarios;exports.merge=merge;exports.Doc=Doc;//////////////////////////////////////////////////////////
functionDoc(text,file,line){if(typeoftext=='object'){for(varkeyintext){this[key]=text[key];}}else{this.text=text;this.file=file;this.line=line;}this.scenarios=this.scenarios||[];this.requires=this.requires||[];this.param=this.param||[];this.properties=this.properties||[];this.methods=this.methods||[];this.links=this.links||[];}Doc.METADATA_IGNORE=(function(){varwords=require('fs').readFileSync(__dirname+'/ignore.words','utf8');returnwords.toString().split(/[,\s\n\r]+/gm);})();Doc.prototype={keywords:functionkeywords(){varkeywords={};Doc.METADATA_IGNORE.forEach(function(ignore){keywords[ignore]=true;});varwords=[];vartokens=this.text.toLowerCase().split(/[,\.\`\'\"\s]+/mg);tokens.forEach(function(key){varmatch=key.match(/^(([\$\_a-z]|ng\:)[\w\_\-]{2,})/);if(match){key=match[1];if(!keywords[key]){keywords[key]=true;words.push(key);}}});words.sort();returnwords.join(' ');},/**
* 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
*/convertUrlToAbsolute:function(url){if(url.substr(-1)=='/')returnurl+'index';if(url.match(/\//))returnurl;returnthis.section+'/'+url;},markdown:function(text){if(!text)returntext;varself=this,IS_URL=/^(https?:\/\/|ftps?:\/\/|mailto:|\.|\/)/,IS_ANGULAR=/^(api\/)?angular\./,parts=trim(text).split(/(<pre>[\s\S]*?<\/pre>|<doc:(\S*).*?>[\s\S]*?<\/doc:\2>)/);parts.forEach(function(text,i){functionisDocWidget(name){if((i+1)%3!=2)returnfalse;if(name)returnparts[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){varclazz='brush: js;';if(content.match(/\<\w/)){// we are HTML
clazz+=' html-script: true;';}return'<div ng:non-bindable><pre class="'+clazz+'">'+content.replace(