diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/angular.filter.ngdoc | 15 | ||||
| -rw-r--r-- | docs/angular.formatter.ngdoc | 70 | ||||
| -rw-r--r-- | docs/angular.service.ngdoc | 93 | ||||
| -rw-r--r-- | docs/angular.validator.ngdoc | 44 | ||||
| -rw-r--r-- | docs/angular.widget.ngdoc | 33 | ||||
| -rw-r--r-- | docs/spec/domSpec.js | 28 | ||||
| -rw-r--r-- | docs/spec/ngdocSpec.js | 70 | ||||
| -rw-r--r-- | docs/src/dom.js | 19 | ||||
| -rw-r--r-- | docs/src/ngdoc.js | 118 | 
9 files changed, 214 insertions, 276 deletions
| diff --git a/docs/angular.filter.ngdoc b/docs/angular.filter.ngdoc index 9d1191c5..5d4f5940 100644 --- a/docs/angular.filter.ngdoc +++ b/docs/angular.filter.ngdoc @@ -46,12 +46,13 @@ You can use these variables in the function:    the DOM in addition to transforming the input. -@exampleDescription +@example   The following example filter reverses a text string. In addition, it conditionally makes the   text upper-case (to demonstrate optional arguments) and assigns color (to demonstrate DOM   modification). -@example +<doc:example> + <doc:source>     <script type="text/javascript">       angular.filter('reverse', function(input, uppercase, color) {         var out = ""; @@ -73,4 +74,14 @@ You can use these variables in the function:     Reverse: {{text|reverse}}<br>     Reverse + uppercase: {{text|reverse:true}}<br>     Reverse + uppercase + blue:  {{text|reverse:true:"blue"}} + </doc:source> + <doc:scenario> +  it('should reverse text', function(){ +    expect(binding('text|reverse')).toEqual('olleh'); +    input('text').enter('ABC'); +    expect(binding('text|reverse')).toEqual('CBA'); +  }); + </doc:scenario> +</doc:example> + diff --git a/docs/angular.formatter.ngdoc b/docs/angular.formatter.ngdoc index 2f4433cf..83371c38 100644 --- a/docs/angular.formatter.ngdoc +++ b/docs/angular.formatter.ngdoc @@ -37,42 +37,46 @@ angular.formatter('reverse', {  </pre>  @example -<script type="text/javascript"> -function reverse(text) { -  var reversed = []; -  for (var i = 0; i < text.length; i++) { -    reversed.unshift(text.charAt(i)); -  } -  return reversed.join(''); -} - -angular.formatter('reverse', { -  parse: function(value){ -    return reverse(value||'').toUpperCase(); -  }, -  format: function(value){ -    return reverse(value||'').toLowerCase(); +<doc:example> + <doc:source> +  <script type="text/javascript"> +  function reverse(text) { +    var reversed = []; +    for (var i = 0; i < text.length; i++) { +      reversed.unshift(text.charAt(i)); +    } +    return reversed.join('');    } -}); -</script> -Formatted: -<input type="text" name="data" value="angular" ng:format="reverse"/> -<br/> +  angular.formatter('reverse', { +    parse: function(value){ +      return reverse(value||'').toUpperCase(); +    }, +    format: function(value){ +      return reverse(value||'').toLowerCase(); +    } +  }); +  </script> -Stored: -<input type="text" name="data"/><br/> -<pre>{{data}}</pre> +  Formatted: +  <input type="text" name="data" value="angular" ng:format="reverse"/> +  <br/> +  Stored: +  <input type="text" name="data"/><br/> +  <pre>{{data}}</pre> + </doc:source> + <doc:scenario> +  it('should store reverse', function(){ +   expect(element('.doc-example input:first').val()).toEqual('angular'); +   expect(element('.doc-example input:last').val()).toEqual('RALUGNA'); -@scenario -it('should store reverse', function(){ - expect(element('.doc-example input:first').val()).toEqual('angular'); - expect(element('.doc-example input:last').val()).toEqual('RALUGNA'); +   this.addFutureAction('change to XYZ', function($window, $document, done){ +     $document.elements('.doc-example input:last').val('XYZ').trigger('change'); +     done(); +   }); +   expect(element('.doc-example input:first').val()).toEqual('zyx'); +  }); + </doc:scenario> +</doc:example> - this.addFutureAction('change to XYZ', function($window, $document, done){ -   $document.elements('.doc-example input:last').val('XYZ').trigger('change'); -   done(); - }); - expect(element('.doc-example input:first').val()).toEqual('zyx'); -}); diff --git a/docs/angular.service.ngdoc b/docs/angular.service.ngdoc index 4e4810f9..0d3406e5 100644 --- a/docs/angular.service.ngdoc +++ b/docs/angular.service.ngdoc @@ -17,22 +17,22 @@ services if needed.  Like other core angular variables and identifiers, the built-in services always start with `$`. -  * `{@link angular.service.$browser $browser}` -  * `{@link angular.service.$window $window}` -  * `{@link angular.service.$document $document}` -  * `{@link angular.service.$location $location}` -  * `{@link angular.service.$log $log}` -  * `{@link angular.service.$exceptionHandler $exceptionHandler}` -  * `{@link angular.service.$hover $hover}` -  * `{@link angular.service.$invalidWidgets $invalidWidgets}` -  * `{@link angular.service.$route $route}` -  * `{@link angular.service.$xhr $xhr}` -  * `{@link angular.service.$xhr.error $xhr.error}` -  * `{@link angular.service.$xhr.bulk $xhr.bulk}` -  * `{@link angular.service.$xhr.cache $xhr.cache}` -  * `{@link angular.service.$resource $resource}` -  * `{@link angular.service.$cookies $cookies}` -  * `{@link angular.service.$cookieStore $cookieStore}` +  * {@link angular.service.$browser $browser} +  * {@link angular.service.$window $window} +  * {@link angular.service.$document $document} +  * {@link angular.service.$location $location} +  * {@link angular.service.$log $log} +  * {@link angular.service.$exceptionHandler $exceptionHandler} +  * {@link angular.service.$hover $hover} +  * {@link angular.service.$invalidWidgets $invalidWidgets} +  * {@link angular.service.$route $route} +  * {@link angular.service.$xhr $xhr} +  * {@link angular.service.$xhr.error $xhr.error} +  * {@link angular.service.$xhr.bulk $xhr.bulk} +  * {@link angular.service.$xhr.cache $xhr.cache} +  * {@link angular.service.$resource $resource} +  * {@link angular.service.$cookies $cookies} +  * {@link angular.service.$cookieStore $cookieStore}  # Writing your own custom services  angular provides only set of basic services, so for any nontrivial application it will be necessary @@ -138,29 +138,38 @@ myController.$inject = ['$location', '$log'];  </pre>  @example -<script type="text/javascript"> - angular.service('notify', function(win) { -   var msgs = []; -   return function(msg) { -     msgs.push(msg); -     if (msgs.length == 3) { -       win.alert(msgs.join("\n")); -       msgs = []; -     } -   }; - }, {$inject: ['$window']}); - - function myController(notifyService) { -   this.callNotify = function(msg) { -     notifyService(msg); -   }; - } - - myController.$inject = ['notify']; -</script> - -<div ng:controller="myController"> -<p>Let's try this simple notify service, injected into the controller...</p> -<input ng:init="message='test'" type="text" name="message" /> -<button ng:click="callNotify(message);">NOTIFY</button> -</div> +<doc:example> + <doc:source> +  <script type="text/javascript"> +   angular.service('notify', function(win) { +     var msgs = []; +     return function(msg) { +       msgs.push(msg); +       if (msgs.length == 3) { +         win.alert(msgs.join("\n")); +         msgs = []; +       } +     }; +   }, {$inject: ['$window']}); + +   function myController(notifyService) { +     this.callNotify = function(msg) { +       notifyService(msg); +     }; +   } + +   myController.$inject = ['notify']; +  </script> + +  <div ng:controller="myController"> +  <p>Let's try this simple notify service, injected into the controller...</p> +  <input ng:init="message='test'" type="text" name="message" /> +  <button ng:click="callNotify(message);">NOTIFY</button> +  </div> + </doc:source> + <doc:scenario> +   it('should test service', function(){ +     expect(element(':input[name=message]').val()).toEqual('test'); +   }); + </doc:scenario> +</doc:example> diff --git a/docs/angular.validator.ngdoc b/docs/angular.validator.ngdoc index 5501cc56..96b1e76a 100644 --- a/docs/angular.validator.ngdoc +++ b/docs/angular.validator.ngdoc @@ -50,24 +50,28 @@ UPS tracking number.    default.  @example -<script> - angular.validator('upsTrackingNo', function(input, format) { -   var regexp = new RegExp("^" + format.replace(/9/g, '\\d') + "$"); -   return input.match(regexp)?"":"The format must match " + format; - }); -</script> -<input type="text" name="trackNo" size="40" -      ng:validate="upsTrackingNo:'1Z 999 999 99 9999 999 9'" -      value="1Z 123 456 78 9012 345 6"/> - -@scenario -it('should validate correct UPS tracking number', function() { -  expect(element('input[name=trackNo]').attr('class')). -     not().toMatch(/ng-validation-error/); -}); +<doc:example> + <doc:source> +  <script> +   angular.validator('upsTrackingNo', function(input, format) { +     var regexp = new RegExp("^" + format.replace(/9/g, '\\d') + "$"); +     return input.match(regexp)?"":"The format must match " + format; +   }); +  </script> +  <input type="text" name="trackNo" size="40" +        ng:validate="upsTrackingNo:'1Z 999 999 99 9999 999 9'" +        value="1Z 123 456 78 9012 345 6"/> + </doc:source> + <doc:scenario> +  it('should validate correct UPS tracking number', function() { +    expect(element('input[name=trackNo]').attr('class')). +       not().toMatch(/ng-validation-error/); +  }); -it('should not validate in correct UPS tracking number', function() { -  input('trackNo').enter('foo'); -  expect(element('input[name=trackNo]').attr('class')). -     toMatch(/ng-validation-error/); -}); +  it('should not validate in correct UPS tracking number', function() { +    input('trackNo').enter('foo'); +    expect(element('input[name=trackNo]').attr('class')). +       toMatch(/ng-validation-error/); +  }); + </doc:scenario> +</doc:example> diff --git a/docs/angular.widget.ngdoc b/docs/angular.widget.ngdoc index 5942d933..6360f8ea 100644 --- a/docs/angular.widget.ngdoc +++ b/docs/angular.widget.ngdoc @@ -57,17 +57,22 @@ angular.widget('@my:watch', function(expression, compileElement) {  </pre>  @example -<script> -  angular.widget('my:time', function(compileElement){ -    compileElement.css('display', 'block'); -    return function(linkElement){ -      function update(){ -        linkElement.text('Current time is: ' + new Date()); -        setTimeout(update, 1000); -      } -      update(); -    }; -  }); -</script> -<my:time></my:time> - +<doc:example> + <doc:source> +  <script> +    angular.widget('my:time', function(compileElement){ +      compileElement.css('display', 'block'); +      return function(linkElement){ +        function update(){ +          linkElement.text('Current time is: ' + new Date()); +          setTimeout(update, 1000); +        } +        update(); +      }; +    }); +  </script> +  <my:time></my:time> + </doc:source> + <doc:scenario> + </doc:scenario> +</doc:example> diff --git a/docs/spec/domSpec.js b/docs/spec/domSpec.js index f9308ed6..3fda656f 100644 --- a/docs/spec/domSpec.js +++ b/docs/spec/domSpec.js @@ -7,34 +7,6 @@ describe('dom', function(){      dom = new DOM();    }); -  describe('example', function(){ -    it('should render code, live, test', function(){ -      dom.example('desc', 'src', 'scenario'); -      expect(dom.toString()).toEqual( -          '<h1>Example</h1>\n' + -          '<div class="example">' + -          'desc<doc:example><doc:source>src</doc:source>\n' + -          '<doc:scenario>scenario</doc:scenario>\n'+ -          '</doc:example>\n' + -          '</div>\n'); -    }); - -    it('should render non-live, test with description', function(){ -      dom.example('desc', 'src', false); -      expect(dom.toString()).toEqual('<h1>Example</h1>\n' + -          '<div class="example">' + -          'desc<div ng:non-bindable="">' + -          '<pre class="brush: js; html-script: true;">src</pre>\n' + -          '</div>\n' + -          '</div>\n'); -    }); - -    it('should render non-live, test', function(){ -      dom.example('desc', 'src', false); -      expect(dom.toString()).toContain('<pre class="brush: js; html-script: true;">src</pre>'); -    }); -  }); -    describe('h', function(){      it('should render using function', function(){ diff --git a/docs/spec/ngdocSpec.js b/docs/spec/ngdocSpec.js index d912bf3a..69bb5db3 100644 --- a/docs/spec/ngdocSpec.js +++ b/docs/spec/ngdocSpec.js @@ -74,12 +74,6 @@ describe('ngdoc', function(){          });        }); -      it('should not remove extra line breaks', function(){ -        var doc = new Doc('@example\nA\n\nB'); -        doc.parse(); -        expect(doc.example).toEqual('A\n\nB'); -      }); -        it('should parse filename', function(){          var doc = new Doc('@name friendly name', 'docs/a.b.ngdoc', 1);          doc.parse(0); @@ -128,32 +122,14 @@ describe('ngdoc', function(){      });    }); -  describe('scenario', function(){ -    it('should render from @example/@scenario and <doc:example>', function(){ -      var doc = new Doc( -          '@id id\n' + -          '@description <doc:example><doc:scenario>scenario0</doc:scenario></doc:example>' + -          '@example exempleText\n' + -          '@scenario scenario1\n' + -          '@scenario scenario2').parse(); -      expect(ngdoc.scenarios([doc])).toContain('describe("id"'); -      expect(ngdoc.scenarios([doc])).toContain('navigateTo("index.html#!id")'); -      expect(ngdoc.scenarios([doc])).toContain('\n  scenario0\n'); -      expect(ngdoc.scenarios([doc])).toContain('\n  scenario1\n'); -      expect(ngdoc.scenarios([doc])).toContain('\n  scenario2\n'); -    }); -  }); -    describe('markdown', function(){ -    var markdown = ngdoc.markdown; -      it('should replace angular in markdown', function(){ -      expect(markdown('<angular/>')). +      expect(new Doc().markdown('<angular/>')).          toEqual('<p><tt><angular/></tt></p>');      });      it('should not replace anything in <pre>, but escape the html escape the content', function(){ -      expect(markdown('bah x\n<pre>\n<b>angular</b>.k\n</pre>\n asdf x')). +      expect(new Doc().markdown('bah x\n<pre>\n<b>angular</b>.k\n</pre>\n asdf x')).          toEqual(              '<p>bah x</p>' +              '<div ng:non-bindable><pre class="brush: js; html-script: true;">\n' + @@ -163,7 +139,7 @@ describe('ngdoc', function(){      });      it('should replace text between two <pre></pre> tags', function() { -      expect(markdown('<pre>x</pre># One<pre>b</pre>')). +      expect(new Doc().markdown('<pre>x</pre># One<pre>b</pre>')).          toMatch('</div><h1>One</h1><div');      }); @@ -340,38 +316,20 @@ describe('ngdoc', function(){        it('should not remove {{}}', function(){          var doc = new Doc('@example text {{ abc }}');          doc.parse(); -        expect(doc.example).toEqual('text {{ abc }}'); +        expect(doc.example).toEqual('<p>text {{ abc }}</p>');        }); -    }); -    describe('@exampleDescription', function(){ -      it('should render example description', function(){ -        var doc = new Doc('@exampleDescription some\n text'); -        doc.ngdoc = "filter"; -        doc.parse(); -        expect(doc.html()).toContain('<p>some\n text'); -      }); - -      it('should alias @exampleDescription to @exampleDesc', function(){ -        var doc = new Doc('@exampleDesc some\n text'); -        doc.ngdoc = "filter"; -        doc.parse(); -        expect(doc.html()).toContain('<p>some\n text'); +      it('should support doc:example', function(){ +        var doc = new Doc('@ngdoc overview\n@example \n' + +            '<doc:example>\n' + +            ' <doc:source><escapeme></doc:source>\n' + +            ' <doc:scenario><scenario></doc:scenario>\n' + +            '</doc:example>').parse(); +        var html = doc.html(); +        expect(html).toContain('<doc:source><escapeme></doc:source>'); +        expect(html).toContain('<doc:scenario><scenario></doc:scenario>'); +        expect(doc.scenarios).toEqual(['<scenario>']);        }); - -      it('should render description in related method', function(){ -        var doc = new Doc('').parse(); -        doc.ngdoc = 'service'; -        doc.methods = [ -           new Doc('@ngdoc method\n@exampleDescription MDesc\n@example MExmp').parse()]; -        doc.properties = [ -          new Doc('@ngdoc property\n@exampleDescription PDesc\n@example PExmp').parse()]; -        expect(doc.html()).toContain('<p>MDesc</p><div ng:non-bindable="">' + -            '<pre class="brush: js; html-script: true;">MExmp</pre>'); -        expect(doc.html()).toContain('<p>PDesc</p><div ng:non-bindable="">' + -            '<pre class="brush: js; html-script: true;">PExmp</pre>'); -      }); -      });      describe('@depricated', function() { diff --git a/docs/src/dom.js b/docs/src/dom.js index 7708cbc9..4210d687 100644 --- a/docs/src/dom.js +++ b/docs/src/dom.js @@ -74,25 +74,8 @@ DOM.prototype = {      });    }, -  example: function(description, source, scenario) { -    if (description || source || scenario) { -      this.h('Example', function(){ -        if (description) -          this.html(description); -        if (scenario === false) { -          this.code(source); -        } else { -          this.tag('doc:example', function(){ -            if (source) this.tag('doc:source', source); -            if (scenario) this.tag('doc:scenario', scenario); -          }); -        } -      }); -    } -  }, -    h: function(heading, content, fn){ -    if (content==undefined || content && content.legth == 0) return; +    if (content==undefined || (content instanceof Array && content.length == 0)) return;      this.headingDepth++;      this.tag('h' + this.headingDepth, heading);      var className = typeof heading == 'string' diff --git a/docs/src/ngdoc.js b/docs/src/ngdoc.js index a3a037cd..d90f8d3d 100644 --- a/docs/src/ngdoc.js +++ b/docs/src/ngdoc.js @@ -7,7 +7,6 @@ var DOM = require('dom.js').DOM;  var htmlEscape = require('dom.js').htmlEscape;  var NEW_LINE = /\n\r?/; -exports.markdown = markdown;  exports.trim = trim;  exports.metadata = metadata;  exports.scenarios = scenarios; @@ -25,6 +24,11 @@ function Doc(text, file, line) {      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 || [];  }  Doc.METADATA_IGNORE = (function(){    var words = require('fs').readFileSync(__dirname + '/ignore.words', 'utf8'); @@ -53,16 +57,53 @@ Doc.prototype = {      return words.join(' ');    }, +  markdown: function (text) { +    var self = this; +    var IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:)/; +    var IS_ANGULAR = /^angular\./; +    if (!text) return text; +    var parts = text.split(/(<pre>[\s\S]*?<\/pre>|<doc:example>[\s\S]*?<\/doc:example>)/), +        match; + +    parts.forEach(function(text, i){ +      if (text.match(/^<pre>/)) { +        text = text.replace(/^<pre>([\s\S]*)<\/pre>/mi, function(_, content){ +          return '<div ng:non-bindable><pre class="brush: js; html-script: true;">' + +                  content.replace(/</g, '<').replace(/>/g, '>') + +                 '</pre></div>'; +        }); +      } else if (text.match(/^<doc:example>/)) { +        text = text.replace(/(<doc:source>)([\s\S]*)(<\/doc:source>)/mi, +          function(_, before, content, after){ +            return before + htmlEscape(content) + after; +          }); +        text = text.replace(/(<doc:scenario>)([\s\S]*)(<\/doc:scenario>)/mi, +          function(_, before, content, after){ +            self.scenarios.push(content); +            return before + htmlEscape(content) + after; +          }); +      } else { +        text = text.replace(/<angular\/>/gm, '<tt><angular/></tt>'); +        text = text.replace(/{@link ([^\s}]+)((\s|\n)+(.+?))?\s*}/gm, +          function(_all, url, _2, _3, title){ +            return '<a href="' + (url.match(IS_URL) ? '' : '#!') + url + '">' +              + (url.match(IS_ANGULAR) ? '<code>' : '') +              + (title || url) +              + (url.match(IS_ANGULAR) ? '</code>' : '') +              + '</a>'; +          }); +        text = new Showdown.converter().makeHtml(text); +      } +      parts[i] = text; +    }); +    return parts.join(''); +  }, +    parse: function(){      var atName;      var atText;      var match;      var self = this; -    this.scenarios = []; -    this.requires = []; -    this.param = []; -    this.properties = []; -    this.methods = [];      self.text.split(NEW_LINE).forEach(function(line){        if (match = line.match(/^\s*@(\w+)(\s+(.*))?/)) {          // we found @name ... @@ -82,9 +123,9 @@ Doc.prototype = {      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 -    this.description = markdown(this.description); -    this['this'] = markdown(this['this']); -    this.exampleDescription = markdown(this.exampleDescription || this.exampleDesc); +    this.description = this.markdown(this.description); +    this.example = this.markdown(this.example); +    this['this'] = this.markdown(this['this']);      return this;      function flush(){ @@ -98,7 +139,7 @@ Doc.prototype = {            }            var param = {              name: match[5] || match[4], -            description:markdown(text.replace(match[0], match[7])), +            description:self.markdown(text.replace(match[0], match[7])),              type: match[1],              optional: !!match[2],              'default':match[6] @@ -111,18 +152,10 @@ Doc.prototype = {            }            self.returns = {              type: match[1], -            description: markdown(text.replace(match[0], match[2])) +            description: self.markdown(text.replace(match[0], match[2]))            }; -        } else if(atName == 'description') { -          text.replace(/<doc:scenario>([\s\S]*?)<\/doc:scenario>/gmi, -              function(_, scenario){ -                self.scenarios.push(scenario); -              }); -          self.description = text;          } else if(atName == 'requires') {            self.requires.push(text); -        } else if(atName == 'scenario') { -          self.scenarios.push(text);          } else if(atName == 'property') {            var match = text.match(/^({(\S+)}\s*)?(\S+)(\s+(.*))?/);            if (!match) { @@ -154,7 +187,7 @@ Doc.prototype = {          throw new Error("Don't know how to format @ngdoc: " + self.ngdoc);        }).call(self, dom); -      dom.example(self.exampleDescription, self.example, self.scenarios[0]); +      dom.h('Example', self.example, dom.html);      });      return dom.toString(); @@ -407,13 +440,13 @@ Doc.prototype = {        dom.h(method.shortName + '(' + signature.join(', ') + ')', method, function(){          dom.html(method.description);          method.html_usage_parameters(dom); -        dom.example(method.exampleDescription, method.example, false); +        dom.h('Example', method.example, dom.html);        });      });      dom.h('Properties', this.properties, function(property){        dom.h(property.name, function(){         dom.text(property.description); -       dom.example(property.exampleDescription, property.example, false); +       dom.h('Example', property.example, dom.html);        });      });    }, @@ -437,47 +470,6 @@ Doc.prototype = {  ////////////////////////////////////////////////////////// -function markdown (text) { -  var IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:)/; -  var IS_ANGULAR = /^angular\./; -  if (!text) return text; -  var parts = text.split(/(<pre>[\s\S]*?<\/pre>|<doc:example>[\s\S]*?<\/doc:example>)/), -      match; - -  parts.forEach(function(text, i){ -    if (text.match(/^<pre>/)) { -      text = text.replace(/^<pre>([\s\S]*)<\/pre>/mi, function(_, content){ -        return '<div ng:non-bindable><pre class="brush: js; html-script: true;">' + -                content.replace(/</g, '<').replace(/>/g, '>') + -               '</pre></div>'; -      }); -    } else if (text.match(/^<doc:example>/)) { -      text = text.replace(/(<doc:source>)([\s\S]*)(<\/doc:source>)/mi, -        function(_, before, content, after){ -          return before + htmlEscape(content) + after; -        }); -      text = text.replace(/(<doc:scenario>)([\s\S]*)(<\/doc:scenario>)/mi, -        function(_, before, content, after){ -          return before + htmlEscape(content) + after; -        }); -    } else { -      text = text.replace(/<angular\/>/gm, '<tt><angular/></tt>'); -      text = text.replace(/{@link ([^\s}]+)((\s|\n)+(.+?))?\s*}/gm, -        function(_all, url, _2, _3, title){ -          return '<a href="' + (url.match(IS_URL) ? '' : '#!') + url + '">' -            + (url.match(IS_ANGULAR) ? '<code>' : '') -            + (title || url) -            + (url.match(IS_ANGULAR) ? '</code>' : '') -            + '</a>'; -        }); -      text = new Showdown.converter().makeHtml(text); -    } -    parts[i] = text; -  }); -  return parts.join(''); -}; - -//////////////////////////////////////////////////////////  function scenarios(docs){    var specs = [];    docs.forEach(function(doc){ | 
