build(aio): filter out ambiguous directives from auto code linking (#20512)

Closes #20466

PR Close #20512
This commit is contained in:
Peter Bacon Darwin 2017-11-20 14:46:14 +00:00 committed by Miško Hevery
parent ae0275e2dd
commit e2b76bb386
3 changed files with 79 additions and 2 deletions

View File

@ -36,6 +36,7 @@ module.exports = new Package('angular-base', [
.factory(require('./readers/json')) .factory(require('./readers/json'))
.factory(require('./services/copyFolder')) .factory(require('./services/copyFolder'))
.factory(require('./services/filterPipes')) .factory(require('./services/filterPipes'))
.factory(require('./services/filterAmbiguousDirectiveAliases'))
.factory(require('./services/getImageDimensions')) .factory(require('./services/getImageDimensions'))
.factory(require('./post-processors/add-image-dimensions')) .factory(require('./post-processors/add-image-dimensions'))
@ -127,9 +128,9 @@ module.exports = new Package('angular-base', [
}) })
.config(function(postProcessHtml, addImageDimensions, autoLinkCode, filterPipes) { .config(function(postProcessHtml, addImageDimensions, autoLinkCode, filterPipes, filterAmbiguousDirectiveAliases) {
addImageDimensions.basePath = path.resolve(AIO_PATH, 'src'); addImageDimensions.basePath = path.resolve(AIO_PATH, 'src');
autoLinkCode.customFilters = [filterPipes]; autoLinkCode.customFilters = [filterPipes, filterAmbiguousDirectiveAliases];
postProcessHtml.plugins = [ postProcessHtml.plugins = [
require('./post-processors/autolink-headings'), require('./post-processors/autolink-headings'),
addImageDimensions, addImageDimensions,

View File

@ -0,0 +1,26 @@
/**
* This service is used by the autoLinkCode post-processor to filter out ambiguous directive
* docs where the matching word is a directive selector.
* E.g. `ngModel`, which is a selector for a number of directives, where we are only really
* interested in the `NgModel` class.
*/
module.exports = function filterAmbiguousDirectiveAliases() {
return (docs, words, index) => {
const word = words[index];
// we are only interested if there are multiple matching docs
if (docs.length > 1) {
if (docs.every(doc =>
// We are only interested if they are all either directives or components
(doc.docType === 'directive' || doc.docType === 'component') &&
// and the matching word is in the selector for all of them
doc[doc.docType + 'Options'].selector.indexOf(word) != -1
)) {
// find the directive whose class name matches the word (case-insensitive)
return docs.filter(doc => doc.name.toLowerCase() === word.toLowerCase());
}
}
return docs;
};
};

View File

@ -0,0 +1,50 @@
const filterAmbiguousDirectiveAliases = require('./filterAmbiguousDirectiveAliases')();
const words = ['Http', 'ngModel', 'NgModel', 'NgControlStatus'];
describe('filterAmbiguousDirectiveAliases(docs, words, index)', () => {
it('should not try to filter the docs, if the docs are not all directives or components', () => {
const docs = [
{ docType: 'class', name: 'Http' },
{ docType: 'directive', name: 'NgModel', directiveOptions: { selector: '[ngModel]' } },
{ docType: 'component', name: 'NgModel', componentOptions: { selector: '[ngModel]' } }
];
// take a copy to prove `docs` was not modified
const filteredDocs = docs.slice(0);
expect(filterAmbiguousDirectiveAliases(docs, words, 1)).toEqual(filteredDocs);
expect(filterAmbiguousDirectiveAliases(docs, words, 2)).toEqual(filteredDocs);
});
describe('(where all the docs are components or directives', () => {
describe('and do not all contain the matching word in their selector)', () => {
it('should not try to filter the docs', () => {
const docs = [
{ docType: 'directive', name: 'NgModel', ['directiveOptions']: { selector: '[ngModel]' } },
{ docType: 'component', name: 'NgControlStatus', ['componentOptions']: { selector: '[ngControlStatus]' } }
];
// take a copy to prove `docs` was not modified
const filteredDocs = docs.slice(0);
expect(filterAmbiguousDirectiveAliases(docs, words, 1)).toEqual(filteredDocs);
expect(filterAmbiguousDirectiveAliases(docs, words, 2)).toEqual(filteredDocs);
// Also test that the check is case-sensitive
docs[1].componentOptions.selector = '[ngModel]';
filteredDocs[1].componentOptions.selector = '[ngModel]';
expect(filterAmbiguousDirectiveAliases(docs, words, 2)).toEqual(filteredDocs);
});
});
describe('and do all contain the matching word in there selector)', () => {
it('should filter out docs whose class name is not (case-insensitively) equal to the matching word', () => {
const docs = [
{ docType: 'directive', name: 'NgModel', ['directiveOptions']: { selector: '[ngModel],[ngControlStatus]' } },
{ docType: 'component', name: 'NgControlStatus', ['componentOptions']: { selector: '[ngModel],[ngControlStatus]' } }
];
const filteredDocs = [
{ docType: 'directive', name: 'NgModel', ['directiveOptions']: { selector: '[ngModel],[ngControlStatus]' } }
];
expect(filterAmbiguousDirectiveAliases(docs, words, 1)).toEqual(filteredDocs);
});
});
});
});