grunt-ngdocs
Advanced tools
Comparing version 0.1.0 to 0.1.1
@@ -0,1 +1,26 @@ | ||
# 0.1.1 (2013-06-01) | ||
## Features | ||
### docs | ||
* Add partial support for dot in module name #4 (bf9b22b) | ||
* Add navbar customizable template, title option (7a8775a) | ||
* Add active class to active navbar item (c89ceb2) | ||
* Make remote scripts not be copied, only referenced (da75892) | ||
* Add 'html5mode' option and copy scripts to docs destination (b1f7413) | ||
## Bug fixes | ||
### docs | ||
* remove sidebar flicker at navigation in large docs (77f1521) | ||
# 0.1.0 (2013-05-15) | ||
@@ -2,0 +27,0 @@ |
{ | ||
"name": "grunt-ngdocs", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"description": "grunt plugin for angularjs documentation", | ||
@@ -24,3 +24,7 @@ "main": "tasks", | ||
"grunt": "0.4.x" | ||
}, | ||
"devDependencies": { | ||
"grunt": "~0.4.1", | ||
"grunt-conventional-changelog": "~0.0.10" | ||
} | ||
} |
@@ -33,2 +33,4 @@ #grunt-ngdocs | ||
scripts: ['../app.min.js'], | ||
html5Mode: true, | ||
title: "My Awesome Docs", | ||
analytics: { | ||
@@ -58,9 +60,20 @@ account: 'UA-08150815-0', | ||
####dest | ||
[default] 'docs' | ||
[default] 'docs' | ||
Folder relative to your Gruntfile were the documentation should be build. | ||
####scripts | ||
[default] ['js/angular.min.js'] | ||
Set which angular.js file or addional custom js files are loaded to the app. This allows the live examles to use custom directives, services etc. The documentation app works with angular.js 1.0.6 and 1.1.5. | ||
[default] ['angular.js'] | ||
Set which angular.js file or addional custom js files are loaded to the app. This allows the live examles to use custom directives, services etc. The documentation app works with angular.js 1.0.+ and 1.1.+. | ||
Possible values: | ||
- ['angular.js'] use angularjs 1.1.5 delivered with ngdocs | ||
- ['path/to/file.js'] file will be copied into the docs, into a `grunt-scripts` folder | ||
- ['http://example.com/file.js', 'https://example.com/file.js', '//example.com/file.js'] reference remote files (eg from a CDN) | ||
- ['../app.js'] reference file relative to the dest folder | ||
####styles | ||
[default] [] | ||
Copy additional css files to the documentation app | ||
####analytics | ||
@@ -72,2 +85,31 @@ Optional include Google Analytics in the documentation app. | ||
####title | ||
[default] "name" or "title" field in `pkg` | ||
Title to put on the navbar and the page's `title` attribute. By default, tries to | ||
find the title in the `pkg`. If it can't find it, it will go to an empty string. | ||
####html5Mode | ||
[default] 'true' | ||
Whether or not to enable `html5Mode` in the docs application. If true, then links will be absolute. If false, they will be prefixed by `#/`. | ||
####animation | ||
[default] 'false' or 'true' for the included angularjs, angularjs 1.1.5+ from CDN or a folder like /vendor/angular-1.1.5/angular.js. | ||
Set to 'true' to enable animations in the sidebar. | ||
####navTemplate | ||
[default] null | ||
Path to a template of a nav HTML template to include. The css for it | ||
should be that of listitems inside a bootstrap navbar: | ||
```html | ||
<header class="header"> | ||
<div class="navbar"> | ||
<ul class="nav"> | ||
{{links to all the docs pages}} | ||
</ul> | ||
{{YOUR_NAV_TEMPLATE_GOES_HERE}} | ||
</div> | ||
</header> | ||
``` | ||
Example: 'templates/my-nav.html' | ||
###Targets | ||
@@ -80,3 +122,3 @@ Each grunt target creates a section in the documentation app. | ||
####title | ||
[default] 'API Documentation' | ||
[default] 'API Documentation' | ||
Set the name for the section in the documentation app. | ||
@@ -122,2 +164,2 @@ | ||
##License | ||
MIT License | ||
MIT License |
@@ -26,3 +26,3 @@ /** | ||
////////////////////////////////////////////////////////// | ||
function Doc(text, file, line) { | ||
function Doc(text, file, line, options) { | ||
if (typeof text == 'object') { | ||
@@ -37,2 +37,3 @@ for ( var key in text) { | ||
} | ||
this.options = options || {}; | ||
this.scenarios = this.scenarios || []; | ||
@@ -98,5 +99,6 @@ this.requires = this.requires || []; | ||
convertUrlToAbsolute: function(url) { | ||
var prefix = this.options.html5Mode ? '' : '#/'; | ||
if (url.substr(-1) == '/') return url + 'index'; | ||
if (url.match(/\//)) return url; | ||
return this.section + '/' + url; | ||
return prefix + this.section + '/' + url; | ||
}, | ||
@@ -746,9 +748,9 @@ | ||
var GLOBALS = /^angular\.([^\.]+)$/, | ||
MODULE = /^((?:(?!^angular\.)[^\.])+)$/, | ||
MODULE = /^([^\.]+)$/, | ||
MODULE_MOCK = /^angular\.mock\.([^\.]+)$/, | ||
MODULE_DIRECTIVE = /^((?:(?!^angular\.)[^\.])+)\.directive:([^\.]+)$/, | ||
MODULE_DIRECTIVE_INPUT = /^((?:(?!^angular\.)[^\.])+)\.directive:input\.([^\.]+)$/, | ||
MODULE_FILTER = /^((?:(?!^angular\.)[^\.])+)\.filter:([^\.]+)$/, | ||
MODULE_SERVICE = /^((?:(?!^angular\.)[^\.])+)\.([^\.]+?)(Provider)?$/, | ||
MODULE_TYPE = /^((?:(?!^angular\.)[^\.])+)\..+\.([A-Z][^\.]+)$/; | ||
MODULE_DIRECTIVE = /^(.+)\.directive:([^\.]+)$/, | ||
MODULE_DIRECTIVE_INPUT = /^(.+)\.directive:input\.([^\.]+)$/, | ||
MODULE_FILTER = /^(.+)\.filter:([^\.]+)$/, | ||
MODULE_SERVICE = /^(.+)\.([^\.]+?)(Provider)?$/, | ||
MODULE_TYPE = /^([^\.]+)\..+\.([A-Z][^\.]+)$/; | ||
@@ -789,2 +791,6 @@ | ||
type = 'filter'; | ||
} else if (match = text.match(MODULE_TYPE)) { | ||
module = match[1]; | ||
name = match[2]; | ||
type = 'type'; | ||
} else if (match = text.match(MODULE_SERVICE)) { | ||
@@ -794,6 +800,2 @@ module = match[1]; | ||
type = 'service'; | ||
} else if (match = text.match(MODULE_TYPE)) { | ||
module = match[1]; | ||
name = match[2]; | ||
type = 'type'; | ||
} else { | ||
@@ -800,0 +802,0 @@ return text; |
@@ -11,3 +11,3 @@ /** | ||
function process(content, file, section) { | ||
function process(content, file, section, options) { | ||
if (/\.js$/.test(file)) { | ||
@@ -19,3 +19,3 @@ processJsFile(content, file).forEach(function(doc) { | ||
var header = '@section ' + section + '\n'; | ||
exports.docs.push(new ngdoc.Doc(header + content.toString(),file, 1).parse()); | ||
exports.docs.push(new ngdoc.Doc(header + content.toString(),file, 1, options).parse()); | ||
} | ||
@@ -22,0 +22,0 @@ } |
/* | ||
AngularJS v1.1.5-af0eaa3 | ||
AngularJS v1.1.5 | ||
(c) 2010-2012 Google, Inc. http://angularjs.org | ||
@@ -4,0 +4,0 @@ License: MIT |
/* | ||
AngularJS v1.1.5-af0eaa3 | ||
AngularJS v1.1.5 | ||
(c) 2010-2012 Google, Inc. http://angularjs.org | ||
License: MIT | ||
*/ | ||
(function(n,j){'use strict';j.module("bootstrap",[]).directive({dropdownToggle:["$document","$location","$window",function(g,d){var e=null,a;return{restrict:"C",link:function(h,b){h.$watch(function(){return d.path()},function(){a&&a()});b.parent().bind("click",function(){a&&a()});b.bind("click",function(i){i.preventDefault();i.stopPropagation();i=!1;e&&(i=e===b,a());i||(b.parent().addClass("open"),e=b,a=function(c){c&&c.preventDefault();c&&c.stopPropagation();g.unbind("click",a);b.parent().removeClass("open"); | ||
e=a=null},g.bind("click",a))})}}}],tabbable:function(){return{restrict:"C",compile:function(g){var d=j.element('<ul class="nav nav-tabs"></ul>'),e=j.element('<div class="tab-content"></div>');e.append(g.contents());g.append(d).append(e)},controller:["$scope","$element",function(g,d){var e=d.contents().eq(0),a=d.controller("ngModel")||{},h=[],b;a.$render=function(){var a=this.$viewValue;if(b?b.value!=a:a)if(b&&(b.paneElement.removeClass("active"),b.tabElement.removeClass("active"),b=null),a){for(var c= | ||
0,d=h.length;c<d;c++)if(a==h[c].value){b=h[c];break}b&&(b.paneElement.addClass("active"),b.tabElement.addClass("active"))}};this.addPane=function(d,c){function l(){f.title=c.title;f.value=c.value||c.title;if(!a.$setViewValue&&(!a.$viewValue||f==b))a.$viewValue=f.value;a.$render()}var k=j.element("<li><a href></a></li>"),m=k.find("a"),f={paneElement:d,paneAttrs:c,tabElement:k};h.push(f);c.$observe("value",l)();c.$observe("title",function(){l();m.text(f.title)})();e.append(k);k.bind("click",function(b){b.preventDefault(); | ||
b.stopPropagation();a.$setViewValue?g.$apply(function(){a.$setViewValue(f.value);a.$render()}):(a.$viewValue=f.value,a.$render())});return function(){f.tabElement.remove();for(var a=0,b=h.length;a<b;a++)f==h[a]&&h.splice(a,1)}}}]}},table:function(){return{restrict:"E",link:function(g,d){d[0].className="table table-bordered table-striped code-table"}}},tabPane:function(){return{require:"^tabbable",restrict:"C",link:function(g,d,e,a){d.bind("$remove",a.addPane(d,e))}}}})})(window,window.angular); | ||
(function(n,i){'use strict';i.module("bootstrap",[]).directive({dropdownToggle:["$document","$location","$window",function(e,a){var d=null,b;return{restrict:"C",link:function(f,c){f.$watch(function(){return a.path()},function(){b&&b()});c.parent().bind("click",function(){b&&b()});c.bind("click",function(a){a.preventDefault();a.stopPropagation();a=!1;d&&(a=d===c,b());a||(c.parent().addClass("open"),d=c,b=function(a){a&&a.preventDefault();a&&a.stopPropagation();e.unbind("click",b);c.parent().removeClass("open"); | ||
d=b=null},e.bind("click",b))})}}}],syntax:function(){return{restrict:"A",link:function(e,a,d){var e="",b={github:{text:"View on Github",key:"syntaxGithub",icon:"icon-github"},plunkr:{text:"View on Plunkr",key:"syntaxPlunkr",icon:"icon-arrow-down"},jsfiddle:{text:"View on JSFiddle",key:"syntaxFiddle",icon:"icon-cloud"}},f;for(f in b){var c=b[f],k=d[c.key];k&&(e+='<a href="'+k+'" class="btn syntax-'+f+'" target="_blank" rel="nofollow"><span class="'+c.icon+'"></span> '+c.text+"</a>")}d=document.createElement("nav"); | ||
d.className="syntax-links";d.innerHTML=e;a=a[0];a.parentNode.insertBefore(d,a)}}},tabbable:function(){return{restrict:"C",compile:function(e){var a=i.element('<ul class="nav nav-tabs"></ul>'),d=i.element('<div class="tab-content"></div>');d.append(e.contents());e.append(a).append(d)},controller:["$scope","$element",function(e,a){var d=a.contents().eq(0),b=a.controller("ngModel")||{},f=[],c;b.$render=function(){var a=this.$viewValue;if(c?c.value!=a:a)if(c&&(c.paneElement.removeClass("active"),c.tabElement.removeClass("active"), | ||
c=null),a){for(var b=0,d=f.length;b<d;b++)if(a==f[b].value){c=f[b];break}c&&(c.paneElement.addClass("active"),c.tabElement.addClass("active"))}};this.addPane=function(a,h){function l(){g.title=h.title;g.value=h.value||h.title;if(!b.$setViewValue&&(!b.$viewValue||g==c))b.$viewValue=g.value;b.$render()}var j=i.element("<li><a href></a></li>"),m=j.find("a"),g={paneElement:a,paneAttrs:h,tabElement:j};f.push(g);h.$observe("value",l)();h.$observe("title",function(){l();m.text(g.title)})();d.append(j);j.bind("click", | ||
function(a){a.preventDefault();a.stopPropagation();b.$setViewValue?e.$apply(function(){b.$setViewValue(g.value);b.$render()}):(b.$viewValue=g.value,b.$render())});return function(){g.tabElement.remove();for(var a=0,b=f.length;a<b;a++)g==f[a]&&f.splice(a,1)}}}]}},table:function(){return{restrict:"E",link:function(e,a){a[0].className="table table-bordered table-striped code-table"}}},tabPane:function(){return{require:"^tabbable",restrict:"C",link:function(e,a,d,b){a.bind("$remove",b.addPane(a,d))}}}})})(window, | ||
window.angular); |
@@ -264,8 +264,9 @@ var docsApp = { | ||
angular.forEach(NG_DOCS.pages, function(page) { | ||
page.url = page.section + '/' + page.id; | ||
var url = page.section + '/' + page.id; | ||
if (page.id == 'angular.Module') { | ||
page.partialUrl = 'partials/api/angular.IModule.html'; | ||
} else { | ||
page.partialUrl = 'partials/' + page.url + '.html'; | ||
page.partialUrl = 'partials/' + url + '.html'; | ||
} | ||
page.url = (NG_DOCS.html5Mode ? '' : '#/') + url; | ||
if (!sections[page.section]) { sections[page.section] = []; } | ||
@@ -282,17 +283,9 @@ sections[page.section].push(page); | ||
GLOBALS = /^angular\.([^\.]+)$/, | ||
MODULE = /^((?:(?!^angular\.)[^\.])+)$/, | ||
MODULE = /^([^\.]+)$/, | ||
MODULE_MOCK = /^angular\.mock\.([^\.]+)$/, | ||
MODULE_DIRECTIVE = /^((?:(?!^angular\.)[^\.])+)\.directive:([^\.]+)$/, | ||
MODULE_DIRECTIVE_INPUT = /^((?:(?!^angular\.)[^\.])+)\.directive:input\.([^\.]+)$/, | ||
MODULE_FILTER = /^((?:(?!^angular\.)[^\.])+)\.filter:([^\.]+)$/, | ||
MODULE_SERVICE = /^((?:(?!^angular\.)[^\.])+)\.([^\.]+?)(Provider)?$/, | ||
MODULE_TYPE = /^((?:(?!^angular\.)[^\.])+)\..+\.([A-Z][^\.]+)$/, | ||
URL = { | ||
module: 'http://docs.angularjs.org/guide/module', | ||
directive: 'http://docs.angularjs.org/guide/directive', | ||
input: 'http://docs.angularjs.org/api/ng.directive:input', | ||
filter: 'http://docs.angularjs.org/guide/dev_guide.templates.filters', | ||
service: 'http://docs.angularjs.org/guide/dev_guide.services', | ||
type: 'http://docs.angularjs.org/guide/types' | ||
}; | ||
MODULE_DIRECTIVE = /^(.+)\.directive:([^\.]+)$/, | ||
MODULE_DIRECTIVE_INPUT = /^(.+)\.directive:input\.([^\.]+)$/, | ||
MODULE_FILTER = /^(.+)\.filter:([^\.]+)$/, | ||
MODULE_SERVICE = /^(.+)\.([^\.]+?)(Provider)?$/, | ||
MODULE_TYPE = /^([^\.]+)\..+\.([A-Z][^\.]+)$/; | ||
@@ -311,2 +304,9 @@ | ||
$scope.isActivePath = function(url) { | ||
if (url.charAt(0) == '#') { | ||
url = url.substring(1, url.length); | ||
} | ||
return $location.path().indexOf(url) > -1; | ||
}; | ||
$scope.submitForm = function() { | ||
@@ -328,3 +328,6 @@ $scope.bestMatch && $location.path($scope.bestMatch.page.url); | ||
$scope.sections = NG_DOCS.sections; | ||
$scope.sections = {}; | ||
angular.forEach(NG_DOCS.sections, function(section, url) { | ||
$scope.sections[(NG_DOCS.html5Mode ? '' : '#/') + url] = section; | ||
}); | ||
$scope.$watch(function docsPathWatch() {return $location.path(); }, function docsPathWatchAction(path) { | ||
@@ -348,6 +351,6 @@ var parts = path.split('/'), | ||
var breadcrumb = $scope.breadcrumb = [], | ||
match; | ||
match, sectionPath = (NG_DOCS.html5Mode ? '' : '#/') + sectionId; | ||
if (partialId) { | ||
breadcrumb.push({ name: sectionName, url: sectionId }); | ||
breadcrumb.push({ name: sectionName, url: sectionPath }); | ||
if (partialId == 'angular.Module') { | ||
@@ -360,16 +363,16 @@ breadcrumb.push({ name: 'angular.Module' }); | ||
} else if (match = partialId.match(MODULE_FILTER)) { | ||
breadcrumb.push({ name: match[1], url: sectionId + '/' + match[1] }); | ||
breadcrumb.push({ name: match[1], url: sectionPath + '/' + match[1] }); | ||
breadcrumb.push({ name: match[2] }); | ||
} else if (match = partialId.match(MODULE_DIRECTIVE)) { | ||
breadcrumb.push({ name: match[1], url: sectionId + '/' + match[1] }); | ||
breadcrumb.push({ name: match[1], url: sectionPath + '/' + match[1] }); | ||
breadcrumb.push({ name: match[2] }); | ||
} else if (match = partialId.match(MODULE_DIRECTIVE_INPUT)) { | ||
breadcrumb.push({ name: match[1], url: sectionId + '/' + match[1] }); | ||
breadcrumb.push({ name: 'input', url: URL.input }); | ||
breadcrumb.push({ name: match[1], url: sectionPath + '/' + match[1] }); | ||
breadcrumb.push({ name: 'input' }); | ||
breadcrumb.push({ name: match[2] }); | ||
} else if (match = partialId.match(MODULE_TYPE)) { | ||
breadcrumb.push({ name: match[1], url: sectionId + '/' + match[1] }); | ||
breadcrumb.push({ name: match[1], url: sectionPath + '/' + match[1] }); | ||
breadcrumb.push({ name: match[2] }); | ||
} else if (match = partialId.match(MODULE_SERVICE)) { | ||
breadcrumb.push({ name: match[1], url: sectionId + '/' + match[1] }); | ||
breadcrumb.push({ name: match[1], url: sectionPath + '/' + match[1] }); | ||
breadcrumb.push({ name: match[2] + (match[3] || '') }); | ||
@@ -399,5 +402,3 @@ } else if (match = partialId.match(MODULE_MOCK)) { | ||
$scope.loading = 0; | ||
$scope.URL = URL; | ||
if (!$location.path() || INDEX_PATH.test($location.path())) { | ||
@@ -453,6 +454,6 @@ $location.path('/api').replace(); | ||
module(match[1]).directives.push(page); | ||
} else if (match = id.match(MODULE_TYPE)) { | ||
module(match[1]).types.push(page); | ||
} else if (match = id.match(MODULE_SERVICE)) { | ||
module(match[1]).service(match[2])[match[3] ? 'provider' : 'instance'] = page; | ||
} else if (match = id.match(MODULE_TYPE)) { | ||
module(match[1]).types.push(page); | ||
} else if (match = id.match(MODULE_MOCK)) { | ||
@@ -473,3 +474,3 @@ module('ngMock').globals.push(page); | ||
name: name, | ||
url: 'api/' + name, | ||
url: (NG_DOCS.html5Mode ? '' : '#/') + 'api/' + name, | ||
globals: [], | ||
@@ -541,3 +542,5 @@ directives: [], | ||
config(function($locationProvider) { | ||
$locationProvider.html5Mode(true).hashPrefix('!'); | ||
if (NG_DOCS.html5Mode) { | ||
$locationProvider.html5Mode(true).hashPrefix('!'); | ||
} | ||
}). | ||
@@ -544,0 +547,0 @@ factory(docsApp.serviceFactory). |
@@ -23,7 +23,48 @@ /* | ||
dest: 'docs/', | ||
scripts: ['js/angular.min.js'] | ||
scripts: ['angular.js'], | ||
styles: [], | ||
title: grunt.config('pkg') ? | ||
(grunt.config('pkg').title || grunt.config('pkg').name) : | ||
'', | ||
html5Mode: true, | ||
animation: false | ||
}), | ||
section = this.target === 'all' ? 'api' : this.target, | ||
setup = prepareSetup(section, options); | ||
setup; | ||
//Copy the scripts into their own folder in docs, unless they are remote or default angular.js | ||
var gruntScriptsFolder = 'grunt-scripts'; | ||
options.scripts = _.map(options.scripts, function(file) { | ||
if (file === 'angular.js') { | ||
options.animation = true; | ||
return 'js/angular.min.js'; | ||
} | ||
if (!options.animation) { | ||
//force animation in new angular versions from CDN or copied from a folder like angular-1.x.x/ | ||
var match = file.match(/1\.(\d\.\d+)\/angular\./); | ||
if (match && parseInt(match[1], 10) > 1.4) { options.animation = true; } | ||
} | ||
if (/^((https?:)?\/\/|\.\.\/)/.test(file)) { | ||
return file; | ||
} else { | ||
var filename = file.split('/').pop(); | ||
//Use path.join here because we aren't sure if options.dest has / or not | ||
grunt.file.copy(file, path.join(options.dest, gruntScriptsFolder, filename)); | ||
//Return the script path: doesn't have options.dest in it, it's relative | ||
//to the docs folder itself | ||
return gruntScriptsFolder + '/' + filename; | ||
} | ||
}); | ||
options.styles = _.map(options.styles, function(file) { | ||
var filename = file.split('/').pop(); | ||
grunt.file.copy(file, path.join(options.dest, 'css', filename)); | ||
return 'css/' + filename; | ||
}); | ||
setup = prepareSetup(section, options); | ||
grunt.log.writeln('Generating Documentation...'); | ||
@@ -36,3 +77,3 @@ | ||
var content = grunt.file.read(filepath); | ||
reader.process(content, filepath, section); | ||
reader.process(content, filepath, section, options); | ||
}); | ||
@@ -52,2 +93,8 @@ }); | ||
if (options.navTemplate) { | ||
options.navContent = grunt.file.read(options.navTemplate); | ||
} else { | ||
options.navContent = ''; | ||
} | ||
writeSetup(setup); | ||
@@ -83,5 +130,11 @@ | ||
scripts: options.scripts, | ||
styles: options.styles, | ||
sections: _.keys(setup.sections).join('|'), | ||
discussions: options.discussions, | ||
analytics: options.analytics | ||
analytics: options.analytics, | ||
navContent: options.navContent, | ||
title: options.title, | ||
trackBy: function(id, animation) { | ||
return options.animation ? ' track by ' + id + (animation ? '" ng-animate="' + animation : '') : ''; | ||
} | ||
}; | ||
@@ -95,2 +148,3 @@ | ||
// create setup file | ||
setup.html5Mode = options.html5Mode; | ||
setup.discussions = options.discussions; | ||
@@ -97,0 +151,0 @@ setup.scripts = _.map(options.scripts, function(url) { return path.basename(url); }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
689463
27
9171
161
2