diff --git a/CHANGELOG.md b/CHANGELOG.md index d5da9ab3..2624d7e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Sort classes inside `className` in Astro ([#215](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/pull/215)) +- Support member access on function calls ([#218](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/pull/218)) ## [0.5.4] - 2023-08-31 diff --git a/package.json b/package.json index 47d834b8..1fe7cb94 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "predev": "npm run _pre", "dev": "npm run _esbuild -- --watch", "pretest": "node scripts/install-fixture-deps.js", - "test": "jest", + "test": "NODE_OPTIONS=--experimental-vm-modules jest", "prepublishOnly": "npm run build && node scripts/copy-licenses.js", "format": "prettier \"src/**/*.js\" \"scripts/**/*.js\" \"tests/test.js\" --write --print-width 100 --single-quote --no-semi --plugin-search-dir ./tests", "release-channel": "node ./scripts/release-channel.js", diff --git a/src/index.js b/src/index.js index 6700a1d5..62337b48 100644 --- a/src/index.js +++ b/src/index.js @@ -460,6 +460,37 @@ function isSortableTemplateExpression(node, functions) { return false } +/** + * + * @param {import('@babel/types').CallExpression | import('ast-types').namedTypes.CallExpression} node + * @param {Set} functions + * @returns {boolean} + */ +function isSortableCallExpression(node, functions) { + if (!node.arguments?.length) { + return false + } + + if (node.callee.type === 'Identifier') { + return functions.has(node.callee.name) + } + + if (node.callee.type === 'MemberExpression') { + let expr = node.callee.object + + // If the tag is a MemberExpression we should traverse all MemberExpression's until we find the leading Identifier + while (expr.type === 'MemberExpression') { + expr = expr.object + } + + if (expr.type === 'Identifier') { + return functions.has(expr.name) + } + } + + return false +} + /** * @param {import('@babel/types').Node} ast * @param {TransformerContext} param1 @@ -502,11 +533,7 @@ function transformJavaScript(ast, { env }) { /** @param {import('@babel/types').CallExpression} node */ CallExpression(node) { - if (!node.arguments?.length) { - return - } - - if (!functions.has(node.callee?.name ?? '')) { + if (!isSortableCallExpression(node, functions)) { return } diff --git a/tests/fixtures.test.js b/tests/fixtures.test.js index a19fa567..0ea7f30e 100644 --- a/tests/fixtures.test.js +++ b/tests/fixtures.test.js @@ -76,6 +76,10 @@ const f = tw.foo\`p-2 sm:p-1\`; const g = tw.foo.bar\`p-2 sm:p-1\`; const h = no.foo\`sm:p-1 p-2\`; const i = no.tw\`sm:p-1 p-2\`; +const k = tw.foo("p-2 sm:p-1"); +const l = tw.foo.bar("p-2 sm:p-1"); +const m = no.foo("sm:p-1 p-2"); +const n = no.tw("sm:p-1 p-2"); const A = (props) =>
; const B = () => ;`, diff --git a/tests/fixtures/custom-jsx/index.jsx b/tests/fixtures/custom-jsx/index.jsx index cff84820..2a423f76 100644 --- a/tests/fixtures/custom-jsx/index.jsx +++ b/tests/fixtures/custom-jsx/index.jsx @@ -10,6 +10,10 @@ const f = tw.foo`sm:p-1 p-2`; const g = tw.foo.bar`sm:p-1 p-2`; const h = no.foo`sm:p-1 p-2`; const i = no.tw`sm:p-1 p-2`; +const k = tw.foo('sm:p-1 p-2'); +const l = tw.foo.bar('sm:p-1 p-2'); +const m = no.foo('sm:p-1 p-2'); +const n = no.tw('sm:p-1 p-2'); const A = (props) =>
; const B = () => ;