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

298
pnpm-lock.yaml generated
View File

@ -14,12 +14,24 @@ importers:
'@emotion/hash':
specifier: ^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:
specifier: ^4.17.21
version: 4.17.21
postcss:
specifier: ^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:
specifier: ^1.3.3
version: 1.3.3
@ -51,6 +63,9 @@ importers:
'@types/react':
specifier: ^18.3.3
version: 18.3.3
'@types/stylis':
specifier: ^4.2.6
version: 4.2.6
cli-highlight:
specifier: ^2.1.11
version: 2.1.11
@ -66,24 +81,15 @@ importers:
dedent:
specifier: ^1.5.3
version: 1.5.3
esbuild:
specifier: ^0.21.5
version: 0.21.5
esbuild-register:
specifier: ^3.5.0
version: 3.5.0(esbuild@0.21.5)
version: 3.5.0(esbuild@0.23.0)
eslint:
specifier: ^8.57.0
version: 8.57.0
postcss-nested:
specifier: ^6.0.1
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:
specifier: ^3.3.2
version: 3.3.2
@ -249,138 +255,282 @@ packages:
cpu: [ppc64]
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':
resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
engines: {node: '>=12'}
cpu: [arm64]
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':
resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
engines: {node: '>=12'}
cpu: [arm]
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':
resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
engines: {node: '>=12'}
cpu: [x64]
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':
resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
engines: {node: '>=12'}
cpu: [arm64]
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':
resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
engines: {node: '>=12'}
cpu: [x64]
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':
resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
engines: {node: '>=12'}
cpu: [arm64]
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':
resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
engines: {node: '>=12'}
cpu: [x64]
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':
resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
engines: {node: '>=12'}
cpu: [arm64]
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':
resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
engines: {node: '>=12'}
cpu: [arm]
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':
resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
engines: {node: '>=12'}
cpu: [ia32]
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':
resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
engines: {node: '>=12'}
cpu: [loong64]
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':
resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
engines: {node: '>=12'}
cpu: [mips64el]
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':
resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
engines: {node: '>=12'}
cpu: [ppc64]
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':
resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
engines: {node: '>=12'}
cpu: [riscv64]
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':
resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
engines: {node: '>=12'}
cpu: [s390x]
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':
resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
engines: {node: '>=12'}
cpu: [x64]
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':
resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
engines: {node: '>=12'}
cpu: [x64]
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':
resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
engines: {node: '>=12'}
cpu: [x64]
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':
resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
engines: {node: '>=12'}
cpu: [x64]
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':
resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
engines: {node: '>=12'}
cpu: [arm64]
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':
resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
engines: {node: '>=12'}
cpu: [ia32]
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':
resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
engines: {node: '>=12'}
cpu: [x64]
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':
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@ -586,6 +736,9 @@ packages:
'@types/react@18.3.3':
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':
resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==}
@ -988,6 +1141,11 @@ packages:
engines: {node: '>=12'}
hasBin: true
esbuild@0.23.0:
resolution: {integrity: sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==}
engines: {node: '>=18'}
hasBin: true
escalade@3.1.2:
resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
engines: {node: '>=6'}
@ -1685,12 +1843,6 @@ packages:
peerDependencies:
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:
resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==}
engines: {node: '>=4'}
@ -1893,6 +2045,9 @@ packages:
strip-literal@2.1.0:
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:
resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
engines: {node: '>=16 || 14 >=14.17'}
@ -2383,72 +2538,144 @@ snapshots:
'@esbuild/aix-ppc64@0.21.5':
optional: true
'@esbuild/aix-ppc64@0.23.0':
optional: true
'@esbuild/android-arm64@0.21.5':
optional: true
'@esbuild/android-arm64@0.23.0':
optional: true
'@esbuild/android-arm@0.21.5':
optional: true
'@esbuild/android-arm@0.23.0':
optional: true
'@esbuild/android-x64@0.21.5':
optional: true
'@esbuild/android-x64@0.23.0':
optional: true
'@esbuild/darwin-arm64@0.21.5':
optional: true
'@esbuild/darwin-arm64@0.23.0':
optional: true
'@esbuild/darwin-x64@0.21.5':
optional: true
'@esbuild/darwin-x64@0.23.0':
optional: true
'@esbuild/freebsd-arm64@0.21.5':
optional: true
'@esbuild/freebsd-arm64@0.23.0':
optional: true
'@esbuild/freebsd-x64@0.21.5':
optional: true
'@esbuild/freebsd-x64@0.23.0':
optional: true
'@esbuild/linux-arm64@0.21.5':
optional: true
'@esbuild/linux-arm64@0.23.0':
optional: true
'@esbuild/linux-arm@0.21.5':
optional: true
'@esbuild/linux-arm@0.23.0':
optional: true
'@esbuild/linux-ia32@0.21.5':
optional: true
'@esbuild/linux-ia32@0.23.0':
optional: true
'@esbuild/linux-loong64@0.21.5':
optional: true
'@esbuild/linux-loong64@0.23.0':
optional: true
'@esbuild/linux-mips64el@0.21.5':
optional: true
'@esbuild/linux-mips64el@0.23.0':
optional: true
'@esbuild/linux-ppc64@0.21.5':
optional: true
'@esbuild/linux-ppc64@0.23.0':
optional: true
'@esbuild/linux-riscv64@0.21.5':
optional: true
'@esbuild/linux-riscv64@0.23.0':
optional: true
'@esbuild/linux-s390x@0.21.5':
optional: true
'@esbuild/linux-s390x@0.23.0':
optional: true
'@esbuild/linux-x64@0.21.5':
optional: true
'@esbuild/linux-x64@0.23.0':
optional: true
'@esbuild/netbsd-x64@0.21.5':
optional: true
'@esbuild/netbsd-x64@0.23.0':
optional: true
'@esbuild/openbsd-arm64@0.23.0':
optional: true
'@esbuild/openbsd-x64@0.21.5':
optional: true
'@esbuild/openbsd-x64@0.23.0':
optional: true
'@esbuild/sunos-x64@0.21.5':
optional: true
'@esbuild/sunos-x64@0.23.0':
optional: true
'@esbuild/win32-arm64@0.21.5':
optional: true
'@esbuild/win32-arm64@0.23.0':
optional: true
'@esbuild/win32-ia32@0.21.5':
optional: true
'@esbuild/win32-ia32@0.23.0':
optional: true
'@esbuild/win32-x64@0.21.5':
optional: true
'@esbuild/win32-x64@0.23.0':
optional: true
'@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)':
dependencies:
eslint: 8.57.0
@ -2651,6 +2878,8 @@ snapshots:
'@types/prop-types': 15.7.12
csstype: 3.1.3
'@types/stylis@4.2.6': {}
'@types/ws@8.5.10':
dependencies:
'@types/node': 20.14.9
@ -3034,10 +3263,10 @@ snapshots:
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:
debug: 4.3.4
esbuild: 0.21.5
esbuild: 0.23.0
transitivePeerDependencies:
- supports-color
@ -3067,6 +3296,33 @@ snapshots:
'@esbuild/win32-ia32': 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: {}
escape-string-regexp@1.0.5: {}
@ -3750,10 +4006,6 @@ snapshots:
postcss: 8.4.39
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:
dependencies:
cssesc: 3.0.0
@ -3948,6 +4200,8 @@ snapshots:
dependencies:
js-tokens: 9.0.0
stylis@4.3.2: {}
sucrase@3.35.0:
dependencies:
'@jridgewell/gen-mapping': 0.3.5

