UNPKG

@salesforce-ux/eslint-plugin-slds

Version:

ESLint plugin provides custom linting rules specifically built for Salesforce Lightning Design System 2 (SLDS 2 beta)

198 lines (197 loc) 5.71 kB
"use strict"; // THIS IS TAKEN FROM html-eslint Object.defineProperty(exports, "__esModule", { value: true }); exports.findAttr = findAttr; exports.isAttributesEmpty = isAttributesEmpty; exports.isNodeTokensOnSameLine = isNodeTokensOnSameLine; exports.splitToLineNodes = splitToLineNodes; exports.getLocBetween = getLocBetween; exports.isExpressionInTemplate = isExpressionInTemplate; exports.isTag = isTag; exports.isComment = isComment; exports.isText = isText; exports.isOverlapWithTemplates = isOverlapWithTemplates; exports.codeToLines = codeToLines; exports.isRangesOverlap = isRangesOverlap; exports.getTemplateTokens = getTemplateTokens; const parser_1 = require("@html-eslint/parser"); /** * @param {TagNode | ScriptTagNode | StyleTagNode} node * @param {string} key * @returns {AttributeNode | undefined} */ function findAttr(node, key) { return node.attributes.find((attr) => attr.key && attr.key.value.toLowerCase() === key.toLowerCase()); } /** * Checks whether a node's attributes is empty or not. * @param {TagNode | ScriptTagNode | StyleTagNode} node * @returns {boolean} */ function isAttributesEmpty(node) { return !node.attributes || node.attributes.length <= 0; } /** * Checks whether a node's all tokens are on the same line or not. * @param {AnyNode} node A node to check * @returns {boolean} `true` if a node's tokens are on the same line, otherwise `false`. */ function isNodeTokensOnSameLine(node) { return node.loc.start.line === node.loc.end.line; } /** * * @param {Range} rangeA * @param {Range} rangeB * @returns {boolean} */ function isRangesOverlap(rangeA, rangeB) { return rangeA[0] < rangeB[1] && rangeB[0] < rangeA[1]; } /** * @param {(TextNode | CommentContentNode)['templates']} templates * @param {Range} range * @returns {boolean} */ function isOverlapWithTemplates(templates, range) { return templates .filter((template) => template.isTemplate) .some((template) => isRangesOverlap(template.range, range)); } /** * * @param {TextNode | CommentContentNode} node * @returns {LineNode[]} */ function splitToLineNodes(node) { let start = node.range[0]; let line = node.loc.start.line; const startCol = node.loc.start.column; /** * @type {LineNode[]} */ const lineNodes = []; const templates = node.templates || []; /** * * @param {import("../../types").Range} range */ function shouldSkipIndentCheck(range) { const overlappedTemplates = templates.filter((template) => template.isTemplate && isRangesOverlap(template.range, range)); const isLineInTemplate = overlappedTemplates.some((template) => { return template.range[0] <= range[0] && template.range[1] >= range[1]; }); if (isLineInTemplate) { return true; } const isLineBeforeTemplate = overlappedTemplates.some((template) => { return template.range[0] <= range[0] && template.range[1] <= range[1]; }); if (isLineBeforeTemplate) { return true; } const isLineAfterTemplate = overlappedTemplates.some((template) => { return template.range[1] <= range[0]; }); if (isLineAfterTemplate) { return true; } return false; } node.value.split("\n").forEach((value, index) => { const columnStart = index === 0 ? startCol : 0; /** * @type {import("../../types").Range} */ const range = [start, start + value.length]; const loc = { start: { line, column: columnStart, }, end: { line, column: columnStart + value.length, }, }; /** * @type {LineNode} */ const lineNode = { type: "Line", value, range, loc, skipIndentCheck: shouldSkipIndentCheck(range), }; start += value.length + 1; line += 1; lineNodes.push(lineNode); }); return lineNodes; } /** * Get location between two nodes. * @param {BaseNode} before A node placed in before * @param {BaseNode} after A node placed in after * @returns {Location} location between two nodes. */ function getLocBetween(before, after) { return { start: before.loc.end, end: after.loc.start, }; } /** * @param {AttributeValueNode} node * @return {boolean} */ function isExpressionInTemplate(node) { if (node.type === parser_1.NODE_TYPES.AttributeValue) { return node.value.indexOf("${") === 0; } return false; } /** * @param {AnyNode} node * @returns {node is TagNode} */ function isTag(node) { return node.type === parser_1.NODE_TYPES.Tag; } /** * @param {AnyNode} node * @returns {node is CommentNode} */ function isComment(node) { return node.type === parser_1.NODE_TYPES.Comment; } /** * @param {AnyNode} node * @returns {node is TextNode} */ function isText(node) { return node.type === parser_1.NODE_TYPES.Text; } const lineBreakPattern = /\r\n|[\r\n\u2028\u2029]/u; const lineEndingPattern = new RegExp(lineBreakPattern.source, "gu"); /** * @param {string} source * @returns {string[]} */ function codeToLines(source) { return source.split(lineEndingPattern); } /** * * @param {AnyToken[]} tokens * @returns {((CommentContentNode | TextNode)['templates'][number])[]} */ function getTemplateTokens(tokens) { return ([] .concat(...tokens // @ts-ignore .map((token) => token["templates"] || [])) // @ts-ignore .filter((token) => token.isTemplate)); }