build(aio): improve automatic linking of code items (#24000)

This commit adds new link disambiguators that mean that more
code links can be generated automatically in a sensible way.

The best example is the use of properties within class, interface and
enum documentation.

PR Close #24000
This commit is contained in:
Pete Bacon Darwin 2018-05-18 12:08:00 +01:00 committed by Miško Hevery
parent 8977b9690e
commit e7b392bf3a
5 changed files with 96 additions and 2 deletions

View File

@ -8,16 +8,20 @@ module.exports =
.factory(require('./services/getAliases'))
.factory(require('./services/getDocFromAlias'))
.factory(require('./services/getLinkInfo'))
.factory(require('./services/disambiguators/disambiguateByContainer'))
.factory(require('./services/disambiguators/disambiguateByDeprecated'))
.factory(require('./services/disambiguators/disambiguateByModule'))
.factory(require('./services/disambiguators/disambiguateByNonMember'))
.config(function(inlineTagProcessor, linkInlineTagDef) {
inlineTagProcessor.inlineTagDefinitions.push(linkInlineTagDef);
})
.config(function(getDocFromAlias, disambiguateByDeprecated, disambiguateByModule) {
.config(function(getDocFromAlias, disambiguateByContainer, disambiguateByDeprecated, disambiguateByModule, disambiguateByNonMember) {
getDocFromAlias.disambiguators = [
disambiguateByContainer,
disambiguateByDeprecated,
disambiguateByModule
disambiguateByModule,
disambiguateByNonMember,
];
});

View File

@ -0,0 +1,19 @@
/**
* This link disambiguator looks for matching docs that have a common container with the
* originatingDoc and will return just those.
*/
module.exports = function disambiguateByContainer() {
return _disambiguate;
};
function _disambiguate(alias, originatingDoc, docs) {
if (originatingDoc) {
const filteredDocs = docs.filter(doc => doc.containerDoc === originatingDoc);
if (filteredDocs.length === 0) {
// No docs match so let's look at the containers container
return _disambiguate(alias, originatingDoc.containerDoc, docs);
}
return filteredDocs;
}
return docs;
}

View File

@ -0,0 +1,34 @@
const disambiguateByContainer = require('./disambiguateByContainer')();
const containerA = { name: 'a' };
const containerB = { name: 'b' };
const docs = [
{ id: 'doc1', containerDoc: containerA },
{ id: 'doc2', containerDoc: containerA },
{ id: 'doc3', containerDoc: containerB },
];
describe('disambiguateByContainer', () => {
it('should return all docs if the originating doc has no containerDoc', () => {
expect(disambiguateByContainer('alias', { }, docs)).toEqual(docs);
});
it('should return all docs if no docs match the originating doc containerDoc', () => {
expect(disambiguateByContainer('alias', { containerDoc: { name: 'c' } }, docs)).toEqual(docs);
});
it('should return only docs that are contained by the originating doc or its containers', () => {
expect(disambiguateByContainer('alias', containerB, docs)).toEqual([
{ id: 'doc3', containerDoc: containerB },
]);
expect(disambiguateByContainer('alias', { containerDoc: containerA }, docs)).toEqual([
{ id: 'doc1', containerDoc: containerA },
{ id: 'doc2', containerDoc: containerA },
]);
expect(disambiguateByContainer('alias', { containerDoc: containerB }, docs)).toEqual([
{ id: 'doc3', containerDoc: containerB },
]);
});
});

View File

@ -0,0 +1,14 @@
/**
* This link disambiguator will remove all the members from the list of ambiguous links
* if there is at least one link to a doc that is not a member.
*
* The heuristic is that exports are more important than members when linking, and that
* in general members will be linked to via a more explicit code links such as
* `MyClass.member` rather than simply `member`.
*/
module.exports = function disambiguateByNonMember() {
return (alias, originatingDoc, docs) => {
const filteredDocs = docs.filter(doc => doc.docType !== 'member');
return filteredDocs.length > 0 ? filteredDocs : docs;
};
};

View File

@ -0,0 +1,23 @@
const disambiguateByNonMember = require('./disambiguateByNonMember')();
const doc1 = { id: 'doc1', docType: 'function', containerDoc: {} };
const doc2 = { id: 'doc2', docType: 'member', containerDoc: {} };
const doc3 = { id: 'doc3', docType: 'member', containerDoc: {} };
const doc4 = { id: 'doc4', docType: 'class', containerDoc: {} };
const doc5 = { id: 'doc5', docType: 'member', containerDoc: {} };
describe('disambiguateByNonMember', () => {
it('should filter out docs that are not members', () => {
const docs = [doc1, doc2, doc3, doc4, doc5];
expect(disambiguateByNonMember('alias', {}, docs)).toEqual([doc1, doc4]);
});
it('should return all docs if there are no members', () => {
const docs = [doc1, doc4];
expect(disambiguateByNonMember('alias', {}, docs)).toEqual([doc1, doc4]);
});
it('should return all docs if there are only members', () => {
const docs = [doc2, doc3, doc5];
expect(disambiguateByNonMember('alias', {}, docs)).toEqual([doc2, doc3, doc5]);
});
});