fix(docs-infra): do not process generated nodes for auto-linking (#41709)

While generating the docs, when a `<code>` element is inspected for
auto-linking, the `autoLinkCode` Dgeni post-processor will break its
contents up into words and generate text nodes for those words that
should not be auto-linked.

Previously, our text node visitor would visit these generated text nodes
and try to auto-link them too. As a result, it would unnecessarily
process nodes that had already been checked (and could potentially
generate links that would otherwise be ignored).

You can see an occurrence of this issue in the
[Create the product list][1] section of the
"Getting started with Angular" tutorial (look for `<a>`).

This commit fixes this by ensuring the visitor will skip the current
node and any nodes generated by `autoLinkCode`.

[1]: https://v11.angular.io/start#create-the-product-list

PR Close #41709
This commit is contained in:
George Kalpakas 2021-04-24 10:46:16 +03:00 committed by Jessica Janiuk
parent 18b33e79d3
commit de19b8bb88
2 changed files with 24 additions and 1 deletions

View File

@ -63,6 +63,8 @@ module.exports = function autoLinkCode(getDocFromAlias) {
const nodes = getNodes(node, file); const nodes = getNodes(node, file);
// Replace the text node with the links and leftover text nodes // Replace the text node with the links and leftover text nodes
Array.prototype.splice.apply(parent.children, [index, 1].concat(nodes)); Array.prototype.splice.apply(parent.children, [index, 1].concat(nodes));
// Do not visit this node's children or the newly added nodes
return [visit.SKIP, index + nodes.length];
} }
}); });
}); });

View File

@ -110,11 +110,32 @@ describe('autoLinkCode post-processor', () => {
'{ xyz | <a href="a/b/myclass" class="code-anchor">myClass</a> } ' + '{ xyz | <a href="a/b/myclass" class="code-anchor">myClass</a> } ' +
'{ xyz|<a href="a/b/myclass" class="code-anchor">myClass</a> } ' + '{ xyz|<a href="a/b/myclass" class="code-anchor">myClass</a> } ' +
'<a href="a/b/myclass" class="code-anchor">MyClass</a> ' + '<a href="a/b/myclass" class="code-anchor">MyClass</a> ' +
'<a href="a/b/myclass" class="code-anchor">myClass</a> ' + 'myClass ' +
'OtherClass|<a href="a/b/myclass" class="code-anchor">MyClass</a>' + 'OtherClass|<a href="a/b/myclass" class="code-anchor">MyClass</a>' +
'</code>'); '</code>');
}); });
it('should ignore generated nodes', () => {
const filterAnchors = (docs, words, index) => (words[index].toLowerCase() === 'a') ? [] : docs;
autoLinkCode.customFilters = [filterAnchors];
autoLinkCode.docTypes = ['directive'];
aliasMap.addDoc({
docType: 'directive',
id: 'MyAnchorDirective',
aliases: ['MyAnchorDirective', 'a'],
path: 'a/b/my-anchor-directive',
});
const doc = {
docType: 'test-doc',
renderedContent: '<code>&#x3C;a></code>',
};
processor.$process([doc]);
expect(doc.renderedContent).toBe('<code>&#x3C;a></code>');
});
it('should ignore code items that match an internal API doc', () => { it('should ignore code items that match an internal API doc', () => {
aliasMap.addDoc({ aliasMap.addDoc({
docType: 'class', docType: 'class',