chore(doc-gen): generate docs for angular.io

You can generate docs for comsumption by the angular.io website by running:

```bash
gulp docs/angular.io
```

The generated docs can be found in `dist/angular.io`
This commit is contained in:
Alex Wolfe 2015-04-25 14:29:20 -07:00 committed by Peter Bacon Darwin
parent b72eb0783b
commit c269bd5d3c
15 changed files with 389 additions and 2 deletions

View File

@ -0,0 +1,48 @@
var path = require('canonical-path');
var Package = require('dgeni').Package;
var basePackage = require('../public-docs-package');
var PARTIAL_PATH = 'partials';
var MODULES_DOCS_PATH = PARTIAL_PATH + '/api';
module.exports = new Package('angular.io', [basePackage])
.factory(require('./services/renderMarkdown'))
.processor(require('./processors/addJadeDataDocsProcessor'))
// Configure rendering
.config(function(templateFinder, templateEngine) {
templateFinder.templateFolders
.unshift(path.resolve(__dirname, 'templates'));
})
.config(function(writeFilesProcessor) {
writeFilesProcessor.outputFolder = 'dist/angular.io';
})
.config(function(computeIdsProcessor, computePathsProcessor, EXPORT_DOC_TYPES) {
computePathsProcessor.pathTemplates.push({
docTypes: ['module'],
pathTemplate: '${id}.html',
outputPathTemplate: MODULES_DOCS_PATH + '/${id}/index.jade'
});
computePathsProcessor.pathTemplates.push({
docTypes: EXPORT_DOC_TYPES,
pathTemplate: '${moduleDoc.id}/${name}-${docType}.html',
outputPathTemplate: MODULES_DOCS_PATH + '/${moduleDoc.id}/${name}-${docType}.jade',
});
computePathsProcessor.pathTemplates.push({
docTypes: ['jade-data'],
pathTemplate: '${originalDoc.id}/_data',
outputPathTemplate: MODULES_DOCS_PATH + '/${path}.json'
});
})
.config(function(getLinkInfo) {
getLinkInfo.relativeLinks = true;
});

View File

@ -0,0 +1,75 @@
var _ = require('lodash');
var path = require('canonical-path');
var titleCase = function(text) {
return text.replace(/(.)(.*)/, function(_, first, rest) {
return first.toUpperCase() + rest;
});
};
/*
* Create _data.json file for Harp pages
*
* http://harpjs.com/docs/development/metadata
*
* This method creates the meta data required for each page
* such as the title, description, etc. This meta data is used
* in the harp static site generator to create the title for headers
* and the navigation used in the API docs
*
*/
module.exports = function addJadeDataDocsProcessor(EXPORT_DOC_TYPES) {
return {
$runAfter: ['adding-extra-docs', 'cloneExportedFromDocs'],
$runBefore: ['extra-docs-added'],
$process: function(docs) {
var extraDocs = [];
var modules = [];
/*
* Create Data for Modules
*
* Modules must be public and have content
*/
_.forEach(docs, function(doc) {
if (doc.docType === 'module' && doc.exports.length) {
modules.push(doc);
// GET DATA FOR INDEX PAGE OF MODULE SECTION
var indexPageInfo = [{
name: 'index',
title: _.map(path.basename(doc.fileInfo.baseName).split('_'), function(part) {
return titleCase(part);
}).join(' '),
intro: doc.description.replace('"', '\"').replace(/\r?\n|\r/g,"")
}];
// GET DATA FOR EACH PAGE (CLASS, VARS, FUNCTIONS)
var modulePageInfo = _.map(doc.exports, function(exportDoc) {
return {
name: exportDoc.name + '-' + exportDoc.docType,
title: exportDoc.name + ' ' + titleCase(exportDoc.docType)
};
});
//COMBINE PAGE DATA
var allPageData = indexPageInfo.concat(modulePageInfo);
// PUSH DATA TO EXTRA DOCS ARRAY
extraDocs.push({
id: doc.id + "-data",
docType: 'jade-data',
originalDoc: doc,
data: allPageData
});
}
});
return docs.concat(extraDocs);
}
};
};

View File

@ -0,0 +1,52 @@
var marked = require('marked');
var Encoder = require('node-html-encoder').Encoder;
var html2jade = require('html2jade');
var indentString = require('indent-string');
var S = require('string');
// entity type encoder
var encoder = new Encoder('entity');
/**
* @dgService renderMarkdown
* @description
* Render the markdown in the given string as HTML.
*/
module.exports = function renderMarkdown(trimIndentation) {
var renderer = new marked.Renderer();
renderer.code = function(code, lang, escaped) {
var cssClasses = ['prettyprint', 'linenums'];
var trimmedCode = trimIndentation(code);
if(lang) {
if(lang=='html') {
trimmedCode = encoder.htmlEncode(trimmedCode);
}
cssClasses.push(this.options.langPrefix + escape(lang, true));
}
return 'pre(class="' + cssClasses.join(' ') + '")\n'
+ indentString('code.\n', ' ', 2)
+ trimmedCode;
};
renderer.heading = function (text, level, raw) {
var headingText = marked.Renderer.prototype.heading.call(renderer, text, level, raw);
var title = 'h2 ' + S(headingText).stripTags().s;
if (level==2) {
title = '.l-main-section\n' + indentString(title, ' ', 2) ;
}
return title;
};
return function(content) {
return marked(content, { renderer: renderer });
};
};

