Bundle core plugins with the standalone build (#15028)

Closes #15012

We do not have replacements for these plugins _just yet_. In order to
increase compatibility with setups that rely on some of these legacy
plugins, this PR bundles `@tailwindcss/forms`,
`@tailwindcss/typography`, and `@tailwindcss/aspect-ratio` (after
https://github.com/tailwindlabs/tailwindcss/pull/15029) with the
standalone build now.

In comparison to v3, this omits the `@tailwindcss/container-queries`
plugin since is not a first-party feature of Tailwind CSS v4.

## Test Plan

Added an integration test. I also tested this by running the standalone
binary in a temporary folder with as simple input css:

```css
@import "tailwindcss";
@plugin "@tailwindcss/typography";
```
This commit is contained in:
Philipp Spiess 2024-11-19 16:19:08 +01:00 committed by GitHub
parent b73c746e6e
commit e4bfa8c9b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 162 additions and 1 deletions

View File

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Reintroduce `max-w-screen-*` utilities that read from the `--breakpoint` namespace as deprecated utilities ([#15013](https://github.com/tailwindlabs/tailwindcss/pull/15013))
- Support using CSS variables as arbitrary values without `var(…)` by using parentheses instead of square brackets (e.g. `bg-(--my-color)`) ([#15020](https://github.com/tailwindlabs/tailwindcss/pull/15020))
- Add new `in-*` variant ([#15025](https://github.com/tailwindlabs/tailwindcss/pull/15025))
- Bundle `@tailwindcss/forms`, `@tailwindcss/typography`, and `@tailwindcss/aspect-ratio` with the standalone CLI ([#15028](https://github.com/tailwindlabs/tailwindcss/pull/15028))
- Allow `addUtilities()` and `addComponents()` to work with child combinators and other complex selectors ([#15029](https://github.com/tailwindlabs/tailwindcss/pull/15029))
- Support colors that use `<alpha-value>` in JS configs and plugins ([#15033](https://github.com/tailwindlabs/tailwindcss/pull/15033))
- _Upgrade (experimental)_: Migrate `[&>*]` to the `*` variant ([#15022](https://github.com/tailwindlabs/tailwindcss/pull/15022))

View File

@ -0,0 +1,58 @@
import os from 'node:os'
import path from 'node:path'
import { candidate, css, html, json, test } from '../utils'
const STANDALONE_BINARY = (() => {
switch (os.platform()) {
case 'win32':
return 'tailwindcss-windows-x64.exe'
case 'darwin':
return os.arch() === 'x64' ? 'tailwindcss-macos-x64' : 'tailwindcss-macos-arm64'
case 'linux':
return os.arch() === 'x64' ? 'tailwindcss-linux-x64' : 'tailwindcss-linux-arm64'
default:
throw new Error(`Unsupported platform: ${os.platform()} ${os.arch()}`)
}
})()
test(
'includes first-party plugins',
{
fs: {
'package.json': json`
{
"dependencies": {
"tailwindcss": "workspace:^",
"@tailwindcss/cli": "workspace:^"
}
}
`,
'index.html': html`
<div className="prose">
<h1>Headline</h1>
</div>
<input type="text" class="form-input" />
<div class="aspect-w-16"></div>
`,
'src/index.css': css`
@import 'tailwindcss/theme' theme(reference);
@import 'tailwindcss/utilities';
@plugin '@tailwindcss/forms';
@plugin '@tailwindcss/typography';
@plugin '@tailwindcss/aspect-ratio';
`,
},
},
async ({ fs, exec }) => {
await exec(
`${path.resolve(__dirname, `../../packages/@tailwindcss-standalone/dist/${STANDALONE_BINARY}`)} --input src/index.css --output dist/out.css`,
)
await fs.expectFileToContain('dist/out.css', [
candidate`form-input`,
candidate`prose`,
candidate`aspect-w-16`,
])
},
)

View File

@ -98,6 +98,7 @@ export async function loadModule(id: string, base: string, onDependency: (path:
if (!resolvedPath) {
throw new Error(`Could not resolve '${id}' from '${base}'`)
}
let [module, moduleDependencies] = await Promise.all([
importModule(pathToFileURL(resolvedPath).href + '?id=' + Date.now()),
getModuleDependencies(resolvedPath),
@ -140,6 +141,13 @@ async function loadStylesheet(id: string, base: string, onDependency: (path: str
// can be resolved properly.
let jiti: null | Jiti = null
async function importModule(path: string): Promise<any> {
if (typeof globalThis.__tw_load === 'function') {
let module = await globalThis.__tw_load(path)
if (module) {
return module
}
}
try {
return await import(path)
} catch (error) {
@ -174,6 +182,12 @@ const jsResolver = EnhancedResolve.ResolverFactory.createResolver({
})
function resolveJsId(id: string, base: string): Promise<string | false | undefined> {
if (typeof globalThis.__tw_resolve === 'function') {
let resolved = globalThis.__tw_resolve(id, base)
if (resolved) {
return Promise.resolve(resolved)
}
}
return runResolver(jsResolver, id, base)
}

View File

@ -25,7 +25,10 @@
"dist"
],
"dependencies": {
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/cli": "workspace:^",
"@tailwindcss/forms": "^0.5.9",
"@tailwindcss/typography": "^0.5.15",
"detect-libc": "1.0.3",
"enhanced-resolve": "^5.17.1",
"tailwindcss": "workspace:^"

View File

@ -12,7 +12,10 @@ const localResolve = createRequire(import.meta.url).resolve
globalThis.__tw_resolve = (id, baseDir) => {
let isEmbeddedFileBase = baseDir === '/$bunfs/root' || baseDir?.includes(':/~BUN/root')
const likelyEmbeddedFile =
id === 'tailwindcss' || id.startsWith('tailwindcss/') || isEmbeddedFileBase
id === 'tailwindcss' ||
id.startsWith('tailwindcss/') ||
id.startsWith('@tailwindcss/') ||
isEmbeddedFileBase
if (!likelyEmbeddedFile) {
return false
@ -38,10 +41,25 @@ globalThis.__tw_resolve = (id, baseDir) => {
case 'utilities':
case 'utilities.css':
return localResolve(utilitiesCss)
case '@tailwindcss/forms':
case '@tailwindcss/typography':
case '@tailwindcss/aspect-ratio':
return id
default:
return false
}
}
globalThis.__tw_load = async (id) => {
if (id.endsWith('@tailwindcss/forms')) {
return require('@tailwindcss/forms')
} else if (id.endsWith('@tailwindcss/typography')) {
return require('@tailwindcss/typography')
} else if (id.endsWith('@tailwindcss/aspect-ratio')) {
return require('@tailwindcss/aspect-ratio')
} else {
return undefined
}
}
globalThis.__tw_version = packageJson.version
globalThis.__tw_readFile = async (path, encoding) => {
// When reading a file from the `$bunfs`, we need to use the synchronous

View File

@ -8,3 +8,4 @@ declare var __tw_resolve: undefined | ((id: string, base?: string) => string | f
declare var __tw_readFile:
| undefined
| ((path: string, encoding: BufferEncoding) => Promise<string | undefined>)
declare var __tw_load: undefined | ((path: string) => Promise<object | undefined>)

66
pnpm-lock.yaml generated
View File

@ -213,9 +213,18 @@ importers:
packages/@tailwindcss-standalone:
dependencies:
'@tailwindcss/aspect-ratio':
specifier: ^0.4.2
version: 0.4.2(tailwindcss@packages+tailwindcss)
'@tailwindcss/cli':
specifier: workspace:^
version: link:../@tailwindcss-cli
'@tailwindcss/forms':
specifier: ^0.5.9
version: 0.5.9(tailwindcss@packages+tailwindcss)
'@tailwindcss/typography':
specifier: ^0.5.15
version: 0.5.15(tailwindcss@packages+tailwindcss)
detect-libc:
specifier: 1.0.3
version: 1.0.3
@ -1408,6 +1417,21 @@ packages:
'@swc/helpers@0.5.2':
resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==}
'@tailwindcss/aspect-ratio@0.4.2':
resolution: {integrity: sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==}
peerDependencies:
tailwindcss: '>=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1'
'@tailwindcss/forms@0.5.9':
resolution: {integrity: sha512-tM4XVr2+UVTxXJzey9Twx48c1gcxFStqn1pQz0tRsX8o3DvxhN5oY5pvyAbUx7VTaZxpej4Zzvc6h+1RJBzpIg==}
peerDependencies:
tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20'
'@tailwindcss/typography@0.5.15':
resolution: {integrity: sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==}
peerDependencies:
tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20'
'@types/babel__core@7.20.5':
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
@ -2721,6 +2745,12 @@ packages:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
lodash.castarray@4.4.0:
resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==}
lodash.isplainobject@4.0.6:
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
@ -2771,6 +2801,10 @@ packages:
resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
engines: {node: '>=12'}
mini-svg-data-uri@1.4.4:
resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==}
hasBin: true
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@ -3050,6 +3084,10 @@ packages:
peerDependencies:
postcss: ^8.2.14
postcss-selector-parser@6.0.10:
resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
engines: {node: '>=4'}
postcss-selector-parser@6.1.2:
resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
engines: {node: '>=4'}
@ -4361,6 +4399,23 @@ snapshots:
dependencies:
tslib: 2.8.0
'@tailwindcss/aspect-ratio@0.4.2(tailwindcss@packages+tailwindcss)':
dependencies:
tailwindcss: link:packages/tailwindcss
'@tailwindcss/forms@0.5.9(tailwindcss@packages+tailwindcss)':
dependencies:
mini-svg-data-uri: 1.4.4
tailwindcss: link:packages/tailwindcss
'@tailwindcss/typography@0.5.15(tailwindcss@packages+tailwindcss)':
dependencies:
lodash.castarray: 4.4.0
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
postcss-selector-parser: 6.0.10
tailwindcss: link:packages/tailwindcss
'@types/babel__core@7.20.5':
dependencies:
'@babel/parser': 7.25.3
@ -6047,6 +6102,10 @@ snapshots:
dependencies:
p-locate: 5.0.0
lodash.castarray@4.4.0: {}
lodash.isplainobject@4.0.6: {}
lodash.merge@4.6.2: {}
lodash.sortby@4.7.0: {}
@ -6090,6 +6149,8 @@ snapshots:
mimic-fn@4.0.0: {}
mini-svg-data-uri@1.4.4: {}
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.11
@ -6341,6 +6402,11 @@ snapshots:
postcss: 8.4.47
postcss-selector-parser: 6.1.2
postcss-selector-parser@6.0.10:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
postcss-selector-parser@6.1.2:
dependencies:
cssesc: 3.0.0