diff --git a/.changeset/spotty-lemons-float.md b/.changeset/spotty-lemons-float.md new file mode 100644 index 0000000..ee54535 --- /dev/null +++ b/.changeset/spotty-lemons-float.md @@ -0,0 +1,5 @@ +--- +'@pandacss/eslint-plugin': patch +--- + +Ignore non panda files diff --git a/.changeset/tender-chefs-help.md b/.changeset/tender-chefs-help.md new file mode 100644 index 0000000..cb969dc --- /dev/null +++ b/.changeset/tender-chefs-help.md @@ -0,0 +1,5 @@ +--- +'@pandacss/eslint-plugin': patch +--- + +Fix array syntax in `no-dynamic-styling` diff --git a/docs/rules/no-dynamic-styling.md b/docs/rules/no-dynamic-styling.md index 9a2bd81..1b520df 100644 --- a/docs/rules/no-dynamic-styling.md +++ b/docs/rules/no-dynamic-styling.md @@ -20,6 +20,13 @@ const styles = css({ bg: color }); ``` ```js +import { css } from './panda/css'; + +const size = '8'; +const styles = css({ padding: ['4', size] }); +``` +```js + import { stack } from './panda/patterns'; const align = 'center'; @@ -74,6 +81,12 @@ const styles = css({ bg: 'gray.900' }); ``` ```js +import { css } from './panda/css'; + +const styles = css({ padding: ['4', '8'] }); +``` +```js + import { Circle } from './panda/jsx'; function App(){ diff --git a/plugin/src/rules/no-dynamic-styling.ts b/plugin/src/rules/no-dynamic-styling.ts index 9bd5fb5..64c512d 100644 --- a/plugin/src/rules/no-dynamic-styling.ts +++ b/plugin/src/rules/no-dynamic-styling.ts @@ -2,6 +2,7 @@ import type { TSESTree } from '@typescript-eslint/utils' import { type Rule, createRule } from '../utils' import { isInPandaFunction, isPandaAttribute, isPandaProp, isRecipeVariant } from '../utils/helpers' import { + isArrayExpression, isIdentifier, isJSXExpressionContainer, isLiteral, @@ -46,6 +47,9 @@ const rule: Rule = createRule({ if (isObjectExpression(node.value.expression)) return if (!isPandaProp(node, context)) return + if (isArrayExpression(node.value.expression)) { + return checkElements(node.value.expression, context) + } context.report({ node: node.value, @@ -53,6 +57,7 @@ const rule: Rule = createRule({ }) }, + // Dynamic properties 'Property[computed=true]'(node: TSESTree.Property) { if (!isInPandaFunction(node, context)) return @@ -74,6 +79,10 @@ const rule: Rule = createRule({ if (!isPandaAttribute(node, context)) return + if (isArrayExpression(node.value)) { + return checkElements(node.value, context) + } + context.report({ node: node.value, messageId: 'dynamic', @@ -83,4 +92,17 @@ const rule: Rule = createRule({ }, }) +function checkElements(array: TSESTree.ArrayExpression, context: Parameters<(typeof rule)['create']>[0]) { + array.elements.forEach((node) => { + if (!node) return + if (isLiteral(node)) return + if (isTemplateLiteral(node) && node.expressions.length === 0) return + + context.report({ + node: node, + messageId: 'dynamic', + }) + }) +} + export default rule diff --git a/plugin/src/utils/nodes.ts b/plugin/src/utils/nodes.ts index 3cd3998..2df2b05 100644 --- a/plugin/src/utils/nodes.ts +++ b/plugin/src/utils/nodes.ts @@ -11,6 +11,8 @@ export const isLiteral = isNodeOfType(AST_NODE_TYPES.Literal) export const isTemplateLiteral = isNodeOfType(AST_NODE_TYPES.TemplateLiteral) +export const isArrayExpression = isNodeOfType(AST_NODE_TYPES.ArrayExpression) + export const isObjectExpression = isNodeOfType(AST_NODE_TYPES.ObjectExpression) export const isMemberExpression = isNodeOfType(AST_NODE_TYPES.MemberExpression) diff --git a/plugin/tests/no-dynamic-styling.test.ts b/plugin/tests/no-dynamic-styling.test.ts index 09f230a..18a11bb 100644 --- a/plugin/tests/no-dynamic-styling.test.ts +++ b/plugin/tests/no-dynamic-styling.test.ts @@ -11,6 +11,13 @@ import { css } from './panda/css'; const styles = css({ bg: 'gray.900' })`, }, + { + code: javascript` +import { css } from './panda/css'; + +const styles = css({ padding: ['4', '8'] })`, + }, + { code: javascript` import { Circle } from './panda/jsx'; @@ -39,6 +46,14 @@ const color = 'red.100'; const styles = css({ bg: color })`, }, + { + code: javascript` +import { css } from './panda/css'; + +const size = '8'; +const styles = css({ padding: ['4', size] })`, + }, + { code: javascript` import { stack } from './panda/patterns'; diff --git a/sandbox/v9/src/App.tsx b/sandbox/v9/src/App.tsx index 6d24583..5e6736c 100644 --- a/sandbox/v9/src/App.tsx +++ b/sandbox/v9/src/App.tsx @@ -24,6 +24,7 @@ console.log(keyframes, literal) const LocalFactoryComp = panda('button') +const pbe = '4' function App() { const className = css({ bg: 'red.100', @@ -33,6 +34,7 @@ function App() { marginTop: '{spacings.4} token(spacing.600)', margin: '4', pt: token('sizes.4'), + paddingBlockEnd: ['4', pbe], }) const color = 'red' @@ -69,6 +71,7 @@ function App() { bg="red.200" borderColor="red.500" borderTopColor={'#111'} + paddingBlockEnd={['4', color]} > Element 2