This PR updates all of the colors in our default theme to use OKLCH instead of RGB and increases the overall chroma to take advantage of the wider color gamut. Just a first draft based on @danhollick's initial work — expecting these will be further refined before a stable release as we continue to test them. <img width="628" alt="image" src="https://github.com/user-attachments/assets/2de1bfca-fddd-47f9-b609-39f26abdee41"> --------- Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
224 lines
5.9 KiB
TypeScript
224 lines
5.9 KiB
TypeScript
import { unlink, writeFile } from 'node:fs/promises'
|
|
import postcss from 'postcss'
|
|
import { afterEach, beforeEach, describe, expect, test } from 'vitest'
|
|
// @ts-ignore
|
|
import tailwindcss from './index'
|
|
|
|
// We give this file path to PostCSS for processing.
|
|
// This file doesn't exist, but the path is used to resolve imports.
|
|
// We place it in packages/ because Vitest runs in the monorepo root,
|
|
// and packages/tailwindcss must be a sub-folder for
|
|
// @import 'tailwindcss' to work.
|
|
const INPUT_CSS_PATH = `${__dirname}/fixtures/example-project/input.css`
|
|
|
|
const css = String.raw
|
|
|
|
test("`@import 'tailwindcss'` is replaced with the generated CSS", async () => {
|
|
let processor = postcss([
|
|
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
|
|
])
|
|
|
|
let result = await processor.process(`@import 'tailwindcss'`, { from: INPUT_CSS_PATH })
|
|
|
|
expect(result.css.trim()).toMatchSnapshot()
|
|
|
|
// Check for dependency messages
|
|
expect(result.messages).toContainEqual({
|
|
type: 'dependency',
|
|
file: expect.stringMatching(/index.html$/g),
|
|
parent: expect.any(String),
|
|
plugin: expect.any(String),
|
|
})
|
|
expect(result.messages).toContainEqual({
|
|
type: 'dependency',
|
|
file: expect.stringMatching(/index.js$/g),
|
|
parent: expect.any(String),
|
|
plugin: expect.any(String),
|
|
})
|
|
expect(result.messages).toContainEqual({
|
|
type: 'dir-dependency',
|
|
dir: expect.stringMatching(/example-project[\/|\\]src$/g),
|
|
glob: expect.stringMatching(/^\*\*\/\*/g),
|
|
parent: expect.any(String),
|
|
plugin: expect.any(String),
|
|
})
|
|
})
|
|
|
|
test('output is optimized by Lightning CSS', async () => {
|
|
let processor = postcss([
|
|
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
|
|
])
|
|
|
|
// `@apply` is used because Lightning is skipped if neither `@tailwind` nor
|
|
// `@apply` is used.
|
|
let result = await processor.process(
|
|
css`
|
|
@layer utilities {
|
|
.foo {
|
|
@apply text-[black];
|
|
}
|
|
}
|
|
|
|
@layer utilities {
|
|
.bar {
|
|
color: red;
|
|
}
|
|
}
|
|
`,
|
|
{ from: INPUT_CSS_PATH },
|
|
)
|
|
|
|
expect(result.css.trim()).toMatchInlineSnapshot(`
|
|
"@layer utilities {
|
|
.foo {
|
|
color: #000;
|
|
}
|
|
|
|
.bar {
|
|
color: red;
|
|
}
|
|
}"
|
|
`)
|
|
})
|
|
|
|
test('@apply can be used without emitting the theme in the CSS file', async () => {
|
|
let processor = postcss([
|
|
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
|
|
])
|
|
|
|
// `@apply` is used because Lightning is skipped if neither `@tailwind` nor
|
|
// `@apply` is used.
|
|
let result = await processor.process(
|
|
css`
|
|
@import 'tailwindcss/theme.css' theme(reference);
|
|
.foo {
|
|
@apply text-red-500;
|
|
}
|
|
`,
|
|
{ from: INPUT_CSS_PATH },
|
|
)
|
|
|
|
expect(result.css.trim()).toMatchInlineSnapshot(`
|
|
".foo {
|
|
color: var(--color-red-500, oklch(.637 .237 25.331));
|
|
}"
|
|
`)
|
|
})
|
|
|
|
describe('processing without specifying a base path', () => {
|
|
let filepath = `${process.cwd()}/my-test-file.html`
|
|
|
|
beforeEach(() =>
|
|
writeFile(filepath, `<div class="md:[&:hover]:content-['testing_default_base_path']">`),
|
|
)
|
|
afterEach(() => unlink(filepath))
|
|
|
|
test('the current working directory is used by default', async () => {
|
|
let processor = postcss([tailwindcss({ optimize: { minify: false } })])
|
|
|
|
let result = await processor.process(`@import "tailwindcss"`, { from: INPUT_CSS_PATH })
|
|
|
|
expect(result.css).toContain(
|
|
".md\\:\\[\\&\\:hover\\]\\:content-\\[\\'testing_default_base_path\\'\\]",
|
|
)
|
|
|
|
expect(result.messages).toContainEqual({
|
|
type: 'dependency',
|
|
file: expect.stringMatching(/my-test-file.html$/g),
|
|
parent: expect.any(String),
|
|
plugin: expect.any(String),
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('plugins', () => {
|
|
test('local CJS plugin', async () => {
|
|
let processor = postcss([
|
|
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
|
|
])
|
|
|
|
let result = await processor.process(
|
|
css`
|
|
@import 'tailwindcss/utilities';
|
|
@plugin './plugin.js';
|
|
`,
|
|
{ from: INPUT_CSS_PATH },
|
|
)
|
|
|
|
expect(result.css.trim()).toMatchInlineSnapshot(`
|
|
".underline {
|
|
text-decoration-line: underline;
|
|
}
|
|
|
|
@media (inverted-colors: inverted) {
|
|
.inverted\\:flex {
|
|
display: flex;
|
|
}
|
|
}
|
|
|
|
.hocus\\:underline:focus, .hocus\\:underline:hover {
|
|
text-decoration-line: underline;
|
|
}"
|
|
`)
|
|
})
|
|
|
|
test('local CJS plugin from `@import`-ed file', async () => {
|
|
let processor = postcss([
|
|
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
|
|
])
|
|
|
|
let result = await processor.process(
|
|
css`
|
|
@import 'tailwindcss/utilities';
|
|
@import '../example-project/src/relative-import.css';
|
|
`,
|
|
{ from: `${__dirname}/fixtures/another-project/input.css` },
|
|
)
|
|
|
|
expect(result.css.trim()).toMatchInlineSnapshot(`
|
|
".underline {
|
|
text-decoration-line: underline;
|
|
}
|
|
|
|
@media (inverted-colors: inverted) {
|
|
.inverted\\:flex {
|
|
display: flex;
|
|
}
|
|
}
|
|
|
|
.hocus\\:underline:focus, .hocus\\:underline:hover {
|
|
text-decoration-line: underline;
|
|
}"
|
|
`)
|
|
})
|
|
|
|
test('published CJS plugin', async () => {
|
|
let processor = postcss([
|
|
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
|
|
])
|
|
|
|
let result = await processor.process(
|
|
css`
|
|
@import 'tailwindcss/utilities';
|
|
@plugin 'internal-example-plugin';
|
|
`,
|
|
{ from: INPUT_CSS_PATH },
|
|
)
|
|
|
|
expect(result.css.trim()).toMatchInlineSnapshot(`
|
|
".underline {
|
|
text-decoration-line: underline;
|
|
}
|
|
|
|
@media (inverted-colors: inverted) {
|
|
.inverted\\:flex {
|
|
display: flex;
|
|
}
|
|
}
|
|
|
|
.hocus\\:underline:focus, .hocus\\:underline:hover {
|
|
text-decoration-line: underline;
|
|
}"
|
|
`)
|
|
})
|
|
})
|