View File

@ -0,0 +1,48 @@
{% include "lib/paramList.html" -%}
{% extends 'layout/base.template.html' -%}
{% block body %}
p.location-badge.
exported from <a href="/{$ doc.moduleDoc.path $}">{$ doc.moduleDoc.id $}</a>
defined in <a href="https://github.com/angular/angular/tree/master/modules/{$ doc.location.start.source.name $}.js#L{$ doc.location.start.line $}">{$ doc.location.start.source.name $}.js (line {$ doc.location.start.line $})</a>
:markdown
{$ doc.description | indent(2, true) $}
{%- if doc.constructorDoc or doc.members.length -%}
.l-main-section
h2 Members
{%- if doc.constructorDoc %}
.l-sub-section
h3 {$ doc.constructorDoc.name $}
{% if doc.constructorDoc.params %}
pre.prettyprint
code.
{$ doc.constructorDoc.name $}{$ paramList(doc.constructorDoc.params) | indent(4, true) | trim $}
{% endif %}
:markdown
{$ doc.constructorDoc.description | indent(6, true) | replace('## Example', '') | replace('# Example', '') $}
{% endif -%}
{%- for member in doc.members %}
.l-sub-section
h3 {$ member.name $}
{% if member.params %}
pre.prettyprint
code.
{$ member.name $}{$ paramList(member.params) | indent(4, true) | trim $}
{% endif %}
:markdown
{$ member.description | indent(6, true) | replace('## Example', '') | replace('# Example', '') $}
{% endfor %}
{%- endif -%}
{% endblock %}

View File

@ -0,0 +1,16 @@
{% include "lib/paramList.html" -%}
{% extends 'layout/base.template.html' -%}
{% block body %}
.l-main-section
h2(class="function export") {$ doc.name $}
p <code>{$ paramList(doc.parameters) $}</code>
p.location-badge.
exported from <a href="/{$ doc.moduleDoc.path $}">{$ doc.moduleDoc.id $}</a>
:markdown
{$ doc.description | indent(4, true) $}
{% endblock %}

View File

@ -0,0 +1,8 @@
{
{%- for item in doc.data %}
"{$ item.name $}" : {
"title" : "{$ item.title $}"{% if item.intro %},
"intro" : "{$ item.intro $}"{% endif %}
}{% if not loop.last %},{% endif %}
{% endfor -%}
}

View File

@ -0,0 +1 @@
{% block body %}{% endblock %}

View File

@ -0,0 +1,7 @@
{% macro paramList(params) -%}
{%- if params -%}
({%- for param in params -%}
{$ param | escape $}{% if not loop.last %}, {% endif %}
{%- endfor %})
{%- endif %}
{%- endmacro -%}

View File

@ -0,0 +1,11 @@
{% extends 'layout/base.template.html' -%}
{% block body -%}
ul
for page, slug in public.docs[current.path[1]][current.path[2]][current.path[3]][current.path[4]]._data
if slug != 'index'
url = "/docs/" + current.path[1] + "/" + current.path[2] + "/" + current.path[3] + "/" + current.path[4] + "/" + slug + ".html"
li.c8
!= partial("../../../../../_includes/_hover-card", {name: page.title, url: url })
{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends 'layout/base.template.html' %}
{% block body %}
.l-main-section
h2 {$ doc.name $} <span class="type">variable</span>
p.location-badge.
exported from <a href="/{$ doc.moduleDoc.path $}">{$ doc.moduleDoc.id $}</a>
:markdown
{$ doc.description | indent(4, true) $}
{% endblock %}

View File

