Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More β†’
Socket
Sign inDemoInstall
Socket

eslint-plugin-tailwindcss

Package Overview
Dependencies
Maintainers
1
Versions
184
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-tailwindcss - npm Package Compare versions

Comparing version 3.8.3 to 3.9.0-beta.0

28

lib/rules/no-custom-classname.js

@@ -172,2 +172,16 @@ /**

const templateVisitor = {
CallExpression: function (node) {
if (callees.findIndex((name) => node.callee.name === name) === -1) {
return;
}
node.arguments.forEach((arg) => {
astUtil.parseNodeRecursive(node, arg, parseForCustomClassNames);
});
},
// TaggedTemplateExpression: function (node) {
// if (!tags.includes(node.tag.name)) {
// return;
// }
// astUtil.parseNodeRecursive(node, node.quasi, parseForCustomClassNames);
// },
VAttribute: function (node) {

@@ -177,3 +191,15 @@ if (!astUtil.isValidVueAttribute(node)) {

}
astUtil.parseNodeRecursive(node, null, parseForCustomClassNames);
if (astUtil.isVLiteralValue(node)) {
astUtil.parseNodeRecursive(node, null, parseForCustomClassNames);
}
if (astUtil.isArrayExpression(node)) {
node.value.expression.elements.forEach((arg) => {
astUtil.parseNodeRecursive(node, arg, parseForCustomClassNames);
});
}
if (astUtil.isObjectExpression(node)) {
node.value.expression.properties.forEach((prop) => {
astUtil.parseNodeRecursive(node, prop, parseForCustomClassNames);
});
}
},

@@ -180,0 +206,0 @@ };

122

lib/util/ast.js

@@ -42,3 +42,15 @@ /**

function isVueClassAttribute(node) {
return node.key && /^class$/.test(node.key.name);
switch (true) {
case node.key && /^class$/.test(node.key.name):
// class="vue-classes-as-litteral"
return true;
break;
case node.key && node.key.name.name && /^bind$/.test(node.key.name.name) && /^class$/.test(node.key.argument.name):
// v-bind:class="vue-classes-as-bind"
// :class="vue-classes-as-bind"
return true;
break;
default:
return false;
}
}

@@ -52,7 +64,42 @@

*/
function isVueLiteralAttributeValue(node) {
if (node.value && node.value.type === 'VLiteral') {
return true;
function isVLiteralValue(node) {
return node.value && node.value.type === 'VLiteral';
}
/**
* Find out if node's value attribute is an ArrayExpression
*
* @param {ASTNode} node The AST node being checked
* @returns {Boolean}
*/
function isArrayExpression(node) {
return node.value && node.value.type === 'VExpressionContainer' && node.value.expression.type === 'ArrayExpression';
}
/**
* Find out if node's value attribute is an ObjectExpression
*
* @param {ASTNode} node The AST node being checked
* @returns {Boolean}
*/
function isObjectExpression(node) {
return node.value && node.value.type === 'VExpressionContainer' && node.value.expression.type === 'ObjectExpression';
}
/**
* Find out if node's value attribute is just simple text
*
* @param {ASTNode} node The AST node being checked
* @returns {Boolean}
*/
function isVueValidAttributeValue(node) {
switch (true) {
case isVLiteralValue(node): // Simple string
case isArrayExpression(node): // ['tw-unknown-class']
case isObjectExpression(node): // {'tw-unknown-class': true}
return true;
break;
default:
return false;
}
return false;
}

@@ -113,3 +160,3 @@

}
if (!isVueLiteralAttributeValue(node)) {
if (!isVueValidAttributeValue(node)) {
// No support for dynamic or conditional classnames

@@ -140,2 +187,12 @@ return false;

return node.value.expression.value;
case 'VExpressionContainer':
switch (node.value.expression.type) {
case 'ArrayExpression':
return node.value.expression.elements;
break;
case 'ObjectExpression':
return node.value.expression.properties;
break;
}
return node.value.expression.value;
default:

@@ -170,4 +227,4 @@ return node.value.value;

*
* @param {ASTNode} arg The AST node child argument being checked
* @param {ASTNode} node The current root node being parsed by eslint
* @param {ASTNode} rootNode The current root node being parsed by eslint
* @param {ASTNode} childNode The AST node child argument being checked
* @param {Function} cb The callback function

@@ -178,7 +235,8 @@ * @param {Boolean} skipConditional Optional, indicate distinct parsing for conditional nodes

*/
function parseNodeRecursive(node, arg, cb, skipConditional = false, isolate = false) {
function parseNodeRecursive(rootNode, childNode, cb, skipConditional = false, isolate = false) {
// TODO allow vue non litteral
let originalClassNamesValue;
let classNames;
if (arg === null) {
originalClassNamesValue = extractValueFromNode(node);
if (childNode === null) {
originalClassNamesValue = extractValueFromNode(rootNode);
({ classNames } = extractClassnamesFromValue(originalClassNamesValue));

@@ -190,4 +248,4 @@ classNames = removeDuplicatesFromArray(classNames);

}
cb(classNames, node);
} else if (arg === undefined) {
cb(classNames, rootNode);
} else if (childNode === undefined) {
// Ignore invalid child candidates (probably inside complex TemplateLiteral)

@@ -198,29 +256,29 @@ return;

let trim = false;
switch (arg.type) {
switch (childNode.type) {
case 'TemplateLiteral':
arg.expressions.forEach((exp) => {
parseNodeRecursive(node, exp, cb, skipConditional, forceIsolation);
childNode.expressions.forEach((exp) => {
parseNodeRecursive(rootNode, exp, cb, skipConditional, forceIsolation);
});
arg.quasis.forEach((quasis) => {
parseNodeRecursive(node, quasis, cb, skipConditional, isolate);
childNode.quasis.forEach((quasis) => {
parseNodeRecursive(rootNode, quasis, cb, skipConditional, isolate);
});
return;
case 'ConditionalExpression':
parseNodeRecursive(node, arg.consequent, cb, skipConditional, forceIsolation);
parseNodeRecursive(node, arg.alternate, cb, skipConditional, forceIsolation);
parseNodeRecursive(rootNode, childNode.consequent, cb, skipConditional, forceIsolation);
parseNodeRecursive(rootNode, childNode.alternate, cb, skipConditional, forceIsolation);
return;
case 'LogicalExpression':
parseNodeRecursive(node, arg.right, cb, skipConditional, forceIsolation);
parseNodeRecursive(rootNode, childNode.right, cb, skipConditional, forceIsolation);
return;
case 'ArrayExpression':
arg.elements.forEach((el) => {
parseNodeRecursive(node, el, cb, skipConditional, forceIsolation);
childNode.elements.forEach((el) => {
parseNodeRecursive(rootNode, el, cb, skipConditional, forceIsolation);
});
return;
case 'ObjectExpression':
arg.properties.forEach((prop) => {
const isUsedByClassNamesPlugin = node.callee && node.callee.name === 'classnames';
childNode.properties.forEach((prop) => {
const isUsedByClassNamesPlugin = rootNode.callee && rootNode.callee.name === 'classnames';
parseNodeRecursive(
node,
rootNode,
isUsedByClassNamesPlugin ? prop.key : prop.value,

@@ -233,8 +291,11 @@ cb,

return;
case 'Property':
parseNodeRecursive(rootNode, childNode.key, cb, skipConditional, forceIsolation);
return;
case 'Literal':
trim = true;
originalClassNamesValue = arg.value;
originalClassNamesValue = childNode.value;
break;
case 'TemplateElement':
originalClassNamesValue = arg.value.raw;
originalClassNamesValue = childNode.value.raw;
break;

@@ -248,3 +309,3 @@ }

}
const targetNode = isolate ? null : node;
const targetNode = isolate ? null : rootNode;
cb(classNames, targetNode);

@@ -284,4 +345,7 @@ }

isLiteralAttributeValue,
isArrayExpression,
isObjectExpression,
isValidJSXAttribute,
isValidVueAttribute,
isVLiteralValue,
parseNodeRecursive,

@@ -288,0 +352,0 @@ getTemplateElementPrefix,

{
"name": "eslint-plugin-tailwindcss",
"version": "3.8.3",
"version": "3.9.0-beta.0",
"description": "Rules enforcing best practices while using Tailwind CSS",

@@ -21,2 +21,3 @@ "keywords": [

"scripts": {
"wip": "mocha tests/lib/rules/wip.js",
"test": "mocha tests --recursive"

@@ -23,0 +24,0 @@ },

@@ -37,3 +37,3 @@ # eslint-plugin-tailwindcss

| **Current Sponsors** <br /> Any amount is appreciated. | <a href="https://github.com/acewf" target="_blank"><img src="https://avatars.githubusercontent.com/u/4835572?s=150&amp;v=4" width="75" height="75" style="border-radius:100%;" alt="@acewf"></a> <a href="https://github.com/charkour" target="_blank"><img src="https://avatars.githubusercontent.com/u/33156025?s=150&amp;v=4" width="75" height="75" style="border-radius:100%;" alt="@charkour"></a> <a href="https://github.com/dailydotdev" target="_blank"><img class="avatar" src="https://avatars.githubusercontent.com/u/41463883?s=150&amp;v=4" width="75" height="75" style="border-radius:100%;" alt="@dailydotdev"></a> |
| **Past sponsors** <br /> Even if this is just a one-time thing. <br /> [Become a backer](https://github.com/sponsors/francoismassart?frequency=one-time) | <a href="https://github.com/mongolyy" target="_blank"><img src="https://avatars.githubusercontent.com/u/10972787?s=100&amp;v=4" width="50" height="50" style="border-radius:100%;" alt="@mongolyy"></a> <a href="https://github.com/t3dotgg" target="_blank"><img src="https://avatars.githubusercontent.com/u/6751787?s=100&amp;v=4" width="50" height="50" style="border-radius:100%;" alt="@t3dotgg"></a> |
| **Past sponsors** <br /> Even if this is just a one-time thing. <br /> [Become a backer](https://github.com/sponsors/francoismassart?frequency=one-time) | <a href="https://github.com/aniravi24" target="_blank"><img src="https://avatars.githubusercontent.com/u/5902976?s=100&amp;v=4" width="50" height="50" style="border-radius:100%;" alt="@aniravi24"></a> <a href="https://github.com/mongolyy" target="_blank"><img src="https://avatars.githubusercontent.com/u/10972787?s=100&amp;v=4" width="50" height="50" style="border-radius:100%;" alt="@mongolyy"></a> <a href="https://github.com/t3dotgg" target="_blank"><img src="https://avatars.githubusercontent.com/u/6751787?s=100&amp;v=4" width="50" height="50" style="border-radius:100%;" alt="@t3dotgg"></a> |
| **Contributors** <br /> This project can evolve thanks to all the people who contribute. <br /> You are welcome to [contribute](CONTRIBUTING.md) to this project by reporting issues, feature requests or even opening Pull Requests. | <a href="https://github.com/francoismassart/eslint-plugin-tailwindcss/graphs/contributors"><img src="https://contrib.rocks/image?repo=francoismassart/eslint-plugin-tailwindcss&width=300&columns=4" /></a> |

@@ -40,0 +40,0 @@ | **Supporters** <br /> Talk about the plugin on your social networks | <a href="https://twitter.com/search?q=eslint-plugin-tailwindcss&src=recent_search_click" target="_blank">eslint-plugin-tailwindcss on Twitter</a> |

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚑️ by Socket Inc