├── ngdoc ├── tag-defs │ ├── priority.spec.js │ ├── id.js │ ├── parent.js │ ├── title.js │ ├── fullName.js │ ├── packageName.js │ ├── example.js │ ├── ngdoc.js │ ├── priority.js │ ├── scope.js │ ├── element.js │ ├── scope.spec.js │ ├── module.js │ ├── area.js │ ├── area.spec.js │ ├── eventType.js │ ├── index.js │ ├── element.spec.js │ ├── eventType.spec.js │ ├── name.js │ ├── restrict.js │ ├── name.spec.js │ ├── module.spec.js │ └── restrict.spec.js ├── templates │ ├── api │ │ ├── type.template.html │ │ ├── function.template.html │ │ ├── provider.template.html │ │ ├── service.template.html │ │ ├── input.template.html │ │ ├── object.template.html │ │ ├── componentGroup.template.html │ │ ├── filter.template.html │ │ ├── api.template.html │ │ ├── directive.template.html │ │ └── module.template.html │ ├── lib │ │ ├── returns.template.html │ │ ├── this.template.html │ │ ├── params.template.html │ │ ├── properties.template.html │ │ ├── methods.template.html │ │ ├── events.template.html │ │ └── macros.html │ ├── overview.template.html │ └── base.template.html ├── rendering │ ├── filters │ │ ├── type-class.js │ │ ├── code.js │ │ ├── link.js │ │ ├── type-class.spec.js │ │ ├── link.spec.js │ │ └── code.spec.js │ └── tags │ │ ├── code.js │ │ └── code.spec.js ├── services │ ├── moduleMap.js │ ├── getTypeClass.js │ ├── getAliases.spec.js │ ├── getTypeClass.spec.js │ ├── getDocFromAlias.js │ ├── getDocFromAlias.spec.js │ ├── getLinkInfo.js │ ├── getAliases.js │ └── getLinkInfo.spec.js ├── mocks │ └── mockPackage.js ├── processors │ ├── filterNgdocs.js │ ├── filterNgdocs.spec.js │ ├── providerDocs.js │ ├── generateComponentGroups.js │ ├── memberDocs.js │ ├── moduleDocs.js │ ├── generateComponentGroups.spec.js │ ├── providerDocs.spec.js │ └── memberDocs.spec.js ├── file-readers │ ├── ngdoc.js │ └── ngdoc.spec.js ├── inline-tag-defs │ ├── link.js │ └── link.spec.js └── index.spec.js ├── base ├── fixtures │ ├── docs │ │ ├── a.js │ │ └── b.ngdoc │ └── src │ │ ├── f1 │ │ └── a.js │ │ └── f2 │ │ └── b.js ├── services │ ├── writeFile.js │ ├── encodeCodeBlock.js │ ├── createDocMessage.js │ ├── extractLinks.js │ ├── resolveUrl.js │ ├── extractLinks.spec.js │ ├── encodeCodeBlock.spec.js │ ├── aliasMap.js │ ├── aliasMap.spec.js │ ├── trimIndentation.spec.js │ ├── templateFinder.spec.js │ ├── createDocMessage.spec.js │ ├── trimIndentation.js │ └── templateFinder.js ├── mocks │ └── mockPackage.js ├── processors │ ├── unescape-comments.js │ ├── unescape-comments.spec.js │ ├── debugDumpProcessor.spec.js │ ├── debugDumpProcessor.js │ ├── write-files.js │ ├── write-files.spec.js │ ├── render-docs.spec.js │ ├── computeIds.js │ ├── computePaths.js │ ├── render-docs.js │ └── computeIds.spec.js └── index.js ├── examples ├── templates │ ├── template.css │ ├── template.js │ ├── template.html │ ├── template.json │ ├── template.scenario │ ├── template.spec │ ├── template.protractor │ ├── manifest.template.json │ ├── protractorTests.template.js │ ├── index.template.html │ └── runnableExample.template.html ├── services │ └── exampleMap.js ├── mocks │ └── mockPackage.js ├── inline-tag-defs │ ├── runnableExample.js │ └── runnableExample.spec.js ├── processors │ ├── protractor-generate.js │ ├── examples-parse.js │ └── examples-parse.spec.js ├── index.js └── index.spec.js ├── jsdoc ├── tag-defs │ ├── class.js │ ├── global.js │ ├── kind.js │ ├── method.js │ ├── module.js │ ├── name.js │ ├── usage.js │ ├── function.js │ ├── private.js │ ├── animations.js │ ├── classdesc.js │ ├── constructor.js │ ├── deprecated.js │ ├── namespace.js │ ├── see.js │ ├── requires.js │ ├── type.js │ ├── returns.js │ ├── param.js │ ├── property.js │ ├── description.js │ ├── index.spec.js │ ├── type.spec.js │ ├── returns.spec.js │ ├── param.spec.js │ ├── property.spec.js │ ├── index.js │ ├── memberof.js │ ├── description.spec.js │ └── memberof.spec.js ├── lib │ ├── Tag.js │ ├── Tag.spec.js │ ├── TagCollection.js │ └── TagCollection.spec.js ├── services │ └── transforms │ │ ├── unknown-tag.js │ │ ├── whole-tag.js │ │ ├── whole-tag.spec.js │ │ ├── trim-whitespace.js │ │ ├── unknown-tag.spec.js │ │ ├── trim-whitespace.spec.js │ │ ├── extract-type.spec.js │ │ ├── extract-name.js │ │ ├── extract-name.spec.js │ │ └── extract-type.js ├── mocks │ ├── mockPackage.js │ └── _test-data │ │ └── docsFromJsFile.js ├── file-readers │ ├── jsdoc.js │ └── jsdoc.spec.js ├── processors │ ├── code-name.spec.js │ ├── code-name.js │ ├── inline-tags.spec.js │ ├── inline-tags.js │ └── extractJSDocComments.js ├── index.js └── index.spec.js ├── dgeni ├── tag-defs │ ├── dgPackage.js │ ├── dgProcessor.js │ └── dgService.js └── index.js ├── nunjucks ├── index.spec.js ├── mocks │ └── mockPackage.js ├── rendering │ ├── filters │ │ ├── json.js │ │ ├── first-line.js │ │ ├── first-paragraph.js │ │ ├── marked.js │ │ ├── first-line.spec.js │ │ ├── change-case.spec.js │ │ ├── first-paragraph.spec.js │ │ ├── json.spec.js │ │ ├── marked.spec.js │ │ └── change-case.js │ └── tags │ │ ├── marked.js │ │ └── marked.spec.js ├── index.js └── services │ ├── renderMarkdown.js │ ├── nunjucks-template-engine.js │ ├── renderMarkdown.spec.js │ └── nunjucks-template-engine.spec.js ├── .gitignore ├── LICENSE └── package.json /ngdoc/tag-defs/priority.spec.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /base/fixtures/docs/a.js: -------------------------------------------------------------------------------- 1 | // Mock code file -------------------------------------------------------------------------------- /base/fixtures/src/f1/a.js: -------------------------------------------------------------------------------- 1 | // Mock code file -------------------------------------------------------------------------------- /base/fixtures/src/f2/b.js: -------------------------------------------------------------------------------- 1 | // Other mock code file -------------------------------------------------------------------------------- /base/fixtures/docs/b.ngdoc: -------------------------------------------------------------------------------- 1 | mock documentation file -------------------------------------------------------------------------------- /examples/templates/template.css: -------------------------------------------------------------------------------- 1 | {$ doc.fileContents $} -------------------------------------------------------------------------------- /examples/templates/template.js: -------------------------------------------------------------------------------- 1 | {$ doc.fileContents $} -------------------------------------------------------------------------------- /examples/templates/template.html: -------------------------------------------------------------------------------- 1 | {$ doc.fileContents $} -------------------------------------------------------------------------------- /examples/templates/template.json: -------------------------------------------------------------------------------- 1 | {$ doc.fileContents $} -------------------------------------------------------------------------------- /examples/templates/template.scenario: -------------------------------------------------------------------------------- 1 | {$ doc.fileContents $} -------------------------------------------------------------------------------- /examples/templates/template.spec: -------------------------------------------------------------------------------- 1 | {$ doc.fileContents $} -------------------------------------------------------------------------------- /examples/templates/template.protractor: -------------------------------------------------------------------------------- 1 | {$ doc.fileContents $} -------------------------------------------------------------------------------- /ngdoc/templates/api/type.template.html: -------------------------------------------------------------------------------- 1 | {% extends "api/object.template.html" %} 2 | -------------------------------------------------------------------------------- /ngdoc/tag-defs/id.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'id' }; 3 | }; -------------------------------------------------------------------------------- /ngdoc/templates/api/function.template.html: -------------------------------------------------------------------------------- 1 | {% extends "api/object.template.html" %} 2 | -------------------------------------------------------------------------------- /jsdoc/tag-defs/class.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'class' }; 3 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/global.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'global' }; 3 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/kind.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'kind' }; 3 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/method.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'method' }; 3 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/module.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'module' }; 3 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/name.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'name' }; 3 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/usage.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'usage' }; 3 | }; -------------------------------------------------------------------------------- /ngdoc/tag-defs/parent.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'parent' }; 3 | }; -------------------------------------------------------------------------------- /ngdoc/tag-defs/title.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'title' }; 3 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/function.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'function' }; 3 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/private.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'private' }; 3 | }; -------------------------------------------------------------------------------- /ngdoc/tag-defs/fullName.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'fullName' }; 3 | }; -------------------------------------------------------------------------------- /dgeni/tag-defs/dgPackage.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'dgPackage' }; 3 | }; -------------------------------------------------------------------------------- /dgeni/tag-defs/dgProcessor.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'dgProcessor' }; 3 | }; -------------------------------------------------------------------------------- /dgeni/tag-defs/dgService.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'dgService' }; 3 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/animations.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'animations' }; 3 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/classdesc.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'classdesc' }; 3 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/constructor.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'constructor' }; 3 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/deprecated.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'deprecated' }; 3 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/namespace.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'namespace' }; 3 | }; -------------------------------------------------------------------------------- /ngdoc/tag-defs/packageName.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { name: 'packageName' }; 3 | }; -------------------------------------------------------------------------------- /nunjucks/index.spec.js: -------------------------------------------------------------------------------- 1 | var package = require('./'); 2 | 3 | describe('nunjucks package', function() { 4 | 5 | }); -------------------------------------------------------------------------------- /jsdoc/tag-defs/see.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { 3 | name: 'see', 4 | multi: true 5 | }; 6 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/requires.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { 3 | name: 'requires', 4 | multi: true 5 | }; 6 | }; -------------------------------------------------------------------------------- /ngdoc/templates/lib/returns.template.html: -------------------------------------------------------------------------------- 1 | {% if doc.returns -%} 2 |

Returns

3 | {$ typeInfo(doc.returns) $} 4 | {%- endif %} -------------------------------------------------------------------------------- /ngdoc/templates/lib/this.template.html: -------------------------------------------------------------------------------- 1 | {% if doc.this %} 2 |

Method's {% code %}this{% endcode %}

3 | {$ doc.this | marked $} 4 | {% endif %} -------------------------------------------------------------------------------- /ngdoc/templates/overview.template.html: -------------------------------------------------------------------------------- 1 | {% extends "base.template.html" %} 2 | 3 | {% block content %} 4 | {$ doc.description | marked $} 5 | {% endblock %} -------------------------------------------------------------------------------- /ngdoc/tag-defs/example.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { 3 | name: 'example', 4 | multi: true, 5 | docProperty: 'examples' 6 | }; 7 | }; -------------------------------------------------------------------------------- /ngdoc/tag-defs/ngdoc.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { 3 | name: 'ngdoc', 4 | required: true, 5 | docProperty: 'docType' 6 | }; 7 | }; -------------------------------------------------------------------------------- /ngdoc/tag-defs/priority.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { 3 | name: 'priority', 4 | defaultFn: function(doc) { return 0; } 5 | }; 6 | }; -------------------------------------------------------------------------------- /ngdoc/tag-defs/scope.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { 3 | name: 'scope', 4 | transforms: function(doc, tag) { return true; } 5 | }; 6 | }; -------------------------------------------------------------------------------- /ngdoc/rendering/filters/type-class.js: -------------------------------------------------------------------------------- 1 | module.exports = function(getTypeClass) { 2 | return { 3 | name: 'typeClass', 4 | process: getTypeClass 5 | }; 6 | }; -------------------------------------------------------------------------------- /ngdoc/templates/lib/params.template.html: -------------------------------------------------------------------------------- 1 | {%- if doc.params %} 2 |
3 |

Arguments

