Compare commits

...
Sign in to create a new pull request.

101 commits
main ... v3

Author SHA1 Message Date
Casey Corcoran
7a836d8495
Fix negation of theme() in arbitrary values (#19928)
## Problem

Using a negative modifier with `theme()` inside an arbitrary value
produces no CSS output.

- ✅ `ms-[theme(margin.1)]` — works
- ✅ `-ms-[10px]` — works
- ❌ `-ms-[theme(margin.1)]` — no output

## Cause

`negateValue()` in `src/util/negateValue.js` doesn't recognize `theme()`
as a negatable function. It falls through all conditions and returns
`undefined`, causing the utility to be silently dropped.

## Fix

Added `'theme'` to the `numericFunctions` list so `theme()` values get
wrapped in `calc(... * -1)`, which the PostCSS `theme()` resolver then
processes downstream.

## Tests

- **Unit test** (`negateValue.test.js`):
`negateValue('theme(margin.1)')` returns `calc(theme(margin.1) * -1)`
- **Integration test** (`arbitrary-values.test.js`):
`-mt-[theme(spacing.1)]` produces `margin-top: -0.25rem`

---------

Co-authored-by: Casey Corcoran <casecorc@amazon.com>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2026-08-03 16:11:32 +02:00
Ifeanyi Madu
ff8b2a0db9
Fix extraction of quoted arbitrary variants in v3 (#20374)
## Summary

Fixes #18387.

The v3 default extractor did not capture the complete candidate when a
standard variant preceded an arbitrary selector containing quoted
values, such as
`focus-visible:[&:not([aria-selected="true"])]:bg-red-500`.

The quote-aware pattern allowed quote characters in the standard-variant
portion, causing extraction to begin at the surrounding `class` or
`className` attribute and split the candidate. This change excludes
single and double quotes from that portion of the pattern while
continuing to allow quotes inside arbitrary variants.

Regression tests cover both single- and double-quoted selectors with
preceding `focus-visible` and `hover` variants.

[ci-all]

## Test plan

* `npx jest tests/default-extractor.test.js
tests/arbitrary-variants.test.js --runInBand`
* `npm test -- --runInBand`

Results:

* 86 test suites passed
* 1,060 tests passed
* 1 test marked todo
* 4 snapshots passed

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2026-08-03 15:57:26 +02:00
Jordan Pittman
f38be227df Fix prepare release workflow 2025-12-10 11:00:34 -05:00
Jordan Pittman
9eb4e3b567 3.4.19 2025-12-10 10:52:55 -05:00
Jordan Pittman
c97337accd update workflows 2025-12-10 10:36:29 -05:00
Jordan Pittman
9835906688 Bump again 2025-12-10 10:33:26 -05:00
Jordan Pittman
d1fc136812 Bump node version in workflow 2025-12-10 10:25:55 -05:00
Jordan Pittman
90aa4a347c
Fix provenance setup for v3 (#19429) 2025-12-09 12:19:22 -05:00
Jordan Pittman
82b5c8d0c0 Fix date 2025-11-28 06:37:56 -05:00
Jordan Pittman
e2b47e8a5e
v3: Don’t break sibling-*() functions when used inside calc(…) (#19335)
The implementation of v3's math operator normalization uses a safe-list
of function names. Need to add `sibling-index()` and `sibling-count()`
to this list otherwise when used inside math functions like `calc()`
they'll get spaces around the `-`.
2025-11-19 10:35:48 -05:00
Robin Malfait
7e2dd5383a
Never publish v3 as latest on npm (#19043)
This PR ensures that if we release v3 in the future, that we don't use
`latest` as the npm tag, but `v3-lts` instead.

Unfortunately we can't just use `3` or `v3` because they are not valid
and you will get an error when trying to publish.

Angular uses `v{n}-lts` for the versions they still support:
https://www.npmjs.com/package/@angular/core?activeTab=versions

Adding a tag is important, because omitting the `--tag` is the same as
`--tag latest`
2025-10-01 18:25:46 +02:00
Jordan Pittman
536e38ff18 Don’t tag v3.4 releases as latest
oops
2025-10-01 11:47:08 -04:00
Jordan Pittman
229b1984dc
v3: Bundle postcss-load-config v4 with the standalone CLI (#19042)
Unfortunately, it’s not possible to intercept the `await import(…)` used
by newer versions. This means the Standalone CLI will not be able to
load ESM postcss config files. You still will using the npm package and
newer versions of Node.js.
2025-10-01 11:18:15 -04:00
Jordan Pittman
11de06fd9d
Prepare v3.4.18 release (#19038) 2025-10-01 09:45:30 -04:00
Jordan Pittman
aecc8521dc
v3: Remove irrelevant utility rules when matching important classes (#19030)
Fixes #18678

When given a simple plugin like this:
```js
export default {
  content: [{ raw: '!a' },],
  plugins: [
    ({ addBase }) => addBase({
      '@media (min-width: 1728px)': {
        '.a': { 'padding-top': '1rem !important' },
        '.b': { 'padding-right': '1rem !important' },
      }
    }),
  ],
}
```

If this plugin saw the utility `!a` it would correctly modify both rules
to eliminate any irrelevant classes. Unfortunately, in the case of the
2nd rule this meant it's left with an empty selector which is invalid.

We now detect this case and remove the rule if that happens.
2025-09-29 18:11:09 -04:00
Jordan Pittman
ba55a445cd
Fix native ESM config loading in v3 (#18938)
Unfortunately for backwards compatibility purposes (with `loadConfig` at
least) we can't switch things to use `import(…)` because there's baked
in knowledge that the config is loaded synchronously for v3.

This PR does two things:
- Defers to `require(…)` which allows newer versions that support
`require(esm)` to work natively. This works around the need to switch to
`import(…)` for those versions.
- Allows newer versions of `postcss-load-config` enabling better
ESM+TypeScript support for PostCSS configs in the CLI.

We support v4, v5, and v6 of `postcss-load-config` simultaneously so any
of those versions should work. I've verified that newer node versions
seem to install v6 while earlier ones like Node v14 install v4 of
`postcss-load-config`. So this should be a backwards compatible change.

- [x] needs tests for `import.meta.resolve(…)`
- [x] needs tests for ESM postcss configs

Fixes #14152
Fixes #14423
2025-09-16 14:03:09 -04:00
Philippe Gaultier
ff52f8caf2
Fix require.cache error when loaded through a typescript file in Node 22.18+ (#18665)
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2025-08-22 12:44:51 -04:00
Brandon McConnell
40f506f317
v3: Allow hyphen character in regex pattern to use support queries as is (#13605)
This is the v3 equivalent of PR #13596

Matching for the hyphen character in the existing regex to use support
queries as-is

Resolves #13594

Tests (w/ updated):
- ✅ `supports-[display:grid]:grid`
- ✅ `supports-[transform-origin:5%_5%]:underline`
- ✅ `supports-[not(foo:bar)]:underline`
- ✅ `supports-[(foo:bar)or(bar:baz)]:underline`
- ✅ `supports-[(foo:bar)and(bar:baz)]:underline`
- ✅ `supports-[(foo:bar)_and_(bar:baz)]:grid`
- ✅ `supports-[(foo:bar)_and_(bar:baz)_or(baz:qux)]:grid`
- ✅ `supports-[container-type]:underline`
- ✅ `supports-grid:underline`
- ✅ `supports-[--test]:flex`
- ✅ `supports-[selector(A_>_B)]:underline`
- ✅ `supports-[font-format(opentype)]:grid`
- ✅ `supports-[font-tech(color-COLRv1)]:flex`

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2025-01-28 17:42:09 +01:00
Jordan Pittman
4f9f603e12 Fix error 2024-12-17 14:07:10 -05:00
Jordan Pittman
02faa1529e v3.4.17 2024-12-17 13:46:50 -05:00
Jordan Pittman
e268b2aa96 Update changelog 2024-12-17 13:45:39 -05:00
Jordan Pittman
0a836f76bb
Work around issue with Node 22 and Jiti (#15421)
Fixes #15374

If we always use Jiti the problem should, in theory, go away (I hope).
It does mean that loading configs is slower than it would be if they're
written in CJS but 🤷‍♂️

Wanna get this running with the integration tests to see if anything
breaks.
2024-12-17 13:43:33 -05:00
Jordan Pittman
f875ab9706 Bump macos version 2024-12-03 14:25:44 -05:00
Jordan Pittman
8f91c27d3e v3.4.16 2024-12-03 14:22:00 -05:00
Andrew Powell
8c8c986e09
fix: update lilconfig for ESM and Windows support (#15289)
This PR updates `lilconfig` from v2.1.0 to v3.1.3. Significant
improvements to this package include Windows absolute path support as
well as ESM config files support. This supersedes
https://github.com/tailwindlabs/tailwindcss/pull/14029 which has fallen
behind and has conflicts with the upstream branch. This is a critical
update for Next.js apps running in development which have dependencies
on packages that use an updated version of `lilconfig`. I understand
that v4 will not be using `lilconfig` but it's an important update for
users on v3.x in the meantime.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-12-03 14:19:29 -05:00
Brody McKee
2702cfcc2c
Fix Plugin type issue (#14668)
This is a quick fix to an issue where the types for PluginsConfig don't
match those used in plugins like
[`@tailwindcss/container-queries`](https://github.com/tailwindlabs/tailwindcss-container-queries).

This was caught by TypeScript with [`exactOptionalPropertyTypes`](
https://www.typescriptlang.org/tsconfig/exactOptionalPropertyTypes.html)
enabled, where TypeScript checks if `undefined` can be supplied as a
value for optional types.

I felt that it made more sense to fix this here, as it makes the core
types more flexible, as opposed to each plugin needing to fix this
when/if they hit it.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2024-11-28 11:12:08 +01:00
Jordan Pittman
6069a81187 v3.4.15 2024-11-14 13:35:09 -05:00
Jordan Pittman
d093dce0fb
Add variable fallback to fix Chrome issue (#15003)
This works around an issue in Chrome where `::selection` does not read
from variables defined on `::selection` thus breaking all uses of color
utilities with the selection variant. e.g. `selection::bg-red-200`.

We now add a fallback value of `1` to all uses of
`var(--tw-bg-opacity)`, `var(--tw-text-opacity)`,
`var(--tw-border-opacity)`, etc… since Chrome treats the variable as if
it did not exist because it's not defined on the parent.

In Chrome 131 (until the change is rolled back) existing utilities like
these will not work:
- `selection:text-opacity-50`
- `selection:[--tw-text-opacity:0.5]`

Fixes #15000

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-14 13:33:27 -05:00
Bart Nagel
4de07697bd
Fix config types for boxShadow (#14856)
`boxShadow` accepts multiple shadows just like `dropShadow` does. This
patch fixes the TS typings to reflect that.

See demo showing that multiple shadows are supported (complete with it
incorrectly complaining that the config is bad) here:
https://play.tailwindcss.com/VHqWbbEIrz?file=config

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2024-11-07 12:22:05 +01:00
Robin Malfait
8b41e82621
update changelog 2024-10-17 18:53:10 +02:00
Robin Malfait
825cd83cca
Add CODEOWNERS file (#14702)
This PR adds a new `CODEOWNERS` file so that the
`@tailwindlabs/engineering` will be automatically requested for review
when changes are made to the repository.
2024-10-17 09:06:05 -04:00
Robin Malfait
c8c3a22442
Bump dependencies to fix vulnerabilities (#14697)
This PR fixes some package vulnerabilities that you will see when
running `npm install`. This PR fixes that by bumping dependencies to get
rid of the vulnerabilities.
2024-10-17 06:41:15 -04:00
Robin Malfait
c616fb9562
3.4.14 2024-10-15 12:29:17 +02:00
Adam Wathan
b570e2b887
Don't set display: none on elements that use hidden="until-found" (#14625)
Fixes an issue reported by the React Aria Components team here:

https://github.com/adobe/react-spectrum/issues/7160

Basically `hidden="until-found"` behaves very differently than `hidden`
and doesn't actually use `display: none`, so we don't want to apply the
behavior we apply for the regular `hidden` attribute.

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-10-09 13:55:48 +02:00
Robin Malfait
ed3c5356b7
3.4.13 2024-09-23 16:56:58 +02:00
ivan
066ccf8894
Improve the performance when checking broad glob patterns. (#14481)
In a large project, it's costly to repeatedly call the
function `micromatch.isMatch` that parses a glob pattern,
creates a regular expression, and tests the path name
against the regular expression. To optimize performance,
it's important to cache the parsing and creating process
before entering the loop.

For example, the content configuration in a project
looks like this
`['./pages/**/*.{ts,js}', './node_modules/pages/**/*.{ts,js}']`.
If the project has 10000 matched files and 10 glob patterns,
the function `micromatch.isMatch` will be called 100000 times.

---

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-09-23 10:52:05 +02:00
Robin Malfait
e8614a268d
3.4.12 2024-09-17 15:13:09 +02:00
Adam Wathan
fe48ca83d8
Insert @defaults at start of stylesheet (#14427)
Prior to this PR, we'd put all of the `@defaults` (the CSS variables and
stuff) _after_ the `base` rules. This creates an issue when using
`optimizeUniversalDefaults` with CSS that looks like this:

```css
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  input {
    @apply shadow;
  }
}
```

…because the default shadow stuff ends up after the base `input` rules,
so the generated styles are like this:

```css
input {
  --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
  --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color),
    0 1px 2px -1px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
    var(--tw-shadow);
}

input {
  --tw-ring-offset-shadow: 0 0 #0000;
  --tw-ring-shadow: 0 0 #0000;
  --tw-shadow: 0 0 #0000;
  --tw-shadow-colored: 0 0 #0000;
}
```

This means all of the actual shadow values for the input are reset and
the shadow doesn't work.

Fixes https://github.com/tailwindlabs/tailwindcss/issues/14426.

Lots of failing tests right because this changes a ton of stuff, albeit
in a totally inconsequential way. @thecrypticace if you could update
these for me this week that would be a huge help, just banging this fix
out quick while the kids are napping 😴

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-09-17 09:09:08 -04:00
Robin Malfait
818d10ab84
3.4.11 2024-09-11 19:25:41 +02:00
Robin Malfait
8dd9246a87
update changelog 2024-09-11 19:25:13 +02:00
Robin Malfait
6d9ae82ba3
Allow anchor-size(…) in arbitrary values (#14393)
This PR fixes an issue where using `anchor-size` in arbitrary values
resulted in the incorrect css.

Input: `w-[calc(anchor-size(width)+8px)]`
Output:
```css
.w-\[calc\(anchor-size\(width\)\+8px\)\] {
  width: calc(anchor - size(width) + 8px);
}
```

This PR fixes that, by generating the correct CSS:
```css
.w-\[calc\(anchor-size\(width\)\+8px\)\] {
  width: calc(anchor-size(width) + 8px);
}
```
2024-09-11 19:23:53 +02:00
Jordan Pittman
f07dbff2a7 3.4.10 2024-08-13 16:24:27 -04:00
Jordan Pittman
c4f23621e1
Bump versions of plugins in the Standalone CLI (#14185)
This PR updates the plugins built into the standalone CLI. The bundled
versions here are several versions behind (whoops).
2024-08-13 16:16:49 -04:00
Robin Malfait
f65023efb9
3.4.9 2024-08-08 15:10:38 +02:00
Philipp Spiess
702ba6aaee
Don't warn about broad globs in vendor folders (#14147)
After shipping the new warning that prevents unexpected scanning of all
dependencies in 3.4.8, we noticed that it was firing more often than we
wanted to.

The heuristics we added works by finding broad glob patterns (once that
contain `/**/`) and when those are found and are the _sole pattern used
to match a file of a known-large directory_, we were showing the
warning. The motivation for this is that we have seen time and time
again that an incorrect config like `/**/*.js` can cause recursive scans
through _all_ dependencies including many minified libraries which
greatly impacts performance.

In #14140, we were adding two known-large directory names: 

- `node_modules` (used by npm)
- `vendor` (used by PHP)

The problem with the `vendor` name though is that it is more generic
than we would like it and there are legit use cases to have a folder
named `vendor` inside your component folder. Additionally, PHP vendors
behave a bit differently and it's not super common to have minified
build files in that folder (which is one of the main reasons for the
slow builds). Because of this, we decided to revert the change for
`vendor` and only scan for `node_modules` going forward.
2024-08-08 15:05:52 +02:00
Robin Malfait
1676118af9
3.4.8 2024-08-07 17:26:53 +02:00
Robin Malfait
69c81f2583
rename master to main 2024-08-07 17:18:38 +02:00
Robin Malfait
858696a8bc
Warn when broad glob patterns are used in the content configuration (#14140)
When you use a glob pattern in your `content` configuration that is too
broad, it could be that you are accidentally including files that you
didn't intend to include. E.g.: all of `node_modules`

This has been documented in the [Tailwind CSS
documentation](https://tailwindcss.com/docs/content-configuration#pattern-recommendations),
but it's still something that a lot of people run into.

This PR will try to detect those patterns and show a big warning to let
you know if you may have done something wrong.

We will show a warning if all of these conditions are true:

1. We detect `**` in the glob pattern
2. _and_ you didn't explicitly use `node_modules` in the glob pattern
3. _and_ we found files that include `node_modules` in the file path
4. _and_ no other globs exist that explicitly match the found file

With these rules in place, the DX has nice trade-offs:

1. Very simple projects (that don't even have a `node_modules` folder),
can simply use `./**/*` because while resolving actual files we won't
see files from `node_modules` and thus won't warn.
2. If you use `./src/**` and you do have a `node_modules`, then we also
won't complain (unless you have a `node_modules` folder in the `./src`
folder).
3. If you work with a 3rd party library that you want to make changes
to. Using an explicit match like `./node_modules/my-package/**/*` is
allowed because `node_modules` is explicitly mentioned.

Note: this only shows a warning, it does not stop the process entirely.
The warning will be show when the very first file in the `node_modules`
is detected.

<!--

👋 Hey, thanks for your interest in contributing to Tailwind!

**Please ask first before starting work on any significant new
features.**

It's never a fun experience to have your pull request declined after
investing a lot of time and effort into a new feature. To avoid this
from happening, we request that contributors create an issue to first
discuss any significant new features. This includes things like adding
new utilities, creating new at-rules, or adding new component examples
to the documentation.


https://github.com/tailwindcss/tailwindcss/blob/master/.github/CONTRIBUTING.md

-->

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-08-07 16:55:20 +02:00
Jordan Pittman
1f23c2e842
Bump to latest cssnano v6 (#14105)
We bundle cssnano in our CLI and it's on an older version that does not
handle nested CSS correctly. This PR updates it to the latest version of
v6.x

Fixes #14092
2024-08-02 08:57:14 -04:00
Jordan Pittman
28bd90eefb
Automate checksum generation for standalone CLI (#14081) 2024-08-01 10:02:25 -04:00
Adam Wathan
9824cb64a0 Update version in package.json 2024-07-25 09:20:52 -04:00
Adam Wathan
aa6c10f67f Add missing heading to changelog 2024-07-25 09:16:26 -04:00
Adam Wathan
245058c7fd Update changelog for v3.4.7 2024-07-25 09:06:56 -04:00
Philipp Spiess
605d8cd5eb
Update CHANGELOG.md 2024-07-25 10:13:56 +02:00
Philipp Spiess
680c55c11c
Normalize attribute selector for data-* and aria-* modifiers (#14037)
Fixes #14026 
See #14040 for the v4 fix

When translating `data-` and `aria-` modifiers with attribute selectors,
we currently do not wrap the target attribute in quotes. This only works
for keywords (purely alphabetic words) but breaks as soon as there are
numbers or things like spaces in the attribute:

```html
<div data-id="foo" class="data-[id=foo]:underline">underlined</div>
<div data-id="f1" class="data-[id=1]:underline">not underlined</div>
<div data-id="foo bar" class="data-[id=foo_bar]:underline">not underlined</div>
```

Since it's fairly common to have attribute selectors with `data-` and
`aria-` modifiers, this PR will now wrap the attribute in quotes unless
these are already wrapped.

| Tailwind Modifier  | CSS Selector |
| ------------- | ------------- |
| `.data-[id=foo]`  | `[data-id='foo']`  |
| `.data-[id='foo']`  | `[data-id='foo']`  |
| `.data-[id=foo_i]`  | `[data-id='foo i']`  |
| `.data-[id='foo'_i]`  | `[data-id='foo' i]`  |
| `.data-[id=123]`  | `[data-id='123']`  |

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-07-24 18:46:21 +02:00
Philipp Spiess
866860e6a6
Print eventual lightning CSS parsing errors when the CSS matcher fail (#14034) 2024-07-23 14:40:11 +02:00
Jordan Pittman
bdc87ae1d7
Fix class detection in Slim templates with attached attributes and IDs (#14019)
* Fix class detection in Slim templates with attached attributes and IDs

* Update changelog

* Tweak regex
2024-07-18 11:21:20 -04:00
Jordan Pittman
d622977b2a Update changelog 2024-07-16 10:52:51 -04:00
Josh Wilson
0573c0769a
Loosen :is() wrapping rules in applyImportantSelector for more readable output. (#13900) 2024-07-16 10:51:45 -04:00
Jordan Pittman
9c29e47c5f 3.4.6 2024-07-16 09:37:15 -04:00
Jordan Pittman
daa5266081 Update changelog 2024-07-16 09:36:07 -04:00
Georg Ledermann
ae6a8d532b
Fix extracting utilities from slim/pug templates (#14006)
A class name starting with number like `2xl:bg-red-500` must not be removed.

Resolves #14005
2024-07-16 09:34:20 -04:00
Jordan Pittman
a0dbb3d876 Update runner image 2024-07-15 11:07:30 -04:00
Jordan Pittman
10a1197989 3.4.5 2024-07-15 10:56:16 -04:00
Adam Wathan
9033d625e1
Always generate -webkit-backdrop-filter property (#13997)
* Always generate -webkit-backdrop-filter property

* Update changelog

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-07-12 20:48:08 -04:00
Adam Wathan
074736c1d6
Avoid over-extracting utilities from candidates with decimal values (#13959)
* Avoid over-extracting utilities from candidates with decimal values

Prevent candidates like `px-1.5` from generating both the `px-1.5` class and the `px-1` class.

* Update CHANGELOG.md

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-07-05 14:46:51 -04:00
Robin Malfait
588a8225eb
Add .mts and .cts config file detection (#13940)
* add `tailwind.config.cts` and `tailwind.config.mts` as default config files

* always use jiti when working with ESM or TS files

* update changelog

* add integration test for `.cts` and `.mts` configuration files
2024-07-03 23:09:35 +02:00
Simon He
0de1f0cce4
refactor(util): code refactor (#13872)
* refactor(util): code refactor

* refactor(util): code refactor
2024-06-24 09:13:12 -04:00
Simon He
a61e5aa06b
fix: typo (#13864) 2024-06-20 06:02:11 -04:00
Robin Malfait
eef91c9065
Use no value instead of blur(0px) for backdrop-blur-none and blur-none utilities (#13830)
* map `backdrop-blur-none` and `blur-none` to ` ` instead of `blur(0px)`

* add test for `backdrop-blur-none` and `blur-none`

* update changelog
2024-06-13 15:49:59 +02:00
Jordan Pittman
9e928ce0be
Disable automatic var() injection for anchor properties (#13826)
* Disable automatic `var()` injection for CSS anchor positioning properties

* Update tests

* Update changelog
2024-06-13 09:19:08 -04:00
Jordan Pittman
ff6f085da2 3.4.4 2024-06-05 12:55:54 -04:00
Jordan Pittman
ed024eeb09 Update changelog 2024-06-05 12:54:06 -04:00
Jordan Pittman
325e7c03ce
Bump deps (#13797) 2024-06-05 12:53:06 -04:00
Jordan Pittman
56116b0904
Update browserslist database (#13792) 2024-06-05 09:55:47 -04:00
Jordan Pittman
8d66d94182
[v3] Support negative values for {col,row}-{start,end} utilities (#13781)
* Support negative values for `{col,row}-{start,end}` utilities

* Add tests

* Update changelog
2024-06-03 11:34:27 -04:00
victor
669109efdd
Don't prefix classes in arbitrary values of has-*, group-has-*, and peer-has-* variants (#13770)
* Added tests to verify that classes are prefixed when using `has-*` variants with arbitrary values

* Fix test

* Don't prefix classes in arbitrary values in `has-*` variants

* Update changelog

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-05-31 20:01:09 -04:00
Maxwell Barvian
9fda4616eb
Fix multiple <alpha-value> in color definitions (#13740)
* Fix multiple <alpha-value> in color definitions

Fixes #13716

* Update CHANGELOG.md

* Use `replace` with global regex

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-05-29 11:32:48 -04:00
Jordan Pittman
f1f419a9ec 3.4.3 2024-03-27 15:18:37 -04:00
Jordan Pittman
e6c1082823
Revert changes to glob handling (#13384)
* Revert "Improve glob handling for folders with `(`, `)`, `[` or `]` in the file path (#12715)"

This reverts commit f2a7c2c453.

* Update changelog
2024-03-27 15:16:52 -04:00
Jordan Pittman
8430d8b520 3.4.2 2024-03-27 11:25:32 -04:00
Jordan Pittman
8b4a2a6770
Change dark selector so @apply works correctly with pseudo elements (#13379)
* Change dark selector so `@apply` hoists pseudo elements properly

* Update tests

* Update changelog
2024-03-27 11:03:49 -04:00
Robin Malfait
97607f1cfb
Ensure that arbitrary properties respect important configuration (#13353)
* ensure we respect important on arbitrary properties

* update changelog

* reword changelog entry
2024-03-26 11:42:41 +01:00
Adam Wathan
c033f106bc
Update CHANGELOG.md 2024-03-24 08:09:45 -04:00
Robin Malfait
bda84210d6
Only detect nesting when using @apply (#13325)
* drop nesting detection for `@tailwind`

* drop separate nesting detection entirely

* detect nesting only when using `@apply` with a class that uses nesting

* drop unnecessary `important` config

* add test to verify applying nested user CSS errors

* add error reason to tests

* update `@apply` error message
2024-03-23 19:10:51 -04:00
Allain Lalonde
3ba51d14c7
Remove leading space in box-shadow's addDefaults call (#13334)
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-03-23 05:35:02 -04:00
Allain Lalonde
a53d854d1d
Fix missing xx-large and remove double x-large absolute size (#13324)
* fixing double x-large absolute size

x-large appears twice in the set of absolute sizes.

I believe the second one is meant to be 'xx-large'.

* update changelog

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-03-22 20:03:21 +01:00
Magnar Ovedal Myrtveit
ea90d3a81c
Reset letter spacing for form elements (#13150)
* Reset letter spacing for form elements

Some browsers, such as Chrome, set `letter-spacing: normal` for form elements. For consistency with the other styles, it should be set to `inherit` by Preflight.

* wip

* Update changelog

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-03-22 14:49:22 -04:00
Jordan Pittman
b10b431d97
Transpile import.meta.url in config files (#13322)
* Use Babel to transpile configs when import.meta is present

* Update minimum jiti version

* Update changelog
2024-03-22 12:45:19 -04:00
Robin Malfait
44b3b429a8
Cleanup oxide — Part #2 (#13312)
* remove all oxide related code

* Update lightningcss to version 1.24.1

* update tests to match bumped Lightning CSS output

---------

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2024-03-22 17:12:14 +01:00
depfu[bot]
c28c718f72
Update esbuild to version 0.20.2 (#13315)
Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2024-03-22 14:56:21 +01:00
Jordan Pittman
27e4b65e0b
Fix crash showing completions in Intellisense when using a custom separator (#13306)
* Fix variant completions in intellisense when using a custom separator

* Update changelog
2024-03-21 19:38:17 -04:00
Robin Malfait
9b90c53bad
Cleanup oxide — Part #1 (#13304)
* swap engines

* remove all oxide related files

* drop swap engine step from CI

* drop oxide tests where we read from a `.oxide.*` file

* drop swap-engines.js file

* drop unused `oxide` variable

Let's make eslint happy!
2024-03-21 18:23:31 +01:00
Robin Malfait
d56d241fd1
Ensure dashes are allowed in variant modifiers (#13303)
* sync package-lock.json

* ensure dashes are allowed in variant modifiers

* update changelog
2024-03-21 15:25:28 +01:00
Robin Malfait
41e94ebfab
Add missing workflow_dispatch (#13302)
* add missing `workflow_dispatch`

* re-add `ci-stable.yml`, purely to fix a broken badge on npmjs.com

* update badge in README to point to `ci.yml` instead of `ci-stable.yml`
2024-03-21 14:04:00 +01:00
depfu[bot]
3eb8cab547
🚨 [security] Update vite 4.3.2 → 5.1.6 (major) (#13287)
* Update vite to version 5.1.6

* Fix regex

---------

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-03-21 09:02:38 -04:00
depfu[bot]
3a466bca04
Update rollup to version 4.13.0 (#13279)
Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2024-03-21 13:42:05 +01:00
depfu[bot]
41c90f6e07
Update sass to version 1.72.0 (#13296)
Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2024-03-21 08:31:08 -04:00
Robin Malfait
f5408d60d9
Fix failing integration tests in CI (#13300)
* run prettier on integrations

* update media query syntax

* drop oxide related workflows

* rename `{workflow}-stable` to just `workflow`
2024-03-21 13:23:19 +01:00
saibotk
d86fd0bb5b
CI: Add provenance to all published packages (#13097)
* CI: Add provenance to all published packages

This commit adds provenance for all published packages. See the NPM documentation [0].

Provenance will allow people to verify that the tailwindcss packages were actually built on GH Actions and with the content of the corresponding commit. This will help with supply chain security.

For this to work, the `id-token` permission was added only where necessary.

[0]: https://docs.npmjs.com/generating-provenance-statements

* chore: Add missing repository links to packages

This is needed for provenance, to link the repository to the build accoring to the NPM docs [0].

[0]: https://docs.npmjs.com/generating-provenance-statements#prerequisites
2024-03-07 15:32:58 -05:00
Adam Wathan
de00a62063 Update contributing 2024-03-07 09:35:57 -05:00
749 changed files with 31568 additions and 1270955 deletions

1
.github/CODEOWNERS vendored Normal file
View file

@ -0,0 +1 @@
* @tailwindlabs/engineering

View file

@ -1,10 +0,0 @@
# Tailwind CSS Community Guidelines
The following community guidelines are based on [The Ruby Community Conduct Guidelines](https://www.ruby-lang.org/en/conduct/).
This document provides community guidelines for a respectful, productive, and collaborative place for any person who is willing to contribute to the Tailwind CSS project. It applies to all “collaborative space”, which is defined as community communications channels (such as mailing lists, submitted patches, commit comments, etc.).
- Participants will be tolerant of opposing views.
- Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
- When interpreting the words and actions of others, participants should always assume good intentions.
- Behaviour which can be reasonably considered harassment will not be tolerated.

View file

@ -1,16 +1,20 @@
# Contributing # Contributing
Thanks for your interest in contributing to Tailwind CSS! Please take a moment to review this document **before submitting a pull request**. ## Bug fixes
## Pull requests If you've found a bug in Tailwind that you'd like to fix, [submit a pull request](https://github.com/tailwindlabs/tailwindcss/pulls) with your changes. Include a helpful description of the problem and how your changes address it, and provide tests so we can verify the fix works as expected.
**Please ask first before starting work on any significant new features.** ## New features
It's never a fun experience to have your pull request declined after investing a lot of time and effort into a new feature. To avoid this from happening, we request that contributors create [a feature request](https://github.com/tailwindlabs/tailwindcss/discussions/new?category=ideas) to first discuss any significant new ideas. This includes things like adding new utilities, creating new at-rules, etc. If there's a new feature you'd like to see added to Tailwind, [share your idea with us](https://github.com/tailwindlabs/tailwindcss/discussions/new?category=ideas) in our discussion forum to get it on our radar as something to consider for a future release.
**Please note that we don't often accept pull requests for new features.** Adding a new feature to Tailwind requires us to think through the entire problem ourselves to make sure we agree with the proposed API, which means the feature needs to be high on our own priority list for us to be able to give it the attention it needs.
If you open a pull request for a new feature, we're likely to close it not because it's a bad idea, but because we aren't ready to prioritize the feature and don't want the PR to sit open for months or even years.
## Coding standards ## Coding standards
Our code formatting rules are defined in [.eslintrc](https://github.com/tailwindcss/tailwindcss/blob/master/.eslintrc.json). You can check your code against these standards by running: Our code formatting rules are defined in [.eslintrc](https://github.com/tailwindcss/tailwindcss/blob/main/.eslintrc.json). You can check your code against these standards by running:
```sh ```sh
npm run style npm run style
@ -31,4 +35,3 @@ npm run build && npm test
``` ```
Please ensure that the tests are passing when submitting a pull request. If you're adding new features to Tailwind, please include tests. Please ensure that the tests are passing when submitting a pull request. If you're adding new features to Tailwind, please include tests.

View file

@ -6,6 +6,6 @@
It's never a fun experience to have your pull request declined after investing a lot of time and effort into a new feature. To avoid this from happening, we request that contributors create an issue to first discuss any significant new features. This includes things like adding new utilities, creating new at-rules, or adding new component examples to the documentation. It's never a fun experience to have your pull request declined after investing a lot of time and effort into a new feature. To avoid this from happening, we request that contributors create an issue to first discuss any significant new features. This includes things like adding new utilities, creating new at-rules, or adding new component examples to the documentation.
https://github.com/tailwindcss/tailwindcss/blob/master/.github/CONTRIBUTING.md https://github.com/tailwindcss/tailwindcss/blob/main/.github/CONTRIBUTING.md
--> -->

View file

@ -1,3 +1,6 @@
# The only reason this file exists is so that the `badge` in the README of the
# currently published version isn't broken (https://www.npmjs.com/package/tailwindcss).
#
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
@ -5,9 +8,9 @@ name: CI — Stable
on: on:
push: push:
branches: [master] branches: [v3]
pull_request: pull_request:
branches: [master, 3.3, 3.4] branches: [v3]
permissions: permissions:
contents: read contents: read
@ -24,7 +27,7 @@ jobs:
strategy: strategy:
matrix: matrix:
node-version: [14, 18] node-version: [14, 18, 20, 22, 24]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -33,10 +36,6 @@ jobs:
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- name: Use the `stable` engine
run: |
node ./scripts/swap-engines.js
- name: Cache node_modules - name: Cache node_modules
uses: actions/cache@v3 uses: actions/cache@v3
with: with:

View file

@ -1,10 +1,13 @@
name: CI — Oxide # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: CI — Stable
on: on:
push: push:
branches: [master, 3.3, 3.4] branches: [v3]
pull_request: pull_request:
branches: [master, 3.3, 3.4] branches: [v3]
permissions: permissions:
contents: read contents: read
@ -13,16 +16,15 @@ env:
CI: true CI: true
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }} TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
CACHE_PREFIX: oxide CACHE_PREFIX: stable
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 15
strategy: strategy:
matrix: matrix:
node-version: [18] node-version: [14, 18, 20, 22, 24]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -37,40 +39,17 @@ jobs:
path: node_modules path: node_modules
key: ${{ runner.os }}-${{ matrix.node-version }}-${{ env.CACHE_PREFIX }}-node_modules-${{ hashFiles('**/package-lock.json') }} key: ${{ runner.os }}-${{ matrix.node-version }}-${{ env.CACHE_PREFIX }}-node_modules-${{ hashFiles('**/package-lock.json') }}
# Cargo already skips downloading dependencies if they already exist
- name: Cache cargo
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
# Cache the `oxide` Rust build
- name: Cache oxide build
uses: actions/cache@v3
with:
path: |
./oxide/target/
./oxide/crates/node/*.node
./oxide/crates/node/index.js
./oxide/crates/node/index.d.ts
key: ${{ runner.os }}-oxide-${{ hashFiles('./oxide/crates/**/*') }}
- name: Install dependencies - name: Install dependencies
run: npm install run: npm install
- name: Build Tailwind CSS - name: Build Tailwind CSS
run: npx turbo run build --filter=// run: npm run build
- name: Test - name: Test
run: | run: |
npx turbo run test --filter=// || \ npm run test || \
npx turbo run test --filter=// || \ npm run test || \
npx turbo run test --filter=// || exit 1 npm run test || exit 1
- name: Lint - name: Lint
run: npx turbo run style --filter=// run: npm run style

View file

@ -1,85 +0,0 @@
name: Integration Tests — Oxide
on:
push:
branches: [master, 3.3, 3.4]
pull_request:
branches: [master, 3.3, 3.4]
permissions:
contents: read
env:
CI: true
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
CACHE_PREFIX: oxide
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
matrix:
integration:
- content-resolution
- parcel
- postcss-cli
- rollup
- rollup-sass
- tailwindcss-cli
- vite
- webpack-4
- webpack-5
node-version: [18]
fail-fast: false
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Cache node_modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-${{ matrix.node-version }}-${{ env.CACHE_PREFIX }}-node_modules-${{ hashFiles('**/package-lock.json') }}
# Cargo already skips downloading dependencies if they already exist
- name: Cache cargo
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
# Cache the `oxide` Rust build
- name: Cache oxide build
uses: actions/cache@v3
with:
path: |
./oxide/target/
./oxide/crates/node/*.node
./oxide/crates/node/index.js
./oxide/crates/node/index.d.ts
key: ${{ runner.os }}-oxide-${{ hashFiles('./oxide/crates/**/*') }}
- name: Install dependencies
run: npm install
- name: Build Tailwind CSS
run: npx turbo run build --filter=//
- name: Test ${{ matrix.integration }}
run: |
npx turbo run test --filter=./integrations/${{ matrix.integration }} || \
npx turbo run test --filter=./integrations/${{ matrix.integration }} || \
npx turbo run test --filter=./integrations/${{ matrix.integration }} || exit 1

View file

@ -1,10 +1,10 @@
name: Integration Tests — Stable name: Integration Tests
on: on:
push: push:
branches: [master, 3.3, 3.4] branches: [main, v3]
pull_request: pull_request:
branches: [master, 3.3, 3.4] branches: [main, v3]
permissions: permissions:
contents: read contents: read
@ -31,7 +31,7 @@ jobs:
- vite - vite
- webpack-4 - webpack-4
- webpack-5 - webpack-5
node-version: [18] node-version: [18, 20]
fail-fast: false fail-fast: false
steps: steps:
@ -42,10 +42,6 @@ jobs:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
cache: 'npm' cache: 'npm'
- name: Use the `stable` engine
run: |
node ./scripts/swap-engines.js
- name: Cache node_modules (tailwindcss) - name: Cache node_modules (tailwindcss)
uses: actions/cache@v3 uses: actions/cache@v3
with: with:

View file

@ -17,12 +17,12 @@ jobs:
permissions: permissions:
contents: write # for softprops/action-gh-release to create GitHub release contents: write # for softprops/action-gh-release to create GitHub release
runs-on: macos-11 runs-on: macos-latest
timeout-minutes: 15 timeout-minutes: 15
strategy: strategy:
matrix: matrix:
node-version: [16] node-version: [20]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -47,10 +47,6 @@ jobs:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
- name: Use the `stable` engine
run: |
node ./scripts/swap-engines.js
- name: Install dependencies - name: Install dependencies
run: npm install run: npm install
@ -87,3 +83,4 @@ jobs:
standalone-cli/dist/tailwindcss-macos-x64 standalone-cli/dist/tailwindcss-macos-x64
standalone-cli/dist/tailwindcss-windows-x64.exe standalone-cli/dist/tailwindcss-windows-x64.exe
standalone-cli/dist/tailwindcss-windows-arm64.exe standalone-cli/dist/tailwindcss-windows-arm64.exe
standalone-cli/dist/sha256sums.txt

View file

@ -1,423 +0,0 @@
name: Release Insiders — Oxide
on:
push:
branches: [master]
env:
APP_NAME: tailwindcss-oxide
NODE_VERSION: 16
OXIDE_LOCATION: ./oxide/crates/node
RELEASE_CHANNEL: oxide-insiders
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
# Windows
- os: windows-latest
target: x86_64-pc-windows-msvc
# Mac OS
- os: macos-latest
target: x86_64-apple-darwin
strip: strip -x # Must use -x on macOS. This produces larger results on linux.
name: Build ${{ matrix.target }} (OXIDE)
runs-on: ${{ matrix.os }}
timeout-minutes: 15
steps:
- uses: actions/checkout@v3
- name: Cache node_modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-${{ matrix.target }}-${{ env.NODE_VERSION }}-node_modules-${{ hashFiles('**/package-lock.json') }}
# Cargo already skips downloading dependencies if they already exist
- name: Cache cargo
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}
# Cache the `oxide` Rust build
- name: Cache oxide build
uses: actions/cache@v3
with:
path: |
./oxide/target/
./oxide/crates/node/*.node
./oxide/crates/node/index.js
./oxide/crates/node/index.d.ts
key: ${{ runner.os }}-${{ matrix.target }}-oxide-${{ hashFiles('./oxide/crates/**/*') }}
- name: Install Node.JS
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Setup rust target
run: rustup target add ${{ matrix.target }}
- name: Install dependencies
run: npm install
- name: Build release
run: cd ${{ env.OXIDE_LOCATION }} && npm run build
env:
RUST_TARGET: ${{ matrix.target }}
- name: Strip debug symbols # https://github.com/rust-lang/rust/issues/46034
if: ${{ matrix.strip }}
run: ${{ matrix.strip }} ${{ env.OXIDE_LOCATION }}/*.node
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: bindings-${{ matrix.target }}
path: |
${{ env.OXIDE_LOCATION }}/*.node
${{ matrix.binary }}
build-apple-silicon:
name: Build Apple Silicon (OXIDE)
runs-on: macos-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v3
- name: Cache node_modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-${{ env.NODE_VERSION }}-node_modules-${{ hashFiles('**/package-lock.json') }}
# Cargo already skips downloading dependencies if they already exist
- name: Cache cargo
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
# Cache the `oxide` Rust build
- name: Cache oxide build
uses: actions/cache@v3
with:
path: |
./oxide/target/
./oxide/crates/node/*.node
./oxide/crates/node/index.js
./oxide/crates/node/index.d.ts
key: ${{ runner.os }}-oxide-${{ hashFiles('./oxide/crates/**/*') }}
- name: Install Node.JS
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Setup rust target
run: rustup target add aarch64-apple-darwin
- name: Install dependencies
run: npm install
- name: Build release
run: cd ${{ env.OXIDE_LOCATION }} && npm run build
env:
RUST_TARGET: aarch64-apple-darwin
JEMALLOC_SYS_WITH_LG_PAGE: 14
- name: Strip debug symbols # https://github.com/rust-lang/rust/issues/46034
run: strip -x ${{ env.OXIDE_LOCATION }}/*.node
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: bindings-aarch64-apple-darwin
path: |
${{ env.OXIDE_LOCATION }}/*.node
${{ env.APP_NAME }}
build-linux:
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
strip: strip
image: docker.io/centos/nodejs-14-centos7
- target: aarch64-unknown-linux-gnu
strip: aarch64-linux-gnu-strip
image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian
setup: apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu -y
- target: armv7-unknown-linux-gnueabihf
strip: arm-linux-gnueabihf-strip
image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian
setup: apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf -y
- target: aarch64-unknown-linux-musl
image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
strip: aarch64-linux-musl-strip
- target: x86_64-unknown-linux-musl
image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
strip: strip
name: Build ${{ matrix.target }} (OXIDE)
runs-on: ubuntu-latest
timeout-minutes: 15
container:
image: ${{ matrix.image }}
steps:
- uses: actions/checkout@v3
- name: Cache node_modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-${{ matrix.target }}-${{ env.NODE_VERSION }}-node_modules-${{ hashFiles('**/package-lock.json') }}
# Cargo already skips downloading dependencies if they already exist
- name: Cache cargo
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}
# Cache the `oxide` Rust build
- name: Cache oxide build
uses: actions/cache@v3
with:
path: |
./oxide/target/
./oxide/crates/node/*.node
./oxide/crates/node/index.js
./oxide/crates/node/index.d.ts
key: ${{ runner.os }}-${{ matrix.target }}-oxide-${{ hashFiles('./oxide/crates/**/*') }}
- name: Install Node.JS
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Setup cross compile toolchain
if: ${{ matrix.setup }}
run: ${{ matrix.setup }}
- name: Setup rust target
run: rustup target add ${{ matrix.target }}
- name: Install dependencies
run: npm install
- name: Build release
run: cd ${{ env.OXIDE_LOCATION }} && npm run build
env:
RUST_TARGET: ${{ matrix.target }}
- name: Strip debug symbols # https://github.com/rust-lang/rust/issues/46034
if: ${{ matrix.strip }}
run: ${{ matrix.strip }} ${{ env.OXIDE_LOCATION }}/*.node
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: bindings-${{ matrix.target }}
path: |
${{ env.OXIDE_LOCATION }}/*.node
${{ env.APP_NAME }}
release:
runs-on: ubuntu-latest
timeout-minutes: 15
name: Build and release
needs:
- build
- build-linux
- build-apple-silicon
steps:
- uses: actions/checkout@v3
- name: Cache node_modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-${{ env.NODE_VERSION }}-node_modules-${{ hashFiles('**/package-lock.json') }}
# Cargo already skips downloading dependencies if they already exist
- name: Cache cargo
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
# Cache the `oxide` Rust build
- name: Cache oxide build
uses: actions/cache@v3
with:
path: |
./oxide/target/
./oxide/crates/node/*.node
./oxide/crates/node/index.js
./oxide/crates/node/index.d.ts
key: ${{ runner.os }}-oxide-${{ hashFiles('./oxide/crates/**/*') }}
- name: Install dependencies
run: npm install
- name: Download artifacts
uses: actions/download-artifact@v3
with:
path: ${{ env.OXIDE_LOCATION }}
- run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} > ~/.npmrc
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Move artifacts
run: |
cd ${{ env.OXIDE_LOCATION }}
cp bindings-aarch64-apple-darwin/oxide/crates/node/* ./npm/darwin-arm64/
cp bindings-aarch64-unknown-linux-gnu/oxide/crates/node/* ./npm/linux-arm64-gnu/
cp bindings-aarch64-unknown-linux-musl/oxide/crates/node/* ./npm/linux-arm64-musl/
cp bindings-armv7-unknown-linux-gnueabihf/oxide/crates/node/* ./npm/linux-arm-gnueabihf/
cp bindings-x86_64-apple-darwin/* ./npm/darwin-x64/
cp bindings-x86_64-pc-windows-msvc/* ./npm/win32-x64-msvc/
cp bindings-x86_64-unknown-linux-gnu/oxide/crates/node/* ./npm/linux-x64-gnu/
cp bindings-x86_64-unknown-linux-musl/oxide/crates/node/* ./npm/linux-x64-musl/
- name: Resolve version
id: vars
run: |
echo "NPM_VERSION=0.0.0-${{ env.RELEASE_CHANNEL }}.$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: Generate entry point
run: npm run build --prefix ${{ env.OXIDE_LOCATION }}
- name: Publish to npm
run: |
for pkg in ${{ env.OXIDE_LOCATION }}/npm/*; do
echo "Publishing $pkg..."
cd $pkg
npm version ${{ env.NPM_VERSION }} --force --no-git-tag-version
npm publish --tag ${{ env.RELEASE_CHANNEL }} --access public
cd -
done
echo "Publishing ${{ env.APP_NAME }}...";
cd ${{ env.OXIDE_LOCATION }}
npm version ${{ env.NPM_VERSION }} --force --no-git-tag-version
sed "s#\"0.0.0\"#\"${{ env.NPM_VERSION }}\"#g" package.json > package_updated.json
mv package_updated.json package.json
npm publish --tag ${{ env.RELEASE_CHANNEL }} --access public
cd -
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
tailwind_oxide_release:
runs-on: ubuntu-latest
timeout-minutes: 15
name: Build and release Tailwind CSS
needs:
- release
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ env.NODE_VERSION }}
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: 'https://registry.npmjs.org'
- name: Resolve version
id: vars
run: |
echo "SHA_SHORT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
echo "OXIDE_NPM_VERSION=0.0.0-${{ env.RELEASE_CHANNEL }}.$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: Setup `@tailwindcss/oxide` version
run: |
sed "s#\"@tailwindcss/oxide\": \".*\"#\"@tailwindcss/oxide\": \"${{ env.OXIDE_NPM_VERSION }}\"#" package.json > package_updated.json
mv package_updated.json package.json
- name: Install dependencies
run: npm install
- name: Build Tailwind CSS
run: npm run build
- name: Test
run: |
npm test || \
npm test || \
npm test || exit 1
- name: 'Version based on commit: 0.0.0-${{ env.RELEASE_CHANNEL }}.${{ env.SHA_SHORT }}'
run: npm version 0.0.0-${{ env.RELEASE_CHANNEL }}.${{ env.SHA_SHORT }} --force --no-git-tag-version
- name: Publish
run: npm publish --tag ${{ env.RELEASE_CHANNEL }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# !! Enable this, once we are cleaning up all the `stable` engine related files.
#
# - name: Trigger Tailwind Play update
# uses: actions/github-script@v6
# with:
# github-token: ${{ secrets.TAILWIND_PLAY_TOKEN }}
# script: |
# await github.rest.actions.createWorkflowDispatch({
# owner: 'tailwindlabs',
# repo: 'play.tailwindcss.com',
# ref: 'master',
# workflow_id: 'upgrade-tailwindcss.yml',
# inputs: {
# insidersVersion: '0.0.0-${{ env.RELEASE_CHANNEL }}.${{ env.SHA_SHORT }}'
# }
# })

View file

@ -1,11 +1,12 @@
name: Release Insiders — Stable name: Release Insiders
on: on:
push: push:
branches: [master] branches: [main]
permissions: permissions:
contents: read contents: read
id-token: write
env: env:
CI: true CI: true
@ -27,10 +28,6 @@ jobs:
node-version: ${{ env.NODE_VERSION }} node-version: ${{ env.NODE_VERSION }}
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
- name: Use the `stable` engine
run: |
node ./scripts/swap-engines.js
- name: Cache node_modules - name: Cache node_modules
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
@ -58,7 +55,7 @@ jobs:
run: npm version 0.0.0-${{ env.RELEASE_CHANNEL }}.${{ env.SHA_SHORT }} --force --no-git-tag-version run: npm version 0.0.0-${{ env.RELEASE_CHANNEL }}.${{ env.SHA_SHORT }} --force --no-git-tag-version
- name: Publish - name: Publish
run: npm publish --tag ${{ env.RELEASE_CHANNEL }} run: npm publish --provenance --tag ${{ env.RELEASE_CHANNEL }}
env: env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View file

@ -1,337 +0,0 @@
name: Release — Oxide
on:
workflow_dispatch:
env:
APP_NAME: tailwindcss-oxide
NODE_VERSION: 14
OXIDE_LOCATION: ./oxide/crates/node
jobs:
oxide-build:
strategy:
fail-fast: false
matrix:
include:
# Windows
- os: windows-latest
target: x86_64-pc-windows-msvc
# Mac OS
- os: macos-latest
target: x86_64-apple-darwin
strip: strip -x # Must use -x on macOS. This produces larger results on linux.
name: Build ${{ matrix.target }} (OXIDE)
runs-on: ${{ matrix.os }}
timeout-minutes: 15
steps:
- uses: actions/checkout@v3
- name: Install Node.JS
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Setup rust target
run: rustup target add ${{ matrix.target }}
# - name: Use cached oxide node_modules
# id: cache-oxide
# uses: actions/cache@v3
# with:
# path: ${{ env.OXIDE_LOCATION }}/node_modules
# key: nodeModules-${{ hashFiles('${{ env.OXIDE_LOCATION }}/package-lock.json') }}-${{ matrix.os }}-${{ matrix.target }}-${{ env.NODE_VERSION }}
# restore-keys: |
# nodeModules-
- name: Oxide — npm install
# if: steps.cache-oxide.outputs.cache-hit != 'true'
run: cd ${{ env.OXIDE_LOCATION }} && npm install
- name: Build release
run: cd ${{ env.OXIDE_LOCATION }} && npm run build
env:
RUST_TARGET: ${{ matrix.target }}
- name: Strip debug symbols # https://github.com/rust-lang/rust/issues/46034
if: ${{ matrix.strip }}
run: ${{ matrix.strip }} ${{ env.OXIDE_LOCATION }}/*.node
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: bindings-${{ matrix.target }}
path: |
${{ env.OXIDE_LOCATION }}/*.node
${{ matrix.binary }}
oxide-build-apple-silicon:
name: Build Apple Silicon (OXIDE)
runs-on: macos-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v3
- name: Cache node_modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-${{ matrix.node-version }}-node_modules-${{ hashFiles('**/package-lock.json') }}
# Cargo already skips downloading dependencies if they already exist
- name: Cache cargo
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('./oxide/**/Cargo.lock') }}
- name: Install Node.JS
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Setup rust target
run: rustup target add aarch64-apple-darwin
- name: Install dependencies
run: npm install
- name: Build release
run: cd ${{ env.OXIDE_LOCATION }} && npm run build
env:
RUST_TARGET: aarch64-apple-darwin
JEMALLOC_SYS_WITH_LG_PAGE: 14
- name: Strip debug symbols # https://github.com/rust-lang/rust/issues/46034
run: strip -x ${{ env.OXIDE_LOCATION }}/*.node
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: bindings-aarch64-apple-darwin
path: |
${{ env.OXIDE_LOCATION }}/*.node
${{ env.APP_NAME }}
oxide-build-linux:
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
strip: strip
image: docker.io/centos/nodejs-14-centos7
- target: aarch64-unknown-linux-gnu
strip: aarch64-linux-gnu-strip
image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian
setup: apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu -y
- target: armv7-unknown-linux-gnueabihf
strip: arm-linux-gnueabihf-strip
image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian
setup: apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf -y
- target: aarch64-unknown-linux-musl
image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
strip: aarch64-linux-musl-strip
- target: x86_64-unknown-linux-musl
image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
strip: strip
name: Build ${{ matrix.target }} (OXIDE)
runs-on: ubuntu-latest
timeout-minutes: 15
container:
image: ${{ matrix.image }}
steps:
- uses: actions/checkout@v3
- name: Install Node.JS
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Setup cross compile toolchain
if: ${{ matrix.setup }}
run: ${{ matrix.setup }}
- name: Setup rust target
run: rustup target add ${{ matrix.target }}
# - name: Use cached oxide node_modules
# id: cache-oxide
# uses: actions/cache@v3
# with:
# path: ${{ env.OXIDE_LOCATION }}/node_modules
# key: nodeModules-${{ hashFiles('${{ env.OXIDE_LOCATION }}/package-lock.json') }}-linux-${{ matrix.target }}-${{ env.NODE_VERSION }}
# restore-keys: |
# nodeModules-
- name: Oxide — npm install
# if: steps.cache-oxide.outputs.cache-hit != 'true'
run: cd ${{ env.OXIDE_LOCATION }} && npm install
- name: Build release
run: cd ${{ env.OXIDE_LOCATION }} && npm run build
env:
RUST_TARGET: ${{ matrix.target }}
- name: Strip debug symbols # https://github.com/rust-lang/rust/issues/46034
if: ${{ matrix.strip }}
run: ${{ matrix.strip }} ${{ env.OXIDE_LOCATION }}/*.node
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: bindings-${{ matrix.target }}
path: |
${{ env.OXIDE_LOCATION }}/*.node
${{ env.APP_NAME }}
oxide-release:
runs-on: ubuntu-latest
timeout-minutes: 15
name: Build and release
needs:
- oxide-build
- oxide-build-linux
- oxide-build-apple-silicon
steps:
- uses: actions/checkout@v3
# - name: Use cached oxide node_modules
# id: cache-oxide
# uses: actions/cache@v3
# with:
# path: ${{ env.OXIDE_LOCATION }}/node_modules
# key: nodeModules-${{ hashFiles('${{ env.OXIDE_LOCATION }}/package-lock.json') }}-ubuntu-latest-${{ env.NODE_VERSION }}
# restore-keys: |
# nodeModules-
- name: Oxide — npm install
# if: steps.cache-oxide.outputs.cache-hit != 'true'
run: cd ${{ env.OXIDE_LOCATION }} && npm install
- name: Download artifacts
uses: actions/download-artifact@v3
with:
path: ${{ env.OXIDE_LOCATION }}
- run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} > ~/.npmrc
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Move artifacts
run: |
cd ${{ env.OXIDE_LOCATION }}
cp bindings-aarch64-apple-darwin/oxide/crates/node/* ./npm/darwin-arm64/
cp bindings-aarch64-unknown-linux-gnu/oxide/crates/node/* ./npm/linux-arm64-gnu/
cp bindings-aarch64-unknown-linux-musl/oxide/crates/node/* ./npm/linux-arm64-musl/
cp bindings-armv7-unknown-linux-gnueabihf/oxide/crates/node/* ./npm/linux-arm-gnueabihf/
cp bindings-x86_64-apple-darwin/* ./npm/darwin-x64/
cp bindings-x86_64-pc-windows-msvc/* ./npm/win32-x64-msvc/
cp bindings-x86_64-unknown-linux-gnu/oxide/crates/node/* ./npm/linux-x64-gnu/
cp bindings-x86_64-unknown-linux-musl/oxide/crates/node/* ./npm/linux-x64-musl/
- name: Resolve version
id: vars
run: |
echo "NPM_VERSION=0.0.0-insiders.$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: Generate entry point
run: npm run build --prefix ${{ env.OXIDE_LOCATION }}
- name: Publish to npm
run: |
for pkg in ${{ env.OXIDE_LOCATION }}/npm/*; do
echo "Publishing $pkg..."
cd $pkg
npm version ${{ env.NPM_VERSION }} --force --no-git-tag-version
npm publish --tag insiders --access public
cd -
done
echo "Publishing ${{ env.APP_NAME }}...";
cd ${{ env.OXIDE_LOCATION }}
npm version ${{ env.NPM_VERSION }} --force --no-git-tag-version
sed "s#\"0.0.0\"#\"${{ env.NPM_VERSION }}\"#g" package.json > package_updated.json
mv package_updated.json package.json
npm publish --tag insiders --access public
cd -
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
tailwind_oxide_release:
runs-on: ubuntu-latest
timeout-minutes: 15
name: Build and release Tailwind CSS
needs:
- oxide-release
strategy:
matrix:
node-version: [14]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
registry-url: 'https://registry.npmjs.org'
- name: Resolve version
id: vars
run: |
echo "SHA_SHORT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
echo "OXIDE_NPM_VERSION=0.0.0-insiders.$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: Setup `@tailwindcss/oxide` version
run: |
sed "s#\"@tailwindcss/oxide\": \".*\"#\"@tailwindcss/oxide\": \"${{ env.OXIDE_NPM_VERSION }}\"#" package.json > package_updated.json
mv package_updated.json package.json
- name: Install dependencies
run: npm install
- name: Build Tailwind CSS
run: npm run build
- name: Test
run: npm test
- name: 'Version based on commit: 0.0.0-oxide.${{ env.SHA_SHORT }}'
run: npm version 0.0.0-oxide.${{ env.SHA_SHORT }} --force --no-git-tag-version
- name: Publish
run: npm publish --tag oxide
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View file

@ -1,11 +1,13 @@
name: Release — Stable name: Release
on: on:
release: release:
types: [published] types: [published]
workflow_dispatch:
permissions: permissions:
contents: read contents: read
id-token: write
env: env:
CI: true CI: true
@ -16,7 +18,7 @@ jobs:
strategy: strategy:
matrix: matrix:
node-version: [14] node-version: [20]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -28,10 +30,6 @@ jobs:
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
cache: 'npm' cache: 'npm'
- name: Use the `stable` engine
run: |
node ./scripts/swap-engines.js
- name: Install dependencies - name: Install dependencies
run: npm install run: npm install
@ -47,7 +45,7 @@ jobs:
echo "TAILWINDCSS_VERSION=$(node -e 'console.log(require(`./package.json`).version);')" >> $GITHUB_ENV echo "TAILWINDCSS_VERSION=$(node -e 'console.log(require(`./package.json`).version);')" >> $GITHUB_ENV
- name: Publish - name: Publish
run: npm publish --tag ${{ env.RELEASE_CHANNEL }} run: npm publish --provenance --tag v3-lts
env: env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View file

@ -9,11 +9,149 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Ensure classes are extracted when a variant precedes an arbitrary variant containing a quoted attribute selector (e.g. `focus-visible:[&:not([aria-selected="true"])]:bg-red-500`) ([#20374](https://github.com/tailwindlabs/tailwindcss/pull/20374))
- Fix negation of `theme()` in arbitrary values (e.g. `-m-[theme(margin.1)]`) ([#19928](https://github.com/tailwindlabs/tailwindcss/pull/19928))
## [3.4.19] - 2025-12-10
### Fixed
- Don’t break `sibling-*()` functions when used inside `calc(…)` ([#19335](https://github.com/tailwindlabs/tailwindcss/pull/19335))
## [3.4.18] - 2025-10-01
### Fixed
- Improve support for raw `supports-[…]` queries in arbitrary values ([#13605](https://github.com/tailwindlabs/tailwindcss/pull/13605))
- Fix `require.cache` error when loaded through a TypeScript file in Node 22.18+ ([#18665](https://github.com/tailwindlabs/tailwindcss/pull/18665))
- Support `import.meta.resolve(…)` in configs for new enough Node.js versions ([#18938](https://github.com/tailwindlabs/tailwindcss/pull/18938))
- Allow using newer versions of `postcss-load-config` for better ESM and TypeScript PostCSS config support with the CLI ([#18938](https://github.com/tailwindlabs/tailwindcss/pull/18938))
- Remove irrelevant utility rules when matching important classes ([#19030](https://github.com/tailwindlabs/tailwindcss/pull/19030))
## [3.4.17] - 2024-12-17
### Fixed
- Work around Node v22.12+ issue ([#15421](https://github.com/tailwindlabs/tailwindcss/pull/15421))
## [3.4.16] - 2024-12-03
### Fixed
- Ensure the TypeScript types for `PluginsConfig` allow `undefined` values ([#14668](https://github.com/tailwindlabs/tailwindcss/pull/14668))
# Changed
- Bumped lilconfig to v3.x ([#15289](https://github.com/tailwindlabs/tailwindcss/pull/15289))
## [3.4.15] - 2024-11-14
- Bump versions for security vulnerabilities ([#14697](https://github.com/tailwindlabs/tailwindcss/pull/14697))
- Ensure the TypeScript types for the `boxShadow` theme configuration allows arrays ([#14856](https://github.com/tailwindlabs/tailwindcss/pull/14856))
- Set fallback for opacity variables to ensure setting colors with the `selection:*` variant works in Chrome 131 ([#15003](https://github.com/tailwindlabs/tailwindcss/pull/15003))
## [3.4.14] - 2024-10-15
### Fixed
- Don't set `display: none` on elements that use `hidden="until-found"` ([#14625](https://github.com/tailwindlabs/tailwindcss/pull/14625))
## [3.4.13] - 2024-09-23
### Fixed
- Improve source glob verification performance ([#14481](https://github.com/tailwindlabs/tailwindcss/pull/14481))
## [3.4.12] - 2024-09-17
### Fixed
- Ensure using `@apply` with utilities that use `@defaults` works with rules defined in the base layer when using `optimizeUniversalDefaults` ([#14427](https://github.com/tailwindlabs/tailwindcss/pull/14427))
## [3.4.11] - 2024-09-11
### Fixed
- Allow `anchor-size(…)` in arbitrary values ([#14393](https://github.com/tailwindlabs/tailwindcss/pull/14393))
## [3.4.10] - 2024-08-13
### Fixed
- Bump versions of plugins in the Standalone CLI ([#14185](https://github.com/tailwindlabs/tailwindcss/pull/14185))
## [3.4.9] - 2024-08-08
### Fixed
- No longer warns when broad glob patterns are detecting `vendor` folders
## [3.4.8] - 2024-08-07
### Fixed
- Fix minification when using nested CSS ([#14105](https://github.com/tailwindlabs/tailwindcss/pull/14105))
- Warn when broad glob patterns are used in the content configuration ([#14140](https://github.com/tailwindlabs/tailwindcss/pull/14140))
## [3.4.7] - 2024-07-25
### Fixed
- Fix class detection in Slim templates with attached attributes and ID ([#14019](https://github.com/tailwindlabs/tailwindcss/pull/14019))
- Ensure attribute values in `data-*` and `aria-*` modifiers are always quoted in the generated CSS ([#14037](https://github.com/tailwindlabs/tailwindcss/pull/14037))
## [3.4.6] - 2024-07-16
### Fixed
- Fix detection of some utilities in Slim/Pug templates ([#14006](https://github.com/tailwindlabs/tailwindcss/pull/14006))
### Changed
- Loosen `:is()` wrapping rules when using an important selector ([#13900](https://github.com/tailwindlabs/tailwindcss/pull/13900))
## [3.4.5] - 2024-07-15
### Fixed
- Disable automatic `var()` injection for anchor properties ([#13826](https://github.com/tailwindlabs/tailwindcss/pull/13826))
- Use no value instead of `blur(0px)` for `backdrop-blur-none` and `blur-none` utilities ([#13830](https://github.com/tailwindlabs/tailwindcss/pull/13830))
- Add `.mts` and `.cts` config file detection ([#13940](https://github.com/tailwindlabs/tailwindcss/pull/13940))
- Don't generate utilities like `px-1` unnecessarily when using utilities like `px-1.5` ([#13959](https://github.com/tailwindlabs/tailwindcss/pull/13959))
- Always generate `-webkit-backdrop-filter` for `backdrop-*` utilities ([#13997](https://github.com/tailwindlabs/tailwindcss/pull/13997))
## [3.4.4] - 2024-06-05
### Fixed
- Make it possible to use multiple `<alpha-value>` placeholders in a single color definition ([#13740](https://github.com/tailwindlabs/tailwindcss/pull/13740))
- Don't prefix classes in arbitrary values of `has-*`, `group-has-*`, and `peer-has-*` variants ([#13770](https://github.com/tailwindlabs/tailwindcss/pull/13770))
- Support negative values for `{col,row}-{start,end}` utilities ([#13781](https://github.com/tailwindlabs/tailwindcss/pull/13781))
- Update embedded browserslist database ([#13792](https://github.com/tailwindlabs/tailwindcss/pull/13792))
## [3.4.3] - 2024-03-27
### Fixed
- Revert changes to glob handling ([#13384](https://github.com/tailwindlabs/tailwindcss/pull/13384))
## [3.4.2] - 2024-03-27
### Fixed
- Ensure max specificity of `0,0,1` for button and input Preflight rules ([#12735](https://github.com/tailwindlabs/tailwindcss/pull/12735)) - Ensure max specificity of `0,0,1` for button and input Preflight rules ([#12735](https://github.com/tailwindlabs/tailwindcss/pull/12735))
- Improve glob handling for folders with `(`, `)`, `[` or `]` in the file path ([#12715](https://github.com/tailwindlabs/tailwindcss/pull/12715)) - Improve glob handling for folders with `(`, `)`, `[` or `]` in the file path ([#12715](https://github.com/tailwindlabs/tailwindcss/pull/12715))
- Split `:has` rules when using `experimental.optimizeUniversalDefaults` ([#12736](https://github.com/tailwindlabs/tailwindcss/pull/12736)) - Split `:has` rules when using `experimental.optimizeUniversalDefaults` ([#12736](https://github.com/tailwindlabs/tailwindcss/pull/12736))
- Sort arbitrary properties alphabetically across multiple class lists ([#12911](https://github.com/tailwindlabs/tailwindcss/pull/12911)) - Sort arbitrary properties alphabetically across multiple class lists ([#12911](https://github.com/tailwindlabs/tailwindcss/pull/12911))
- Add `mix-blend-plus-darker` utility ([#12923](https://github.com/tailwindlabs/tailwindcss/pull/12923)) - Add `mix-blend-plus-darker` utility ([#12923](https://github.com/tailwindlabs/tailwindcss/pull/12923))
- Ensure dashes are allowed in variant modifiers ([#13303](https://github.com/tailwindlabs/tailwindcss/pull/13303))
- Fix crash showing completions in Intellisense when using a custom separator ([#13306](https://github.com/tailwindlabs/tailwindcss/pull/13306))
- Transpile `import.meta.url` in config files ([#13322](https://github.com/tailwindlabs/tailwindcss/pull/13322))
- Reset letter spacing for form elements ([#13150](https://github.com/tailwindlabs/tailwindcss/pull/13150))
- Fix missing `xx-large` and remove double `x-large` absolute size ([#13324](https://github.com/tailwindlabs/tailwindcss/pull/13324))
- Don't error when encountering nested CSS unless trying to `@apply` a class that uses nesting ([#13325](https://github.com/tailwindlabs/tailwindcss/pull/13325))
- Ensure that arbitrary properties respect `important` configuration ([#13353](https://github.com/tailwindlabs/tailwindcss/pull/13353))
- Change dark mode selector so `@apply` works correctly with pseudo elements ([#13379](https://github.com/tailwindlabs/tailwindcss/pull/13379))
## [3.4.1] - 2024-01-05 ## [3.4.1] - 2024-01-05
@ -2358,7 +2496,25 @@ No release notes
- Everything! - Everything!
[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.1...HEAD [unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.19...v3
[3.4.19]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.18...v3.4.19
[3.4.18]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.17...v3.4.18
[3.4.17]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.16...v3.4.17
[3.4.16]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.15...v3.4.16
[3.4.15]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.14...v3.4.15
[3.4.14]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.13...v3.4.14
[3.4.13]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.12...v3.4.13
[3.4.12]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.11...v3.4.12
[3.4.11]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.10...v3.4.11
[3.4.10]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.9...v3.4.10
[3.4.9]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.8...v3.4.9
[3.4.8]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.7...v3.4.8
[3.4.7]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.6...v3.4.7
[3.4.6]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.5...v3.4.6
[3.4.5]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.4...v3.4.5
[3.4.4]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.3...v3.4.4
[3.4.3]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.2...v3.4.3
[3.4.2]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.1...v3.4.2
[3.4.1]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.0...v3.4.1 [3.4.1]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.0...v3.4.1
[3.4.0]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.7...v3.4.0 [3.4.0]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.7...v3.4.0
[3.3.7]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.6...v3.3.7 [3.3.7]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.6...v3.3.7

View file

@ -12,15 +12,14 @@
A utility-first CSS framework for rapidly building custom user interfaces. A utility-first CSS framework for rapidly building custom user interfaces.
</p> </p>
<p align="center"> <p align="center">
<a href="https://github.com/tailwindlabs/tailwindcss/actions"><img src="https://img.shields.io/github/actions/workflow/status/tailwindlabs/tailwindcss/ci-stable.yml?branch=master" alt="Build Status"></a> <a href="https://github.com/tailwindlabs/tailwindcss/actions"><img src="https://img.shields.io/github/actions/workflow/status/tailwindlabs/tailwindcss/ci.yml?branch=main" alt="Build Status"></a>
<a href="https://www.npmjs.com/package/tailwindcss"><img src="https://img.shields.io/npm/dt/tailwindcss.svg" alt="Total Downloads"></a> <a href="https://www.npmjs.com/package/tailwindcss"><img src="https://img.shields.io/npm/dt/tailwindcss.svg" alt="Total Downloads"></a>
<a href="https://github.com/tailwindcss/tailwindcss/releases"><img src="https://img.shields.io/npm/v/tailwindcss.svg" alt="Latest Release"></a> <a href="https://github.com/tailwindcss/tailwindcss/releases"><img src="https://img.shields.io/npm/v/tailwindcss.svg" alt="Latest Release"></a>
<a href="https://github.com/tailwindcss/tailwindcss/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/tailwindcss.svg" alt="License"></a> <a href="https://github.com/tailwindcss/tailwindcss/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/tailwindcss.svg" alt="License"></a>
</p> </p>
------ ---
## Documentation ## Documentation
@ -38,4 +37,4 @@ For casual chit-chat with others using the framework:
## Contributing ## Contributing
If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/master/.github/CONTRIBUTING.md) **before submitting a pull request**. If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/main/.github/CONTRIBUTING.md) **before submitting a pull request**.

View file

@ -1,12 +1,13 @@
let fs = require('fs') let fs = require('fs')
let path = require('path') let path = require('path')
let { stripVTControlCharacters } = require('util')
let { cwd } = require('./cwd.js') let { cwd } = require('./cwd.js')
let { writeConfigs, destroyConfigs } = require('./config.js') let { writeConfigs, destroyConfigs } = require('./config.js')
let $ = require('../../execute') let $ = require('../../execute')
let { css } = require('../../syntax') let { css } = require('../../syntax')
let { readOutputFile } = require('../../io')({ let { writeInputFile, readOutputFile } = require('../../io')({
output: 'dist', output: 'dist',
input: '.', input: '.',
}) })
@ -37,14 +38,22 @@ async function build({ cwd: cwdPath } = {}) {
await cwd.switch(cwdPath) await cwd.switch(cwdPath)
// Hide console.log and console.error output
let consoleLogMock = jest.spyOn(console, 'log').mockImplementation(() => {})
let consoleErrorMock = jest.spyOn(console, 'error').mockImplementation(() => {})
// Note that ./tailwind.config.js is hardcoded on purpose here // Note that ./tailwind.config.js is hardcoded on purpose here
// It represents a config but one that could be in different places // It represents a config but one that could be in different places
await $(`postcss ${inputPath} -o ${outputPath}`, { let result = await $(`postcss ${inputPath} -o ${outputPath}`, {
env: { NODE_ENV: 'production' }, env: { NODE_ENV: 'production', JEST_WORKER_ID: undefined },
cwd: cwdPath, cwd: cwdPath,
}) })
consoleLogMock.mockRestore()
consoleErrorMock.mockRestore()
return { return {
...result,
css: await readOutputFile('main.css'), css: await readOutputFile('main.css'),
} }
} }
@ -160,6 +169,206 @@ it('it handles ignored globs correctly when not relative to the config', async (
expect(result.css).toMatchCss(``) expect(result.css).toMatchCss(``)
}) })
it('warns when globs are too broad and match node_modules', async () => {
await writeConfigs({
both: {
content: {
files: ['./**/*.html'],
},
},
})
let result = await build({ cwd: path.resolve(__dirname, '..') })
// No issues yet, because we don't have a file that resolves inside `node_modules`
expect(result.stderr).toEqual('')
// We didn't scan any node_modules files yet
expect(result.css).not.toIncludeCss(
css`
.content-\[\'node\\_modules\/bad\.html\'\] {
--tw-content: 'node_modules/bad.html';
content: var(--tw-content);
}
`
)
// Write a file that resolves inside `node_modules`
await writeInputFile(
'node_modules/bad.html',
String.raw`<div class="content-['node\_modules/bad.html']">Bad</div>`
)
result = await build({ cwd: path.resolve(__dirname, '..') })
// We still expect the node_modules file to be processed
expect(result.css).toIncludeCss(
css`
.content-\[\'node\\_modules\/bad\.html\'\] {
--tw-content: 'node_modules/bad.html';
content: var(--tw-content);
}
`
)
// We didn't list `node_modules` in the glob explicitly, so we should see a
// warning.
expect(stripVTControlCharacters(result.stderr)).toMatchInlineSnapshot(`
"
warn - Your \`content\` configuration includes a pattern which looks like it's accidentally matching all of \`node_modules\` and can cause serious performance issues.
warn - Pattern: \`./**/*.html\`
warn - See our documentation for recommendations:
warn - https://tailwindcss.com/docs/content-configuration#pattern-recommendations
"
`)
})
it('should not warn when glob contains node_modules explicitly', async () => {
await writeConfigs({
both: {
content: {
files: ['./node_modules/**/*.html'],
},
},
})
let result = await build({ cwd: path.resolve(__dirname, '..') })
// Write a file that resolves inside `node_modules`
await writeInputFile(
'node_modules/bad.html',
String.raw`<div class="content-['node\_modules/bad.html']">Bad</div>`
)
result = await build({ cwd: path.resolve(__dirname, '..') })
// We still expect the node_modules file to be processed
expect(result.css).toIncludeCss(
css`
.content-\[\'node\\_modules\/bad\.html\'\] {
--tw-content: 'node_modules/bad.html';
content: var(--tw-content);
}
`
)
// We explicitly listed `node_modules` in the glob, so we shouldn't see a
// warning.
expect(result.stderr).toEqual('')
})
it('should not warn when globs are too broad if other glob match node_modules explicitly', async () => {
await writeConfigs({
both: {
content: {
files: ['./**/*.html', './node_modules/bad.html'],
},
},
})
let result = await build({ cwd: path.resolve(__dirname, '..') })
// No issues yet, because we don't have a file that resolves inside `node_modules`
expect(result.stderr).toEqual('')
// We didn't scan any node_modules files yet
expect(result.css).not.toIncludeCss(
css`
.content-\[\'node\\_modules\/bad\.html\'\] {
--tw-content: 'node_modules/bad.html';
content: var(--tw-content);
}
`
)
// Write a file that resolves inside `node_modules`
await writeInputFile(
'node_modules/bad.html',
String.raw`<div class="content-['node\_modules/bad.html']">Bad</div>`
)
result = await build({ cwd: path.resolve(__dirname, '..') })
// We still expect the node_modules file to be processed
expect(result.css).toIncludeCss(
css`
.content-\[\'node\\_modules\/bad\.html\'\] {
--tw-content: 'node_modules/bad.html';
content: var(--tw-content);
}
`
)
// We explicitly listed `node_modules` in the glob, so we shouldn't see a
// warning.
expect(result.stderr).toEqual('')
// Write a file that resolves inside `node_modules` but is not covered by the
// explicit glob patterns.
await writeInputFile(
'node_modules/very-very-bad.html',
String.raw`<div class="content-['node\_modules/very-very-bad.html']">Bad</div>`
)
result = await build({ cwd: path.resolve(__dirname, '..') })
// We still expect the node_modules file to be processed
expect(result.css).toIncludeCss(
css`
.content-\[\'node\\_modules\/very-very-bad\.html\'\] {
--tw-content: 'node_modules/very-very-bad.html';
content: var(--tw-content);
}
`
)
// The very-very-bad.html file is not covered by the explicit glob patterns,
// so we should see a warning.
expect(stripVTControlCharacters(result.stderr)).toMatchInlineSnapshot(`
"
warn - Your \`content\` configuration includes a pattern which looks like it's accidentally matching all of \`node_modules\` and can cause serious performance issues.
warn - Pattern: \`./**/*.html\`
warn - See our documentation for recommendations:
warn - https://tailwindcss.com/docs/content-configuration#pattern-recommendations
"
`)
})
it('should not warn when a negative glob is used', async () => {
await writeConfigs({
both: {
content: {
files: ['./**/*.html', '!./node_modules/**/*.html'],
},
},
})
// Write a file that resolves inside `node_modules`
await writeInputFile(
'node_modules/bad.html',
String.raw`<div class="content-['node\_modules/bad.html']">Bad</div>`
)
let result = await build({ cwd: path.resolve(__dirname, '..') })
// The initial glob resolving shouldn't use the node_modules file
// in the first place.
// We still expect the node_modules file to be processed
expect(result.css).not.toIncludeCss(
css`
.content-\[\'node\\_modules\/bad\.html\'\] {
--tw-content: 'node_modules/bad.html';
content: var(--tw-content);
}
`
)
// The node_modules file shouldn't have been processed at all because it was
// ignored by the negative glob.
expect(result.stderr).toEqual('')
})
it('it handles ignored globs correctly when relative to the config', async () => { it('it handles ignored globs correctly when relative to the config', async () => {
await writeConfigs({ await writeConfigs({
both: { both: {

View file

@ -5,10 +5,10 @@ let resolveToolRoot = require('./resolve-tool-root')
let SHOW_OUTPUT = false let SHOW_OUTPUT = false
let runningProcessess = [] let runningProcesses = []
afterEach(() => { afterEach(() => {
runningProcessess.splice(0).forEach((runningProcess) => runningProcess.stop()) runningProcesses.splice(0).forEach((runningProcess) => runningProcess.stop())
}) })
function debounce(fn, ms) { function debounce(fn, ms) {
@ -129,7 +129,7 @@ module.exports = function $(command, options = {}) {
}) })
}) })
runningProcessess.push(runningProcess) runningProcesses.push(runningProcess)
return Object.assign(runningProcess, { return Object.assign(runningProcess, {
stop() { stop() {

View file

@ -134,7 +134,8 @@ module.exports = function ({
} }
} }
return fs.writeFile(path.resolve(absoluteInputFolder, file), contents, 'utf8') await fs.mkdir(path.dirname(filePath), { recursive: true })
return fs.writeFile(filePath, contents, 'utf8')
}, },
async waitForOutputFileCreation(file) { async waitForOutputFileCreation(file) {
if (file instanceof RegExp) { if (file instanceof RegExp) {

View file

@ -1,12 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./index.css"> <link rel="stylesheet" href="./index.css" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -1,12 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./index.css"> <link rel="stylesheet" href="./index.css" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -1,6 +1,5 @@
let $ = require('../../execute') let $ = require('../../execute')
let { css, html, javascript } = require('../../syntax') let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
let { let {
appendToInputFile, appendToInputFile,
@ -25,13 +24,11 @@ describe('static build', () => {
env: { NODE_ENV: 'production' }, env: { NODE_ENV: 'production' },
}) })
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
css` .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} `)
`
)
}) })
it('can use a tailwind.config.js configuration file with ESM syntax', async () => { it('can use a tailwind.config.js configuration file with ESM syntax', async () => {
@ -74,26 +71,12 @@ describe('static build', () => {
env: { NODE_ENV: 'production' }, env: { NODE_ENV: 'production' },
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( .bg-primary {
css` --tw-bg-opacity: 1;
.bg-primary { background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 1; }
background-color: rgb(0 0 0 / var(--tw-bg-opacity)); `)
}
`
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
css`
.bg-primary {
background-color: black;
}
`
)
}
}) })
it('can use a tailwind.config.ts configuration file', async () => { it('can use a tailwind.config.ts configuration file', async () => {
@ -138,26 +121,12 @@ describe('static build', () => {
env: { NODE_ENV: 'production' }, env: { NODE_ENV: 'production' },
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( .bg-primary {
css` --tw-bg-opacity: 1;
.bg-primary { background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 1; }
background-color: rgb(0 0 0 / var(--tw-bg-opacity)); `)
}
`
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
css`
.bg-primary {
background-color: black;
}
`
)
}
}) })
}) })
@ -173,67 +142,43 @@ describe('watcher', () => {
let runningProcess = $('parcel watch ./src/index.html --no-cache') let runningProcess = $('parcel watch ./src/index.html --no-cache')
await waitForOutputFileCreation(/index\.\w+\.css$/) await waitForOutputFileCreation(/parcel\.\w+\.css$/)
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
css` .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} `)
`
)
await waitForOutputFileChange(/index\.\w+\.css$/, async () => { await waitForOutputFileChange(/parcel\.\w+\.css$/, async () => {
await appendToInputFile('index.html', html`<div class="font-normal"></div>`) await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
}) })
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
css` .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `)
`
)
await waitForOutputFileChange(/index\.\w+\.css$/, async () => { await waitForOutputFileChange(/parcel\.\w+\.css$/, async () => {
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( .bg-red-500 {
css` --tw-bg-opacity: 1;
.bg-red-500 { background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 1; }
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); .font-bold {
} font-weight: 700;
.font-bold { }
font-weight: 700; .font-normal {
} font-weight: 400;
.font-normal { }
font-weight: 400; `)
}
`
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -245,67 +190,43 @@ describe('watcher', () => {
let runningProcess = $('parcel watch ./src/index.html --no-cache') let runningProcess = $('parcel watch ./src/index.html --no-cache')
await waitForOutputFileCreation(/index\.\w+\.css$/) await waitForOutputFileCreation(/parcel\.\w+\.css$/)
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
css` .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} `)
`
)
await waitForOutputFileChange(/index\.\w+\.css$/, async () => { await waitForOutputFileChange(/parcel\.\w+\.css$/, async () => {
await appendToInputFile('glob/index.html', html`<div class="font-normal"></div>`) await appendToInputFile('glob/index.html', html`<div class="font-normal"></div>`)
}) })
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
css` .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `)
`
)
await waitForOutputFileChange(/index\.\w+\.css$/, async () => { await waitForOutputFileChange(/parcel\.\w+\.css$/, async () => {
await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`)
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( .bg-red-500 {
css` --tw-bg-opacity: 1;
.bg-red-500 { background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 1; }
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); .font-bold {
} font-weight: 700;
.font-bold { }
font-weight: 700; .font-normal {
} font-weight: 400;
.font-normal { }
font-weight: 400; `)
}
`
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -321,22 +242,20 @@ describe('watcher', () => {
let runningProcess = $('parcel watch ./src/index.html --no-cache') let runningProcess = $('parcel watch ./src/index.html --no-cache')
await waitForOutputFileCreation(/index\.\w+\.css$/) await waitForOutputFileCreation(/parcel\.\w+\.css$/)
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
css` .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
@media (width >= 768px) {
.md\:font-medium {
font-weight: 500;
} }
@media (min-width: 768px) { }
.md\:font-medium { `)
font-weight: 500;
}
}
`
)
await waitForOutputFileChange(/index\.\w+\.css$/, async () => { await waitForOutputFileChange(/parcel\.\w+\.css$/, async () => {
await writeInputFile( await writeInputFile(
'../tailwind.config.js', '../tailwind.config.js',
javascript` javascript`
@ -361,18 +280,16 @@ describe('watcher', () => {
) )
}) })
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
css` .font-bold {
.font-bold { font-weight: bold;
font-weight: bold; }
@media (width >= 800px) {
.md\:font-medium {
font-weight: 500;
} }
@media (min-width: 800px) { }
.md\:font-medium { `)
font-weight: 500;
}
}
`
)
return runningProcess.stop() return runningProcess.stop()
}) })
@ -388,17 +305,15 @@ describe('watcher', () => {
let runningProcess = $('parcel watch ./src/index.html --no-cache') let runningProcess = $('parcel watch ./src/index.html --no-cache')
await waitForOutputFileCreation(/index\.\w+\.css$/) await waitForOutputFileCreation(/parcel\.\w+\.css$/)
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
css` .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} `)
`
)
await waitForOutputFileChange(/index\.\w+\.css$/, async () => { await waitForOutputFileChange(/parcel\.\w+\.css$/, async () => {
await writeInputFile( await writeInputFile(
'index.css', 'index.css',
css` css`
@ -415,20 +330,18 @@ describe('watcher', () => {
) )
}) })
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
css` /* prettier-ignore */
/* prettier-ignore */ .btn {
.btn {
border-radius: .25rem; border-radius: .25rem;
padding: .25rem .5rem; padding: .25rem .5rem;
} }
.font-bold { .font-bold {
font-weight: 700; font-weight: 700;
} }
` `)
)
await waitForOutputFileChange(/index\.\w+\.css$/, async () => { await waitForOutputFileChange(/parcel\.\w+\.css$/, async () => {
await writeInputFile( await writeInputFile(
'index.css', 'index.css',
css` css`
@ -445,36 +358,17 @@ describe('watcher', () => {
) )
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile(/parcel\.\w+\.css$/)).toIncludeCss(css`
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss( .btn {
css` --tw-bg-opacity: 1;
.btn { background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 1; border-radius: 0.25rem;
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); padding: 0.25rem 0.5rem;
border-radius: 0.25rem; }
padding: 0.25rem 0.5rem; .font-bold {
} font-weight: 700;
.font-bold { }
font-weight: 700; `)
}
`
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
css`
.btn {
background-color: #ef4444;
border-radius: 0.25rem;
padding: 0.25rem 0.5rem;
}
.font-bold {
font-weight: 700;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })

View file

@ -1,11 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -1,11 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -1,6 +1,5 @@
let $ = require('../../execute') let $ = require('../../execute')
let { css, html, javascript } = require('../../syntax') let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
let { readOutputFile, appendToInputFile, writeInputFile } = require('../../io')({ let { readOutputFile, appendToInputFile, writeInputFile } = require('../../io')({
output: 'dist', output: 'dist',
@ -61,38 +60,20 @@ describe('watcher', () => {
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -128,38 +109,20 @@ describe('watcher', () => {
await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`)
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -284,40 +247,22 @@ describe('watcher', () => {
) )
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .btn {
.btn { border-radius: 0.25rem;
border-radius: 0.25rem; --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); padding-left: 0.5rem;
padding-left: 0.5rem; padding-right: 0.5rem;
padding-right: 0.5rem; padding-top: 0.25rem;
padding-top: 0.25rem; padding-bottom: 0.25rem;
padding-bottom: 0.25rem; }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
/* prettier-ignore */
.btn {
border-radius: 0.25rem;
background-color: #ef4444;
padding: 0.25rem 0.5rem;
}
.font-bold {
font-weight: 700;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })

View file

@ -18,8 +18,8 @@
} }
}, },
"devDependencies": { "devDependencies": {
"rollup": "^3.21.0", "rollup": "^4.13.0",
"rollup-plugin-postcss": "^4.0.2", "rollup-plugin-postcss": "^4.0.2",
"sass": "^1.62.0" "sass": "^1.72.0"
} }
} }

View file

@ -1,9 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title> <title>Document</title>
</head> </head>
<body></body> <body></body>
</html> </html>

View file

@ -1,9 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title> <title>Document</title>
</head> </head>
<body></body> <body></body>
</html> </html>

View file

@ -1,4 +1,4 @@
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
@import "./imported"; @import './imported';

View file

@ -1,6 +1,5 @@
let $ = require('../../execute') let $ = require('../../execute')
let { css, html, javascript } = require('../../syntax') let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
let { readOutputFile, appendToInputFile, writeInputFile } = require('../../io')({ let { readOutputFile, appendToInputFile, writeInputFile } = require('../../io')({
output: 'dist', output: 'dist',
@ -61,38 +60,20 @@ describe('watcher', () => {
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('index.css')).toIncludeCss(
expect(await readOutputFile('index.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('index.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -128,38 +109,20 @@ describe('watcher', () => {
await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`)
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('index.css')).toIncludeCss(
expect(await readOutputFile('index.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('index.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -282,36 +245,19 @@ describe('watcher', () => {
) )
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('index.css')).toIncludeCss(
expect(await readOutputFile('index.css')).toIncludeCss( css`
css` .btn {
.btn { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); border-radius: 0.25rem;
border-radius: 0.25rem; padding: 0.25rem 0.5rem;
padding: 0.25rem 0.5rem; }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('index.css')).toIncludeCss(
css`
.btn {
background-color: #ef4444;
border-radius: 0.25rem;
padding: 0.25rem 0.5rem;
}
.font-bold {
font-weight: 700;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -379,36 +325,19 @@ describe('watcher', () => {
) )
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('index.css')).toIncludeCss(
expect(await readOutputFile('index.css')).toIncludeCss( css`
css` .btn {
.btn { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); border-radius: 0.25rem;
border-radius: 0.25rem; padding: 0.25rem 0.5rem;
padding: 0.25rem 0.5rem; }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('index.css')).toIncludeCss(
css`
.btn {
background-color: #ef4444;
border-radius: 0.25rem;
padding: 0.25rem 0.5rem;
}
.font-bold {
font-weight: 700;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}, 30000) }, 30000)

View file

@ -18,7 +18,7 @@
} }
}, },
"devDependencies": { "devDependencies": {
"rollup": "^3.21.0", "rollup": "^4.13.0",
"rollup-plugin-postcss": "^4.0.2" "rollup-plugin-postcss": "^4.0.2"
} }
} }

View file

@ -1,11 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -1,11 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -1,6 +1,5 @@
let $ = require('../../execute') let $ = require('../../execute')
let { css, html, javascript } = require('../../syntax') let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
let { readOutputFile, appendToInputFile, writeInputFile, removeFile } = require('../../io')({ let { readOutputFile, appendToInputFile, writeInputFile, removeFile } = require('../../io')({
output: 'dist', output: 'dist',
@ -62,26 +61,14 @@ describe('static build', () => {
env: { NODE_ENV: 'production' }, env: { NODE_ENV: 'production' },
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile('index.css')).toIncludeCss(
expect(await readOutputFile('index.css')).toIncludeCss( css`
css` .bg-primary {
.bg-primary { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
background-color: rgb(0 0 0 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('index.css')).toIncludeCss(
css`
.bg-primary {
background-color: black;
}
`
)
}
}) })
it('can use a tailwind.config.ts configuration file', async () => { it('can use a tailwind.config.ts configuration file', async () => {
@ -120,26 +107,14 @@ describe('static build', () => {
env: { NODE_ENV: 'production' }, env: { NODE_ENV: 'production' },
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile('index.css')).toIncludeCss(
expect(await readOutputFile('index.css')).toIncludeCss( css`
css` .bg-primary {
.bg-primary { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
background-color: rgb(0 0 0 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('index.css')).toIncludeCss(
css`
.bg-primary {
background-color: black;
}
`
)
}
}) })
}) })
@ -175,38 +150,20 @@ describe('watcher', () => {
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('index.css')).toIncludeCss(
expect(await readOutputFile('index.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('index.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -242,38 +199,20 @@ describe('watcher', () => {
await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`)
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('index.css')).toIncludeCss(
expect(await readOutputFile('index.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('index.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -396,39 +335,22 @@ describe('watcher', () => {
) )
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('index.css')).toIncludeCss(
expect(await readOutputFile('index.css')).toIncludeCss( css`
css` .btn {
.btn { border-radius: 0.25rem;
border-radius: 0.25rem; --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); padding-left: 0.5rem;
padding-left: 0.5rem; padding-right: 0.5rem;
padding-right: 0.5rem; padding-top: 0.25rem;
padding-top: 0.25rem; padding-bottom: 0.25rem;
padding-bottom: 0.25rem; }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('index.css')).toIncludeCss(
css`
.btn {
border-radius: 0.25rem;
background-color: #ef4444;
padding: 0.25rem 0.5rem;
}
.font-bold {
font-weight: 700;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })

View file

@ -1,11 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -1,11 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -2,7 +2,6 @@ let path = require('path')
let $ = require('../../execute') let $ = require('../../execute')
let { css, html, javascript } = require('../../syntax') let { css, html, javascript } = require('../../syntax')
let resolveToolRoot = require('../../resolve-tool-root') let resolveToolRoot = require('../../resolve-tool-root')
let { env } = require('../../../lib/lib/sharedState')
let version = require('../../../package.json').version let version = require('../../../package.json').version
@ -19,7 +18,6 @@ let {
}) })
let EXECUTABLE = 'node ../../lib/cli.js' let EXECUTABLE = 'node ../../lib/cli.js'
let testStable = env.ENGINE === 'stable' ? test : test.skip
function dedent(input) { function dedent(input) {
let lines = input.split('\n') let lines = input.split('\n')
@ -98,7 +96,46 @@ describe('Build command', () => {
expect(withoutMinify.length).toBeGreaterThan(withMinify.length) expect(withoutMinify.length).toBeGreaterThan(withMinify.length)
}) })
testStable('--no-autoprefixer', async () => { test('--minify does not break nested CSS', async () => {
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
await writeInputFile(
'input.css',
css`
.parent {
& .child {
color: red;
}
& .child {
&:not([href]) {
color: green;
}
}
}
`
)
await $(`${EXECUTABLE} --input ./src/input.css --output ./dist/main.css --minify`)
let withMinify = await readOutputFile('main.css')
// Verify that we got the expected output. Note: `.toIncludeCss` formats
// `actual` & `expected`
expect(withMinify).toIncludeCss(
css`
.parent {
& .child {
color: red;
}
& .child {
&:not([href]) {
color: green;
}
}
}
`
)
})
test('--no-autoprefixer', async () => {
await writeInputFile('index.html', html`<div class="select-none"></div>`) await writeInputFile('index.html', html`<div class="select-none"></div>`)
await $(`${EXECUTABLE} --output ./dist/main.css`) await $(`${EXECUTABLE} --output ./dist/main.css`)
@ -170,6 +207,52 @@ describe('Build command', () => {
) )
}) })
test('configs support import.meta', async () => {
// Skip this test in Node 18 as this only works with
// `require(esm)` in Node 20.19+
if (process.versions.node.startsWith('18.')) {
expect(true).toBe(true)
return
}
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
let customConfig = `
console.log(import.meta.url)
console.log(import.meta.resolve('./tailwind.config.mjs'))
export default ${JSON.stringify(
{
content: ['./src/index.html'],
theme: {
extend: {
fontWeight: {
bold: 'BOLD',
},
},
},
corePlugins: {
preflight: false,
},
plugins: [],
},
null,
2
)}
`
await writeInputFile('../tailwind.config.mjs', customConfig)
await $(`${EXECUTABLE} --output ./dist/main.css --config ./tailwind.config.mjs`)
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.font-bold {
font-weight: BOLD;
}
`
)
})
test('--content', async () => { test('--content', async () => {
await writeInputFile('other.html', html`<div class="font-bold"></div>`) await writeInputFile('other.html', html`<div class="font-bold"></div>`)
@ -184,7 +267,7 @@ describe('Build command', () => {
) )
}) })
testStable('--postcss (postcss.config.js)', async () => { test('--postcss (postcss.config.js)', async () => {
await writeInputFile('index.html', html`<div class="font-bold"></div>`) await writeInputFile('index.html', html`<div class="font-bold"></div>`)
let customConfig = javascript` let customConfig = javascript`
@ -217,45 +300,25 @@ describe('Build command', () => {
await $(`${EXECUTABLE} --output ./dist/main.css --postcss`) await $(`${EXECUTABLE} --output ./dist/main.css --postcss`)
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .font-bold-after {
.font-bold-after { font-weight: 700;
font-weight: 700; }
}
.btn-after { .btn-after {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
padding-left: 0.5rem; padding-left: 0.5rem;
padding-right: 0.5rem; padding-right: 0.5rem;
padding-top: 0.25rem; padding-top: 0.25rem;
padding-bottom: 0.25rem; padding-bottom: 0.25rem;
} }
` `
) )
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.font-bold-after {
font-weight: 700;
}
.btn-after {
background-color: #ef4444;
padding-left: 0.5rem;
padding-right: 0.5rem;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
`
)
}
}) })
testStable('--postcss (custom.postcss.config.js)', async () => { test('--postcss (custom.postcss.config.js)', async () => {
await writeInputFile('index.html', html`<div class="font-bold"></div>`) await writeInputFile('index.html', html`<div class="font-bold"></div>`)
let customConfig = javascript` let customConfig = javascript`
@ -288,45 +351,25 @@ describe('Build command', () => {
await $(`${EXECUTABLE} --output ./dist/main.css --postcss ./custom.postcss.config.js`) await $(`${EXECUTABLE} --output ./dist/main.css --postcss ./custom.postcss.config.js`)
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .font-bold-after {
.font-bold-after { font-weight: 700;
font-weight: 700; }
}
.btn-after { .btn-after {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
padding-left: 0.5rem; padding-left: 0.5rem;
padding-right: 0.5rem; padding-right: 0.5rem;
padding-top: 0.25rem; padding-top: 0.25rem;
padding-bottom: 0.25rem; padding-bottom: 0.25rem;
} }
` `
) )
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.font-bold-after {
font-weight: 700;
}
.btn-after {
background-color: #ef4444;
padding-left: 0.5rem;
padding-right: 0.5rem;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
`
)
}
}) })
testStable('--postcss supports process options', async () => { test('--postcss supports process options', async () => {
await writeInputFile('index.html', html`<div class="font-bold"></div>`) await writeInputFile('index.html', html`<div class="font-bold"></div>`)
let customConfig = javascript` let customConfig = javascript`
@ -360,7 +403,7 @@ describe('Build command', () => {
expect(contents).toContain(`/*# sourceMappingURL`) expect(contents).toContain(`/*# sourceMappingURL`)
}) })
testStable('--postcss supports process options with custom config', async () => { test('--postcss supports process options with custom config', async () => {
await writeInputFile('index.html', html`<div class="font-bold"></div>`) await writeInputFile('index.html', html`<div class="font-bold"></div>`)
let customConfig = javascript` let customConfig = javascript`
@ -394,6 +437,79 @@ describe('Build command', () => {
expect(contents).toContain(`/*# sourceMappingURL`) expect(contents).toContain(`/*# sourceMappingURL`)
}) })
test('--postcss supports ESM configs', async () => {
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
let customConfig = javascript`
import * as path from 'path'
import { createRequire } from 'module'
const require = createRequire(import.meta.url)
export default {
map: { inline: true },
plugins: [
function tailwindcss() {
return require(path.resolve('..', '..'))
},
],
}
`
await removeFile('./postcss.config.js')
await writeInputFile('../postcss.config.mjs', customConfig)
await $(`${EXECUTABLE} --output ./dist/main.css --postcss`)
let contents = await readOutputFile('main.css')
expect(contents).toIncludeCss(
css`
.font-bold {
font-weight: 700;
}
`
)
expect(contents).toContain(`/*# sourceMappingURL`)
})
test('--postcss supports TS configs', async () => {
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
let customConfig = javascript`
import * as path from 'path'
import { createRequire } from 'module'
import type { AcceptedPlugin } from 'postcss'
const require = createRequire(import.meta.url)
export default {
map: { inline: true },
plugins: [
function tailwindcss() {
return require(path.resolve('..', '..'))
} as AcceptedPlugin,
],
}
`
await removeFile('./postcss.config.js')
await writeInputFile('../postcss.config.ts', customConfig)
await $(`${EXECUTABLE} --output ./dist/main.css --postcss`)
let contents = await readOutputFile('main.css')
expect(contents).toIncludeCss(
css`
.font-bold {
font-weight: 700;
}
`
)
expect(contents).toContain(`/*# sourceMappingURL`)
})
test('postcss-import is supported by default', async () => { test('postcss-import is supported by default', async () => {
cleanupFile('src/test.css') cleanupFile('src/test.css')
@ -481,7 +597,7 @@ describe('Build command', () => {
return runningProcess.stop() return runningProcess.stop()
}) })
testStable('postcss-import is included when using a custom postcss configuration', async () => { test('postcss-import is included when using a custom postcss configuration', async () => {
cleanupFile('src/test.css') cleanupFile('src/test.css')
await writeInputFile('index.html', html`<div class="md:something-cool"></div>`) await writeInputFile('index.html', html`<div class="md:something-cool"></div>`)
@ -509,28 +625,8 @@ describe('Build command', () => {
test('--help', async () => { test('--help', async () => {
let { combined } = await $(`${EXECUTABLE} --help`) let { combined } = await $(`${EXECUTABLE} --help`)
if (env.ENGINE === 'oxide') { expect(dedent(combined)).toEqual(
expect(dedent(combined)).toEqual( dedent(`
dedent(`
tailwindcss v${version}
Usage:
tailwindcss build [options]
Options:
-i, --input Input file
-o, --output Output file
-w, --watch Watch for changes and rebuild as needed
-p, --poll Use polling instead of filesystem events when watching
--content Content paths to use for removing unused classes
-m, --minify Minify the output
-c, --config Path to a custom config file
-h, --help Display usage information
`)
)
} else if (env.ENGINE === 'stable') {
expect(dedent(combined)).toEqual(
dedent(`
tailwindcss v${version} tailwindcss v${version}
Usage: Usage:
@ -548,8 +644,7 @@ describe('Build command', () => {
--no-autoprefixer Disable autoprefixer --no-autoprefixer Disable autoprefixer
-h, --help Display usage information -h, --help Display usage information
`) `)
) )
}
}) })
}) })
@ -611,7 +706,7 @@ describe('Init command', () => {
expect((await readOutputFile('../full.config.js')).split('\n').length).toBeGreaterThan(50) expect((await readOutputFile('../full.config.js')).split('\n').length).toBeGreaterThan(50)
}) })
testStable('--postcss', async () => { test('--postcss', async () => {
expect(await fileExists('postcss.config.js')).toBe(true) expect(await fileExists('postcss.config.js')).toBe(true)
await removeFile('postcss.config.js') await removeFile('postcss.config.js')
expect(await fileExists('postcss.config.js')).toBe(false) expect(await fileExists('postcss.config.js')).toBe(false)
@ -631,38 +726,21 @@ describe('Init command', () => {
test('--help', async () => { test('--help', async () => {
let { combined } = await $(`${EXECUTABLE} init --help`) let { combined } = await $(`${EXECUTABLE} init --help`)
if (env.ENGINE === 'oxide') { expect(dedent(combined)).toEqual(
expect(dedent(combined)).toEqual( dedent(`
dedent(` tailwindcss v${version}
tailwindcss v${version}
Usage: Usage:
tailwindcss init [options] tailwindcss init [options]
Options: Options:
--esm Initialize configuration file as ESM --esm Initialize configuration file as ESM
--ts Initialize configuration file as TypeScript --ts Initialize configuration file as TypeScript
-f, --full Include the default values for all options in the generated configuration file -p, --postcss Initialize a \`postcss.config.js\` file
-h, --help Display usage information -f, --full Include the default values for all options in the generated configuration file
`) -h, --help Display usage information
) `)
} else if (env.ENGINE === 'stable') { )
expect(dedent(combined)).toEqual(
dedent(`
tailwindcss v${version}
Usage:
tailwindcss init [options]
Options:
--esm Initialize configuration file as ESM
--ts Initialize configuration file as TypeScript
-p, --postcss Initialize a \`postcss.config.js\` file
-f, --full Include the default values for all options in the generated configuration file
-h, --help Display usage information
`)
)
}
}) })
test('ESM config is created by default in an ESM project', async () => { test('ESM config is created by default in an ESM project', async () => {

View file

@ -1,7 +1,6 @@
let fs = require('fs') let fs = require('fs')
let $ = require('../../execute') let $ = require('../../execute')
let { css, html, javascript } = require('../../syntax') let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
let { readOutputFile, appendToInputFile, writeInputFile, removeFile } = require('../../io')({ let { readOutputFile, appendToInputFile, writeInputFile, removeFile } = require('../../io')({
output: 'dist', output: 'dist',
@ -72,43 +71,23 @@ describe('static build', () => {
env: { NODE_ENV: 'production' }, env: { NODE_ENV: 'production' },
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
}
.bg-red-600 { .bg-red-600 {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(220 38 38 / var(--tw-bg-opacity)); background-color: rgb(220 38 38 / var(--tw-bg-opacity, 1));
} }
.font-bold { .font-bold {
font-weight: 700; font-weight: 700;
} }
` `
) )
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.bg-red-600 {
background-color: #dc2626;
}
.font-bold {
font-weight: 700;
}
`
)
}
}) })
it('can use a tailwind.config.js configuration file with ESM syntax', async () => { it('can use a tailwind.config.js configuration file with ESM syntax', async () => {
@ -145,85 +124,64 @@ describe('static build', () => {
env: { NODE_ENV: 'production' }, env: { NODE_ENV: 'production' },
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-primary {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
}
`
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-primary {
background-color: black;
}
`
)
}
})
it('can use a tailwind.config.ts configuration file', async () => {
await removeFile('tailwind.config.js')
await writeInputFile('index.html', html`<div class="bg-primary"></div>`)
await writeInputFile(
'index.css',
css` css`
@tailwind base; .bg-primary {
@tailwind components; --tw-bg-opacity: 1;
@tailwind utilities; background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
}
` `
) )
await writeInputFile( })
'../tailwind.config.ts',
javascript`
import type { Config } from 'tailwindcss'
export default { it.each([['../tailwind.config.ts'], ['../tailwind.config.cts'], ['../tailwind.config.mts']])(
content: ['./src/index.html'], 'can use a %s configuration file',
theme: { async (path) => {
extend: { await removeFile('tailwind.config.js')
colors: { await writeInputFile('index.html', html`<div class="bg-primary"></div>`)
primary: 'black', await writeInputFile(
'index.css',
css`
@tailwind base;
@tailwind components;
@tailwind utilities;
`
)
await writeInputFile(
path,
javascript`
import type { Config } from 'tailwindcss'
export default {
content: ['./src/index.html'],
theme: {
extend: {
colors: {
primary: 'black',
},
}, },
}, },
}, corePlugins: {
corePlugins: { preflight: false,
preflight: false, },
}, } satisfies Config
} satisfies Config `
` )
)
await $('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css', { await $('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css', {
env: { NODE_ENV: 'production' }, env: { NODE_ENV: 'production' },
}) })
if (env.ENGINE === 'stable') {
expect(await readOutputFile('main.css')).toIncludeCss( expect(await readOutputFile('main.css')).toIncludeCss(
css` css`
.bg-primary { .bg-primary {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity)); background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
} }
` `
) )
} }
)
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-primary {
background-color: black;
}
`
)
}
})
it('can read from a config file from an @config directive', async () => { it('can read from a config file from an @config directive', async () => {
await writeInputFile('index.html', html`<div class="bg-yellow"></div>`) await writeInputFile('index.html', html`<div class="bg-yellow"></div>`)
@ -262,26 +220,14 @@ describe('static build', () => {
env: { NODE_ENV: 'production' }, env: { NODE_ENV: 'production' },
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-yellow {
.bg-yellow { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(255 255 0 / var(--tw-bg-opacity, 1));
background-color: rgb(255 255 0 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-yellow {
background-color: #ff0;
}
`
)
}
}) })
it('can read from a config file from an @config directive inside an @import from postcss-import', async () => { it('can read from a config file from an @config directive inside an @import from postcss-import', async () => {
@ -329,26 +275,14 @@ describe('static build', () => {
env: { NODE_ENV: 'production' }, env: { NODE_ENV: 'production' },
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-yellow {
.bg-yellow { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(255 255 0 / var(--tw-bg-opacity, 1));
background-color: rgb(255 255 0 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-yellow {
background-color: #ff0;
}
`
)
}
}) })
it('should work with raw content', async () => { it('should work with raw content', async () => {
@ -375,26 +309,14 @@ describe('static build', () => {
env: { NODE_ENV: 'production' }, env: { NODE_ENV: 'production' },
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
`
)
}
}) })
}) })
@ -430,38 +352,20 @@ describe('watcher', () => {
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -497,38 +401,20 @@ describe('watcher', () => {
await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`)
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -703,42 +589,22 @@ describe('watcher', () => {
) )
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .btn {
.btn { border-radius: 0.25rem;
border-radius: 0.25rem; --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); padding-left: 0.5rem;
padding-left: 0.5rem; padding-right: 0.5rem;
padding-right: 0.5rem; padding-top: 0.25rem;
padding-top: 0.25rem; padding-bottom: 0.25rem;
padding-bottom: 0.25rem; }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.btn {
border-radius: 0.25rem;
background-color: #ef4444;
padding-left: 0.5rem;
padding-right: 0.5rem;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
.font-bold {
font-weight: 700;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -800,26 +666,14 @@ describe('watcher', () => {
let runningProcess = $('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css -w') let runningProcess = $('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css -w')
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-yellow {
.bg-yellow { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(255 255 0 / var(--tw-bg-opacity, 1));
background-color: rgb(255 255 0 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-yellow {
background-color: #ff0;
}
`
)
}
await writeInputFile( await writeInputFile(
'index.css', 'index.css',
@ -832,26 +686,14 @@ describe('watcher', () => {
) )
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-yellow {
.bg-yellow { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(255 255 119 / var(--tw-bg-opacity, 1));
background-color: rgb(255 255 119 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-yellow {
background-color: #ff7;
}
`
)
}
await writeInputFile( await writeInputFile(
'tailwind.2.config.js', 'tailwind.2.config.js',
@ -876,26 +718,14 @@ describe('watcher', () => {
) )
await runningProcess.onStderr(ready) await runningProcess.onStderr(ready)
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-yellow {
.bg-yellow { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
background-color: rgb(255 255 255 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-yellow {
background-color: #fff;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })

View file

@ -1,12 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./index.css"> <link rel="stylesheet" href="./index.css" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -1,12 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./index.css"> <link rel="stylesheet" href="./index.css" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -21,6 +21,6 @@
}, },
"devDependencies": { "devDependencies": {
"isomorphic-fetch": "^3.0.0", "isomorphic-fetch": "^3.0.0",
"vite": "^4.3.2" "vite": "^5.1.6"
} }
} }

View file

@ -2,7 +2,6 @@ require('isomorphic-fetch')
let $ = require('../../execute') let $ = require('../../execute')
let { css, html, javascript } = require('../../syntax') let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
let { readOutputFile, appendToInputFile, writeInputFile, removeFile } = require('../../io')({ let { readOutputFile, appendToInputFile, writeInputFile, removeFile } = require('../../io')({
output: 'dist', output: 'dist',
@ -34,7 +33,7 @@ describe('static build', () => {
env: { NODE_ENV: 'production', NO_COLOR: '1' }, env: { NODE_ENV: 'production', NO_COLOR: '1' },
}) })
expect(await readOutputFile(/index.\w+\.css$/)).toIncludeCss( expect(await readOutputFile(/index.[a-z0-9_-]+\.css$/i)).toIncludeCss(
css` css`
.font-bold { .font-bold {
font-weight: 700; font-weight: 700;
@ -75,26 +74,14 @@ describe('static build', () => {
env: { NODE_ENV: 'production', NO_COLOR: '1' }, env: { NODE_ENV: 'production', NO_COLOR: '1' },
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile(/index.[a-z0-9_-]+\.css$/i)).toIncludeCss(
expect(await readOutputFile(/index.\w+\.css$/)).toIncludeCss( css`
css` .bg-primary {
.bg-primary { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
background-color: rgb(0 0 0 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile(/index.\w+\.css$/)).toIncludeCss(
css`
.bg-primary {
background-color: black;
}
`
)
}
}) })
it('can use a tailwind.config.ts configuration file', async () => { it('can use a tailwind.config.ts configuration file', async () => {
@ -131,26 +118,14 @@ describe('static build', () => {
env: { NODE_ENV: 'production', NO_COLOR: '1' }, env: { NODE_ENV: 'production', NO_COLOR: '1' },
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile(/index.[a-z0-9_-]+\.css$/i)).toIncludeCss(
expect(await readOutputFile(/index.\w+\.css$/)).toIncludeCss( css`
css` .bg-primary {
.bg-primary { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
background-color: rgb(0 0 0 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile(/index.\w+\.css$/)).toIncludeCss(
css`
.bg-primary {
background-color: black;
}
`
)
}
}) })
}) })
@ -194,38 +169,20 @@ describe('watcher', () => {
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
await runningProcess.onStdout((message) => message.includes('page reload')) await runningProcess.onStdout((message) => message.includes('page reload'))
if (env.ENGINE === 'stable') { expect(await fetchCSS()).toIncludeCss(
expect(await fetchCSS()).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await fetchCSS()).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -265,38 +222,20 @@ describe('watcher', () => {
await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`)
await runningProcess.onStdout((message) => message.includes('page reload')) await runningProcess.onStdout((message) => message.includes('page reload'))
if (env.ENGINE === 'stable') { expect(await fetchCSS()).toIncludeCss(
expect(await fetchCSS()).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await fetchCSS()).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -435,42 +374,22 @@ describe('watcher', () => {
) )
await runningProcess.onStdout((message) => message.includes('hmr update /index.css')) await runningProcess.onStdout((message) => message.includes('hmr update /index.css'))
if (env.ENGINE === 'stable') { expect(await fetchCSS()).toIncludeCss(
expect(await fetchCSS()).toIncludeCss( css`
css` .btn {
.btn { border-radius: 0.25rem;
border-radius: 0.25rem; --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); padding-left: 0.5rem;
padding-left: 0.5rem; padding-right: 0.5rem;
padding-right: 0.5rem; padding-top: 0.25rem;
padding-top: 0.25rem; padding-bottom: 0.25rem;
padding-bottom: 0.25rem; }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await fetchCSS()).toIncludeCss(
css`
.btn {
border-radius: 0.25rem;
background-color: #ef4444;
padding-left: 0.5rem;
padding-right: 0.5rem;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
.font-bold {
font-weight: 700;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })

View file

@ -1,11 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -1,11 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -1,6 +1,5 @@
let $ = require('../../execute') let $ = require('../../execute')
let { css, html, javascript } = require('../../syntax') let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
let { let {
appendToInputFile, appendToInputFile,
@ -58,26 +57,14 @@ describe('static build', () => {
await $('webpack --mode=production') await $('webpack --mode=production')
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-primary {
.bg-primary { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
background-color: rgb(0 0 0 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-primary {
background-color: black;
}
`
)
}
}) })
it('can use a tailwind.config.ts configuration file', async () => { it('can use a tailwind.config.ts configuration file', async () => {
@ -114,26 +101,14 @@ describe('static build', () => {
await $('webpack --mode=production') await $('webpack --mode=production')
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-primary {
.bg-primary { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
background-color: rgb(0 0 0 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-primary {
background-color: black;
}
`
)
}
}) })
}) })
@ -172,38 +147,20 @@ describe('watcher', () => {
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -242,38 +199,20 @@ describe('watcher', () => {
await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('glob/index.html', html`<div class="bg-red-500"></div>`)
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -401,39 +340,22 @@ describe('watcher', () => {
) )
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .btn {
.btn { border-radius: 0.25rem;
border-radius: 0.25rem; --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); padding-left: 0.5rem;
padding-left: 0.5rem; padding-right: 0.5rem;
padding-right: 0.5rem; padding-top: 0.25rem;
padding-top: 0.25rem; padding-bottom: 0.25rem;
padding-bottom: 0.25rem; }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.btn {
background-color: #ef4444;
border-radius: 0.25rem;
padding: 0.25rem 0.5rem;
}
.font-bold {
font-weight: 700;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })

View file

@ -1,11 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -1,11 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View file

@ -1,6 +1,5 @@
let $ = require('../../execute') let $ = require('../../execute')
let { css, html, javascript } = require('../../syntax') let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
let { let {
appendToInputFile, appendToInputFile,
@ -58,26 +57,14 @@ describe('static build', () => {
await $('webpack --mode=production') await $('webpack --mode=production')
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-primary {
.bg-primary { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
background-color: rgb(0 0 0 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-primary {
background-color: black;
}
`
)
}
}) })
it('can use a tailwind.config.ts configuration file', async () => { it('can use a tailwind.config.ts configuration file', async () => {
@ -114,26 +101,14 @@ describe('static build', () => {
await $('webpack --mode=production') await $('webpack --mode=production')
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-primary {
.bg-primary { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
background-color: rgb(0 0 0 / var(--tw-bg-opacity)); }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-primary {
background-color: black;
}
`
)
}
}) })
}) })
@ -172,38 +147,20 @@ describe('watcher', () => {
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -242,38 +199,20 @@ describe('watcher', () => {
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`) await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} .font-normal {
.font-normal { font-weight: 400;
font-weight: 400; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -401,39 +340,22 @@ describe('watcher', () => {
) )
}) })
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .btn {
.btn { border-radius: 0.25rem;
border-radius: 0.25rem; --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); padding-left: 0.5rem;
padding-left: 0.5rem; padding-right: 0.5rem;
padding-right: 0.5rem; padding-top: 0.25rem;
padding-top: 0.25rem; padding-bottom: 0.25rem;
padding-bottom: 0.25rem; }
} .font-bold {
.font-bold { font-weight: 700;
font-weight: 700; }
} `
` )
)
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.btn {
background-color: #ef4444;
border-radius: 0.25rem;
padding: 0.25rem 0.5rem;
}
.font-bold {
font-weight: 700;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })
@ -464,43 +386,23 @@ describe('watcher', () => {
await waitForOutputFileCreation('main.css') await waitForOutputFileCreation('main.css')
if (env.ENGINE === 'stable') { expect(await readOutputFile('main.css')).toIncludeCss(
expect(await readOutputFile('main.css')).toIncludeCss( css`
css` .bg-red-500 {
.bg-red-500 { --tw-bg-opacity: 1;
--tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
background-color: rgb(239 68 68 / var(--tw-bg-opacity)); }
}
.bg-red-600 { .bg-red-600 {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(220 38 38 / var(--tw-bg-opacity)); background-color: rgb(220 38 38 / var(--tw-bg-opacity, 1));
} }
.font-bold { .font-bold {
font-weight: 700; font-weight: 700;
} }
` `
) )
}
if (env.ENGINE === 'oxide') {
expect(await readOutputFile('main.css')).toIncludeCss(
css`
.bg-red-500 {
background-color: #ef4444;
}
.bg-red-600 {
background-color: #dc2626;
}
.font-bold {
font-weight: 700;
}
`
)
}
return runningProcess.stop() return runningProcess.stop()
}) })

View file

@ -23,39 +23,42 @@ function formatPrettier(input) {
function format(input) { function format(input) {
try { try {
return lightningcss return [
.transform({ lightningcss
filename: 'input.css', .transform({
code: Buffer.from(input), filename: 'input.css',
minify: false, code: Buffer.from(input),
targets: { chrome: 106 << 16 }, minify: false,
drafts: { targets: { chrome: 106 << 16 },
nesting: true, drafts: {
customMedia: true, nesting: true,
}, customMedia: true,
}) },
.code.toString('utf8') })
.code.toString('utf8'),
null,
]
} catch (err) { } catch (err) {
let lines = err.source.split('\n')
let e = new Error(
[
'Error formatting using Lightning CSS:',
'',
...[
'```css',
...lines.slice(Math.max(err.loc.line - 3, 0), err.loc.line),
' '.repeat(err.loc.column - 1) + '^-- ' + err.toString(),
...lines.slice(err.loc.line, err.loc.line + 2),
'```',
],
].join('\n')
)
try { try {
// Lightning CSS is pretty strict, so it will fail for `@media screen(md) {}` for example, // Lightning CSS is pretty strict, so it will fail for `@media screen(md) {}` for example,
// in that case we can fallback to prettier since it doesn't really care. However if an // in that case we can fallback to prettier since it doesn't really care. However if an
// actual syntax error is made, then we still want to show the proper error. // actual syntax error is made, then we still want to show the proper error.
return formatPrettier(input.replace(/\n/g, '')) return [formatPrettier(input.replace(/\n/g, '')), e]
} catch { } catch {
let lines = err.source.split('\n')
let e = new Error(
[
'Error formatting using Lightning CSS:',
'',
...[
'```css',
...lines.slice(Math.max(err.loc.line - 3, 0), err.loc.line),
' '.repeat(err.loc.column - 1) + '^-- ' + err.toString(),
...lines.slice(err.loc.line, err.loc.line + 2),
'```',
],
].join('\n')
)
if (Error.captureStackTrace) { if (Error.captureStackTrace) {
Error.captureStackTrace(e, toMatchFormattedCss) Error.captureStackTrace(e, toMatchFormattedCss)
} }
@ -71,8 +74,8 @@ function toMatchFormattedCss(received = '', argument = '') {
promise: this.promise, promise: this.promise,
} }
let formattedReceived = format(received) let [formattedReceived, formattingReceivedError] = format(received)
let formattedArgument = format(argument) let [formattedArgument, formattingArgumentError] = format(argument)
let pass = formattedReceived === formattedArgument let pass = formattedReceived === formattedArgument
@ -99,7 +102,9 @@ function toMatchFormattedCss(received = '', argument = '') {
(diffString && diffString.includes('- Expect') (diffString && diffString.includes('- Expect')
? `Difference:\n\n${diffString}` ? `Difference:\n\n${diffString}`
: `Expected: ${this.utils.printExpected(expected)}\n` + : `Expected: ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(actual)}`) `Received: ${this.utils.printReceived(actual)}`) +
(formattingReceivedError ? '\n\n' + formattingReceivedError : '') +
(formattingArgumentError ? '\n\n' + formattingArgumentError : '')
) )
} }
@ -118,7 +123,9 @@ expect.extend({
promise: this.promise, promise: this.promise,
} }
let pass = format(received).includes(format(argument)) let [formattedReceived, formattedReceivedError] = format(received)
let [formattedArgument, formattedArgumentError] = format(argument)
let pass = formattedReceived.includes(formattedArgument)
let message = pass let message = pass
? () => { ? () => {
@ -143,7 +150,9 @@ expect.extend({
(diffString && diffString.includes('- Expect') (diffString && diffString.includes('- Expect')
? `Difference:\n\n${diffString}` ? `Difference:\n\n${diffString}`
: `Expected: ${this.utils.printExpected(expected)}\n` + : `Expected: ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(actual)}`) `Received: ${this.utils.printReceived(actual)}`) +
(formattedReceivedError ? '\n\n' + formattedReceivedError : '') +
(formattedArgumentError ? '\n\n' + formattedArgumentError : '')
) )
} }

1
oxide/.gitignore vendored
View file

@ -1 +0,0 @@
target/

1042
oxide/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
[workspace]
resolver = "2"
members = ["crates/*"]
[profile.release]
lto = true

View file

@ -1 +0,0 @@
## Tailwind CSS Oxide

View file

@ -1,9 +0,0 @@
[package]
name = "tailwindcss-oxide"
version = "0.1.0"
edition = "2021"
[dependencies]
clap = { version = "4.0.18", features = ["derive"] }
rayon = "1.5.3"
tailwindcss-core = { path = "../core" }

View file

@ -1,132 +0,0 @@
use clap::{Args, Parser, Subcommand};
use rayon::prelude::*;
use std::fmt::Debug;
use std::fs::{self, File};
use std::io::{self, BufRead};
use std::path::{Path, PathBuf};
use std::time::Instant;
use tailwindcss_core::glob;
use tailwindcss_core::parser::Extractor;
use tailwindcss_core::candidate::Candidate;
/// Tailwind CLI
#[derive(Parser, Debug)]
struct Cli {
/// The current working directory
#[arg(long, default_value = ".")]
pwd: PathBuf,
/// Path to a custom config file
#[arg(short, long, default_value = "tailwind.config.js")]
config: String,
/// Build
#[command(flatten)]
build: Build,
/// The subcommand to run
#[command(subcommand)]
subcommand: Option<Commands>,
}
#[derive(Args, Debug)]
#[command()]
#[group()]
struct Build {
/// Input file
#[arg(short, long)]
input: Option<String>,
/// Output file
#[arg(short, long)]
output: Option<String>,
/// Watch for changes and rebuild as needed
#[arg(short, long)]
watch: bool,
/// Use polling instead of filesystem events when watching
#[arg(short, long)]
poll: bool,
/// Content paths to use for removing unused classes
#[arg(long, default_value = "**/*.html")]
content: Vec<String>,
/// Load custom PostCSS configuration
#[arg(long)]
postcss: bool,
/// Minify the output
#[arg(short, long)]
minify: bool,
/// Disable autoprefixer
#[arg(long)]
no_autoprefixer: bool,
}
#[derive(Subcommand, Debug)]
enum Commands {
/// Initialize your Tailwind project
Init {
/// Initialize a full `tailwind.config.js` file
#[clap(short, long)]
full: bool,
/// Initialize a `postcss.config.js` file
#[clap(short, long)]
postcss: bool,
},
}
// The output is wrapped in a Result to allow matching on errors
// Returns an Iterator to the Reader of the lines of the file.
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where
P: AsRef<Path>,
{
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}
fn main() -> Result<(), std::io::Error> {
let mut args = Cli::parse();
args.pwd = fs::canonicalize(&args.pwd)?;
let now = Instant::now();
let patterns = args.build.content;
let content_paths = glob::fast_glob(&args.pwd, &patterns)?;
let total_paths = glob::fast_glob(&args.pwd, &patterns)?.count();
let candidates = content_paths.par_bridge().flat_map(|path| {
read_lines(path)
.unwrap()
.filter_map(Result::ok)
.par_bridge()
.flat_map_iter(|line| {
Extractor::unique(line.as_bytes(), Default::default())
.into_iter()
.map(|candidate| Candidate::new(String::from_utf8(candidate.to_vec()).unwrap()))
.collect::<Vec<_>>()
})
});
println!("Total files: {}", total_paths);
println!("Total candidates: {}", candidates.count());
println!("Took: {:?}", now.elapsed());
Ok(())
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
// ...
}
}

View file

@ -1,8 +0,0 @@
[package]
name = "tailwindcss-config"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View file

@ -1,30 +0,0 @@
use std::collections::HashMap;
#[derive(Debug, Default)]
pub struct Config {
pub prefix: Option<String>,
pub important: bool,
pub separator: String,
pub content: Content,
pub theme: Theme,
pub plugins: Vec<Option<bool>>,
}
#[derive(Debug, Default)]
pub struct Theme {
pub colors: HashMap<String, String>,
}
#[derive(Debug, Default)]
pub struct Content {
pub relative: bool,
pub files: Vec<File>,
}
#[derive(Debug, Default)]
pub struct File {
pub raw: Option<String>,
pub path: Option<String>,
pub extension: Option<String>,
}

View file

@ -1,25 +0,0 @@
[package]
name = "tailwindcss-core"
version = "0.1.0"
edition = "2021"
[dependencies]
bstr = "1.0.1"
globwalk = "0.8.1"
log = "0.4"
rayon = "1.5.3"
fxhash = "0.2.1"
crossbeam = "0.8.2"
tracing = { version = "0.1.37", features = [] }
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
[dev-dependencies]
criterion = { version = "0.3", features = ['html_reports'] }
[[bench]]
name = "parse_candidates"
harness = false
[[bench]]
name = "parse_candidate_strings_from_files"
harness = false

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,5 +0,0 @@
<div class="sm:items-baseline sm:space-x-4 flex">
<a href="#" target="_blank" class="block sm:hidden px-4 py-2 text-sm">
This is link afe0b95d-703b-4471-b828-7fee034e18a0
</a>
</div>

View file

@ -1,613 +0,0 @@
<div class="font-semibold px-3 text-left text-gray-900 py-3.5 text-sm">
<nav class="font-medium text-gray-900">
<ul class="h-7 justify-center rounded-full items-center w-7 flex mx-auto">
<li class="h-0.5 inset-x-0 absolute bottom-0">
<a href="#" target="_blank" class="space-y-1 px-2 mt-3">
This is link 4132f37a-a03f-4776-9a8e-1b70ff626f71
</a>
<img
class="text-gray-900 font-medium text-sm ml-3.5"
alt="Profile picture of user 40faf8f0-6221-4ec4-a65e-fe22e1d9abd2"
src="https://example.org/pictures/4f7d7f80-e9cd-447a-9b35-f9d93befe025"
/>
</li>
<li class="text-indigo-700 order-1 font-semibold">
<ol
class="h-24 sm:w-32 w-24 object-center rounded-md sm:h-32 object-cover"
>
<li
class="lg:justify-center lg:gap-x-12 hidden lg:flex lg:min-w-0 lg:flex-1"
>
<img
class="hover:bg-gray-100 bg-gray-50 py-1.5 focus:z-10 text-gray-400"
alt="Profile picture of user d27b5a21-1622-4f3a-ba7d-6230fae487c2"
src="https://example.org/pictures/2a026d06-0e67-467d-babf-8a18614667f2"
/>
<ul class="w-6 h-6 mr-3 flex-shrink-0">
<li class="flow-root">
<img
class="bg-white focus:ring-indigo-500 group font-medium items-center inline-flex focus:ring-offset-2 focus:ring-2 focus:outline-none text-base rounded-md hover:text-gray-900"
alt="Profile picture of user 0052230e-90d8-4d84-ab64-904b87fe4622"
src="https://example.org/pictures/f7ec91ba-17a7-470f-a472-705a8b5a79ce"
/>
</li>
<li
class="items-center right-0 flex pointer-events-none absolute inset-y-0"
>
<img
class="ml-3"
alt="Profile picture of user a7c51adf-3917-4e41-b5f1-d263768c9adf"
src="https://example.org/pictures/a56323a8-8aa3-4d39-8c79-9ee875ecd6f0"
/>
</li>
</ul>
<ul class="hover:bg-opacity-75 hover:bg-indigo-500 text-white">
<li
class="font-medium hover:text-indigo-500 text-indigo-600 text-sm"
>
<ul class="sr-only"></ul>
<ol class="flex-col px-8 flex pt-8"></ol>
<a href="#" class="items-center sm:items-start flex">
This is link 8c59d1ad-9ef0-4a41-ab15-e9fe04d77ae2
</a>
</li>
<li class="rounded-full w-8 h-8">
<ol class="lg:grid lg:grid-cols-12"></ol>
<a
href="#"
target="_blank"
rel="noreferrer"
class="px-4 border-t py-6 space-y-6 border-gray-200"
>
This is link 4182f198-ff54-45a4-ace9-e6f46a60ec92
</a>
</li>
<li class="border-gray-700 border-t pt-4 pb-3">
<ol class="font-medium text-gray-900 p-2 block -m-2"></ol>
<ol
class="sm:py-24 to-green-400 lg:px-0 bg-gradient-to-r lg:items-center lg:justify-end sm:px-6 lg:bg-none from-cyan-600 px-4 lg:pl-8 py-16 lg:flex"
></ol>
<img
class="lg:gap-24 lg:grid-cols-2 lg:grid lg:mx-auto lg:items-start lg:max-w-7xl lg:px-8"
alt="Profile picture of user c44d18a8-a1f1-4bf4-87b0-89f37e34aba1"
src="https://example.org/pictures/527dca2c-5afe-4a5c-96cd-706396701c36"
/>
</li>
<li
class="hover:bg-gray-100 bg-white focus:z-10 text-gray-900 relative py-1.5"
>
<a
href="#"
target="_blank"
rel="noreferrer"
class="text-sm font-medium text-gray-500"
>
This is link f6db0c8d-6409-4abd-9af1-d3e68ebbd25c
</a>
<a href="#" rel="noreferrer" class="text-sm font-medium mt-12">
This is link 51c9b242-e449-44d8-9289-1a5d474d5fbb
</a>
<ul class="h-12"></ul>
</li>
<li class="bg-gray-100">
<a href="#" rel="noreferrer" class="bg-gray-100">
This is link eb479051-0dff-4d8f-9456-bb8b56ab90af
</a>
<img
class="ml-3 text-gray-900 font-medium text-base"
alt="Profile picture of user 17d797ac-aea7-4154-b522-f0ac89762b0b"
src="https://example.org/pictures/55e31a5b-2fcb-4b35-832c-fad711717f1a"
/>
<ul
class="font-medium hover:text-gray-700 text-gray-500 ml-4 text-sm"
></ul>
</li>
</ul>
<ul class="space-y-6 border-t py-6 border-gray-200 px-4">
<li class="md:hidden z-40 relative">
<ol
class="h-7 w-7 mx-auto items-center justify-center rounded-full flex"
></ol>
<ol
class="items-center flex rounded-full w-7 mx-auto h-7 justify-center"
></ol>
<a
href="#"
target="_blank"
class="sm:py-32 lg:px-8 max-w-7xl mx-auto px-4 py-24 sm:px-6 relative"
>
This is link 5014471c-4f44-4696-a1f6-7817d57827eb
</a>
<img
class="h-5 group-hover:text-gray-500 w-5 ml-2"
alt="Profile picture of user 98731873-0af8-4823-9115-f1333a2cdc2e"
src="https://example.org/pictures/12ac8cbf-4540-49ff-a71f-4b0ac684b374"
/>
</li>
<li
class="focus:outline-none font-medium px-4 justify-center text-sm focus:ring-2 border hover:bg-gray-50 focus:ring-offset-2 py-2 border-gray-300 bg-white inline-flex text-gray-700 rounded-md shadow-sm focus:ring-gray-900"
>
<img
class="bg-white focus:ring-indigo-500 text-base focus:outline-none focus:ring-2 items-center font-medium focus:ring-offset-2 hover:text-gray-900 rounded-md group inline-flex"
alt="Profile picture of user 3ae3670d-c729-41d2-adee-691340673aef"
src="https://example.org/pictures/5f289b87-efc2-4cc9-9061-21883b0778db"
/>
</li>
<li class="text-base text-gray-500 mt-6 font-medium text-center">
<ol
class="text-sm font-medium text-indigo-600 hover:text-indigo-500"
></ol>
<ol class="rounded-md h-6 w-6 inline-block"></ol>
</li>
<li class="hidden lg:flex lg:items-center">
<ol class="border-indigo-600"></ol>
</li>
</ul>
</li>
<li class="sr-only">
<img
class="justify-center py-2 bg-white flex"
alt="Profile picture of user 89195190-9a42-4826-89ba-e7bc1d677520"
src="https://example.org/pictures/742d9c44-1c75-461f-b2d0-e52636041966"
/>
<img
class="-ml-14 sticky left-0 z-20 text-gray-400 -mt-2.5 leading-5 pr-2 w-14 text-right text-xs"
alt="Profile picture of user 77a37b14-1c0f-4ef0-85d4-a18755065ea3"
src="https://example.org/pictures/8ad2e05f-6ea6-4d94-8f82-f8aa59274b9e"
/>
</li>
</ol>
<img
class="border-t shadow-sm sm:border bg-white sm:rounded-lg border-gray-200 border-b"
alt="Profile picture of user 07935cf2-78e5-49ba-afdb-09d13c8320d6"
src="https://example.org/pictures/8f895991-6e8c-4bcb-82c3-11c2a3338eb2"
/>
<ol class="grid-cols-2 grid gap-x-8 gap-y-10">
<li
class="py-1 w-48 shadow-lg bg-white rounded-md ring-1 absolute ring-black z-10 focus:outline-none right-0 mt-2 ring-opacity-5 origin-top-right"
>
<ol class="h-6 w-6">
<li
class="bg-gray-500 inset-0 transition-opacity fixed bg-opacity-75"
>
<ol class="flex"></ol>
<a href="#" class="mt-2 flex items-center justify-between">
This is link 1a1a3c60-a2ea-4153-acd7-12aa82f03c8d
</a>
<a
href="#"
target="_blank"
class="text-gray-300 flex-shrink-0 w-5 h-5"
>
This is link bdaa695c-3fe4-4cab-8d68-dbb338601044
</a>
</li>
<li class="text-gray-500">
<ol class="py-20"></ol>
<a href="#" target="_blank" class="text-sm ml-3">
This is link 2183c71d-39ec-42d4-8b1e-eeb7e5490050
</a>
</li>
<li class="mt-10">
<ol class="group"></ol>
<a href="#" rel="noreferrer" class="bg-gray-50">
This is link c49882fd-ab55-41a4-8dac-b96fe2901bce
</a>
<ol class="bg-white h-[940px] overflow-y-auto"></ol>
</li>
<li class="flex-1 space-y-1">
<ol class="h-6 w-6"></ol>
</li>
</ol>
<ul class="z-10 flex relative items-center lg:hidden">
<li
class="aspect-w-1 bg-gray-100 rounded-lg overflow-hidden aspect-h-1"
>
<img
class="overflow-hidden sm:rounded-md bg-white shadow"
alt="Profile picture of user 263bb89c-5b54-4247-8c82-fec829b1a895"
src="https://example.org/pictures/4c12a5c4-d117-4f81-93e1-47a45626a36e"
/>
<a href="#" class="sr-only">
This is link fc3885d8-d63f-4455-b056-f113aa3a2f23
</a>
<ol
class="border-t grid-cols-1 border-gray-200 gap-6 border-b mt-6 sm:grid-cols-2 grid py-6"
></ol>
</li>
<li class="space-x-3 items-center flex">
<a href="#" class="py-2 bg-white">
This is link 1d718cb1-05e3-4d14-b959-92f5fd475ce0
</a>
<img
class="rounded-md w-full focus:border-indigo-500 border-gray-300 focus:ring-indigo-500 block mt-1 shadow-sm sm:text-sm"
alt="Profile picture of user 1c4d6dc3-700a-4167-8ec3-3dc2f73d4ad5"
src="https://example.org/pictures/359599b3-5610-482e-bc09-025ac5283170"
/>
<ul class="max-w-3xl mx-auto divide-y-2 divide-gray-200"></ul>
<ul class="flex space-x-4"></ul>
</li>
<li class="text-gray-500 hover:text-gray-600">
<ul class="h-96 w-full relative lg:hidden"></ul>
<ol class="text-gray-500 mt-6 text-sm"></ol>
<a href="#" class="sm:col-span-6">
This is link 51cc68af-1184-4f8c-9efd-d2f855902b0b
</a>
<ol
class="left-0 inset-y-0 absolute pointer-events-none pl-3 items-center flex"
></ol>
</li>
<li class="flex-shrink-0">
<ol
class="shadow-lg rounded-lg ring-1 bg-white ring-black ring-opacity-5 divide-gray-50 divide-y-2"
></ol>
</li>
</ul>
<img
class="pl-3 sm:pr-6 py-3.5 relative pr-4"
alt="Profile picture of user 095f88c2-1892-41d1-8165-981ab47b1942"
src="https://example.org/pictures/c70d575b-353a-4360-99df-c2100a36e41b"
/>
</li>
<li class="whitespace-nowrap">
<a href="#" target="_blank" rel="noreferrer" class="h-full">
This is link c804eb7a-39ea-46e6-a79a-2d48e61d5b4e
</a>
</li>
<li class="text-gray-900 text-2xl font-bold tracking-tight">
<img
class="text-gray-900 font-medium"
alt="Profile picture of user 12190673-25cb-4175-90d7-73282e51bd02"
src="https://example.org/pictures/e55a076b-0325-4629-8e02-c9491f2f49cc"
/>
</li>
<li
class="ring-black sm:-mx-6 overflow-hidden ring-1 ring-opacity-5 mt-8 md:rounded-lg md:mx-0 -mx-4 shadow"
>
<ol
class="flex items-center font-medium hover:text-gray-800 text-sm text-gray-700"
>
<li class="flex mt-8 flex-col">
<ol class="sm:inline hidden"></ol>
<ul class="flex items-center absolute inset-0"></ul>
<ol class="h-6 w-6"></ol>
</li>
<li class="-ml-2 rounded-md text-gray-400 p-2 bg-white">
<img
class="block ml-3 font-medium text-sm text-gray-700"
alt="Profile picture of user 2cee83e8-6405-4046-9454-7f6083db307d"
src="https://example.org/pictures/93097140-2e56-4a3f-bc41-e00c658b7767"
/>
<ul
class="sm:grid font-medium hidden grid-cols-4 text-gray-600 mt-6 text-sm"
></ul>
<ul class="h-64 w-64 rounded-full xl:h-80 xl:w-80"></ul>
<ul class="sr-only"></ul>
</li>
</ol>
<img
class="aspect-w-2 group sm:aspect-w-1 aspect-h-1 overflow-hidden sm:aspect-h-1 sm:row-span-2 rounded-lg"
alt="Profile picture of user bc370a72-a44e-44e1-bbec-962c234060da"
src="https://example.org/pictures/d284630d-a088-49ad-a018-b245a8d7acb7"
/>
</li>
<li class="space-y-6 mt-6">
<ul class="w-5 text-gray-400 h-5">
<li
class="hover:bg-gray-100 py-1.5 bg-gray-50 text-gray-400 focus:z-10 rounded-tl-lg"
>
<img
class="bg-gray-50 py-1.5 hover:bg-gray-100 focus:z-10 text-gray-400"
alt="Profile picture of user 4b298841-5911-4b70-ae5a-a5aa8646e575"
src="https://example.org/pictures/fd05d4f7-2b6c-4de4-b7a7-3035e7b5fe78"
/>
<img
class="px-3 py-2 bg-white relative"
alt="Profile picture of user 5406aa7d-5563-4ce1-980f-754a912cd9ff"
src="https://example.org/pictures/e979117e-580c-40a7-be74-bf1b916b9ac0"
/>
<a
href="#"
target="_blank"
rel="noreferrer"
class="mt-2 font-medium text-gray-900 text-lg"
>
This is link 95d285c9-6e4e-43c2-a97f-bb958dcce92f
</a>
<ul class="sr-only"></ul>
</li>
<li class="mt-2 text-sm text-gray-500">
<a
href="#"
target="_blank"
class="text-sm text-blue-gray-900 font-medium block"
>
This is link e0ca5c13-efa5-44d7-b91e-512df7c88410
</a>
<img
class="w-5 h-5"
alt="Profile picture of user 4f5aeddc-6718-40fd-87d2-dcca7e4ef8b1"
src="https://example.org/pictures/6a2ed606-6c59-413c-911f-612c7390091f"
/>
<ol class="font-medium text-gray-900"></ol>
<ol
class="justify-center rounded-full h-7 items-center mx-auto w-7 flex"
></ol>
</li>
<li
class="font-medium px-1 whitespace-nowrap py-4 text-sm border-b-2"
>
<a
href="#"
target="_blank"
class="min-h-80 rounded-md aspect-h-1 aspect-w-1 lg:aspect-none w-full group-hover:opacity-75 lg:h-80 overflow-hidden bg-gray-200"
>
This is link 4f52e535-2e46-44e2-8a5f-fce48c1a673a
</a>
<ul class="text-gray-300 h-full w-full"></ul>
<img
class="block"
alt="Profile picture of user 76dd6af3-d2b7-4a7a-8bc3-628ce95ea9b3"
src="https://example.org/pictures/c6b476c8-283c-44f7-a5c6-4cb48c5ae10b"
/>
<ol class="h-32 relative lg:hidden w-full"></ol>
</li>
<li
class="bg-gray-100 z-10 sticky sm:pt-3 pl-1 pt-1 md:hidden sm:pl-3 top-0"
>
<ol class="z-40 relative lg:hidden"></ol>
<a href="#" class="sr-only">
This is link ec11a608-55b8-41fd-8085-325252c469af
</a>
<ol class="divide-gray-200 lg:col-span-9 divide-y"></ol>
</li>
</ul>
<ul class="text-xl font-semibold ml-1">
<li class="lg:flex-1 lg:w-0">
<ol class="sm:hidden"></ol>
<img
class="block py-2 text-blue-gray-900 text-base hover:bg-blue-gray-50 font-medium px-3 rounded-md"
alt="Profile picture of user 885eb4a3-98ca-4614-b255-ec03e124c026"
src="https://example.org/pictures/6d3a9136-583e-4742-826f-e6d94f60ce99"
/>
</li>
<li class="truncate w-0 ml-2 flex-1">
<img
class="hover:text-gray-600 text-gray-500"
alt="Profile picture of user de38ffb5-607b-4ed6-87bd-dd05fde1731c"
src="https://example.org/pictures/da67f442-40c9-425d-9344-2f9772582519"
/>
<ol class="text-center mt-8 text-gray-400 text-base"></ol>
</li>
</ul>
</li>
</ol>
</li>
<li class="lg:block hidden lg:flex-1">
<a href="#" target="_blank" class="text-base ml-3 text-gray-500">
This is link 9a44892f-7ead-48b6-af94-913ec04821a1
</a>
<ol
class="shadow-sm border-gray-300 focus:ring-indigo-500 sm:text-sm focus:border-indigo-500 w-full rounded-md block"
>
<li class="bg-white hover:bg-gray-100 py-1.5 focus:z-10">
<a
href="#"
target="_blank"
class="bg-gray-200 text-gray-700 gap-px lg:flex-none border-b text-center grid-cols-7 grid text-xs leading-6 border-gray-300 font-semibold"
>
This is link 42a16c66-508d-4d65-bb1a-b252f7e78df2
</a>
<a href="#" class="h-8 w-auto">
This is link 021bda37-522f-413d-af3c-4a8c4f4d666a
</a>
<img
class="max-h-12"
alt="Profile picture of user a1a859bc-ef5e-4349-99ab-a8f4ae262d94"
src="https://example.org/pictures/da93a022-cbbf-4ba0-b34c-21c090d87d74"
/>
<a
href="#"
target="_blank"
rel="noreferrer"
class="flex relative justify-center text-sm"
>
This is link fa5aded2-2906-4809-b742-26832b226f50
</a>
</li>
<li class="py-12 sm:px-6 lg:py-16 px-4 lg:px-8 mx-auto max-w-7xl">
<a href="#" rel="noreferrer" class="min-w-0 ml-3 flex-1">
This is link 715e397d-5676-42fc-9d8f-456172543c31
</a>
<img
class="bg-gray-800"
alt="Profile picture of user c02575ab-6ff1-45f9-a8e3-242c79b133fc"
src="https://example.org/pictures/3d8ecc7a-2504-4797-a644-f93d74acf853"
/>
<img
class="text-base text-gray-900 font-medium"
alt="Profile picture of user 9f457701-be79-4ff2-9dfc-9382dafb20ab"
src="https://example.org/pictures/438b713b-c9fd-4da2-a265-4b8d8f531e30"
/>
<a href="#" rel="noreferrer" class="text-sm">
This is link 4c84098a-c0ac-4044-bbba-6f10bcc315fb
</a>
</li>
<li class="w-6 flex-shrink-0 h-6 text-green-500">
<img
class="mx-auto sm:px-6 px-4 max-w-7xl"
alt="Profile picture of user 00ae83b8-845d-447e-ae1b-cd3c685e1ca0"
src="https://example.org/pictures/b9deba2b-c5b3-4b80-bf76-e0a717d310fd"
/>
<ul class="w-72">
<li class="sm:flex sm:justify-between sm:items-center">
<img
class="block font-medium text-sm text-gray-700"
alt="Profile picture of user c0de8cb0-e9d7-4639-8c3d-851ca17e665b"
src="https://example.org/pictures/897193ff-aa53-4e9e-b761-bc4f75aef572"
/>
</li>
<li
class="text-sm hidden font-medium ml-3 text-gray-700 lg:block"
>
<img
class="h-8 w-auto"
alt="Profile picture of user 9ff9c8ac-2374-4960-9996-ec258745c91a"
src="https://example.org/pictures/e898638f-08fa-4743-aea7-66adba84bded"
/>
</li>
<li
class="mx-auto sm:px-6 px-4 lg:items-center lg:flex lg:py-16 lg:px-8 max-w-7xl py-12"
>
<img
class="lg:max-w-none px-4 max-w-2xl mx-auto lg:px-0"
alt="Profile picture of user 7c4d617d-afa2-4410-81c5-2def540d2d20"
src="https://example.org/pictures/05a7dbc1-c1cc-4f99-99e5-7b507a4108b3"
/>
<ul class="hover:text-gray-600 text-gray-500"></ul>
<ul
class="relative rounded-md border-transparent focus-within:ring-2 focus-within:ring-white -ml-2 group"
></ul>
</li>
</ul>
<img
class="h-5 text-gray-300 w-5"
alt="Profile picture of user bf2c6905-715a-4e38-9b5d-17fd8e7aec2a"
src="https://example.org/pictures/e759a4d7-5e63-4075-ba32-c6574107f401"
/>
</li>
<li class="object-cover object-center h-full w-full">
<ol class="w-full">
<li class="md:mt-0 absolute sm:-mt-32 -mt-72 inset-0">
<ul class="w-12 h-12 rounded-full"></ul>
</li>
<li class="h-1.5 rounded-full w-1.5 mb-1 mx-0.5 bg-gray-400">
<ol
class="border-gray-200 border-4 rounded-lg border-dashed h-96"
></ol>
<img
class="order-1 font-semibold text-gray-700"
alt="Profile picture of user 1c2cabee-08a3-4b48-ba54-5a578b2c3d30"
src="https://example.org/pictures/f5c185be-8b9d-490d-81f4-73a6e1517d98"
/>
<img
class="font-bold sm:text-4xl text-gray-900 tracking-tight text-3xl leading-8 text-center"
alt="Profile picture of user 1e8a2508-a37d-4f6b-9a8c-c6fcf0773604"
src="https://example.org/pictures/90af1bd2-30ed-45d3-917f-c685190ce56e"
/>
</li>
<li class="space-x-2 mt-4 text-sm text-gray-700 flex">
<ul
class="rounded-full translate-x-1/2 block transform border-2 absolute bottom-0 right-0 border-white translate-y-1/2"
></ul>
<ol
class="sm:hidden text-base py-2 text-gray-900 w-full placeholder-gray-500 h-full focus:outline-none border-transparent pr-3 pl-8 focus:placeholder-gray-400 focus:ring-0 focus:border-transparent"
></ol>
</li>
</ol>
<ul class="lg:mt-0 self-center flow-root mt-8">
<li
class="justify-center rounded-full bg-transparent bg-white hover:text-gray-500 focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 text-gray-400 inline-flex focus:outline-none h-8 items-center w-8"
>
<ol class="block xl:inline"></ol>
<ol class="flex-shrink-0 ml-4"></ol>
<ol class="text-gray-200"></ol>
<img
class="border-gray-300 focus:relative md:w-9 rounded-r-md flex bg-white md:hover:bg-gray-50 pl-4 text-gray-400 border hover:text-gray-500 items-center pr-3 border-l-0 justify-center md:px-2 py-2"
alt="Profile picture of user b0a1e2d3-84c4-494b-91d6-194fc294b0db"
src="https://example.org/pictures/2f414511-756c-40ef-aded-22e3f4d985d7"
/>
</li>
<li class="inset-0 absolute">
<img
class="text-gray-500 text-base font-medium text-center"
alt="Profile picture of user 431f88eb-5002-43ab-b23a-37ae0ef7d424"
src="https://example.org/pictures/bc7c19bb-4ef2-46ff-b00e-da70febab926"
/>
<img
class="inset-0 absolute z-10"
alt="Profile picture of user 4a3698d0-7cea-4ba2-854d-28b2bb2d374b"
src="https://example.org/pictures/6078c4cd-db51-43af-90b3-8aeb0a8f1030"
/>
</li>
</ul>
<a href="#" rel="noreferrer" class="bg-white">
This is link ab01c689-e03a-4992-8322-37c20551cb07
</a>
</li>
<li class="flex px-4 pb-2 pt-5">
<ol
class="sm:px-6 px-4 bg-white relative pb-8 md:p-6 shadow-2xl items-center flex w-full sm:pt-8 overflow-hidden lg:p-8 pt-14"
>
<li
class="py-1.5 hover:bg-gray-100 focus:z-10 text-gray-400 bg-gray-50"
>
<a
href="#"
rel="noreferrer"
class="sm:text-sm bg-gray-50 items-center border-gray-300 border-r-0 rounded-l-md text-gray-500 inline-flex border px-3"
>
This is link 3ef75acd-3dfc-4e82-801b-eae9ff7c4351
</a>
<ol
class="absolute border-dashed border-gray-200 border-2 rounded-lg inset-0"
></ol>
</li>
<li class="hover:bg-gray-50 block">
<ol class="items-center flex justify-center p-8"></ol>
<ul class="mx-auto sm:px-6 lg:px-8 pb-12 max-w-7xl px-4"></ul>
<img
class="h-6 w-6 text-green-400"
alt="Profile picture of user f5900afb-7bee-4492-b6e3-148f0afc4f5f"
src="https://example.org/pictures/1b12c3fb-9f84-4cc7-84a7-d38f7ea232ee"
/>
</li>
<li
class="flex mt-4 lg:flex-grow-0 flex-grow lg:ml-4 flex-shrink-0 ml-8"
>
<img
class="focus:ring-indigo-500 block w-full sm:text-sm border-gray-300 focus:border-indigo-500 rounded-md shadow-sm"
alt="Profile picture of user c9dd7fa0-c1f4-477c-b24e-87d200ebb161"
src="https://example.org/pictures/1a3b2e5c-a192-47f3-a550-e18f715213a2"
/>
<a
href="#"
target="_blank"
rel="noreferrer"
class="text-gray-300 hover:text-white"
>
This is link 81b819f3-b2e8-41db-ab8d-abe8c6926047
</a>
</li>
</ol>
<img
class="lg:flex-1 lg:block hidden"
alt="Profile picture of user 352e9ea2-0216-4a0c-917c-1906f5ef4ed1"
src="https://example.org/pictures/ec02985c-b92d-4978-906e-7bdc70bfa54e"
/>
</li>
</ol>
</li>
<li class="sr-only">
<a href="#" target="_blank" class="text-gray-500 mt-4 text-sm">
This is link a712361b-f51e-4f0a-9d55-b64a5d53e10e
</a>
<a
href="#"
rel="noreferrer"
class="rounded-lg ring-opacity-5 shadow-lg overflow-hidden ring-1 ring-black"
>
This is link 8eb412d6-1c39-4fed-b507-cf2a65904247
</a>
</li>
</ul>
</nav>
<img
class="bg-gray-100"
alt="Profile picture of user 8825a6f0-3a41-44b8-92ec-abcd0af79bfb"
src="https://example.org/pictures/679e2a54-073e-416a-85c4-3eba0626aab3"
/>
<span class="bg-white focus:z-10 py-1.5 hover:bg-gray-100">
This is text 3d190171-53b3-4393-99ab-9bedfc964141
</span>
</div>

View file

@ -1,6 +0,0 @@
<div class="md:absolute items-center flex lg:hidden md:inset-y-0 md:right-0">
<input
type="password"
class="text-pink-800 py-0.5 bg-pink-100 font-medium text-sm items-center px-3 inline-flex rounded-full"
/>
</div>

View file

@ -1,8 +0,0 @@
<div class="text-gray-200">
<span class="lg:hidden z-40 relative">
This is text cd32f5df-af14-4332-9fd3-0e5589f8d457
</span>
<a href="#" target="_blank" rel="noreferrer" class="border-gray-200 border-t">
This is link 05289860-74df-49a7-91dd-1a3a0d215bc3
</a>
</div>

View file

@ -1,5 +0,0 @@
<div class="italic text-sm text-gray-500">
<span class="relative text-left inline-block">
This is text bec24672-f081-47d1-8130-cc06506974b5
</span>
</div>

File diff suppressed because it is too large Load diff

View file

@ -1,542 +0,0 @@
<div class="text-gray-500">
<nav class="sm:p-6 px-4 py-5">
<ul class="flex ml-4 items-center md:ml-6">
<li class="lg:hidden z-40 relative">
<img
class="text-gray-500 text-base mt-4"
alt="Profile picture of user 50ae0af8-daf0-410c-bc80-6fa89945008f"
src="https://example.org/pictures/668d6e75-8b90-46e9-958b-04c7df1c7878"
/>
<ol
class="items-center h-7 justify-center rounded-full mx-auto w-7 flex"
>
<li class="text-base text-gray-500 hover:text-gray-900">
<img
class="hover:bg-gray-100 block text-base px-3 text-gray-900 py-2 rounded-md font-medium"
alt="Profile picture of user 5c79c657-6bd0-4ba0-ac79-2f9df6d02efb"
src="https://example.org/pictures/6481de37-cff4-4f2b-9b7e-8184a2ce01b7"
/>
<ul class="bg-white shadow top-1/2 absolute inset-0">
<li
class="overflow-hidden sm:aspect-w-2 aspect-h-1 w-full aspect-w-1 rounded-lg sm:aspect-h-3"
>
<ul
class="w-full pr-3 block focus:outline-none focus:ring-white bg-sky-700 border-transparent rounded-md py-2 leading-5 focus:bg-white focus:placeholder-gray-500 sm:text-sm focus:border-white focus:text-gray-900 placeholder-sky-100 pl-10 border bg-opacity-50"
></ul>
</li>
<li class="bg-white divide-y divide-gray-200">
<ol class="h-6 text-red-600 w-6"></ol>
<ol class="font-medium text-sm text-gray-500"></ol>
<img
class="lg:px-8 mx-auto max-w-3xl sm:px-6 px-4 lg:max-w-7xl"
alt="Profile picture of user cf4f116b-2abe-4069-ad5e-7ddce0cfb37f"
src="https://example.org/pictures/57c94bab-748f-4d2c-b4f7-1760b438f255"
/>
</li>
</ul>
</li>
<li class="mt-2">
<ol class="bg-gray-100 text-gray-900">
<li
class="text-sm text-gray-900 px-3 text-left font-semibold py-3.5"
>
<ol class="fixed inset-0"></ol>
</li>
<li class="space-y-4 mt-4">
<a
href="#"
target="_blank"
class="bg-gray-500 transition-opacity fixed inset-0 bg-opacity-75"
>
This is link 4dc0fdf1-fe92-4132-a7c1-70e75e5e9557
</a>
<a
href="#"
target="_blank"
rel="noreferrer"
class="px-1 py-4 border-b-2 text-base flex-1 font-medium whitespace-nowrap"
>
This is link 75d7c922-e349-471e-8eb3-ad472f0fc0be
</a>
</li>
</ol>
<img
class="text-white bg-gray-900"
alt="Profile picture of user f5d14005-1155-4903-bee1-4f7ced1a2cc1"
src="https://example.org/pictures/1b9e997f-54a9-4a0f-a87d-38194a2dfc57"
/>
<ul class="text-gray-500">
<li
class="group bg-gray-900 focus-within:ring-white -ml-2 focus-within:ring-2 border-transparent rounded-md relative"
>
<ul
class="text-lg font-medium mt-8 relative text-gray-700"
></ul>
<img
class="bg-gray-50 py-8 col-span-1 px-8 flex justify-center"
alt="Profile picture of user 305405bb-186d-4f35-86a0-84efe575a901"
src="https://example.org/pictures/33a7c53d-0087-439e-8357-e59a6a6cc3d5"
/>
<a
href="#"
class="hover:text-gray-500 inline-flex text-gray-400 space-x-2"
>
This is link 608531bd-0a36-405a-a47c-906fd19850ff
</a>
<ol class="lg:hidden"></ol>
</li>
<li class="h-6 w-6">
<ul
class="mt-6 grid text-gray-500 leading-6 grid-cols-7 text-xs"
></ul>
<a href="#" rel="noreferrer" class="relative">
This is link 83e9bb9e-6e60-4498-aeca-8187a7b64d68
</a>
</li>
</ul>
</li>
<li class="max-w-7xl mx-auto">
<ul class="mt-auto font-bold text-gray-900 text-sm">
<li class="sm:max-w-md lg:mt-0 sm:flex mt-4">
<a href="#" class="sr-only">
This is link 347dc36d-0807-448b-b4c9-908a37bf9fca
</a>
<ul
class="items-center px-4 max-w-7xl mx-auto flex justify-between sm:px-6 lg:px-8"
></ul>
<ul class="border-b border-gray-200"></ul>
</li>
<li class="text-sm font-medium text-gray-900">
<a href="#" target="_blank" class="ml-3 relative">
This is link 030563df-7409-45a4-ab3b-b4b6c6b82c4c
</a>
<ul class="mt-6 text-base text-gray-600 leading-7"></ul>
<img
class="flex-1 overflow-y-auto"
alt="Profile picture of user 42b1a2be-eaed-4c33-be60-09b87390445e"
src="https://example.org/pictures/3b4c60c3-dc84-45f0-a094-2bf93c54480d"
/>
</li>
<li
class="lg:-translate-y-1/2 transform sm:left-1/2 absolute sm:translate-x-8 lg:top-1/2 lg:left-1/2 sm:top-0 lg:translate-x-8"
>
<a href="#" class="sm:text-center">
This is link b24c17b1-01b3-4515-8e92-e28b39f57d7e
</a>
</li>
</ul>
</li>
<li
class="lg:px-8 py-12 lg:flex lg:items-center sm:px-6 px-4 lg:justify-between lg:py-16 max-w-7xl mx-auto"
>
<a
href="#"
target="_blank"
rel="noreferrer"
class="border-b border-gray-200"
>
This is link 02110cff-cd79-4bfa-864f-47ffb0c8c339
</a>
<ul class="sm:flex sm:-mt-16 sm:space-x-5 sm:items-end -mt-12">
<li class="sr-only">
<img
class="block font-medium text-sm ml-3"
alt="Profile picture of user 306d7b71-2068-470e-a733-135caea6a74b"
src="https://example.org/pictures/fa4bd013-90a3-4f62-b571-4481b5fbf24c"
/>
<ol class="mt-5 text-gray-500 text-xl"></ol>
<img
class="select-none px-3 cursor-default rounded-md group flex py-2 items-center"
alt="Profile picture of user fd3680a4-9b44-4561-ad44-dddca3974b90"
src="https://example.org/pictures/21f10f3a-075a-4d9d-8f23-e1c5fb9a5b42"
/>
</li>
<li class="text-gray-900 text-lg font-semibold">
<img
class="text-gray-500 hover:text-gray-600"
alt="Profile picture of user 01286af3-89f0-4b29-989f-9d40501403bc"
src="https://example.org/pictures/8ac83cb9-8526-42c7-957c-39ede7dd4063"
/>
</li>
<li class="max-w-none prose-sm prose mt-4 text-gray-500">
<a
href="#"
target="_blank"
rel="noreferrer"
class="focus:ring-indigo-500 shadow-sm border-gray-300 sm:text-sm block rounded-md focus:border-indigo-500 w-full"
>
This is link b26d02b8-3eff-41f1-90e5-4c9ea50d2cd6
</a>
</li>
<li
class="py-3 bg-gray-50 font-medium text-center w-full px-5 text-indigo-600 block hover:bg-gray-100"
>
<a
href="#"
target="_blank"
class="text-sm group text-gray-500 inline-flex hover:text-gray-700"
>
This is link 550e85ba-660a-411c-961d-1a95fde7a5c1
</a>
<ul class="lg:inline hidden"></ul>
</li>
</ul>
<a
href="#"
target="_blank"
rel="noreferrer"
class="absolute inset-0"
>
This is link 734d4d7f-d92d-4256-aa8d-2f568b22ad3c
</a>
</li>
</ol>
</li>
<li
class="w-full bg-white text-gray-200 border-dashed rounded border-gray-300 border-2 h-8"
>
<img
class="sr-only"
alt="Profile picture of user 05ce0f38-8741-47a7-8d3c-8645a4e45e0d"
src="https://example.org/pictures/a82c36cd-8f38-40d2-a1c8-eaa4b2376426"
/>
</li>
<li class="hover:bg-gray-100 bg-white focus:z-10 py-1.5">
<img
class="text-gray-900 font-medium"
alt="Profile picture of user dde74731-2eb4-4088-be6b-f34e591edf4c"
src="https://example.org/pictures/ba995d96-b8fd-45a2-95bb-82a035fde39b"
/>
<ol
class="focus:ring-indigo-500 shadow-sm bg-indigo-600 focus:ring-2 items-center border py-2 font-medium focus:ring-offset-2 text-sm focus:outline-none inline-flex rounded-md border-transparent hover:bg-indigo-700 px-4 text-white"
>
<li
class="flex inset-y-0 absolute left-0 pointer-events-none items-center"
>
<ol class="flex py-3 items-center justify-between">
<li class="sr-only">
<a
href="#"
target="_blank"
rel="noreferrer"
class="rounded-lg aspect-w-1 bg-gray-100 overflow-hidden aspect-h-1 group-hover:opacity-75"
>
This is link 921fa774-a146-4f69-8045-777491829dd7
</a>
<a href="#" rel="noreferrer" class="mt-10">
This is link 5fcca0e4-ac4a-4fad-80f8-eeeeaf88a3be
</a>
</li>
<li class="text-gray-500">
<img
class="w-8 h-8 rounded-full"
alt="Profile picture of user 0cf82f00-13a2-45d8-af86-c49f52f06038"
src="https://example.org/pictures/7d77da49-093f-43bc-b063-fa177dbb92a4"
/>
<a href="#" class="sm:col-span-2">
This is link ae2ddf0b-522c-4243-a044-3d8bc391d867
</a>
<ol
class="bg-white h-8 w-full border-2 border-dashed rounded text-gray-200 border-gray-300"
></ol>
</li>
<li class="items-center flex text-gray-500 text-sm">
<ul
class="text-base rounded-md focus:ring-indigo-500 font-medium bg-indigo-100 focus:outline-none px-4 border inline-flex text-indigo-700 focus:ring-2 border-transparent items-center py-2 focus:ring-offset-2 hover:bg-indigo-200"
></ul>
<a href="#" class="sr-only">
This is link 70446dbd-4606-4526-ac1d-db9c3dabdbaf
</a>
<ul class="flex -mb-px px-4 space-x-8"></ul>
<a
href="#"
target="_blank"
class="font-medium -m-2 text-gray-900 block p-2"
>
This is link 453b9bee-cb33-41eb-8e14-467c51dc5b43
</a>
</li>
<li class="font-medium text-lg text-gray-900">
<ul
class="sm:py-24 lg:px-8 px-4 sm:px-6 py-16 mx-auto max-w-xl lg:max-w-7xl"
></ul>
<ol
class="rounded-lg shadow-xl sm:h-auto h-96 bg-white sm:aspect-w-4 group relative sm:aspect-h-5"
></ol>
<ol class="inset-0 sm:px-6 lg:px-8 absolute py-6 px-4"></ol>
</li>
<li class="inline">
<ul
class="whitespace-nowrap px-1 text-base border-b-2 font-medium flex-1 py-4"
></ul>
<img
class="w-auto h-8"
alt="Profile picture of user e26b9df8-000d-47ea-b0e2-4f3713cc3be0"
src="https://example.org/pictures/efeb3ccd-bde3-4525-a705-f7105bf4e6c6"
/>
</li>
</ol>
<a
href="#"
rel="noreferrer"
class="sm:justify-between relative sm:flex py-4 px-6 bg-white cursor-pointer rounded-lg shadow-sm border focus:outline-none block"
>
This is link 7dfaad9b-0d84-41c9-a03a-764f979da9e6
</a>
<ul
class="w-7 justify-center h-7 rounded-full flex items-center mx-auto"
>
<li class="flex space-x-8">
<img
class="sm:pt-16 pt-10 xl:py-20 sm:px-16 xl:px-20 lg:pr-0 lg:py-16 px-6 pb-12"
alt="Profile picture of user d6bc973d-ff48-4c8e-8341-1c50154334c9"
src="https://example.org/pictures/52d88363-b3c1-41c3-8572-74186439c1cd"
/>
<a href="#" target="_blank" rel="noreferrer" class="ml-3">
This is link 94411a71-4572-4215-ba13-2db540b08fbb
</a>
<ul class="py-6 lg:col-span-3"></ul>
<ul class="sr-only"></ul>
</li>
<li class="sm:pb-12 lg:pb-12 bg-white pb-8">
<img
class="border placeholder-blue-gray-400 sm:max-w-xs focus:border-blue-500 px-5 focus:ring-1 focus:ring-blue-500 py-3 shadow-sm rounded-md w-full border-blue-gray-300"
alt="Profile picture of user 1259f0db-76eb-4684-a0f8-41ed9e62def2"
src="https://example.org/pictures/fc3c0b7f-0899-425a-9564-70ffdde03dc0"
/>
<img
class="flex-shrink-0"
alt="Profile picture of user 40727f67-cf13-48a4-84e4-68e9b6b2f93d"
src="https://example.org/pictures/b6daf615-b078-44b5-b108-6f0a6d5b8a4a"
/>
<img
class="sr-only"
alt="Profile picture of user aa650316-d4b5-41e4-af8f-ac143baff429"
src="https://example.org/pictures/4148e511-2385-499e-90c9-a2e56a9cb55c"
/>
<ol class="flex mt-4"></ol>
</li>
<li class="md:mt-0 lg:ml-0 md:ml-4 lg:mt-6 mt-6">
<ol class="font-medium underline text-white"></ol>
<a
href="#"
target="_blank"
rel="noreferrer"
class="font-medium text-sm text-gray-600"
>
This is link 19e4a36c-365d-4a9a-8c88-e23db1e3d329
</a>
</li>
</ul>
<a
href="#"
rel="noreferrer"
class="hover:text-white text-gray-300 text-base"
>
This is link c3ab918e-f495-40e5-ab0d-08d3c3b337a2
</a>
</li>
<li class="relative flex">
<ul class="focus:z-10 hover:bg-gray-100 bg-white py-1.5">
<li class="mt-6 space-y-6">
<ul class="font-medium text-sm text-gray-500"></ul>
<ol class="border-gray-200 border-b"></ol>
<a href="#" target="_blank" class="items-end flex mt-6 flex-1">
This is link c0ee8750-a725-4758-9c1d-fff1bcfc6387
</a>
</li>
<li class="flex space-x-3">
<img
class="text-sm text-gray-900 font-medium"
alt="Profile picture of user 1bf327c7-9262-4343-885d-7066efb01152"
src="https://example.org/pictures/3b3116c6-d317-4dbe-979b-40946e1133b6"
/>
<ul class="items-center flex px-4"></ul>
</li>
<li class="text-gray-500 items-center mt-2 flex text-sm">
<img
class="space-x-6 items-center mt-4 flex"
alt="Profile picture of user 13f39d6e-057e-4ac3-8038-b0a4a7e4ce09"
src="https://example.org/pictures/cd194ac5-6d50-4f14-990c-4eeb8e21e716"
/>
<ol
class="gap-x-8 pb-12 items-start gap-y-10 pt-10 grid grid-cols-2"
></ol>
<img
class="py-2 px-4 border text-sm shadow-sm text-gray-500 justify-center bg-white border-gray-300 w-full inline-flex hover:bg-gray-50 font-medium rounded-md"
alt="Profile picture of user c0b687e7-9303-43b2-a09c-82bafc1910c7"
src="https://example.org/pictures/05e0d6ba-21ac-40b6-aff6-d10a5d93cd62"
/>
</li>
<li class="hover:bg-gray-100 focus:z-10 bg-white py-1.5">
<a href="#" class="mx-auto max-w-xs w-full">
This is link b9b278f1-6847-4046-90ab-edfe27241757
</a>
<a
href="#"
target="_blank"
rel="noreferrer"
class="space-y-4 mt-4"
>
This is link a56011bb-f589-4cb2-8c9d-2e184e33df57
</a>
<a
href="#"
target="_blank"
class="text-gray-400 hover:bg-gray-700"
>
This is link 5d6429d2-e9f5-4414-8e07-b5f8dac0aaea
</a>
<ol class="sm:text-sm items-center flex text-base"></ol>
</li>
<li class="text-sm">
<img
class="select-none px-3 py-2 cursor-default relative"
alt="Profile picture of user 77805ae7-08c9-455c-b58c-7aeb5d8a582e"
src="https://example.org/pictures/794d7468-c92c-4b4f-9224-121dcc3b262d"
/>
<ol class="text-gray-900 font-medium"></ol>
<img
class="text-gray-400 items-center focus:outline-none focus:ring-indigo-500 focus:ring-2 w-10 justify-center bg-white flex -mr-2 hover:bg-gray-50 h-10 rounded-md p-2"
alt="Profile picture of user caf62604-a62b-47e1-956c-a148f09bc2ed"
src="https://example.org/pictures/f3723af0-d897-4bdf-8726-64f7f4772980"
/>
</li>
</ul>
<ul class="sm:hidden">
<li class="p-6">
<ul
class="lg:px-8 mx-auto max-w-7xl sm:px-6 px-4 relative"
></ul>
</li>
<li class="border-t border-gray-200 py-20">
<img
class="text-gray-500 mt-3 text-base"
alt="Profile picture of user 2391f746-d982-44c9-b771-8f340ace8e3a"
src="https://example.org/pictures/5fa981c8-e71e-48fd-9601-9069ee9ff2bc"
/>
<ol class="inset-0 z-10 fixed overflow-y-auto"></ol>
</li>
<li
class="text-sm font-medium ml-2 text-gray-700 group-hover:text-gray-800"
>
<ol
class="focus:ring-2 inline-flex focus:outline-none hover:bg-gray-100 hover:text-gray-500 focus:ring-indigo-500 justify-center text-gray-400 focus:ring-inset items-center bg-white rounded-md p-2"
></ol>
</li>
<li class="py-1.5 hover:bg-gray-100 focus:z-10 bg-white">
<a
href="#"
target="_blank"
rel="noreferrer"
class="py-16 grid gap-x-8 gap-y-10 grid-cols-4"
>
This is link 973020fa-e5b9-4e35-83f9-92d744e1d155
</a>
<a
href="#"
target="_blank"
class="text-lg font-medium space-y-1 leading-6"
>
This is link 34a34675-e2cc-4bcc-a946-520cf4ab995b
</a>
</li>
</ul>
<ul class="sm:mt-0 text-gray-900 text-sm mt-1 sm:col-span-2">
<li class="focus-within:text-gray-500 relative text-gray-400">
<ul class="font-medium text-gray-700 underline"></ul>
</li>
<li class="font-semibold col-end-1 text-gray-900">
<img
class="bg-white px-2 text-gray-500"
alt="Profile picture of user 1435989c-22da-4535-918a-58923740285d"
src="https://example.org/pictures/1e1f10ae-3ac4-4aee-89c1-e90edeaf4d12"
/>
<ul
class="absolute top-0 mx-auto h-px inset-0 px-8 max-w-7xl"
></ul>
<ul class="border-t w-full border-gray-300"></ul>
</li>
<li class="mt-2">
<a
href="#"
class="text-gray-400 font-medium group-hover:text-gray-300 text-sm"
>
This is link bce54268-13f6-44f8-9e1b-9578e57347ee
</a>
<ol class="sm:col-span-2"></ol>
<img
class="shadow-lg mt-px lg:ring-opacity-5 top-16 lg:right-0 pb-6 bg-white lg:left-auto lg:top-full lg:rounded-lg lg:ring-1 lg:-mr-1.5 inset-x-0 sm:px-2 lg:mt-3 lg:w-80 absolute lg:ring-black"
alt="Profile picture of user 4bfef42f-a65c-4c23-bd86-869edf16caa6"
src="https://example.org/pictures/0b8edd55-bf71-40af-b1b5-bf8574c694c9"
/>
</li>
<li class="text-gray-600 hover:bg-gray-50 hover:text-gray-900">
<a
href="#"
rel="noreferrer"
class="right-0 sm:text-sm bg-white ring-opacity-5 focus:outline-none text-base py-3 mt-1 z-10 ring-1 ring-black w-52 rounded-lg absolute overflow-auto shadow max-h-56"
>
This is link f8948c8b-ae87-4b9a-94c8-61a5217c34c3
</a>
<ol class="text-sm text-gray-500"></ol>
<ul class="w-full h-full inset-0 absolute"></ul>
</li>
</ul>
<ul class="flex text-gray-500 space-x-4 text-sm">
<li
class="lg:h-full lg:max-w-none rounded-md lg:w-auto w-full ring-opacity-5 ring-black ring-1 shadow-xl"
>
<a href="#" class="mt-6">
This is link 185d05d6-dc5d-45f7-889f-097f75d59634
</a>
<a
href="#"
target="_blank"
class="rounded-md border px-4 hover:bg-indigo-700 focus:ring-2 font-medium focus:ring-indigo-500 shadow-sm focus:outline-none py-2 border-transparent bg-indigo-600 text-sm text-white focus:ring-offset-2 ml-4 flex-shrink-0"
>
This is link bbf577d7-c799-4c40-9171-cabbaa1b2802
</a>
</li>
<li
class="focus:ring-indigo-500 border-gray-300 text-gray-900 block focus:z-10 relative focus:outline-none px-3 placeholder-gray-500 rounded-t-md rounded-none appearance-none py-2 focus:border-indigo-500 sm:text-sm border w-full"
>
<ul
class="lg:gap-24 lg:grid-cols-2 lg:grid lg:items-center"
></ul>
<a
href="#"
target="_blank"
rel="noreferrer"
class="text-sm text-gray-500 sm:flex-shrink-0 font-medium sm:w-40"
>
This is link 897efa9d-e0d2-457d-8aeb-176c3d6d8793
</a>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</nav>
<img
class="lg:pb-16 lg:bg-transparent lg:px-0 bg-gray-50 sm:px-6 lg:col-start-2 lg:row-start-1 px-4 pb-10 pt-16"
alt="Profile picture of user 1a6d625a-a03c-46c6-9498-307c64da5261"
src="https://example.org/pictures/824c1f74-50c5-442f-9890-4dc80c43ebbc"
/>
<img
class="sr-only"
alt="Profile picture of user 91de36fa-215a-48e8-b4d4-3681acc21a1a"
src="https://example.org/pictures/1fadc974-b0d8-49a9-9c7b-50e6651724a0"
/>
<p class="sr-only">
<a
href="#"
target="_blank"
rel="noreferrer"
class="absolute inset-x-0 transition-colors sm:translate-y-px ease-out sm:transform bottom-0 sm:mt-5 duration-200 h-0.5"
>
This is link 96627dae-7b53-4d6e-ae81-807366c9b89b
</a>
</p>
</div>

View file

@ -1,7 +0,0 @@
<div class="sm:flex">
<img
class="ml-3 h-7 items-center flex"
alt="Profile picture of user 9c07ab87-0e91-476c-bc31-d875f9dd10a6"
src="https://example.org/pictures/f87d1490-0c9b-4792-9f6d-db630866b2f0"
/>
</div>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,24 +0,0 @@
<div class="md:mt-0 mt-12 sm:mt-16">
<section class="items-center group flex -m-2 p-2">
<form class="text-gray-700 block font-medium text-sm">
<button type="submit">
This is action fdf8f6a4-91d2-4354-b435-eb086f846200
</button>
<button type="submit">
This is action f24d6b31-228c-4338-b23e-0cd068f3210b
</button>
<input type="password" class="text-gray-500 font-medium text-sm" />
</form>
<select class="py-2 text-sm px-4 block">
<option>This is item 6d43a1ce-4e83-461f-8ce4-5cbce958a7f5</option>
<option>This is item 79e58d9d-d874-4590-9e1e-332056cff1d7</option>
<option value="b47117fe-fa8c-4794-887a-dbb405aba9bc">
This is item 47333a76-d83f-4b71-afc5-80aacec1225c
</option>
<option value="1de1d8b7-6f9c-453d-a025-5b3dcea0f4e1">
This is item 187518c0-0e0c-4411-ba7d-92cfb7077f76
</option>
<option>This is item 30f5cdf0-3bcc-48b4-abc2-498b2a0d468b</option>
</select>
</section>
</div>

View file

@ -1,35 +0,0 @@
<div class="bg-white focus:z-10 hover:bg-gray-100 py-1.5">
<p class="flex mt-2 sm:max-w-md">
<span class="text-gray-500 hover:text-gray-600">
This is text e2f94933-d3b0-4372-8edb-956db927469f
</span>
<span class="mt-1">
This is text 94fa4461-2cfd-48cb-b079-384ef5db034a
</span>
</p>
<p class="mt-1">
<a
href="#"
class="border-gray-200 flex bg-white border-r flex-col min-h-0 flex-1"
>
This is link 1af124a0-1d05-4243-b15d-81af7865c244
</a>
<span class="justify-center h-7 mx-auto flex items-center rounded-full w-7">
This is text b6aad685-1afc-4a6b-9510-a61cec2f9cb7
</span>
</p>
<span class="-mr-2 md:hidden -my-2">
This is text 4639f49f-9fc2-4de5-b3b6-69dbb8808fe5
</span>
<p class="sm:flex-shrink-0">
<span class="border-gray-200 border-b">
This is text efd63bb6-4a93-4254-b5ab-b8ebe64c3dfb
</span>
<a href="#" class="px-2 w-full">
This is link eb864a37-edd4-41a0-9407-7a9c56f066d5
</a>
</p>
<h3 class="mt-4 text-gray-900 text-sm">
This is heading d4970345-5403-482a-80a1-13f23eebc097
</h3>
</div>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,339 +0,0 @@
<div class="sr-only">
<h3 class="xl:grid xl:grid-cols-3 xl:gap-8">
This is heading 480a8642-333a-493b-be9c-672922b8d915
</h3>
<section
class="bg-gray-100 rounded-full inline-block h-8 overflow-hidden w-8"
>
<img
class="max-w-lg mx-auto flex items-end justify-around w-full"
alt="Profile picture of user 850e431c-05bb-4cf7-928d-75a35ae10497"
src="https://example.org/pictures/c33e532c-307b-4325-9ae4-ffe439320ae7"
/>
<a
href="#"
target="_blank"
rel="noreferrer"
class="whitespace-nowrap sm:pr-6 font-medium text-right pr-4 pl-3 relative py-4 md:pr-0 text-sm"
>
This is link a54c6d10-527d-42a6-afd9-1bfa354de681
</a>
<nav class="w-6 h-6">
<ul class="ml-3">
<li class="text-gray-500 order-2 mt-2 text-lg leading-6 font-medium">
<ul class="border-t border-b border-gray-200">
<li
class="text-indigo-600 font-medium text-base hover:text-indigo-500"
>
<ol class="text-white w-4 h-4">
<li class="flex justify-between items-center">
This is item 64adb8a7-c803-4f73-a79d-b78e3fb2684d
</li>
<li class="font-medium text-indigo-600 hover:text-indigo-500">
This is item e7776a35-0586-4f23-bb01-c83296aed658
</li>
<li class="border-t border-gray-200 px-4 py-6">
This is item 6f81bb01-b8da-4c6e-9461-7d3c9b20d12c
</li>
<li
class="focus:z-10 py-1.5 rounded-bl-lg bg-white hover:bg-gray-100 text-gray-900"
>
This is item 992f51b3-3ac3-4609-b3d6-c11b16fae1c2
</li>
<li class="pb-24">
This is item 93849f08-1d15-4b72-87a7-8a63bbd33fb6
</li>
</ol>
<ol class="-ml-1 mr-2 text-gray-500 w-5 h-5">
<li class="block">
This is item 464b4fde-66ef-46a0-9042-2280cddfe2b7
</li>
<li class="grid gap-x-4 grid-cols-2 gap-y-8">
This is item 83438c8b-d681-459e-aa71-6481b290cb9a
</li>
<li
class="lg:grid-cols-4 lg:px-8 px-4 sm:grid-cols-2 mx-auto max-w-7xl py-6 gap-y-6 xl:py-16 sm:gap-8 lg:py-12 grid sm:py-8 sm:px-6"
>
This is item 2bc06445-15d7-4271-9460-9a9b30832365
</li>
</ol>
<ul class="text-center">
<li class="text-gray-900 text-base font-medium">
This is item 9e5a3082-44e1-4c8f-bb42-731c3fbe54d6
</li>
<li class="p-2 items-center -m-2 group flex">
This is item 8aa76c91-d291-47f8-b649-5e5c587f3ca1
</li>
<li class="bg-white rounded-lg shadow overflow-hidden">
This is item 6dc0074c-f7f7-478c-b5e4-f278e0796785
</li>
<li class="sr-only">
This is item 82bff66b-f8d1-4d34-8181-bef72608acb5
</li>
<li class="sr-only">
This is item 9890012b-daff-44a8-b4dc-e4bca140dff0
</li>
</ul>
</li>
<li
class="w-5 absolute h-5 left-4 pointer-events-none text-gray-500 top-3.5"
>
<a href="#" rel="noreferrer" class="items-center flex">
This is link 85c00e28-7105-4834-b398-f8fb900f2875
</a>
<ol class="grid grid-cols-7 leading-6 text-xs text-gray-500 mt-6">
<li
class="flex-col pb-12 flex shadow-xl max-w-xs bg-white w-full overflow-y-auto relative"
>
This is item ce8ccc6e-edbe-489c-9bb0-e73785ec4988
</li>
<li class="absolute overflow-hidden rounded-lg inset-0">
This is item 6b1ea845-264a-4308-af3c-d3e123f63172
</li>
</ol>
<img
class="flex-auto"
alt="Profile picture of user d624fe32-5216-4491-97cf-54287f87c40d"
src="https://example.org/pictures/27858b0a-7be7-4767-a4a7-d27ec0c05aad"
/>
</li>
</ul>
</li>
<li class="lg:bg-transparent bg-gray-100 relative">
<ol class="text-base text-white font-medium">
<li class="h-12">
<img
class="leading-6 text-lg text-gray-900 font-medium"
alt="Profile picture of user 026cb9eb-2827-4b94-ac28-e39dc65f8335"
src="https://example.org/pictures/f0ec71f9-febd-4fb1-8244-401c229caaf2"
/>
<ul class="group-hover:text-gray-500 h-5 w-5 text-gray-400">
<li class="space-x-4 ml-10 flex items-baseline">
This is item 1fcee6a6-1008-4ecc-b935-c1c56db14d38
</li>
<li class="mt-4 text-white text-xl">
This is item c23b11eb-c112-4d57-8ec4-c081b1637c32
</li>
<li class="flex space-x-8 h-full">
This is item 33ec1b34-b86b-4ea9-a1f7-db089868d8c5
</li>
<li class="bg-white hover:bg-gray-100 py-1.5 focus:z-10">
This is item 3b395f68-596c-4ace-a389-d732b51613ce
</li>
</ul>
<ul class="flow-root">
<li class="sr-only">
This is item fa717680-1b52-4603-b703-eda7c50cfdc3
</li>
<li class="mt-10">
This is item 649a1f8b-ef0e-4cb5-bb0d-53b598672a8f
</li>
</ul>
</li>
<li
class="border-gray-300 px-4 rounded-md hover:bg-gray-50 text-sm py-2 bg-white inline-flex items-center font-medium text-gray-700 relative ml-3 border"
>
<ul
class="border-transparent rounded-full flex items-center hover:text-gray-500 border -mx-2 text-gray-400 p-2"
>
<li class="pb-4 flex-1 space-y-1 px-2">
This is item fd412b95-9fa6-4fb3-a2e3-b427ce97d83e
</li>
<li class="truncate w-full inline-flex">
This is item ccc2d139-dded-4a33-93b4-eb73027416d4
</li>
<li
class="sm:h-full group-hover:opacity-75 object-center sm:absolute sm:w-full object-cover sm:inset-0"
>
This is item 9616628f-d772-4d8a-ad10-2e502c16fb40
</li>
<li
class="ring-1 ring-black w-48 z-10 absolute origin-top-right rounded-md right-0 shadow-lg mt-2 bg-white py-1 ring-opacity-5 focus:outline-none"
>
This is item 48d8538e-1a48-4f77-86fb-47e7902327c1
</li>
<li
class="flex mx-auto rounded-full justify-center w-7 items-center h-7"
>
This is item 5dab52c4-6b02-43fe-883f-5d53ffef9140
</li>
</ul>
</li>
<li
class="sm:text-6xl font-bold sm:mt-5 tracking-tight lg:mt-6 text-white xl:text-6xl text-4xl mt-4"
>
<a
href="#"
target="_blank"
class="cursor-not-allowed text-gray-200 bg-gray-50"
>
This is link 30918c36-ee8d-499b-bf9e-0d6b0921808e
</a>
</li>
<li class="mt-1 sm:mt-0 sm:col-span-2">
<ul class="flex flex-col py-6 min-h-0 flex-1 overflow-y-scroll">
<li class="truncate font-medium ml-3 block">
This is item 8250f848-bb62-42c2-9c24-140ebda122ba
</li>
<li class="w-5 h-5">
This is item 3c7a80a4-57fa-4487-ad6d-3e6f3944642c
</li>
<li class="bg-gray-900 relative">
This is item 48693a54-dfb1-493c-b1eb-12448b92645c
</li>
<li class="flex justify-between items-center">
This is item cec9053c-0a9f-4db9-a35c-9c45db9901b0
</li>
</ul>
<ol class="truncate text-gray-900 text-sm font-medium">
<li class="text-sm block text-gray-700 font-medium">
This is item 2cdfa3cc-e8f6-4c11-8506-e368e6c821af
</li>
<li class="sr-only">
This is item 3bf758d1-ce42-4f0e-bfb7-1fb33535abba
</li>
<li class="bg-gray-900 relative">
This is item 3ba88186-dc2d-439c-9995-6f2595dcd2ae
</li>
</ol>
<ul class="border-t border-gray-200 py-5 px-4 sm:p-0">
<li class="mt-2 text-sm text-gray-500">
This is item c8c70131-082c-42ba-81ad-c472fdf34ebc
</li>
<li class="sr-only">
This is item c6e1d863-5076-425a-a734-f32584755133
</li>
<li
class="focus:z-10 relative hover:bg-gray-100 py-1.5 text-gray-900 bg-white"
>
This is item f74ce352-7105-46d7-9daf-f21af65294c0
</li>
<li class="text-gray-900 font-medium">
This is item 233869ba-2f73-4ffa-b20c-78cefa258fa5
</li>
<li class="overflow-hidden relative">
This is item 27d4d256-cde7-416b-843d-310ce092ec8b
</li>
</ul>
</li>
</ol>
<ul class="flex-shrink-0">
<li class="block font-medium truncate">
<a
href="#"
rel="noreferrer"
class="block border-gray-300 sm:text-sm shadow-sm rounded-md w-full focus:border-indigo-500 mt-1 focus:ring-indigo-500"
>
This is link d5b6023a-afcc-4345-bbc6-42d03de03b4c
</a>
</li>
<li class="text-lg mt-6 text-gray-500 max-w-3xl">
<ol class="w-64 object-cover md:h-72 h-64 rounded-lg md:w-72">
<li
class="border-dashed h-96 rounded-lg border-gray-200 border-4"
>
This is item 2be8ff2c-655e-4188-a404-7f7e7cf142a2
</li>
<li class="text-sm font-medium text-gray-500">
This is item 44a5098c-ba02-4962-a84c-f53b251fa37d
</li>
</ol>
<img
class="pr-5 flex-shrink-0 flex"
alt="Profile picture of user d8fb8181-0eb6-4692-aaba-8e245b4834f3"
src="https://example.org/pictures/f0c627e2-92e5-41bc-922f-cdd3a7d83157"
/>
<a href="#" class="relative">
This is link b109f8f9-52e4-40eb-93da-ba8b262c151e
</a>
</li>
<li
class="lg:justify-end items-center px-2 flex lg:ml-6 flex-1 justify-center"
>
<a
href="#"
target="_blank"
rel="noreferrer"
class="text-center sm:text-4xl tracking-tight text-gray-900 text-3xl font-bold"
>
This is link cfc95894-55e8-4f69-b3d2-36af0baa4a89
</a>
<ul class="mt-0.5">
<li class="items-start flex space-x-4">
This is item 433aff9f-a8a5-4472-a635-508760d6a046
</li>
<li
class="sm:py-5 sm:pt-5 sm:grid sm:grid-cols-3 py-4 sm:gap-4"
>
This is item 3300729a-e096-4d1c-b3a1-d328b0c17c31
</li>
<li
class="bg-gray-800 hover:bg-gray-900 flex rounded-md py-3 border-transparent border items-center text-base px-5 text-white font-medium justify-center"
>
This is item 2157654f-a7fd-452e-98a6-b4fb39d7de6d
</li>
<li class="bg-gray-900">
This is item 7a32058d-1fc1-4dcc-9434-58e5d71c562e
</li>
</ul>
</li>
<li class="py-8 bg-white">
<ul class="mt-1 max-w-2xl text-sm text-gray-500">
<li class="sr-only">
This is item 7acbfd34-9c79-4975-96a4-b3a2939e54dd
</li>
<li class="font-medium text-gray-500 text-sm">
This is item 502abdc2-de6a-4c7e-8d85-8d8c1d9a45d2
</li>
<li class="text-sm block text-gray-700 font-medium">
This is item 8bddeba0-6c53-4625-a31e-1d2406ba02be
</li>
<li class="sr-only">
This is item f79fe551-c013-4141-8622-f5727bad097f
</li>
<li class="text-lg font-medium leading-6 text-gray-900">
This is item f1cb2f21-63c8-44d6-a01f-67702958d120
</li>
</ul>
<ul class="lg:hidden w-auto h-8 block">
<li class="text-gray-900">
This is item 25f7dcb8-7470-4271-a39b-9fecbc546686
</li>
<li
class="flex pointer-events-none sm:items-start py-6 items-end fixed sm:p-6 inset-0 px-4"
>
This is item bbd5030b-c7ec-4ecb-8fa5-9b517665cc7b
</li>
<li class="sr-only">
This is item cd3cf690-2947-472b-a85b-66f056b13e49
</li>
<li class="bg-white p-8">
This is item 3e7f4a04-2d9e-4694-9399-654a274fbc76
</li>
<li class="text-gray-200">
This is item 405ece28-5d5a-4c7e-9a74-cd27efb9d6ac
</li>
</ul>
<img
class="w-6 h-6"
alt="Profile picture of user ba2c0d91-4eca-473a-868f-0be357f57d02"
src="https://example.org/pictures/fc81828e-7144-4c70-9106-1a24f02d159e"
/>
</li>
</ul>
<a
href="#"
class="lg:static lg:flex-shrink-0 inset-y-0 left-0 absolute"
>
This is link a8a48ec6-c9e7-473f-a47c-edee8e26d307
</a>
</li>
</ul>
</nav>
</section>
<img
class="sr-only"
alt="Profile picture of user 69deaf42-c676-45ec-b66a-6d2c93178847"
src="https://example.org/pictures/82db045e-f73a-4247-9ee2-d689f773e67b"
/>
</div>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,40 +0,0 @@
<div
class="block bg-gray-50 px-5 text-center hover:text-indigo-700 w-full py-3 hover:bg-gray-100 font-medium text-indigo-600"
>
<form class="pt-8">
<button type="submit">
This is action a247e19a-6241-40d5-918e-59acfed89fd1
</button>
<button type="reset">
This is action 28034dc1-4b14-41d3-a8a0-1b3caf4fa30d
</button>
<p
class="leading-5 group items-center font-medium py-2 text-base px-2 flex rounded-md"
>
This is paragraph 405f1bec-eb87-4969-bb55-4cf53544a14f
</p>
<select
class="sm:justify-between sm:items-center border-gray-200 mt-10 border-t pt-6 sm:flex"
>
<option value="c4529e40-02c5-45b3-bc0f-0c3189586851">
This is item 8f23c008-ddd2-41f3-b3ea-c46bb6f28d82
</option>
<option>This is item c4f71102-aef4-4e44-9f71-327fd5e7a170</option>
<option value="2ba13422-e067-438b-a018-b136c7aa6d0f">
This is item b0a84e46-0be8-4670-9806-a32d232977ee
</option>
<option value="344d5540-7984-4d99-9cb1-2ce5516bc256">
This is item aa5ac653-6243-4813-b06c-2a864ad1a57c
</option>
<option>This is item 5cf82826-4689-4ac5-bfc6-5825fecba631</option>
<option>This is item 54ef6fd7-9bfd-4585-859a-a2ce2389f3bd</option>
</select>
<select class="text-base mt-4 text-gray-300">
<option value="1a868568-b8be-46af-abf1-63d0f0eff46b">
This is item 5834f17b-43aa-48fc-a6a2-b7e178056595
</option>
<option>This is item 5d23a2e8-b7c8-43d6-b008-1d5d580b4eb8</option>
<option>This is item b79dcba7-ca37-47d0-bc3d-4156f4a75502</option>
</select>
</form>
</div>

File diff suppressed because it is too large Load diff

View file

@ -1,25 +0,0 @@
<div class="text-lg font-medium leading-6 text-gray-900">
<button type="button">
This is action e24e5f1c-9035-4ee2-a891-02117eb66f94
</button>
<img
class="bg-white hover:bg-gray-50 text-gray-500 text-sm px-4 py-2 focus:z-20 border border-gray-300 font-medium items-center relative inline-flex"
alt="Profile picture of user f05cb42f-7c6e-4ae0-a41a-f35182e57ee3"
src="https://example.org/pictures/4379ac75-365d-4e25-87a2-d5efd8897ea7"
/>
<input
type="password"
class="lg:gap-8 sm:gap-6 sm:space-y-0 space-y-4 sm:grid lg:grid-cols-3 sm:grid-cols-2"
/>
<span
class="md:col-span-8 md:row-start-2 lg:col-start-9 lg:row-start-1 md:mt-0 lg:col-span-4 mt-12 md:col-start-3"
>
This is text f21af450-0ce0-4cdb-8e69-c99776d18e53
</span>
<img
class="w-6 h-6 flex-none rounded-full"
alt="Profile picture of user f6738819-0fad-4738-b241-c074e6887a40"
src="https://example.org/pictures/e93a2481-4de5-4f90-a32b-1730631b989c"
/>
<input type="password" class="absolute inset-0" />
</div>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,12 +0,0 @@
<div class="mt-1">
<select class="text-center">
<option value="f51fc163-8223-486c-8763-f35526a54b3a">
This is item d8d705d4-5eef-46d7-91bb-1888b85b625a
</option>
<option>This is item eff23a8c-31e8-4d4b-ab38-e31e057cc502</option>
<option value="f44c6613-0db4-4db9-98dd-c58f80e2b21d">
This is item d0d4e6fc-62e1-4796-bbc3-ba1c660f24cb
</option>
<option>This is item bb90ae39-5976-4cd9-a5f1-b6cbeb11e270</option>
</select>
</div>

View file

@ -1,7 +0,0 @@
<div class="mt-1">
<img
class="bg-white"
alt="Profile picture of user 79526e3d-786c-48f2-99ce-fd5c403d6880"
src="https://example.org/pictures/6e8870ca-4388-4e28-ad24-c501946863a3"
/>
</div>

Some files were not shown because too many files have changed in this diff Show more