From adb0b761f1f089b7ee8cfa0dd7884c50357a0678 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Mon, 25 Sep 2017 20:00:05 +0100 Subject: [PATCH] build(aio): add metadata aliases for directives, components and pipes (#19317) This change will enable people to link to the API docs via their selectors or names, as used in a template. Since the selectors can be quite complex we are not able to get 100% accuracy. Closes #16787 --- .../transforms/angular-api-package/index.js | 1 + .../processors/addMetadataAliases.js | 40 +++++++++++++ .../processors/addMetadataAliases.spec.js | 57 +++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 aio/tools/transforms/angular-api-package/processors/addMetadataAliases.js create mode 100644 aio/tools/transforms/angular-api-package/processors/addMetadataAliases.spec.js diff --git a/aio/tools/transforms/angular-api-package/index.js b/aio/tools/transforms/angular-api-package/index.js index b54c75dd2a..d3e6fd8601 100644 --- a/aio/tools/transforms/angular-api-package/index.js +++ b/aio/tools/transforms/angular-api-package/index.js @@ -20,6 +20,7 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage]) .processor(require('./processors/mergeDecoratorDocs')) .processor(require('./processors/extractDecoratedClasses')) .processor(require('./processors/matchUpDirectiveDecorators')) + .processor(require('./processors/addMetadataAliases')) .processor(require('./processors/filterContainedDocs')) .processor(require('./processors/markBarredODocsAsPrivate')) .processor(require('./processors/filterPrivateDocs')) diff --git a/aio/tools/transforms/angular-api-package/processors/addMetadataAliases.js b/aio/tools/transforms/angular-api-package/processors/addMetadataAliases.js new file mode 100644 index 0000000000..ef3dff8511 --- /dev/null +++ b/aio/tools/transforms/angular-api-package/processors/addMetadataAliases.js @@ -0,0 +1,40 @@ +/** + * @dgProcessor addMetadataAliases + * + * Directives and components can also be referenced by their selectors, + * and Pipes can be referenced by their name. + * So let's add each selector as an alias to this doc. + */ +module.exports = function addMetadataAliasesProcessor() { + return { + $runAfter: ['extractDecoratedClassesProcessor'], + $runBefore: ['computing-ids'], + $process: function(docs) { + docs.forEach(doc => { + switch(doc.docType) { + case 'directive': + case 'component': + doc.aliases = doc.aliases.concat(extractSelectors(doc[doc.docType + 'Options'].selector)); + break; + case 'pipe': + if (doc.pipeOptions.name) { + doc.aliases = doc.aliases.concat(stripQuotes(doc.pipeOptions.name)); + } + break; + } + }); + } + }; +}; + +function extractSelectors(selectors) { + if (selectors) { + return stripQuotes(selectors).split(',').map(selector => selector.replace(/^\W*([\w-]+)\W*$/, '$1')); + } else { + return []; + } +} + +function stripQuotes(value) { + return (typeof(value) === 'string') ? value.trim().replace(/^(['"])(.*)\1$/, '$2') : value; +} diff --git a/aio/tools/transforms/angular-api-package/processors/addMetadataAliases.spec.js b/aio/tools/transforms/angular-api-package/processors/addMetadataAliases.spec.js new file mode 100644 index 0000000000..d1fe015e66 --- /dev/null +++ b/aio/tools/transforms/angular-api-package/processors/addMetadataAliases.spec.js @@ -0,0 +1,57 @@ +const testPackage = require('../../helpers/test-package'); +const processorFactory = require('./addMetadataAliases'); +const Dgeni = require('dgeni'); + +describe('addSelectorsAsAliases processor', () => { + + it('should be available on the injector', () => { + const dgeni = new Dgeni([testPackage('angular-api-package')]); + const injector = dgeni.configureInjector(); + const processor = injector.get('addMetadataAliasesProcessor'); + expect(processor.$process).toBeDefined(); + }); + + it('should run after the correct processor', () => { + const processor = processorFactory(); + expect(processor.$runAfter).toEqual(['extractDecoratedClassesProcessor']); + }); + + it('should run before the correct processor', () => { + const processor = processorFactory(); + expect(processor.$runBefore).toEqual(['computing-ids']); + }); + + it('should add new aliases for directives, components and pipes', () => { + const processor = processorFactory(); + const docs = [ + { docType: 'class', name: 'MyClass', aliases: ['MyClass'] }, + { docType: 'interface', name: 'MyInterface', aliases: ['MyInterface'] }, + { docType: 'enum', name: 'MyEnum', aliases: ['MyEnum'] }, + { docType: 'function', name: 'myFunction', aliases: ['myFunction'] }, + { docType: 'pipe', name: 'MyPipe', aliases: ['MyPipe'], pipeOptions: { name: '\'myPipe\'' } }, + { docType: 'directive', name: 'MyDirective', aliases: ['MyDirective'], directiveOptions: { selector: '\'my-directive,[myDirective],[my-directive]\'' } }, + { docType: 'directive', name: 'NgModel', aliases: ['NgModel'], directiveOptions: { selector: '\'[ngModel]:not([formControlName]):not([formControl])\'' } }, + { docType: 'component', name: 'MyComponent', aliases: ['MyComponent'], componentOptions: { selector: '\'my-component\'' } }, + { docType: 'decorator', name: 'MyDecorator', aliases: ['MyDecorator'] }, + { docType: 'module', name: 'myModule', aliases: ['myModule'], id: 'some/myModule' }, + { docType: 'var', name: 'myVar', aliases: ['myVar'] }, + { docType: 'let', name: 'myLet', aliases: ['myLet'] }, + { docType: 'const', name: 'myConst', aliases: ['myConst'] }, + { docType: 'type-alias', name: 'myType', aliases: ['myType'] }, + ]; + processor.$process(docs); + expect(docs[0].aliases).toEqual([docs[0].name]); + expect(docs[1].aliases).toEqual([docs[1].name]); + expect(docs[2].aliases).toEqual([docs[2].name]); + expect(docs[3].aliases).toEqual([docs[3].name]); + expect(docs[4].aliases).toEqual([docs[4].name, 'myPipe']); + expect(docs[5].aliases).toEqual([docs[5].name, 'my-directive', 'myDirective', 'my-directive']); + expect(docs[6].aliases).toEqual([docs[6].name, '[ngModel]:not([formControlName]):not([formControl])']); + expect(docs[7].aliases).toEqual([docs[7].name, 'my-component']); + expect(docs[8].aliases).toEqual([docs[8].name]); + expect(docs[9].aliases).toEqual([docs[9].name]); + expect(docs[10].aliases).toEqual([docs[10].name]); + expect(docs[11].aliases).toEqual([docs[11].name]); + expect(docs[12].aliases).toEqual([docs[12].name]); + }); +});