diff --git a/aio/tools/transforms/links-package/index.js b/aio/tools/transforms/links-package/index.js index 2f6964cfaf..e6b93b093e 100644 --- a/aio/tools/transforms/links-package/index.js +++ b/aio/tools/transforms/links-package/index.js @@ -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, ]; }); diff --git a/aio/tools/transforms/links-package/services/disambiguators/disambiguateByContainer.js b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByContainer.js new file mode 100644 index 0000000000..abd68a4854 --- /dev/null +++ b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByContainer.js @@ -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; +} diff --git a/aio/tools/transforms/links-package/services/disambiguators/disambiguateByContainer.spec.js b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByContainer.spec.js new file mode 100644 index 0000000000..310133800f --- /dev/null +++ b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByContainer.spec.js @@ -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 }, + ]); + + }); +}); \ No newline at end of file diff --git a/aio/tools/transforms/links-package/services/disambiguators/disambiguateByNonMember.js b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByNonMember.js new file mode 100644 index 0000000000..0f6cd1dd1f --- /dev/null +++ b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByNonMember.js @@ -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; + }; +}; diff --git a/aio/tools/transforms/links-package/services/disambiguators/disambiguateByNonMember.spec.js b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByNonMember.spec.js new file mode 100644 index 0000000000..fd2afca6fd --- /dev/null +++ b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByNonMember.spec.js @@ -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]); + }); +}); \ No newline at end of file