diff --git a/packages/eslint-plugin/src/functions/filter-collision-classes.ts b/packages/eslint-plugin/src/functions/filter-collision-classes.ts index 546e3dfd8..177b6d4e0 100644 --- a/packages/eslint-plugin/src/functions/filter-collision-classes.ts +++ b/packages/eslint-plugin/src/functions/filter-collision-classes.ts @@ -8,15 +8,15 @@ export default function filterCollisionClasses(classNames: string[], css: Master const collisionClassesRecord: Record = {} for (let i = 0; i < classNames.length; i++) { const className = classNames[i] - const rule = validRules.find((eachValidRule) => eachValidRule.className === className) + const rule = validRules.find((eachValidRule) => eachValidRule.name === className) const collisionClasses = [] if (rule) { for (let j = 0; j < classNames.length; j++) { const compareClassName = classNames[j] - const compareRule = validRules.find((eachValidRule) => eachValidRule.className === compareClassName) + const compareRule = validRules.find((eachValidRule) => eachValidRule.name === compareClassName) if (i !== j && compareRule - && areRulesDuplicated(rule, compareRule) - && areRuleStatesEqual(rule, compareRule) + && areRulesDuplicated(rule as any, compareRule as any) + && areRuleStatesEqual(rule as any, compareRule as any) ) { collisionClasses.push(compareClassName) } diff --git a/packages/eslint-plugin/src/rules/class-collision.ts b/packages/eslint-plugin/src/rules/class-collision.ts index 8d79eefc3..8fc820c0b 100644 --- a/packages/eslint-plugin/src/rules/class-collision.ts +++ b/packages/eslint-plugin/src/rules/class-collision.ts @@ -31,7 +31,9 @@ export default createRule({ const sourceCode = context.sourceCode const sourceCodeLines = sourceCode.lines const nodeStartLine = node.loc.start.line + const nodeStartColumn = node.loc.start.column const nodeEndLine = node.loc.end.line + const nodeEndColumn = node.loc.end.column // todo css const collisionClassesRecord = filterCollisionClasses(classNames, css) for (const className in collisionClassesRecord) { @@ -42,8 +44,9 @@ export default createRule({ const regexSafe = collisionClassName.replace(/(\\|\.|\(|\)|\[|\]|\{|\}|\+|\*|\?|\^|\$|\||\/)/g, '\\$1') fixClassNames = fixClassNames.replace(new RegExp(`\\s+${regexSafe}|${regexSafe}\\s+`), '') } + context.report({ - loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeEndLine), + loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeStartColumn, nodeEndLine, nodeEndColumn), messageId: 'collisionClass', data: { message: `"${className}" applies the same CSS declarations as ${collisionClassNamesMsg}.`, diff --git a/packages/eslint-plugin/src/rules/class-order.ts b/packages/eslint-plugin/src/rules/class-order.ts index 3766abfd7..1f662e475 100644 --- a/packages/eslint-plugin/src/rules/class-order.ts +++ b/packages/eslint-plugin/src/rules/class-order.ts @@ -163,10 +163,12 @@ export default createRule({ const sourceCodeLines = sourceCode.lines const nodeStartLine = node.loc.start.line + const nodeStartColumn = node.loc.start.column const nodeEndLine = node.loc.end.line + const nodeEndColumn = node.loc.end.column context.report({ - loc: findLoc(originalClassNamesValue, sourceCodeLines, nodeStartLine, nodeEndLine), + loc: findLoc(originalClassNamesValue, sourceCodeLines, nodeStartLine, nodeStartColumn, nodeEndLine, nodeEndColumn), messageId: 'invalidClassOrder', fix: function (fixer) { return fixer.replaceTextRange([start, end], validatedClassNamesValue) diff --git a/packages/eslint-plugin/src/rules/class-validation.ts b/packages/eslint-plugin/src/rules/class-validation.ts index 5dd204033..a8f9b183a 100644 --- a/packages/eslint-plugin/src/rules/class-validation.ts +++ b/packages/eslint-plugin/src/rules/class-validation.ts @@ -32,14 +32,17 @@ export default createRule({ const sourceCode = context.sourceCode const sourceCodeLines = sourceCode.lines const nodeStartLine = node.loc.start.line + const nodeStartColumn = node.loc.start.column const nodeEndLine = node.loc.end.line + const nodeEndColumn = node.loc.end.column + for (const className of classNames) { const { matched, errors } = validate(className, css) if (errors.length > 0) { for (const error of errors) { if (matched) { context.report({ - loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeEndLine), + loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeStartColumn, nodeEndLine, nodeEndColumn), messageId: 'invalidClass', data: { message: error.message + '.', @@ -47,7 +50,7 @@ export default createRule({ }) } else if (options.disallowUnknownClass) { context.report({ - loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeEndLine), + loc: findLoc(className, sourceCodeLines, nodeStartLine, nodeStartColumn, nodeEndLine, nodeEndColumn), messageId: 'disallowUnknownClass', data: { message: `"${className}" is not a valid or known class.` diff --git a/packages/eslint-plugin/src/utils/find-loc.ts b/packages/eslint-plugin/src/utils/find-loc.ts index 3246c513b..b8d8d0dc9 100644 --- a/packages/eslint-plugin/src/utils/find-loc.ts +++ b/packages/eslint-plugin/src/utils/find-loc.ts @@ -1,6 +1,6 @@ import { indexOfAll } from './index-of-all' -export default function findLoc(text, lines, startLine, endLine) { +export default function findLoc(text, lines, startLine, startColumn, endLine, endColumn) { const targetLines = text.match(/.+(?:\r\n|\n)?/g) let checkingTargetLine = 0 @@ -15,6 +15,10 @@ export default function findLoc(text, lines, startLine, endLine) { if (indexes.length > 0) { for (const index of indexes) { + if (i === startLine && index < startColumn || i === endLine && index > endColumn) { + continue + } + if ((index !== 0 && sourceCodeLine[index - 1].match(/\w/)) || (index + content.length < sourceCodeLine.length && sourceCodeLine[index + content.length].match(/\w/))) { continue diff --git a/packages/eslint-plugin/src/utils/parse-node-recursive.ts b/packages/eslint-plugin/src/utils/parse-node-recursive.ts index 72f92e92a..462003a71 100644 --- a/packages/eslint-plugin/src/utils/parse-node-recursive.ts +++ b/packages/eslint-plugin/src/utils/parse-node-recursive.ts @@ -92,7 +92,7 @@ export function parseNodeRecursive(rootNode, childNode, cb, skipConditional = fa } parseNodeRecursive( - rootNode, + prop, isUsedByClassNamesPlugin ? prop.key : prop.value, cb, skipConditional, diff --git a/packages/eslint-plugin/tests/class-matching/styles.test.ts b/packages/eslint-plugin/tests/class-matching/styles.test.ts index a30281342..3da90eda6 100644 --- a/packages/eslint-plugin/tests/class-matching/styles.test.ts +++ b/packages/eslint-plugin/tests/class-matching/styles.test.ts @@ -12,7 +12,8 @@ new RuleTester({ } }).run('class matching styles', rule, { valid: [ - { code: 'export default { styles: { btn: "block" } }' } + { code: 'export default { styles: { btn: "block" } }' }, + { code: 'export default { styles: { btn: { xs: "font: 12 h: 6x px: 2x r: 2x", rounded: { xs: "font: 12 h: 6x px: 2x r: 2x" } } } }' } ], invalid: [ { code: 'export default { styles: { btn: "bg:error" } }', errors: [{ messageId: 'invalidClass' }] }, diff --git a/packages/eslint-plugin/tests/find-loc.test.ts b/packages/eslint-plugin/tests/find-loc.test.ts index 3fbaa86a1..30c324956 100644 --- a/packages/eslint-plugin/tests/find-loc.test.ts +++ b/packages/eslint-plugin/tests/find-loc.test.ts @@ -5,7 +5,7 @@ describe('findLoc', () => { it('Causes incorrect class selection when there is only one character #345', () => { const text = 'f' const lines = ['font:12 font:24@sm m:32 block font:32@md mb:48 f', 'bg:indigo font:'] - const result = findLoc(text, lines, 1, 2) + const result = findLoc(text, lines, 1, 0, 2, 0) expect(result).toEqual({ start: { line: 1, column: 47 }, end: { line: 1, column: 48 } }) }) }) \ No newline at end of file