Skip to content

Commit

Permalink
Bundle core plugins with the standalone build (#15028)
Browse files Browse the repository at this point in the history
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
#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";
```
  • Loading branch information
philipp-spiess authored Nov 19, 2024
1 parent b73c746 commit e4bfa8c
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
58 changes: 58 additions & 0 deletions integrations/cli/standalone.test.ts
Original file line number Diff line number Diff line change
@@ -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`,
])
},
)
14 changes: 14 additions & 0 deletions packages/@tailwindcss-node/src/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
}

Expand Down
3 changes: 3 additions & 0 deletions packages/@tailwindcss-standalone/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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:^"
Expand Down
20 changes: 19 additions & 1 deletion packages/@tailwindcss-standalone/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions packages/@tailwindcss-standalone/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 66 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e4bfa8c

Please sign in to comment.