eslint-plugin-tailwindcss
Advanced tools
Comparing version 1.10.0 to 1.11.0
@@ -14,2 +14,3 @@ /** | ||
const getOption = require('../util/settings'); | ||
const parserUtil = require('../util/parser'); | ||
@@ -289,3 +290,3 @@ //------------------------------------------------------------------------------ | ||
//---------------------------------------------------------------------- | ||
return { | ||
const scriptVisitor = { | ||
JSXAttribute: function (node) { | ||
@@ -307,3 +308,13 @@ if (!astUtil.isValidJSXAttribute(node)) { | ||
}; | ||
const templateVisitor = { | ||
VAttribute: function (node) { | ||
if (!astUtil.isValidVueAttribute(node)) { | ||
return; | ||
} | ||
sortNodeArgumentValue(node); | ||
}, | ||
}; | ||
return parserUtil.defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor); | ||
}, | ||
}; |
@@ -14,2 +14,3 @@ /** | ||
const getOption = require('../util/settings'); | ||
const parserUtil = require('../util/parser'); | ||
@@ -124,3 +125,3 @@ //------------------------------------------------------------------------------ | ||
return { | ||
const scriptVisitor = { | ||
JSXAttribute: function (node) { | ||
@@ -152,3 +153,14 @@ if (!astUtil.isValidJSXAttribute(node)) { | ||
}; | ||
const templateVisitor = { | ||
VAttribute: function (node) { | ||
if (!astUtil.isValidVueAttribute(node)) { | ||
return; | ||
} | ||
astUtil.parseNodeRecursive(node, null, parseForContradictingClassNames, true); | ||
}, | ||
}; | ||
return parserUtil.defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor); | ||
}, | ||
}; |
@@ -15,2 +15,3 @@ /** | ||
const getOption = require('../util/settings'); | ||
const parserUtil = require('../util/parser'); | ||
@@ -100,3 +101,3 @@ //------------------------------------------------------------------------------ | ||
return { | ||
const scriptVisitor = { | ||
JSXAttribute: function (node) { | ||
@@ -117,3 +118,14 @@ if (!astUtil.isValidJSXAttribute(node)) { | ||
}; | ||
const templateVisitor = { | ||
VAttribute: function (node) { | ||
if (!astUtil.isValidVueAttribute(node)) { | ||
return; | ||
} | ||
astUtil.parseNodeRecursive(node, null, parseForCustomClassNames); | ||
}, | ||
}; | ||
return parserUtil.defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor); | ||
}, | ||
}; |
@@ -21,2 +21,12 @@ /** | ||
/** | ||
* Find out if node is `class` | ||
* | ||
* @param {ASTNode} node The AST node being checked | ||
* @returns {Boolean} | ||
*/ | ||
function isVueClassAttribute(node) { | ||
return node.key && /^class$/.test(node.key.name); | ||
} | ||
/** | ||
* Find out if node's value attribute is just simple text | ||
@@ -27,2 +37,15 @@ * | ||
*/ | ||
function isVueLiteralAttributeValue(node) { | ||
if (node.value && node.value.type === 'VLiteral') { | ||
return true; | ||
} | ||
return false; | ||
} | ||
/** | ||
* Find out if node's value attribute is just simple text | ||
* | ||
* @param {ASTNode} node The AST node being checked | ||
* @returns {Boolean} | ||
*/ | ||
function isLiteralAttributeValue(node) { | ||
@@ -55,2 +78,20 @@ if (node.value && node.value.type === 'Literal') { | ||
/** | ||
* Find out if the node is a valid candidate for our rules | ||
* | ||
* @param {ASTNode} node The AST node being checked | ||
* @returns {Boolean} | ||
*/ | ||
function isValidVueAttribute(node) { | ||
if (!isVueClassAttribute(node)) { | ||
// Only run for class attributes | ||
return false; | ||
} | ||
if (!isVueLiteralAttributeValue(node)) { | ||
// No support for dynamic or conditional classnames | ||
return false; | ||
} | ||
return true; | ||
} | ||
/** | ||
* Inspect and parse an abstract syntax node and run a callback function | ||
@@ -134,2 +175,3 @@ * | ||
isValidJSXAttribute, | ||
isValidVueAttribute, | ||
parseNodeRecursive, | ||
@@ -136,0 +178,0 @@ getTemplateElementPrefix, |
{ | ||
"name": "eslint-plugin-tailwindcss", | ||
"version": "1.10.0", | ||
"version": "1.11.0", | ||
"description": "Rules enforcing best practices while using Tailwind CSS", | ||
@@ -31,3 +31,4 @@ "keywords": [ | ||
"eslint": "^7.1.0", | ||
"mocha": "^7.2.0" | ||
"mocha": "^7.2.0", | ||
"vue-eslint-parser": "^7.6.0" | ||
}, | ||
@@ -34,0 +35,0 @@ "engines": { |
@@ -13,2 +13,8 @@ # eslint-plugin-tailwindcss | ||
## Latest changelog | ||
- Basic [support for Vue SFC](https://github.com/francoismassart/eslint-plugin-tailwindcss/releases/tag/v1.11.0) (Single File Components) in `v1.11.0` | ||
[View all releases on github](https://github.com/francoismassart/eslint-plugin-tailwindcss/releases) | ||
## Supported Rules | ||
@@ -63,3 +69,3 @@ | ||
> The following lines are matching the configuration saved `recommended` preset... | ||
> The following lines are matching the configuration saved in the `recommended` preset... | ||
@@ -66,0 +72,0 @@ ```json |
@@ -46,2 +46,17 @@ /** | ||
{ | ||
code: `<template><div class="container box-content lg:box-border custom">Simple, basic</div></template>`, | ||
filename: "test.vue", | ||
parser: require.resolve("vue-eslint-parser"), | ||
}, | ||
{ | ||
code: `<template><div class='box-content lg:box-border'>Simple quotes</div></template>`, | ||
filename: "test.vue", | ||
parser: require.resolve("vue-eslint-parser"), | ||
}, | ||
{ | ||
code: `<template><div class="p-5 lg:p-4 md:py-2 sm:px-3 xl:px-6">'p', then 'py' then 'px'</div></template>`, | ||
filename: "test.vue", | ||
parser: require.resolve("vue-eslint-parser"), | ||
}, | ||
{ | ||
code: `<div class="custom another-custom w-12 lg:w-6">prependCustom: true</div>`, | ||
@@ -139,2 +154,23 @@ options: [ | ||
{ | ||
code: `<template><div class="sm:w-6 container w-12">Classnames will be ordered</div></template>`, | ||
output: `<template><div class="container w-12 sm:w-6">Classnames will be ordered</div></template>`, | ||
errors: errors, | ||
filename: "test.vue", | ||
parser: require.resolve("vue-eslint-parser"), | ||
}, | ||
{ | ||
code: `<template><div class="sm:py-5 p-4 sm:px-7 lg:p-8">Enhancing readability</div></template>`, | ||
output: `<template><div class="p-4 lg:p-8 sm:py-5 sm:px-7">Enhancing readability</div></template>`, | ||
errors: errors, | ||
filename: "test.vue", | ||
parser: require.resolve("vue-eslint-parser"), | ||
}, | ||
{ | ||
code: `<template><div class="grid grid-cols-1 sm:grid-cols-2 sm:px-8 sm:py-12 sm:gap-x-8 md:py-16">:)</div></template>`, | ||
output: `<template><div class="grid grid-cols-1 sm:grid-cols-2 sm:gap-x-8 sm:py-12 md:py-16 sm:px-8">:)</div></template>`, | ||
errors: errors, | ||
filename: "test.vue", | ||
parser: require.resolve("vue-eslint-parser"), | ||
}, | ||
{ | ||
code: `<div class="bg-gradient-to-r from-green-400 to-blue-500 focus:from-pink-500 focus:to-yellow-500"></div>`, | ||
@@ -141,0 +177,0 @@ output: `<div class="bg-gradient-to-r from-green-400 focus:from-pink-500 to-blue-500 focus:to-yellow-500"></div>`, |
@@ -37,2 +37,12 @@ /** | ||
{ | ||
code: '<template><div class="overflow-auto overflow-x-hidden lg:overflow-x-auto lg:dark:overflow-x-visible lg:dark:active:overflow-x-visible active:overflow-auto"></div></template>', | ||
filename: "test.vue", | ||
parser: require.resolve("vue-eslint-parser"), | ||
}, | ||
{ | ||
code: '<template><div class="p-1 px-2 sm:px-3 sm:pt-0">Accepts shorthands</div></template>', | ||
filename: "test.vue", | ||
parser: require.resolve("vue-eslint-parser"), | ||
}, | ||
{ | ||
code: '<div class="p-1 px-2 sm_px-3 sm_pt-0">Still works with different separator</div>', | ||
@@ -113,2 +123,33 @@ options: [ | ||
{ | ||
code: '<template><div class="container w-1 w-2"></div></template>', | ||
errors: [ | ||
{ | ||
messageId: "conflictingClassnames", | ||
data: { | ||
classnames: "w-1, w-2", | ||
}, | ||
}, | ||
], | ||
filename: "test.vue", | ||
parser: require.resolve("vue-eslint-parser"), | ||
}, | ||
{ | ||
code: '<template><div class="container sm_w-3 sm_w-4 lg_w-6"></div></template>', | ||
options: [ | ||
{ | ||
config: { separator: "_" }, | ||
}, | ||
], | ||
errors: [ | ||
{ | ||
messageId: "conflictingClassnames", | ||
data: { | ||
classnames: "sm_w-3, sm_w-4", | ||
}, | ||
}, | ||
], | ||
filename: "test.vue", | ||
parser: require.resolve("vue-eslint-parser"), | ||
}, | ||
{ | ||
code: '<div class="flex-1 order-first order-11 sm:order-last flex-none"></div>', | ||
@@ -115,0 +156,0 @@ errors: [ |
@@ -34,2 +34,7 @@ /** | ||
{ | ||
code: `<template><div class="container box-content lg:box-border max-h-24 self-end">Only Tailwind CSS classnames</div></template>`, | ||
filename: "test.vue", | ||
parser: require.resolve("vue-eslint-parser"), | ||
}, | ||
{ | ||
code: ` | ||
@@ -134,2 +139,15 @@ ctl(\` | ||
{ | ||
code: `<template><div class="w-12 my-custom">my-custom is not defined in Tailwind CSS!</div></template>`, | ||
errors: [ | ||
{ | ||
messageId: "customClassnameDetected", | ||
data: { | ||
classname: "my-custom", | ||
}, | ||
}, | ||
], | ||
filename: "test.vue", | ||
parser: require.resolve("vue-eslint-parser"), | ||
}, | ||
{ | ||
code: `<div class="hello world">2 classnames are not defined in Tailwind CSS!</div>`, | ||
@@ -136,0 +154,0 @@ errors: [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
118297
32
3250
129
6