Bug fixes

This commit is contained in:
Alex 2024-07-03 01:04:49 -04:00
parent 398f2a7c69
commit 2b3812b2ba
14 changed files with 637 additions and 251 deletions

View File

@ -1,3 +1,4 @@
{ {
"editor.formatOnSave": true "editor.formatOnSave": true,
"typescript.tsdk": "node_modules/typescript/lib"
} }

View File

@ -1,7 +1,6 @@
{ {
"name": "@aet/tailwind", "name": "@aet/tailwind",
"version": "0.0.1-beta.21", "version": "0.0.1-beta.30",
"main": "dist/index.js",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"build": "./scripts/index.ts", "build": "./scripts/index.ts",
@ -10,6 +9,14 @@
"files": [ "files": [
"dist" "dist"
], ],
"exports": {
".": "./dist/index.js",
"./package.json": "./package.json",
"./classed": "./dist/classed.mjs",
"./macro": {
"types": "./dist/macro.d.ts"
}
},
"devDependencies": { "devDependencies": {
"@aet/eslint-rules": "^0.0.34", "@aet/eslint-rules": "^0.0.34",
"@types/babel__core": "^7.20.5", "@types/babel__core": "^7.20.5",
@ -19,16 +26,15 @@
"@types/node": "^20.14.9", "@types/node": "^20.14.9",
"@types/postcss-safe-parser": "^5.0.4", "@types/postcss-safe-parser": "^5.0.4",
"@types/react": "^18.3.3", "@types/react": "^18.3.3",
"@types/stylis": "^4.2.6",
"cli-highlight": "^2.1.11", "cli-highlight": "^2.1.11",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"colord": "^2.9.3", "colord": "^2.9.3",
"css-what": "^6.1.0", "css-what": "^6.1.0",
"dedent": "^1.5.3", "dedent": "^1.5.3",
"esbuild": "^0.21.5",
"esbuild-register": "^3.5.0", "esbuild-register": "^3.5.0",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"postcss-nested": "^6.0.1", "postcss-nested": "^6.0.1",
"postcss-safe-parser": "^7.0.0",
"prettier": "^3.3.2", "prettier": "^3.3.2",
"tailwindcss": "^3.4.4", "tailwindcss": "^3.4.4",
"tsup": "^8.1.0", "tsup": "^8.1.0",
@ -42,9 +48,12 @@
"dependencies": { "dependencies": {
"@babel/core": "^7.24.7", "@babel/core": "^7.24.7",
"@emotion/hash": "^0.9.1", "@emotion/hash": "^0.9.1",
"esbuild": "^0.23.0",
"json5": "^2.2.3",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"postcss": "^8.4.39", "postcss": "^8.4.39",
"postcss-selector-parser": "^6.1.0", "postcss-selector-parser": "^6.1.0",
"stylis": "^4.3.2",
"tiny-invariant": "^1.3.3", "tiny-invariant": "^1.3.3",
"type-fest": "^4.21.0" "type-fest": "^4.21.0"
}, },

298
pnpm-lock.yaml generated
View File

@ -14,12 +14,24 @@ importers:
'@emotion/hash': '@emotion/hash':
specifier: ^0.9.1 specifier: ^0.9.1
version: 0.9.1 version: 0.9.1
esbuild:
specifier: ^0.23.0
version: 0.23.0
json5:
specifier: ^2.2.3
version: 2.2.3
lodash: lodash:
specifier: ^4.17.21 specifier: ^4.17.21
version: 4.17.21 version: 4.17.21
postcss: postcss:
specifier: ^8.4.39 specifier: ^8.4.39
version: 8.4.39 version: 8.4.39
postcss-selector-parser:
specifier: ^6.1.0
version: 6.1.0
stylis:
specifier: ^4.3.2
version: 4.3.2
tiny-invariant: tiny-invariant:
specifier: ^1.3.3 specifier: ^1.3.3
version: 1.3.3 version: 1.3.3
@ -51,6 +63,9 @@ importers:
'@types/react': '@types/react':
specifier: ^18.3.3 specifier: ^18.3.3
version: 18.3.3 version: 18.3.3
'@types/stylis':
specifier: ^4.2.6
version: 4.2.6
cli-highlight: cli-highlight:
specifier: ^2.1.11 specifier: ^2.1.11
version: 2.1.11 version: 2.1.11
@ -66,24 +81,15 @@ importers:
dedent: dedent:
specifier: ^1.5.3 specifier: ^1.5.3
version: 1.5.3 version: 1.5.3
esbuild:
specifier: ^0.21.5
version: 0.21.5
esbuild-register: esbuild-register:
specifier: ^3.5.0 specifier: ^3.5.0
version: 3.5.0(esbuild@0.21.5) version: 3.5.0(esbuild@0.23.0)
eslint: eslint:
specifier: ^8.57.0 specifier: ^8.57.0
version: 8.57.0 version: 8.57.0
postcss-nested: postcss-nested:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1(postcss@8.4.39) version: 6.0.1(postcss@8.4.39)
postcss-safe-parser:
specifier: ^7.0.0
version: 7.0.0(postcss@8.4.39)
postcss-selector-parser:
specifier: ^6.1.0
version: 6.1.0
prettier: prettier:
specifier: ^3.3.2 specifier: ^3.3.2
version: 3.3.2 version: 3.3.2
@ -249,138 +255,282 @@ packages:
cpu: [ppc64] cpu: [ppc64]
os: [aix] os: [aix]
'@esbuild/aix-ppc64@0.23.0':
resolution: {integrity: sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
'@esbuild/android-arm64@0.21.5': '@esbuild/android-arm64@0.21.5':
resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@esbuild/android-arm64@0.23.0':
resolution: {integrity: sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.21.5': '@esbuild/android-arm@0.21.5':
resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [arm] cpu: [arm]
os: [android] os: [android]
'@esbuild/android-arm@0.23.0':
resolution: {integrity: sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
'@esbuild/android-x64@0.21.5': '@esbuild/android-x64@0.21.5':
resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
os: [android] os: [android]
'@esbuild/android-x64@0.23.0':
resolution: {integrity: sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
'@esbuild/darwin-arm64@0.21.5': '@esbuild/darwin-arm64@0.21.5':
resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@esbuild/darwin-arm64@0.23.0':
resolution: {integrity: sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-x64@0.21.5': '@esbuild/darwin-x64@0.21.5':
resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@esbuild/darwin-x64@0.23.0':
resolution: {integrity: sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
'@esbuild/freebsd-arm64@0.21.5': '@esbuild/freebsd-arm64@0.21.5':
resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [arm64] cpu: [arm64]
os: [freebsd] os: [freebsd]
'@esbuild/freebsd-arm64@0.23.0':
resolution: {integrity: sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-x64@0.21.5': '@esbuild/freebsd-x64@0.21.5':
resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@esbuild/freebsd-x64@0.23.0':
resolution: {integrity: sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
'@esbuild/linux-arm64@0.21.5': '@esbuild/linux-arm64@0.21.5':
resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@esbuild/linux-arm64@0.23.0':
resolution: {integrity: sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm@0.21.5': '@esbuild/linux-arm@0.21.5':
resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@esbuild/linux-arm@0.23.0':
resolution: {integrity: sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
'@esbuild/linux-ia32@0.21.5': '@esbuild/linux-ia32@0.21.5':
resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [ia32] cpu: [ia32]
os: [linux] os: [linux]
'@esbuild/linux-ia32@0.23.0':
resolution: {integrity: sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.21.5': '@esbuild/linux-loong64@0.21.5':
resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [loong64] cpu: [loong64]
os: [linux] os: [linux]
'@esbuild/linux-loong64@0.23.0':
resolution: {integrity: sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-mips64el@0.21.5': '@esbuild/linux-mips64el@0.21.5':
resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [mips64el] cpu: [mips64el]
os: [linux] os: [linux]
'@esbuild/linux-mips64el@0.23.0':
resolution: {integrity: sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-ppc64@0.21.5': '@esbuild/linux-ppc64@0.21.5':
resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
'@esbuild/linux-ppc64@0.23.0':
resolution: {integrity: sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-riscv64@0.21.5': '@esbuild/linux-riscv64@0.21.5':
resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
'@esbuild/linux-riscv64@0.23.0':
resolution: {integrity: sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-s390x@0.21.5': '@esbuild/linux-s390x@0.21.5':
resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
'@esbuild/linux-s390x@0.23.0':
resolution: {integrity: sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-x64@0.21.5': '@esbuild/linux-x64@0.21.5':
resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@esbuild/linux-x64@0.23.0':
resolution: {integrity: sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
'@esbuild/netbsd-x64@0.21.5': '@esbuild/netbsd-x64@0.21.5':
resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
os: [netbsd] os: [netbsd]
'@esbuild/netbsd-x64@0.23.0':
resolution: {integrity: sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
'@esbuild/openbsd-arm64@0.23.0':
resolution: {integrity: sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-x64@0.21.5': '@esbuild/openbsd-x64@0.21.5':
resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
os: [openbsd] os: [openbsd]
'@esbuild/openbsd-x64@0.23.0':
resolution: {integrity: sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
'@esbuild/sunos-x64@0.21.5': '@esbuild/sunos-x64@0.21.5':
resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
os: [sunos] os: [sunos]
'@esbuild/sunos-x64@0.23.0':
resolution: {integrity: sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
'@esbuild/win32-arm64@0.21.5': '@esbuild/win32-arm64@0.21.5':
resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@esbuild/win32-arm64@0.23.0':
resolution: {integrity: sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-ia32@0.21.5': '@esbuild/win32-ia32@0.21.5':
resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
'@esbuild/win32-ia32@0.23.0':
resolution: {integrity: sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-x64@0.21.5': '@esbuild/win32-x64@0.21.5':
resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@esbuild/win32-x64@0.23.0':
resolution: {integrity: sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
'@eslint-community/eslint-utils@4.4.0': '@eslint-community/eslint-utils@4.4.0':
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@ -586,6 +736,9 @@ packages:
'@types/react@18.3.3': '@types/react@18.3.3':
resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==}
'@types/stylis@4.2.6':
resolution: {integrity: sha512-4nebF2ZJGzQk0ka0O6+FZUWceyFv4vWq/0dXBMmrSeAwzOuOd/GxE5Pa64d/ndeNLG73dXoBsRzvtsVsYUv6Uw==}
'@types/ws@8.5.10': '@types/ws@8.5.10':
resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==}
@ -988,6 +1141,11 @@ packages:
engines: {node: '>=12'} engines: {node: '>=12'}
hasBin: true hasBin: true
esbuild@0.23.0:
resolution: {integrity: sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==}
engines: {node: '>=18'}
hasBin: true
escalade@3.1.2: escalade@3.1.2:
resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -1685,12 +1843,6 @@ packages:
peerDependencies: peerDependencies:
postcss: ^8.2.14 postcss: ^8.2.14
postcss-safe-parser@7.0.0:
resolution: {integrity: sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==}
engines: {node: '>=18.0'}
peerDependencies:
postcss: ^8.4.31
postcss-selector-parser@6.1.0: postcss-selector-parser@6.1.0:
resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==} resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -1893,6 +2045,9 @@ packages:
strip-literal@2.1.0: strip-literal@2.1.0:
resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==}
stylis@4.3.2:
resolution: {integrity: sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==}
sucrase@3.35.0: sucrase@3.35.0:
resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
engines: {node: '>=16 || 14 >=14.17'} engines: {node: '>=16 || 14 >=14.17'}
@ -2383,72 +2538,144 @@ snapshots:
'@esbuild/aix-ppc64@0.21.5': '@esbuild/aix-ppc64@0.21.5':
optional: true optional: true
'@esbuild/aix-ppc64@0.23.0':
optional: true
'@esbuild/android-arm64@0.21.5': '@esbuild/android-arm64@0.21.5':
optional: true optional: true
'@esbuild/android-arm64@0.23.0':
optional: true
'@esbuild/android-arm@0.21.5': '@esbuild/android-arm@0.21.5':
optional: true optional: true
'@esbuild/android-arm@0.23.0':
optional: true
'@esbuild/android-x64@0.21.5': '@esbuild/android-x64@0.21.5':
optional: true optional: true
'@esbuild/android-x64@0.23.0':
optional: true
'@esbuild/darwin-arm64@0.21.5': '@esbuild/darwin-arm64@0.21.5':
optional: true optional: true
'@esbuild/darwin-arm64@0.23.0':
optional: true
'@esbuild/darwin-x64@0.21.5': '@esbuild/darwin-x64@0.21.5':
optional: true optional: true
'@esbuild/darwin-x64@0.23.0':
optional: true
'@esbuild/freebsd-arm64@0.21.5': '@esbuild/freebsd-arm64@0.21.5':
optional: true optional: true
'@esbuild/freebsd-arm64@0.23.0':
optional: true
'@esbuild/freebsd-x64@0.21.5': '@esbuild/freebsd-x64@0.21.5':
optional: true optional: true
'@esbuild/freebsd-x64@0.23.0':
optional: true
'@esbuild/linux-arm64@0.21.5': '@esbuild/linux-arm64@0.21.5':
optional: true optional: true
'@esbuild/linux-arm64@0.23.0':
optional: true
'@esbuild/linux-arm@0.21.5': '@esbuild/linux-arm@0.21.5':
optional: true optional: true
'@esbuild/linux-arm@0.23.0':
optional: true
'@esbuild/linux-ia32@0.21.5': '@esbuild/linux-ia32@0.21.5':
optional: true optional: true
'@esbuild/linux-ia32@0.23.0':
optional: true
'@esbuild/linux-loong64@0.21.5': '@esbuild/linux-loong64@0.21.5':
optional: true optional: true
'@esbuild/linux-loong64@0.23.0':
optional: true
'@esbuild/linux-mips64el@0.21.5': '@esbuild/linux-mips64el@0.21.5':
optional: true optional: true
'@esbuild/linux-mips64el@0.23.0':
optional: true
'@esbuild/linux-ppc64@0.21.5': '@esbuild/linux-ppc64@0.21.5':
optional: true optional: true
'@esbuild/linux-ppc64@0.23.0':
optional: true
'@esbuild/linux-riscv64@0.21.5': '@esbuild/linux-riscv64@0.21.5':
optional: true optional: true
'@esbuild/linux-riscv64@0.23.0':
optional: true
'@esbuild/linux-s390x@0.21.5': '@esbuild/linux-s390x@0.21.5':
optional: true optional: true
'@esbuild/linux-s390x@0.23.0':
optional: true
'@esbuild/linux-x64@0.21.5': '@esbuild/linux-x64@0.21.5':
optional: true optional: true
'@esbuild/linux-x64@0.23.0':
optional: true
'@esbuild/netbsd-x64@0.21.5': '@esbuild/netbsd-x64@0.21.5':
optional: true optional: true
'@esbuild/netbsd-x64@0.23.0':
optional: true
'@esbuild/openbsd-arm64@0.23.0':
optional: true
'@esbuild/openbsd-x64@0.21.5': '@esbuild/openbsd-x64@0.21.5':
optional: true optional: true
'@esbuild/openbsd-x64@0.23.0':
optional: true
'@esbuild/sunos-x64@0.21.5': '@esbuild/sunos-x64@0.21.5':
optional: true optional: true
'@esbuild/sunos-x64@0.23.0':
optional: true
'@esbuild/win32-arm64@0.21.5': '@esbuild/win32-arm64@0.21.5':
optional: true optional: true
'@esbuild/win32-arm64@0.23.0':
optional: true
'@esbuild/win32-ia32@0.21.5': '@esbuild/win32-ia32@0.21.5':
optional: true optional: true
'@esbuild/win32-ia32@0.23.0':
optional: true
'@esbuild/win32-x64@0.21.5': '@esbuild/win32-x64@0.21.5':
optional: true optional: true
'@esbuild/win32-x64@0.23.0':
optional: true
'@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)':
dependencies: dependencies:
eslint: 8.57.0 eslint: 8.57.0
@ -2651,6 +2878,8 @@ snapshots:
'@types/prop-types': 15.7.12 '@types/prop-types': 15.7.12
csstype: 3.1.3 csstype: 3.1.3
'@types/stylis@4.2.6': {}
'@types/ws@8.5.10': '@types/ws@8.5.10':
dependencies: dependencies:
'@types/node': 20.14.9 '@types/node': 20.14.9
@ -3034,10 +3263,10 @@ snapshots:
es-module-lexer@1.5.4: {} es-module-lexer@1.5.4: {}
esbuild-register@3.5.0(esbuild@0.21.5): esbuild-register@3.5.0(esbuild@0.23.0):
dependencies: dependencies:
debug: 4.3.4 debug: 4.3.4
esbuild: 0.21.5 esbuild: 0.23.0
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -3067,6 +3296,33 @@ snapshots:
'@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-ia32': 0.21.5
'@esbuild/win32-x64': 0.21.5 '@esbuild/win32-x64': 0.21.5
esbuild@0.23.0:
optionalDependencies:
'@esbuild/aix-ppc64': 0.23.0
'@esbuild/android-arm': 0.23.0
'@esbuild/android-arm64': 0.23.0
'@esbuild/android-x64': 0.23.0
'@esbuild/darwin-arm64': 0.23.0
'@esbuild/darwin-x64': 0.23.0
'@esbuild/freebsd-arm64': 0.23.0
'@esbuild/freebsd-x64': 0.23.0
'@esbuild/linux-arm': 0.23.0
'@esbuild/linux-arm64': 0.23.0
'@esbuild/linux-ia32': 0.23.0
'@esbuild/linux-loong64': 0.23.0
'@esbuild/linux-mips64el': 0.23.0
'@esbuild/linux-ppc64': 0.23.0
'@esbuild/linux-riscv64': 0.23.0
'@esbuild/linux-s390x': 0.23.0
'@esbuild/linux-x64': 0.23.0
'@esbuild/netbsd-x64': 0.23.0
'@esbuild/openbsd-arm64': 0.23.0
'@esbuild/openbsd-x64': 0.23.0
'@esbuild/sunos-x64': 0.23.0
'@esbuild/win32-arm64': 0.23.0
'@esbuild/win32-ia32': 0.23.0
'@esbuild/win32-x64': 0.23.0
escalade@3.1.2: {} escalade@3.1.2: {}
escape-string-regexp@1.0.5: {} escape-string-regexp@1.0.5: {}
@ -3750,10 +4006,6 @@ snapshots:
postcss: 8.4.39 postcss: 8.4.39
postcss-selector-parser: 6.1.0 postcss-selector-parser: 6.1.0
postcss-safe-parser@7.0.0(postcss@8.4.39):
dependencies:
postcss: 8.4.39
postcss-selector-parser@6.1.0: postcss-selector-parser@6.1.0:
dependencies: dependencies:
cssesc: 3.0.0 cssesc: 3.0.0
@ -3948,6 +4200,8 @@ snapshots:
dependencies: dependencies:
js-tokens: 9.0.0 js-tokens: 9.0.0
stylis@4.3.2: {}
sucrase@3.35.0: sucrase@3.35.0:
dependencies: dependencies:
'@jridgewell/gen-mapping': 0.3.5 '@jridgewell/gen-mapping': 0.3.5

View File

@ -28,7 +28,7 @@ await Promise.all([
build({ build({
...tsupConfig, ...tsupConfig,
entry: ["src/index.ts"], entry: ["src/index.ts"],
external: ["postcss-selector-parser", "postcss"], external: ["postcss-selector-parser", "postcss", "stylis"],
}), }),
Bun.write( Bun.write(
"dist/package.json", "dist/package.json",
@ -44,6 +44,7 @@ await Promise.all([
await Promise.all([ await Promise.all([
fs.copyFile("README.md", "dist/README.md"), fs.copyFile("README.md", "dist/README.md"),
fs.copyFile("LICENSE.md", "dist/LICENSE.md"), fs.copyFile("LICENSE.md", "dist/LICENSE.md"),
fs.copyFile("src/macro.d.ts", "dist/macro.d.ts"),
]); ]);
process.exit(0); process.exit(0);

View File

@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest";
import { getBuild } from "./utils"; import { getBuild } from "./utils";
import { getClassName } from "../index"; import { getClassName } from "../index";
describe.only("babel-tailwind", () => { describe("babel-tailwind", () => {
const compileESBuild = getBuild("styleObject"); const compileESBuild = getBuild("styleObject");
it("supports conversion into CSSProperties", async () => { it("supports conversion into CSSProperties", async () => {
@ -10,9 +10,11 @@ describe.only("babel-tailwind", () => {
clsx: "emotion", clsx: "emotion",
expectFiles: 1, expectFiles: 1,
javascript: ` javascript: `
import { tws } from "@aet/tailwind/macro";
export function Hello() { export function Hello() {
return ( return (
<div style={tws\`p-2 text-center\`}> <div style={tws\`p-2 text-center hover:font-semibold sm:p-1\`}>
Hello, world! Hello, world!
</div> </div>
); );
@ -20,9 +22,23 @@ describe.only("babel-tailwind", () => {
`, `,
}); });
const clsName = getClassName("p-2 text-center").replace(/^tw-/, "tw_"); const clsName = getClassName("p-2 text-center hover:font-semibold sm:p-1").replace(
/^tw-/,
"tw_"
);
expect(files.js.text).toContain( expect(files.js.text).toContain(
`var ${clsName} = {\n "padding": "0.5rem",\n "textAlign": "center"\n}` [
`var ${clsName} = {`,
' padding: "0.5rem",',
' textAlign: "center",',
' "&:hover": {',
' fontWeight: "600"',
" },",
' "@media (min-width: 640px)": {',
' padding: "0.25rem"',
" }",
"}",
].join("\n")
); );
expect(files.js.text).toContain(`style: ${clsName}`); expect(files.js.text).toContain(`style: ${clsName}`);
}); });

View File

@ -4,11 +4,14 @@ import { getBuild } from "./utils";
describe("babel-tailwind", () => { describe("babel-tailwind", () => {
const compileESBuild = getBuild("tw"); const compileESBuild = getBuild("tw");
it("supports grouped tw", async () => { it("supports grouped tw", async () => {
const { files } = await compileESBuild({ const { files } = await compileESBuild({
clsx: "emotion", clsx: "emotion",
expectFiles: 2, expectFiles: 2,
javascript: ` javascript: `
import { tw } from "@aet/tailwind/macro";
export default tw("text-sm", \`flex\`, { export default tw("text-sm", \`flex\`, {
"group-hover": "text-center", "group-hover": "text-center",
"[&>div]": \`font-semibold\`, "[&>div]": \`font-semibold\`,

View File

@ -4,10 +4,11 @@ import hash from "@emotion/hash";
import { isPlainObject } from "lodash"; import { isPlainObject } from "lodash";
import invariant from "tiny-invariant"; import invariant from "tiny-invariant";
import { type NodePath, type types as t } from "@babel/core"; import { type NodePath, type types as t } from "@babel/core";
import type { SourceLocation, StyleMapEntry } from "./shared"; import { type SourceLocation, type StyleMapEntry, macroName } from "./shared";
import { type ResolveTailwindOptions, getClassName } from "./index"; import { type ResolveTailwindOptions, getClassName } from "./index";
export type ClassNameCollector = (path: string, entries: StyleMapEntry[]) => void; export type ClassNameCollector = (path: string, entries: StyleMapEntry[]) => void;
type BabelTypes = typeof babel.types;
type Type = "css" | "js"; type Type = "css" | "js";
export function babelTailwind( export function babelTailwind(
@ -15,8 +16,6 @@ export function babelTailwind(
styleMap, styleMap,
clsx, clsx,
getClassName: getClass = getClassName, getClassName: getClass = getClassName,
macroFunction,
macroStyleFunction,
jsxAttributeAction = "delete", jsxAttributeAction = "delete",
jsxAttributeName = "css", jsxAttributeName = "css",
vite, vite,
@ -25,11 +24,7 @@ export function babelTailwind(
) { ) {
type BabelPluginState = ReturnType<typeof getState>; type BabelPluginState = ReturnType<typeof getState>;
function getState( function getState(path: NodePath<t.Program>, state: babel.PluginPass, t: BabelTypes) {
path: NodePath<t.Program>,
state: babel.PluginPass,
t: typeof babel.types
) {
let cx: t.Identifier; let cx: t.Identifier;
let styleImport: t.Identifier; let styleImport: t.Identifier;
@ -118,69 +113,62 @@ export function babelTailwind(
}; };
} }
const getType = (fnName: string): Type | undefined =>
fnName === macroFunction ? "css" : fnName === macroStyleFunction ? "js" : undefined;
return definePlugin<BabelPluginState>(({ types: t }) => ({ return definePlugin<BabelPluginState>(({ types: t }) => ({
Program: { Program: {
enter(path, state) { enter(path, state) {
Object.assign(state, getState(path, state, t)); const _ = getState(path, state, t);
Object.assign(state, _);
for (const {
local: { parentPath: local },
imported,
} of getMacros(t, path, macroName)) {
const type = imported === "tw" ? "css" : imported === "tws" ? "js" : undefined;
if (!type) continue;
if (isNodePath(local, t.isTaggedTemplateExpression)) {
const { node } = local;
const { tag, quasi } = node;
if (!t.isIdentifier(tag)) continue;
invariant(
!quasi.expressions.length,
`Macro call should not contain expressions`
);
const value = quasi.quasis[0].value.cooked;
if (value) {
const trimmed = trim(value);
const className = _.getClass(type, trimmed);
_.recordIfAbsent(type, {
key: className,
className: trimmed,
location: _.sliceText(node),
});
_.replaceWithImport(type, local, className);
}
} else if (isNodePath(local, t.isCallExpression)) {
const { node } = local;
const { callee } = node;
if (!t.isIdentifier(callee)) continue;
const trimmed = local.get("arguments").flatMap(evaluateArgs).join(" ");
const className = getClass(trimmed);
_.recordIfAbsent(type, {
key: className,
className: trimmed,
location: _.sliceText(node),
});
_.replaceWithImport(type, local, className);
}
}
}, },
exit({ node }, _) { exit({ node }, _) {
_.finish(node); _.finish(node);
}, },
}, },
TaggedTemplateExpression(path, _) {
if (macroFunction == null && macroStyleFunction == null) return;
const { node } = path;
const {
tag,
quasi: { quasis, expressions },
} = node;
if (!t.isIdentifier(tag)) return;
invariant(
!expressions.length,
`${macroFunction}\`\` should not contain expressions`
);
const type = getType(tag.name);
if (!type) return;
const value = quasis[0].value.cooked;
if (value) {
const trimmed = trim(value);
const className = _.getClass(type, trimmed);
_.recordIfAbsent(type, {
key: className,
className: trimmed,
location: _.sliceText(node),
});
_.replaceWithImport(type, path, className);
}
},
CallExpression(path, _) {
if (macroFunction == null) return;
const { node } = path;
const { callee } = node;
if (!t.isIdentifier(callee)) return;
const type = getType(callee.name);
if (!type) return;
const trimmed = path.get("arguments").flatMap(evaluateArgs).join(" ");
const className = getClass(trimmed);
_.recordIfAbsent(type, {
key: className,
className: trimmed,
location: _.sliceText(node),
});
_.replaceWithImport(type, path, className);
},
JSXAttribute(path, _) { JSXAttribute(path, _) {
const { name } = path.node; const { name } = path.node;
if (name.name !== jsxAttributeName) return; if (name.name !== jsxAttributeName) return;
@ -296,7 +284,7 @@ export function babelTailwind(
})); }));
} }
function getClsxImport(t: typeof babel.types, cx: t.Identifier, clsx: string) { function getClsxImport(t: BabelTypes, cx: t.Identifier, clsx: string) {
switch (clsx) { switch (clsx) {
case "emotion": case "emotion":
return t.importDeclaration( return t.importDeclaration(
@ -346,6 +334,56 @@ function evaluateArgs(path: NodePath) {
throw new Error("Invalid argument type"); throw new Error("Invalid argument type");
} }
function getName(t: BabelTypes, exp: t.Node) {
if (t.isIdentifier(exp)) {
return exp.name;
} else if (t.isStringLiteral(exp)) {
return exp.value;
}
}
function getMacros(
t: BabelTypes,
programPath: NodePath<t.Program>,
importSource: string
) {
const importDecs = programPath
.get("body")
.filter(x => isNodePath(x, t.isImportDeclaration))
.filter(x => x.node.source.value === importSource);
const macros = importDecs
.flatMap(x => x.get("specifiers"))
.map(x => {
const local = x.get("local");
if (isNodePath(x, t.isImportNamespaceSpecifier)) {
return local.scope
.getOwnBinding(local.node.name)!
.referencePaths.map(p => p.parentPath)
.filter(p => isNodePath(p, t.isMemberExpression))
.map(p => ({
local: p,
imported: getName(t, p.node.property)!,
}))
.filter(p => p.imported);
} else if (t.isImportSpecifier(x.node)) {
const imported = x.node.imported;
return local.scope.getOwnBinding(local.node.name)!.referencePaths.map(p => ({
local: p as NodePath<t.Identifier>,
imported: getName(t, imported)!,
}));
}
})
.filter(Boolean)
.flat(1);
for (const x of importDecs) {
x.remove();
}
return macros;
}
const definePlugin = const definePlugin =
<T>(fn: (runtime: typeof babel) => babel.Visitor<babel.PluginPass & T>) => <T>(fn: (runtime: typeof babel) => babel.Visitor<babel.PluginPass & T>) =>
(runtime: typeof babel) => { (runtime: typeof babel) => {
@ -367,6 +405,11 @@ function matchPath(
fn?.(nodePath); fn?.(nodePath);
} }
const isNodePath = <T extends t.Node>(
nodePath: NodePath<t.Node | null | undefined> | null,
predicate: (node: t.Node) => node is T
): nodePath is NodePath<T> => Boolean(nodePath?.node && predicate(nodePath.node));
function getSuffix(add: boolean | undefined, entries: StyleMapEntry[]) { function getSuffix(add: boolean | undefined, entries: StyleMapEntry[]) {
if (!add) return ""; if (!add) return "";

View File

@ -3,14 +3,15 @@
import { import {
type AtRule, type AtRule,
type Builder, type Builder,
type ChildNode,
type Node, type Node,
type Root, type Root,
type Rule, type Rule,
parse, parse,
} from "postcss"; } from "postcss";
import JSON5 from "json5";
import parseSelector from "postcss-selector-parser"; import parseSelector from "postcss-selector-parser";
import Stringifier from "postcss/lib/stringifier"; import Stringifier from "postcss/lib/stringifier";
import { type Element, compile } from "stylis";
import { camelCase } from "lodash"; import { camelCase } from "lodash";
function getSelectorScope(selector: string): string { function getSelectorScope(selector: string): string {
@ -99,10 +100,6 @@ function getCssIndexedByScope(css: string) {
} }
for (const scope of scopesStack.at(-1)!) { for (const scope of scopesStack.at(-1)!) {
if (!cssIndexedByScope.has(scope)) {
cssIndexedByScope.set(scope, "");
}
if ( if (
flag === "start" && flag === "start" &&
isNode(node, "rule") && isNode(node, "rule") &&
@ -113,7 +110,7 @@ function getCssIndexedByScope(css: string) {
.join(", ")} {`; .join(", ")} {`;
} }
cssIndexedByScope.set(scope, cssIndexedByScope.get(scope) + output); cssIndexedByScope.set(scope, (cssIndexedByScope.get(scope) || "") + output);
} }
if (flag === "end") { if (flag === "end") {
@ -124,23 +121,6 @@ function getCssIndexedByScope(css: string) {
return cssIndexedByScope; return cssIndexedByScope;
} }
function convertSelectorForEmotion(
selector: string,
scope: string,
knownScopes: Set<string>,
mapClassNames: (className: string) => string
): string {
return parseSelector(nodes => {
nodes.first.walkClasses(node => {
if (node.toString() === scope) {
node.toString = () => "&";
} else if (knownScopes.has(node.toString())) {
node.toString = () => `.\${${mapClassNames(node.value)}}`;
}
});
}).processSync(selector);
}
const convertScopeToModuleName = (scope: string) => const convertScopeToModuleName = (scope: string) =>
camelCase(scope) camelCase(scope)
.replace(/^(\d)/, "_$1") .replace(/^(\d)/, "_$1")
@ -149,141 +129,214 @@ const convertScopeToModuleName = (scope: string) =>
"_$1" "_$1"
); );
function convertScopedCssForEmotion(
scopedCss: string,
scope: string,
knownScopes: Set<string>,
mapClassNames: (className: string) => string
): string {
let scopedCssForEmotion = "";
stringify(scopedCss, (output, node, flag) => {
if ((flag === "start" || flag === "end") && isNode(node, "rule")) {
if (node.selector === scope) {
if (isNode(node.parent, "root")) {
return;
} else if (flag === "start") {
output = "& {";
}
} else if (flag === "start") {
const selectors = new Set(
node.selectors.map(selector =>
convertSelectorForEmotion(selector, scope, knownScopes, mapClassNames)
)
);
// TODO remove join usage once https://github.com/prettier/prettier/issues/2883 is resolved
output = `${[...selectors].join(", ")} {`;
}
}
scopedCssForEmotion += output;
});
return scopedCssForEmotion.replace(/\\/g, "\\\\").replace(/`/g, "\\`");
}
export function convertCssToJS( export function convertCssToJS(
css: string, css: string,
mapClassNames: (className: string) => string = convertScopeToModuleName mapClassNames: (className: string) => string = convertScopeToModuleName
): string { ): string {
let cssForEmotion = ""; let res = "";
const cssIndexedByScope = getCssIndexedByScope(css); const map = getCssIndexedByScope(css);
if (map.has("root") && map.get("root")!.trim()) {
if (cssIndexedByScope.has("root") && cssIndexedByScope.get("root")!.trim()) { res += 'import { injectGlobal } from "@emotion/css";\n';
cssForEmotion += 'import { injectGlobal } from "@emotion/css";\n';
} }
const knownScopes = new Set(cssIndexedByScope.keys()); const knownScopes = new Set(map.keys());
const collator = new Intl.Collator(undefined, { const collator = new Intl.Collator(undefined, {
numeric: true, numeric: true,
sensitivity: "base", sensitivity: "base",
}); });
function convertScopedCss(scope: string): string {
let scopedCssText = "";
const scopedCss = map.get(scope)!;
stringify(scopedCss, (output, node, flag) => {
if ((flag === "start" || flag === "end") && isNode(node, "rule")) {
if (node.selector === scope) {
if (isNode(node.parent, "root")) {
return;
} else if (flag === "start") {
output = "& {";
}
} else if (flag === "start") {
const selectors = new Set(
node.selectors.map(selector =>
parseSelector(nodes => {
nodes.first.walkClasses(node => {
if (node.toString() === scope) {
node.toString = () => "&";
} else if (knownScopes.has(node.toString())) {
node.toString = () => `.\${${mapClassNames(node.value)}}`;
}
});
}).processSync(selector)
)
);
// TODO remove join usage once https://github.com/prettier/prettier/issues/2883 is resolved
output = `${[...selectors].join(", ")} {`;
}
}
scopedCssText += output;
if (node?.type === "decl" && output.at(-1) !== ";") {
scopedCssText += ";";
}
});
return scopedCssText.replace(/\\/g, "\\\\").replace(/`/g, "\\`");
}
const sortedKnownScopes = [...knownScopes] const sortedKnownScopes = [...knownScopes]
.sort((scopeA, scopeB) => (scopeA === "root" ? -1 : collator.compare(scopeA, scopeB))) .sort((scopeA, scopeB) => (scopeA === "root" ? -1 : collator.compare(scopeA, scopeB)))
.reduce((previousSortedKnownScopes, knownScope) => { .reduce((accum, knownScope) => {
for (const requiredScope of getRequiredScopes( for (const requiredScope of getRequiredScopes(
cssIndexedByScope.get(knownScope)!, map.get(knownScope)!,
knownScope, knownScope,
knownScopes knownScopes
)) { )) {
previousSortedKnownScopes.add(requiredScope); accum.add(requiredScope);
} }
previousSortedKnownScopes.add(knownScope); accum.add(knownScope);
return previousSortedKnownScopes; return accum;
}, new Set<string>()); }, new Set<string>());
for (const scope of sortedKnownScopes) { for (const scope of sortedKnownScopes) {
cssForEmotion += "\n"; const style = convertScopedCss(scope).trimEnd();
if (!style.trim()) continue;
const convertedScopedCssForEmotion = convertScopedCssForEmotion( res +=
cssIndexedByScope.get(scope)!,
scope,
knownScopes,
mapClassNames
).trimEnd();
if (!convertedScopedCssForEmotion.trim()) continue;
cssForEmotion +=
scope === "root" scope === "root"
? `injectGlobal\`${convertedScopedCssForEmotion}\n\`;\n` ? `injectGlobal\`${style}\n\`;\n`
: `\nexport const ${mapClassNames( : `\nexport const ${mapClassNames(
scope scope
)} = ${JSON.stringify(asJSObject(convertedScopedCssForEmotion), null, 2)};\n`; )} = ${JSON5.stringify(asJSObject(style), null, 2)};\n`;
} }
return cssForEmotion.trim(); return res.trim();
} }
// https://github.com/facebook/react/blob/3db98c917701d59f62cf1fbe45cbf01b0b61c704/packages/react-dom-bindings/src/shared/isUnitlessNumber.js#L13
const unitlessNumbers = new Set([
"animationIterationCount",
"aspectRatio",
"borderImageOutset",
"borderImageSlice",
"borderImageWidth",
"boxFlex",
"boxFlexGroup",
"boxOrdinalGroup",
"columnCount",
"columns",
"flex",
"flexGrow",
"flexPositive",
"flexShrink",
"flexNegative",
"flexOrder",
"gridArea",
"gridRow",
"gridRowEnd",
"gridRowSpan",
"gridRowStart",
"gridColumn",
"gridColumnEnd",
"gridColumnSpan",
"gridColumnStart",
"fontWeight",
"lineClamp",
"lineHeight",
"opacity",
"order",
"orphans",
"scale",
"tabSize",
"widows",
"zIndex",
"zoom",
"fillOpacity", // SVG-related properties
"floodOpacity",
"stopOpacity",
"strokeDasharray",
"strokeDashoffset",
"strokeMiterlimit",
"strokeOpacity",
"strokeWidth",
"MozAnimationIterationCount", // Known Prefixed Properties
"MozBoxFlex", // TODO: Remove these since they shouldn't be used in modern code
"MozBoxFlexGroup",
"MozLineClamp",
"msAnimationIterationCount",
"msFlex",
"msZoom",
"msFlexGrow",
"msFlexNegative",
"msFlexOrder",
"msFlexPositive",
"msFlexShrink",
"msGridColumn",
"msGridColumnSpan",
"msGridRow",
"msGridRowSpan",
"WebkitAnimationIterationCount",
"WebkitBoxFlex",
"WebKitBoxFlexGroup",
"WebkitBoxOrdinalGroup",
"WebkitColumnCount",
"WebkitColumns",
"WebkitFlex",
"WebkitFlexGrow",
"WebkitFlexPositive",
"WebkitFlexShrink",
"WebkitLineClamp",
]);
const candidates = new Set(["fontSize"]);
function simplifyValue(propName: string, value: string) { function simplifyValue(propName: string, value: string) {
const num = value.match(/^(\d+(\.\d+)?)px$/)?.[1]; const num = value.match(/^(\d+(\.\d+)?)px$/)?.[1];
if (num != null && candidates.has(propName)) { if (num != null && unitlessNumbers.has(propName)) {
return parseFloat(num); return parseFloat(num);
} }
return value; return value;
} }
function asJSObject(inputCssText: string) { function asJSObject(inputCssText: string) {
const css = parse(`a{${inputCssText}}`); const css = compile(inputCssText);
const result: Record<string, string> = {}; const result: Record<string, string> = {};
if (css.nodes.length !== 1) {
throw new Error("Expected exactly one root node");
}
const node = css.first!; function walk(collect: Record<string, any>, node: Element) {
if (node.type !== "rule") return;
function walk(collect: Record<string, any>, node: ChildNode) {
switch (node.type) { switch (node.type) {
case "atrule": case "decl": {
const obj = (collect[`@${node.name} ${node.params}`] ??= {}); const prop = node.props as string;
node.each(child => { const propName = prop.startsWith("--")
? prop
: prop.replace(/(-.)/g, v => v[1].toUpperCase());
collect[propName] = simplifyValue(propName, node.children as string);
break;
}
case "rule": {
const ruleName = node.value.replaceAll("\f", "");
const obj = ruleName === "&" ? collect : (collect[ruleName] ??= {});
for (const child of node.children as Element[]) {
walk(obj, child); walk(obj, child);
}); }
break;
}
case "comm":
break; break;
case "decl": case "@media":
const propName = node.prop.replace(/(-.)/g, v => v[1].toUpperCase()); const media = (collect[node.value] ??= {});
collect[propName] = simplifyValue(propName, node.value); for (const child of node.children as Element[]) {
break; walk(media, child);
}
case "rule":
node.each(declaration => {
walk(collect, declaration);
});
break;
case "comment":
break; break;
} }
} }
walk(result, node); for (const node of css) {
walk(result, node);
}
return result as React.CSSProperties; return result as React.CSSProperties;
} }

View File

@ -59,6 +59,7 @@ export const esbuildPlugin = ({
const entry = styles.find(s => s.key === cls)!; const entry = styles.find(s => s.key === cls)!;
if (!entry) { if (!entry) {
console.error(e);
throw new Error("Could not find entry for CSS"); throw new Error("Could not find entry for CSS");
} }

View File

@ -17,30 +17,6 @@ export type BuildStyleFile = (
path: string path: string
) => Promise<readonly ["css", string] | readonly ["js", string]>; ) => Promise<readonly ["css", string] | readonly ["js", string]>;
interface RecursiveStringObject {
[modifier: string]: string | RecursiveStringObject;
}
export type CSSAttributeValue = string | (string | RecursiveStringObject)[];
/**
* Tagged template macro function combining Tailwind classes
* @example "tw" => tw`p-2 text-center`
*/
export interface TailwindFunction {
(strings: TemplateStringsArray): string;
(...args: (string | RecursiveStringObject)[]): string;
}
/**
* Tagged template macro function compiling Tailwind styles
* @example "tws" => tws`p-2 text-center` // { padding: 2, textAlign: "center" }
*/
export interface TailwindStyleFunction<Output = React.CSSProperties> {
(strings: TemplateStringsArray): Output;
(...args: (string | RecursiveStringObject)[]): Output;
}
export interface TailwindPluginOptions { export interface TailwindPluginOptions {
/** /**
* Tailwind CSS configuration * Tailwind CSS configuration
@ -74,22 +50,6 @@ export interface TailwindPluginOptions {
*/ */
jsxAttributeAction?: "delete" | "preserve" | ["rename", string]; jsxAttributeAction?: "delete" | "preserve" | ["rename", string];
/**
* Template macro function to combine Tailwind classes
* @example
* declare const tw: TailwindFunction;
* "tw" => tw`p-2 text-center`
*/
macroFunction?: string | undefined;
/**
* Template macro function to compile Tailwind classes
* @example
* declare const tws: TailwindStyleFunction;
* "tws" => tws`p-2 text-center` // { padding: 2, textAlign: "center" }
*/
macroStyleFunction?: string | undefined;
/** /**
* The prefix to use for the generated class names. * The prefix to use for the generated class names.
* @default className => `tw-${hash(className)}` * @default className => `tw-${hash(className)}`
@ -127,8 +87,6 @@ export type ResolveTailwindOptions = SetRequired<
| "postCSSPlugins" | "postCSSPlugins"
| "styleMap" | "styleMap"
| "tailwindConfig" | "tailwindConfig"
| "macroFunction"
| "macroStyleFunction"
>; >;
/** /**
@ -160,8 +118,6 @@ export function getTailwindPlugins(options: TailwindPluginOptions) {
jsxAttributeName: "css", jsxAttributeName: "css",
postCSSPlugins: [], postCSSPlugins: [],
styleMap: new Map(), styleMap: new Map(),
macroFunction: undefined,
macroStyleFunction: undefined,
tailwindConfig: {}, tailwindConfig: {},
...options, ...options,
}; };

43
src/macro.d.ts vendored Normal file
View File

@ -0,0 +1,43 @@
interface RecursiveStringObject {
[modifier: string]: string | RecursiveStringObject;
}
type CSSAttributeValue = string | (string | RecursiveStringObject)[];
/**
* Tagged template macro function combining Tailwind classes
* @example "tw" => tw`p-2 text-center`
*/
export interface TailwindFunction {
(strings: TemplateStringsArray): string;
(...args: (string | RecursiveStringObject)[]): string;
}
/**
* Tagged template macro function compiling Tailwind styles
* @example "tws" => tws`p-2 text-center` // { padding: 2, textAlign: "center" }
*/
export interface TailwindStyleFunction {
(strings: TemplateStringsArray): TailwindStyleFunctionReturn;
(...args: (string | RecursiveStringObject)[]): TailwindStyleFunctionReturn;
}
export const tw: TailwindFunction;
export const tws: TailwindStyleFunction;
type TailwindStyleFunctionReturn = Config extends { tws: infer T } ? T : never;
/**
* Type configuration for the Tailwind style macro
* @example
*
* ```ts
* declare module "_tailwind_lib/macro" {
* interface Config {
* tws: React.CSSProperties;
* }
* }
* ```
*/
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface Config {}

View File

@ -3,6 +3,7 @@ import postcss from "postcss";
import type { ResolveTailwindOptions } from "./index"; import type { ResolveTailwindOptions } from "./index";
export const { name: pkgName } = [require][0]("../package.json"); export const { name: pkgName } = [require][0]("../package.json");
export const macroName = `${pkgName}/macro`;
interface LineColumn { interface LineColumn {
line: number; line: number;

View File

@ -1,6 +1,6 @@
import { dirname, join } from "node:path"; import { dirname, join } from "node:path";
import type * as vite from "vite"; import type * as vite from "vite";
import { type Compile, type StyleMap, pkgName } from "./shared"; import { type Compile, type StyleMap, macroName, pkgName } from "./shared";
import type { BuildStyleFile } from "./index"; import type { BuildStyleFile } from "./index";
const ROLLUP_PREFIX = "\0tailwind:"; const ROLLUP_PREFIX = "\0tailwind:";
@ -15,6 +15,11 @@ export const vitePlugin = ({
buildStyleFile: BuildStyleFile; buildStyleFile: BuildStyleFile;
}): vite.Plugin => ({ }): vite.Plugin => ({
name: "tailwind", name: "tailwind",
configResolved(config) {
(config.optimizeDeps.exclude ?? []).push(macroName, `${pkgName}/base`);
},
resolveId(id, importer) { resolveId(id, importer) {
if (id === `${pkgName}/base`) { if (id === `${pkgName}/base`) {
return { return {

View File

@ -7,7 +7,7 @@
"exactOptionalPropertyTypes": true, "exactOptionalPropertyTypes": true,
"jsx": "react-jsx", "jsx": "react-jsx",
"module": "esnext", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "bundler",
"noImplicitOverride": true, "noImplicitOverride": true,
"noUnusedLocals": true, "noUnusedLocals": true,
"noUnusedParameters": true, "noUnusedParameters": true,