UNPKG

@codeque/core

Version:

Multiline code search for every language. Structural code search for JavaScript, TypeScript, HTML and CSS

226 lines (185 loc) 6.26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.angularEslintTemplateParser = void 0; var _templateParser = require("@angular-eslint/template-parser"); var _utils = require("../../utils"); var _common = require("./common"); var _traverseAndMatch = require("../../searchStages/traverseAndMatch"); var _beforeWildcardsComparators = require("./beforeWildcardsComparators"); const supportedExtensions = ['html', 'htm']; const getProgramNodeFromRootNode = rootNode => rootNode; // root node is program node const getProgramBodyFromRootNode = fileNode => { return fileNode.templateNodes; }; const unwrapExpressionStatement = node => { return node; }; const createBlockStatementNode = (templateNodes, position) => ({ type: 'Program', templateNodes, ...position }); const isNode = maybeNode => { return typeof maybeNode?.type === 'string'; }; const astPropsToSkip = ['range', 'sourceSpan', 'startSourceSpan', 'endSourceSpan', 'valueSpan', 'keySpan', 'loc', 'start', 'end', 'extra', 'trailingComments', 'leadingComments', 'innerComments', 'comments', 'tail' // Support for partial matching of template literals ]; const parseCode = (code, filePath = '') => { return (0, _templateParser.parseForESLint)(code, { filePath, range: true, loc: true }).ast; }; const nodeValuesSanitizers = { ['Text$3']: { value: _utils.normalizeText } }; const getSanitizedNodeValue = (nodeType, valueKey, value) => { const valueSanitizer = nodeValuesSanitizers?.[nodeType]?.[valueKey]; if (valueSanitizer) { return valueSanitizer(value); } return value; }; const shouldCompareNode = node => { if (node.type === 'Text$3') { const value = getSanitizedNodeValue('Text$3', 'value', node.value); const shouldCompare = value.length > 0; return shouldCompare; } return true; }; const getNodeType = node => node.type; const isIdentifierNode = node => _common.identifierNodeTypes.includes(getNodeType(node)); const stringLikeLiteralUtils = { // Text$3 is only pure string node isStringLikeLiteralNode: node => node.type === 'Text$3', getStringLikeLiteralValue: node => { return node?.value; } }; const numericLiteralUtils = { isNumericLiteralNode: node => node.type === 'NumericLiteral', getNumericLiteralValue: node => node.extra.raw }; const programNodeAndBlockNodeUtils = { isProgramNode: node => node.type === 'Program', isBlockNode: node => node.type === 'Program', programNodeBodyKey: 'templateNodes', blockNodeBodyKey: 'templateNodes' }; const getNodePosition = node => ({ start: node?.sourceSpan?.start?.offset ?? 0, end: node?.sourceSpan?.end?.offset ?? 0, loc: node.loc }); const getParseErrorLocation = e => ({ line: e.loc?.line ?? 0, column: e.loc?.column ?? 0 }); const alternativeNodeTypes = { Identifier: _common.identifierNodeTypes }; /** * To support wildcards in html we have to * - encode wildcard, do it in query text before parsing $$ => a_a_$$ * - decode wildcard, traverse parsed query and: a_a_$$ => $$ * `$$` is invalid tag name start in all html parsers */ const encodedWildcardSequence = 'a_$$_x'; const preprocessQueryCode = code => { const queryCode = code.replace(/(\$\$)/g, () => encodedWildcardSequence); return queryCode; }; const replaceEncodedWildcards = value => value.replace(/a_\$\$_x/g, () => '$$'); const postprocessQueryNode = queryNode => { (0, _traverseAndMatch.traverseAst)(queryNode, isNode, getNodeType, { Element$1: node => { const nodeName = node.name; if (nodeName.includes(encodedWildcardSequence)) { node.name = replaceEncodedWildcards(nodeName); } }, TextAttribute: node => { const nodeValue = node.value; if (nodeValue.includes(encodedWildcardSequence)) { node.value = replaceEncodedWildcards(nodeValue); } }, Text$3: node => { const nodeValue = node.value; if (nodeValue.includes(encodedWildcardSequence)) { node.value = replaceEncodedWildcards(nodeValue); } } }); return queryNode; }; const compareNodesBeforeWildcardsComparison = (...nodeComparatorParams) => { return (0, _utils.runNodesComparators)(_beforeWildcardsComparators.beforeWildcardsComparators, nodeComparatorParams); }; const getUniqueTokensFromStringOrIdentifierNode = ({ queryNode, caseInsensitive, parserSettings }) => { const MIN_TOKEN_LEN = 2; const { anyStringWildcardRegExp } = parserSettings.wildcardUtils; const tokens = []; const valuesToProcess = []; if (queryNode.type === 'TextAttribute') { valuesToProcess.push(queryNode.name); valuesToProcess.push(queryNode.value); } if (queryNode.type === 'Element$1') { valuesToProcess.push(queryNode.name); } if (queryNode.type === 'Text$3') { valuesToProcess.push(queryNode.value); } valuesToProcess.map(val => parserSettings.wildcardUtils.removeWildcardAliasesFromStringLiteral(val)).map(val => (0, _utils.decomposeString)(val, anyStringWildcardRegExp)).flat(1).forEach(part => { if (part.length >= MIN_TOKEN_LEN) { tokens.push(caseInsensitive ? part.toLocaleLowerCase() : part); } }); return tokens; }; const angularEslintTemplateParser = { supportedExtensions, parseCode, isNode, isIdentifierNode, astPropsToSkip, getProgramBodyFromRootNode, getProgramNodeFromRootNode, getIdentifierNodeName: _common.getIdentifierNodeName, getNodeType, unwrapExpressionStatement, createBlockStatementNode, getSanitizedNodeValue, identifierNodeTypes: _common.identifierNodeTypes, setIdentifierNodeName: _common.setIdentifierNodeName, shouldCompareNode, wildcardUtils: _common.wildcardUtils, compareNodesBeforeWildcardsComparison, compareNodesAfterWildcardsComparison: () => undefined, identifierTypeAnnotationFieldName: 'typeAnnotation', stringLikeLiteralUtils, numericLiteralUtils, programNodeAndBlockNodeUtils, getNodePosition, getParseErrorLocation, alternativeNodeTypes, postprocessQueryNode, preprocessQueryCode, getUniqueTokensFromStringOrIdentifierNode }; exports.angularEslintTemplateParser = angularEslintTemplateParser; var _default = angularEslintTemplateParser; exports.default = _default;