Skip to content

Improve compatibility with Safari 15 #17435

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
56883e7
WIP
philipp-spiess Mar 26, 2025
747dacf
Do what needs to be done
philipp-spiess Mar 27, 2025
40ba52b
Improve Next.js playground
philipp-spiess Mar 28, 2025
5183f44
De-duplicate `lightningcss` configuration
philipp-spiess Mar 28, 2025
6937fef
Simplify `color-mix(…)` inlining and adding unit tests
philipp-spiess Mar 28, 2025
e7f48b6
Revert changes to tsconfig
philipp-spiess Mar 28, 2025
19e4beb
Update snapshots
philipp-spiess Mar 28, 2025
f3e2993
Make the `@property` stuff disable-able
philipp-spiess Mar 28, 2025
1460365
PostCSS should not polyfill `@property` for CSS module files
philipp-spiess Mar 28, 2025
f6f78b1
Update more snapshots
philipp-spiess Mar 28, 2025
4c01e6f
Update snapshots
philipp-spiess Mar 31, 2025
74c5cef
Emit `@property` fallbacks at the beginning of the file
philipp-spiess Mar 31, 2025
eb801de
Add test case to stuff
philipp-spiess Mar 31, 2025
77eb998
Update snapshots
philipp-spiess Mar 31, 2025
e4ecce7
Refactor `replaceShadowColors(…)` to print AST
philipp-spiess Mar 31, 2025
9bddc09
Add fallbacks for new relative color usage
philipp-spiess Mar 31, 2025
8f09cac
More snapshot updates and comments
philipp-spiess Mar 31, 2025
5be1398
Don't use regex for replacement
philipp-spiess Mar 31, 2025
78e10dc
Further reduce the precision of color values because lightningcss pre…
philipp-spiess Mar 31, 2025
cbcf42a
Fix regex
philipp-spiess Mar 31, 2025
0ad7aad
Fix Svelte tests
philipp-spiess Mar 31, 2025
0bbcd09
Still needs a layer and fix supports query
philipp-spiess Mar 31, 2025
7d6fabc
Even more snapshot updates
philipp-spiess Mar 31, 2025
66c2c48
So. Many. Snapshots
philipp-spiess Mar 31, 2025
ddace46
Apply cleanups and also flag `color-mix(…)` polyfills so they aren't …
philipp-spiess Apr 1, 2025
8e54832
Revert changes to `replaceShadowColors(…)` and move polyfill closer t…
philipp-spiess Apr 1, 2025
79144ce
Update color values in `colors.ts`
philipp-spiess Apr 1, 2025
9244037
Update snapshots
philipp-spiess Apr 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions integrations/cli/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,13 @@ test(
expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
"
--- ./dist/out.css ---
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
@layer base {
*, ::before, ::after, ::backdrop {
--tw-content: "";
}
}
}
.content-\\[\\"components\\/my-component\\.tsx\\"\\] {
--tw-content: "components/my-component.tsx";
content: var(--tw-content);
Expand Down Expand Up @@ -944,6 +951,13 @@ test(
expect(await fs.dumpFiles('./project-a/dist/*.css')).toMatchInlineSnapshot(`
"
--- ./project-a/dist/out.css ---
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
@layer base {
*, ::before, ::after, ::backdrop {
--tw-content: "";
}
}
}
.content-\\[\\'project-a\\/node_modules\\/my-lib-1\\/src\\/index\\.html\\'\\] {
--tw-content: 'project-a/node modules/my-lib-1/src/index.html';
content: var(--tw-content);
Expand Down Expand Up @@ -1181,6 +1195,13 @@ test(
expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
"
--- ./dist/out.css ---
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
@layer base {
*, ::before, ::after, ::backdrop {
--tw-content: "";
}
}
}
.content-\\[\\"pages\\/foo\\.html\\"\\] {
--tw-content: "pages/foo.html";
content: var(--tw-content);
Expand Down Expand Up @@ -1508,7 +1529,7 @@ test(
"
--- ./dist/out.css ---
:root, :host {
--color-blue-500: oklch(0.623 0.214 259.815);
--color-blue-500: oklch(62.3% 0.214 259.815);
}
.flex {
display: flex;
Expand All @@ -1531,8 +1552,8 @@ test(
"
--- ./dist/out.css ---
:root, :host {
--color-red-500: oklch(0.637 0.237 25.331);
--color-blue-500: oklch(0.623 0.214 259.815);
--color-red-500: oklch(63.7% 0.237 25.331);
--color-blue-500: oklch(62.3% 0.214 259.815);
}
.flex {
display: flex;
Expand Down
8 changes: 5 additions & 3 deletions integrations/postcss/next.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ test(
'app/page.module.css': css`
@reference './globals.css';
.heading {
@apply text-red-500 animate-ping;
@apply text-red-500 animate-ping skew-7;
}
`,
'app/globals.css': css`
Expand Down Expand Up @@ -77,9 +77,10 @@ test(
])

await fs.expectFileToContain(moduleCss!, [
'color:var(--color-red-500,oklch(.637 .237 25.331)',
'color:var(--color-red-500,oklch(63.7% .237 25.331)',
'animation:var(--animate-ping,ping 1s cubic-bezier(0,0,.2,1) infinite)',
/@keyframes page_ping.*{75%,to{transform:scale\(2\);opacity:0}/,
'--tw-skew-x:skewX(7deg);',
])
},
)
Expand Down Expand Up @@ -130,7 +131,7 @@ describe.each(['turbo', 'webpack'])('%s', (bundler) => {
'app/page.module.css': css`
@reference './globals.css';
.heading {
@apply text-red-500 animate-ping content-['module'];
@apply text-red-500 animate-ping skew-7 content-['module'];
}
`,
'app/globals.css': css`
Expand Down Expand Up @@ -173,6 +174,7 @@ describe.each(['turbo', 'webpack'])('%s', (bundler) => {
let css = await fetchStyles(url)
expect(css).toContain(candidate`underline`)
expect(css).toContain(candidate`bg-red-500`)
expect(css).toContain('--tw-skew-x: skewX(7deg);')
expect(css).toContain('content: var(--tw-content)')
expect(css).toContain('@keyframes')
})
Expand Down
28 changes: 28 additions & 0 deletions integrations/postcss/source.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ test(
expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
"
--- ./dist/out.css ---
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
@layer base {
*, ::before, ::after, ::backdrop {
--tw-content: "";
}
}
}
.content-\\[\\"components\\/my-component\\.tsx\\"\\] {
--tw-content: "components/my-component.tsx";
content: var(--tw-content);
Expand Down Expand Up @@ -324,6 +331,13 @@ test(
expect(await fs.dumpFiles('./project-a/dist/*.css')).toMatchInlineSnapshot(`
"
--- ./project-a/dist/out.css ---
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
@layer base {
*, ::before, ::after, ::backdrop {
--tw-content: "";
}
}
}
.content-\\[\\'project-a\\/node_modules\\/my-lib-1\\/src\\/index\\.html\\'\\] {
--tw-content: 'project-a/node modules/my-lib-1/src/index.html';
content: var(--tw-content);
Expand Down Expand Up @@ -579,6 +593,13 @@ test(
expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
"
--- ./dist/out.css ---
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
@layer base {
*, ::before, ::after, ::backdrop {
--tw-content: "";
}
}
}
.content-\\[\\"pages\\/foo\\.html\\"\\] {
--tw-content: "pages/foo.html";
content: var(--tw-content);
Expand Down Expand Up @@ -683,6 +704,13 @@ test(
expect(await fs.dumpFiles('./project-a/dist/*.css')).toMatchInlineSnapshot(`
"
--- ./project-a/dist/out.css ---
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
@layer base {
*, ::before, ::after, ::backdrop {
--tw-content: "";
}
}
}
.content-\\[\\'keep-me\\.html\\'\\] {
--tw-content: 'keep-me.html';
content: var(--tw-content);
Expand Down
24 changes: 12 additions & 12 deletions integrations/upgrade/js-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,17 +472,17 @@ test(
@import 'tailwindcss';

@theme {
--color-gray-50: oklch(0.985 0 0);
--color-gray-100: oklch(0.97 0 0);
--color-gray-200: oklch(0.922 0 0);
--color-gray-300: oklch(0.87 0 0);
--color-gray-400: oklch(0.708 0 0);
--color-gray-500: oklch(0.556 0 0);
--color-gray-600: oklch(0.439 0 0);
--color-gray-700: oklch(0.371 0 0);
--color-gray-800: oklch(0.269 0 0);
--color-gray-900: oklch(0.205 0 0);
--color-gray-950: oklch(0.145 0 0);
--color-gray-50: oklch(98.5% 0 0);
--color-gray-100: oklch(97% 0 0);
--color-gray-200: oklch(92.2% 0 0);
--color-gray-300: oklch(87% 0 0);
--color-gray-400: oklch(70.8% 0 0);
--color-gray-500: oklch(55.6% 0 0);
--color-gray-600: oklch(43.9% 0 0);
--color-gray-700: oklch(37.1% 0 0);
--color-gray-800: oklch(26.9% 0 0);
--color-gray-900: oklch(20.5% 0 0);
--color-gray-950: oklch(14.5% 0 0);
}

/*
Expand Down Expand Up @@ -1061,7 +1061,7 @@ describe('border compatibility', () => {
::before,
::backdrop,
::file-selector-button {
border-color: oklch(0.623 0.214 259.815);
border-color: oklch(62.3% 0.214 259.815);
}
}
"
Expand Down
14 changes: 7 additions & 7 deletions integrations/vite/svelte.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ test(

await fs.expectFileToContain(files[0][0], [
candidate`underline`,
'.global{color:var(--color-green-500,oklch(.723 .219 149.579));animation:2s ease-in-out infinite globalKeyframes}',
/\.local.svelte-.*\{color:var\(--color-red-500\,oklch\(\.637 \.237 25\.331\)\);animation:2s ease-in-out infinite svelte-.*-localKeyframes\}/,
'.global{color:var(--color-green-500,oklch(72.3% .219 149.579));animation:2s ease-in-out infinite globalKeyframes}',
/\.local.svelte-.*\{color:var\(--color-red-500\,oklch\(63\.7% \.237 25\.331\)\);animation:2s ease-in-out infinite svelte-.*-localKeyframes\}/,
/@keyframes globalKeyframes\{/,
/@keyframes svelte-.*-localKeyframes\{/,
])
Expand Down Expand Up @@ -213,10 +213,10 @@ test(
let [, css] = files[0]
expect(css).toContain(candidate`underline`)
expect(css).toContain(
'.global{color:var(--color-green-500,oklch(.723 .219 149.579));animation:2s ease-in-out infinite globalKeyframes}',
'.global{color:var(--color-green-500,oklch(72.3% .219 149.579));animation:2s ease-in-out infinite globalKeyframes}',
)
expect(css).toMatch(
/\.local.svelte-.*\{color:var\(--color-red-500,oklch\(\.637 \.237 25\.331\)\);animation:2s ease-in-out infinite svelte-.*-localKeyframes\}/,
/\.local.svelte-.*\{color:var\(--color-red-500,oklch\(63\.7% \.237 25\.331\)\);animation:2s ease-in-out infinite svelte-.*-localKeyframes\}/,
)
expect(css).toMatch(/@keyframes globalKeyframes\{/)
expect(css).toMatch(/@keyframes svelte-.*-localKeyframes\{/)
Expand All @@ -238,15 +238,15 @@ test(
let [, css] = files[0]
expect(css).toContain(candidate`font-bold`)
expect(css).toContain(
'.global{color:var(--color-green-500,oklch(.723 .219 149.579));animation:2s ease-in-out infinite globalKeyframes}',
'.global{color:var(--color-green-500,oklch(72.3% .219 149.579));animation:2s ease-in-out infinite globalKeyframes}',
)
expect(css).toMatch(
/\.local.svelte-.*\{color:var\(--color-red-500,oklch\(\.637 \.237 25\.331\)\);animation:2s ease-in-out infinite svelte-.*-localKeyframes\}/,
/\.local.svelte-.*\{color:var\(--color-red-500,oklch\(63\.7% \.237 25\.331\)\);animation:2s ease-in-out infinite svelte-.*-localKeyframes\}/,
)
expect(css).toMatch(/@keyframes globalKeyframes\{/)
expect(css).toMatch(/@keyframes svelte-.*-localKeyframes\{/)
expect(css).toMatch(
/\.bar.svelte-.*\{color:var\(--color-pink-500,oklch\(\.656 \.241 354\.308\)\)\}/,
/\.bar.svelte-.*\{color:var\(--color-pink-500,oklch\(65\.6% \.241 354\.308\)\)\}/,
)
})
},
Expand Down
6 changes: 3 additions & 3 deletions integrations/webpack/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ test(
"
--- ./dist/main.css ---
:root, :host {
--color-blue-500: oklch(0.623 0.214 259.815);
--color-blue-500: oklch(62.3% 0.214 259.815);
}
.flex {
display: flex;
Expand All @@ -98,8 +98,8 @@ test(
"
--- ./dist/main.css ---
:root, :host {
--color-red-500: oklch(0.637 0.237 25.331);
--color-blue-500: oklch(0.623 0.214 259.815);
--color-red-500: oklch(63.7% 0.237 25.331);
--color-blue-500: oklch(62.3% 0.214 259.815);
}
.flex {
display: flex;
Expand Down
1 change: 0 additions & 1 deletion packages/@tailwindcss-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
"@tailwindcss/node": "workspace:*",
"@tailwindcss/oxide": "workspace:*",
"enhanced-resolve": "^5.18.1",
"lightningcss": "catalog:",
"mri": "^1.2.0",
"picocolors": "^1.1.1",
"tailwindcss": "workspace:*"
Expand Down
37 changes: 2 additions & 35 deletions packages/@tailwindcss-cli/src/commands/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import watcher from '@parcel/watcher'
import { compile, env, Instrumentation } from '@tailwindcss/node'
import { clearRequireCache } from '@tailwindcss/node/require-cache'
import { Scanner, type ChangedContent } from '@tailwindcss/oxide'
import { Features, transform } from 'lightningcss'
import { existsSync, type Stats } from 'node:fs'
import fs from 'node:fs/promises'
import path from 'node:path'
import { optimize } from '../../../../@tailwindcss-node/src'
import type { Arg, Result } from '../../utils/args'
import { Disposables } from '../../utils/disposables'
import {
Expand Down Expand Up @@ -128,7 +128,7 @@ export async function handle(args: Result<ReturnType<typeof options>>) {
if (args['--minify'] || args['--optimize']) {
if (css !== previous.css) {
DEBUG && I.start('Optimize CSS')
let optimizedCss = optimizeCss(css, {
let optimizedCss = optimize(css, {
file: args['--input'] ?? 'input.css',
minify: args['--minify'] ?? false,
})
Expand Down Expand Up @@ -430,39 +430,6 @@ async function createWatchers(dirs: string[], cb: (files: string[]) => void) {
}
}

function optimizeCss(
input: string,
{ file = 'input.css', minify = false }: { file?: string; minify?: boolean } = {},
) {
function optimize(code: Buffer | Uint8Array) {
return transform({
filename: file,
code,
minify,
sourceMap: false,
drafts: {
customMedia: true,
},
nonStandard: {
deepSelectorCombinator: true,
},
include: Features.Nesting,
exclude: Features.LogicalProperties | Features.DirSelector | Features.LightDark,
targets: {
safari: (16 << 16) | (4 << 8),
ios_saf: (16 << 16) | (4 << 8),
firefox: 128 << 16,
chrome: 111 << 16,
},
errorRecovery: true,
}).code
}

// Running Lightning CSS twice to ensure that adjacent rules are merged after
// nesting is applied. This creates a more optimized output.
return optimize(optimize(Buffer.from(input))).toString()
}

function watchDirectories(scanner: Scanner) {
return [...new Set(scanner.normalizedSources.flatMap((globEntry) => globEntry.base))]
}
3 changes: 2 additions & 1 deletion packages/@tailwindcss-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"dependencies": {
"enhanced-resolve": "^5.18.1",
"jiti": "^2.4.2",
"tailwindcss": "workspace:*"
"tailwindcss": "workspace:*",
"lightningcss": "catalog:"
}
}
6 changes: 5 additions & 1 deletion packages/@tailwindcss-node/src/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,29 @@ import {
compile as _compile,
compileAst as _compileAst,
Features,
Polyfills,
} from 'tailwindcss'
import type { AstNode } from '../../tailwindcss/src/ast'
import { getModuleDependencies } from './get-module-dependencies'
import { rewriteUrls } from './urls'

export { Features }
export { Features, Polyfills }

export type Resolver = (id: string, base: string) => Promise<string | false | undefined>

export interface CompileOptions {
base: string
onDependency: (path: string) => void
shouldRewriteUrls?: boolean
polyfills?: Polyfills

customCssResolver?: Resolver
customJsResolver?: Resolver
}

function createCompileOptions({
base,
polyfills,
onDependency,
shouldRewriteUrls,

Expand All @@ -37,6 +40,7 @@ function createCompileOptions({
}: CompileOptions) {
return {
base,
polyfills,
async loadModule(id: string, base: string) {
return loadModule(id, base, onDependency, customJsResolver)
},
Expand Down
1 change: 1 addition & 0 deletions packages/@tailwindcss-node/src/index.cts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as env from './env'
export * from './compile'
export * from './instrumentation'
export * from './normalize-path'
export * from './optimize'
export { env }

// In Bun, ESM modules will also populate `require.cache`, so the module hook is
Expand Down
3 changes: 2 additions & 1 deletion packages/@tailwindcss-node/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import * as Module from 'node:module'
import { pathToFileURL } from 'node:url'
import * as env from './env'
export { __unstable__loadDesignSystem, compile, compileAst, Features } from './compile'
export * from './compile'
export * from './instrumentation'
export * from './normalize-path'
export * from './optimize'
export { env }

// In Bun, ESM modules will also populate `require.cache`, so the module hook is
Expand Down
Loading