@ -2,10 +2,10 @@ var Package = require('dgeni').Package;
module.exports = new Package('links', [])
.factory(require('dgeni-packages/ngdoc/inline-tag-defs/link'))
.factory(require('./inline-tag-defs/link'))
.factory(require('dgeni-packages/ngdoc/services/getAliases'))
.factory(require('dgeni-packages/ngdoc/services/getDocFromAlias'))
.factory(require('dgeni-packages/ngdoc/services/getLinkInfo'))
.factory(require('./services/getLinkInfo'))
.config(function(inlineTagProcessor, linkInlineTagDef) {
inlineTagProcessor.inlineTagDefinitions.push(linkInlineTagDef);

View File

@ -0,0 +1,22 @@
var INLINE_LINK = /(\S+)(?:\s+([\s\S]+))?/;
module.exports = function linkInlineTagDef(getLinkInfo, createDocMessage) {
return {
name: 'link',
description: 'Process inline link tags (of the form {@link some/uri Some Title}), replacing them with HTML anchors',
handler: function(doc, tagName, tagDescription) {
// Parse out the uri and title
return tagDescription.replace(INLINE_LINK, function(match, uri, title) {
var linkInfo = getLinkInfo(uri, title, doc);
if ( !linkInfo.valid ) {
throw new Error(createDocMessage(linkInfo.error, doc));
}
return "<a href='" + linkInfo.url + "'>" + linkInfo.title + "</a>";
});
}
};
};

View File

@ -0,0 +1,70 @@
var _ = require('lodash');
var path = require('canonical-path');
/**
* @dgService getLinkInfo
* @description
* Get link information to a document that matches the given url
* @kind function
* @param {String} url The url to match
* @param {String} title An optional title to return in the link information
* @return {Object} The link information
*
* @property {boolean} relativeLinks Whether we expect the links to be relative to the originating doc
*/
module.exports = function getLinkInfo(getDocFromAlias, encodeCodeBlock, log) {
return function getLinkInfoImpl(url, title, currentDoc) {
var linkInfo = {
url: url,
type: 'url',
valid: true,
title: title || url
};
if ( !url ) {
throw new Error('Invalid url');
}
var docs = getDocFromAlias(url, currentDoc);
if ( docs.length > 1 ) {
linkInfo.valid = false;
linkInfo.error = 'Ambiguous link: "' + url + '".\n' +
docs.reduce(function(msg, doc) { return msg + '\n "' + doc.id + '" ('+ doc.docType + ') : (' + doc.area + ')'; }, 'Matching docs: ');
} else if ( docs.length === 1 ) {
linkInfo.url = docs[0].path;
linkInfo.title = title || encodeCodeBlock(docs[0].name, true);
linkInfo.type = 'doc';
if ( getLinkInfoImpl.relativeLinks && currentDoc && currentDoc.path ) {
var currentFolder = path.dirname(currentDoc.path);
var docFolder = path.dirname(linkInfo.url);
var relativeFolder = path.relative(path.join('/', currentFolder), path.join('/', docFolder));
linkInfo.url = path.join(relativeFolder, path.basename(linkInfo.url));
log.debug(currentDoc.path, docs[0].path, linkInfo.url);
}
} else if ( url.indexOf('#') > 0 ) {
var pathAndHash = url.split('#');
linkInfo = getLinkInfoImpl(pathAndHash[0], title, currentDoc);
linkInfo.url = linkInfo.url + '#' + pathAndHash[1];
return linkInfo;
} else if ( url.indexOf('/') === -1 && url.indexOf('#') !== 0 ) {
linkInfo.valid = false;
linkInfo.error = 'Invalid link (does not match any doc): "' + url + '"';
} else {
linkInfo.title = title || (( url.indexOf('#') === 0 ) ? url.substring(1) : path.basename(url, '.html'));
}
return linkInfo;
};
};

View File

@ -284,6 +284,18 @@ function createDocsTasks(publicBuild) {
createDocsTasks(true);
createDocsTasks(false);
gulp.task('docs/angular.io', function() {
try {
var dgeni = new Dgeni([require('./docs/angular.io-package')]);
return dgeni.generate();
} catch(x) {
console.log(x);
console.log(x.stack);
throw x;
}
});
// ------------------
// CI tests suites

View File

@ -73,6 +73,9 @@
"gulp-traceur": "0.17.*",
"gulp-typescript": "ivogabe/gulp-typescript#3422fbff06532ccc57368f3b4c8801de8f72ef27",
"gulp-webserver": "^0.8.7",
"html2jade": "^0.8.3",
"indent-string": "^1.2.1",
"js-beautify": "^1.5.5",
"js-yaml": "^3.2.7",
"karma": "^0.12.23",
"karma-chrome-launcher": "^0.1.4",
@ -81,12 +84,14 @@
"karma-jasmine": "^0.2.2",
"lodash": "^2.4.1",
"madge": "^0.5.0",
"marked": "^0.3.3",
"merge": "^1.2.0",
"merge2": "^0.3.5",
"minijasminenode2": "^1.0.0",
"minimatch": "^2.0.1",
"minimist": "1.1.x",
"mock-fs": "^2.5.0",
"node-html-encoder": "0.0.2",
"parse5": "1.3.2",
"protractor": "2.0.0",
"q": "^1.0.1",
@ -94,6 +99,7 @@
"sorted-object": "^1.0.0",
"source-map": "^0.3.0",
"sprintf-js": "1.0.*",
"string": "^3.1.1",
"symlink-or-copy": "^1.0.1",
"systemjs-builder": "^0.10.3",
"temp": "^0.8.1",