Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build(docs-infra): fix autoLinkCode to ignore docs without a path #36316

Closed
Expand Up @@ -28,7 +28,7 @@ module.exports = function autoLinkCode(getDocFromAlias) {
return autoLinkCodeImpl;

function autoLinkCodeImpl() {
return (ast) => {
return (ast, file) => {
visit(ast, 'element', (node, ancestors) => {
// Only interested in code elements that:
// * do not have `no-auto-link` class
Expand All @@ -46,7 +46,7 @@ module.exports = function autoLinkCode(getDocFromAlias) {

// Can we convert the whole text node into a doc link?
const docs = getDocFromAlias(node.value);
if (foundValidDoc(docs)) {
if (foundValidDoc(docs, node.value, file)) {
parent.children.splice(index, 1, createLinkNode(docs[0], node.value));
} else {
// Parse the text for words that we can convert to links
Expand All @@ -58,7 +58,7 @@ module.exports = function autoLinkCode(getDocFromAlias) {
// remove docs that fail the custom filter tests
const filteredDocs = autoLinkCodeImpl.customFilters.reduce(
(docs, filter) => filter(docs, words, index), getDocFromAlias(word));
return foundValidDoc(filteredDocs) ?
return foundValidDoc(filteredDocs, word, file) ?
// Create a link wrapping the text node.
createLinkNode(filteredDocs[0], word) :
// this is just text so push a new text node
Expand All @@ -75,9 +75,37 @@ module.exports = function autoLinkCode(getDocFromAlias) {
};
}

function foundValidDoc(docs) {
return docs.length === 1 && !docs[0].internal &&
autoLinkCodeImpl.docTypes.indexOf(docs[0].docType) !== -1;
/**
* Validates the docs to be used to generate the links. The validation ensures
* that the docs are not `internal` and that the `docType` is supported. The `path`
* can be empty when the `API` is not public.
*
* @param {Array<Object>} docs An array of objects containing the doc details
petebacondarwin marked this conversation as resolved.
Show resolved Hide resolved
*
* @param {string} keyword The keyword the doc applies to
*/
function foundValidDoc(docs, keyword, file) {
if (docs.length !== 1) {
return false;
}

var doc = docs[0];

const isInvalidDoc = doc.docType === 'member' && !keyword.includes('.');
if (isInvalidDoc) {
return false;
}

if (doc.path === '') {
gkalpak marked this conversation as resolved.
Show resolved Hide resolved
var message = `
autoLinkCode: Doc path is empty for "${doc.id}" - link will not be generated for "${keyword}".
Please make sure if the doc should be public. If not, it should probably not be referenced in the docs.`;

file.message(message);
return false;
}

return !doc.internal && autoLinkCodeImpl.docTypes.includes(doc.docType);
}

function createLinkNode(doc, text) {
Expand Down
Expand Up @@ -126,6 +126,24 @@ describe('autoLinkCode post-processor', () => {
expect(doc.renderedContent).toEqual('<code>MyClass</code>');
});

it('should ignore code items that match an API doc but have no path set',
() => {
aliasMap.addDoc(
{docType: 'class', id: 'MyClass', aliases: ['MyClass'], path: ''});
const doc = {docType: 'test-doc', renderedContent: '<code>MyClass</code>'};
processor.$process([doc]);
expect(doc.renderedContent).toEqual('<code>MyClass</code>');
});

it('should ignore documents when the `docType` is set to `member` and the keyword doesn\'t include `.`',
() => {
aliasMap.addDoc(
{docType: 'member', id: 'MyEnum', aliases: ['MyEnum'], path: 'a/b/c'});
const doc = {docType: 'test-doc', renderedContent: '<code>MyEnum</code>'};
processor.$process([doc]);
expect(doc.renderedContent).toEqual('<code>MyEnum</code>');
});

it('should insert anchors for individual text nodes within a code block', () => {
aliasMap.addDoc({docType: 'class', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass'});
const doc = {
Expand Down
Expand Up @@ -5,6 +5,6 @@
*/

module.exports = function ignoreGenericWords() {
const ignoredWords = new Set(['a', 'classes', 'create', 'error', 'group', 'request', 'target', 'value']);
const ignoredWords = new Set(['a', 'classes', 'create', 'error', 'group', 'request', 'target', 'value', '_']);
return (docs, words, index) => ignoredWords.has(words[index].toLowerCase()) ? [] : docs;
};