View File

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

View File

@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest";
import { getBuild } from "./utils";
import { getClassName } from "../index";
describe.only("babel-tailwind", () => {
describe("babel-tailwind", () => {
const compileESBuild = getBuild("styleObject");
it("supports conversion into CSSProperties", async () => {
@ -10,9 +10,11 @@ describe.only("babel-tailwind", () => {
clsx: "emotion",
expectFiles: 1,
javascript: `
import { tws } from "@aet/tailwind/macro";
export function Hello() {
return (
<div style={tws\`p-2 text-center\`}>
<div style={tws\`p-2 text-center hover:font-semibold sm:p-1\`}>
Hello, world!
</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(
`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}`);
});

View File

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

View File

@ -4,10 +4,11 @@ import hash from "@emotion/hash";
import { isPlainObject } from "lodash";
import invariant from "tiny-invariant";
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";
export type ClassNameCollector = (path: string, entries: StyleMapEntry[]) => void;
type BabelTypes = typeof babel.types;
type Type = "css" | "js";
export function babelTailwind(
@ -15,8 +16,6 @@ export function babelTailwind(
styleMap,
clsx,
getClassName: getClass = getClassName,
macroFunction,
macroStyleFunction,
jsxAttributeAction = "delete",
jsxAttributeName = "css",
vite,
@ -25,11 +24,7 @@ export function babelTailwind(
) {
type BabelPluginState = ReturnType<typeof getState>;
function getState(
path: NodePath<t.Program>,
state: babel.PluginPass,
t: typeof babel.types
) {
function getState(path: NodePath<t.Program>, state: babel.PluginPass, t: BabelTypes) {
let cx: 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 }) => ({
Program: {
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 }, _) {
_.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, _) {
const { name } = path.node;
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) {
case "emotion":
return t.importDeclaration(
@ -346,6 +334,56 @@ function evaluateArgs(path: NodePath) {
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 =
<T>(fn: (runtime: typeof babel) => babel.Visitor<babel.PluginPass & T>) =>
(runtime: typeof babel) => {
@ -367,6 +405,11 @@ function matchPath(
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[]) {
if (!add) return "";

View File

@ -3,14 +3,15 @@
import {
type AtRule,
type Builder,
type ChildNode,
type Node,
type Root,
type Rule,
parse,
} from "postcss";
import JSON5 from "json5";
import parseSelector from "postcss-selector-parser";
import Stringifier from "postcss/lib/stringifier";
import { type Element, compile } from "stylis";
import { camelCase } from "lodash";
function getSelectorScope(selector: string): string {
@ -99,10 +100,6 @@ function getCssIndexedByScope(css: string) {
}
for (const scope of scopesStack.at(-1)!) {
if (!cssIndexedByScope.has(scope)) {
cssIndexedByScope.set(scope, "");
}
if (
flag === "start" &&
isNode(node, "rule") &&
@ -113,7 +110,7 @@ function getCssIndexedByScope(css: string) {
.join(", ")} {`;
}
cssIndexedByScope.set(scope, cssIndexedByScope.get(scope) + output);
cssIndexedByScope.set(scope, (cssIndexedByScope.get(scope) || "") + output);
}
if (flag === "end") {
@ -124,23 +121,6 @@ function getCssIndexedByScope(css: string) {
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) =>
camelCase(scope)
.replace(/^(\d)/, "_$1")
@ -149,141 +129,214 @@ const convertScopeToModuleName = (scope: string) =>
"_$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(
css: string,
mapClassNames: (className: string) => string = convertScopeToModuleName
): string {
let cssForEmotion = "";
let res = "";
const cssIndexedByScope = getCssIndexedByScope(css);
if (cssIndexedByScope.has("root") && cssIndexedByScope.get("root")!.trim()) {
cssForEmotion += 'import { injectGlobal } from "@emotion/css";\n';
const map = getCssIndexedByScope(css);
if (map.has("root") && map.get("root")!.trim()) {
res += 'import { injectGlobal } from "@emotion/css";\n';
}
const knownScopes = new Set(cssIndexedByScope.keys());
const knownScopes = new Set(map.keys());
const collator = new Intl.Collator(undefined, {
numeric: true,
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]
.sort((scopeA, scopeB) => (scopeA === "root" ? -1 : collator.compare(scopeA, scopeB)))
.reduce((previousSortedKnownScopes, knownScope) => {
.reduce((accum, knownScope) => {
for (const requiredScope of getRequiredScopes(
cssIndexedByScope.get(knownScope)!,
map.get(knownScope)!,
knownScope,
knownScopes
)) {
previousSortedKnownScopes.add(requiredScope);
accum.add(requiredScope);
}
previousSortedKnownScopes.add(knownScope);
return previousSortedKnownScopes;
accum.add(knownScope);
return accum;
}, new Set<string>());
for (const scope of sortedKnownScopes) {
cssForEmotion += "\n";
const style = convertScopedCss(scope).trimEnd();
if (!style.trim()) continue;
const convertedScopedCssForEmotion = convertScopedCssForEmotion(
cssIndexedByScope.get(scope)!,
scope,
knownScopes,
mapClassNames
).trimEnd();
if (!convertedScopedCssForEmotion.trim()) continue;
cssForEmotion +=
res +=
scope === "root"
? `injectGlobal\`${convertedScopedCssForEmotion}\n\`;\n`
? `injectGlobal\`${style}\n\`;\n`
: `\nexport const ${mapClassNames(
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) {
const num = value.match(/^(\d+(\.\d+)?)px$/)?.[1];
if (num != null && candidates.has(propName)) {
if (num != null && unitlessNumbers.has(propName)) {
return parseFloat(num);
}
return value;
}
function asJSObject(inputCssText: string) {
const css = parse(`a{${inputCssText}}`);
const css = compile(inputCssText);
const result: Record<string, string> = {};
if (css.nodes.length !== 1) {
throw new Error("Expected exactly one root node");
}
const node = css.first!;
if (node.type !== "rule") return;
function walk(collect: Record<string, any>, node: ChildNode) {
function walk(collect: Record<string, any>, node: Element) {
switch (node.type) {
case "atrule":
const obj = (collect[`@${node.name} ${node.params}`] ??= {});
node.each(child => {
case "decl": {
const prop = node.props as string;
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);
});
}
break;
}
case "comm":
break;
case "decl":
const propName = node.prop.replace(/(-.)/g, v => v[1].toUpperCase());
collect[propName] = simplifyValue(propName, node.value);
break;
case "rule":
node.each(declaration => {
walk(collect, declaration);
});
break;
case "comment":
case "@media":
const media = (collect[node.value] ??= {});
for (const child of node.children as Element[]) {
walk(media, child);
}
break;
}
}
walk(result, node);
for (const node of css) {
walk(result, node);
}
return result as React.CSSProperties;
}

View File

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

View File

@ -17,30 +17,6 @@ export type BuildStyleFile = (
path: 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 {
/**
* Tailwind CSS configuration
@ -74,22 +50,6 @@ export interface TailwindPluginOptions {
*/
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.
* @default className => `tw-${hash(className)}`
@ -127,8 +87,6 @@ export type ResolveTailwindOptions = SetRequired<
| "postCSSPlugins"
| "styleMap"
| "tailwindConfig"
| "macroFunction"
| "macroStyleFunction"
>;
/**
@ -160,8 +118,6 @@ export function getTailwindPlugins(options: TailwindPluginOptions) {
jsxAttributeName: "css",
postCSSPlugins: [],
styleMap: new Map(),
macroFunction: undefined,
macroStyleFunction: undefined,
tailwindConfig: {},
...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";
export const { name: pkgName } = [require][0]("../package.json");
export const macroName = `${pkgName}/macro`;
interface LineColumn {
line: number;

View File

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

View File

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