Copy JIT over, tests passing separately, not yet integrated
This commit is contained in:
parent
60b5d63b19
commit
bc5a82a4e3
195 changed files with 9932 additions and 9 deletions
55
jit/tests/_customMatchers.js
Normal file
55
jit/tests/_customMatchers.js
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
const prettier = require('prettier')
|
||||
const diff = require('jest-diff').default
|
||||
|
||||
function format(input) {
|
||||
return prettier.format(input, {
|
||||
parser: 'css',
|
||||
printWidth: 100,
|
||||
})
|
||||
}
|
||||
|
||||
expect.extend({
|
||||
// Compare two CSS strings with all whitespace removed
|
||||
// This is probably naive but it's fast and works well enough.
|
||||
toMatchCss(received, argument) {
|
||||
const options = {
|
||||
comment: 'stripped(received) === stripped(argument)',
|
||||
isNot: this.isNot,
|
||||
promise: this.promise,
|
||||
}
|
||||
|
||||
let formattedReceived = format(received)
|
||||
let formattedArgument = format(argument)
|
||||
|
||||
const pass = formattedReceived === formattedArgument
|
||||
|
||||
const message = pass
|
||||
? () => {
|
||||
return (
|
||||
this.utils.matcherHint('toMatchCss', undefined, undefined, options) +
|
||||
'\n\n' +
|
||||
`Expected: not ${this.utils.printExpected(formattedReceived)}\n` +
|
||||
`Received: ${this.utils.printReceived(formattedArgument)}`
|
||||
)
|
||||
}
|
||||
: () => {
|
||||
const actual = formattedReceived
|
||||
const expected = formattedArgument
|
||||
|
||||
const diffString = diff(expected, actual, {
|
||||
expand: this.expand,
|
||||
})
|
||||
|
||||
return (
|
||||
this.utils.matcherHint('toMatchCss', undefined, undefined, options) +
|
||||
'\n\n' +
|
||||
(diffString && diffString.includes('- Expect')
|
||||
? `Difference:\n\n${diffString}`
|
||||
: `Expected: ${this.utils.printExpected(expected)}\n` +
|
||||
`Received: ${this.utils.printReceived(actual)}`)
|
||||
)
|
||||
}
|
||||
|
||||
return { actual: received, message, pass }
|
||||
},
|
||||
})
|
||||
341
jit/tests/apply.test.css
Normal file
341
jit/tests/apply.test.css
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
.basic-example {
|
||||
border-radius: 0.375rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(59, 130, 246, var(--tw-bg-opacity));
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
.class-order {
|
||||
padding: 2rem;
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem;
|
||||
padding-top: 1.75rem;
|
||||
padding-bottom: 1.75rem;
|
||||
padding-top: 1rem;
|
||||
padding-right: 0.25rem;
|
||||
}
|
||||
.with-additional-properties {
|
||||
font-weight: 500;
|
||||
text-align: right;
|
||||
}
|
||||
.variants {
|
||||
font-weight: 600;
|
||||
}
|
||||
.variants:hover {
|
||||
font-weight: 700;
|
||||
}
|
||||
.variants:focus {
|
||||
font-weight: 500;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.variants {
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.variants:focus {
|
||||
font-weight: 900;
|
||||
}
|
||||
}
|
||||
.only-variants:hover {
|
||||
font-weight: 700;
|
||||
}
|
||||
.only-variants:focus {
|
||||
font-weight: 500;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.only-variants {
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.only-variants:focus {
|
||||
font-weight: 900;
|
||||
}
|
||||
}
|
||||
.group:hover .apply-group-variant {
|
||||
text-align: center;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.group:hover .apply-group-variant {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
.dark .apply-dark-variant {
|
||||
text-align: center;
|
||||
}
|
||||
.dark .apply-dark-variant:hover {
|
||||
text-align: right;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.dark .apply-dark-variant {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
.apply-custom-utility {
|
||||
custom: stuff;
|
||||
}
|
||||
.apply-custom-utility:hover {
|
||||
custom: stuff;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.apply-custom-utility {
|
||||
custom: stuff;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.apply-custom-utility:focus {
|
||||
custom: stuff;
|
||||
}
|
||||
}
|
||||
.multiple,
|
||||
.selectors {
|
||||
border-radius: 0.375rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(59, 130, 246, var(--tw-bg-opacity));
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
.multiple-variants:hover,
|
||||
.selectors-variants:hover {
|
||||
text-align: center;
|
||||
}
|
||||
.multiple-variants:active,
|
||||
.selectors-variants:active {
|
||||
text-align: right;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.multiple-variants:focus,
|
||||
.selectors-variants:focus {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
.group:hover .multiple-group,
|
||||
.group:hover .selectors-group {
|
||||
text-align: center;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.group:hover .multiple-group,
|
||||
.group:hover .selectors-group {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
/* TODO: This works but the generated CSS is unnecessarily verbose. */
|
||||
.complex-utilities {
|
||||
--tw-ordinal: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-slashed-zero: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-figure: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-spacing: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-fraction: var(--tw-empty, /*!*/ /*!*/);
|
||||
font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure)
|
||||
var(--tw-numeric-spacing) var(--tw-numeric-fraction);
|
||||
--tw-ordinal: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-slashed-zero: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-figure: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-spacing: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-fraction: var(--tw-empty, /*!*/ /*!*/);
|
||||
font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure)
|
||||
var(--tw-numeric-spacing) var(--tw-numeric-fraction);
|
||||
--tw-ordinal: ordinal;
|
||||
--tw-numeric-spacing: tabular-nums;
|
||||
--tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.complex-utilities:hover {
|
||||
--tw-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.complex-utilities:focus {
|
||||
--tw-ordinal: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-slashed-zero: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-figure: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-spacing: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-fraction: var(--tw-empty, /*!*/ /*!*/);
|
||||
font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure)
|
||||
var(--tw-numeric-spacing) var(--tw-numeric-fraction);
|
||||
--tw-numeric-fraction: diagonal-fractions;
|
||||
}
|
||||
.basic-nesting-parent {
|
||||
.basic-nesting-child {
|
||||
font-weight: 700;
|
||||
}
|
||||
.basic-nesting-child:hover {
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
.use-base-only-a {
|
||||
font-weight: 700;
|
||||
}
|
||||
.use-dependant-only-b {
|
||||
font-weight: 700;
|
||||
font-weight: 400;
|
||||
}
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
.btn-blue {
|
||||
border-radius: 0.25rem;
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
font-weight: 700;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(59, 130, 246, var(--tw-bg-opacity));
|
||||
--tw-text-opacity: 1;
|
||||
color: rgba(255, 255, 255, var(--tw-text-opacity));
|
||||
}
|
||||
.btn-blue:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(29, 78, 216, var(--tw-bg-opacity));
|
||||
}
|
||||
.recursive-apply-a {
|
||||
font-weight: 900;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.recursive-apply-a {
|
||||
font-weight: 100;
|
||||
}
|
||||
}
|
||||
.recursive-apply-b {
|
||||
font-weight: 900;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.recursive-apply-b {
|
||||
font-weight: 100;
|
||||
}
|
||||
}
|
||||
.recursive-apply-b {
|
||||
font-weight: 600;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.recursive-apply-b {
|
||||
font-weight: 200;
|
||||
}
|
||||
}
|
||||
.recursive-apply-c {
|
||||
font-weight: 900;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.recursive-apply-c {
|
||||
font-weight: 100;
|
||||
}
|
||||
}
|
||||
.recursive-apply-c {
|
||||
font-weight: 600;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.recursive-apply-c {
|
||||
font-weight: 200;
|
||||
}
|
||||
}
|
||||
.recursive-apply-c {
|
||||
font-weight: 700;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.recursive-apply-c {
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
.use-with-other-properties-base {
|
||||
color: green;
|
||||
font-weight: 700;
|
||||
}
|
||||
.use-with-other-properties-component {
|
||||
color: green;
|
||||
font-weight: 700;
|
||||
}
|
||||
.add-sibling-properties {
|
||||
padding: 2rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
.add-sibling-properties:hover {
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.add-sibling-properties {
|
||||
padding-left: 2.5rem;
|
||||
padding-right: 2.5rem;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.add-sibling-properties:focus {
|
||||
padding-left: 0.25rem;
|
||||
padding-right: 0.25rem;
|
||||
}
|
||||
}
|
||||
.add-sibling-properties {
|
||||
padding-top: 3px;
|
||||
color: green;
|
||||
font-weight: 700;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
h1 {
|
||||
font-size: 1.875rem;
|
||||
line-height: 2.25rem;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
h2 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
h2 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
}
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.foo {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
@keyframes pulse {
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
.bar {
|
||||
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite !important;
|
||||
}
|
||||
39
jit/tests/apply.test.html
Normal file
39
jit/tests/apply.test.html
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Title</title>
|
||||
<link rel="stylesheet" href="./tailwind.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="basic-example"></div>
|
||||
<div class="class-order"></div>
|
||||
<div class="with-additional-properties"></div>
|
||||
<div class="variants"></div>
|
||||
<div class="only-variants"></div>
|
||||
<div class="apply-group-variant"></div>
|
||||
<div class="apply-dark-variant"></div>
|
||||
<div class="apply-custom-utility"></div>
|
||||
<div class="multiple selectors"></div>
|
||||
<div class="multiple-variants selectors-variants"></div>
|
||||
<div class="multiple-group selectors-group"></div>
|
||||
<div class="complex-utilities"></div>
|
||||
<div class="basic-nesting-parent">
|
||||
<div class="basic-nesting-child"></div>
|
||||
</div>
|
||||
<div class="use-base-only-a"></div>
|
||||
<div class="use-dependant-only-b"></div>
|
||||
<div class="btn"></div>
|
||||
<div class="btn-blue"></div>
|
||||
<div class="recursive-apply-a"></div>
|
||||
<div class="recursive-apply-b"></div>
|
||||
<div class="recursive-apply-c"></div>
|
||||
<div class="use-with-other-properties-base use-with-other-properties-component"></div>
|
||||
<div class="add-sibling-properties"></div>
|
||||
<div class="a b"></div>
|
||||
<div class="foo"></div>
|
||||
<div class="bar"></div>
|
||||
</body>
|
||||
</html>
|
||||
218
jit/tests/apply.test.js
Normal file
218
jit/tests/apply.test.js
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
const { currentTestName } = expect.getState()
|
||||
|
||||
return postcss([tailwind(config)]).process(input, {
|
||||
from: `${path.resolve(__filename)}?test=${currentTestName}`,
|
||||
})
|
||||
}
|
||||
|
||||
test('@apply', () => {
|
||||
let config = {
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './apply.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.basic-example {
|
||||
@apply px-4 py-2 bg-blue-500 rounded-md;
|
||||
}
|
||||
.class-order {
|
||||
@apply pt-4 pr-1 px-3 py-7 p-8;
|
||||
}
|
||||
.with-additional-properties {
|
||||
font-weight: 500;
|
||||
@apply text-right;
|
||||
}
|
||||
.variants {
|
||||
@apply xl:focus:font-black hover:font-bold lg:font-light focus:font-medium font-semibold;
|
||||
}
|
||||
.only-variants {
|
||||
@apply xl:focus:font-black hover:font-bold lg:font-light focus:font-medium;
|
||||
}
|
||||
.apply-group-variant {
|
||||
@apply group-hover:text-center lg:group-hover:text-left;
|
||||
}
|
||||
.apply-dark-variant {
|
||||
@apply dark:text-center dark:hover:text-right lg:dark:text-left;
|
||||
}
|
||||
.apply-custom-utility {
|
||||
@apply custom-util hover:custom-util lg:custom-util xl:focus:custom-util;
|
||||
}
|
||||
.multiple, .selectors {
|
||||
@apply px-4 py-2 bg-blue-500 rounded-md;
|
||||
}
|
||||
.multiple-variants, .selectors-variants {
|
||||
@apply hover:text-center active:text-right lg:focus:text-left;
|
||||
}
|
||||
.multiple-group, .selectors-group {
|
||||
@apply group-hover:text-center lg:group-hover:text-left;
|
||||
}
|
||||
/* TODO: This works but the generated CSS is unnecessarily verbose. */
|
||||
.complex-utilities {
|
||||
@apply ordinal tabular-nums focus:diagonal-fractions shadow-lg hover:shadow-xl;
|
||||
}
|
||||
.basic-nesting-parent {
|
||||
.basic-nesting-child {
|
||||
@apply font-bold hover:font-normal;
|
||||
}
|
||||
}
|
||||
.use-base-only-a {
|
||||
@apply font-bold;
|
||||
}
|
||||
.use-base-only-b {
|
||||
@apply use-base-only-a font-normal;
|
||||
}
|
||||
.use-dependant-only-a {
|
||||
@apply font-bold;
|
||||
}
|
||||
.use-dependant-only-b {
|
||||
@apply use-dependant-only-a font-normal;
|
||||
}
|
||||
.btn {
|
||||
@apply font-bold py-2 px-4 rounded;
|
||||
}
|
||||
.btn-blue {
|
||||
@apply btn bg-blue-500 hover:bg-blue-700 text-white;
|
||||
}
|
||||
.recursive-apply-a {
|
||||
@apply font-black sm:font-thin;
|
||||
}
|
||||
.recursive-apply-b {
|
||||
@apply recursive-apply-a font-semibold md:font-extralight;
|
||||
}
|
||||
.recursive-apply-c {
|
||||
@apply recursive-apply-b font-bold lg:font-light;
|
||||
}
|
||||
.use-with-other-properties-base {
|
||||
color: green;
|
||||
@apply font-bold;
|
||||
}
|
||||
.use-with-other-properties-component {
|
||||
@apply use-with-other-properties-base;
|
||||
}
|
||||
.add-sibling-properties {
|
||||
padding: 2rem;
|
||||
@apply px-4 hover:px-2 lg:px-10 xl:focus:px-1;
|
||||
padding-top: 3px;
|
||||
@apply use-with-other-properties-base;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@apply text-2xl lg:text-2xl sm:text-3xl;
|
||||
}
|
||||
h2 {
|
||||
@apply text-2xl;
|
||||
@apply lg:text-2xl;
|
||||
@apply sm:text-2xl;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.custom-util {
|
||||
custom: stuff;
|
||||
}
|
||||
|
||||
.foo {
|
||||
@apply animate-spin;
|
||||
}
|
||||
|
||||
.bar {
|
||||
@apply animate-pulse !important;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './apply.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
|
||||
test('@apply error with unknown utility', async () => {
|
||||
let config = {
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './apply.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.foo {
|
||||
@apply a-utility-that-does-not-exist;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
await expect(run(css, config)).rejects.toThrowError('class does not exist')
|
||||
})
|
||||
|
||||
test('@apply error with nested @screen', async () => {
|
||||
let config = {
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './apply.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.foo {
|
||||
@screen md {
|
||||
@apply text-black;
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
await expect(run(css, config)).rejects.toThrowError(
|
||||
'@apply is not supported within nested at-rules like @screen'
|
||||
)
|
||||
})
|
||||
|
||||
test('@apply error with nested @anyatrulehere', async () => {
|
||||
let config = {
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './apply.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.foo {
|
||||
@genie {
|
||||
@apply text-black;
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
await expect(run(css, config)).rejects.toThrowError(
|
||||
'@apply is not supported within nested at-rules like @genie'
|
||||
)
|
||||
})
|
||||
149
jit/tests/arbitrary-values.test.css
Normal file
149
jit/tests/arbitrary-values.test.css
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
.inset-\[11px\] {
|
||||
top: 11px;
|
||||
right: 11px;
|
||||
bottom: 11px;
|
||||
left: 11px;
|
||||
}
|
||||
.mt-\[clamp\(30px\2c 100px\)\] {
|
||||
margin-top: clamp(30px, 100px);
|
||||
}
|
||||
.h-\[3\.23rem\] {
|
||||
height: 3.23rem;
|
||||
}
|
||||
.h-\[calc\(100\%\+1rem\)\] {
|
||||
height: calc(100% + 1rem);
|
||||
}
|
||||
.h-\[var\(--height\)\] {
|
||||
height: var(--height);
|
||||
}
|
||||
.max-h-\[3\.23rem\] {
|
||||
max-height: 3.23rem;
|
||||
}
|
||||
.max-h-\[calc\(100\%\+1rem\)\] {
|
||||
max-height: calc(100% + 1rem);
|
||||
}
|
||||
.max-h-\[var\(--height\)\] {
|
||||
max-height: var(--height);
|
||||
}
|
||||
.min-h-\[3\.23rem\] {
|
||||
min-height: 3.23rem;
|
||||
}
|
||||
.min-h-\[calc\(100\%\+1rem\)\] {
|
||||
min-height: calc(100% + 1rem);
|
||||
}
|
||||
.min-h-\[var\(--height\)\] {
|
||||
min-height: var(--height);
|
||||
}
|
||||
.w-\[3\.23rem\] {
|
||||
width: 3.23rem;
|
||||
}
|
||||
.w-\[calc\(100\%\+1rem\)\] {
|
||||
width: calc(100% + 1rem);
|
||||
}
|
||||
.w-\[var\(--width\)\] {
|
||||
width: var(--width);
|
||||
}
|
||||
.min-w-\[3\.23rem\] {
|
||||
min-width: 3.23rem;
|
||||
}
|
||||
.min-w-\[calc\(100\%\+1rem\)\] {
|
||||
min-width: calc(100% + 1rem);
|
||||
}
|
||||
.min-w-\[var\(--width\)\] {
|
||||
min-width: var(--width);
|
||||
}
|
||||
.max-w-\[3\.23rem\] {
|
||||
max-width: 3.23rem;
|
||||
}
|
||||
.max-w-\[calc\(100\%\+1rem\)\] {
|
||||
max-width: calc(100% + 1rem);
|
||||
}
|
||||
.max-w-\[var\(--width\)\] {
|
||||
max-width: var(--width);
|
||||
}
|
||||
.rotate-\[23deg\] {
|
||||
--tw-rotate: 23deg;
|
||||
}
|
||||
.rotate-\[2\.3rad\] {
|
||||
--tw-rotate: 2.3rad;
|
||||
}
|
||||
.rotate-\[401grad\] {
|
||||
--tw-rotate: 401grad;
|
||||
}
|
||||
.rotate-\[1\.5turn\] {
|
||||
--tw-rotate: 1.5turn;
|
||||
}
|
||||
.grid-cols-\[200px\2c repeat\(auto-fill\2c minmax\(15\%\2c 100px\)\)\2c 300px\] {
|
||||
grid-template-columns: 200px repeat(auto-fill, minmax(15%, 100px)) 300px;
|
||||
}
|
||||
.space-x-\[20cm\] > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-x-reverse: 0;
|
||||
margin-right: calc(20cm * var(--tw-space-x-reverse));
|
||||
margin-left: calc(20cm * calc(1 - var(--tw-space-x-reverse)));
|
||||
}
|
||||
.space-x-\[calc\(20\%-1cm\)\] > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-x-reverse: 0;
|
||||
margin-right: calc(calc(20% - 1cm) * var(--tw-space-x-reverse));
|
||||
margin-left: calc(calc(20% - 1cm) * calc(1 - var(--tw-space-x-reverse)));
|
||||
}
|
||||
.border-\[2\.5px\] {
|
||||
border-width: 2.5px;
|
||||
}
|
||||
.border-\[\#f00\] {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgba(255, 0, 0, var(--tw-border-opacity));
|
||||
}
|
||||
.bg-\[\#0f0\] {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(0, 255, 0, var(--tw-bg-opacity));
|
||||
}
|
||||
.bg-\[\#ff0000\] {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(255, 0, 0, var(--tw-bg-opacity));
|
||||
}
|
||||
.bg-\[\#0000ffcc\] {
|
||||
background-color: #0000ffcc;
|
||||
}
|
||||
.bg-\[rgb\(123\2c 123\2c 123\)\] {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(123, 123, 123, var(--tw-bg-opacity));
|
||||
}
|
||||
.bg-\[rgba\(123\2c 123\2c 123\2c 0\.5\)\] {
|
||||
background-color: rgba(123, 123, 123, 0.5);
|
||||
}
|
||||
.bg-\[hsl\(0\2c 100\%\2c 50\%\)\] {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(255, 0, 0, var(--tw-bg-opacity));
|
||||
}
|
||||
.bg-\[hsla\(0\2c 100\%\2c 50\%\2c 0\.3\)\] {
|
||||
background-color: hsla(0, 100%, 50%, 0.3);
|
||||
}
|
||||
.bg-opacity-\[0\.11\] {
|
||||
--tw-bg-opacity: 0.11;
|
||||
}
|
||||
.p-\[var\(--app-padding\)\] {
|
||||
padding: var(--app-padding);
|
||||
}
|
||||
.text-\[2\.23rem\] {
|
||||
font-size: 2.23rem;
|
||||
}
|
||||
.duration-\[2s\] {
|
||||
transition-duration: 2s;
|
||||
}
|
||||
.duration-\[var\(--app-duration\)\] {
|
||||
transition-duration: var(--app-duration);
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.lg\:grid-cols-\[200px\2c repeat\(auto-fill\2c minmax\(15\%\2c 100px\)\)\2c 300px\] {
|
||||
grid-template-columns: 200px repeat(auto-fill, minmax(15%, 100px)) 300px;
|
||||
}
|
||||
}
|
||||
47
jit/tests/arbitrary-values.test.html
Normal file
47
jit/tests/arbitrary-values.test.html
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Title</title>
|
||||
<link rel="stylesheet" href="./tailwind.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="bg-[#0f0] bg-[#ff0000] bg-[#0000ffcc]"></div>
|
||||
<div class="bg-[rgb(123,123,123)] bg-[rgba(123,123,123,0.5)]"></div>
|
||||
<div class="bg-[hsl(0,100%,50%)] bg-[hsla(0,100%,50%,0.3)]"></div>
|
||||
<div class="bg-opacity-[0.11]"></div>
|
||||
<div class="border-[#f00]"></div>
|
||||
<div class="border-[2.5px]"></div>
|
||||
<div class="w-[3.23rem]"></div>
|
||||
<div class="w-[calc(100%+1rem)]"></div>
|
||||
<div class="w-[var(--width)]"></div>
|
||||
<div class="min-w-[3.23rem]"></div>
|
||||
<div class="min-w-[calc(100%+1rem)]"></div>
|
||||
<div class="min-w-[var(--width)]"></div>
|
||||
<div class="max-w-[3.23rem]"></div>
|
||||
<div class="max-w-[calc(100%+1rem)]"></div>
|
||||
<div class="max-w-[var(--width)]"></div>
|
||||
<div class="h-[3.23rem]"></div>
|
||||
<div class="h-[calc(100%+1rem)]"></div>
|
||||
<div class="h-[var(--height)]"></div>
|
||||
<div class="min-h-[3.23rem]"></div>
|
||||
<div class="min-h-[calc(100%+1rem)]"></div>
|
||||
<div class="min-h-[var(--height)]"></div>
|
||||
<div class="max-h-[3.23rem]"></div>
|
||||
<div class="max-h-[calc(100%+1rem)]"></div>
|
||||
<div class="max-h-[var(--height)]"></div>
|
||||
<div class="space-x-[20cm]"></div>
|
||||
<div class="space-x-[calc(20%-1cm)]"></div>
|
||||
<div class="grid-cols-[200px,repeat(auto-fill,minmax(15%,100px)),300px]"></div>
|
||||
<div class="lg:grid-cols-[200px,repeat(auto-fill,minmax(15%,100px)),300px]"></div>
|
||||
<div class="rotate-[23deg] rotate-[2.3rad] rotate-[401grad] rotate-[1.5turn]"></div>
|
||||
<div class="text-[2.23rem]"></div>
|
||||
<div class="duration-[2s]"></div>
|
||||
<div class="mt-[clamp(30px,100px)]"></div>
|
||||
<div class="duration-[var(--app-duration)]"></div>
|
||||
<div class="p-[var(--app-padding)]"></div>
|
||||
<div class="inset-[11px]"></div>
|
||||
</body>
|
||||
</html>
|
||||
30
jit/tests/arbitrary-values.test.js
Normal file
30
jit/tests/arbitrary-values.test.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('arbitrary values', () => {
|
||||
let config = {
|
||||
purge: [path.resolve(__dirname, './arbitrary-values.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './arbitrary-values.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
631
jit/tests/basic-usage.test.css
Normal file
631
jit/tests/basic-usage.test.css
Normal file
|
|
@ -0,0 +1,631 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
.container {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.container {
|
||||
max-width: 640px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
max-width: 768px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.container {
|
||||
max-width: 1024px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.container {
|
||||
max-width: 1280px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
.container {
|
||||
max-width: 1536px;
|
||||
}
|
||||
}
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
.pointer-events-none {
|
||||
pointer-events: none;
|
||||
}
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
.absolute {
|
||||
position: absolute;
|
||||
}
|
||||
.inset-0 {
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
.inset-y-4 {
|
||||
top: 1rem;
|
||||
bottom: 1rem;
|
||||
}
|
||||
.inset-x-2 {
|
||||
left: 0.5rem;
|
||||
right: 0.5rem;
|
||||
}
|
||||
.top-6 {
|
||||
top: 1.5rem;
|
||||
}
|
||||
.right-8 {
|
||||
right: 2rem;
|
||||
}
|
||||
.bottom-12 {
|
||||
bottom: 3rem;
|
||||
}
|
||||
.left-16 {
|
||||
left: 4rem;
|
||||
}
|
||||
.z-30 {
|
||||
z-index: 30;
|
||||
}
|
||||
.order-last {
|
||||
order: 9999;
|
||||
}
|
||||
.order-2 {
|
||||
order: 2;
|
||||
}
|
||||
.col-span-3 {
|
||||
grid-column: span 3 / span 3;
|
||||
}
|
||||
.col-end-4 {
|
||||
grid-column-end: 4;
|
||||
}
|
||||
.col-start-1 {
|
||||
grid-column-start: 1;
|
||||
}
|
||||
.row-span-2 {
|
||||
grid-row: span 2 / span 2;
|
||||
}
|
||||
.row-end-5 {
|
||||
grid-row-end: 5;
|
||||
}
|
||||
.row-start-3 {
|
||||
grid-row-start: 3;
|
||||
}
|
||||
.float-right {
|
||||
float: right;
|
||||
}
|
||||
.clear-left {
|
||||
clear: left;
|
||||
}
|
||||
.m-4 {
|
||||
margin: 1rem;
|
||||
}
|
||||
.my-2 {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.mx-auto {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.mt-0 {
|
||||
margin-top: 0px;
|
||||
}
|
||||
.mr-1 {
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
.mb-3 {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
.ml-4 {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
.box-border {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.inline-grid {
|
||||
display: inline-grid;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.h-16 {
|
||||
height: 4rem;
|
||||
}
|
||||
.max-h-screen {
|
||||
max-height: 100vh;
|
||||
}
|
||||
.min-h-0 {
|
||||
min-height: 0px;
|
||||
}
|
||||
.w-12 {
|
||||
width: 3rem;
|
||||
}
|
||||
.min-w-min {
|
||||
min-width: min-content;
|
||||
}
|
||||
.max-w-full {
|
||||
max-width: 100%;
|
||||
}
|
||||
.flex-1 {
|
||||
flex: 1 1 0%;
|
||||
}
|
||||
.flex-shrink {
|
||||
flex-shrink: 1;
|
||||
}
|
||||
.flex-shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.flex-grow {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.flex-grow-0 {
|
||||
flex-grow: 0;
|
||||
}
|
||||
.table-fixed {
|
||||
table-layout: fixed;
|
||||
}
|
||||
.border-collapse {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.transform {
|
||||
--tw-translate-x: 0;
|
||||
--tw-translate-y: 0;
|
||||
--tw-rotate: 0;
|
||||
--tw-skew-x: 0;
|
||||
--tw-skew-y: 0;
|
||||
--tw-scale-x: 1;
|
||||
--tw-scale-y: 1;
|
||||
transform: translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y))
|
||||
rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
|
||||
scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
.transform-gpu {
|
||||
--tw-translate-x: 0;
|
||||
--tw-translate-y: 0;
|
||||
--tw-rotate: 0;
|
||||
--tw-skew-x: 0;
|
||||
--tw-skew-y: 0;
|
||||
--tw-scale-x: 1;
|
||||
--tw-scale-y: 1;
|
||||
transform: translate3d(var(--tw-translate-x), var(--tw-translate-y), 0) rotate(var(--tw-rotate))
|
||||
skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
|
||||
scaleY(var(--tw-scale-y));
|
||||
}
|
||||
.origin-top-right {
|
||||
transform-origin: top right;
|
||||
}
|
||||
.translate-x-5 {
|
||||
--tw-translate-x: 1.25rem;
|
||||
}
|
||||
.-translate-x-4 {
|
||||
--tw-translate-x: -1rem;
|
||||
}
|
||||
.translate-y-6 {
|
||||
--tw-translate-y: 1.5rem;
|
||||
}
|
||||
.-translate-x-3 {
|
||||
--tw-translate-x: -0.75rem;
|
||||
}
|
||||
.rotate-3 {
|
||||
--tw-rotate: 3deg;
|
||||
}
|
||||
.skew-y-12 {
|
||||
--tw-skew-y: 12deg;
|
||||
}
|
||||
.skew-x-12 {
|
||||
--tw-skew-x: 12deg;
|
||||
}
|
||||
.scale-95 {
|
||||
--tw-scale-x: 0.95;
|
||||
--tw-scale-y: 0.95;
|
||||
}
|
||||
.animate-none {
|
||||
animation: none;
|
||||
}
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.animate-spin {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
.select-none {
|
||||
user-select: none;
|
||||
}
|
||||
.resize-none {
|
||||
resize: none;
|
||||
}
|
||||
.list-inside {
|
||||
list-style-position: inside;
|
||||
}
|
||||
.list-disc {
|
||||
list-style-type: disc;
|
||||
}
|
||||
.appearance-none {
|
||||
appearance: none;
|
||||
}
|
||||
.auto-cols-min {
|
||||
grid-auto-columns: min-content;
|
||||
}
|
||||
.grid-flow-row {
|
||||
grid-auto-flow: row;
|
||||
}
|
||||
.auto-rows-max {
|
||||
grid-auto-rows: max-content;
|
||||
}
|
||||
.grid-cols-4 {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
.grid-rows-3 {
|
||||
grid-template-rows: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
.flex-row-reverse {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
.flex-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.place-content-start {
|
||||
place-content: start;
|
||||
}
|
||||
.place-items-end {
|
||||
place-items: end;
|
||||
}
|
||||
.content-center {
|
||||
align-content: center;
|
||||
}
|
||||
.items-start {
|
||||
align-items: flex-start;
|
||||
}
|
||||
.justify-center {
|
||||
justify-content: center;
|
||||
}
|
||||
.justify-items-end {
|
||||
justify-items: end;
|
||||
}
|
||||
.gap-4 {
|
||||
gap: 1rem;
|
||||
}
|
||||
.gap-x-2 {
|
||||
column-gap: 0.5rem;
|
||||
}
|
||||
.gap-y-3 {
|
||||
row-gap: 0.75rem;
|
||||
}
|
||||
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-x-reverse: 0;
|
||||
margin-right: calc(1rem * var(--tw-space-x-reverse));
|
||||
margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
|
||||
}
|
||||
.space-y-3 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-y-reverse: 0;
|
||||
margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
|
||||
margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));
|
||||
}
|
||||
.space-y-reverse > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-y-reverse: 1;
|
||||
}
|
||||
.space-x-reverse > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-x-reverse: 1;
|
||||
}
|
||||
.divide-x-2 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-divide-x-reverse: 0;
|
||||
border-right-width: calc(2px * var(--tw-divide-x-reverse));
|
||||
border-left-width: calc(2px * calc(1 - var(--tw-divide-x-reverse)));
|
||||
}
|
||||
.divide-y-4 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-divide-y-reverse: 0;
|
||||
border-top-width: calc(4px * calc(1 - var(--tw-divide-y-reverse)));
|
||||
border-bottom-width: calc(4px * var(--tw-divide-y-reverse));
|
||||
}
|
||||
.divide-x-0 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-divide-x-reverse: 0;
|
||||
border-right-width: calc(0px * var(--tw-divide-x-reverse));
|
||||
border-left-width: calc(0px * calc(1 - var(--tw-divide-x-reverse)));
|
||||
}
|
||||
.divide-y-0 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-divide-y-reverse: 0;
|
||||
border-top-width: calc(0px * calc(1 - var(--tw-divide-y-reverse)));
|
||||
border-bottom-width: calc(0px * var(--tw-divide-y-reverse));
|
||||
}
|
||||
.divide-dotted > :not([hidden]) ~ :not([hidden]) {
|
||||
border-style: dotted;
|
||||
}
|
||||
.divide-gray-200 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-divide-opacity: 1;
|
||||
border-color: rgba(229, 231, 235, var(--tw-divide-opacity));
|
||||
}
|
||||
.divide-opacity-50 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-divide-opacity: 0.5;
|
||||
}
|
||||
.place-self-center {
|
||||
place-self: center;
|
||||
}
|
||||
.self-end {
|
||||
align-self: flex-end;
|
||||
}
|
||||
.justify-self-start {
|
||||
justify-self: start;
|
||||
}
|
||||
.overflow-hidden {
|
||||
overflow: hidden;
|
||||
}
|
||||
.overscroll-contain {
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
.truncate {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.overflow-ellipsis {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.whitespace-nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.break-words {
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
.rounded-md {
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
.border {
|
||||
border-width: 1px;
|
||||
}
|
||||
.border-2 {
|
||||
border-width: 2px;
|
||||
}
|
||||
.border-solid {
|
||||
border-style: solid;
|
||||
}
|
||||
.border-black {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgba(0, 0, 0, var(--tw-border-opacity));
|
||||
}
|
||||
.border-opacity-10 {
|
||||
--tw-border-opacity: 0.1;
|
||||
}
|
||||
.bg-green-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(16, 185, 129, var(--tw-bg-opacity));
|
||||
}
|
||||
.bg-opacity-20 {
|
||||
--tw-bg-opacity: 0.2;
|
||||
}
|
||||
.bg-gradient-to-r {
|
||||
background-image: linear-gradient(to right, var(--tw-gradient-stops));
|
||||
}
|
||||
.from-red-300 {
|
||||
--tw-gradient-from: #fca5a5;
|
||||
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgba(252, 165, 165, 0));
|
||||
}
|
||||
.via-purple-200 {
|
||||
--tw-gradient-stops: var(--tw-gradient-from), #ddd6fe,
|
||||
var(--tw-gradient-to, rgba(221, 214, 254, 0));
|
||||
}
|
||||
.to-blue-400 {
|
||||
--tw-gradient-to: #60a5fa;
|
||||
}
|
||||
.bg-cover {
|
||||
background-size: cover;
|
||||
}
|
||||
.bg-local {
|
||||
background-attachment: local;
|
||||
}
|
||||
.bg-clip-border {
|
||||
background-clip: border-box;
|
||||
}
|
||||
.bg-top {
|
||||
background-position: top;
|
||||
}
|
||||
.bg-no-repeat {
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.fill-current {
|
||||
fill: currentColor;
|
||||
}
|
||||
.stroke-current {
|
||||
stroke: currentColor;
|
||||
}
|
||||
.stroke-2 {
|
||||
stroke-width: 2;
|
||||
}
|
||||
.object-cover {
|
||||
object-fit: cover;
|
||||
}
|
||||
.object-bottom {
|
||||
object-position: bottom;
|
||||
}
|
||||
.p-4 {
|
||||
padding: 1rem;
|
||||
}
|
||||
.py-2 {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
.px-3 {
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem;
|
||||
}
|
||||
.pt-1 {
|
||||
padding-top: 0.25rem;
|
||||
}
|
||||
.pr-2 {
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
.pb-3 {
|
||||
padding-bottom: 0.75rem;
|
||||
}
|
||||
.pl-4 {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
.align-middle {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.font-sans {
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
||||
'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
}
|
||||
.text-2xl {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
.font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
.uppercase {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.not-italic {
|
||||
font-style: normal;
|
||||
}
|
||||
.ordinal,
|
||||
.slashed-zero,
|
||||
.lining-nums,
|
||||
.oldstyle-nums,
|
||||
.proportional-nums,
|
||||
.tabular-nums,
|
||||
.diagonal-fractions,
|
||||
.stacked-fractions {
|
||||
--tw-ordinal: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-slashed-zero: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-figure: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-spacing: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-fraction: var(--tw-empty, /*!*/ /*!*/);
|
||||
font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure)
|
||||
var(--tw-numeric-spacing) var(--tw-numeric-fraction);
|
||||
}
|
||||
.tabular-nums {
|
||||
--tw-numeric-spacing: tabular-nums;
|
||||
}
|
||||
.ordinal {
|
||||
--tw-ordinal: ordinal;
|
||||
}
|
||||
.diagonal-fractions {
|
||||
--tw-numeric-fraction: diagonal-fractions;
|
||||
}
|
||||
.leading-relaxed {
|
||||
line-height: 1.625;
|
||||
}
|
||||
.leading-5 {
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
.tracking-tight {
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
.text-indigo-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgba(99, 102, 241, var(--tw-text-opacity));
|
||||
}
|
||||
.text-opacity-10 {
|
||||
--tw-text-opacity: 0.1;
|
||||
}
|
||||
.underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.antialiased {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
.placeholder-green-300::placeholder {
|
||||
--tw-placeholder-opacity: 1;
|
||||
color: rgba(110, 231, 183, var(--tw-placeholder-opacity));
|
||||
}
|
||||
.placeholder-opacity-60::placeholder {
|
||||
--tw-placeholder-opacity: 0.6;
|
||||
}
|
||||
.opacity-90 {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.shadow-lg {
|
||||
--tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.outline-none {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.outline-black {
|
||||
outline: 2px dotted black;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.ring {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
||||
var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width))
|
||||
var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
}
|
||||
.ring-4 {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
||||
var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width))
|
||||
var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
}
|
||||
.ring-white {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgba(255, 255, 255, var(--tw-ring-opacity));
|
||||
}
|
||||
.ring-opacity-40 {
|
||||
--tw-ring-opacity: 0.4;
|
||||
}
|
||||
.ring-offset-2 {
|
||||
--tw-ring-offset-width: 2px;
|
||||
}
|
||||
.ring-offset-blue-300 {
|
||||
--tw-ring-offset-color: #93c5fd;
|
||||
}
|
||||
.transition {
|
||||
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow,
|
||||
transform;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
.transition-all {
|
||||
transition-property: all;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
.delay-300 {
|
||||
transition-delay: 300ms;
|
||||
}
|
||||
.duration-200 {
|
||||
transition-duration: 200ms;
|
||||
}
|
||||
.ease-in-out {
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
135
jit/tests/basic-usage.test.html
Normal file
135
jit/tests/basic-usage.test.html
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Title</title>
|
||||
<link rel="stylesheet" href="./tailwind.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="sr-only"></div>
|
||||
<div class="content-center"></div>
|
||||
<div class="items-start"></div>
|
||||
<div class="self-end"></div>
|
||||
<div class="animate-none"></div>
|
||||
<div class="animate-spin"></div>
|
||||
<div class="appearance-none"></div>
|
||||
<div class="bg-local"></div>
|
||||
<div class="bg-clip-border"></div>
|
||||
<div class="bg-green-500"></div>
|
||||
<div class="bg-gradient-to-r"></div>
|
||||
<div class="bg-opacity-20"></div>
|
||||
<div class="bg-top"></div>
|
||||
<div class="bg-no-repeat"></div>
|
||||
<div class="bg-cover"></div>
|
||||
<div class="border-collapse"></div>
|
||||
<div class="border-black"></div>
|
||||
<div class="border-opacity-10"></div>
|
||||
<div class="rounded-md"></div>
|
||||
<div class="border-solid"></div>
|
||||
<div class="border"></div>
|
||||
<div class="border-2"></div>
|
||||
<div class="shadow-md"></div>
|
||||
<div class="shadow-lg"></div>
|
||||
<div class="box-border"></div>
|
||||
<div class="clear-left"></div>
|
||||
<div class="container"></div>
|
||||
<div class="cursor-pointer"></div>
|
||||
<div class="hidden inline-grid"></div>
|
||||
<div class="divide-gray-200"></div>
|
||||
<div class="divide-opacity-50"></div>
|
||||
<div class="divide-dotted"></div>
|
||||
<div class="divide-x-2 divide-y-4 divide-x-0 divide-y-0"></div>
|
||||
<div class="fill-current"></div>
|
||||
<div class="flex-1"></div>
|
||||
<div class="flex-row-reverse"></div>
|
||||
<div class="flex-grow"></div>
|
||||
<div class="flex-grow-0"></div>
|
||||
<div class="flex-shrink"></div>
|
||||
<div class="flex-shrink-0"></div>
|
||||
<div class="flex-wrap"></div>
|
||||
<div class="float-right"></div>
|
||||
<div class="font-sans"></div>
|
||||
<div class="text-2xl"></div>
|
||||
<div class="antialiased"></div>
|
||||
<div class="not-italic"></div>
|
||||
<div class="tabular-nums ordinal diagonal-fractions"></div>
|
||||
<div class="font-medium"></div>
|
||||
<div class="gap-x-2 gap-y-3 gap-4"></div>
|
||||
<div class="from-red-300 via-purple-200 to-blue-400"></div>
|
||||
<div class="auto-cols-min"></div>
|
||||
<div class="grid-flow-row"></div>
|
||||
<div class="auto-rows-max"></div>
|
||||
<div class="col-span-3"></div>
|
||||
<div class="col-start-1"></div>
|
||||
<div class="col-end-4"></div>
|
||||
<div class="row-span-2"></div>
|
||||
<div class="row-start-3"></div>
|
||||
<div class="row-end-5"></div>
|
||||
<div class="grid-cols-4"></div>
|
||||
<div class="grid-rows-3"></div>
|
||||
<div class="h-16"></div>
|
||||
<div class="inset-0 inset-y-4 inset-x-2 top-6 right-8 bottom-12 left-16"></div>
|
||||
<div class="justify-center"></div>
|
||||
<div class="justify-items-end"></div>
|
||||
<div class="justify-self-start"></div>
|
||||
<div class="tracking-tight"></div>
|
||||
<div class="leading-relaxed leading-5"></div>
|
||||
<div class="list-inside"></div>
|
||||
<div class="list-disc"></div>
|
||||
<div class="m-4 my-2 mx-auto mt-0 mr-1 mb-3 ml-4"></div>
|
||||
<div class="max-h-screen"></div>
|
||||
<div class="max-w-full"></div>
|
||||
<div class="min-h-0"></div>
|
||||
<div class="min-w-min"></div>
|
||||
<div class="object-cover"></div>
|
||||
<div class="object-bottom"></div>
|
||||
<div class="opacity-90"></div>
|
||||
<div class="order-last order-2"></div>
|
||||
<div class="outline-none outline-black"></div>
|
||||
<div class="overflow-hidden"></div>
|
||||
<div class="overscroll-contain"></div>
|
||||
<div class="p-4 py-2 px-3 pt-1 pr-2 pb-3 pl-4"></div>
|
||||
<div class="place-content-start"></div>
|
||||
<div class="placeholder-green-300"></div>
|
||||
<div class="placeholder-opacity-60"></div>
|
||||
<div class="place-items-end"></div>
|
||||
<div class="place-self-center"></div>
|
||||
<div class="pointer-events-none"></div>
|
||||
<div class="absolute"></div>
|
||||
<div class="resize-none"></div>
|
||||
<div class="ring-white"></div>
|
||||
<div class="ring-offset-blue-300"></div>
|
||||
<div class="ring-offset-2"></div>
|
||||
<div class="ring-opacity-40"></div>
|
||||
<div class="ring ring-4"></div>
|
||||
<div class="rotate-3"></div>
|
||||
<div class="scale-95"></div>
|
||||
<div class="skew-y-12 skew-x-12"></div>
|
||||
<div class="space-x-4 space-y-3 space-x-reverse space-y-reverse"></div>
|
||||
<div class="stroke-current"></div>
|
||||
<div class="stroke-2"></div>
|
||||
<div class="table-fixed"></div>
|
||||
<div class="text-center"></div>
|
||||
<div class="text-indigo-500"></div>
|
||||
<div class="underline"></div>
|
||||
<div class="text-opacity-10"></div>
|
||||
<div class="overflow-ellipsis truncate"></div>
|
||||
<div class="uppercase"></div>
|
||||
<div class="transform transform-gpu"></div>
|
||||
<div class="origin-top-right"></div>
|
||||
<div class="delay-300"></div>
|
||||
<div class="duration-200"></div>
|
||||
<div class="transition transition-all"></div>
|
||||
<div class="ease-in-out"></div>
|
||||
<div class="translate-x-5 -translate-x-4 translate-y-6 -translate-x-3"></div>
|
||||
<div class="select-none"></div>
|
||||
<div class="align-middle"></div>
|
||||
<div class="invisible"></div>
|
||||
<div class="whitespace-nowrap"></div>
|
||||
<div class="w-12"></div>
|
||||
<div class="break-words"></div>
|
||||
<div class="z-30"></div>
|
||||
</body>
|
||||
</html>
|
||||
30
jit/tests/basic-usage.test.js
Normal file
30
jit/tests/basic-usage.test.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('basic usage', () => {
|
||||
let config = {
|
||||
purge: [path.resolve(__dirname, './basic-usage.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './basic-usage.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
56
jit/tests/collapse-adjacent-rules.test.css
Normal file
56
jit/tests/collapse-adjacent-rules.test.css
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
src: url('/fonts/Poppins.woff2') format('woff2'), url('/fonts/Poppins.woff') format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Proxima Nova';
|
||||
src: url('/fonts/ProximaNova.woff2') format('woff2'),
|
||||
url('/fonts/ProximaNova.woff') format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
src: url('/fonts/Inter.woff2') format('woff2'), url('/fonts/Inter.woff') format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Gilroy';
|
||||
src: url('/fonts/Gilroy.woff2') format('woff2'), url('/fonts/Gilroy.woff') format('woff');
|
||||
}
|
||||
@page {
|
||||
margin: 1cm;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.sm\:text-center {
|
||||
text-align: center;
|
||||
}
|
||||
.sm\:font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\:text-center {
|
||||
text-align: center;
|
||||
}
|
||||
.md\:font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.lg\:text-center {
|
||||
text-align: center;
|
||||
}
|
||||
.lg\:font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
23
jit/tests/collapse-adjacent-rules.test.html
Normal file
23
jit/tests/collapse-adjacent-rules.test.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Title</title>
|
||||
<link rel="stylesheet" href="./tailwind.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="custom-component"></div>
|
||||
<div class="sm:custom-component"></div>
|
||||
<div class="md:custom-component"></div>
|
||||
<div class="lg:custom-component"></div>
|
||||
<div class="font-bold"></div>
|
||||
<div class="sm:font-bold"></div>
|
||||
<div class="sm:text-center"></div>
|
||||
<div class="md:font-bold"></div>
|
||||
<div class="md:text-center"></div>
|
||||
<div class="lg:font-bold"></div>
|
||||
<div class="lg:text-center"></div>
|
||||
</body>
|
||||
</html>
|
||||
55
jit/tests/collapse-adjacent-rules.test.js
Normal file
55
jit/tests/collapse-adjacent-rules.test.js
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('collapse adjacent rules', () => {
|
||||
let config = {
|
||||
purge: [path.resolve(__dirname, './collapse-adjacent-rules.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind base;
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
src: url("/fonts/Inter.woff2") format("woff2"),
|
||||
url("/fonts/Inter.woff") format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Gilroy";
|
||||
src: url("/fonts/Gilroy.woff2") format("woff2"),
|
||||
url("/fonts/Gilroy.woff") format("woff");
|
||||
}
|
||||
@page {
|
||||
margin: 1cm;
|
||||
}
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@layer base {
|
||||
@font-face {
|
||||
font-family: "Poppins";
|
||||
src: url("/fonts/Poppins.woff2") format("woff2"),
|
||||
url("/fonts/Poppins.woff") format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Proxima Nova";
|
||||
src: url("/fonts/ProximaNova.woff2") format("woff2"),
|
||||
url("/fonts/ProximaNova.woff") format("woff");
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './collapse-adjacent-rules.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
11
jit/tests/context-reuse.test.html
Normal file
11
jit/tests/context-reuse.test.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Title</title>
|
||||
<link rel="stylesheet" href="./tailwind.css" />
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
17
jit/tests/context-reuse.test.js
Normal file
17
jit/tests/context-reuse.test.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
const path = require('path')
|
||||
const process = require('child_process')
|
||||
const { promisify } = require('util')
|
||||
const exec = promisify(process.exec)
|
||||
|
||||
test('a build re-uses the context across multiple files with the same config', async () => {
|
||||
const filepath = path.resolve(__dirname, './context-reuse.worker.js')
|
||||
|
||||
const { stdout } = await exec(`node ${filepath}`)
|
||||
|
||||
const results = JSON.parse(stdout.trim())
|
||||
|
||||
expect(results[0].activeContexts).toBe(1)
|
||||
expect(results[1].activeContexts).toBe(1)
|
||||
expect(results[2].activeContexts).toBe(1)
|
||||
expect(results[3].activeContexts).toBe(1)
|
||||
})
|
||||
47
jit/tests/context-reuse.worker.js
Normal file
47
jit/tests/context-reuse.worker.js
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const sharedState = require('../lib/sharedState.js')
|
||||
const configPath = path.resolve(__dirname, './context-reuse.tailwind.config.js')
|
||||
|
||||
function run(input, config = {}, from = null) {
|
||||
from = from || path.resolve(__filename)
|
||||
|
||||
return postcss([tailwind(config)]).process(input, { from })
|
||||
}
|
||||
|
||||
async function runTest() {
|
||||
let messages = []
|
||||
|
||||
let config = {
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './context-reuse.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let from = path.resolve(__filename)
|
||||
|
||||
fs.writeFileSync(configPath, `module.exports = ${JSON.stringify(config)};`)
|
||||
|
||||
let results = [
|
||||
await run(`@tailwind utilities;`, configPath, `${from}?id=1`),
|
||||
await run(`body { @apply bg-blue-400; }`, configPath, `${from}?id=2`),
|
||||
await run(`body { @apply text-red-400; }`, configPath, `${from}?id=3`),
|
||||
await run(`body { @apply mb-4; }`, configPath, `${from}?id=4`),
|
||||
]
|
||||
|
||||
results.forEach(() => {
|
||||
messages.push({
|
||||
activeContexts: sharedState.contextSourcesMap.size,
|
||||
})
|
||||
})
|
||||
|
||||
process.stdout.write(JSON.stringify(messages))
|
||||
}
|
||||
|
||||
runTest().finally(() => {
|
||||
fs.unlinkSync(configPath)
|
||||
})
|
||||
17
jit/tests/custom-extractors.test.css
Normal file
17
jit/tests/custom-extractors.test.css
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
.bg-white {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(255, 255, 255, var(--tw-bg-opacity));
|
||||
}
|
||||
.text-indigo-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgba(99, 102, 241, var(--tw-text-opacity));
|
||||
}
|
||||
14
jit/tests/custom-extractors.test.html
Normal file
14
jit/tests/custom-extractors.test.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Title</title>
|
||||
<link rel="stylesheet" href="./tailwind.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="text-indigo-500 bg-white">hello world</div>
|
||||
<span>text-red-500 shouldn't appear in the output</span>
|
||||
</body>
|
||||
</html>
|
||||
63
jit/tests/custom-extractors.test.js
Normal file
63
jit/tests/custom-extractors.test.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
const postcss = require('postcss')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
jest.resetModules()
|
||||
const tailwind = require('../index.js')
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
function customExtractor(content) {
|
||||
const matches = content.match(/class="([^"]+)"/)
|
||||
return matches ? matches[1].split(/\s+/) : []
|
||||
}
|
||||
|
||||
const css = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
`
|
||||
const expectedPath = path.resolve(__dirname, './custom-extractors.test.css')
|
||||
const expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
test('defaultExtractor', () => {
|
||||
let config = {
|
||||
purge: {
|
||||
content: [path.resolve(__dirname, './custom-extractors.test.html')],
|
||||
options: {
|
||||
defaultExtractor: customExtractor,
|
||||
},
|
||||
},
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
|
||||
test('extractors array', () => {
|
||||
let config = {
|
||||
purge: {
|
||||
content: [path.resolve(__dirname, './custom-extractors.test.html')],
|
||||
options: {
|
||||
extractors: [
|
||||
{
|
||||
extractor: customExtractor,
|
||||
extensions: ['html'],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
19
jit/tests/custom-separator.test.css
Normal file
19
jit/tests/custom-separator.test.css
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
.group_hover .group-hover_focus-within_text-left:focus-within {
|
||||
text-align: left;
|
||||
}
|
||||
[dir='rtl'] .rtl_active_text-center:active {
|
||||
text-align: center;
|
||||
}
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.motion-safe_hover_text-center:hover {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.dark .dark_focus_text-left:focus {
|
||||
text-align: left;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md_hover_text-right:hover {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
5
jit/tests/custom-separator.test.html
Normal file
5
jit/tests/custom-separator.test.html
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<div class="md_hover_text-right"></div>
|
||||
<div class="motion-safe_hover_text-center"></div>
|
||||
<div class="dark_focus_text-left"></div>
|
||||
<div class="group-hover_focus-within_text-left"></div>
|
||||
<div class="rtl_active_text-center"></div>
|
||||
28
jit/tests/custom-separator.test.js
Normal file
28
jit/tests/custom-separator.test.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('custom separator', () => {
|
||||
let config = {
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './custom-separator.test.html')],
|
||||
separator: '_',
|
||||
corePlugins: {},
|
||||
theme: {},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `@tailwind utilities`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './custom-separator.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
52
jit/tests/import-syntax.test.css
Normal file
52
jit/tests/import-syntax.test.css
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
h1 {
|
||||
font-size: 32px;
|
||||
}
|
||||
.container {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.container {
|
||||
max-width: 640px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
max-width: 768px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.container {
|
||||
max-width: 1024px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.container {
|
||||
max-width: 1280px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
.container {
|
||||
max-width: 1536px;
|
||||
}
|
||||
}
|
||||
.mt-6 {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
.bg-black {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(0, 0, 0, var(--tw-bg-opacity));
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\:hover\:text-center:hover {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
5
jit/tests/import-syntax.test.html
Normal file
5
jit/tests/import-syntax.test.html
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<h1>Hello world!</h1>
|
||||
<div class="container"></div>
|
||||
<div class="mt-6"></div>
|
||||
<div class="bg-black"></div>
|
||||
<div class="md:hover:text-center"></div>
|
||||
38
jit/tests/import-syntax.test.js
Normal file
38
jit/tests/import-syntax.test.js
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('using @import instead of @tailwind', () => {
|
||||
let config = {
|
||||
purge: [path.resolve(__dirname, './import-syntax.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [
|
||||
function ({ addBase }) {
|
||||
addBase({
|
||||
h1: {
|
||||
fontSize: '32px',
|
||||
},
|
||||
})
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@import "tailwindcss/base";
|
||||
@import "tailwindcss/components";
|
||||
@import "tailwindcss/utilities";
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './import-syntax.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
85
jit/tests/important-boolean.test.css
Normal file
85
jit/tests/important-boolean.test.css
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
.container {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.container {
|
||||
max-width: 640px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
max-width: 768px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.container {
|
||||
max-width: 1024px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.container {
|
||||
max-width: 1280px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
.container {
|
||||
max-width: 1536px;
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
button: yes !important;
|
||||
}
|
||||
@font-face {
|
||||
font-family: Inter;
|
||||
}
|
||||
@page {
|
||||
margin: 1cm;
|
||||
}
|
||||
.custom-component {
|
||||
font-weight: 700;
|
||||
}
|
||||
.custom-important-component {
|
||||
text-align: center !important;
|
||||
}
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.animate-spin {
|
||||
animation: spin 1s linear infinite !important;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
.custom-util {
|
||||
button: no;
|
||||
}
|
||||
.group:hover .group-hover\:focus-within\:text-left:focus-within {
|
||||
text-align: left !important;
|
||||
}
|
||||
[dir='rtl'] .rtl\:active\:text-center:active {
|
||||
text-align: center !important;
|
||||
}
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.motion-safe\:hover\:text-center:hover {
|
||||
text-align: center !important;
|
||||
}
|
||||
}
|
||||
.dark .dark\:focus\:text-left:focus {
|
||||
text-align: left !important;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\:hover\:text-right:hover {
|
||||
text-align: right !important;
|
||||
}
|
||||
}
|
||||
12
jit/tests/important-boolean.test.html
Normal file
12
jit/tests/important-boolean.test.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<div class="container"></div>
|
||||
<div class="btn"></div>
|
||||
<div class="animate-spin"></div>
|
||||
<div class="custom-util"></div>
|
||||
<div class="custom-component"></div>
|
||||
<div class="custom-important-component"></div>
|
||||
<div class="font-bold"></div>
|
||||
<div class="md:hover:text-right"></div>
|
||||
<div class="motion-safe:hover:text-center"></div>
|
||||
<div class="dark:focus:text-left"></div>
|
||||
<div class="group-hover:focus-within:text-left"></div>
|
||||
<div class="rtl:active:text-center"></div>
|
||||
70
jit/tests/important-boolean.test.js
Normal file
70
jit/tests/important-boolean.test.js
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('important boolean', () => {
|
||||
let config = {
|
||||
important: true,
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './important-boolean.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [
|
||||
function ({ addComponents, addUtilities }) {
|
||||
addComponents(
|
||||
{
|
||||
'.btn': {
|
||||
button: 'yes',
|
||||
},
|
||||
},
|
||||
{ respectImportant: true }
|
||||
)
|
||||
addComponents(
|
||||
{
|
||||
'@font-face': {
|
||||
'font-family': 'Inter',
|
||||
},
|
||||
'@page': {
|
||||
margin: '1cm',
|
||||
},
|
||||
},
|
||||
{ respectImportant: true }
|
||||
)
|
||||
addUtilities(
|
||||
{
|
||||
'.custom-util': {
|
||||
button: 'no',
|
||||
},
|
||||
},
|
||||
{ respectImportant: false }
|
||||
)
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@layer components {
|
||||
.custom-component {
|
||||
@apply font-bold;
|
||||
}
|
||||
.custom-important-component {
|
||||
@apply text-center !important;
|
||||
}
|
||||
}
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './important-boolean.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
53
jit/tests/important-modifier-prefix.test.css
Normal file
53
jit/tests/important-modifier-prefix.test.css
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
.\!tw-container {
|
||||
width: 100% !important;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.\!tw-container {
|
||||
max-width: 640px !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.\!tw-container {
|
||||
max-width: 768px !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.\!tw-container {
|
||||
max-width: 1024px !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.\!tw-container {
|
||||
max-width: 1280px !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
.\!tw-container {
|
||||
max-width: 1536px !important;
|
||||
}
|
||||
}
|
||||
.\!tw-font-bold {
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
.hover\:\!tw-text-center:hover {
|
||||
text-align: center !important;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.lg\:\!tw-opacity-50 {
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.xl\:focus\:disabled\:\!tw-float-right:focus:disabled {
|
||||
float: right !important;
|
||||
}
|
||||
}
|
||||
5
jit/tests/important-modifier-prefix.test.html
Normal file
5
jit/tests/important-modifier-prefix.test.html
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<div class="!tw-container"></div>
|
||||
<div class="!tw-font-bold"></div>
|
||||
<div class="hover:!tw-text-center"></div>
|
||||
<div class="lg:!tw-opacity-50"></div>
|
||||
<div class="xl:focus:disabled:!tw-float-right"></div>
|
||||
33
jit/tests/important-modifier-prefix.test.js
Normal file
33
jit/tests/important-modifier-prefix.test.js
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('important modifier with prefix', () => {
|
||||
let config = {
|
||||
important: false,
|
||||
prefix: 'tw-',
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './important-modifier-prefix.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './important-modifier-prefix.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
53
jit/tests/important-modifier.test.css
Normal file
53
jit/tests/important-modifier.test.css
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
.\!container {
|
||||
width: 100% !important;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.\!container {
|
||||
max-width: 640px !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.\!container {
|
||||
max-width: 768px !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.\!container {
|
||||
max-width: 1024px !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.\!container {
|
||||
max-width: 1280px !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
.\!container {
|
||||
max-width: 1536px !important;
|
||||
}
|
||||
}
|
||||
.\!font-bold {
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
.hover\:\!text-center:hover {
|
||||
text-align: center !important;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.lg\:\!opacity-50 {
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.xl\:focus\:disabled\:\!float-right:focus:disabled {
|
||||
float: right !important;
|
||||
}
|
||||
}
|
||||
5
jit/tests/important-modifier.test.html
Normal file
5
jit/tests/important-modifier.test.html
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<div class="!container"></div>
|
||||
<div class="!font-bold"></div>
|
||||
<div class="hover:!text-center"></div>
|
||||
<div class="lg:!opacity-50"></div>
|
||||
<div class="xl:focus:disabled:!float-right"></div>
|
||||
32
jit/tests/important-modifier.test.js
Normal file
32
jit/tests/important-modifier.test.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('important modifier', () => {
|
||||
let config = {
|
||||
important: false,
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './important-modifier.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './important-modifier.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
85
jit/tests/important-selector.test.css
Normal file
85
jit/tests/important-selector.test.css
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
.container {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.container {
|
||||
max-width: 640px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
max-width: 768px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.container {
|
||||
max-width: 1024px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.container {
|
||||
max-width: 1280px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
.container {
|
||||
max-width: 1536px;
|
||||
}
|
||||
}
|
||||
#app .btn {
|
||||
button: yes;
|
||||
}
|
||||
@font-face {
|
||||
font-family: Inter;
|
||||
}
|
||||
@page {
|
||||
margin: 1cm;
|
||||
}
|
||||
.custom-component {
|
||||
font-weight: 700;
|
||||
}
|
||||
.custom-important-component {
|
||||
text-align: center !important;
|
||||
}
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
#app .animate-spin {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
#app .font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.custom-util {
|
||||
button: no;
|
||||
}
|
||||
#app .group:hover .group-hover\:focus-within\:text-left:focus-within {
|
||||
text-align: left;
|
||||
}
|
||||
#app [dir='rtl'] .rtl\:active\:text-center:active {
|
||||
text-align: center;
|
||||
}
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
#app .motion-safe\:hover\:text-center:hover {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
#app .dark .dark\:focus\:text-left:focus {
|
||||
text-align: left;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
#app .md\:hover\:text-right:hover {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
12
jit/tests/important-selector.test.html
Normal file
12
jit/tests/important-selector.test.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<div class="container"></div>
|
||||
<div class="btn"></div>
|
||||
<div class="animate-spin"></div>
|
||||
<div class="custom-util"></div>
|
||||
<div class="custom-component"></div>
|
||||
<div class="custom-important-component"></div>
|
||||
<div class="font-bold"></div>
|
||||
<div class="md:hover:text-right"></div>
|
||||
<div class="motion-safe:hover:text-center"></div>
|
||||
<div class="dark:focus:text-left"></div>
|
||||
<div class="group-hover:focus-within:text-left"></div>
|
||||
<div class="rtl:active:text-center"></div>
|
||||
70
jit/tests/important-selector.test.js
Normal file
70
jit/tests/important-selector.test.js
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('important selector', () => {
|
||||
let config = {
|
||||
important: '#app',
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './important-selector.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [
|
||||
function ({ addComponents, addUtilities }) {
|
||||
addComponents(
|
||||
{
|
||||
'.btn': {
|
||||
button: 'yes',
|
||||
},
|
||||
},
|
||||
{ respectImportant: true }
|
||||
)
|
||||
addComponents(
|
||||
{
|
||||
'@font-face': {
|
||||
'font-family': 'Inter',
|
||||
},
|
||||
'@page': {
|
||||
margin: '1cm',
|
||||
},
|
||||
},
|
||||
{ respectImportant: true }
|
||||
)
|
||||
addUtilities(
|
||||
{
|
||||
'.custom-util': {
|
||||
button: 'no',
|
||||
},
|
||||
},
|
||||
{ respectImportant: false }
|
||||
)
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@layer components {
|
||||
.custom-component {
|
||||
@apply font-bold;
|
||||
}
|
||||
.custom-important-component {
|
||||
@apply text-center !important;
|
||||
}
|
||||
}
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './important-selector.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
568
jit/tests/kitchen-sink.test.css
Normal file
568
jit/tests/kitchen-sink.test.css
Normal file
|
|
@ -0,0 +1,568 @@
|
|||
.theme-test {
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
||||
'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
color: #3b82f6;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.screen-test {
|
||||
color: purple;
|
||||
}
|
||||
}
|
||||
.apply-1 {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
.apply-2 {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
.apply-test {
|
||||
margin-top: 1.5rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(236, 72, 153, var(--tw-bg-opacity));
|
||||
}
|
||||
.apply-test:hover {
|
||||
font-weight: 700;
|
||||
}
|
||||
.apply-test:focus:hover {
|
||||
font-weight: 700;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.apply-test {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(16, 185, 129, var(--tw-bg-opacity));
|
||||
}
|
||||
.apply-test:focus:nth-child(even) {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(251, 207, 232, var(--tw-bg-opacity));
|
||||
}
|
||||
}
|
||||
.apply-components {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.apply-components {
|
||||
max-width: 640px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.apply-components {
|
||||
max-width: 768px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.apply-components {
|
||||
max-width: 1024px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.apply-components {
|
||||
max-width: 1280px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
.apply-components {
|
||||
max-width: 1536px;
|
||||
}
|
||||
}
|
||||
.apply-components {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.drop-empty-rules:hover {
|
||||
font-weight: 700;
|
||||
}
|
||||
.group:hover .apply-group {
|
||||
font-weight: 700;
|
||||
}
|
||||
.dark .apply-dark-mode {
|
||||
font-weight: 700;
|
||||
}
|
||||
.apply-with-existing:hover {
|
||||
font-weight: 400;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.apply-with-existing:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(16, 185, 129, var(--tw-bg-opacity));
|
||||
}
|
||||
}
|
||||
.multiple,
|
||||
.selectors {
|
||||
font-weight: 700;
|
||||
}
|
||||
.group:hover .multiple,
|
||||
.group:hover .selectors {
|
||||
font-weight: 400;
|
||||
}
|
||||
.list > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-x-reverse: 0;
|
||||
margin-right: calc(1rem * var(--tw-space-x-reverse));
|
||||
margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
|
||||
}
|
||||
.nested {
|
||||
.example {
|
||||
font-weight: 700;
|
||||
}
|
||||
.example:hover {
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
.apply-order-a {
|
||||
margin: 1.25rem;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
.apply-order-b {
|
||||
margin: 1.25rem;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
.dark .group:hover .apply-dark-group-example-a {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(16, 185, 129, var(--tw-bg-opacity));
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.group:active .crazy-example:focus {
|
||||
opacity: 0.1;
|
||||
}
|
||||
}
|
||||
}
|
||||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
h1:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
div {
|
||||
background: #654321;
|
||||
}
|
||||
.container {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.container {
|
||||
max-width: 640px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
max-width: 768px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.container {
|
||||
max-width: 1024px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.container {
|
||||
max-width: 1280px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
.container {
|
||||
max-width: 1536px;
|
||||
}
|
||||
}
|
||||
.aspect-w-1,
|
||||
.aspect-w-2,
|
||||
.aspect-w-3,
|
||||
.aspect-w-4,
|
||||
.aspect-w-5,
|
||||
.aspect-w-6,
|
||||
.aspect-w-7,
|
||||
.aspect-w-8,
|
||||
.aspect-w-9,
|
||||
.aspect-w-10,
|
||||
.aspect-w-11,
|
||||
.aspect-w-12,
|
||||
.aspect-w-13,
|
||||
.aspect-w-14,
|
||||
.aspect-w-15,
|
||||
.aspect-w-16 {
|
||||
position: relative;
|
||||
padding-bottom: calc(var(--tw-aspect-h) / var(--tw-aspect-w) * 100%);
|
||||
}
|
||||
.aspect-w-1 > *,
|
||||
.aspect-w-2 > *,
|
||||
.aspect-w-3 > *,
|
||||
.aspect-w-4 > *,
|
||||
.aspect-w-5 > *,
|
||||
.aspect-w-6 > *,
|
||||
.aspect-w-7 > *,
|
||||
.aspect-w-8 > *,
|
||||
.aspect-w-9 > *,
|
||||
.aspect-w-10 > *,
|
||||
.aspect-w-11 > *,
|
||||
.aspect-w-12 > *,
|
||||
.aspect-w-13 > *,
|
||||
.aspect-w-14 > *,
|
||||
.aspect-w-15 > *,
|
||||
.aspect-w-16 > * {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
.aspect-w-1 {
|
||||
--tw-aspect-w: 1;
|
||||
}
|
||||
.aspect-w-3 {
|
||||
--tw-aspect-w: 3;
|
||||
}
|
||||
.aspect-h-2 {
|
||||
--tw-aspect-h: 2;
|
||||
}
|
||||
.aspect-h-4 {
|
||||
--tw-aspect-h: 4;
|
||||
}
|
||||
.test-apply-font-variant {
|
||||
--tw-ordinal: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-slashed-zero: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-figure: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-spacing: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-fraction: var(--tw-empty, /*!*/ /*!*/);
|
||||
font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure)
|
||||
var(--tw-numeric-spacing) var(--tw-numeric-fraction);
|
||||
--tw-ordinal: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-slashed-zero: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-figure: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-spacing: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-fraction: var(--tw-empty, /*!*/ /*!*/);
|
||||
font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure)
|
||||
var(--tw-numeric-spacing) var(--tw-numeric-fraction);
|
||||
--tw-ordinal: ordinal;
|
||||
--tw-numeric-spacing: tabular-nums;
|
||||
}
|
||||
.custom-component {
|
||||
background: #123456;
|
||||
}
|
||||
* {
|
||||
padding: 5px;
|
||||
}
|
||||
.foo .bg-black {
|
||||
appearance: none;
|
||||
}
|
||||
.mt-6 {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
.transform {
|
||||
--tw-translate-x: 0;
|
||||
--tw-translate-y: 0;
|
||||
--tw-rotate: 0;
|
||||
--tw-skew-x: 0;
|
||||
--tw-skew-y: 0;
|
||||
--tw-scale-x: 1;
|
||||
--tw-scale-y: 1;
|
||||
transform: translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y))
|
||||
rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
|
||||
scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
.scale-50 {
|
||||
--tw-scale-x: 0.5;
|
||||
--tw-scale-y: 0.5;
|
||||
}
|
||||
.grid-cols-\[200px\2c repeat\(auto-fill\2c minmax\(15\%\2c 100px\)\)\2c 300px\] {
|
||||
grid-template-columns: 200px repeat(auto-fill, minmax(15%, 100px)) 300px;
|
||||
}
|
||||
.bg-black {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(0, 0, 0, var(--tw-bg-opacity));
|
||||
}
|
||||
.bg-green-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(16, 185, 129, var(--tw-bg-opacity));
|
||||
}
|
||||
.bg-opacity-50 {
|
||||
--tw-bg-opacity: 0.5;
|
||||
}
|
||||
.bg-gradient-to-r {
|
||||
background-image: linear-gradient(to right, var(--tw-gradient-stops));
|
||||
}
|
||||
.bg-hero--home-1 {
|
||||
background-image: url('/images/homepage-1.jpg');
|
||||
}
|
||||
.from-foo {
|
||||
--tw-gradient-from: #bada55;
|
||||
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgba(186, 218, 85, 0));
|
||||
}
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
.font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
.shadow-sm {
|
||||
--tw-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.filter-none {
|
||||
filter: none;
|
||||
}
|
||||
.filter-grayscale {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
.custom-util {
|
||||
background: #abcdef;
|
||||
}
|
||||
* {
|
||||
margin: 10px;
|
||||
}
|
||||
.first\:pt-0:first-child {
|
||||
padding-top: 0px;
|
||||
}
|
||||
.hover\:container:hover {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.hover\:container:hover {
|
||||
max-width: 640px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.hover\:container:hover {
|
||||
max-width: 768px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.hover\:container:hover {
|
||||
max-width: 1024px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.hover\:container:hover {
|
||||
max-width: 1280px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
.hover\:container:hover {
|
||||
max-width: 1536px;
|
||||
}
|
||||
}
|
||||
.hover\:scale-75:hover {
|
||||
--tw-scale-x: 0.75;
|
||||
--tw-scale-y: 0.75;
|
||||
}
|
||||
.hover\:font-bold:hover {
|
||||
font-weight: 700;
|
||||
}
|
||||
.hover\:shadow-lg:hover {
|
||||
--tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.hover\:custom-util:hover {
|
||||
background: #abcdef;
|
||||
}
|
||||
.focus\:font-normal:focus {
|
||||
font-weight: 400;
|
||||
}
|
||||
.focus\:ring-2:focus {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
||||
var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width))
|
||||
var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
}
|
||||
.focus\:ring-blue-500:focus {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgba(59, 130, 246, var(--tw-ring-opacity));
|
||||
}
|
||||
.focus\:hover\:font-light:focus:hover {
|
||||
font-weight: 300;
|
||||
}
|
||||
.disabled\:font-bold:disabled {
|
||||
font-weight: 700;
|
||||
}
|
||||
.group:hover .group-hover\:opacity-100 {
|
||||
opacity: 1;
|
||||
}
|
||||
.group:hover .group-hover\:custom-util {
|
||||
background: #abcdef;
|
||||
}
|
||||
.group:active .group-active\:opacity-10 {
|
||||
opacity: 0.1;
|
||||
}
|
||||
.foo\:custom-util {
|
||||
background: #abcdef !important;
|
||||
}
|
||||
.foo\:hover\:custom-util:hover {
|
||||
background: #abcdef !important;
|
||||
}
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.motion-safe\:transition {
|
||||
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow,
|
||||
transform;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
.motion-safe\:custom-util {
|
||||
background: #abcdef;
|
||||
}
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.motion-reduce\:transition {
|
||||
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow,
|
||||
transform;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
}
|
||||
.dark .dark\:custom-util {
|
||||
background: #abcdef;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.sm\:container {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.sm\:container {
|
||||
max-width: 640px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.sm\:container {
|
||||
max-width: 768px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.sm\:container {
|
||||
max-width: 1024px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.sm\:container {
|
||||
max-width: 1280px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
.sm\:container {
|
||||
max-width: 1536px;
|
||||
}
|
||||
}
|
||||
.sm\:text-center {
|
||||
text-align: center;
|
||||
}
|
||||
.sm\:ordinal,
|
||||
.sm\:slashed-zero,
|
||||
.sm\:lining-nums,
|
||||
.sm\:oldstyle-nums,
|
||||
.sm\:proportional-nums,
|
||||
.sm\:tabular-nums,
|
||||
.sm\:diagonal-fractions,
|
||||
.sm\:stacked-fractions {
|
||||
--tw-ordinal: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-slashed-zero: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-figure: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-spacing: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-numeric-fraction: var(--tw-empty, /*!*/ /*!*/);
|
||||
font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure)
|
||||
var(--tw-numeric-spacing) var(--tw-numeric-fraction);
|
||||
}
|
||||
.sm\:tabular-nums {
|
||||
--tw-numeric-spacing: tabular-nums;
|
||||
}
|
||||
.sm\:custom-util {
|
||||
background: #abcdef;
|
||||
}
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.group:active .sm\:motion-safe\:group-active\:focus\:opacity-10:focus {
|
||||
opacity: 0.1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\:container {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.md\:container {
|
||||
max-width: 640px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\:container {
|
||||
max-width: 768px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.md\:container {
|
||||
max-width: 1024px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.md\:container {
|
||||
max-width: 1280px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
.md\:container {
|
||||
max-width: 1536px;
|
||||
}
|
||||
}
|
||||
.md\:text-center {
|
||||
text-align: center;
|
||||
}
|
||||
.md\:opacity-50 {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.md\:shadow-sm {
|
||||
--tw-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.md\:hover\:opacity-20:hover {
|
||||
opacity: 0.2;
|
||||
}
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.md\:motion-safe\:hover\:transition:hover {
|
||||
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow,
|
||||
transform;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
}
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.dark .md\:dark\:motion-safe\:foo\:active\:custom-util:active {
|
||||
background: #abcdef !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.md\:sm\:text-center {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (orientation: portrait) {
|
||||
.portrait\:text-center {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) and (max-width: 1535px) {
|
||||
.range\:text-right {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
@media (min-width: 640px) and (max-width: 767px), (max-width: 868px) {
|
||||
.multi\:text-left {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
76
jit/tests/kitchen-sink.test.html
Normal file
76
jit/tests/kitchen-sink.test.html
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Title</title>
|
||||
<link rel="stylesheet" href="./tailwind.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="portrait:text-center range:text-right multi:text-left"></div>
|
||||
<div
|
||||
class="container hover:container sm:container md:container text-center sm:text-center md:text-center"
|
||||
></div>
|
||||
<div class="grid-cols-[200px,repeat(auto-fill,minmax(15%,100px)),300px]"></div>
|
||||
<div class="test-apply-font-variant"></div>
|
||||
<div class="mt-6"></div>
|
||||
<div class="bg-black"></div>
|
||||
<div class="custom-util"></div>
|
||||
<div class="hover:custom-util"></div>
|
||||
<div class="group-hover:custom-util"></div>
|
||||
<div class="foo:custom-util"></div>
|
||||
<div class="foo:hover:custom-util"></div>
|
||||
<div class="sm:custom-util"></div>
|
||||
<div class="dark:custom-util"></div>
|
||||
<div class="motion-safe:custom-util"></div>
|
||||
<div class="md:dark:motion-safe:foo:active:custom-util"></div>
|
||||
<div class="aspect-w-1 aspect-h-2"></div>
|
||||
<div class="aspect-w-3 aspect-h-4"></div>
|
||||
<div class="filter-none filter-grayscale"></div>
|
||||
<div class="focus:font-normal"></div>
|
||||
<div class="font-medium"></div>
|
||||
<div class="bg-gradient-to-r from-foo"></div>
|
||||
<div class="custom-component custom-util"></div>
|
||||
<div class="bg-opacity-50"></div>
|
||||
<div class="focus:ring-2 focus:ring-blue-500"></div>
|
||||
<div class="hover:font-bold"></div>
|
||||
<div class="disabled:font-bold"></div>
|
||||
<div class="focus:hover:font-light"></div>
|
||||
<div class="first:pt-0"></div>
|
||||
<div class="container"></div>
|
||||
<div class="bg-hero--home-1"></div>
|
||||
<div class="group-hover:opacity-100"></div>
|
||||
<div class="group-active:opacity-10"></div>
|
||||
<div class="sm:motion-safe:group-active:focus:opacity-10"></div>
|
||||
<div class="motion-safe:transition"></div>
|
||||
<div class="motion-reduce:transition"></div>
|
||||
<div class="md:motion-safe:hover:transition"></div>
|
||||
<div class="md:sm:text-center shadow-sm md:shadow-sm"></div>
|
||||
<div class="md:sm:text-center shadow-sm md:shadow-sm"></div>
|
||||
<div class="bg-green-500 md:opacity-50 md:hover:opacity-20 sm:tabular-nums"></div>
|
||||
<div class="text-center shadow-md hover:shadow-lg transform scale-50 hover:scale-75"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<script>
|
||||
defineComponent({
|
||||
name: 'HelloWorld',
|
||||
props: {
|
||||
msg: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
things: Array /* PropType<string[]> */,
|
||||
},
|
||||
setup: () => {
|
||||
const count = ref(0)
|
||||
// Weird regex-looking stuff that once caused a stack overflow in candidatePermutations
|
||||
const pattern = ' ]-[] '
|
||||
return {
|
||||
count,
|
||||
stuff: [] /* string[] | undefined */,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
166
jit/tests/kitchen-sink.test.js
Normal file
166
jit/tests/kitchen-sink.test.js
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('it works', () => {
|
||||
let config = {
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './kitchen-sink.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {
|
||||
extend: {
|
||||
screens: {
|
||||
portrait: { raw: '(orientation: portrait)' },
|
||||
range: { min: '1280px', max: '1535px' },
|
||||
multi: [{ min: '640px', max: '767px' }, { max: '868px' }],
|
||||
},
|
||||
gradientColorStops: {
|
||||
foo: '#bada55',
|
||||
},
|
||||
backgroundImage: {
|
||||
'hero--home-1': "url('/images/homepage-1.jpg')",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
require('@tailwindcss/aspect-ratio'),
|
||||
function ({ addVariant }) {
|
||||
addVariant(
|
||||
'foo',
|
||||
({ container }) => {
|
||||
container.walkRules((rule) => {
|
||||
rule.selector = `.foo\\:${rule.selector.slice(1)}`
|
||||
rule.walkDecls((decl) => {
|
||||
decl.important = true
|
||||
})
|
||||
})
|
||||
},
|
||||
{ before: 'sm' }
|
||||
)
|
||||
},
|
||||
function ({ addUtilities, addBase, theme }) {
|
||||
addBase({
|
||||
h1: {
|
||||
fontSize: theme('fontSize.2xl'),
|
||||
fontWeight: theme('fontWeight.bold'),
|
||||
'&:first-child': {
|
||||
marginTop: '0px',
|
||||
},
|
||||
},
|
||||
})
|
||||
addUtilities(
|
||||
{
|
||||
'.filter-none': {
|
||||
filter: 'none',
|
||||
},
|
||||
'.filter-grayscale': {
|
||||
filter: 'grayscale(100%)',
|
||||
},
|
||||
},
|
||||
['responsive', 'hover']
|
||||
)
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@layer utilities {
|
||||
.custom-util {
|
||||
background: #abcdef;
|
||||
}
|
||||
* {
|
||||
margin: 10px;
|
||||
}
|
||||
}
|
||||
@layer components {
|
||||
.test-apply-font-variant {
|
||||
@apply ordinal tabular-nums;
|
||||
}
|
||||
.custom-component {
|
||||
background: #123456;
|
||||
}
|
||||
* {
|
||||
padding: 5px;
|
||||
}
|
||||
.foo .bg-black {
|
||||
appearance: none;
|
||||
}
|
||||
}
|
||||
@layer base {
|
||||
div {
|
||||
background: #654321;
|
||||
}
|
||||
}
|
||||
.theme-test {
|
||||
font-family: theme('fontFamily.sans');
|
||||
color: theme('colors.blue.500');
|
||||
}
|
||||
@screen lg {
|
||||
.screen-test {
|
||||
color: purple;
|
||||
}
|
||||
}
|
||||
.apply-1 {
|
||||
@apply mt-6;
|
||||
}
|
||||
.apply-2 {
|
||||
@apply mt-6;
|
||||
}
|
||||
.apply-test {
|
||||
@apply mt-6 bg-pink-500 hover:font-bold focus:hover:font-bold sm:bg-green-500 sm:focus:even:bg-pink-200;
|
||||
}
|
||||
.apply-components {
|
||||
@apply container mx-auto;
|
||||
}
|
||||
.drop-empty-rules {
|
||||
@apply hover:font-bold;
|
||||
}
|
||||
.apply-group {
|
||||
@apply group-hover:font-bold;
|
||||
}
|
||||
.apply-dark-mode {
|
||||
@apply dark:font-bold;
|
||||
}
|
||||
.apply-with-existing:hover {
|
||||
@apply font-normal sm:bg-green-500;
|
||||
}
|
||||
.multiple, .selectors {
|
||||
@apply font-bold group-hover:font-normal;
|
||||
}
|
||||
.list {
|
||||
@apply space-x-4;
|
||||
}
|
||||
.nested {
|
||||
.example {
|
||||
@apply font-bold hover:font-normal;
|
||||
}
|
||||
}
|
||||
.apply-order-a {
|
||||
@apply m-5 mt-6;
|
||||
}
|
||||
.apply-order-b {
|
||||
@apply mt-6 m-5;
|
||||
}
|
||||
.apply-dark-group-example-a {
|
||||
@apply dark:group-hover:bg-green-500;
|
||||
}
|
||||
.crazy-example {
|
||||
@apply sm:motion-safe:group-active:focus:opacity-10;
|
||||
}
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './kitchen-sink.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
33
jit/tests/modify-selectors.test.css
Normal file
33
jit/tests/modify-selectors.test.css
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
.markdown > p {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.foo .foo\:markdown > p {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.foo .foo\:font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.foo .foo\:visited\:markdown:visited > p {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.foo .foo\:hover\:font-bold:hover {
|
||||
font-weight: 700;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.foo .sm\:foo\:font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.foo .md\:foo\:focus\:font-bold:focus {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.foo .lg\:foo\:disabled\:markdown:disabled > p {
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
17
jit/tests/modify-selectors.test.html
Normal file
17
jit/tests/modify-selectors.test.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<div class="font-bold"></div>
|
||||
<div class="foo:font-bold"></div>
|
||||
<div class="foo:hover:font-bold"></div>
|
||||
<div class="sm:foo:font-bold"></div>
|
||||
<div class="md:foo:focus:font-bold"></div>
|
||||
<div class="markdown">
|
||||
<p>Lorem ipsum dolor sit amet...</p>
|
||||
</div>
|
||||
<div class="foo:markdown">
|
||||
<p>Lorem ipsum dolor sit amet...</p>
|
||||
</div>
|
||||
<div class="foo:visited:markdown">
|
||||
<p>Lorem ipsum dolor sit amet...</p>
|
||||
</div>
|
||||
<div class="lg:foo:disabled:markdown">
|
||||
<p>Lorem ipsum dolor sit amet...</p>
|
||||
</div>
|
||||
50
jit/tests/modify-selectors.test.js
Normal file
50
jit/tests/modify-selectors.test.js
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const selectorParser = require('postcss-selector-parser')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('modify selectors', () => {
|
||||
let config = {
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './modify-selectors.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [
|
||||
function ({ addVariant, e }) {
|
||||
addVariant('foo', ({ modifySelectors, separator }) => {
|
||||
modifySelectors(({ selector }) => {
|
||||
return selectorParser((selectors) => {
|
||||
selectors.walkClasses((classNode) => {
|
||||
classNode.value = `foo${separator}${classNode.value}`
|
||||
classNode.parent.insertBefore(classNode, selectorParser().astSync(`.foo `))
|
||||
})
|
||||
}).processSync(selector)
|
||||
})
|
||||
})
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.markdown > p {
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './modify-selectors.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
3
jit/tests/mutable.test.css
Normal file
3
jit/tests/mutable.test.css
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
.bg-foo {
|
||||
background-image: url("./foo.png");
|
||||
}
|
||||
13
jit/tests/mutable.test.html
Normal file
13
jit/tests/mutable.test.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Title</title>
|
||||
<link rel="stylesheet" href="./tailwind.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="bg-foo"></div>
|
||||
</body>
|
||||
</html>
|
||||
55
jit/tests/mutable.test.js
Normal file
55
jit/tests/mutable.test.js
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function pluginThatMutatesRules() {
|
||||
return (root) => {
|
||||
root.walkRules((rule) => {
|
||||
rule.nodes
|
||||
.filter((node) => node.prop === 'background-image')
|
||||
.forEach((node) => {
|
||||
node.value = 'url("./bar.png")'
|
||||
})
|
||||
|
||||
return rule
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test.only('plugins mutating rules after tailwind doesnt break it', async () => {
|
||||
let config = {
|
||||
purge: [path.resolve(__dirname, './mutable.test.html')],
|
||||
theme: {
|
||||
backgroundImage: {
|
||||
foo: 'url("./foo.png")',
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `@tailwind utilities;`
|
||||
|
||||
function checkResult(result) {
|
||||
let expectedPath = path.resolve(__dirname, './mutable.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
}
|
||||
|
||||
// Verify the first run produces the expected result
|
||||
let firstRun = await run(css, config)
|
||||
checkResult(firstRun)
|
||||
|
||||
// Outside of the context of tailwind jit more postcss plugins may operate on the AST:
|
||||
// In this case we have a plugin that mutates rules directly
|
||||
await postcss([pluginThatMutatesRules()]).process(firstRun, { from: path.resolve(__filename) })
|
||||
|
||||
// Verify subsequent runs don't produce mutated rules
|
||||
let secondRun = await run(css, config)
|
||||
checkResult(secondRun)
|
||||
})
|
||||
9
jit/tests/prefix.fn.test.css
Normal file
9
jit/tests/prefix.fn.test.css
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
.tw-ml-1 {
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
.tw-align-bottom {
|
||||
vertical-align: bottom
|
||||
}
|
||||
3
jit/tests/prefix.fn.test.html
Normal file
3
jit/tests/prefix.fn.test.html
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<div class="flex"></div>
|
||||
<div class="tw-align-bottom"></div>
|
||||
<div class="tw-ml-1"></div>
|
||||
34
jit/tests/prefix.fn.test.js
Normal file
34
jit/tests/prefix.fn.test.js
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('prefix fn', () => {
|
||||
let config = {
|
||||
prefix(selector) {
|
||||
if (['.align-bottom', '.ml'].some((prefix) => selector.startsWith(prefix))) {
|
||||
return 'tw-'
|
||||
}
|
||||
|
||||
return ''
|
||||
},
|
||||
purge: [path.resolve(__dirname, './prefix.fn.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './prefix.fn.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
86
jit/tests/prefix.test.css
Normal file
86
jit/tests/prefix.test.css
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
.tw-container {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.tw-container {
|
||||
max-width: 640px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.tw-container {
|
||||
max-width: 768px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.tw-container {
|
||||
max-width: 1024px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.tw-container {
|
||||
max-width: 1280px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
.tw-container {
|
||||
max-width: 1536px;
|
||||
}
|
||||
}
|
||||
.tw-btn-prefix {
|
||||
button: yes;
|
||||
}
|
||||
.btn-no-prefix {
|
||||
button: yes;
|
||||
}
|
||||
.custom-component {
|
||||
font-weight: 700;
|
||||
}
|
||||
.tw-dark .tw-group:hover .custom-component {
|
||||
font-weight: 400;
|
||||
}
|
||||
.tw--ml-4 {
|
||||
margin-left: -1rem;
|
||||
}
|
||||
.tw-font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.tw-custom-util-prefix {
|
||||
button: no;
|
||||
}
|
||||
.custom-util-no-prefix {
|
||||
button: no;
|
||||
}
|
||||
.tw-group:hover .group-hover\:focus-within\:tw-text-left:focus-within {
|
||||
text-align: left;
|
||||
}
|
||||
[dir='rtl'] .rtl\:active\:tw-text-center:active {
|
||||
text-align: center;
|
||||
}
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.motion-safe\:hover\:tw-text-center:hover {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.tw-dark .dark\:focus\:tw-text-left:focus {
|
||||
text-align: left;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\:tw--ml-5 {
|
||||
margin-left: -1.25rem;
|
||||
}
|
||||
.md\:hover\:tw--ml-6:hover {
|
||||
margin-left: -1.5rem;
|
||||
}
|
||||
.md\:hover\:tw-text-right:hover {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
17
jit/tests/prefix.test.html
Normal file
17
jit/tests/prefix.test.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<div class="tw--ml-4"></div>
|
||||
<div class="md:tw--ml-5"></div>
|
||||
<div class="md:hover:tw--ml-6"></div>
|
||||
<div class="tw-container"></div>
|
||||
<div class="btn-no-prefix"></div>
|
||||
<div class="tw-btn-prefix"></div>
|
||||
<div class="tw-custom-util-prefix"></div>
|
||||
<div class="custom-util-no-prefix"></div>
|
||||
<div class="custom-component"></div>
|
||||
<div class="tw-custom-component-prefix"></div>
|
||||
<div class="custom-component-no-prefix"></div>
|
||||
<div class="tw-font-bold"></div>
|
||||
<div class="md:hover:tw-text-right"></div>
|
||||
<div class="motion-safe:hover:tw-text-center"></div>
|
||||
<div class="dark:focus:tw-text-left"></div>
|
||||
<div class="group-hover:focus-within:tw-text-left"></div>
|
||||
<div class="rtl:active:tw-text-center"></div>
|
||||
71
jit/tests/prefix.test.js
Normal file
71
jit/tests/prefix.test.js
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('prefix', () => {
|
||||
let config = {
|
||||
prefix: 'tw-',
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './prefix.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [
|
||||
function ({ addComponents, addUtilities }) {
|
||||
addComponents({
|
||||
'.btn-prefix': {
|
||||
button: 'yes',
|
||||
},
|
||||
})
|
||||
addComponents(
|
||||
{
|
||||
'.btn-no-prefix': {
|
||||
button: 'yes',
|
||||
},
|
||||
},
|
||||
{ respectPrefix: false }
|
||||
)
|
||||
addUtilities({
|
||||
'.custom-util-prefix': {
|
||||
button: 'no',
|
||||
},
|
||||
})
|
||||
addUtilities(
|
||||
{
|
||||
'.custom-util-no-prefix': {
|
||||
button: 'no',
|
||||
},
|
||||
},
|
||||
{ respectPrefix: false }
|
||||
)
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@layer components {
|
||||
.custom-component {
|
||||
@apply tw-font-bold dark:group-hover:tw-font-normal;
|
||||
}
|
||||
}
|
||||
@tailwind utilities;
|
||||
@layer utilites {
|
||||
.custom-utility {
|
||||
foo: bar;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './prefix.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
65
jit/tests/responsive-and-variants-atrules.test.css
Normal file
65
jit/tests/responsive-and-variants-atrules.test.css
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
.responsive-in-components {
|
||||
color: blue;
|
||||
}
|
||||
.variants-in-components {
|
||||
color: red;
|
||||
}
|
||||
.both-in-components {
|
||||
color: green;
|
||||
}
|
||||
.responsive-in-utilities {
|
||||
color: blue;
|
||||
}
|
||||
.variants-in-utilities {
|
||||
color: red;
|
||||
}
|
||||
.both-in-utilities {
|
||||
color: green;
|
||||
}
|
||||
.responsive-at-root {
|
||||
color: white;
|
||||
}
|
||||
.variants-at-root {
|
||||
color: orange;
|
||||
}
|
||||
.both-at-root {
|
||||
color: pink;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\:focus\:responsive-in-components:focus {
|
||||
color: blue;
|
||||
}
|
||||
.md\:focus\:variants-in-components:focus {
|
||||
color: red;
|
||||
}
|
||||
.md\:focus\:both-in-components:focus {
|
||||
color: green;
|
||||
}
|
||||
.md\:focus\:responsive-in-utilities:focus {
|
||||
color: blue;
|
||||
}
|
||||
.md\:focus\:variants-in-utilities:focus {
|
||||
color: red;
|
||||
}
|
||||
.md\:focus\:both-in-utilities:focus {
|
||||
color: green;
|
||||
}
|
||||
.md\:focus\:responsive-at-root:focus {
|
||||
color: white;
|
||||
}
|
||||
.md\:focus\:variants-at-root:focus {
|
||||
color: orange;
|
||||
}
|
||||
.md\:focus\:both-at-root:focus {
|
||||
color: pink;
|
||||
}
|
||||
}
|
||||
18
jit/tests/responsive-and-variants-atrules.test.html
Normal file
18
jit/tests/responsive-and-variants-atrules.test.html
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<div class="responsive-in-utilities"></div>
|
||||
<div class="variants-in-utilities"></div>
|
||||
<div class="both-in-utilities"></div>
|
||||
<div class="responsive-at-root"></div>
|
||||
<div class="variants-at-root"></div>
|
||||
<div class="both-at-root"></div>
|
||||
<div class="responsive-in-components"></div>
|
||||
<div class="variants-in-components"></div>
|
||||
<div class="both-in-components"></div>
|
||||
<div class="md:focus:responsive-in-utilities"></div>
|
||||
<div class="md:focus:variants-in-utilities"></div>
|
||||
<div class="md:focus:both-in-utilities"></div>
|
||||
<div class="md:focus:responsive-at-root"></div>
|
||||
<div class="md:focus:variants-at-root"></div>
|
||||
<div class="md:focus:both-at-root"></div>
|
||||
<div class="md:focus:responsive-in-components"></div>
|
||||
<div class="md:focus:variants-in-components"></div>
|
||||
<div class="md:focus:both-in-components"></div>
|
||||
88
jit/tests/responsive-and-variants-atrules.test.js
Normal file
88
jit/tests/responsive-and-variants-atrules.test.js
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('responsive and variants atrules', () => {
|
||||
let config = {
|
||||
purge: [path.resolve(__dirname, './responsive-and-variants-atrules.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer utilities {
|
||||
@responsive {
|
||||
.responsive-in-utilities {
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
@variants {
|
||||
.variants-in-utilities {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
@responsive {
|
||||
@variants {
|
||||
.both-in-utilities {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@responsive {
|
||||
.responsive-at-root {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
@variants {
|
||||
.variants-at-root {
|
||||
color: orange;
|
||||
}
|
||||
}
|
||||
@responsive {
|
||||
@variants {
|
||||
.both-at-root {
|
||||
color: pink;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
@responsive {
|
||||
.responsive-in-components {
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
@variants {
|
||||
.variants-in-components {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
@responsive {
|
||||
@variants {
|
||||
.both-in-components {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './responsive-and-variants-atrules.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
15
jit/tests/svelte-syntax.test.css
Normal file
15
jit/tests/svelte-syntax.test.css
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.lg\:hover\:bg-blue-500:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(59, 130, 246, var(--tw-bg-opacity));
|
||||
}
|
||||
}
|
||||
30
jit/tests/svelte-syntax.test.js
Normal file
30
jit/tests/svelte-syntax.test.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('basic usage', () => {
|
||||
let config = {
|
||||
purge: [path.resolve(__dirname, './svelte-syntax.test.svelte')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './svelte-syntax.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
5
jit/tests/svelte-syntax.test.svelte
Normal file
5
jit/tests/svelte-syntax.test.svelte
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<script>
|
||||
let current = 'foo'
|
||||
</script>
|
||||
|
||||
<button class:lg:hover:bg-blue-500={current === 'foo'}>Click me</button>
|
||||
225
jit/tests/variants.test.css
Normal file
225
jit/tests/variants.test.css
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
* {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-ring-shadow: 0 0 #0000;
|
||||
}
|
||||
.shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.first\:shadow-md:first-child {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.last\:shadow-md:last-child {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.odd\:shadow-md:nth-child(odd) {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.even\:shadow-md:nth-child(even) {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.visited\:shadow-md:visited {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.checked\:shadow-md:checked {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.focus-within\:shadow-md:focus-within {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.hover\:shadow-md:hover {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.focus\:shadow-md:focus {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.focus\:hover\:shadow-md:focus:hover {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.focus-visible\:shadow-md:focus-visible {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.active\:shadow-md:active {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.disabled\:shadow-md:disabled {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.group:first-child .group-first\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.group:last-child .group-last\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.group:nth-child(odd) .group-odd\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.group:nth-child(even) .group-even\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.group:visited .group-visited\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.group:checked .group-checked\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.group:focus-within .group-focus-within\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.group:hover .group-hover\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.group:focus .group-focus\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.group:focus-visible .group-focus-visible\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.group:active .group-active\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.group:disabled .group-disabled\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
[dir='ltr'] .ltr\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
[dir='rtl'] .rtl\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.motion-safe\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.motion-reduce\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
}
|
||||
.dark .dark\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.sm\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.sm\:active\:shadow-md:active {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.group:focus .md\:group-focus\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.lg\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
.dark .lg\:dark\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.xl\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
.\32xl\:shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.dark .\32xl\:dark\:motion-safe\:focus-within\:shadow-md:focus-within {
|
||||
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
}
|
||||
}
|
||||
68
jit/tests/variants.test.html
Normal file
68
jit/tests/variants.test.html
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Title</title>
|
||||
<link rel="stylesheet" href="./tailwind.css" />
|
||||
</head>
|
||||
<body>
|
||||
<!-- Basic pseudo variants -->
|
||||
<div class="shadow-md"></div>
|
||||
<div class="hover:shadow-md"></div>
|
||||
<div class="focus:shadow-md"></div>
|
||||
<div class="disabled:shadow-md"></div>
|
||||
<div class="active:shadow-md"></div>
|
||||
<div class="first:shadow-md"></div>
|
||||
<div class="last:shadow-md"></div>
|
||||
<div class="even:shadow-md"></div>
|
||||
<div class="odd:shadow-md"></div>
|
||||
<div class="visited:shadow-md"></div>
|
||||
<div class="checked:shadow-md"></div>
|
||||
<div class="focus-within:shadow-md"></div>
|
||||
<div class="focus-visible:shadow-md"></div>
|
||||
|
||||
<!-- Group variants -->
|
||||
<div class="group-hover:shadow-md"></div>
|
||||
<div class="group-focus:shadow-md"></div>
|
||||
<div class="group-disabled:shadow-md"></div>
|
||||
<div class="group-active:shadow-md"></div>
|
||||
<div class="group-first:shadow-md"></div>
|
||||
<div class="group-last:shadow-md"></div>
|
||||
<div class="group-even:shadow-md"></div>
|
||||
<div class="group-odd:shadow-md"></div>
|
||||
<div class="group-odd:shadow-md"></div>
|
||||
<div class="group-visited:shadow-md"></div>
|
||||
<div class="group-checked:shadow-md"></div>
|
||||
<div class="group-focus-within:shadow-md"></div>
|
||||
<div class="group-focus-visible:shadow-md"></div>
|
||||
<div class="group-focus-visible:shadow-md"></div>
|
||||
|
||||
<!-- Reduced motion variants -->
|
||||
<div class="motion-safe:shadow-md"></div>
|
||||
<div class="motion-reduce:shadow-md"></div>
|
||||
|
||||
<!-- Direction variants -->
|
||||
<div class="rtl:shadow-md"></div>
|
||||
<div class="ltr:shadow-md"></div>
|
||||
|
||||
<!-- Dark mode variants -->
|
||||
<div class="dark:shadow-md"></div>
|
||||
|
||||
<!-- Screen variants -->
|
||||
<div class="sm:shadow-md"></div>
|
||||
<div class="md:shadow-md"></div>
|
||||
<div class="lg:shadow-md"></div>
|
||||
<div class="xl:shadow-md"></div>
|
||||
<div class="2xl:shadow-md"></div>
|
||||
|
||||
<!-- Stacked variants -->
|
||||
<div class="focus:hover:shadow-md"></div>
|
||||
<div class="sm:active:shadow-md"></div>
|
||||
<div class="md:group-focus:shadow-md"></div>
|
||||
<div class="lg:dark:shadow-md"></div>
|
||||
<div class="xl:dark:disabledshadow-md"></div>
|
||||
<div class="2xl:dark:motion-safe:focus-within:shadow-md"></div>
|
||||
</body>
|
||||
</html>
|
||||
31
jit/tests/variants.test.js
Normal file
31
jit/tests/variants.test.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
const postcss = require('postcss')
|
||||
const tailwind = require('../index.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function run(input, config = {}) {
|
||||
return postcss([tailwind(config)]).process(input, { from: path.resolve(__filename) })
|
||||
}
|
||||
|
||||
test('variants', () => {
|
||||
let config = {
|
||||
darkMode: 'class',
|
||||
purge: [path.resolve(__dirname, './variants.test.html')],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
let css = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
return run(css, config).then((result) => {
|
||||
let expectedPath = path.resolve(__dirname, './variants.test.css')
|
||||
let expected = fs.readFileSync(expectedPath, 'utf8')
|
||||
|
||||
expect(result.css).toMatchCss(expected)
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue