From c94ad87dd4fd3fdb09451af2d859ee145e192c24 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Tue, 15 Dec 2015 10:43:43 +0000 Subject: [PATCH] chore(doc-gen): add createDecoratorDocs processor The createDecoratorDocs processor identifies docs of exports that actually represent decorators and get useful information for them. This commit also set up the rest of the generation to display these new decorator docs with their own template and updates the API list so that we can filter the docs by decorator docType. --- public/resources/css/module/_api.scss | 4 ++ public/resources/js/directives/api-list.js | 3 +- tools/api-builder/angular.io-package/index.js | 7 ++ .../templates/decorator.template.html | 23 +++++++ tools/api-builder/docs-package/index.js | 1 + .../processors/createDecoratorDocs.js | 39 +++++++++++ .../processors/createDecoratorDocs.spec.js | 67 +++++++++++++++++++ .../processors/readTypeScriptModules.js | 1 + 8 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 tools/api-builder/angular.io-package/templates/decorator.template.html create mode 100644 tools/api-builder/docs-package/processors/createDecoratorDocs.js create mode 100644 tools/api-builder/docs-package/processors/createDecoratorDocs.spec.js diff --git a/public/resources/css/module/_api.scss b/public/resources/css/module/_api.scss index 0bcbc76714..7ba17787f9 100644 --- a/public/resources/css/module/_api.scss +++ b/public/resources/css/module/_api.scss @@ -1,5 +1,9 @@ @mixin icon { line-height: 14px; + &.decorator:before { + content: 'A'; + background: $blueberry; + } &.directive:before { content: 'D'; background: #db4437; diff --git a/public/resources/js/directives/api-list.js b/public/resources/js/directives/api-list.js index 5e53ae1dfc..f893b3a748 100644 --- a/public/resources/js/directives/api-list.js +++ b/public/resources/js/directives/api-list.js @@ -28,9 +28,10 @@ angularIO.directive('apiList', function () { $ctrl.apiTypes = [ { cssClass: 'directive', title: 'Directive', matches: ['directive'] }, + { cssClass: 'decorator', title: 'Decorator', matches: ['decorator'] }, { cssClass: 'class', title: 'Class', matches: ['class'] }, { cssClass: 'interface', title: 'Interface', matches: ['interface'] }, - { cssClass: 'function', title: 'function', matches: ['function'] }, + { cssClass: 'function', title: 'Function', matches: ['function'] }, { cssClass: 'const', title: 'Const or Enum', matches: ['const', 'enum'] }, { cssClass: 'var', title: 'Variable', matches: ['var', 'let'] } ]; diff --git a/tools/api-builder/angular.io-package/index.js b/tools/api-builder/angular.io-package/index.js index a0a72dcd29..b0dfa11f86 100644 --- a/tools/api-builder/angular.io-package/index.js +++ b/tools/api-builder/angular.io-package/index.js @@ -92,6 +92,13 @@ module.exports = new Package('angular.io', [basePackage, targetPackage, cheatshe outputPathTemplate:'${moduleDoc.moduleFolder}/${name}-${docType}.jade', }); + + computePathsProcessor.pathTemplates.push({ + docTypes: ['decorator'], + pathTemplate: '${moduleDoc.moduleFolder}/${name}-${docType}.html', + outputPathTemplate:'${moduleDoc.moduleFolder}/${name}-${docType}.jade', + }); + computePathsProcessor.pathTemplates.push({ docTypes: ['jade-data'], pathTemplate: '${originalDoc.moduleFolder}/_data', diff --git a/tools/api-builder/angular.io-package/templates/decorator.template.html b/tools/api-builder/angular.io-package/templates/decorator.template.html new file mode 100644 index 0000000000..5c32e00c79 --- /dev/null +++ b/tools/api-builder/angular.io-package/templates/decorator.template.html @@ -0,0 +1,23 @@ +{% include "lib/githubLinks.html" -%} +{% include "lib/paramList.html" -%} +{% extends 'layout/base.template.html' %} + +{% block body %} +include {$ relativePath(doc.path, '_util-fns') $} +.l-main-section + h2(class="decorator export") + pre.prettyprint + code. + export {$ doc.name $}(options : {@link {$ doc.decoratorType $} {$ doc.decoratorType | escape $}}){$ returnType(doc.returnType) $} + + p.location-badge. + exported from {@link {$ doc.moduleDoc.id $} {$doc.moduleDoc.id $} } + defined in {$ githubViewLink(doc) $} + + :marked +{%- if doc.notYetDocumented %} + *Not Yet Documented* +{% else %} +{$ doc.description | indentForMarkdown(4) | trimBlankLines $} +{% endif -%} +{% endblock %} diff --git a/tools/api-builder/docs-package/index.js b/tools/api-builder/docs-package/index.js index 63d3272cd8..c6cb9e88af 100644 --- a/tools/api-builder/docs-package/index.js +++ b/tools/api-builder/docs-package/index.js @@ -19,6 +19,7 @@ module.exports = new Package('angular-v2-docs', [jsdocPackage, nunjucksPackage, .processor(require('./processors/checkUnbalancedBackTicks')) .processor(require('./processors/convertBackticksToCodeBlocks')) .processor(require('./processors/addNotYetDocumentedProperty')) +.processor(require('./processors/createDecoratorDocs')) // Configure the log service .config(function(log) { diff --git a/tools/api-builder/docs-package/processors/createDecoratorDocs.js b/tools/api-builder/docs-package/processors/createDecoratorDocs.js new file mode 100644 index 0000000000..4e3b70dfd5 --- /dev/null +++ b/tools/api-builder/docs-package/processors/createDecoratorDocs.js @@ -0,0 +1,39 @@ +module.exports = function mergeDecoratorDocs() { + return { + $runAfter: ['processing-docs'], + $runBefore: ['docs-processed'], + $process: function(docs) { + docs.forEach(function(doc) { + var makeDecorator = getMakeDecoratorCall(doc); + if (makeDecorator) { + doc.docType = 'decorator'; + doc.decoratorType = makeDecorator.arguments[0].text; + } + }); + } + }; +}; + +function getMakeDecoratorCall(doc, type) { + + var makeDecoratorFnName = 'make' + (type || '')+ 'Decorator'; + + var initializer = doc.exportSymbol && + doc.exportSymbol.valueDeclaration && + doc.exportSymbol.valueDeclaration.initializer; + + if (initializer) { + // There appear to be two forms of initializer: + // export var Injectable: InjectableFactory = makeDecorator(InjectableMetadata); + // and + // export var RouteConfig: (configs: RouteDefinition[]) => ClassDecorator = makeDecorator(RouteConfigAnnotation); + // In the first case, the type assertion `` causes the AST to contain an extra level of expression + // to hold the new type of the expression. + if (initializer.expression && initializer.expression.expression) { + initializer = initializer.expression; + } + if (initializer.expression && initializer.expression.text === makeDecoratorFnName) { + return initializer; + } + } +} \ No newline at end of file diff --git a/tools/api-builder/docs-package/processors/createDecoratorDocs.spec.js b/tools/api-builder/docs-package/processors/createDecoratorDocs.spec.js new file mode 100644 index 0000000000..32d0b6501a --- /dev/null +++ b/tools/api-builder/docs-package/processors/createDecoratorDocs.spec.js @@ -0,0 +1,67 @@ +var mockPackage = require('../mocks/mockPackage'); +var Dgeni = require('dgeni'); + +describe('mergeDecoratorDocs processor', function() { + var dgeni, injector, processor, decoratorDoc, otherDoc; + + beforeEach(function() { + dgeni = new Dgeni([mockPackage()]); + injector = dgeni.configureInjector(); + processor = injector.get('mergeDecoratorDocs'); + + decoratorDoc = { + name: 'X', + docType: 'var', + exportSymbol: { + valueDeclaration: { + initializer: { + expression: { text: 'makeDecorator' }, + arguments: [{ text: 'XMetadata' }] + } + } + } + }; + + decoratorDocWithTypeAssertion = { + name: 'Y', + docType: 'var', + exportSymbol: { + valueDeclaration: { + initializer: { + expression: { + type: {}, + expression: { text: 'makeDecorator' }, + arguments: [{ text: 'YMetadata' }] + } + } + } + } + }; + otherDoc = { + name: 'Y', + docType: 'var', + exportSymbol: { + valueDeclaration: { + initializer: { + expression: { text: 'otherCall' }, + arguments: [{ text: 'param1' }] + } + } + } + }; + }); + + + it('should change the docType of only the docs that are initialied by a call to makeDecorator', function() { + processor.$process([decoratorDoc, decoratorDocWithTypeAssertion, otherDoc]); + expect(decoratorDoc.docType).toEqual('decorator'); + expect(decoratorDocWithTypeAssertion.docType).toEqual('decorator'); + expect(otherDoc.docType).toEqual('var'); + }); + + it('should extract the "type" of the decorator meta data', function() { + processor.$process([decoratorDoc, decoratorDocWithTypeAssertion, otherDoc]); + expect(decoratorDoc.decoratorType).toEqual('XMetadata'); + expect(decoratorDocWithTypeAssertion.decoratorType).toEqual('YMetadata'); + }); +}); \ No newline at end of file diff --git a/tools/api-builder/typescript-package/processors/readTypeScriptModules.js b/tools/api-builder/typescript-package/processors/readTypeScriptModules.js index 55b77ddd6d..3739b7b337 100644 --- a/tools/api-builder/typescript-package/processors/readTypeScriptModules.js +++ b/tools/api-builder/typescript-package/processors/readTypeScriptModules.js @@ -202,6 +202,7 @@ module.exports = function readTypeScriptModules(tsParser, modules, getFileInfo, var exportDoc = { docType: getExportDocType(exportSymbol), + exportSymbol: exportSymbol, name: name, id: moduleDoc.id + '/' + name, typeParams: typeParamString,