4 | {$ paramTable(doc.params) $} 5 |
6 | {%- endif -%} 7 | -------------------------------------------------------------------------------- /jsdoc/tag-defs/type.js: -------------------------------------------------------------------------------- 1 | module.exports = function(extractTypeTransform, wholeTagTransform) { 2 | return { 3 | name: 'type', 4 | transforms: [ extractTypeTransform, wholeTagTransform ] 5 | }; 6 | }; -------------------------------------------------------------------------------- /examples/templates/manifest.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "{$ doc.example.id $}", 3 | "files": [ 4 | "index-production.html" 5 | {%- for file in doc.files %}, 6 | "{$ file $}"{% endfor %} 7 | ] 8 | } -------------------------------------------------------------------------------- /nunjucks/mocks/mockPackage.js: -------------------------------------------------------------------------------- 1 | var Package = require('dgeni').Package; 2 | 3 | module.exports = function mockPackage() { 4 | 5 | return new Package('mockPackage', [require('../'), require('../../base')]); 6 | 7 | }; 8 | -------------------------------------------------------------------------------- /ngdoc/rendering/filters/code.js: -------------------------------------------------------------------------------- 1 | module.exports = function(encodeCodeBlock) { 2 | return { 3 | name: 'code', 4 | process: function(str, lang) { 5 | return encodeCodeBlock(str, true, lang); 6 | } 7 | }; 8 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | *.DS_Store 10 | 11 | pids 12 | logs 13 | results 14 | 15 | npm-debug.log 16 | node_modules 17 | 18 | .agignore 19 | 20 | coverage -------------------------------------------------------------------------------- /jsdoc/lib/Tag.js: -------------------------------------------------------------------------------- 1 | function Tag(tagDef, tagName, description, lineNumber) { 2 | this.tagDef = tagDef; 3 | this.tagName = tagName; 4 | this.description = description; 5 | this.startingLine = lineNumber; 6 | } 7 | 8 | module.exports = Tag; -------------------------------------------------------------------------------- /jsdoc/tag-defs/returns.js: -------------------------------------------------------------------------------- 1 | module.exports = function(extractTypeTransform, wholeTagTransform) { 2 | return { 3 | name: 'returns', 4 | aliases: ['return'], 5 | transforms: [ extractTypeTransform, wholeTagTransform ] 6 | }; 7 | }; -------------------------------------------------------------------------------- /ngdoc/tag-defs/element.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { 3 | name: 'element', 4 | defaultFn: function(doc) { 5 | if ( doc.docType === 'directive' || doc.docType === 'input') { 6 | return'ANY'; 7 | } 8 | } 9 | }; 10 | }; -------------------------------------------------------------------------------- /nunjucks/rendering/filters/json.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @dgRenderFilter json 3 | * @description Convert the object to a JSON string 4 | */ 5 | module.exports = { 6 | name: 'json', 7 | process: function(obj) { 8 | return JSON.stringify(obj, null, ' '); 9 | } 10 | }; -------------------------------------------------------------------------------- /ngdoc/services/moduleMap.js: -------------------------------------------------------------------------------- 1 | var StringMap = require('stringmap'); 2 | 3 | /** 4 | * @dgService moduleMap 5 | * @description 6 | * A collection of modules keyed on the module name 7 | */ 8 | module.exports = function moduleMap() { 9 | return new StringMap(); 10 | }; -------------------------------------------------------------------------------- /ngdoc/tag-defs/scope.spec.js: -------------------------------------------------------------------------------- 1 | var tagDefFactory = require('./scope'); 2 | 3 | describe("scope tag-def", function() { 4 | it("should transform the value to true", function() { 5 | var tagDef = tagDefFactory(); 6 | expect(tagDef.transforms()).toEqual(true); 7 | }); 8 | }); -------------------------------------------------------------------------------- /jsdoc/services/transforms/unknown-tag.js: -------------------------------------------------------------------------------- 1 | module.exports = function unknownTagTransform() { 2 | return function(doc, tag, value) { 3 | if ( !tag.tagDef ) { 4 | tag.errors = tag.errors || []; 5 | tag.errors.push('Unknown tag: ' + tag.tagName); 6 | } 7 | }; 8 | }; -------------------------------------------------------------------------------- /examples/services/exampleMap.js: -------------------------------------------------------------------------------- 1 | var StringMap = require('stringmap'); 2 | 3 | /** 4 | * @dgService exampleMap 5 | * @description 6 | * A map of examples parsed out of the doc content, keyed on 7 | */ 8 | module.exports = function exampleMap() { 9 | return new StringMap(); 10 | }; -------------------------------------------------------------------------------- /ngdoc/rendering/filters/link.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | 3 | module.exports = function() { 4 | return { 5 | name: 'link', 6 | process: function(url, title, doc) { 7 | return _.template('{@link ${url} ${title} }', { url: url, title: title }); 8 | } 9 | }; 10 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/param.js: -------------------------------------------------------------------------------- 1 | module.exports = function(extractTypeTransform, extractNameTransform, wholeTagTransform) { 2 | return { 3 | name: 'param', 4 | multi: true, 5 | docProperty: 'params', 6 | transforms: [ extractTypeTransform, extractNameTransform, wholeTagTransform ] 7 | }; 8 | }; -------------------------------------------------------------------------------- /ngdoc/templates/api/provider.template.html: -------------------------------------------------------------------------------- 1 | {% extends "api/object.template.html" %} 2 | 3 | {% block related_components %} 4 | {% if doc.serviceDoc -%} 5 |
  • 6 | - {$ doc.serviceDoc.name $} 7 |
  • 8 | {%- endif %} 9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /ngdoc/templates/api/service.template.html: -------------------------------------------------------------------------------- 1 | {% extends "api/object.template.html" %} 2 | 3 | {% block related_components %} 4 | {% if doc.providerDoc -%} 5 |
  • 6 | - {$ doc.providerDoc.name $} 7 |
  • 8 | {%- endif %} 9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /jsdoc/services/transforms/whole-tag.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Use the whole tag as the value rather than using a tag property, such as `description` 3 | * @param {Tag} tag The tag to process 4 | */ 5 | module.exports = function wholeTagTransform() { 6 | return function(doc, tag, value) { 7 | return tag; 8 | }; 9 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/property.js: -------------------------------------------------------------------------------- 1 | module.exports = function(extractTypeTransform, extractNameTransform, wholeTagTransform) { 2 | return { 3 | name: 'property', 4 | multi: true, 5 | docProperty: 'properties', 6 | transforms: [ extractTypeTransform, extractNameTransform, wholeTagTransform ] 7 | }; 8 | }; -------------------------------------------------------------------------------- /ngdoc/mocks/mockPackage.js: -------------------------------------------------------------------------------- 1 | var Package = require('dgeni').Package; 2 | 3 | module.exports = function mockPackage() { 4 | 5 | return new Package('mockPackage', [require('../')]) 6 | 7 | // provide a mock log service 8 | .factory('log', function() { return require('dgeni/lib/mocks/log')(false); }); 9 | }; 10 | -------------------------------------------------------------------------------- /nunjucks/rendering/filters/first-line.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @dgRenderFilter firstLine 3 | * @description Extract the first line from the value 4 | */ 5 | module.exports = { 6 | name: 'firstLine', 7 | process: function(str) { 8 | if (!str) return str; 9 | 10 | str = str 11 | .split("\n")[0]; 12 | return str; 13 | } 14 | }; -------------------------------------------------------------------------------- /jsdoc/services/transforms/whole-tag.spec.js: -------------------------------------------------------------------------------- 1 | var transformFactory = require('./whole-tag'); 2 | 3 | describe("whole-tag transform", function() { 4 | it("should return the whole tag", function() { 5 | var transform = transformFactory(); 6 | var doc = {}, tag = {}, value = {}; 7 | expect(transform(doc, tag, value)).toBe(tag); 8 | }); 9 | }); -------------------------------------------------------------------------------- /ngdoc/templates/lib/properties.template.html: -------------------------------------------------------------------------------- 1 | {%- if doc.properties %} 2 |

    Properties

    3 | 11 | {%- endif -%} 12 | -------------------------------------------------------------------------------- /jsdoc/services/transforms/trim-whitespace.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | 3 | /** 4 | * Trim excess whitespace from the value 5 | */ 6 | module.exports = function trimWhitespaceTransform() { 7 | return function(doc, tag, value) { 8 | if ( _.isString(value) ) { 9 | return value.trim(); 10 | } 11 | return value; 12 | }; 13 | }; -------------------------------------------------------------------------------- /ngdoc/tag-defs/module.js: -------------------------------------------------------------------------------- 1 | var path = require('canonical-path'); 2 | 3 | module.exports = function() { 4 | return { 5 | name: 'module', 6 | defaultFn: function(doc) { 7 | if ( doc.area === 'api' && doc.docType !== 'overview' ) { 8 | return path.dirname(doc.fileInfo.relativePath).split('/')[0]; 9 | } 10 | } 11 | }; 12 | }; -------------------------------------------------------------------------------- /ngdoc/tag-defs/area.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { 3 | name: 'area', 4 | defaultFn: function(doc) { 5 | // Code files are put in the 'api' area 6 | // Other files compute their area from the first path segment 7 | return (doc.fileInfo.extension === 'js') ? 'api' : doc.fileInfo.relativePath.split('/')[0]; 8 | } 9 | }; 10 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/description.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { 3 | name: 'description', 4 | transforms: function(doc, tag, value) { 5 | if ( doc.tags.description ) { 6 | value = doc.tags.description + '\n' + value; 7 | } 8 | return value; 9 | }, 10 | defaultFn: function(doc) { 11 | return doc.tags.description; 12 | } 13 | }; 14 | }; -------------------------------------------------------------------------------- /nunjucks/rendering/filters/first-paragraph.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @dgRenderFilter firstParagraph 3 | * @description Extract the first paragraph from the value, breaking on the first double newline 4 | */ 5 | module.exports = { 6 | name: 'firstParagraph', 7 | process: function(str) { 8 | if (!str) return str; 9 | 10 | str = str 11 | .split("\n\n")[0]; 12 | return str; 13 | } 14 | }; -------------------------------------------------------------------------------- /ngdoc/templates/api/input.template.html: -------------------------------------------------------------------------------- 1 | {% include "lib/macros.html" -%} 2 | {% extends "api/directive.template.html" %} 3 | 4 | {% block usage %} 5 |

    Usage

    6 | {% code %} 7 | 11 | {% endcode %} 12 | {% endblock %} -------------------------------------------------------------------------------- /nunjucks/rendering/filters/marked.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @dgRenderFilter marked 3 | * @description Convert the value, as markdown, into HTML using the marked library 4 | */ 5 | module.exports = function markedNunjucksFilter(renderMarkdown) { 6 | return { 7 | name: 'marked', 8 | process: function(str) { 9 | var output = str && renderMarkdown(str); 10 | return output; 11 | } 12 | }; 13 | }; -------------------------------------------------------------------------------- /ngdoc/rendering/filters/type-class.spec.js: -------------------------------------------------------------------------------- 1 | var filterFactory = require('./type-class'); 2 | 3 | describe("type-class filter", function() { 4 | it("should call getTypeClass", function() { 5 | var getTypeClassSpy = jasmine.createSpy('getTypeClass'); 6 | var filter = filterFactory(getTypeClassSpy); 7 | 8 | filter.process('object'); 9 | expect(getTypeClassSpy).toHaveBeenCalled(); 10 | }); 11 | }); -------------------------------------------------------------------------------- /ngdoc/tag-defs/area.spec.js: -------------------------------------------------------------------------------- 1 | var tagDefFactory = require('./area'); 2 | 3 | describe("area tag-def", function() { 4 | it("should set default based on fileType", function() { 5 | var tagDef = tagDefFactory(); 6 | expect(tagDef.defaultFn({ fileInfo: { extension: 'js' } })).toEqual('api'); 7 | expect(tagDef.defaultFn({ fileInfo: { relativePath: 'guide/concepts.ngdoc' } })).toEqual('guide'); 8 | }); 9 | }); -------------------------------------------------------------------------------- /ngdoc/tag-defs/eventType.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { 3 | name: 'eventType', 4 | transforms: function(doc, tag, value) { 5 | var EVENTTYPE_REGEX = /^([^\s]*)\s+on\s+([\S\s]*)/; 6 | var match = EVENTTYPE_REGEX.exec(value); 7 | // Attach the target to the doc 8 | doc.eventTarget = match[2]; 9 | // And return the type 10 | return match[1]; 11 | } 12 | }; 13 | }; -------------------------------------------------------------------------------- /base/services/writeFile.js: -------------------------------------------------------------------------------- 1 | var fs = require('q-io/fs'); 2 | 3 | /** 4 | * @dgService writeFile 5 | * @description 6 | * Write the given contents to a file, ensuring the path to the file exists 7 | */ 8 | module.exports = function writeFile() { 9 | return function(file, content) { 10 | return fs.makeTree(fs.directory(file)).then(function() { 11 | return fs.write(file, content, 'wb'); 12 | }); 13 | }; 14 | }; -------------------------------------------------------------------------------- /jsdoc/services/transforms/unknown-tag.spec.js: -------------------------------------------------------------------------------- 1 | var transformFactory = require('./unknown-tag'); 2 | 3 | describe("unknown-tag transform", function() { 4 | it("should add an error to the tag if it has no tagDef", function() { 5 | var doc = {}, tag = { tagName: 'bad-tag'}; 6 | var transform = transformFactory(); 7 | transform(doc, tag); 8 | expect(tag.errors).toEqual(['Unknown tag: bad-tag']); 9 | }); 10 | }); -------------------------------------------------------------------------------- /ngdoc/services/getTypeClass.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @dgService getTypeClass 3 | * @description 4 | * Get a CSS class string for the given type string 5 | */ 6 | module.exports = function getTypeClass() { 7 | return function(typeStr) { 8 | var typeClass = typeStr.toLowerCase().match(/^[-\w]+/) || []; 9 | typeClass = typeClass[0] ? typeClass[0] : 'object'; 10 | return 'label type-hint type-hint-' + typeClass; 11 | }; 12 | }; -------------------------------------------------------------------------------- /dgeni/index.js: -------------------------------------------------------------------------------- 1 | var Package = require('dgeni').Package; 2 | 3 | module.exports = new Package('dgeni', ['jsdoc']) 4 | 5 | .config(function(parseTagsProcessor, getInjectables) { 6 | parseTagsProcessor.tagDefinitions = parseTagsProcessor.tagDefinitions.concat( 7 | getInjectables([ 8 | require('./tag-defs/dgPackage'), 9 | require('./tag-defs/dgService'), 10 | require('./tag-defs/dgProcessor') 11 | ])); 12 | }); -------------------------------------------------------------------------------- /jsdoc/tag-defs/index.spec.js: -------------------------------------------------------------------------------- 1 | var tagDefFactories = require('./'); 2 | 3 | describe("jsdoc tagdefs", function() { 4 | it("should contain an array of tagDef factory functions", function() { 5 | expect(tagDefFactories).toEqual(jasmine.any(Array)); 6 | expect(tagDefFactories.length).toEqual(22); 7 | tagDefFactories.forEach(function(factory) { 8 | expect(factory).toEqual(jasmine.any(Function)); 9 | }); 10 | }); 11 | }); -------------------------------------------------------------------------------- /jsdoc/mocks/mockPackage.js: -------------------------------------------------------------------------------- 1 | var Package = require('dgeni').Package; 2 | 3 | module.exports = function mockPackage() { 4 | 5 | return new Package('mockPackage', [require('../')]) 6 | 7 | // provide a mock log service 8 | .factory('log', function() { return require('dgeni/lib/mocks/log')(false); }) 9 | 10 | // provide a mock template engine for the tests 11 | .factory('templateEngine', function dummyTemplateEngine() {}); 12 | }; 13 | -------------------------------------------------------------------------------- /nunjucks/rendering/filters/first-line.spec.js: -------------------------------------------------------------------------------- 1 | var filter = require('./first-line'); 2 | 3 | describe("firstLine filter", function() { 4 | it("should have the name 'firstLine'", function() { 5 | expect(filter.name).toEqual('firstLine'); 6 | }); 7 | it("should return the content up to the first newline", function() { 8 | expect(filter.process('this is a line\nthis is another line')).toEqual('this is a line'); 9 | }); 10 | }); 11 | 12 | -------------------------------------------------------------------------------- /ngdoc/tag-defs/index.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | require('./ngdoc'), 3 | require('./name'), 4 | require('./area'), 5 | require('./module'), 6 | require('./id'), 7 | require('./restrict'), 8 | require('./eventType'), 9 | require('./example'), 10 | require('./element'), 11 | require('./fullName'), 12 | require('./priority'), 13 | require('./title'), 14 | require('./parent'), 15 | require('./packageName'), 16 | require('./scope') 17 | ]; -------------------------------------------------------------------------------- /examples/mocks/mockPackage.js: -------------------------------------------------------------------------------- 1 | var Package = require('dgeni').Package; 2 | 3 | module.exports = function mockPackage() { 4 | 5 | return new Package('mockPackage', [require('../'), require('../../jsdoc')]) 6 | 7 | // provide a mock log service 8 | .factory('log', function() { return require('dgeni/lib/mocks/log')(false); }) 9 | 10 | // provide a mock template engine for the tests 11 | .factory('templateEngine', function dummyTemplateEngine() {}); 12 | }; 13 | -------------------------------------------------------------------------------- /ngdoc/tag-defs/element.spec.js: -------------------------------------------------------------------------------- 1 | var tagDefFactory = require('./element'); 2 | 3 | describe("element tag-def", function() { 4 | it("should set default based on docType", function() { 5 | 6 | var tagDef = tagDefFactory(); 7 | expect(tagDef.defaultFn({ docType: 'directive' })).toEqual('ANY'); 8 | expect(tagDef.defaultFn({ docType: 'input' })).toEqual('ANY'); 9 | expect(tagDef.defaultFn({ docType: 'service' })).toBeUndefined(); 10 | 11 | }); 12 | }); -------------------------------------------------------------------------------- /ngdoc/templates/base.template.html: -------------------------------------------------------------------------------- 1 |  Improve this Doc 2 | 3 | {% block content %} 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /jsdoc/lib/Tag.spec.js: -------------------------------------------------------------------------------- 1 | var Tag = require('./Tag'); 2 | 3 | describe("Tag", function() { 4 | it("should put constructor parameters into member properties", function() { 5 | var tagDef = {}; 6 | var tag = new Tag(tagDef, 'someName', 'a load of content', 12); 7 | expect(tag.tagDef).toBe(tagDef); 8 | expect(tag.tagName).toEqual('someName'); 9 | expect(tag.description).toEqual('a load of content'); 10 | expect(tag.startingLine).toEqual(12); 11 | }); 12 | }); -------------------------------------------------------------------------------- /jsdoc/tag-defs/type.spec.js: -------------------------------------------------------------------------------- 1 | var tagDefFactory = require('./type'); 2 | 3 | describe("type tagDef", function() { 4 | it("should add the injected transforms to the transforms property", function() { 5 | var extractTypeTransform = function() {}; 6 | var wholeTagTransform = function() {}; 7 | 8 | var tagDef = tagDefFactory(extractTypeTransform, wholeTagTransform); 9 | expect(tagDef.transforms).toEqual([extractTypeTransform, wholeTagTransform]); 10 | }); 11 | }); -------------------------------------------------------------------------------- /jsdoc/tag-defs/returns.spec.js: -------------------------------------------------------------------------------- 1 | var tagDefFactory = require('./returns'); 2 | 3 | describe("returns tagDef", function() { 4 | it("should add the injected transforms to the transforms property", function() { 5 | var extractTypeTransform = function() {}; 6 | var wholeTagTransform = function() {}; 7 | 8 | var tagDef = tagDefFactory(extractTypeTransform, wholeTagTransform); 9 | expect(tagDef.transforms).toEqual([extractTypeTransform, wholeTagTransform]); 10 | }); 11 | }); -------------------------------------------------------------------------------- /examples/templates/protractorTests.template.js: -------------------------------------------------------------------------------- 1 | describe("{$ doc.description $}", function() { 2 | var rootEl; 3 | beforeEach(function() { 4 | rootEl = browser.rootEl;{% if doc['ng-app-included'] %} 5 | browser.rootEl = '[ng-app]';{% endif %} 6 | browser.get("{$ doc.basePath $}{$ doc.example.deployments[doc.deployment.name].outputPath $}"); 7 | }); 8 | {% if doc['ng-app-included'] %}afterEach(function() { browser.rootEl = rootEl; });{% endif %} 9 | {$ doc.innerTest $} 10 | }); -------------------------------------------------------------------------------- /ngdoc/tag-defs/eventType.spec.js: -------------------------------------------------------------------------------- 1 | var tagDefFactory = require('./eventType'); 2 | 3 | describe("eventType tag-def", function() { 4 | it("should split into eventType and eventTarget", function() { 5 | var doc = {}, tag = {}; 6 | var tagDef = tagDefFactory(); 7 | var value = tagDef.transforms(doc, tag, 'broadcast on module:ng.directive:ngInclude'); 8 | expect(value).toEqual('broadcast'); 9 | expect(doc.eventTarget).toEqual('module:ng.directive:ngInclude'); 10 | }); 11 | }); -------------------------------------------------------------------------------- /ngdoc/rendering/filters/link.spec.js: -------------------------------------------------------------------------------- 1 | var filterFactory = require('./link'); 2 | 3 | describe("link filter", function() { 4 | var filter; 5 | 6 | beforeEach(function() { 7 | filter = filterFactory(); 8 | }); 9 | 10 | it("should have the name 'link'", function() { 11 | expect(filter.name).toEqual('link'); 12 | }); 13 | 14 | it("should inject an inline link tag", function() { 15 | expect(filter.process('URL', 'TITLE')).toEqual('{@link URL TITLE }'); 16 | }); 17 | 18 | }); -------------------------------------------------------------------------------- /nunjucks/rendering/filters/change-case.spec.js: -------------------------------------------------------------------------------- 1 | var filters = require('./change-case'); 2 | var _ = require('lodash'); 3 | 4 | var dashCase = _.find(filters, function(filter) { return filter.name === 'dashCase'; }); 5 | 6 | describe("dashCase custom filter", function() { 7 | it("should have the name 'dashCase'", function() { 8 | expect(dashCase.name).toEqual('dashCase'); 9 | }); 10 | it("should transform the content to dash-case", function() { 11 | expect(dashCase.process('fooBar')).toEqual('foo-bar'); 12 | }); 13 | }); 14 | 15 | -------------------------------------------------------------------------------- /nunjucks/rendering/filters/first-paragraph.spec.js: -------------------------------------------------------------------------------- 1 | var filter = require('./first-paragraph'); 2 | 3 | describe("firstParagraph filter", function() { 4 | it("should have the name 'firstParagraph'", function() { 5 | expect(filter.name).toEqual('firstParagraph'); 6 | }); 7 | it("should return the content up to end of the first paragraph", function() { 8 | expect(filter.process('this is a line\nthis is another line\n\nthis is new paragraph')) 9 | .toEqual('this is a line\nthis is another line'); 10 | }); 11 | }); 12 | 13 | -------------------------------------------------------------------------------- /jsdoc/tag-defs/param.spec.js: -------------------------------------------------------------------------------- 1 | var tagDefFactory = require('./param'); 2 | 3 | describe('param tagDef', function() { 4 | it("should add the injected transforms to the transforms property", function() { 5 | var extractNameTransform = function() {}; 6 | var extractTypeTransform = function() {}; 7 | var wholeTagTransform = function() {}; 8 | 9 | var tagDef = tagDefFactory(extractTypeTransform, extractNameTransform, wholeTagTransform); 10 | expect(tagDef.transforms).toEqual([extractTypeTransform, extractNameTransform, wholeTagTransform]); 11 | }); 12 | }); -------------------------------------------------------------------------------- /ngdoc/services/getAliases.spec.js: -------------------------------------------------------------------------------- 1 | var getAliasesFactory = require('./getAliases'); 2 | 3 | describe("getAliases", function() { 4 | 5 | it("should extract all the parts from a code name", function() { 6 | 7 | var getAliases = getAliasesFactory(); 8 | 9 | expect(getAliases({ id: 'module:ng.service:$http#get'})).toEqual([ 10 | '$http#get', 11 | 'service:$http#get', 12 | 'ng.$http#get', 13 | 'module:ng.$http#get', 14 | 'ng.service:$http#get', 15 | 'module:ng.service:$http#get', 16 | 'get' 17 | ]); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /jsdoc/tag-defs/property.spec.js: -------------------------------------------------------------------------------- 1 | var tagDefFactory = require('./property'); 2 | 3 | describe("property tagDef", function() { 4 | it("should add the injected transforms to the transforms property", function() { 5 | var extractNameTransform = function() {}; 6 | var extractTypeTransform = function() {}; 7 | var wholeTagTransform = function() {}; 8 | 9 | var tagDef = tagDefFactory(extractTypeTransform, extractNameTransform, wholeTagTransform); 10 | expect(tagDef.transforms).toEqual([extractTypeTransform, extractNameTransform, wholeTagTransform]); 11 | }); 12 | }); -------------------------------------------------------------------------------- /base/mocks/mockPackage.js: -------------------------------------------------------------------------------- 1 | var Package = require('dgeni').Package; 2 | 3 | module.exports = function mockPackage() { 4 | 5 | return new Package('mockPackage', [require('../')]) 6 | 7 | // provide a mock log service 8 | .factory('log', function() { return require('dgeni/lib/mocks/log')(false); }) 9 | 10 | // provide a mock template engine for the tests 11 | .factory('templateEngine', function dummyTemplateEngine() { 12 | var renderSpy = jasmine.createSpy('templateEngine'); 13 | return { 14 | getRenderer: function() { return renderSpy; } 15 | }; 16 | }); 17 | }; 18 | -------------------------------------------------------------------------------- /ngdoc/tag-defs/name.js: -------------------------------------------------------------------------------- 1 | module.exports = function(createDocMessage) { 2 | return { 3 | name: 'name', 4 | required: true, 5 | transforms: function(doc, tag, value) { 6 | var INPUT_TYPE = /input\[(.+)\]/; 7 | if ( doc.docType === 'input' ) { 8 | var match = INPUT_TYPE.exec(value); 9 | if ( !match ) { 10 | throw new Error(createDocMessage('Invalid input directive name. It should be of the form: "input[inputType]" but was "' + value + '"', doc)); 11 | } 12 | doc.inputType = match[1]; 13 | } 14 | return value; 15 | } 16 | }; 17 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Google, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /ngdoc/processors/filterNgdocs.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | 3 | /** 4 | * dgProcessor filterNgDocsProcessor 5 | * @description 6 | * Remove docs that do not contain the ngdoc tag 7 | */ 8 | module.exports = function filterNgDocsProcessor(log) { 9 | return { 10 | $runAfter: ['tags-parsed'], 11 | $runBefore: ['extracting-tags'], 12 | $process: function(docs) { 13 | var docCount = docs.length; 14 | docs = _.filter(docs, function(doc) { 15 | return doc.tags.getTag('ngdoc'); 16 | }); 17 | log.debug('filtered ' + (docCount - docs.length) + ' docs'); 18 | return docs; 19 | } 20 | }; 21 | }; -------------------------------------------------------------------------------- /ngdoc/tag-defs/restrict.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { 3 | name: 'restrict', 4 | defaultFn: function(doc) { 5 | if ( doc.docType === 'directive' || doc.docType === 'input' ) { 6 | return { element: false, attribute: true, cssClass: false, comment: false }; 7 | } 8 | }, 9 | transforms: function(doc, tag, value) { 10 | value = value || ''; 11 | return { 12 | element: value.indexOf('E') !== -1, 13 | attribute: value.indexOf('A') !== -1, 14 | cssClass: value.indexOf('C') !== -1, 15 | comment: value.indexOf('M') !== -1 16 | }; 17 | } 18 | }; 19 | }; -------------------------------------------------------------------------------- /nunjucks/rendering/filters/json.spec.js: -------------------------------------------------------------------------------- 1 | var filter = require('./json'); 2 | 3 | describe("json filter", function() { 4 | it("should have the name 'json'", function() { 5 | expect(filter.name).toEqual('json'); 6 | }); 7 | it("should return the value stringified into JSON", function() { 8 | expect(filter.process({ prop1: 'val1', prop2: [1,2,3] })) 9 | .toEqual('{\n'+ 10 | ' "prop1": "val1",\n'+ 11 | ' "prop2": [\n' + 12 | ' 1,\n'+ 13 | ' 2,\n'+ 14 | ' 3\n'+ 15 | ' ]\n'+ 16 | '}'); 17 | }); 18 | }); 19 | 20 | -------------------------------------------------------------------------------- /base/services/encodeCodeBlock.js: -------------------------------------------------------------------------------- 1 | var encoder = new require('node-html-encoder').Encoder(); 2 | module.exports = function encodeCodeBlock() { 3 | return function(str, inline, lang) { 4 | 5 | // Encode any HTML entities in the code string 6 | str = encoder.htmlEncode(str, true); 7 | 8 | // If a language is provided then attach a CSS class to the code element 9 | lang = lang ? ' class="lang-' + lang + '"' : ''; 10 | 11 | str = '' + str + ''; 12 | 13 | // If not inline then wrap the code element in a pre element 14 | if ( !inline ) { 15 | str = '
    ' + str + '
    '; 16 | } 17 | 18 | return str; 19 | }; 20 | }; -------------------------------------------------------------------------------- /jsdoc/tag-defs/index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = [ 3 | require('./name'), 4 | require('./memberof'), 5 | require('./param'), 6 | require('./property'), 7 | require('./returns'), 8 | require('./type'), 9 | require('./requires'), 10 | require('./module'), 11 | require('./description'), 12 | require('./deprecated'), 13 | require('./private'), 14 | require('./see'), 15 | require('./usage'), 16 | require('./animations'), 17 | require('./constructor'), 18 | require('./class'), 19 | require('./classdesc'), 20 | require('./global'), 21 | require('./namespace'), 22 | require('./kind'), 23 | require('./function'), 24 | require('./method') 25 | ]; 26 | -------------------------------------------------------------------------------- /ngdoc/services/getTypeClass.spec.js: -------------------------------------------------------------------------------- 1 | var getTypeClassFactory = require('./getTypeClass'); 2 | 3 | describe("getTypeClass", function() { 4 | it("should convert the type name to a css string", function() { 5 | var getTypeClass = getTypeClassFactory(); 6 | expect(getTypeClass('string')).toEqual('label type-hint type-hint-string'); 7 | expect(getTypeClass('Object')).toEqual('label type-hint type-hint-object'); 8 | expect(getTypeClass('')).toEqual('label type-hint type-hint-object'); 9 | expect(getTypeClass('function() {}')).toEqual('label type-hint type-hint-function'); 10 | expect(getTypeClass('array.')).toEqual('label type-hint type-hint-array'); 11 | }); 12 | }); -------------------------------------------------------------------------------- /jsdoc/tag-defs/memberof.js: -------------------------------------------------------------------------------- 1 | module.exports = function(createDocMessage) { 2 | return { 3 | name: 'memberof', 4 | defaultFn: function(doc) { 5 | if ( doc.docType === 'event' || doc.docType === 'property' || doc.docType === 'method' ) { 6 | throw new Error(createDocMessage('Missing tag "@memberof" for doc of type "'+ doc.docType, doc)); 7 | } 8 | }, 9 | transforms: function(doc, tag, value) { 10 | if ( !(doc.docType === 'event' || doc.docType === 'property' || doc.docType === 'method') ) { 11 | throw new Error(createDocMessage('"@'+ tag.name +'" tag found on non-'+ doc.docType +' document', doc)); 12 | } 13 | return value; 14 | } 15 | }; 16 | }; -------------------------------------------------------------------------------- /jsdoc/services/transforms/trim-whitespace.spec.js: -------------------------------------------------------------------------------- 1 | var transformFactory = require('./trim-whitespace'); 2 | 3 | describe("trim-whitespace", function() { 4 | 5 | var transform; 6 | 7 | beforeEach(function() { 8 | transform = transformFactory(); 9 | }); 10 | 11 | it("should trim newlines and whitespace from the end of the description", function() { 12 | expect(transform({}, {}, 'myId\n\nsome other text \n \n')).toEqual('myId\n\nsome other text'); 13 | }); 14 | 15 | it("should not do anything if the value is not a string", function() { 16 | var someNonStringObject = {}; 17 | expect(transform({}, {}, someNonStringObject)).toEqual(someNonStringObject); 18 | }); 19 | 20 | }); 21 | -------------------------------------------------------------------------------- /ngdoc/file-readers/ngdoc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @dgService ngdocFileReader 3 | * @description 4 | * This file reader will pull the contents from a text file (by default .ngdoc) 5 | * 6 | * The doc will initially have the form: 7 | * ``` 8 | * { 9 | * content: 'the content of the file', 10 | * startingLine: 1 11 | * } 12 | * ``` 13 | */ 14 | module.exports = function ngdocFileReader() { 15 | return { 16 | name: 'ngdocFileReader', 17 | defaultPattern: /\.ngdoc$/, 18 | getDocs: function(fileInfo) { 19 | // We return a single element array because ngdoc files only contain one document 20 | return [{ 21 | content: fileInfo.content, 22 | startingLine: 1 23 | }]; 24 | } 25 | }; 26 | }; -------------------------------------------------------------------------------- /ngdoc/templates/lib/methods.template.html: -------------------------------------------------------------------------------- 1 | {%- if doc.methods %} 2 |

    Methods

    3 | 27 | {%- endif -%} 28 | -------------------------------------------------------------------------------- /ngdoc/templates/api/object.template.html: -------------------------------------------------------------------------------- 1 | {% include "lib/macros.html" %} 2 | {% extends "api/api.template.html" %} 3 | 4 | {% block additional %} 5 | 6 | {% if doc.params or doc.returns or doc.this or doc.kind == 'function' -%} 7 |

    Usage

    8 | {% if doc.usage %} 9 | {$ doc.usage | code $} 10 | {% else %} 11 | {$ functionSyntax(doc) $} 12 | {% endif %} 13 | 14 | {% include "lib/params.template.html" %} 15 | {% include "lib/this.template.html" %} 16 | {% include "lib/returns.template.html" %} 17 | {%- endif %} 18 | 19 | {% include "lib/methods.template.html" %} 20 | {% include "lib/events.template.html" %} 21 | {% include "lib/properties.template.html" %} 22 | 23 | {% endblock %} 24 | -------------------------------------------------------------------------------- /base/processors/unescape-comments.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | 3 | /** 4 | * @dgProcessor unescapeCommentsProcessor 5 | * @description 6 | * Some files (like CSS) use the same comment markers as the jsdoc comments, such as /*. 7 | * To get around this we HTML encode them in the source. 8 | * This processor unescapes them back to normal comment markers 9 | */ 10 | module.exports = function unescapeCommentsProcessor() { 11 | return { 12 | $runAfter: ['docs-rendered'], 13 | $runBefore: ['writing-files'], 14 | $process: function(docs) { 15 | _.forEach(docs, function(doc) { 16 | doc.renderedContent = doc.renderedContent.replace(/\/*/g, '/*').replace(/*\//g, '*/'); 17 | }); 18 | } 19 | }; 20 | }; -------------------------------------------------------------------------------- /ngdoc/templates/lib/events.template.html: -------------------------------------------------------------------------------- 1 | {%- if doc.events %} 2 |

    Events

    3 | 25 | {% endif -%} 26 | -------------------------------------------------------------------------------- /base/processors/unescape-comments.spec.js: -------------------------------------------------------------------------------- 1 | var mockPackage = require('../mocks/mockPackage'); 2 | var Dgeni = require('dgeni'); 3 | 4 | describe("unescapeCommentsProcessor", function() { 5 | it("should convert HTML encoded comments back to their original form", function() { 6 | 7 | var dgeni = new Dgeni([mockPackage()]); 8 | var injector = dgeni.configureInjector(); 9 | var processor = injector.get('unescapeCommentsProcessor'); 10 | 11 | var doc = { 12 | renderedContent: 'Some text containing /* a comment */\nSome text containing /* a comment */' 13 | }; 14 | processor.$process([doc]); 15 | expect(doc.renderedContent).toEqual('Some text containing /* a comment */\nSome text containing /* a comment */'); 16 | }); 17 | }); -------------------------------------------------------------------------------- /ngdoc/inline-tag-defs/link.js: -------------------------------------------------------------------------------- 1 | var INLINE_LINK = /(\S+)(?:\s+([\s\S]+))?/; 2 | 3 | module.exports = function linkInlineTagDef(getLinkInfo, createDocMessage) { 4 | return { 5 | name: 'link', 6 | description: 'Process inline link tags (of the form {@link some/uri Some Title}), replacing them with HTML anchors', 7 | handler: function(doc, tagName, tagDescription) { 8 | 9 | // Parse out the uri and title 10 | return tagDescription.replace(INLINE_LINK, function(match, uri, title) { 11 | 12 | var linkInfo = getLinkInfo(uri, title, doc); 13 | 14 | if ( !linkInfo.valid ) { 15 | throw new Error(createDocMessage(linkInfo.error, doc)); 16 | } 17 | 18 | return '' + linkInfo.title + ''; 19 | }); 20 | } 21 | }; 22 | }; -------------------------------------------------------------------------------- /ngdoc/templates/api/componentGroup.template.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 |

    3 | {%- if doc.title -%} 4 | {$ doc.title $} 5 | {%- elif doc.moduleName -%} 6 | {$ doc.groupType | title $} components in {$ doc.moduleName | code $} 7 | {%- else -%} 8 | Pages 9 | {%- endif -%} 10 |

    11 | 12 | {$ doc.description | marked $} 13 | 14 |
    15 |
    16 | 17 | 18 | 19 | 20 | 21 | {% for page in doc.components %} 22 | 23 | 24 | 25 | 26 | {% endfor %} 27 |
    NameDescription
    {$ page.id | link(page.name, page) $}{$ page.description | firstParagraph | marked $}
    28 |
    29 |
    30 | 31 | {% endblock %} -------------------------------------------------------------------------------- /examples/templates/index.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Example - {$ doc.id $} 6 | {% for stylesheet in doc.stylesheets %} 7 | {% endfor %} 8 | 9 | {% for script in doc.scripts %} 10 | {% endfor %} 11 | 12 | {% if doc.example.fixBase -%} 13 | 16 | {%- endif %} 17 | 18 | 19 | {$ doc.fileContents $} 20 | 21 | -------------------------------------------------------------------------------- /ngdoc/rendering/tags/code.js: -------------------------------------------------------------------------------- 1 | module.exports = function(trimIndentation, encodeCodeBlock) { 2 | return { 3 | tags: ['code'], 4 | 5 | parse: function(parser, nodes) { 6 | var tok = parser.nextToken(); 7 | var args = parser.parseSignature(null, true); 8 | parser.advanceAfterBlockEnd(tok.value); 9 | 10 | var content = parser.parseUntilBlocks("endcode"); 11 | var tag = new nodes.CallExtension(this, 'process', args, [content]); 12 | parser.advanceAfterBlockEnd(); 13 | 14 | return tag; 15 | }, 16 | 17 | process: function(context, lang, content) { 18 | if ( !content ) { 19 | content = lang; 20 | lang = undefined; 21 | } 22 | var trimmedString = trimIndentation(content()); 23 | var codeString = encodeCodeBlock(trimmedString, false, lang); 24 | return codeString; 25 | } 26 | }; 27 | }; -------------------------------------------------------------------------------- /ngdoc/templates/api/filter.template.html: -------------------------------------------------------------------------------- 1 | {% include "lib/macros.html" -%} 2 | {% extends "api/api.template.html" %} 3 | 4 | {% block additional %} 5 |

    Usage

    6 |

    In HTML Template Binding

    7 | {% if doc.usage %} 8 | {$ doc.usage | code $} 9 | {% else %} 10 | {% code -%} 11 | {{ {$ doc.name $}_expression | {$ doc.name $} 12 | {%- for param in doc.params %}{% if not loop.first %} : {$ param.name $}{% endif %}{% endfor -%} 13 | }} 14 | {%- endcode %} 15 | {% endif %} 16 | 17 |

    In JavaScript

    18 | {% code -%} 19 | {%- set sep = joiner(', ') -%} 20 | $filter('{$ doc.name $}')({% for param in doc.params %}{$ sep() $}{$ param.name $}{% endfor -%}) 21 | {%- endcode %} 22 | 23 | {% include "lib/params.template.html" %} 24 | {% include "lib/this.template.html" %} 25 | {% include "lib/returns.template.html" %} 26 | {% endblock %} 27 | -------------------------------------------------------------------------------- /nunjucks/index.js: -------------------------------------------------------------------------------- 1 | var Package = require('dgeni').Package; 2 | 3 | /** 4 | * @dgPackage nunjucks 5 | * @description Provides a template engine powered by Nunjucks 6 | */ 7 | module.exports = new Package('nunjucks', ['base']) 8 | 9 | .factory(require('./services/renderMarkdown')) 10 | .factory(require('./services/nunjucks-template-engine')) 11 | .factory(require('./rendering/tags/marked')) 12 | .factory(require('./rendering/filters/marked')) 13 | 14 | .config(function(templateEngine, markedNunjucksTag, markedNunjucksFilter) { 15 | templateEngine.tags.push(markedNunjucksTag); 16 | templateEngine.filters = templateEngine.filters 17 | .concat(require('./rendering/filters/change-case')) 18 | .concat([ 19 | require('./rendering/filters/first-line'), 20 | require('./rendering/filters/first-paragraph'), 21 | require('./rendering/filters/json'), 22 | markedNunjucksFilter 23 | ]); 24 | }); 25 | -------------------------------------------------------------------------------- /ngdoc/rendering/filters/code.spec.js: -------------------------------------------------------------------------------- 1 | var codeFilterFactory = require('./code'); 2 | 3 | describe("code custom filter", function() { 4 | 5 | var codeFilter, codeSpy; 6 | 7 | beforeEach(function() { 8 | codeSpy = jasmine.createSpy('code').and.callFake(function(value) { return '' + value + ''; }); 9 | codeFilter = codeFilterFactory(codeSpy); 10 | }); 11 | 12 | it("should have the name 'code'", function() { 13 | expect(codeFilter.name).toEqual('code'); 14 | }); 15 | 16 | 17 | it("should call the code utility", function() { 18 | codeFilter.process('function foo() { }'); 19 | expect(codeSpy).toHaveBeenCalledWith('function foo() { }', true, undefined); 20 | }); 21 | 22 | 23 | it("should pass the language to the code utility", function() { 24 | codeFilter.process('function foo() { }', 'js'); 25 | expect(codeSpy).toHaveBeenCalledWith('function foo() { }', true, 'js'); 26 | }); 27 | }); -------------------------------------------------------------------------------- /jsdoc/file-readers/jsdoc.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var esprima = require('esprima'); 3 | 4 | /** 5 | * @dgService jsdocFileReader 6 | * @description 7 | * This file reader will create a simple doc for each js 8 | * file including a code AST of the JavaScript in the file. 9 | */ 10 | module.exports = function jsdocFileReader(log) { 11 | return { 12 | name: 'jsdocFileReader', 13 | defaultPattern: /\.js$/, 14 | getDocs: function(fileInfo) { 15 | 16 | try { 17 | fileInfo.ast = esprima.parse(fileInfo.content, { 18 | loc: true, 19 | attachComment: true 20 | }); 21 | } catch(ex) { 22 | ex.file = fileInfo.filePath; 23 | throw new Error( 24 | _.template('JavaScript error in file "${file}"" [line ${lineNumber}, column ${column}]: "${description}"', ex)); 25 | } 26 | 27 | return [{ 28 | docType: 'jsFile' 29 | }]; 30 | } 31 | }; 32 | }; -------------------------------------------------------------------------------- /jsdoc/processors/code-name.spec.js: -------------------------------------------------------------------------------- 1 | var codeNameProcessorFactory = require('./code-name'); 2 | var jsParser = require('esprima'); 3 | 4 | var mockLog = jasmine.createSpyObj('log', ['error', 'warn', 'info', 'debug', 'silly']); 5 | 6 | describe('code-name doc processor', function() { 7 | it("should understand CallExpressions", function() { 8 | var processor = codeNameProcessorFactory(mockLog); 9 | var ast = jsParser.parse('(function foo() { })()'); 10 | var doc = { codeNode: ast }; 11 | processor.$process([doc]); 12 | expect(doc.codeName).toEqual('foo'); 13 | }); 14 | 15 | it("should understand ArrayExpressions", function() { 16 | var processor = codeNameProcessorFactory(mockLog); 17 | var ast = jsParser.parse("$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];"); 18 | var doc = { codeNode: ast }; 19 | processor.$process([doc]); 20 | expect(doc.codeName).toEqual('$inject'); 21 | }); 22 | 23 | }); -------------------------------------------------------------------------------- /nunjucks/services/renderMarkdown.js: -------------------------------------------------------------------------------- 1 | var marked = require('marked'); 2 | 3 | /** 4 | * @dgService renderMarkdown 5 | * @description 6 | * Render the markdown in the given string as HTML. 7 | */ 8 | module.exports = function renderMarkdown(trimIndentation) { 9 | 10 | var renderer = new marked.Renderer(); 11 | 12 | // remove the leading whitespace from the code block before it gets to the 13 | // markdown code render function 14 | renderer.code = function(code, string, language) { 15 | 16 | var trimmedCode = trimIndentation(code); 17 | var renderedCode = marked.Renderer.prototype.code.call(this, trimmedCode, string, language); 18 | 19 | // Bug in marked - forgets to add a final newline sometimes 20 | if ( !/\n$/.test(renderedCode) ) { 21 | renderedCode += '\n'; 22 | } 23 | 24 | return renderedCode; 25 | }; 26 | 27 | return function(content) { 28 | return marked(content, { renderer: renderer }); 29 | }; 30 | }; -------------------------------------------------------------------------------- /jsdoc/services/transforms/extract-type.spec.js: -------------------------------------------------------------------------------- 1 | var transformFactory = require('./extract-type'); 2 | 3 | describe("extract-type transform", function() { 4 | 5 | var transform; 6 | 7 | beforeEach(function() { 8 | doc = {}; 9 | tag = {}; 10 | transform = transformFactory(); 11 | }); 12 | 13 | it("should extract the type from the description", function() { 14 | 15 | value = ' {string} paramName - Some description \n Some more description'; 16 | value = transform(doc, tag, value); 17 | 18 | expect(tag.typeList).toEqual(['string']); 19 | expect(value).toEqual('paramName - Some description \n Some more description'); 20 | }); 21 | 22 | it("should return the description if no type is found", function() { 23 | value = 'paramName - Some description \n Some more description'; 24 | value = transform(doc, tag, value); 25 | expect(value).toEqual('paramName - Some description \n Some more description'); 26 | }); 27 | }); -------------------------------------------------------------------------------- /jsdoc/tag-defs/description.spec.js: -------------------------------------------------------------------------------- 1 | var tagDefFactory = require('./description'); 2 | 3 | describe("description tag-def", function() { 4 | var tagDef; 5 | 6 | beforeEach(function() { 7 | tagDef = tagDefFactory(); 8 | }); 9 | 10 | describe('transforms', function() { 11 | it("should prepend any non-tag specific description found in the jsdoc comment", function() { 12 | var doc = { tags: { description: 'general description'} }; 13 | var tag = {}; 14 | var value = "tag specific description"; 15 | expect(tagDef.transforms(doc, tag, value)).toEqual('general description\ntag specific description'); 16 | }); 17 | }); 18 | 19 | 20 | describe("defaultFn", function() { 21 | it("should get the contents of the non-tag specific description", function() { 22 | var doc = { tags: { description: 'general description'} }; 23 | expect(tagDef.defaultFn(doc)).toEqual('general description'); 24 | }); 25 | }); 26 | }); -------------------------------------------------------------------------------- /examples/inline-tag-defs/runnableExample.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @dgService runnableExampleInlineTagDef 3 | * @description 4 | * Inject the specified runnable example into the doc 5 | */ 6 | module.exports = function runnableExampleInlineTagDef(exampleMap, createDocMessage) { 7 | return { 8 | name: 'runnableExample', 9 | 10 | handler: function(doc, tagName, description) { 11 | 12 | // The tag description should contain the id of the runnable example doc 13 | var example = exampleMap.get(description); 14 | if ( !example ) { 15 | throw new Error(createDocMessage('No example exists with id "' + description + '".', doc)); 16 | } 17 | if ( !example.runnableExampleDoc ) { 18 | throw new Error(createDocMessage('Example "' + description + '" does not have an associated runnableExampleDoc. Are you missing a processor (examples-generate)?"', doc)); 19 | } 20 | 21 | return example.runnableExampleDoc.renderedContent; 22 | } 23 | }; 24 | }; -------------------------------------------------------------------------------- /base/services/createDocMessage.js: -------------------------------------------------------------------------------- 1 | module.exports = function createDocMessage() { 2 | return function(message, doc, error) { 3 | message = message || ''; 4 | if ( doc ) { 5 | message += ' - doc'; 6 | var docIdentifier = doc.id || doc.name || doc.path; 7 | if ( docIdentifier ) { 8 | message += ' "' + docIdentifier + '"'; 9 | } 10 | if ( doc.docType ) { 11 | message += ' (' + doc.docType + ') '; 12 | } 13 | var filePath = doc.fileInfo && doc.fileInfo.relativePath; 14 | if ( filePath ) { 15 | message += ' - from file "' + filePath + '"'; 16 | if ( doc.startingLine ) { 17 | message += ' - starting at line ' + doc.startingLine; 18 | } 19 | if ( doc.endingLine ) { 20 | message += ', ending at line ' + doc.endingLine; 21 | } 22 | } 23 | } 24 | if ( error ) { 25 | message += '\n\nOriginal Error: \n\n' + error.stack; 26 | } 27 | return message; 28 | }; 29 | }; -------------------------------------------------------------------------------- /nunjucks/rendering/tags/marked.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @dgRenderTag marked 3 | * @description Convert a block of template text from markdown to HTML 4 | */ 5 | module.exports = function markedNunjucksTag(trimIndentation, renderMarkdown) { 6 | return { 7 | tags: ['marked'], 8 | 9 | parse: function(parser, nodes) { 10 | parser.advanceAfterBlockEnd(); 11 | 12 | var content = parser.parseUntilBlocks("endmarked"); 13 | var tag = new nodes.CallExtension(this, 'process', null, [content]); 14 | parser.advanceAfterBlockEnd(); 15 | 16 | return tag; 17 | }, 18 | 19 | process: function(context, content) { 20 | var contentString = content(); 21 | var indent = trimIndentation.calcIndent(contentString); 22 | var trimmedString = trimIndentation.trimIndent(contentString, indent); 23 | var markedString = renderMarkdown(trimmedString); 24 | var reindentedString = trimIndentation.reindent(markedString, indent); 25 | return reindentedString; 26 | } 27 | }; 28 | }; -------------------------------------------------------------------------------- /base/processors/debugDumpProcessor.spec.js: -------------------------------------------------------------------------------- 1 | var path = require('canonical-path'); 2 | var Q = require('q'); 3 | 4 | var mockPackage = require('../mocks/mockPackage'); 5 | var Dgeni = require('dgeni'); 6 | 7 | 8 | describe("debugDumpProcessor", function() { 9 | it("should write out the docs to a file", function() { 10 | 11 | var writeFileSpy = jasmine.createSpy('writeFile').and.returnValue(Q()); 12 | var testPackage = mockPackage().factory('writeFile', function() { return writeFileSpy; }); 13 | 14 | var dgeni = new Dgeni([testPackage]); 15 | var injector = dgeni.configureInjector(); 16 | 17 | var readFilesProcessor = injector.get('readFilesProcessor'); 18 | readFilesProcessor.basePath = path.resolve('some/path'); 19 | 20 | var processor = injector.get('debugDumpProcessor'); 21 | 22 | processor.outputPath = 'build/dump.txt'; 23 | processor.$process([{ val: 'a' }, { val: 'b' }]); 24 | expect(writeFileSpy).toHaveBeenCalledWith(path.resolve('some/path/build/dump.txt'), "[ { val: 'a' }, { val: 'b' } ]"); 25 | }); 26 | }); -------------------------------------------------------------------------------- /base/services/extractLinks.js: -------------------------------------------------------------------------------- 1 | var htmlparser = require("htmlparser2"); 2 | 3 | /** 4 | * @dgService extractLinks 5 | * @description 6 | * Extracts the links and references from a given html 7 | * @param {String} html The html 8 | */ 9 | module.exports = function extractLinks() { 10 | return function(html) { 11 | var result = {hrefs: [], names: []}; 12 | var parser = new htmlparser.Parser({ 13 | onopentag: function(name, attribs) { 14 | 15 | // Parse anchor elements, extracting href and name 16 | if (name === 'a') { 17 | if (attribs.href) { 18 | result.hrefs.push(attribs.href); 19 | } 20 | if (attribs.name) { 21 | result.names.push(attribs.name); 22 | } 23 | } 24 | 25 | // Extract id from other elements 26 | if(attribs.id) { 27 | result.names.push(attribs.id); 28 | } 29 | } 30 | }, { 31 | decodeEntities: true 32 | }); 33 | parser.write(html); 34 | parser.end(); 35 | return result; 36 | }; 37 | }; 38 | -------------------------------------------------------------------------------- /examples/inline-tag-defs/runnableExample.spec.js: -------------------------------------------------------------------------------- 1 | var mockPackage = require('../mocks/mockPackage'); 2 | var Dgeni = require('dgeni'); 3 | 4 | describe("runnableExampleInlineTagDef", function() { 5 | 6 | var exampleMap, tagDef; 7 | 8 | beforeEach(function() { 9 | var dgeni = new Dgeni([mockPackage()]); 10 | var injector = dgeni.configureInjector(); 11 | 12 | exampleMap = injector.get('exampleMap'); 13 | exampleMap.set('some-example', { 14 | runnableExampleDoc: { 15 | renderedContent: 'The rendered content of the some-example example' 16 | } 17 | }); 18 | tagDef = injector.get('runnableExampleInlineTagDef'); 19 | }); 20 | 21 | it("should have the correct name", function() { 22 | expect(tagDef.name).toEqual('runnableExample'); 23 | }); 24 | 25 | it("should lookup the runnableExampleDoc identified in the tag description and return its renderedContent", function() { 26 | expect(tagDef.handler({}, 'runnableExample', 'some-example')).toEqual('The rendered content of the some-example example'); 27 | }); 28 | }); -------------------------------------------------------------------------------- /examples/templates/runnableExample.template.html: -------------------------------------------------------------------------------- 1 | {# Be aware that we need these extra new lines here or marked will not realise that the
    2 | is HTML and wrap each line in a

    - thus breaking the HTML #} 3 | 4 | 5 |

    9 | 10 | {% for fileName, file in doc.example.files %} 11 |
    13 | {% code -%} 14 | {$ file.fileContents $} 15 | {%- endcode %} 16 |
    17 | {% endfor %} 18 | 19 | 20 |
    21 | 22 | 23 | {# Be aware that we need these extra new lines here or marked will not realise that the
    24 | above is HTML and wrap each line in a

    - thus breaking the HTML #} -------------------------------------------------------------------------------- /base/services/resolveUrl.js: -------------------------------------------------------------------------------- 1 | var url = require('url'); 2 | var path = require('canonical-path'); 3 | 4 | /** 5 | * @dgService resolveUrl 6 | * @description 7 | * Calculates the absolute path of the url from the current path, 8 | * the relative path and the base 9 | * @param {String=} currentPath The current path 10 | * @param {String} newPath The new path 11 | * @param {String=} base The base path 12 | */ 13 | module.exports = function resolveUrl() { 14 | return function(currentPath, newPath, base) { 15 | 16 | // Extract only the path and the hash from the newPath 17 | var parsedUrl = url.parse(newPath); 18 | parsedUrl.search = null; 19 | newPath = url.format(parsedUrl); 20 | 21 | if ( base && newPath.charAt(0) !== '/' ) { 22 | // Resolve against the base url if there is a base and the new path is not absolute 23 | newPath = path.resolve(base, newPath).substr(1); 24 | } else { 25 | // Otherwise resolve against the current path 26 | newPath = url.resolve(currentPath || '', newPath); 27 | } 28 | 29 | return newPath; 30 | }; 31 | }; 32 | -------------------------------------------------------------------------------- /ngdoc/rendering/tags/code.spec.js: -------------------------------------------------------------------------------- 1 | var codeTagFactory = require('./code'); 2 | var nunjucks = require('nunjucks'); 3 | 4 | describe("code custom tag", function() { 5 | var codeTag, trimIndentationSpy, codeSpy, env; 6 | 7 | beforeEach(function() { 8 | trimIndentationSpy = jasmine.createSpy('trimIndentation').and.callFake(function(value) { return value.trim(); }); 9 | codeSpy = jasmine.createSpy('code'); 10 | codeTag = codeTagFactory(trimIndentationSpy, codeSpy); 11 | 12 | env = nunjucks.configure('views'); 13 | env.addExtension(codeTag.tags[0], codeTag); 14 | }); 15 | 16 | it("should pass the content to the code utility", function() { 17 | env.renderString('\n{% code %}\nfunction() {}\n{% endcode %}\n'); 18 | expect(codeSpy).toHaveBeenCalledWith('function() {}', false, undefined); 19 | }); 20 | 21 | it("should pass the language if provided to the code utility", function() { 22 | env.renderString('\n{% code lang %}\nfunction() {}\n{% endcode %}\n', { lang: 'js' }); 23 | expect(codeSpy).toHaveBeenCalledWith('function() {}', false, 'js'); 24 | }); 25 | }); -------------------------------------------------------------------------------- /jsdoc/services/transforms/extract-name.js: -------------------------------------------------------------------------------- 1 | // Matches: 2 | // name, [name], [name=default], name text, [name] text, [name=default] text, name - text, [name] - text or [name=default] - text 3 | var NAME_AND_DESCRIPTION = /^\s*(\[([^\]=]+)(?:=([^\]]+))?\]|\S+)((?:[ \t]*\-\s*|\s+)(\S[\s\S]*))?\s*$/; 4 | 5 | /** 6 | * Extract the name information from a tag 7 | * @param {Tag} tag The tag to process 8 | */ 9 | module.exports = function extractNameTransform() { 10 | return function(doc, tag, value) { 11 | 12 | tag.description = value.replace(NAME_AND_DESCRIPTION, function(match, name, optionalName, defaultValue, description, dashDescription) { 13 | tag.name = optionalName || name; 14 | 15 | if ( optionalName ) { 16 | tag.optional = true; 17 | } 18 | 19 | if ( defaultValue ) { 20 | tag.defaultValue = defaultValue; 21 | } 22 | 23 | var aliasParts = tag.name.split('|'); 24 | tag.name = aliasParts[0]; 25 | tag.alias = aliasParts[1]; 26 | return dashDescription || description || ''; 27 | }); 28 | 29 | return tag.description; 30 | 31 | }; 32 | }; -------------------------------------------------------------------------------- /ngdoc/processors/filterNgdocs.spec.js: -------------------------------------------------------------------------------- 1 | var mockPackage = require('../mocks/mockPackage'); 2 | var Dgeni = require('dgeni'); 3 | 4 | function createMockTagCollection(tags) { 5 | return { 6 | getTag: function(value) { 7 | return tags[value]; 8 | } 9 | }; 10 | } 11 | 12 | 13 | describe("filter-ngdocs doc-processor plugin", function() { 14 | var processor; 15 | 16 | beforeEach(function() { 17 | var dgeni = new Dgeni([mockPackage()]); 18 | var injector = dgeni.configureInjector(); 19 | processor = injector.get('filterNgDocsProcessor'); 20 | }); 21 | 22 | it("should only return docs that have the ngdoc tag", function() { 23 | 24 | var doc1 = { tags: createMockTagCollection({ngdoc: 'a'}) }; 25 | 26 | var doc2 = { tags: createMockTagCollection({other: 'b'}) }; 27 | 28 | var doc3 = { tags: createMockTagCollection({ngdoc: 'c', other: 'd'}) }; 29 | 30 | var doc4 = { tags: createMockTagCollection({}) }; 31 | 32 | var docs = [ doc1, doc2, doc3, doc4 ]; 33 | 34 | var filteredDocs = processor.$process(docs); 35 | 36 | expect(filteredDocs).toEqual([doc1, doc3]); 37 | }); 38 | }); -------------------------------------------------------------------------------- /base/processors/debugDumpProcessor.js: -------------------------------------------------------------------------------- 1 | var path = require('canonical-path'); 2 | var util = require("util"); 3 | 4 | /** 5 | * @dgProcessor debugDumpProcessor 6 | * @description 7 | * This processor dumps docs that match a filter to a file 8 | */ 9 | module.exports = function debugDumpProcessor(log, readFilesProcessor, writeFile) { 10 | return { 11 | filterFn: function(docs) { return docs; }, 12 | outputPath: 'debug-dump.txt', 13 | depth: 2, 14 | 15 | $enabled: false, 16 | 17 | $validate: { 18 | filterFn: { presence: true }, 19 | outputPath: { presence: true }, 20 | depth: { presence: true } 21 | }, 22 | 23 | $runBefore: ['writing-files'], 24 | 25 | $process: function(docs) { 26 | log.info('Dumping docs:', this.filterFn, this.outputPath); 27 | var filteredDocs = this.filterFn(docs); 28 | var dumpedDocs = util.inspect(filteredDocs, this.depth); 29 | var outputPath = path.resolve(readFilesProcessor.basePath, this.outputPath); 30 | return writeFile(outputPath, dumpedDocs).then(function() { 31 | return docs; 32 | }); 33 | } 34 | }; 35 | 36 | }; -------------------------------------------------------------------------------- /ngdoc/services/getDocFromAlias.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | 3 | /** 4 | * @dgService getDocFromAlias 5 | * @description Get an array of docs that match this alias, relative to the originating doc. 6 | */ 7 | module.exports = function getDocFromAlias(aliasMap, log) { 8 | 9 | return function getDocFromAlias(alias, originatingDoc) { 10 | var docs = aliasMap.getDocs(alias); 11 | 12 | // If there is more than one item with this name then try to filter them by the originatingDoc's area 13 | if ( docs.length > 1 && originatingDoc && originatingDoc.area) { 14 | docs = _.filter(docs, function(doc) { 15 | return doc.area === originatingDoc.area; 16 | }); 17 | } 18 | 19 | // If filtering by area left us with none then let's start again 20 | if ( docs.length === 0 ) { 21 | docs = aliasMap.getDocs(alias); 22 | } 23 | 24 | // If there is more than one item with this name then try to filter them by the originatingDoc's module 25 | if ( docs.length > 1 && originatingDoc && originatingDoc.module ) { 26 | docs = _.filter(docs, function(doc) { 27 | return doc.module === originatingDoc.module; 28 | }); 29 | } 30 | 31 | return docs; 32 | }; 33 | }; -------------------------------------------------------------------------------- /nunjucks/services/nunjucks-template-engine.js: -------------------------------------------------------------------------------- 1 | var nunjucks = require('nunjucks'); 2 | 3 | /** 4 | * @dgService templateEngine 5 | * @description A nunjucks powered template rendering engine 6 | */ 7 | module.exports = function templateEngine(templateFinder) { 8 | 9 | return { 10 | 11 | /** 12 | * Nunjucks specific options, such as using `{$ $}` for nunjucks interpolation 13 | * rather than `{{ }}`, which conflicts with AngularJS 14 | */ 15 | config: {}, 16 | 17 | filters: [], 18 | tags: [], 19 | 20 | getRenderer: function() { 21 | var loader = new nunjucks.FileSystemLoader(templateFinder.templateFolders, true); 22 | var engine = new nunjucks.Environment(loader, this.config); 23 | 24 | // Configure nunjucks with the custom filters 25 | this.filters.forEach(function(filter) { 26 | engine.addFilter(filter.name, filter.process); 27 | }); 28 | 29 | // Configure nunjucks with the custom tags 30 | this.tags.forEach(function(tag) { 31 | engine.addExtension(tag.tags[0], tag); 32 | }); 33 | 34 | return function render(template, data) { 35 | return engine.render(template, data); 36 | }; 37 | } 38 | }; 39 | }; -------------------------------------------------------------------------------- /base/services/extractLinks.spec.js: -------------------------------------------------------------------------------- 1 | var mockPackage = require('../mocks/mockPackage'); 2 | var Dgeni = require('dgeni'); 3 | 4 | describe("extractLinks", function() { 5 | var urlExtractor; 6 | 7 | beforeEach(function() { 8 | var dgeni = new Dgeni([mockPackage()]); 9 | var injector = dgeni.configureInjector(); 10 | extractLinks = injector.get('extractLinks'); 11 | }); 12 | 13 | it("should extract the hrefs from anchors", function() { 14 | expect(extractLinks('bar').hrefs).toEqual(['foo']); 15 | expect(extractLinks('barshell').hrefs).toEqual(['foo', 'man']); 16 | expect(extractLinks('

    bar
    ').hrefs).toEqual([]); 17 | }); 18 | 19 | it("should extract the names from anchors", function() { 20 | expect(extractLinks('barshell').names).toEqual(['foo']); 21 | expect(extractLinks('
    bar
    ').names).toEqual([]); 22 | }); 23 | 24 | it("should extract the ids from elements", function() { 25 | expect(extractLinks('barshell').names).toEqual(['foo']); 26 | expect(extractLinks('
    bar
    ').names).toEqual(['foo']); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /nunjucks/rendering/filters/marked.spec.js: -------------------------------------------------------------------------------- 1 | var Dgeni = require('dgeni'); 2 | var mockPackage = require('../../mocks/mockPackage'); 3 | 4 | describe("marked custom filter", function() { 5 | var filter; 6 | 7 | beforeEach(function() { 8 | var dgeni = new Dgeni([mockPackage()]); 9 | var injector = dgeni.configureInjector(); 10 | 11 | filter = injector.get('markedNunjucksFilter'); 12 | }); 13 | 14 | it("should have the name 'marked'", function() { 15 | expect(filter.name).toEqual('marked'); 16 | }); 17 | it("should transform the content as markdown trimming excess code indentation", function() { 18 | var result = filter.process( 19 | '## heading 2\n\n' + 20 | 'some paragraph\n\n' + 21 | ' * a bullet point\n\n' + 22 | '```\n' + 23 | ' code\n' + 24 | ' indented code\n' + 25 | ' code\n' + 26 | '```' 27 | ); 28 | expect(result).toEqual( 29 | '

    heading 2

    \n' + 30 | '

    some paragraph

    \n' + 31 | '
      \n' + 32 | '
    • a bullet point
    • \n' + 33 | '
    \n' + 34 | '
    code\n' +
    35 |         '  indented code\n' +
    36 |         'code\n' +
    37 |         '
    \n' + 38 | '' 39 | ); 40 | }); 41 | }); -------------------------------------------------------------------------------- /ngdoc/tag-defs/name.spec.js: -------------------------------------------------------------------------------- 1 | var mockPackage = require('../mocks/mockPackage'); 2 | var Dgeni = require('dgeni'); 3 | 4 | var tagDefFactory = require('./name'); 5 | 6 | describe("name tag-def", function() { 7 | var tagDef; 8 | 9 | beforeEach(function() { 10 | var dgeni = new Dgeni([mockPackage()]); 11 | var injector = dgeni.configureInjector(); 12 | tagDef = injector.invoke(tagDefFactory); 13 | }); 14 | 15 | it("should update the inputType if docType is input", function() { 16 | var doc = { docType: 'input' }; 17 | var tag = {}; 18 | var value = tagDef.transforms(doc, tag, 'input[checkbox]'); 19 | expect(value).toEqual('input[checkbox]'); 20 | expect(doc.inputType).toEqual('checkbox'); 21 | }); 22 | 23 | it("should not update the inputType if docType is not input", function() { 24 | var doc = { docType: 'directive' }; 25 | var tag = {}; 26 | var value = tagDef.transforms(doc, tag, 'input[checkbox]'); 27 | expect(value).toEqual('input[checkbox]'); 28 | expect(doc.inputType).toBeUndefined(); 29 | }); 30 | 31 | it("should throw error if the docType is 'input' and the name is not a valid format", function() { 32 | var doc = { docType: 'input' }; 33 | var tag = {}; 34 | expect(function() { 35 | tagDef.transforms(doc, tag, 'invalidInputName'); 36 | }).toThrow(); 37 | }); 38 | 39 | }); 40 | -------------------------------------------------------------------------------- /base/services/encodeCodeBlock.spec.js: -------------------------------------------------------------------------------- 1 | var mockPackage = require('../mocks/mockPackage'); 2 | var Dgeni = require('dgeni'); 3 | 4 | describe("code utility", function() { 5 | var encodeCodeBlock; 6 | 7 | beforeEach(function() { 8 | var dgeni = new Dgeni([mockPackage()]); 9 | var injector = dgeni.configureInjector(); 10 | encodeCodeBlock = injector.get('encodeCodeBlock'); 11 | }); 12 | 13 | it("should wrap the string in code and pre tags", function() { 14 | expect(encodeCodeBlock('abc')).toEqual('
    abc
    '); 15 | }); 16 | 17 | it("should HTML encode the string", function() { 18 | expect(encodeCodeBlock('
    &
    ')).toEqual('
    <div>&</div>
    '); 19 | }); 20 | 21 | it("should encode HTML entities", function() { 22 | expect(encodeCodeBlock('
    ')).toEqual('
    <div>&#10;</div>
    '); 23 | }); 24 | 25 | describe("inline", function() { 26 | it("should only wrap in a code tag", function() { 27 | expect(encodeCodeBlock('abc', true)).toEqual('abc'); 28 | }); 29 | }); 30 | 31 | describe("language", function() { 32 | it("should add a CSS class if a language is specified", function() { 33 | expect(encodeCodeBlock('abc', true, 'js')).toEqual('abc'); 34 | }); 35 | }); 36 | }); -------------------------------------------------------------------------------- /ngdoc/file-readers/ngdoc.spec.js: -------------------------------------------------------------------------------- 1 | var ngdocFileReaderFactory = require('./ngdoc'); 2 | var path = require('canonical-path'); 3 | 4 | describe("ngdocFileReader", function() { 5 | 6 | var fileReader; 7 | 8 | var createFileInfo = function(file, content, basePath) { 9 | return { 10 | fileReader: fileReader.name, 11 | filePath: file, 12 | baseName: path.basename(file, path.extname(file)), 13 | extension: path.extname(file).replace(/^\./, ''), 14 | basePath: basePath, 15 | relativePath: path.relative(basePath, file), 16 | content: content 17 | }; 18 | }; 19 | 20 | 21 | beforeEach(function() { 22 | fileReader = ngdocFileReaderFactory(); 23 | }); 24 | 25 | 26 | describe("defaultPattern", function() { 27 | it("should match .ngdoc files", function() { 28 | expect(fileReader.defaultPattern.test('abc.ngdoc')).toBeTruthy(); 29 | expect(fileReader.defaultPattern.test('abc.js')).toBeFalsy(); 30 | }); 31 | }); 32 | 33 | 34 | describe("getDocs", function() { 35 | it('should return an object containing info about the file and its contents', function() { 36 | var fileInfo = createFileInfo('foo/bar.ngdoc', 'A load of content', 'base/path'); 37 | expect(fileReader.getDocs(fileInfo)).toEqual([{ 38 | content: 'A load of content', 39 | startingLine: 1 40 | }]); 41 | }); 42 | }); 43 | }); 44 | 45 | -------------------------------------------------------------------------------- /ngdoc/tag-defs/module.spec.js: -------------------------------------------------------------------------------- 1 | var path = require('canonical-path'); 2 | var tagDefFactory = require('./module'); 3 | 4 | describe("module tag-def", function() { 5 | it("should calculate the module from the second segment of the file path", function() { 6 | var tagDef = tagDefFactory(); 7 | expect(tagDef.defaultFn({ area: 'api', fileInfo: { relativePath: 'ng/service/$http.js' } })).toEqual('ng'); 8 | }); 9 | 10 | it("should use the relative file path", function() { 11 | var tagDef = tagDefFactory(); 12 | var relativePath = 'ng/service/$http.js'; 13 | expect(tagDef.defaultFn({ area: 'api', fileInfo: { filePath: path.resolve(relativePath), relativePath: relativePath } })).toEqual('ng'); 14 | }); 15 | 16 | it("should not calculate module if the doc is not in 'api' area", function() { 17 | var tagDef = tagDefFactory(); 18 | var relativePath = 'guide/concepts.ngdoc'; 19 | expect(tagDef.defaultFn({ area: 'guide', fileInfo: { filePath: path.resolve(relativePath), relativePath: relativePath } })).toBeUndefined(); 20 | }); 21 | 22 | it("should not calculate module if the doc has docType 'overview'", function() { 23 | var tagDef = tagDefFactory(); 24 | var relativePath = 'api/index.ngdoc'; 25 | expect(tagDef.defaultFn({ docType: 'overview', area: 'api', fileInfo: { filePath: path.resolve(relativePath), relativePath: relativePath } })).toBeUndefined(); 26 | }); 27 | }); -------------------------------------------------------------------------------- /ngdoc/processors/providerDocs.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | 3 | /** 4 | * @dgProcessor providerDocsProcessor 5 | * @description 6 | * Connect docs for services to docs for their providers 7 | */ 8 | module.exports = function providerDocsProcessor(log, aliasMap, createDocMessage) { 9 | return { 10 | $runAfter: ['ids-computed', 'memberDocsProcessor'], 11 | $runBefore: ['computing-paths'], 12 | $process: function(docs) { 13 | 14 | // Map services to their providers 15 | _.forEach(docs, function(doc) { 16 | if ( doc.docType === 'provider' ) { 17 | var serviceId = doc.id.replace(/provider:/, 'service:').replace(/Provider$/, ''); 18 | var serviceDocs = aliasMap.getDocs(serviceId); 19 | 20 | if ( serviceDocs.length === 1 ) { 21 | serviceDoc = serviceDocs[0]; 22 | doc.serviceDoc = serviceDoc; 23 | serviceDoc.providerDoc = doc; 24 | } else if ( serviceDocs.length === 0 ) { 25 | log.warn(createDocMessage('Missing service "' + serviceId + '" for provider', doc)); 26 | } else { 27 | log.warn(createDocMessage('Ambiguous service name "' + serviceId + '" for provider', doc) + '\n' + 28 | _.reduce(serviceDocs, function(msg, doc) { 29 | return msg + '\n "' + doc.id + '"'; 30 | }, 'Matching docs: ')); 31 | } 32 | } 33 | }); 34 | } 35 | }; 36 | }; -------------------------------------------------------------------------------- /nunjucks/services/renderMarkdown.spec.js: -------------------------------------------------------------------------------- 1 | var Dgeni = require('dgeni'); 2 | var mockPackage = require('../mocks/mockPackage'); 3 | 4 | describe("renderMarkdown", function() { 5 | 6 | var renderMarkdown, trimIndentation; 7 | 8 | beforeEach(function() { 9 | var dgeni = new Dgeni([mockPackage()]); 10 | var injector = dgeni.configureInjector(); 11 | trimIndentation = injector.get('trimIndentation'); 12 | renderMarkdown = injector.get('renderMarkdown'); 13 | }); 14 | 15 | it("should render the given markdown content as HTML", function() { 16 | var html = renderMarkdown( 17 | '## heading 2\n\n' + 18 | 'some paragraph\n\n' + 19 | '* a bullet point'); 20 | expect(html).toEqual( 21 | '

    heading 2

    \n' + 22 | '

    some paragraph

    \n' + 23 | '
      \n' + 24 | '
    • a bullet point
    • \n' + 25 | '
    \n' 26 | ); 27 | }); 28 | 29 | it("should trim leading whitespace from code blocks", function() { 30 | var html = renderMarkdown( 31 | 'some test\n\n' + 32 | '```\n' + 33 | ' code\n' + 34 | ' indented code\n' + 35 | ' more code\n' + 36 | '```\n\n' + 37 | 'more text' 38 | ); 39 | expect(html).toEqual( 40 | '

    some test

    \n' + 41 | '
    code\n' +
    42 |       '  indented code\n' +
    43 |       'more code\n' +
    44 |       '
    \n' + 45 | '

    more text

    \n' 46 | ); 47 | 48 | }); 49 | 50 | }); -------------------------------------------------------------------------------- /ngdoc/processors/generateComponentGroups.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | 3 | /** 4 | * @dgProcessor generateComponentGroupsProcessor 5 | * @description 6 | * Generate documents for each group of components (by type) within a module 7 | */ 8 | module.exports = function generateComponentGroupsProcessor(moduleMap) { 9 | return { 10 | $runAfter: ['moduleDocsProcessor'], 11 | $runBefore: ['computing-paths'], 12 | $process: function(docs) { 13 | 14 | moduleMap.forEach(function(module) { 15 | 16 | _(module.components) 17 | .groupBy('docType') 18 | .tap(function(docTypes) { 19 | // We don't want the overview docType to be represented as a componentGroup 20 | delete docTypes.overview; 21 | }) 22 | .map(function(docs, docType) { 23 | return { 24 | id: module.id + '.' + docType, 25 | docType: 'componentGroup', 26 | groupType: docType, 27 | moduleName: module.name, 28 | moduleDoc: module, 29 | area: module.area, 30 | name: docType + ' components in ' + module.name, 31 | components: docs 32 | }; 33 | }) 34 | .tap(function(groups) { 35 | module.componentGroups = groups; 36 | _.forEach(groups, function(group) { 37 | docs.push(group); 38 | }); 39 | }); 40 | }); 41 | } 42 | }; 43 | }; -------------------------------------------------------------------------------- /base/processors/write-files.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var path = require('canonical-path'); 3 | var fs = require('q-io/fs'); 4 | var Q = require('q'); 5 | 6 | /** 7 | * @dgProcessor writeFilesProcessor 8 | * @param {Object} log A service that provides logging 9 | * @description Write the value of `doc.renderedContent` to a file a `doc.outputPath`. 10 | * @property {String} outputFolder The base path to the folder where files are outputted 11 | */ 12 | module.exports = function writeFilesProcessor(log, readFilesProcessor, writeFile) { 13 | return { 14 | outputFolder: null, 15 | $validate: { 16 | outputFolder: { presence: true }, 17 | }, 18 | $runAfter:['writing-files'], 19 | $runBefore: ['files-written'], 20 | $process: function(docs) { 21 | var outputFolder = this.outputFolder; 22 | return Q.all(_.map(docs, function(doc) { 23 | 24 | if ( !doc.outputPath ) { 25 | log.debug('Document "' + doc.id + ', ' + doc.docType + '" has no outputPath.'); 26 | } else { 27 | 28 | var outputFile = path.resolve(readFilesProcessor.basePath, outputFolder, doc.outputPath); 29 | 30 | log.silly('writing file', outputFile); 31 | return writeFile(outputFile, doc.renderedContent).then(function() { 32 | log.debug('written file', outputFile); 33 | return outputFile; 34 | }); 35 | 36 | } 37 | })).then(function() { 38 | return docs; 39 | }); 40 | } 41 | }; 42 | }; -------------------------------------------------------------------------------- /base/processors/write-files.spec.js: -------------------------------------------------------------------------------- 1 | var path = require('canonical-path'); 2 | var Q = require('q'); 3 | 4 | var mockPackage = require('../mocks/mockPackage'); 5 | var Dgeni = require('dgeni'); 6 | 7 | describe("writeFilesProcessor", function() { 8 | var processor, writeFileSpy, mockLog; 9 | 10 | 11 | beforeEach(function() { 12 | writeFileSpy = jasmine.createSpy('writeFile').and.returnValue(Q()); 13 | 14 | var testPackage = mockPackage().factory('writeFile', function() { return writeFileSpy; }); 15 | 16 | var dgeni = new Dgeni([testPackage]); 17 | var injector = dgeni.configureInjector(); 18 | 19 | var readFilesProcessor = injector.get('readFilesProcessor'); 20 | readFilesProcessor.basePath = path.resolve('some/path'); 21 | 22 | processor = injector.get('writeFilesProcessor'); 23 | processor.outputFolder = 'build'; 24 | 25 | mockLog = injector.get('log'); 26 | }); 27 | 28 | it("should write each document to a file", function() { 29 | processor.$process([{ renderedContent: 'SOME RENDERED CONTENT', outputPath: 'doc/path.html' }]); 30 | expect(writeFileSpy).toHaveBeenCalledWith(path.resolve('some/path/build/doc/path.html'), 'SOME RENDERED CONTENT'); 31 | }); 32 | 33 | it("should log a debug message if a doc has no outputPath", function() { 34 | processor.$process([{ renderedContent: 'SOME RENDERED CONTENT', id: 'doc1', docType: 'test' }]); 35 | expect(mockLog.debug).toHaveBeenCalledWith('Document "doc1, test" has no outputPath.'); 36 | }); 37 | }); -------------------------------------------------------------------------------- /ngdoc/tag-defs/restrict.spec.js: -------------------------------------------------------------------------------- 1 | var tagDefFactory = require('./restrict'); 2 | 3 | describe("restrict tag-def", function() { 4 | var tagDef; 5 | 6 | beforeEach(function() { 7 | tagDef = tagDefFactory(); 8 | }); 9 | 10 | it("should convert a restrict tag text to an object", function() { 11 | expect(tagDef.transforms({}, {}, 'A')).toEqual({ element: false, attribute: true, cssClass: false, comment: false }); 12 | expect(tagDef.transforms({}, {}, 'C')).toEqual({ element: false, attribute: false, cssClass: true, comment: false }); 13 | expect(tagDef.transforms({}, {}, 'E')).toEqual({ element: true, attribute: false, cssClass: false, comment: false }); 14 | expect(tagDef.transforms({}, {}, 'M')).toEqual({ element: false, attribute: false, cssClass: false, comment: true }); 15 | expect(tagDef.transforms({}, {}, 'ACEM')).toEqual({ element: true, attribute: true, cssClass: true, comment: true }); 16 | }); 17 | 18 | it("should default to restricting to an attribute if no tag is found and the doc is for a directive", function() { 19 | expect(tagDef.defaultFn({ docType: 'directive' })).toEqual({ element: false, attribute: true, cssClass: false, comment: false }); 20 | expect(tagDef.defaultFn({ docType: 'input' })).toEqual({ element: false, attribute: true, cssClass: false, comment: false }); 21 | }); 22 | 23 | it("should not add a restrict property if the docType is not 'directive'", function() { 24 | expect(tagDef.defaultFn({ docType: 'service' })).toBeUndefined(); 25 | }); 26 | }); 27 | 28 | -------------------------------------------------------------------------------- /examples/processors/protractor-generate.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _ = require('lodash'); 4 | 5 | /** 6 | * dgProcessor generateProtractorTestsProcessor 7 | * @description 8 | * Generate a protractor test files from the e2e tests in the examples 9 | */ 10 | module.exports = function generateProtractorTestsProcessor(exampleMap) { 11 | return { 12 | deployments: [], 13 | basePath: '', 14 | $validate: { 15 | deployments: { presence: true }, 16 | }, 17 | $runAfter: ['adding-extra-docs'], 18 | $runBefore: ['extra-docs-added'], 19 | $process: function(docs) { 20 | 21 | var deployments = this.deployments; 22 | var basePath = this.basePath; 23 | 24 | exampleMap.forEach(function(example) { 25 | _.forEach(example.files, function(file) { 26 | 27 | // Check if it's a Protractor test. 28 | if (file.type === 'protractor') { 29 | 30 | _.forEach(deployments, function(deployment) { 31 | docs.push(createProtractorDoc(example, deployment, file, basePath)); 32 | }); 33 | } 34 | 35 | }); 36 | }); 37 | } 38 | }; 39 | }; 40 | 41 | function createProtractorDoc(example, deployment, file, basePath) { 42 | return { 43 | docType: 'e2e-test', 44 | id: 'protractorTest' + '-' + example.id + '-' + deployment.name, 45 | example: example, 46 | deployment: deployment, 47 | template: 'protractorTests.template.js', 48 | innerTest: file.fileContents, 49 | 'ng-app-included': example['ng-app-included'], 50 | basePath: basePath 51 | }; 52 | } -------------------------------------------------------------------------------- /jsdoc/services/transforms/extract-name.spec.js: -------------------------------------------------------------------------------- 1 | var transformFactory = require('./extract-name'); 2 | 3 | describe("extract-name transform", function() { 4 | var doc, tag, value, transform; 5 | 6 | beforeEach(function() { 7 | doc = {}; 8 | tag = {}; 9 | transform = transformFactory(); 10 | }); 11 | 12 | it("should extract the name from the description", function() { 13 | 14 | value = ' paramName - Some description \n Some more description'; 15 | value = transform(doc, tag, value); 16 | 17 | expect(tag.name).toEqual('paramName'); 18 | expect(value).toEqual('Some description \n Some more description'); 19 | }); 20 | 21 | it("should extract an optional name", function() { 22 | value = '[someName]'; 23 | value = transform(doc, tag, value); 24 | expect(tag.name).toEqual('someName'); 25 | expect(tag.optional).toEqual(true); 26 | expect(value).toEqual(''); 27 | }); 28 | 29 | it("should extract a name and its default value", function() { 30 | value = '[someName=someDefault]'; 31 | value = transform(doc, tag, value); 32 | expect(tag.name).toEqual('someName'); 33 | expect(tag.optional).toEqual(true); 34 | expect(tag.defaultValue).toEqual('someDefault'); 35 | expect(value).toEqual(''); 36 | }); 37 | 38 | it("should extract a param name alias", function() { 39 | value = 'paramName|aliasName some description'; 40 | value = transform(doc, tag, value); 41 | expect(tag.name).toEqual('paramName'); 42 | expect(tag.alias).toEqual('aliasName'); 43 | expect(value).toEqual('some description'); 44 | }); 45 | 46 | }); -------------------------------------------------------------------------------- /examples/index.js: -------------------------------------------------------------------------------- 1 | var path = require('canonical-path'); 2 | var packagePath = __dirname; 3 | var Package = require('dgeni').Package; 4 | 5 | module.exports = new Package('examples', ['jsdoc']) 6 | 7 | .processor(require('./processors/examples-parse')) 8 | .processor(require('./processors/examples-generate')) 9 | .processor(require('./processors/protractor-generate')) 10 | 11 | .factory(require('./services/exampleMap')) 12 | .factory(require('./inline-tag-defs/runnableExample')) 13 | 14 | .config(function(templateFinder, generateExamplesProcessor) { 15 | templateFinder.templateFolders.push(path.resolve(packagePath, 'templates')); 16 | 17 | }) 18 | 19 | .config(function(inlineTagProcessor, runnableExampleInlineTagDef) { 20 | inlineTagProcessor.inlineTagDefinitions.push(runnableExampleInlineTagDef); 21 | }) 22 | 23 | .config(function(computePathsProcessor, computeIdsProcessor) { 24 | computePathsProcessor.pathTemplates.push({ 25 | docTypes: ['example'], 26 | pathTemplate: 'examples/${example.id}', 27 | outputPathTemplate: 'examples/${example.id}/index${deploymentQualifier}.html' 28 | }); 29 | computePathsProcessor.pathTemplates.push({ 30 | docTypes: ['example-file'], 31 | getPath: function() {}, 32 | outputPathTemplate: 'examples/${id}' 33 | }); 34 | computePathsProcessor.pathTemplates.push({ 35 | docTypes: ['runnableExample' ], 36 | pathTemplate: 'examples/${example.id}', 37 | getOutputPath: function() {}, 38 | }); 39 | 40 | computeIdsProcessor.idTemplates.push({ 41 | docTypes: ['example', 'example-file', 'runnableExample'], 42 | getAliases: function(doc) { return [doc.id]; } 43 | }); 44 | }); -------------------------------------------------------------------------------- /jsdoc/tag-defs/memberof.spec.js: -------------------------------------------------------------------------------- 1 | var mockPackage = require('../mocks/mockPackage'); 2 | var Dgeni = require('dgeni'); 3 | var tagDefFactory = require('./memberof'); 4 | 5 | describe("memberof tag-def", function() { 6 | var tagDef; 7 | 8 | beforeEach(function() { 9 | var dgeni = new Dgeni([mockPackage()]); 10 | var injector = dgeni.configureInjector(); 11 | tagDef = injector.invoke(tagDefFactory); 12 | }); 13 | 14 | describe('transforms', function() { 15 | it("should throw an exception if the docType is not 'event', 'method' or 'property'", function() { 16 | expect(function() { 17 | tagDef.transforms({ docType: 'unknown'}); 18 | }).toThrowError(); 19 | 20 | expect(function() { 21 | tagDef.transforms({ docType: 'event'}); 22 | }).not.toThrowError(); 23 | 24 | expect(function() { 25 | tagDef.transforms({ docType: 'method'}); 26 | }).not.toThrowError(); 27 | 28 | expect(function() { 29 | tagDef.transforms({ docType: 'property'}); 30 | }).not.toThrowError(); 31 | }); 32 | }); 33 | 34 | 35 | describe("defaultFn", function() { 36 | it("should throw an exception if the docType is 'event', 'method' or 'property'", function() { 37 | expect(function() { 38 | tagDef.defaultFn({ docType: 'unknown'}); 39 | }).not.toThrowError(); 40 | 41 | expect(function() { 42 | tagDef.defaultFn({ docType: 'event'}); 43 | }).toThrowError(); 44 | 45 | expect(function() { 46 | tagDef.defaultFn({ docType: 'method'}); 47 | }).toThrowError(); 48 | 49 | expect(function() { 50 | tagDef.defaultFn({ docType: 'property'}); 51 | }).toThrowError(); 52 | }); 53 | }); 54 | }); -------------------------------------------------------------------------------- /ngdoc/templates/api/api.template.html: -------------------------------------------------------------------------------- 1 | {% extends "base.template.html" %} 2 | 3 | {% block content %} 4 | 5 | 6 |  View Source 7 | 8 | 9 | {% block header %} 10 |
    11 |

    {$ doc.name $}

    12 |
      13 | {% block related_components %}{% endblock %} 14 |
    1. 15 | - {$ doc.docType $} in module {$ doc.moduleDoc.name $} 16 |
    2. 17 |
    18 |
    19 | {% endblock %} 20 | 21 | {% block description %} 22 |
    23 | {$ doc.description | marked $} 24 |
    25 | {% endblock %} 26 | 27 | {% if doc.deprecated %} 28 |
    29 | Deprecated API 30 | {$ doc.deprecated| marked $} 31 |
    32 | {% endif %} 33 | 34 |
    35 | {% block dependencies %} 36 | {%- if doc.requires %} 37 |

    Dependencies

    38 |
      39 | {% for require in doc.requires %}
    • {$ require | link $}
    • {% endfor %} 40 |
    41 | {% endif -%} 42 | {% endblock %} 43 | 44 | {% block additional %} 45 | {% endblock %} 46 | 47 | {% block examples %} 48 | {%- if doc.examples %} 49 |

    Example

    50 | {%- for example in doc.examples -%} 51 | {$ example | marked $} 52 | {%- endfor -%} 53 | {% endif -%} 54 | {% endblock %} 55 |
    56 | 57 | {% endblock %} 58 | -------------------------------------------------------------------------------- /jsdoc/lib/TagCollection.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var StringMap = require('stringmap'); 3 | 4 | /** 5 | * A collection of tags that can be looked up by their tagDefinition. 6 | */ 7 | var TagCollection = function(tags) { 8 | this.tags = []; 9 | this.tagsByName = new StringMap(); 10 | this.badTags = []; 11 | this.description = ''; 12 | 13 | _.forEach(tags, function(tag) { 14 | this.addTag(tag); 15 | }, this); 16 | }; 17 | 18 | TagCollection.prototype = { 19 | 20 | /** 21 | * Add a new tag to the collection. 22 | * @param {Tag} tag The tag to add 23 | */ 24 | addTag: function(tag) { 25 | if ( !tag.errors && tag.tagDef ) { 26 | this.tags.push(tag); 27 | 28 | var tags = this.tagsByName.get(tag.tagDef.name) || []; 29 | tags.push(tag); 30 | this.tagsByName.set(tag.tagDef.name, tags); 31 | 32 | } else { 33 | this.badTags.push(tag); 34 | } 35 | }, 36 | 37 | /** 38 | * Remove a tag from the collection 39 | * @param {Tag} tag The tag to remove 40 | */ 41 | removeTag: function(tag) { 42 | _.remove(this.tags, tag); 43 | _.remove(this.tagsByName.get(tag.tagDef.name), tag); 44 | }, 45 | 46 | /** 47 | * Get the first tag in the collection that has the specified tag definition 48 | * @param {string} name The name of the tag definition whose tag we should get 49 | * @return {Tag} 50 | */ 51 | getTag: function(name) { 52 | return this.getTags(name)[0]; 53 | }, 54 | 55 | /** 56 | * Get the tags in the collection that have the specified tag definition 57 | * @param {string} name The name of the tag definition whose tags we should get 58 | * @return {Array} 59 | */ 60 | getTags: function(name) { 61 | return this.tagsByName.get(name) || []; 62 | } 63 | 64 | }; 65 | 66 | 67 | module.exports = TagCollection; -------------------------------------------------------------------------------- /ngdoc/templates/lib/macros.html: -------------------------------------------------------------------------------- 1 | {% macro typeList(types) -%} 2 | {% for typeName in types %}{$ typeName | escape $}{% endfor %} 3 | {%- endmacro -%} 4 | 5 | {%- macro paramTable(params) %} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% for param in params %} 16 | 17 | 22 | 25 | 29 | 30 | {% endfor %} 31 | 32 |
    ParamTypeDetails
    18 | {$ param.name $} 19 | {% if param.alias %}| {$ param.alias $}{% endif %} 20 | {% if param.type.optional %}
    (optional)
    {% endif %} 21 |
    23 | {$ typeList(param.typeList) $} 24 | 26 | {$ param.description | marked $} 27 | {% if param.defaultValue %}

    (default: {$ param.defaultValue $})

    {% endif %} 28 |
    33 | {% endmacro -%} 34 | 35 | 36 | {%- macro directiveParam(name, type, join, sep) %} 37 | {%- if type.optional %}[{% endif -%} 38 | {$ name | dashCase $}{$ join $}{$ type.description $}{$ sep $} 39 | {%- if type.optional %}]{% endif -%} 40 | {% endmacro -%} 41 | 42 | {%- macro functionSyntax(fn) %} 43 | {%- set sep = joiner(', ') -%} 44 | {% marked -%} 45 | `{$ fn.name $}({%- for param in fn.params %}{$ sep() $} 46 | {%- if param.type.optional %}[{% endif -%} 47 | {$ param.name $} 48 | {%- if param.type.optional %}]{% endif -%} 49 | {% endfor %});` 50 | {%- endmarked %} 51 | {% endmacro -%} 52 | 53 | {%- macro typeInfo(fn) -%} 54 | 55 | 56 | 57 | 58 | 59 |
    {$ typeList(fn.typeList) $}{$ fn.description | marked $}
    60 | {%- endmacro -%} 61 | -------------------------------------------------------------------------------- /ngdoc/services/getDocFromAlias.spec.js: -------------------------------------------------------------------------------- 1 | var mockPackage = require('../mocks/mockPackage'); 2 | var Dgeni = require('dgeni'); 3 | 4 | var getDocFromAlias, aliasMap; 5 | 6 | describe("getDocFromAlias", function() { 7 | beforeEach(function() { 8 | var dgeni = new Dgeni([mockPackage()]); 9 | var injector = dgeni.configureInjector(); 10 | aliasMap = injector.get('aliasMap'); 11 | getDocFromAlias = injector.get('getDocFromAlias'); 12 | }); 13 | 14 | it("should return an array of docs that match the alias", function() { 15 | var doc1 = { aliases: ['a','b','c'] }; 16 | var doc2 = { aliases: ['a','b'] }; 17 | var doc3 = { aliases: ['a'] }; 18 | aliasMap.addDoc(doc1); 19 | aliasMap.addDoc(doc2); 20 | aliasMap.addDoc(doc3); 21 | 22 | expect(getDocFromAlias('a')).toEqual([doc1, doc2, doc3]); 23 | expect(getDocFromAlias('b')).toEqual([doc1, doc2]); 24 | expect(getDocFromAlias('c')).toEqual([doc1]); 25 | }); 26 | 27 | it("should return docs that match the alias and originating doc's area", function() { 28 | var doc1 = { aliases: ['a'], area: 'api'}; 29 | var doc2 = { aliases: ['a'], area: 'api'}; 30 | var doc3 = { aliases: ['a'], area: 'other'}; 31 | aliasMap.addDoc(doc1); 32 | aliasMap.addDoc(doc2); 33 | aliasMap.addDoc(doc3); 34 | 35 | expect(getDocFromAlias('a', {area: 'api'})).toEqual([doc1, doc2]); 36 | }); 37 | 38 | it("should return docs that match the alias and originating doc's area and module", function() { 39 | var doc1 = { aliases: ['a'], area: 'api', module: 'ng'}; 40 | var doc2 = { aliases: ['a'], area: 'api', module: 'ngMock'}; 41 | var doc3 = { aliases: ['a'], area: 'other', module: 'ng'}; 42 | aliasMap.addDoc(doc1); 43 | aliasMap.addDoc(doc2); 44 | aliasMap.addDoc(doc3); 45 | 46 | expect(getDocFromAlias('a', {area: 'api', module:'ng'})).toEqual([doc1]); 47 | }); 48 | }); -------------------------------------------------------------------------------- /base/services/aliasMap.js: -------------------------------------------------------------------------------- 1 | var StringMap = require('stringmap'); 2 | 3 | /** 4 | * @dgService aliasMap 5 | * @description 6 | * A map of id aliases to docs 7 | */ 8 | module.exports = function aliasMap() { 9 | var map = new StringMap(); 10 | 11 | return { 12 | /** 13 | * Add a new document to the map associating it with each of its potential aliases 14 | * @param {Object} doc The document to add to the map 15 | */ 16 | addDoc: function(doc) { 17 | 18 | if ( !doc.aliases ) return; 19 | 20 | // We store references to this doc under all its id aliases in the map 21 | // This map will be used to match references to docs 22 | doc.aliases.forEach(function(alias) { 23 | 24 | // Try to get a list of docs that match this alias 25 | var matchedDocs = map.get(alias) || []; 26 | matchedDocs.push(doc); 27 | map.set(alias, matchedDocs); 28 | 29 | }); 30 | 31 | }, 32 | 33 | /** 34 | * Remove a document from the map, including entries for each of its aliases 35 | * @param {Object} doc The document to remove from the map 36 | */ 37 | removeDoc: function(doc) { 38 | 39 | doc.aliases.forEach(function(alias) { 40 | 41 | var matchedDocs = map.get(alias); 42 | if ( matchedDocs ) { 43 | // We have an array of docs so we need to remove the culprit 44 | var index = matchedDocs.indexOf(doc); 45 | if ( index !== -1 ) { 46 | matchedDocs.splice(index, 1); 47 | } 48 | } 49 | 50 | }); 51 | }, 52 | 53 | /** 54 | * Get the documents associated with the given alias 55 | * @param {string} alias The alias to search for 56 | * @return {Array} An array containing all matched docs 57 | */ 58 | getDocs: function(alias) { 59 | return map.get(alias) || []; 60 | } 61 | }; 62 | 63 | }; -------------------------------------------------------------------------------- /ngdoc/services/getLinkInfo.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var path = require('canonical-path'); 3 | 4 | /** 5 | * @dgService getLinkInfo 6 | * @description 7 | * Get link information to a document that matches the given url 8 | * @kind function 9 | * @param {String} url The url to match 10 | * @param {String} title An optional title to return in the link information 11 | * @return {Object} The link information 12 | */ 13 | module.exports = function getLinkInfo(getDocFromAlias, encodeCodeBlock) { 14 | 15 | return function getLinkInfoImpl(url, title, currentDoc) { 16 | var linkInfo = { 17 | url: url, 18 | type: 'url', 19 | valid: true, 20 | title: title || url 21 | }; 22 | 23 | if ( !url ) { 24 | throw new Error('Invalid url'); 25 | } 26 | 27 | var docs = getDocFromAlias(url, currentDoc); 28 | 29 | if ( docs.length > 1 ) { 30 | 31 | linkInfo.valid = false; 32 | linkInfo.error = 'Ambiguous link: "' + url + '".\n' + 33 | docs.reduce(function(msg, doc) { return msg + '\n "' + doc.id + '" ('+ doc.docType + ') : (' + doc.area + ')'; }, 'Matching docs: '); 34 | 35 | } else if ( docs.length === 1 ) { 36 | 37 | linkInfo.url = docs[0].path; 38 | linkInfo.title = title || encodeCodeBlock(docs[0].name, true); 39 | linkInfo.type = 'doc'; 40 | 41 | } else if ( url.indexOf('#') > 0 ) { 42 | var pathAndHash = url.split('#'); 43 | linkInfo = getLinkInfoImpl(pathAndHash[0], title, currentDoc); 44 | linkInfo.url = linkInfo.url + '#' + pathAndHash[1]; 45 | return linkInfo; 46 | 47 | } else if ( url.indexOf('/') === -1 && url.indexOf('#') !== 0 ) { 48 | 49 | linkInfo.valid = false; 50 | linkInfo.error = 'Invalid link (does not match any doc): "' + url + '"'; 51 | 52 | } else { 53 | 54 | linkInfo.title = title || (( url.indexOf('#') === 0 ) ? url.substring(1) : path.basename(url, '.html')); 55 | 56 | } 57 | 58 | return linkInfo; 59 | }; 60 | }; -------------------------------------------------------------------------------- /base/services/aliasMap.spec.js: -------------------------------------------------------------------------------- 1 | var mockPackage = require('../mocks/mockPackage'); 2 | var Dgeni = require('dgeni'); 3 | 4 | describe("aliasMap", function() { 5 | var aliasMap; 6 | 7 | beforeEach(function() { 8 | var dgeni = new Dgeni([mockPackage()]); 9 | var injector = dgeni.configureInjector(); 10 | aliasMap = injector.get('aliasMap'); 11 | }); 12 | 13 | describe("addDoc", function() { 14 | it("should add the doc to an array for each alias", function() { 15 | var doc = { aliases: ['a', 'b', 'c'] }; 16 | aliasMap.addDoc(doc); 17 | expect(aliasMap.getDocs('a')).toEqual([doc]); 18 | expect(aliasMap.getDocs('b')).toEqual([doc]); 19 | expect(aliasMap.getDocs('c')).toEqual([doc]); 20 | }); 21 | 22 | it("should not add the doc if it has no aliases", function() { 23 | var doc = { }; 24 | aliasMap.addDoc(doc); 25 | expect(aliasMap.getDocs('a')).toEqual([]); 26 | expect(aliasMap.getDocs('b')).toEqual([]); 27 | expect(aliasMap.getDocs('c')).toEqual([]); 28 | }); 29 | }); 30 | 31 | describe("getDocs", function() { 32 | it("should return an empty array if no doc matches the alias", function() { 33 | var doc = { aliases: ['a', 'b', 'c'] }; 34 | expect(aliasMap.getDocs('d')).toEqual([]); 35 | }); 36 | }); 37 | 38 | describe("removeDoc", function() { 39 | it("should remove the doc from any parts of the aliasMap", function() { 40 | var doc1 = { aliases: ['a','b1'] }; 41 | var doc2 = { aliases: ['a','b2'] }; 42 | aliasMap.addDoc(doc1); 43 | aliasMap.addDoc(doc2); 44 | 45 | expect(aliasMap.getDocs('a')).toEqual([doc1, doc2]); 46 | expect(aliasMap.getDocs('b1')).toEqual([doc1]); 47 | expect(aliasMap.getDocs('b2')).toEqual([doc2]); 48 | 49 | aliasMap.removeDoc(doc1); 50 | 51 | expect(aliasMap.getDocs('a')).toEqual([doc2]); 52 | expect(aliasMap.getDocs('b1')).toEqual([]); 53 | expect(aliasMap.getDocs('b2')).toEqual([doc2]); 54 | 55 | }); 56 | }); 57 | }); -------------------------------------------------------------------------------- /nunjucks/rendering/filters/change-case.js: -------------------------------------------------------------------------------- 1 | var changeCase = require('change-case'); 2 | 3 | var _ = require('lodash'); 4 | 5 | /** 6 | * @dgRenderFilter lowerCase 7 | * @description Convert the value to lowercase. 8 | */ 9 | /** 10 | * @dgRenderFilter pascalCase 11 | * @description Convert the value to PascalCase. 12 | */ 13 | /** 14 | * @dgRenderFilter upperCase 15 | * @description Convert the value to UPPERCASE. 16 | */ 17 | /** 18 | * @dgRenderFilter swapCase 19 | * @description Swap the case of the letters in value. 20 | */ 21 | /** 22 | * @dgRenderFilter pathCase 23 | * @description Convert the value to/a/path. 24 | */ 25 | /** 26 | * @dgRenderFilter snakeCase 27 | * @description Convert the value to snake-case. 28 | */ 29 | /** 30 | * @dgRenderFilter constantCase 31 | * @description Convert the value to CONSTANT_CASE. 32 | */ 33 | /** 34 | * @dgRenderFilter paramCase 35 | * @description Convert the value to a param-case (sometimes called dash-case). 36 | */ 37 | /** 38 | * @dgRenderFilter dashCase 39 | * @description Convert the value to a dash-case (sometimes called param-case). 40 | */ 41 | /** 42 | * @dgRenderFilter dotCase 43 | * @description Convert the value to dot.case. 44 | */ 45 | /** 46 | * @dgRenderFilter camelCase 47 | * @description Convert the value to camelCase. 48 | */ 49 | /** 50 | * @dgRenderFilter titleCase 51 | * @description Convert the value to Title Case. 52 | */ 53 | /** 54 | * @dgRenderFilter sentenceCase 55 | * @description Convert the value to Sentence case. 56 | */ 57 | 58 | 59 | var changers = [ 60 | 'lower', 61 | 'pascal', 62 | 'upper', 63 | 'swap', 64 | 'path', 65 | 'snake', 66 | 'constant', 67 | 'param', 68 | 'dot', 69 | 'camel', 70 | 'title', 71 | 'sentence' 72 | ]; 73 | 74 | module.exports = _.map(changers, function(changer) { 75 | return { 76 | name: changer + 'Case', 77 | process: changeCase[changer] 78 | }; 79 | }); 80 | 81 | // Aliases 82 | module.exports.push({ 83 | name: 'dashCase', 84 | process: changeCase.paramCase 85 | }); -------------------------------------------------------------------------------- /base/services/trimIndentation.spec.js: -------------------------------------------------------------------------------- 1 | var mockPackage = require('../mocks/mockPackage'); 2 | var Dgeni = require('dgeni'); 3 | 4 | describe("trimIndentation", function() { 5 | var trimIndentation; 6 | beforeEach(function() { 7 | var dgeni = new Dgeni([mockPackage()]); 8 | var injector = dgeni.configureInjector(); 9 | trimIndentation = injector.get('trimIndentation'); 10 | }); 11 | it("should trim simple leading white-space from a single line of text", function() { 12 | expect(trimIndentation(' abc ')).toEqual('abc '); 13 | }); 14 | it("should trim excess indentation from multi-line text ", function() { 15 | expect(trimIndentation('abc\n xyz\n 123\n\n')).toEqual('abc\nxyz\n123'); 16 | expect(trimIndentation(' abc\n xyz\n 123\n\n')).toEqual('abc\n xyz\n 123'); 17 | expect(trimIndentation(' abc\n xyz\n 123\n\n')).toEqual('abc\n xyz\n 123'); 18 | }); 19 | it("should remove leading empty lines", function() { 20 | expect(trimIndentation('\n\n\nabc')).toEqual('abc'); 21 | expect(trimIndentation('\n\n\n abc')).toEqual('abc'); 22 | }); 23 | it("should remove trailing empty lines", function() { 24 | expect(trimIndentation('abc\n\n\n')).toEqual('abc'); 25 | }); 26 | 27 | describe("calcIndent", function() { 28 | it("should calculate simple leading white-space from a single line of text", function() { 29 | expect(trimIndentation.calcIndent(' abc ')).toEqual(3); 30 | }); 31 | it("should trim excess indentation from multi-line text ", function() { 32 | expect(trimIndentation.calcIndent('abc\n xyz\n 123\n\n')).toEqual(5); 33 | expect(trimIndentation.calcIndent(' abc\n xyz\n 123\n\n')).toEqual(2); 34 | expect(trimIndentation.calcIndent(' abc\n xyz\n 123\n\n')).toEqual(1); 35 | }); 36 | }); 37 | 38 | describe("reindent", function() { 39 | it("should add whitespace to the start of each line", function() { 40 | expect(trimIndentation.reindent('abc\n xyz', 4)).toEqual(' abc\n xyz'); 41 | }); 42 | }); 43 | }); -------------------------------------------------------------------------------- /nunjucks/rendering/tags/marked.spec.js: -------------------------------------------------------------------------------- 1 | var Dgeni = require('dgeni'); 2 | var mockPackage = require('../../mocks/mockPackage'); 3 | 4 | describe("marked custom tag extension", function() { 5 | var extension; 6 | 7 | beforeEach(function() { 8 | var dgeni = new Dgeni([mockPackage()]); 9 | var injector = dgeni.configureInjector(); 10 | 11 | extension = injector.get('markedNunjucksTag'); 12 | }); 13 | 14 | it("should specify the tags to match", function() { 15 | expect(extension.tags).toEqual(['marked']); 16 | }); 17 | 18 | describe("process", function() { 19 | 20 | it("should render the markdown and reindent", function() { 21 | var result = extension.process(null, function() { 22 | return ' ## heading 2\n\n' + 23 | ' some paragraph\n\n' + 24 | ' * a bullet point'; 25 | }); 26 | expect(result).toEqual( 27 | '

    heading 2

    \n' + 28 | '

    some paragraph

    \n' + 29 | '
      \n' + 30 | '
    • a bullet point
    • \n' + 31 | '
    \n' + 32 | ' ' 33 | ); 34 | }); 35 | 36 | }); 37 | 38 | describe("parse", function() { 39 | it("should interact correctly with the parser", function() { 40 | var log = []; 41 | var parserMock = { 42 | advanceAfterBlockEnd: function() { log.push('advanceAfterBlockEnd'); }, 43 | parseUntilBlocks: function() { log.push('parseUntilBlocks'); return 'some content'; } 44 | }; 45 | var nodesMock = { 46 | CallExtension: function() { log.push('CallExtension'); this.args = arguments; } 47 | }; 48 | 49 | var tag = extension.parse(parserMock, nodesMock); 50 | 51 | expect(log).toEqual([ 52 | 'advanceAfterBlockEnd', 53 | 'parseUntilBlocks', 54 | 'CallExtension', 55 | 'advanceAfterBlockEnd' 56 | ]); 57 | 58 | expect(tag.args[0]).toEqual(extension); 59 | expect(tag.args[1]).toEqual('process'); 60 | expect(tag.args[3]).toEqual(['some content']); 61 | }); 62 | }); 63 | }); -------------------------------------------------------------------------------- /nunjucks/services/nunjucks-template-engine.spec.js: -------------------------------------------------------------------------------- 1 | var rewire = require('rewire'); 2 | var engineFactory = rewire('./nunjucks-template-engine'); 3 | 4 | describe("nunjucksTemplateEngine service", function() { 5 | var nunjucks, addFilterSpy, addExtensionSpy, engine, mockTemplateFinder; 6 | 7 | beforeEach(function() { 8 | 9 | nunjucks = engineFactory.__get__('nunjucks'); 10 | 11 | nunjucks.Environment = jasmine.createSpy('Environment'); 12 | nunjucks.Environment.prototype.addFilter = addFilterSpy = jasmine.createSpy('addFilter'); 13 | nunjucks.Environment.prototype.addExtension = addExtensionSpy = jasmine.createSpy('addExtension'); 14 | 15 | mockTemplateFinder = { 16 | templateFolders: 'templates' 17 | }; 18 | engine = engineFactory(mockTemplateFinder); 19 | }); 20 | 21 | describe("getRenderer()", function() { 22 | 23 | it("should configure nunjucks", function() { 24 | 25 | engine.templateFolders = ['templates']; 26 | engine.config = { foo: 'bar' }; 27 | 28 | var render = engine.getRenderer(); 29 | expect(render).toEqual(jasmine.any(Function)); 30 | 31 | expect(nunjucks.Environment).toHaveBeenCalledWith( 32 | jasmine.any(nunjucks.FileSystemLoader), 33 | engine.config 34 | ); 35 | }); 36 | 37 | 38 | it("should load the given custom filters", function() { 39 | 40 | var dummyFilter = { name: 'test', process: function() {} }; 41 | engine.filters.push(dummyFilter); 42 | 43 | var render = engine.getRenderer(); 44 | expect(render).toEqual(jasmine.any(Function)); 45 | 46 | expect(addFilterSpy).toHaveBeenCalledWith(dummyFilter.name, dummyFilter.process); 47 | }); 48 | 49 | 50 | it("should load the given custom tags", function() { 51 | 52 | var dummyExtension = { tags: ['dummy']}; 53 | engine.tags.push(dummyExtension); 54 | 55 | var render = engine.getRenderer(); 56 | expect(render).toEqual(jasmine.any(Function)); 57 | 58 | expect(addExtensionSpy).toHaveBeenCalledWith('dummy', dummyExtension); 59 | }); 60 | }); 61 | }); -------------------------------------------------------------------------------- /base/services/templateFinder.spec.js: -------------------------------------------------------------------------------- 1 | var rewire = require('rewire'); 2 | var mockPackage = require('../mocks/mockPackage'); 3 | var Dgeni = require('dgeni'); 4 | var templateFinderFactory = rewire('./templateFinder'); 5 | 6 | describe("templateFinder", function() { 7 | 8 | var templateFinder; 9 | 10 | beforeEach(function() { 11 | var dgeni = new Dgeni([mockPackage()]); 12 | var injector = dgeni.configureInjector(); 13 | templateFinder = injector.get('templateFinder'); 14 | }); 15 | 16 | 17 | describe("getFinder", function() { 18 | 19 | var glob, patterns, templateFolders, findTemplate; 20 | 21 | beforeEach(function() { 22 | glob = templateFinderFactory.__get__('glob'); 23 | spyOn(glob, 'sync').and.returnValue([ 24 | 'a.x', 'b.x', 'c.x', 'c.a.x', 'f.other' 25 | ]); 26 | patterns = [ 27 | '${ doc.id }.${ doc.docType }.x', 28 | '${ doc.id }.x', 29 | '${ doc.docType }.x' 30 | ]; 31 | templateFolders = ['abc']; 32 | 33 | templateFinder.templateFolders = templateFolders; 34 | templateFinder.templatePatterns = patterns; 35 | 36 | findTemplate = templateFinder.getFinder(); 37 | }); 38 | 39 | 40 | it("should match id followed by doctype if both are provided and the file exists", function() { 41 | expect(findTemplate({ docType: 'a', id: 'c'})).toEqual('c.a.x'); 42 | }); 43 | 44 | 45 | it("should match id before docType", function() { 46 | expect(findTemplate({ docType: 'a', id: 'b' })).toEqual('b.x'); 47 | }); 48 | 49 | 50 | it("should match docType if id doesn't match", function() { 51 | expect(findTemplate({ docType: 'a', id: 'missing' })).toEqual('a.x'); 52 | }); 53 | 54 | 55 | it("should match docType if id is undefined", function() { 56 | expect(findTemplate({ docType: 'a' })).toEqual('a.x'); 57 | }); 58 | 59 | 60 | it("should throw an error if no template was found", function() { 61 | expect(function() { 62 | findTemplate({docType:'missing'}); 63 | }).toThrow(); 64 | }); 65 | 66 | }); 67 | }); -------------------------------------------------------------------------------- /base/index.js: -------------------------------------------------------------------------------- 1 | var Package = require('dgeni').Package; 2 | 3 | // Define the `base` package 4 | module.exports = new Package('base') 5 | 6 | // A set of pseudo processors that act as markers to help position real processors at the right 7 | // place in the pipeline 8 | .processor({ name: 'reading-files' }) 9 | .processor({ name: 'files-read', $runAfter: ['reading-files'] }) 10 | .processor({ name: 'processing-docs', $runAfter: ['files-read'] }) 11 | .processor({ name: 'docs-processed', $runAfter: ['processing-docs'] }) 12 | .processor({ name: 'adding-extra-docs', $runAfter: ['docs-processed'] }) 13 | .processor({ name: 'extra-docs-added', $runAfter: ['adding-extra-docs'] }) 14 | .processor({ name: 'computing-ids', $runAfter: ['extra-docs-added'] }) 15 | .processor({ name: 'ids-computed', $runAfter: ['computing-ids'] }) 16 | .processor({ name: 'computing-paths', $runAfter: ['ids-computed'] }) 17 | .processor({ name: 'paths-computed', $runAfter: ['computing-paths'] }) 18 | .processor({ name: 'rendering-docs', $runAfter: ['paths-computed'] }) 19 | .processor({ name: 'docs-rendered', $runAfter: ['rendering-docs'] }) 20 | .processor({ name: 'writing-files', $runAfter: ['docs-rendered'] }) 21 | .processor({ name: 'files-written', $runAfter: ['writing-files'] }) 22 | 23 | // Real processors for this package 24 | .processor(require('./processors/read-files')) 25 | .processor(require('./processors/render-docs')) 26 | .processor(require('./processors/unescape-comments')) 27 | .processor(require('./processors/write-files')) 28 | .processor(require('./processors/debugDumpProcessor')) 29 | .processor(require('./processors/computeIds')) 30 | .processor(require('./processors/computePaths')) 31 | .processor(require('./processors/checkAnchorLinks')) 32 | 33 | // Helper services 34 | .factory(require('./services/resolveUrl')) 35 | .factory(require('./services/extractLinks')) 36 | .factory(require('./services/templateFinder')) 37 | .factory(require('./services/encodeCodeBlock')) 38 | .factory(require('./services/trimIndentation')) 39 | .factory(require('./services/aliasMap')) 40 | .factory(require('./services/createDocMessage')) 41 | .factory(require('./services/writeFile')); 42 | -------------------------------------------------------------------------------- /base/services/createDocMessage.spec.js: -------------------------------------------------------------------------------- 1 | var mockPackage = require('../mocks/mockPackage'); 2 | var Dgeni = require('dgeni'); 3 | 4 | describe("createDocMessage", function() { 5 | var createDocMessage; 6 | 7 | beforeEach(function() { 8 | var dgeni = new Dgeni([mockPackage()]); 9 | var injector = dgeni.configureInjector(); 10 | createDocMessage = injector.get('createDocMessage'); 11 | }); 12 | 13 | 14 | it("should generate a message with doc info", function() { 15 | var message = createDocMessage('some message', { id: 'doc1', name: 'doc-one', path: 'some/doc1', fileInfo: { relativePath: 'some/file.js'} , startingLine: 10, endingLine: 20 }); 16 | expect(message).toEqual('some message - doc "doc1" - from file "some/file.js" - starting at line 10, ending at line 20'); 17 | 18 | 19 | message = createDocMessage('some message', { name: 'doc-one', path: 'some/doc1', fileInfo: { relativePath: 'some/file.js'} , startingLine: 10 }); 20 | expect(message).toEqual('some message - doc "doc-one" - from file "some/file.js" - starting at line 10'); 21 | 22 | message = createDocMessage('some message', { path: 'some/doc1', fileInfo: { relativePath: 'some/file.js'} }); 23 | expect(message).toEqual('some message - doc "some/doc1" - from file "some/file.js"'); 24 | 25 | 26 | message = createDocMessage('some message', { path: 'some/doc1' }); 27 | expect(message).toEqual('some message - doc "some/doc1"'); 28 | 29 | message = createDocMessage('some message', { fileInfo: { relativePath: 'some/file.js'} }); 30 | expect(message).toEqual('some message - doc - from file "some/file.js"'); 31 | }); 32 | 33 | 34 | it("should be able to wrap an original error", function() { 35 | var caught = false; 36 | try { 37 | throw new Error('original error'); 38 | } catch(originalError) { 39 | caught = true; 40 | var message = createDocMessage('some message', { id: 'doc1', name: 'doc-one', path: 'some/doc1', fileInfo: { relativePath: 'some/file.js'} , startingLine: 10, endingLine: 20 }, originalError); 41 | expect(message).toContain('original error'); 42 | } 43 | expect(caught).toBe(true); 44 | }); 45 | }); -------------------------------------------------------------------------------- /ngdoc/services/getAliases.js: -------------------------------------------------------------------------------- 1 | 2 | function parseCodeName(codeName) { 3 | var parts = []; 4 | var currentPart; 5 | 6 | codeName.split('.').forEach(function(part) { 7 | var subParts = part.split(':'); 8 | 9 | var name = subParts.pop(); 10 | var modifier = subParts.pop(); 11 | 12 | if ( !modifier && currentPart ) { 13 | currentPart.name += '.' + name; 14 | } else { 15 | currentPart = { 16 | name: name, 17 | modifier: modifier 18 | }; 19 | parts.push(currentPart); 20 | } 21 | }); 22 | return parts; 23 | } 24 | 25 | /** 26 | * @dgService getAliases 27 | * @description 28 | * Get a list of all the aliases that can be made from the doc 29 | * @param {Object} doc A doc from which to extract aliases 30 | * @return {Array} A collection of aliases 31 | */ 32 | module.exports = function getAliases() { 33 | 34 | return function(doc) { 35 | 36 | var codeNameParts = parseCodeName(doc.id); 37 | 38 | var methodName; 39 | var aliases = []; 40 | // Add the last part to the list of aliases 41 | var part = codeNameParts.pop(); 42 | 43 | // If the name contains a # then it is a member and that should be included in the aliases 44 | if ( part.name.indexOf('#') !== -1 ) { 45 | methodName = part.name.split('#')[1]; 46 | } 47 | // Add the part name and modifier, if provided 48 | aliases.push(part.name); 49 | if (part.modifier) { 50 | aliases.push(part.modifier + ':' + part.name); 51 | } 52 | 53 | // Continue popping off the parts of the codeName and work forward collecting up each alias 54 | aliases = codeNameParts.reduceRight(function(aliases, part) { 55 | 56 | // Add this part to each of the aliases we have so far 57 | aliases.forEach(function(name) { 58 | // Add the part name and modifier, if provided 59 | aliases.push(part.name + '.' + name); 60 | if ( part.modifier ) { 61 | aliases.push(part.modifier + ':' + part.name + '.' + name); 62 | } 63 | }); 64 | 65 | return aliases; 66 | }, aliases); 67 | 68 | if ( methodName ) { 69 | aliases.push(methodName); 70 | } 71 | 72 | return aliases; 73 | }; 74 | }; -------------------------------------------------------------------------------- /jsdoc/mocks/_test-data/docsFromJsFile.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | startingLine : 3, 4 | content: 5 | "@ngdoc object\n" + 6 | "@name ng/$controllerProvider\n" + 7 | "@description\n" + 8 | "The {@link ng/$controller $controller service} is used by Angular to create new\n" + 9 | "controllers.\n" + 10 | "\n" + 11 | "This provider allows controller registration via the\n" + 12 | "{@link ng/$controllerProvider#methods_register register} method." 13 | }, 14 | { 15 | startingLine: 18, 16 | content: 17 | "@ngdoc function\n" + 18 | "@name ng/$controllerProvider#register\n" + 19 | "@methodOf ng/$controllerProvider\n" + 20 | "@param {string|Object} name Controller name, or an object map of controllers where the keys are\n" + 21 | " the names and the values are the constructors.\n" + 22 | "@param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n" + 23 | " annotations in the array notation).", 24 | }, 25 | { 26 | startingLine: 39, 27 | content: 28 | "@ngdoc function\n" + 29 | "@name ng/$controller\n" + 30 | "@requires $injector\n" + 31 | "\n" + 32 | "@param {Function|string} constructor If called with a function then it's considered to be the\n" + 33 | " controller constructor function. Otherwise it's considered to be a string which is used\n" + 34 | " to retrieve the controller constructor using the following steps:\n" + 35 | "\n" + 36 | " * check if a controller with given name is registered via `$controllerProvider`\n" + 37 | " * check if evaluating the string on the current scope returns a constructor\n" + 38 | " * check `window[constructor]` on the global `window` object\n" + 39 | "\n" + 40 | "@param {Object} locals Injection locals for Controller.\n" + 41 | "@return {Object} Instance of given controller.\n" + 42 | "\n" + 43 | "@description\n" + 44 | "`$controller` service is responsible for instantiating controllers.\n" + 45 | "\n" + 46 | "It's just a simple call to {@link AUTO/$injector $injector}, but extracted into\n" + 47 | "a service, so that one can override this service with {@link https://gist.github.com/1649788\n" + 48 | "BC version}." 49 | }]; -------------------------------------------------------------------------------- /ngdoc/processors/memberDocs.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | 3 | /** 4 | * @dgProcessor memberDocsProcessor 5 | * @description 6 | * Merge the member docs into their container doc, and remove them from the main docs collection 7 | */ 8 | module.exports = function memberDocsProcessor(log, getDocFromAlias, createDocMessage) { 9 | 10 | var mergeableTypes = { 11 | method: 'methods', 12 | property: 'properties', 13 | event: 'events' 14 | }; 15 | 16 | return { 17 | $runAfter: ['ids-computed'], 18 | $runBefore: ['computing-paths'], 19 | $process: function(docs) { 20 | var parts; 21 | 22 | docs = _.filter(docs, function(doc) { 23 | 24 | // Is this doc a member of another doc? 25 | if ( doc.id.indexOf('#' ) !== -1 ) { 26 | doc.isMember = true; 27 | parts = doc.id.split('#'); 28 | doc.memberof = parts[0]; 29 | // remove the 'method:', 'property:', etc specifier from the id part 30 | doc.name = parts[1].replace(/^.*:/, ''); 31 | 32 | log.debug('child doc found', doc.id, doc.memberof); 33 | 34 | var containerDocs = getDocFromAlias(doc.memberof, doc); 35 | 36 | if ( containerDocs.length === 0 ) { 37 | log.warn(createDocMessage('Missing container document: "'+ doc.memberof + '"', doc)); 38 | return; 39 | } 40 | 41 | if ( containerDocs.length > 1 ) { 42 | // The memberof field was ambiguous, try prepending the module name too 43 | containerDocs = getDocFromAlias(_.template('${module}.${memberof}', doc), doc); 44 | if ( containerDocs.length !== 1 ) { 45 | log.warn(createDocMessage('Ambiguous container document reference: '+ doc.memberof)); 46 | return; 47 | } 48 | } 49 | 50 | var containerDoc = containerDocs[0]; 51 | doc.memberof = containerDoc.id; 52 | 53 | // Add this member doc to the container doc 54 | var containerProperty = mergeableTypes[doc.docType]; 55 | var container = containerDoc[containerProperty] = containerDoc[containerProperty] || []; 56 | container.push(doc); 57 | 58 | } else { 59 | return doc; 60 | } 61 | }); 62 | 63 | return docs; 64 | } 65 | }; 66 | }; -------------------------------------------------------------------------------- /base/processors/render-docs.spec.js: -------------------------------------------------------------------------------- 1 | var mockPackage = require('../mocks/mockPackage'); 2 | var Dgeni = require('dgeni'); 3 | 4 | var processor, renderSpy, findTemplateSpy; 5 | 6 | beforeEach(function() { 7 | 8 | var testPackage = mockPackage().factory('templateFinder', function() { 9 | var finderSpy = createSpy('findTemplate').and.returnValue('SOME TEMPLATE'); 10 | return { 11 | getFinder: function() { return finderSpy; } 12 | }; 13 | }); 14 | 15 | var dgeni = new Dgeni([testPackage]); 16 | var injector = dgeni.configureInjector(); 17 | findTemplateSpy = injector.get('templateFinder').getFinder(); 18 | renderSpy = injector.get('templateEngine').getRenderer(); 19 | 20 | processor = injector.get('renderDocsProcessor'); 21 | }); 22 | 23 | describe("render-docs", function() { 24 | 25 | it("should call the templateFinder for each doc", function() { 26 | var doc1 = {}, doc2 = {}, docs = [ doc1, doc2 ]; 27 | processor.$process(docs); 28 | expect(findTemplateSpy.calls.count()).toEqual(2); 29 | expect(findTemplateSpy.calls.argsFor(0)).toEqual([doc1]); 30 | expect(findTemplateSpy.calls.argsFor(1)).toEqual([doc2]); 31 | }); 32 | 33 | it("should call the templateEngine.render with the template and data", function() { 34 | var doc1 = { id: 1 }, doc2 = { id: 2 }, docs = [ doc1, doc2 ]; 35 | var someProp = {}, someMethod = function() {}; 36 | 37 | processor.extraData.someProp = someProp; 38 | processor.helpers.someMethod = someMethod; 39 | 40 | processor.$process(docs); 41 | 42 | expect(renderSpy.calls.count()).toEqual(2); 43 | expect(renderSpy.calls.argsFor(0)).toEqual(['SOME TEMPLATE', 44 | { doc: doc1, docs: docs, someProp: someProp, someMethod: someMethod }]); 45 | expect(renderSpy.calls.argsFor(1)).toEqual(['SOME TEMPLATE', 46 | { doc: doc2, docs: docs, someProp: someProp, someMethod: someMethod }]); 47 | }); 48 | 49 | it("should place the result of calling templateEngine.render into doc.renderedContent", function() { 50 | var doc1 = { id: 1 }, doc2 = { id: 2 }, docs = [ doc1, doc2 ]; 51 | 52 | renderSpy.and.returnValue('RENDERED CONTENT'); 53 | 54 | processor.$process(docs); 55 | expect(doc1.renderedContent).toEqual('RENDERED CONTENT'); 56 | expect(doc2.renderedContent).toEqual('RENDERED CONTENT'); 57 | }); 58 | 59 | }); 60 | -------------------------------------------------------------------------------- /base/services/trimIndentation.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | 3 | var isEmpty = RegExp.prototype.test.bind(/^\s*$/); 4 | 5 | function calcIndent(text) { 6 | var MAX_INDENT = 9999; 7 | var lines = text.split('\n'); 8 | var minIndent = MAX_INDENT; 9 | 10 | // ignore first line if it has no indentation and there is more than one line 11 | // this is because sometimes our text starts in the middle of a line of other 12 | // text that is indented and so doesn't appear to have an indent when it really does. 13 | var ignoreLine = (lines[0][0] != ' ' && lines.length > 1); 14 | if ( ignoreLine ) { 15 | lines.shift(); 16 | } 17 | // ignore leading empty lines 18 | while(isEmpty(lines[0])) { 19 | lines.shift(); 20 | } 21 | 22 | lines.forEach(function(line){ 23 | var indent = line.match(/^\s*/)[0].length; 24 | // If indent is 0 then we assume that it is just an overflow and not part of the indentation 25 | if (indent > 0 || minIndent == MAX_INDENT) { 26 | minIndent = Math.min(minIndent, indent); 27 | } 28 | }); 29 | 30 | return minIndent; 31 | } 32 | 33 | function reindent(text, indent) { 34 | var lines = text.split('\n'); 35 | var indentedLines = []; 36 | var indentStr = new Array(indent + 1).join(' '); 37 | _.forEach(lines, function(line) { 38 | indentedLines.push(indentStr + line); 39 | }); 40 | return indentedLines.join('\n'); 41 | } 42 | 43 | function trimIndent(text, indent) { 44 | var lines = text.split('\n'); 45 | var indentRegExp = new RegExp('^\\s{0,' + indent + '}'); 46 | 47 | // remove the indentation 48 | for ( var i = 0; i < lines.length; i++) { 49 | lines[i] = lines[i].replace(indentRegExp, ''); 50 | } 51 | 52 | // remove leading lines 53 | while (isEmpty(lines[0])) { lines.shift(); } 54 | 55 | // remove trailing 56 | while (isEmpty(lines[lines.length - 1])) { lines.pop(); } 57 | 58 | return lines.join('\n'); 59 | } 60 | 61 | // The primary export is a function that does the intentation trimming 62 | module.exports = function trimIndentation() { 63 | var trimIndentationImpl = function(text) { 64 | return trimIndent(text, calcIndent(text)); 65 | }; 66 | trimIndentationImpl.calcIndent = calcIndent; 67 | trimIndentationImpl.trimIndent = trimIndent; 68 | trimIndentationImpl.reindent = reindent; 69 | return trimIndentationImpl; 70 | }; -------------------------------------------------------------------------------- /ngdoc/templates/api/directive.template.html: -------------------------------------------------------------------------------- 1 | {% include "lib/macros.html" -%} 2 | {% extends "api/api.template.html" %} 3 | 4 | {% block additional %} 5 |

    Directive Info

    6 |
      7 | {% if doc.scope %}
    • This directive creates new scope.
    • {% endif %} 8 |
    • This directive executes at priority level {$ doc.priority $}.
    • 9 |
    10 | 11 | {% block usage %} 12 |

    Usage

    13 |
    14 | {% if doc.usage %} 15 | {$ doc.usage | marked $} 16 | {% else %} 17 |
      18 | {% if doc.restrict.element %} 19 |
    • as element: 20 | {% if doc.name.indexOf('ng') == 0 -%} 21 | (This directive can be used as custom element, but be aware of IE restrictions). 22 | {%- endif %} 23 | {% code %} 24 | <{$ doc.name | dashCase $} 25 | {%- for param in doc.params %} 26 | {$ directiveParam(param.alias or param.name, param.type, '="', '"') $} 27 | {%- endfor %}> 28 | ... 29 | 30 | {% endcode %} 31 |
    • 32 | {% endif -%} 33 | 34 | {%- if doc.restrict.attribute -%} 35 |
    • as attribute: 36 | {% code %} 37 | <{$ doc.element $} 38 | {%- for param in doc.params %} 39 | {$ directiveParam(param.name, param.type, '="', '"') $} 40 | {%- endfor %}> 41 | ... 42 | 43 | {% endcode %} 44 |
    • 45 | {% endif -%} 46 | 47 | {%- if doc.restrict.cssClass -%} 48 |
    • as CSS class: 49 | {% code %} 50 | {% set sep = joiner(' ') %} 51 | <{$ doc.element $} class=" 52 | {%- for param in doc.params -%} 53 | {$ sep() $}{$ directiveParam(param.name, param.type, ': ', ';') $} 54 | {%- endfor %}"> ... 55 | {% endcode %} 56 |
    • 57 | {% endif -%} 58 | 59 | {%- endif %} 60 |
    61 | {% endblock -%} 62 | 63 | {%- if doc.animations %} 64 |

    Animations

    65 | {$ doc.animations | marked $} 66 | {$ 'module:ngAnimate.$animate' | link('Click here', doc) $} to learn more about the steps involved in the animation. 67 | {%- endif -%} 68 | 69 | {% include "lib/params.template.html" %} 70 | {% include "lib/events.template.html" %} 71 | {% endblock %} 72 | -------------------------------------------------------------------------------- /jsdoc/processors/code-name.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @dgProcessor codeNameProcessor 3 | * @description Infer the name of the document from name of the following code 4 | */ 5 | module.exports = function codeNameProcessor(log) { 6 | return { 7 | $runAfter: ['files-read'], 8 | $runBefore: ['processing-docs'], 9 | $process: function(docs) { 10 | docs.forEach(function(doc) { 11 | doc.codeName = doc.codeName || (doc.codeNode && findCodeName(doc.codeNode)); 12 | if ( doc.codeName ) { 13 | log.silly('found codeName: ', doc.codeName); 14 | } 15 | }); 16 | return docs; 17 | } 18 | }; 19 | 20 | /** 21 | * Recurse down the code AST node that is associated with this doc for a name 22 | * @param {Object} node The esprima node information for the code to find the name of 23 | * @return {String} The name of the code or null if none found. 24 | */ 25 | function findCodeName(node) { 26 | var match; 27 | switch(node.type) { 28 | case 'FunctionDeclaration': 29 | return node.id && node.id.name; 30 | case 'ExpressionStatement': 31 | return findCodeName(node.expression); 32 | case 'AssignmentExpression': 33 | return findCodeName(node.right) || findCodeName(node.left); 34 | case 'FunctionExpression': 35 | return node.id && node.id.name; 36 | case 'MemberExpression': 37 | return findCodeName(node.property); 38 | case 'CallExpression': 39 | return findCodeName(node.callee); 40 | case 'Identifier': 41 | return node.name; 42 | case 'ReturnStatement': 43 | return findCodeName(node.argument); 44 | case 'Property': 45 | return findCodeName(node.value) || findCodeName(node.key); 46 | case 'ObjectExpression': 47 | return null; 48 | case 'ArrayExpression': 49 | return null; 50 | case 'Literal': 51 | return node.value; 52 | case 'Program': 53 | return node.body[0] ? findCodeName(node.body[0]) : null; 54 | case 'VariableDeclaration': 55 | return findCodeName(node.declarations[0]); 56 | case 'VariableDeclarator': 57 | return node.id && node.id.name; 58 | default: 59 | log.warn('HELP! Unrecognised node type: ' + node.type); 60 | log.warn(node); 61 | return null; 62 | } 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /ngdoc/templates/api/module.template.html: -------------------------------------------------------------------------------- 1 | {% extends "base.template.html" %} 2 | 3 | {% block content %} 4 |

    5 | {% if doc.title %}{$ doc.title | marked $}{% else %}{$ doc.name | code $}{% endif %} 6 |

    7 | 8 | {$ doc.description | marked $} 9 | 10 | {% if doc.name != 'ng' and doc.name != 'auto' %} 11 |

    Installation

    12 | 13 |

    First include {$ doc.packageFile | code $} in your HTML:

    14 | 15 | {% code %} 16 |