From c269bd5d3cfc44b471afa0118755efe4f2556235 Mon Sep 17 00:00:00 2001 From: Alex Wolfe Date: Sat, 25 Apr 2015 14:29:20 -0700 Subject: [PATCH] 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` --- docs/angular.io-package/index.js | 48 ++++++++++++ .../processors/addJadeDataDocsProcessor.js | 75 +++++++++++++++++++ .../services/renderMarkdown.js | 52 +++++++++++++ .../templates/class.template.html | 48 ++++++++++++ .../templates/function.template.html | 16 ++++ .../templates/jade-data.template.html | 8 ++ .../templates/layout/base.template.html | 1 + .../templates/lib/paramList.html | 7 ++ .../templates/module.template.html | 11 +++ .../templates/var.template.html | 11 +++ docs/links-package/index.js | 4 +- docs/links-package/inline-tag-defs/link.js | 22 ++++++ docs/links-package/services/getLInkInfo.js | 70 +++++++++++++++++ gulpfile.js | 12 +++ package.json | 6 ++ 15 files changed, 389 insertions(+), 2 deletions(-) create mode 100644 docs/angular.io-package/index.js create mode 100644 docs/angular.io-package/processors/addJadeDataDocsProcessor.js create mode 100644 docs/angular.io-package/services/renderMarkdown.js create mode 100644 docs/angular.io-package/templates/class.template.html create mode 100644 docs/angular.io-package/templates/function.template.html create mode 100644 docs/angular.io-package/templates/jade-data.template.html create mode 100644 docs/angular.io-package/templates/layout/base.template.html create mode 100644 docs/angular.io-package/templates/lib/paramList.html create mode 100644 docs/angular.io-package/templates/module.template.html create mode 100644 docs/angular.io-package/templates/var.template.html create mode 100644 docs/links-package/inline-tag-defs/link.js create mode 100644 docs/links-package/services/getLInkInfo.js diff --git a/docs/angular.io-package/index.js b/docs/angular.io-package/index.js new file mode 100644 index 0000000000..cdeb17f110 --- /dev/null +++ b/docs/angular.io-package/index.js @@ -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; +}); \ No newline at end of file diff --git a/docs/angular.io-package/processors/addJadeDataDocsProcessor.js b/docs/angular.io-package/processors/addJadeDataDocsProcessor.js new file mode 100644 index 0000000000..8421816a0c --- /dev/null +++ b/docs/angular.io-package/processors/addJadeDataDocsProcessor.js @@ -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); + } + }; +}; \ No newline at end of file diff --git a/docs/angular.io-package/services/renderMarkdown.js b/docs/angular.io-package/services/renderMarkdown.js new file mode 100644 index 0000000000..538fb0537c --- /dev/null +++ b/docs/angular.io-package/services/renderMarkdown.js @@ -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 }); + }; +}; \ No newline at end of file diff --git a/docs/angular.io-package/templates/class.template.html b/docs/angular.io-package/templates/class.template.html new file mode 100644 index 0000000000..cd31e928a3 --- /dev/null +++ b/docs/angular.io-package/templates/class.template.html @@ -0,0 +1,48 @@ +{% include "lib/paramList.html" -%} +{% extends 'layout/base.template.html' -%} + +{% block body %} +p.location-badge. + exported from {$ doc.moduleDoc.id $} + defined in {$ doc.location.start.source.name $}.js (line {$ doc.location.start.line $}) + +: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 %} \ No newline at end of file diff --git a/docs/angular.io-package/templates/function.template.html b/docs/angular.io-package/templates/function.template.html new file mode 100644 index 0000000000..bd198ba0fe --- /dev/null +++ b/docs/angular.io-package/templates/function.template.html @@ -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 {$ paramList(doc.parameters) $} + + p.location-badge. + exported from {$ doc.moduleDoc.id $} + + :markdown +{$ doc.description | indent(4, true) $} + +{% endblock %} \ No newline at end of file diff --git a/docs/angular.io-package/templates/jade-data.template.html b/docs/angular.io-package/templates/jade-data.template.html new file mode 100644 index 0000000000..fcafb63db7 --- /dev/null +++ b/docs/angular.io-package/templates/jade-data.template.html @@ -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 -%} +} \ No newline at end of file diff --git a/docs/angular.io-package/templates/layout/base.template.html b/docs/angular.io-package/templates/layout/base.template.html new file mode 100644 index 0000000000..16a0d9dc96 --- /dev/null +++ b/docs/angular.io-package/templates/layout/base.template.html @@ -0,0 +1 @@ +{% block body %}{% endblock %} \ No newline at end of file diff --git a/docs/angular.io-package/templates/lib/paramList.html b/docs/angular.io-package/templates/lib/paramList.html new file mode 100644 index 0000000000..b84a8d7162 --- /dev/null +++ b/docs/angular.io-package/templates/lib/paramList.html @@ -0,0 +1,7 @@ +{% macro paramList(params) -%} + {%- if params -%} + ({%- for param in params -%} + {$ param | escape $}{% if not loop.last %}, {% endif %} + {%- endfor %}) + {%- endif %} +{%- endmacro -%} \ No newline at end of file diff --git a/docs/angular.io-package/templates/module.template.html b/docs/angular.io-package/templates/module.template.html new file mode 100644 index 0000000000..497b3ca956 --- /dev/null +++ b/docs/angular.io-package/templates/module.template.html @@ -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 %} \ No newline at end of file diff --git a/docs/angular.io-package/templates/var.template.html b/docs/angular.io-package/templates/var.template.html new file mode 100644 index 0000000000..3ff0248082 --- /dev/null +++ b/docs/angular.io-package/templates/var.template.html @@ -0,0 +1,11 @@ +{% extends 'layout/base.template.html' %} + +{% block body %} +.l-main-section + h2 {$ doc.name $} variable + p.location-badge. + exported from {$ doc.moduleDoc.id $} + + :markdown +{$ doc.description | indent(4, true) $} +{% endblock %} \ No newline at end of file diff --git a/docs/links-package/index.js b/docs/links-package/index.js index 86a835f19c..a3ffc71991 100644 --- a/docs/links-package/index.js +++ b/docs/links-package/index.js @@ -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); diff --git a/docs/links-package/inline-tag-defs/link.js b/docs/links-package/inline-tag-defs/link.js new file mode 100644 index 0000000000..a1c4c5a047 --- /dev/null +++ b/docs/links-package/inline-tag-defs/link.js @@ -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 "" + linkInfo.title + ""; + }); + } + }; +}; \ No newline at end of file diff --git a/docs/links-package/services/getLInkInfo.js b/docs/links-package/services/getLInkInfo.js new file mode 100644 index 0000000000..a0874329b5 --- /dev/null +++ b/docs/links-package/services/getLInkInfo.js @@ -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; + }; +}; \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 8e8637581a..0a23dfa325 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -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 diff --git a/package.json b/package.json index 6f66189cd4..2ef510330b 100644 --- a/package.json +++ b/package.json @@ -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",