From d7c77cb175d135d5bd2a7b6a070785d49e983394 Mon Sep 17 00:00:00 2001 From: Sonu Kapoor Date: Fri, 17 Apr 2020 06:59:18 -0400 Subject: [PATCH] refactor(docs-infra): refactors `autoLinkCode` (#36686) PR Close #36686 --- .../post-processors/auto-link-code.js | 96 +++++++++++-------- 1 file changed, 56 insertions(+), 40 deletions(-) diff --git a/aio/tools/transforms/angular-base-package/post-processors/auto-link-code.js b/aio/tools/transforms/angular-base-package/post-processors/auto-link-code.js index f84481bace..278205eef7 100644 --- a/aio/tools/transforms/angular-base-package/post-processors/auto-link-code.js +++ b/aio/tools/transforms/angular-base-package/post-processors/auto-link-code.js @@ -30,51 +30,67 @@ module.exports = function autoLinkCode(getDocFromAlias) { function autoLinkCodeImpl() { return (ast, file) => { visit(ast, 'element', (node, ancestors) => { - // Only interested in code elements that: - // * do not have `no-auto-link` class - // * do not have an ignored language - // * are not inside links - if (autoLinkCodeImpl.codeElements.some(elementType => is(node, elementType)) && - (!node.properties.className || !node.properties.className.includes('no-auto-link')) && - !autoLinkCodeImpl.ignoredLanguages.includes(node.properties.language) && - ancestors.every(ancestor => !is(ancestor, 'a'))) { - visit(node, 'text', (node, ancestors) => { - // Only interested in text nodes that are not inside links - if (ancestors.every(ancestor => !is(ancestor, 'a'))) { - const parent = ancestors[ancestors.length - 1]; - const index = parent.children.indexOf(node); - - // Can we convert the whole text node into a doc link? - const docs = getDocFromAlias(node.value); - 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 - const nodes = - textContent(node) - .split(/([A-Za-z0-9_.-]+)/) - .filter(word => word.length) - .map((word, index, words) => { - // remove docs that fail the custom filter tests - const filteredDocs = autoLinkCodeImpl.customFilters.reduce( - (docs, filter) => filter(docs, words, index), getDocFromAlias(word)); - 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 - {type: 'text', value: word}; - }); - - // Replace the text node with the links and leftover text nodes - Array.prototype.splice.apply(parent.children, [index, 1].concat(nodes)); - } - } - }); + if (!isValidCodeElement(node, ancestors)) { + return; } + + visit(node, 'text', (node, ancestors) => { + const isInLink = isInsideLink(ancestors); + if (isInLink) { + return; + } + + const parent = ancestors[ancestors.length - 1]; + const index = parent.children.indexOf(node); + + // Can we convert the whole text node into a doc link? + const docs = getDocFromAlias(node.value); + 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 + const nodes = getNodes(node, file); + // Replace the text node with the links and leftover text nodes + Array.prototype.splice.apply(parent.children, [index, 1].concat(nodes)); + } + }); }); }; } + function isValidCodeElement(node, ancestors) { + // Only interested in code elements that: + // * do not have `no-auto-link` class + // * do not have an ignored language + // * are not inside links + const isCodeElement = autoLinkCodeImpl.codeElements.some(elementType => is(node, elementType)); + const hasNoAutoLink = node.properties.className && node.properties.className.includes('no-auto-link'); + const isLanguageSupported = !autoLinkCodeImpl.ignoredLanguages.includes(node.properties.language); + const isInLink = isInsideLink(ancestors); + return isCodeElement && !hasNoAutoLink && isLanguageSupported && !isInLink; + } + + function isInsideLink(ancestors) { + return ancestors.some(ancestor => is(ancestor, 'a')); + } + + function getNodes(node, file) { + return textContent(node) + .split(/([A-Za-z0-9_.-]+)/) + .filter(word => word.length) + .map((word, index, words) => { + // remove docs that fail the custom filter tests + const filteredDocs = autoLinkCodeImpl.customFilters.reduce( + (docs, filter) => filter(docs, words, index), getDocFromAlias(word)); + + 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 + {type: 'text', value: word}; + }); + } + /** * 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`