├── .github
├── powered-by-vercel.svg
└── typewind-logo.png
├── .gitignore
├── .prettierrc.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── TRADEOFFS.md
├── examples
├── next-example
│ ├── .gitignore
│ ├── README.md
│ ├── next.config.js
│ ├── package.json
│ ├── pages
│ │ ├── _app.tsx
│ │ ├── _document.tsx
│ │ ├── api
│ │ │ └── hello.ts
│ │ └── index.tsx
│ ├── postcss.config.js
│ ├── public
│ │ ├── favicon.ico
│ │ ├── next.svg
│ │ ├── thirteen.svg
│ │ └── vercel.svg
│ ├── styles
│ │ └── globals.css
│ ├── tailwind.config.js
│ └── tsconfig.json
├── runtime-example
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── postcss.config.cjs
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── App.tsx
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tailwind.config.cjs
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
└── vite-example
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── postcss.config.cjs
│ ├── public
│ └── vite.svg
│ ├── src
│ ├── App.tsx
│ ├── index.css
│ ├── main.tsx
│ └── vite-env.d.ts
│ ├── tailwind.config.cjs
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── jest.config.js
├── package-lock.json
├── package.json
├── packages
└── typewind
│ ├── .cargo
│ └── config
│ ├── .gitignore
│ ├── .release-it.json
│ ├── Cargo.lock
│ ├── Cargo.toml
│ ├── README.md
│ ├── package.json
│ ├── rust-toolchain
│ ├── src
│ ├── babel.ts
│ ├── cli.ts
│ ├── cn.ts
│ ├── evaluate.ts
│ ├── index.ts
│ ├── runtime.ts
│ ├── transform.ts
│ └── utils.ts
│ ├── swc
│ ├── lib.rs
│ └── value.json
│ ├── tests
│ └── __swc_snapshots__
│ │ └── swc
│ │ └── lib.rs
│ │ └── boo.js
│ ├── tsconfig.json
│ └── tsup.config.ts
├── site
├── .babelrc
├── .gitignore
├── LICENSE
├── README.md
├── components
│ ├── CodeOutput.tsx
│ ├── Features.tsx
│ ├── Home.tsx
│ ├── Stackblitz.tsx
│ └── Tweet.tsx
├── next-env.d.ts
├── next.config.mjs
├── package-lock.json
├── package.json
├── pages
│ ├── _app.tsx
│ ├── _meta.json
│ ├── docs
│ │ ├── _meta.json
│ │ ├── advanced
│ │ │ ├── _meta.json
│ │ │ ├── configuration.mdx
│ │ │ ├── custom-config-file-path.mdx
│ │ │ ├── escape-hatch.mdx
│ │ │ └── rem-to-px.mdx
│ │ ├── examples
│ │ │ ├── _meta.json
│ │ │ ├── next.mdx
│ │ │ └── vite.mdx
│ │ ├── index.mdx
│ │ ├── installation.mdx
│ │ ├── transpilers
│ │ │ ├── _meta.json
│ │ │ ├── babel.mdx
│ │ │ └── swc.mdx
│ │ ├── usage.mdx
│ │ └── usage
│ │ │ ├── _meta.json
│ │ │ ├── arbitrary-values.mdx
│ │ │ ├── arbitrary-variants.mdx
│ │ │ ├── container-queries.mdx
│ │ │ ├── important-modifier.mdx
│ │ │ ├── modifiers.mdx
│ │ │ └── normal-usage.mdx
│ └── index.mdx
├── postcss.config.js
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── preview.mov
│ ├── site.webmanifest
│ ├── typewind-logo.png
│ └── typewind-share.png
├── styles.css
├── tailwind.config.js
├── theme.config.tsx
└── tsconfig.json
└── tests
├── __snapshots__
└── transform.test.ts.snap
├── fixtures
├── arbitrary-values
│ ├── App.tsx
│ ├── package.json
│ └── tailwind.config.cjs
├── arbitrary-variants
│ ├── App.tsx
│ ├── package.json
│ └── tailwind.config.cjs
├── container-queries
│ ├── App.tsx
│ ├── package-lock.json
│ ├── package.json
│ └── tailwind.config.cjs
├── modifiers
│ ├── App.tsx
│ ├── package.json
│ └── tailwind.config.cjs
├── normal-usage
│ ├── App.tsx
│ ├── package.json
│ └── tailwind.config.cjs
└── transform
│ ├── App.tsx
│ ├── package.json
│ └── tailwind.config.cjs
└── transform.test.ts
/.github/powered-by-vercel.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.github/typewind-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mokshit06/typewind/68f453eecde4b99668d835b3a7516edc4f759b69/.github/typewind-logo.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .vscode
3 | .DS_STORE
4 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true
3 | }
4 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | mail@mokshitjain.co.
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | ## Bug fixes
4 |
5 | If you've found a bug in Typewind that you'd like to fix, [submit a pull request](https://github.com/mokshit06/typewind/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.
6 |
7 | ## New features
8 |
9 | If there's a new feature you'd like to see added to Typewind, [share your idea with us](https://github.com/mokshit06/typewind/discussions/new?category=ideas) in our discussion forum to get it on our radar as something to consider for a future release.
10 |
11 | **Please note that we don't often accept pull requests for new features.** Adding a new feature to Typewind 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.
12 |
13 | 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.
14 |
15 | ## Running tests
16 |
17 | You can run the test suite using the following commands:
18 |
19 | ```sh
20 | cargo test
21 | ```
22 |
23 | You can run update the test suite snapshot using the following command:
24 |
25 | ```sh
26 | UPDATE=1 cargo test
27 | ```
28 |
29 | To test the features you've added, run the following command:
30 |
31 | ```sh
32 | npm run build
33 | ```
34 |
35 | and then run each of the examples in `examples/*` to test that the changes are working as intended.
36 |
37 | Please ensure that the tests are passing when submitting a pull request. If you're adding new features to Typewind's SWC plugin, please include tests.
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Mokshit Jain
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The safety of Typescript with the magic of Tailwind.
5 |
6 |
7 | ---
8 |
9 | ## Introduction
10 |
11 | Typewind brings the safety, productivity and intellisense of Typescript over to Tailwind
12 |
13 | ```js
14 | import { tw } from 'typewind';
15 |
16 | const styles = tw.border.hover(tw.border_black);
17 | ```
18 |
19 | ## How it works
20 |
21 | Typewind's compiler is a babel plugin that runs over your code, statically analyses it and converts all the `tw` styles into their corresponding Tailwind classes.
22 |
23 | This results Typewind compiles away, leaving 0 runtime code.
24 |
25 | ```js
26 | import { tw } from 'typewind';
27 |
28 | const styles = tw.border.hover(tw.border_black);
29 |
30 | // ↓ ↓ ↓ ↓ ↓ ↓
31 |
32 | const styles = 'border hover:border-black';
33 | ```
34 |
35 | ## Features
36 |
37 | **Zero bundle size** - Typewind compiles away all the styles used, and converts them to static classes at build
38 |
39 | **Apply variants to multiple styles at once** - Since Typewind uses TS, it allows for more intuitive syntax for applying variants
40 |
41 | ```js
42 | import { tw } from 'typewind';
43 |
44 | const mediaStyles = tw.sm(tw.w_4.mt_3).lg(tw.w_8.mt_6);
45 | const groupInGroups = tw.text_sm.sm(tw.bg_black.hover(tw.bg_white.w_10));
46 | ```
47 |
48 | **Type safety and intellisense** - Using the TS compiler, Typewind is able to provide type safety to tailwind, and provide intellisense & autocomplete for all the classes from tailwind config.
49 |
50 | ```js
51 | import { tw } from 'typewind';
52 |
53 | const styles = tw.border_blackk; // ❌ Property 'border_blackk' does not exist on type 'Typewind'. Did you mean 'border_black'?
54 | ```
55 |
56 | The above code would also return in a build error on running `tsc`
57 |
58 | **Types generated from config** - Type definitions of `tw` are generated directly from your tailwind config, so it is always custom to you, and also creates types for custom theme palette and plugins.
59 |
60 | [](https://vercel.com?utm_source=typewind&utm_campaign=oss)
61 |
--------------------------------------------------------------------------------
/TRADEOFFS.md:
--------------------------------------------------------------------------------
1 | # Tradeoffs
2 |
3 | ## Benefits
4 |
5 | - Typesafety
6 |
7 | Using TS intellisense and type generation, Typewind is able to provide type safety and autocomplete for all the classes based on `tailwind.config.js`. It can also catch typos and report incorrect classes.
8 |
9 | Typewind also works with all tailwind plugins, and provides type safety to them as well.
10 |
11 | - CSS Docs on hover
12 |
13 | Typewind shows the CSS that tailwind would generate for each style on hovering over the property, as well as when typing them with autocomplete using JSDoc.
14 |
15 | - Zero Bundle Size
16 |
17 | Typewind compiles away all the styles used, and converts them to static classes at build time. It adds 0 additional bytes to your bundle
18 |
19 | - Grouped variants
20 |
21 | Managing multiple styles for a variant can get messy and hard to keep track of, for eg `hover:text-red-500 text-red-700 hover:text-sm`. Here we're having to specify `hover:` twice, and need to read all styles to find the hover variants.
22 | In typewind these can be grouped together `tw.text_red_700.hover(tw.text_red_500.text_sm)`.
23 |
24 | - No need for extensions
25 |
26 | Since typewind uses Typescript for autocomplete as well as linting/type-checking, it doesn't require the setup of any additional editor extensions/eslint plugins to do this.
27 |
28 | ## Limitations
29 |
30 | - Slightly slower build times
31 |
32 | Typewind's babel transform runs at compile time, so it does make the builds a bit slower. It also requires babel currently, so if you're using some other transpiler like SWC, you would need to switch to babel which would again slow down the builds.
33 |
34 | - Doesn't support _every_ tailwind syntax.
35 |
36 | Typewind currently doesn't support some classes of tailwind, such as background opacity and named container queries. This is mostly because the syntax for them isn't finalised and due to the contrainsts of JS, we can't use seperators like `/` or `#`
37 |
38 | - Odd formatting
39 |
40 | If you use arbitrary values, formatters like prettier might format the styles in an odd way, like moving the arbitrary part to new line.
41 |
42 | - Doesn't sort classes using prettier
43 |
44 | Tailwind's prettier plugin for sorting classes based on recommended class order doesn't work with Typewind, but it might soon have a custom prettier plugin to support that.
45 |
46 | - Only works in JS/TS files
47 |
48 | This library can only be used in TS and JS files as of now, and doesn't work in `.astro`, `.svelte` and `.mdx` files.
49 |
--------------------------------------------------------------------------------
/examples/next-example/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | .pnpm-debug.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/examples/next-example/README.md:
--------------------------------------------------------------------------------
1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2 |
3 | ## Getting Started
4 |
5 | First, run the development server:
6 |
7 | ```bash
8 | npm run dev
9 | # or
10 | yarn dev
11 | # or
12 | pnpm dev
13 | ```
14 |
15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
16 |
17 | You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
18 |
19 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
20 |
21 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
22 |
23 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
24 |
25 | ## Learn More
26 |
27 | To learn more about Next.js, take a look at the following resources:
28 |
29 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
30 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
31 |
32 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
33 |
34 | ## Deploy on Vercel
35 |
36 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
37 |
38 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
39 |
--------------------------------------------------------------------------------
/examples/next-example/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | reactStrictMode: true,
4 | experimental: {
5 | swcPlugins: [['typewind/swc', {}]],
6 | },
7 | };
8 |
9 | module.exports = nextConfig;
10 |
--------------------------------------------------------------------------------
/examples/next-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "next-example",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "postinstall": "typewind generate",
7 | "dev": "next dev",
8 | "build": "next build",
9 | "start": "next start",
10 | "lint": "next lint"
11 | },
12 | "dependencies": {
13 | "@next/font": "^14.1.3",
14 | "@tailwindcss/container-queries": "^0.1.0",
15 | "@types/node": "18.11.18",
16 | "@types/react": "18.0.27",
17 | "@types/react-dom": "18.0.10",
18 | "next": "^14.1.3",
19 | "react": "18.2.0",
20 | "react-dom": "18.2.0",
21 | "typescript": "4.9.4"
22 | },
23 | "devDependencies": {
24 | "autoprefixer": "^10.4.13",
25 | "postcss": "^8.4.21",
26 | "tailwindcss": "^3.2.4",
27 | "typewind": "^0.1.4"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/examples/next-example/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import '@/styles/globals.css'
2 | import type { AppProps } from 'next/app'
3 |
4 | export default function App({ Component, pageProps }: AppProps) {
5 | return
6 | }
7 |
--------------------------------------------------------------------------------
/examples/next-example/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | import { Html, Head, Main, NextScript } from 'next/document'
2 |
3 | export default function Document() {
4 | return (
5 |
6 |
8 |
9 |
10 |
11 |
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/examples/next-example/pages/api/hello.ts:
--------------------------------------------------------------------------------
1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
2 | import type { NextApiRequest, NextApiResponse } from 'next'
3 |
4 | type Data = {
5 | name: string
6 | }
7 |
8 | export default function handler(
9 | req: NextApiRequest,
10 | res: NextApiResponse
11 | ) {
12 | res.status(200).json({ name: 'John Doe' })
13 | }
14 |
--------------------------------------------------------------------------------
/examples/next-example/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import Head from 'next/head';
2 | import { tw } from 'typewind';
3 |
4 | export default function Home() {
5 | return (
6 | <>
7 |
8 | Create Next App
9 |
10 |
11 |
12 |
13 |
14 |
19 |
24 | {/* primary color is coming from tailwind.config.js */}
25 |
30 | Hello World
31 |
32 |
33 | {Array(5)
34 | .fill(' ')
35 | .map((_, i) => (
36 |
45 | Item {i}
46 |
47 | ))}
48 |
49 |
50 | This is an example vite app demonstrating the use of{' '}
51 |
55 | Typewind
56 |
57 | .
58 |
59 |
60 |
61 |
62 | >
63 | );
64 | }
65 |
--------------------------------------------------------------------------------
/examples/next-example/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/examples/next-example/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mokshit06/typewind/68f453eecde4b99668d835b3a7516edc4f759b69/examples/next-example/public/favicon.ico
--------------------------------------------------------------------------------
/examples/next-example/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/next-example/public/thirteen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/next-example/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/next-example/styles/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/examples/next-example/tailwind.config.js:
--------------------------------------------------------------------------------
1 | const { typewindTransforms } = require('typewind/transform');
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | content: {
6 | files: [
7 | './app/**/*.{js,ts,jsx,tsx}',
8 | './pages/**/*.{js,ts,jsx,tsx}',
9 | './components/**/*.{js,ts,jsx,tsx}',
10 |
11 | // Or if using `src` directory:
12 | './src/**/*.{js,ts,jsx,tsx}',
13 | ],
14 | transform: typewindTransforms,
15 | },
16 | theme: {
17 | extend: {
18 | colors: {
19 | 'next-example-primary': '#1FA5E9',
20 | },
21 | },
22 | },
23 | plugins: [require('@tailwindcss/container-queries')],
24 | };
25 |
--------------------------------------------------------------------------------
/examples/next-example/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "baseUrl": ".",
18 | "paths": {
19 | "@/*": ["./*"]
20 | },
21 | "noPropertyAccessFromIndexSignature": true
22 | },
23 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
24 | "exclude": ["node_modules"]
25 | }
26 |
--------------------------------------------------------------------------------
/examples/runtime-example/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/examples/runtime-example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/examples/runtime-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "runtime-example",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "postinstall": "typewind generate",
8 | "dev": "vite",
9 | "build": "tsc && vite build",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@tailwindcss/typography": "^0.5.9",
14 | "react": "^18.2.0",
15 | "react-dom": "^18.2.0"
16 | },
17 | "devDependencies": {
18 | "@types/react": "^18.0.26",
19 | "@types/react-dom": "^18.0.9",
20 | "@vitejs/plugin-react": "^3.0.0",
21 | "typescript": "^4.9.3",
22 | "autoprefixer": "^10.4.13",
23 | "postcss": "^8.4.21",
24 | "tailwindcss": "^3.2.4",
25 | "typewind": "*",
26 | "vite": "^4.0.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/examples/runtime-example/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/examples/runtime-example/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/runtime-example/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { tw } from 'typewind';
2 | import { cn } from 'typewind/cn';
3 |
4 | import './index.css';
5 |
6 | export default function App() {
7 | return (
8 |
15 |
20 |
Hello World
21 |
22 | This is an example vite app demonstrating the use of{' '}
23 |
24 | Typewind
25 |
26 | .
27 |
28 |
29 |
30 | );
31 | }
32 |
--------------------------------------------------------------------------------
/examples/runtime-example/src/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/examples/runtime-example/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import App from './App';
4 | import './index.css';
5 |
6 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/examples/runtime-example/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/examples/runtime-example/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | const { typewindTransforms } = require('typewind/transform');
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | content: {
6 | files: ['./index.html', './src/**/*.{js,jsx,ts,tsx}'],
7 | transform: typewindTransforms,
8 | },
9 | theme: {
10 | extend: {
11 | colors: {
12 | primary: '#1FA5E9',
13 | },
14 | },
15 | },
16 | plugins: [require('@tailwindcss/typography')],
17 | };
18 |
--------------------------------------------------------------------------------
/examples/runtime-example/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": true,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Bundler",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx",
18 | "noPropertyAccessFromIndexSignature": true
19 | },
20 | "include": ["src"],
21 | "references": [{ "path": "./tsconfig.node.json" }]
22 | }
23 |
--------------------------------------------------------------------------------
/examples/runtime-example/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "ESNext",
5 | "moduleResolution": "Bundler",
6 | "allowSyntheticDefaultImports": true
7 | },
8 | "include": [
9 | "vite.config.ts"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/examples/runtime-example/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/vite-example/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/examples/vite-example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/examples/vite-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vite-example",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "postinstall": "typewind generate",
8 | "dev": "vite",
9 | "build": "tsc && vite build",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@tailwindcss/typography": "^0.5.9",
14 | "react": "^18.2.0",
15 | "react-dom": "^18.2.0"
16 | },
17 | "devDependencies": {
18 | "@types/react": "^18.0.26",
19 | "@types/react-dom": "^18.0.9",
20 | "@vitejs/plugin-react": "^3.0.0",
21 | "typescript": "^4.9.3",
22 | "autoprefixer": "^10.4.13",
23 | "postcss": "^8.4.21",
24 | "tailwindcss": "^3.2.4",
25 | "typewind": "*",
26 | "vite": "^4.0.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/examples/vite-example/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/examples/vite-example/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/vite-example/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { tw } from 'typewind';
2 | import './index.css';
3 |
4 | export default function App() {
5 | return (
6 |
11 |
16 | {/* primary color is coming from tailwind.config.js */}
17 |
Hello World
18 |
19 | This is an example vite app demonstrating the use of{' '}
20 |
21 | Typewind
22 |
23 | .
24 |
25 |
26 |
27 | );
28 | }
29 |
--------------------------------------------------------------------------------
/examples/vite-example/src/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/examples/vite-example/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import App from './App';
4 | import './index.css';
5 |
6 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/examples/vite-example/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/examples/vite-example/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | const { typewindTransforms } = require('typewind/transform');
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | content: {
6 | files: ['./index.html', './src/**/*.{js,jsx,ts,tsx}'],
7 | transform: typewindTransforms,
8 | },
9 | theme: {
10 | extend: {
11 | colors: {
12 | primary: '#1FA5E9',
13 | },
14 | },
15 | },
16 | plugins: [require('@tailwindcss/typography')],
17 | };
18 |
--------------------------------------------------------------------------------
/examples/vite-example/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": true,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx",
18 | "noPropertyAccessFromIndexSignature": true
19 | },
20 | "include": ["src"],
21 | "references": [{ "path": "./tsconfig.node.json" }]
22 | }
23 |
--------------------------------------------------------------------------------
/examples/vite-example/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "ESNext",
5 | "moduleResolution": "Node",
6 | "allowSyntheticDefaultImports": true
7 | },
8 | "include": ["vite.config.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/examples/vite-example/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react({ babel: { plugins: ['typewind/babel'] } })],
7 | });
8 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | preset: 'ts-jest',
3 | };
4 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "typewind-repo",
3 | "version": "1.0.0",
4 | "private": true,
5 | "engines": {
6 | "node": ">=15.0.0"
7 | },
8 | "type": "module",
9 | "keywords": [],
10 | "workspaces": [
11 | "packages/*",
12 | "examples/*"
13 | ],
14 | "author": "",
15 | "license": "ISC",
16 | "scripts": {
17 | "test": "jest"
18 | },
19 | "description": "",
20 | "devDependencies": {
21 | "@types/glob": "^8.0.1",
22 | "@types/jest": "^29.4.0",
23 | "@types/node": "^18.11.18",
24 | "jest": "^29.4.1",
25 | "tailwindcss": "^3.4.10",
26 | "ts-jest": "^29.0.5",
27 | "typescript": "^4.9.4",
28 | "typewind": "*"
29 | },
30 | "dependencies": {
31 | "esbuild": "^0.23.1",
32 | "glob": "^8.1.0"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/typewind/.cargo/config:
--------------------------------------------------------------------------------
1 | # These command aliases are not final, may change
2 | [alias]
3 | # Alias to build actual plugin binary for the specified target.
4 | build-wasi = "build --target wasm32-wasi"
5 | build-wasm32 = "build --target wasm32-unknown-unknown"
6 |
--------------------------------------------------------------------------------
/packages/typewind/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | target/
--------------------------------------------------------------------------------
/packages/typewind/.release-it.json:
--------------------------------------------------------------------------------
1 | {
2 | "github": {
3 | "release": true
4 | },
5 | "git": {
6 | "commitMessage": "release: v${version}"
7 | }
8 | }
--------------------------------------------------------------------------------
/packages/typewind/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "Inflector"
7 | version = "0.11.4"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
10 | dependencies = [
11 | "lazy_static",
12 | "regex",
13 | ]
14 |
15 | [[package]]
16 | name = "addr2line"
17 | version = "0.21.0"
18 | source = "registry+https://github.com/rust-lang/crates.io-index"
19 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
20 | dependencies = [
21 | "gimli",
22 | ]
23 |
24 | [[package]]
25 | name = "adler"
26 | version = "1.0.2"
27 | source = "registry+https://github.com/rust-lang/crates.io-index"
28 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
29 |
30 | [[package]]
31 | name = "ahash"
32 | version = "0.7.6"
33 | source = "registry+https://github.com/rust-lang/crates.io-index"
34 | checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
35 | dependencies = [
36 | "getrandom",
37 | "once_cell",
38 | "version_check",
39 | ]
40 |
41 | [[package]]
42 | name = "aho-corasick"
43 | version = "1.1.1"
44 | source = "registry+https://github.com/rust-lang/crates.io-index"
45 | checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab"
46 | dependencies = [
47 | "memchr",
48 | ]
49 |
50 | [[package]]
51 | name = "ansi_term"
52 | version = "0.12.1"
53 | source = "registry+https://github.com/rust-lang/crates.io-index"
54 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
55 | dependencies = [
56 | "winapi",
57 | ]
58 |
59 | [[package]]
60 | name = "anyhow"
61 | version = "1.0.87"
62 | source = "registry+https://github.com/rust-lang/crates.io-index"
63 | checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8"
64 |
65 | [[package]]
66 | name = "ast_node"
67 | version = "0.9.9"
68 | source = "registry+https://github.com/rust-lang/crates.io-index"
69 | checksum = "f9184f2b369b3e8625712493c89b785881f27eedc6cde480a81883cef78868b2"
70 | dependencies = [
71 | "proc-macro2",
72 | "quote",
73 | "swc_macros_common",
74 | "syn 2.0.77",
75 | ]
76 |
77 | [[package]]
78 | name = "atty"
79 | version = "0.2.14"
80 | source = "registry+https://github.com/rust-lang/crates.io-index"
81 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
82 | dependencies = [
83 | "hermit-abi 0.1.19",
84 | "libc",
85 | "winapi",
86 | ]
87 |
88 | [[package]]
89 | name = "autocfg"
90 | version = "1.1.0"
91 | source = "registry+https://github.com/rust-lang/crates.io-index"
92 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
93 |
94 | [[package]]
95 | name = "backtrace"
96 | version = "0.3.69"
97 | source = "registry+https://github.com/rust-lang/crates.io-index"
98 | checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
99 | dependencies = [
100 | "addr2line",
101 | "cc",
102 | "cfg-if",
103 | "libc",
104 | "miniz_oxide",
105 | "object",
106 | "rustc-demangle",
107 | ]
108 |
109 | [[package]]
110 | name = "base64"
111 | version = "0.21.7"
112 | source = "registry+https://github.com/rust-lang/crates.io-index"
113 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
114 |
115 | [[package]]
116 | name = "base64-simd"
117 | version = "0.7.0"
118 | source = "registry+https://github.com/rust-lang/crates.io-index"
119 | checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5"
120 | dependencies = [
121 | "simd-abstraction",
122 | ]
123 |
124 | [[package]]
125 | name = "better_scoped_tls"
126 | version = "0.1.1"
127 | source = "registry+https://github.com/rust-lang/crates.io-index"
128 | checksum = "794edcc9b3fb07bb4aecaa11f093fd45663b4feadb782d68303a2268bc2701de"
129 | dependencies = [
130 | "scoped-tls",
131 | ]
132 |
133 | [[package]]
134 | name = "bitflags"
135 | version = "1.3.2"
136 | source = "registry+https://github.com/rust-lang/crates.io-index"
137 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
138 |
139 | [[package]]
140 | name = "bitflags"
141 | version = "2.6.0"
142 | source = "registry+https://github.com/rust-lang/crates.io-index"
143 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
144 |
145 | [[package]]
146 | name = "bitvec"
147 | version = "1.0.1"
148 | source = "registry+https://github.com/rust-lang/crates.io-index"
149 | checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
150 | dependencies = [
151 | "funty",
152 | "radium",
153 | "tap",
154 | "wyz",
155 | ]
156 |
157 | [[package]]
158 | name = "block-buffer"
159 | version = "0.10.4"
160 | source = "registry+https://github.com/rust-lang/crates.io-index"
161 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
162 | dependencies = [
163 | "generic-array",
164 | ]
165 |
166 | [[package]]
167 | name = "bytecheck"
168 | version = "0.6.11"
169 | source = "registry+https://github.com/rust-lang/crates.io-index"
170 | checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627"
171 | dependencies = [
172 | "bytecheck_derive",
173 | "ptr_meta",
174 | "simdutf8",
175 | ]
176 |
177 | [[package]]
178 | name = "bytecheck_derive"
179 | version = "0.6.11"
180 | source = "registry+https://github.com/rust-lang/crates.io-index"
181 | checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61"
182 | dependencies = [
183 | "proc-macro2",
184 | "quote",
185 | "syn 1.0.109",
186 | ]
187 |
188 | [[package]]
189 | name = "bytes"
190 | version = "1.7.1"
191 | source = "registry+https://github.com/rust-lang/crates.io-index"
192 | checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
193 |
194 | [[package]]
195 | name = "camino"
196 | version = "1.1.6"
197 | source = "registry+https://github.com/rust-lang/crates.io-index"
198 | checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
199 | dependencies = [
200 | "serde",
201 | ]
202 |
203 | [[package]]
204 | name = "cargo-platform"
205 | version = "0.1.3"
206 | source = "registry+https://github.com/rust-lang/crates.io-index"
207 | checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479"
208 | dependencies = [
209 | "serde",
210 | ]
211 |
212 | [[package]]
213 | name = "cargo_metadata"
214 | version = "0.15.4"
215 | source = "registry+https://github.com/rust-lang/crates.io-index"
216 | checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a"
217 | dependencies = [
218 | "camino",
219 | "cargo-platform",
220 | "semver 1.0.19",
221 | "serde",
222 | "serde_json",
223 | "thiserror",
224 | ]
225 |
226 | [[package]]
227 | name = "cargo_metadata"
228 | version = "0.18.1"
229 | source = "registry+https://github.com/rust-lang/crates.io-index"
230 | checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037"
231 | dependencies = [
232 | "camino",
233 | "cargo-platform",
234 | "semver 1.0.19",
235 | "serde",
236 | "serde_json",
237 | "thiserror",
238 | ]
239 |
240 | [[package]]
241 | name = "cc"
242 | version = "1.0.83"
243 | source = "registry+https://github.com/rust-lang/crates.io-index"
244 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
245 | dependencies = [
246 | "libc",
247 | ]
248 |
249 | [[package]]
250 | name = "cfg-if"
251 | version = "1.0.0"
252 | source = "registry+https://github.com/rust-lang/crates.io-index"
253 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
254 |
255 | [[package]]
256 | name = "cpufeatures"
257 | version = "0.2.9"
258 | source = "registry+https://github.com/rust-lang/crates.io-index"
259 | checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
260 | dependencies = [
261 | "libc",
262 | ]
263 |
264 | [[package]]
265 | name = "crypto-common"
266 | version = "0.1.6"
267 | source = "registry+https://github.com/rust-lang/crates.io-index"
268 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
269 | dependencies = [
270 | "generic-array",
271 | "typenum",
272 | ]
273 |
274 | [[package]]
275 | name = "data-encoding"
276 | version = "2.4.0"
277 | source = "registry+https://github.com/rust-lang/crates.io-index"
278 | checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
279 |
280 | [[package]]
281 | name = "debugid"
282 | version = "0.8.0"
283 | source = "registry+https://github.com/rust-lang/crates.io-index"
284 | checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d"
285 | dependencies = [
286 | "serde",
287 | "uuid",
288 | ]
289 |
290 | [[package]]
291 | name = "diff"
292 | version = "0.1.13"
293 | source = "registry+https://github.com/rust-lang/crates.io-index"
294 | checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
295 |
296 | [[package]]
297 | name = "difference"
298 | version = "2.0.0"
299 | source = "registry+https://github.com/rust-lang/crates.io-index"
300 | checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
301 |
302 | [[package]]
303 | name = "digest"
304 | version = "0.10.7"
305 | source = "registry+https://github.com/rust-lang/crates.io-index"
306 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
307 | dependencies = [
308 | "block-buffer",
309 | "crypto-common",
310 | ]
311 |
312 | [[package]]
313 | name = "either"
314 | version = "1.13.0"
315 | source = "registry+https://github.com/rust-lang/crates.io-index"
316 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
317 |
318 | [[package]]
319 | name = "equivalent"
320 | version = "1.0.1"
321 | source = "registry+https://github.com/rust-lang/crates.io-index"
322 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
323 |
324 | [[package]]
325 | name = "errno"
326 | version = "0.3.4"
327 | source = "registry+https://github.com/rust-lang/crates.io-index"
328 | checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480"
329 | dependencies = [
330 | "errno-dragonfly",
331 | "libc",
332 | "windows-sys",
333 | ]
334 |
335 | [[package]]
336 | name = "errno-dragonfly"
337 | version = "0.1.2"
338 | source = "registry+https://github.com/rust-lang/crates.io-index"
339 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
340 | dependencies = [
341 | "cc",
342 | "libc",
343 | ]
344 |
345 | [[package]]
346 | name = "fastrand"
347 | version = "2.0.1"
348 | source = "registry+https://github.com/rust-lang/crates.io-index"
349 | checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
350 |
351 | [[package]]
352 | name = "form_urlencoded"
353 | version = "1.2.0"
354 | source = "registry+https://github.com/rust-lang/crates.io-index"
355 | checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
356 | dependencies = [
357 | "percent-encoding",
358 | ]
359 |
360 | [[package]]
361 | name = "from_variant"
362 | version = "0.1.9"
363 | source = "registry+https://github.com/rust-lang/crates.io-index"
364 | checksum = "32016f1242eb82af5474752d00fd8ebcd9004bd69b462b1c91de833972d08ed4"
365 | dependencies = [
366 | "proc-macro2",
367 | "swc_macros_common",
368 | "syn 2.0.77",
369 | ]
370 |
371 | [[package]]
372 | name = "funty"
373 | version = "2.0.0"
374 | source = "registry+https://github.com/rust-lang/crates.io-index"
375 | checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
376 |
377 | [[package]]
378 | name = "generic-array"
379 | version = "0.14.7"
380 | source = "registry+https://github.com/rust-lang/crates.io-index"
381 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
382 | dependencies = [
383 | "typenum",
384 | "version_check",
385 | ]
386 |
387 | [[package]]
388 | name = "getrandom"
389 | version = "0.2.10"
390 | source = "registry+https://github.com/rust-lang/crates.io-index"
391 | checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
392 | dependencies = [
393 | "cfg-if",
394 | "libc",
395 | "wasi",
396 | ]
397 |
398 | [[package]]
399 | name = "gimli"
400 | version = "0.28.0"
401 | source = "registry+https://github.com/rust-lang/crates.io-index"
402 | checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
403 |
404 | [[package]]
405 | name = "glob"
406 | version = "0.3.1"
407 | source = "registry+https://github.com/rust-lang/crates.io-index"
408 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
409 |
410 | [[package]]
411 | name = "hashbrown"
412 | version = "0.12.3"
413 | source = "registry+https://github.com/rust-lang/crates.io-index"
414 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
415 | dependencies = [
416 | "ahash",
417 | ]
418 |
419 | [[package]]
420 | name = "hashbrown"
421 | version = "0.14.5"
422 | source = "registry+https://github.com/rust-lang/crates.io-index"
423 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
424 |
425 | [[package]]
426 | name = "hermit-abi"
427 | version = "0.1.19"
428 | source = "registry+https://github.com/rust-lang/crates.io-index"
429 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
430 | dependencies = [
431 | "libc",
432 | ]
433 |
434 | [[package]]
435 | name = "hermit-abi"
436 | version = "0.3.3"
437 | source = "registry+https://github.com/rust-lang/crates.io-index"
438 | checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
439 |
440 | [[package]]
441 | name = "hex"
442 | version = "0.4.3"
443 | source = "registry+https://github.com/rust-lang/crates.io-index"
444 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
445 |
446 | [[package]]
447 | name = "hstr"
448 | version = "0.2.12"
449 | source = "registry+https://github.com/rust-lang/crates.io-index"
450 | checksum = "dae404c0c5d4e95d4858876ab02eecd6a196bb8caa42050dfa809938833fc412"
451 | dependencies = [
452 | "hashbrown 0.14.5",
453 | "new_debug_unreachable",
454 | "once_cell",
455 | "phf",
456 | "rustc-hash",
457 | "triomphe",
458 | ]
459 |
460 | [[package]]
461 | name = "idna"
462 | version = "0.4.0"
463 | source = "registry+https://github.com/rust-lang/crates.io-index"
464 | checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
465 | dependencies = [
466 | "unicode-bidi",
467 | "unicode-normalization",
468 | ]
469 |
470 | [[package]]
471 | name = "if_chain"
472 | version = "1.0.2"
473 | source = "registry+https://github.com/rust-lang/crates.io-index"
474 | checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
475 |
476 | [[package]]
477 | name = "indexmap"
478 | version = "2.5.0"
479 | source = "registry+https://github.com/rust-lang/crates.io-index"
480 | checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
481 | dependencies = [
482 | "equivalent",
483 | "hashbrown 0.14.5",
484 | ]
485 |
486 | [[package]]
487 | name = "is-macro"
488 | version = "0.3.6"
489 | source = "registry+https://github.com/rust-lang/crates.io-index"
490 | checksum = "2069faacbe981460232f880d26bf3c7634e322d49053aa48c27e3ae642f728f1"
491 | dependencies = [
492 | "Inflector",
493 | "proc-macro2",
494 | "quote",
495 | "syn 2.0.77",
496 | ]
497 |
498 | [[package]]
499 | name = "is_ci"
500 | version = "1.1.1"
501 | source = "registry+https://github.com/rust-lang/crates.io-index"
502 | checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
503 |
504 | [[package]]
505 | name = "itoa"
506 | version = "1.0.9"
507 | source = "registry+https://github.com/rust-lang/crates.io-index"
508 | checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
509 |
510 | [[package]]
511 | name = "lazy_static"
512 | version = "1.4.0"
513 | source = "registry+https://github.com/rust-lang/crates.io-index"
514 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
515 |
516 | [[package]]
517 | name = "libc"
518 | version = "0.2.148"
519 | source = "registry+https://github.com/rust-lang/crates.io-index"
520 | checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
521 |
522 | [[package]]
523 | name = "linux-raw-sys"
524 | version = "0.4.8"
525 | source = "registry+https://github.com/rust-lang/crates.io-index"
526 | checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db"
527 |
528 | [[package]]
529 | name = "lock_api"
530 | version = "0.4.10"
531 | source = "registry+https://github.com/rust-lang/crates.io-index"
532 | checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
533 | dependencies = [
534 | "autocfg",
535 | "scopeguard",
536 | ]
537 |
538 | [[package]]
539 | name = "log"
540 | version = "0.4.20"
541 | source = "registry+https://github.com/rust-lang/crates.io-index"
542 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
543 |
544 | [[package]]
545 | name = "matchers"
546 | version = "0.1.0"
547 | source = "registry+https://github.com/rust-lang/crates.io-index"
548 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
549 | dependencies = [
550 | "regex-automata 0.1.10",
551 | ]
552 |
553 | [[package]]
554 | name = "memchr"
555 | version = "2.6.4"
556 | source = "registry+https://github.com/rust-lang/crates.io-index"
557 | checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
558 |
559 | [[package]]
560 | name = "miette"
561 | version = "4.7.1"
562 | source = "registry+https://github.com/rust-lang/crates.io-index"
563 | checksum = "1c90329e44f9208b55f45711f9558cec15d7ef8295cc65ecd6d4188ae8edc58c"
564 | dependencies = [
565 | "atty",
566 | "backtrace",
567 | "miette-derive",
568 | "once_cell",
569 | "owo-colors",
570 | "supports-color",
571 | "supports-hyperlinks",
572 | "supports-unicode",
573 | "terminal_size",
574 | "textwrap",
575 | "thiserror",
576 | "unicode-width",
577 | ]
578 |
579 | [[package]]
580 | name = "miette-derive"
581 | version = "4.7.1"
582 | source = "registry+https://github.com/rust-lang/crates.io-index"
583 | checksum = "6b5bc45b761bcf1b5e6e6c4128cd93b84c218721a8d9b894aa0aff4ed180174c"
584 | dependencies = [
585 | "proc-macro2",
586 | "quote",
587 | "syn 1.0.109",
588 | ]
589 |
590 | [[package]]
591 | name = "miniz_oxide"
592 | version = "0.7.1"
593 | source = "registry+https://github.com/rust-lang/crates.io-index"
594 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
595 | dependencies = [
596 | "adler",
597 | ]
598 |
599 | [[package]]
600 | name = "new_debug_unreachable"
601 | version = "1.0.4"
602 | source = "registry+https://github.com/rust-lang/crates.io-index"
603 | checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
604 |
605 | [[package]]
606 | name = "nu-ansi-term"
607 | version = "0.46.0"
608 | source = "registry+https://github.com/rust-lang/crates.io-index"
609 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
610 | dependencies = [
611 | "overload",
612 | "winapi",
613 | ]
614 |
615 | [[package]]
616 | name = "num-bigint"
617 | version = "0.4.4"
618 | source = "registry+https://github.com/rust-lang/crates.io-index"
619 | checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
620 | dependencies = [
621 | "autocfg",
622 | "num-integer",
623 | "num-traits",
624 | "serde",
625 | ]
626 |
627 | [[package]]
628 | name = "num-integer"
629 | version = "0.1.45"
630 | source = "registry+https://github.com/rust-lang/crates.io-index"
631 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
632 | dependencies = [
633 | "autocfg",
634 | "num-traits",
635 | ]
636 |
637 | [[package]]
638 | name = "num-traits"
639 | version = "0.2.16"
640 | source = "registry+https://github.com/rust-lang/crates.io-index"
641 | checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
642 | dependencies = [
643 | "autocfg",
644 | ]
645 |
646 | [[package]]
647 | name = "num_cpus"
648 | version = "1.16.0"
649 | source = "registry+https://github.com/rust-lang/crates.io-index"
650 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
651 | dependencies = [
652 | "hermit-abi 0.3.3",
653 | "libc",
654 | ]
655 |
656 | [[package]]
657 | name = "object"
658 | version = "0.32.1"
659 | source = "registry+https://github.com/rust-lang/crates.io-index"
660 | checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
661 | dependencies = [
662 | "memchr",
663 | ]
664 |
665 | [[package]]
666 | name = "once_cell"
667 | version = "1.19.0"
668 | source = "registry+https://github.com/rust-lang/crates.io-index"
669 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
670 |
671 | [[package]]
672 | name = "outref"
673 | version = "0.1.0"
674 | source = "registry+https://github.com/rust-lang/crates.io-index"
675 | checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4"
676 |
677 | [[package]]
678 | name = "overload"
679 | version = "0.1.1"
680 | source = "registry+https://github.com/rust-lang/crates.io-index"
681 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
682 |
683 | [[package]]
684 | name = "owo-colors"
685 | version = "3.5.0"
686 | source = "registry+https://github.com/rust-lang/crates.io-index"
687 | checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
688 |
689 | [[package]]
690 | name = "parking_lot"
691 | version = "0.12.1"
692 | source = "registry+https://github.com/rust-lang/crates.io-index"
693 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
694 | dependencies = [
695 | "lock_api",
696 | "parking_lot_core",
697 | ]
698 |
699 | [[package]]
700 | name = "parking_lot_core"
701 | version = "0.9.8"
702 | source = "registry+https://github.com/rust-lang/crates.io-index"
703 | checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
704 | dependencies = [
705 | "cfg-if",
706 | "libc",
707 | "redox_syscall",
708 | "smallvec",
709 | "windows-targets",
710 | ]
711 |
712 | [[package]]
713 | name = "percent-encoding"
714 | version = "2.3.0"
715 | source = "registry+https://github.com/rust-lang/crates.io-index"
716 | checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
717 |
718 | [[package]]
719 | name = "phf"
720 | version = "0.11.2"
721 | source = "registry+https://github.com/rust-lang/crates.io-index"
722 | checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
723 | dependencies = [
724 | "phf_macros",
725 | "phf_shared 0.11.2",
726 | ]
727 |
728 | [[package]]
729 | name = "phf_generator"
730 | version = "0.10.0"
731 | source = "registry+https://github.com/rust-lang/crates.io-index"
732 | checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
733 | dependencies = [
734 | "phf_shared 0.10.0",
735 | "rand",
736 | ]
737 |
738 | [[package]]
739 | name = "phf_generator"
740 | version = "0.11.2"
741 | source = "registry+https://github.com/rust-lang/crates.io-index"
742 | checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
743 | dependencies = [
744 | "phf_shared 0.11.2",
745 | "rand",
746 | ]
747 |
748 | [[package]]
749 | name = "phf_macros"
750 | version = "0.11.2"
751 | source = "registry+https://github.com/rust-lang/crates.io-index"
752 | checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
753 | dependencies = [
754 | "phf_generator 0.11.2",
755 | "phf_shared 0.11.2",
756 | "proc-macro2",
757 | "quote",
758 | "syn 2.0.77",
759 | ]
760 |
761 | [[package]]
762 | name = "phf_shared"
763 | version = "0.10.0"
764 | source = "registry+https://github.com/rust-lang/crates.io-index"
765 | checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
766 | dependencies = [
767 | "siphasher",
768 | ]
769 |
770 | [[package]]
771 | name = "phf_shared"
772 | version = "0.11.2"
773 | source = "registry+https://github.com/rust-lang/crates.io-index"
774 | checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
775 | dependencies = [
776 | "siphasher",
777 | ]
778 |
779 | [[package]]
780 | name = "pin-project-lite"
781 | version = "0.2.13"
782 | source = "registry+https://github.com/rust-lang/crates.io-index"
783 | checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
784 |
785 | [[package]]
786 | name = "ppv-lite86"
787 | version = "0.2.17"
788 | source = "registry+https://github.com/rust-lang/crates.io-index"
789 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
790 |
791 | [[package]]
792 | name = "precomputed-hash"
793 | version = "0.1.1"
794 | source = "registry+https://github.com/rust-lang/crates.io-index"
795 | checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
796 |
797 | [[package]]
798 | name = "pretty_assertions"
799 | version = "1.4.0"
800 | source = "registry+https://github.com/rust-lang/crates.io-index"
801 | checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
802 | dependencies = [
803 | "diff",
804 | "yansi",
805 | ]
806 |
807 | [[package]]
808 | name = "proc-macro2"
809 | version = "1.0.86"
810 | source = "registry+https://github.com/rust-lang/crates.io-index"
811 | checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
812 | dependencies = [
813 | "unicode-ident",
814 | ]
815 |
816 | [[package]]
817 | name = "psm"
818 | version = "0.1.21"
819 | source = "registry+https://github.com/rust-lang/crates.io-index"
820 | checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874"
821 | dependencies = [
822 | "cc",
823 | ]
824 |
825 | [[package]]
826 | name = "ptr_meta"
827 | version = "0.1.4"
828 | source = "registry+https://github.com/rust-lang/crates.io-index"
829 | checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
830 | dependencies = [
831 | "ptr_meta_derive",
832 | ]
833 |
834 | [[package]]
835 | name = "ptr_meta_derive"
836 | version = "0.1.4"
837 | source = "registry+https://github.com/rust-lang/crates.io-index"
838 | checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
839 | dependencies = [
840 | "proc-macro2",
841 | "quote",
842 | "syn 1.0.109",
843 | ]
844 |
845 | [[package]]
846 | name = "quote"
847 | version = "1.0.37"
848 | source = "registry+https://github.com/rust-lang/crates.io-index"
849 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
850 | dependencies = [
851 | "proc-macro2",
852 | ]
853 |
854 | [[package]]
855 | name = "radium"
856 | version = "0.7.0"
857 | source = "registry+https://github.com/rust-lang/crates.io-index"
858 | checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
859 |
860 | [[package]]
861 | name = "rand"
862 | version = "0.8.5"
863 | source = "registry+https://github.com/rust-lang/crates.io-index"
864 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
865 | dependencies = [
866 | "libc",
867 | "rand_chacha",
868 | "rand_core",
869 | ]
870 |
871 | [[package]]
872 | name = "rand_chacha"
873 | version = "0.3.1"
874 | source = "registry+https://github.com/rust-lang/crates.io-index"
875 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
876 | dependencies = [
877 | "ppv-lite86",
878 | "rand_core",
879 | ]
880 |
881 | [[package]]
882 | name = "rand_core"
883 | version = "0.6.4"
884 | source = "registry+https://github.com/rust-lang/crates.io-index"
885 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
886 | dependencies = [
887 | "getrandom",
888 | ]
889 |
890 | [[package]]
891 | name = "redox_syscall"
892 | version = "0.3.5"
893 | source = "registry+https://github.com/rust-lang/crates.io-index"
894 | checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
895 | dependencies = [
896 | "bitflags 1.3.2",
897 | ]
898 |
899 | [[package]]
900 | name = "regex"
901 | version = "1.9.6"
902 | source = "registry+https://github.com/rust-lang/crates.io-index"
903 | checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff"
904 | dependencies = [
905 | "aho-corasick",
906 | "memchr",
907 | "regex-automata 0.3.9",
908 | "regex-syntax 0.7.5",
909 | ]
910 |
911 | [[package]]
912 | name = "regex-automata"
913 | version = "0.1.10"
914 | source = "registry+https://github.com/rust-lang/crates.io-index"
915 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
916 | dependencies = [
917 | "regex-syntax 0.6.29",
918 | ]
919 |
920 | [[package]]
921 | name = "regex-automata"
922 | version = "0.3.9"
923 | source = "registry+https://github.com/rust-lang/crates.io-index"
924 | checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9"
925 | dependencies = [
926 | "aho-corasick",
927 | "memchr",
928 | "regex-syntax 0.7.5",
929 | ]
930 |
931 | [[package]]
932 | name = "regex-syntax"
933 | version = "0.6.29"
934 | source = "registry+https://github.com/rust-lang/crates.io-index"
935 | checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
936 |
937 | [[package]]
938 | name = "regex-syntax"
939 | version = "0.7.5"
940 | source = "registry+https://github.com/rust-lang/crates.io-index"
941 | checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
942 |
943 | [[package]]
944 | name = "relative-path"
945 | version = "1.9.0"
946 | source = "registry+https://github.com/rust-lang/crates.io-index"
947 | checksum = "c707298afce11da2efef2f600116fa93ffa7a032b5d7b628aa17711ec81383ca"
948 |
949 | [[package]]
950 | name = "rend"
951 | version = "0.4.1"
952 | source = "registry+https://github.com/rust-lang/crates.io-index"
953 | checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd"
954 | dependencies = [
955 | "bytecheck",
956 | ]
957 |
958 | [[package]]
959 | name = "rkyv"
960 | version = "0.7.44"
961 | source = "registry+https://github.com/rust-lang/crates.io-index"
962 | checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0"
963 | dependencies = [
964 | "bitvec",
965 | "bytecheck",
966 | "bytes",
967 | "hashbrown 0.12.3",
968 | "ptr_meta",
969 | "rend",
970 | "rkyv_derive",
971 | "seahash",
972 | "tinyvec",
973 | "uuid",
974 | ]
975 |
976 | [[package]]
977 | name = "rkyv_derive"
978 | version = "0.7.44"
979 | source = "registry+https://github.com/rust-lang/crates.io-index"
980 | checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65"
981 | dependencies = [
982 | "proc-macro2",
983 | "quote",
984 | "syn 1.0.109",
985 | ]
986 |
987 | [[package]]
988 | name = "rustc-demangle"
989 | version = "0.1.23"
990 | source = "registry+https://github.com/rust-lang/crates.io-index"
991 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
992 |
993 | [[package]]
994 | name = "rustc-hash"
995 | version = "1.1.0"
996 | source = "registry+https://github.com/rust-lang/crates.io-index"
997 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
998 |
999 | [[package]]
1000 | name = "rustc_version"
1001 | version = "0.2.3"
1002 | source = "registry+https://github.com/rust-lang/crates.io-index"
1003 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
1004 | dependencies = [
1005 | "semver 0.9.0",
1006 | ]
1007 |
1008 | [[package]]
1009 | name = "rustix"
1010 | version = "0.38.15"
1011 | source = "registry+https://github.com/rust-lang/crates.io-index"
1012 | checksum = "d2f9da0cbd88f9f09e7814e388301c8414c51c62aa6ce1e4b5c551d49d96e531"
1013 | dependencies = [
1014 | "bitflags 2.6.0",
1015 | "errno",
1016 | "libc",
1017 | "linux-raw-sys",
1018 | "windows-sys",
1019 | ]
1020 |
1021 | [[package]]
1022 | name = "rustversion"
1023 | version = "1.0.14"
1024 | source = "registry+https://github.com/rust-lang/crates.io-index"
1025 | checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
1026 |
1027 | [[package]]
1028 | name = "ryu"
1029 | version = "1.0.15"
1030 | source = "registry+https://github.com/rust-lang/crates.io-index"
1031 | checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
1032 |
1033 | [[package]]
1034 | name = "scoped-tls"
1035 | version = "1.0.1"
1036 | source = "registry+https://github.com/rust-lang/crates.io-index"
1037 | checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
1038 |
1039 | [[package]]
1040 | name = "scopeguard"
1041 | version = "1.2.0"
1042 | source = "registry+https://github.com/rust-lang/crates.io-index"
1043 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
1044 |
1045 | [[package]]
1046 | name = "seahash"
1047 | version = "4.1.0"
1048 | source = "registry+https://github.com/rust-lang/crates.io-index"
1049 | checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
1050 |
1051 | [[package]]
1052 | name = "semver"
1053 | version = "0.9.0"
1054 | source = "registry+https://github.com/rust-lang/crates.io-index"
1055 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
1056 | dependencies = [
1057 | "semver-parser",
1058 | ]
1059 |
1060 | [[package]]
1061 | name = "semver"
1062 | version = "1.0.19"
1063 | source = "registry+https://github.com/rust-lang/crates.io-index"
1064 | checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0"
1065 | dependencies = [
1066 | "serde",
1067 | ]
1068 |
1069 | [[package]]
1070 | name = "semver-parser"
1071 | version = "0.7.0"
1072 | source = "registry+https://github.com/rust-lang/crates.io-index"
1073 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
1074 |
1075 | [[package]]
1076 | name = "serde"
1077 | version = "1.0.210"
1078 | source = "registry+https://github.com/rust-lang/crates.io-index"
1079 | checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
1080 | dependencies = [
1081 | "serde_derive",
1082 | ]
1083 |
1084 | [[package]]
1085 | name = "serde_derive"
1086 | version = "1.0.210"
1087 | source = "registry+https://github.com/rust-lang/crates.io-index"
1088 | checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
1089 | dependencies = [
1090 | "proc-macro2",
1091 | "quote",
1092 | "syn 2.0.77",
1093 | ]
1094 |
1095 | [[package]]
1096 | name = "serde_json"
1097 | version = "1.0.128"
1098 | source = "registry+https://github.com/rust-lang/crates.io-index"
1099 | checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
1100 | dependencies = [
1101 | "itoa",
1102 | "memchr",
1103 | "ryu",
1104 | "serde",
1105 | ]
1106 |
1107 | [[package]]
1108 | name = "sha2"
1109 | version = "0.10.8"
1110 | source = "registry+https://github.com/rust-lang/crates.io-index"
1111 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
1112 | dependencies = [
1113 | "cfg-if",
1114 | "cpufeatures",
1115 | "digest",
1116 | ]
1117 |
1118 | [[package]]
1119 | name = "sharded-slab"
1120 | version = "0.1.6"
1121 | source = "registry+https://github.com/rust-lang/crates.io-index"
1122 | checksum = "c1b21f559e07218024e7e9f90f96f601825397de0e25420135f7f952453fed0b"
1123 | dependencies = [
1124 | "lazy_static",
1125 | ]
1126 |
1127 | [[package]]
1128 | name = "simd-abstraction"
1129 | version = "0.7.1"
1130 | source = "registry+https://github.com/rust-lang/crates.io-index"
1131 | checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987"
1132 | dependencies = [
1133 | "outref",
1134 | ]
1135 |
1136 | [[package]]
1137 | name = "simdutf8"
1138 | version = "0.1.4"
1139 | source = "registry+https://github.com/rust-lang/crates.io-index"
1140 | checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
1141 |
1142 | [[package]]
1143 | name = "siphasher"
1144 | version = "0.3.11"
1145 | source = "registry+https://github.com/rust-lang/crates.io-index"
1146 | checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
1147 |
1148 | [[package]]
1149 | name = "smallvec"
1150 | version = "1.11.1"
1151 | source = "registry+https://github.com/rust-lang/crates.io-index"
1152 | checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
1153 |
1154 | [[package]]
1155 | name = "smartstring"
1156 | version = "1.0.1"
1157 | source = "registry+https://github.com/rust-lang/crates.io-index"
1158 | checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
1159 | dependencies = [
1160 | "autocfg",
1161 | "static_assertions",
1162 | "version_check",
1163 | ]
1164 |
1165 | [[package]]
1166 | name = "smawk"
1167 | version = "0.3.2"
1168 | source = "registry+https://github.com/rust-lang/crates.io-index"
1169 | checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
1170 |
1171 | [[package]]
1172 | name = "sourcemap"
1173 | version = "6.4.1"
1174 | source = "registry+https://github.com/rust-lang/crates.io-index"
1175 | checksum = "e4cbf65ca7dc576cf50e21f8d0712d96d4fcfd797389744b7b222a85cdf5bd90"
1176 | dependencies = [
1177 | "data-encoding",
1178 | "debugid",
1179 | "if_chain",
1180 | "rustc_version",
1181 | "serde",
1182 | "serde_json",
1183 | "unicode-id",
1184 | "url",
1185 | ]
1186 |
1187 | [[package]]
1188 | name = "sourcemap"
1189 | version = "8.0.1"
1190 | source = "registry+https://github.com/rust-lang/crates.io-index"
1191 | checksum = "208d40b9e8cad9f93613778ea295ed8f3c2b1824217c6cfc7219d3f6f45b96d4"
1192 | dependencies = [
1193 | "base64-simd",
1194 | "bitvec",
1195 | "data-encoding",
1196 | "debugid",
1197 | "if_chain",
1198 | "rustc-hash",
1199 | "rustc_version",
1200 | "serde",
1201 | "serde_json",
1202 | "unicode-id-start",
1203 | "url",
1204 | ]
1205 |
1206 | [[package]]
1207 | name = "stable_deref_trait"
1208 | version = "1.2.0"
1209 | source = "registry+https://github.com/rust-lang/crates.io-index"
1210 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
1211 |
1212 | [[package]]
1213 | name = "stacker"
1214 | version = "0.1.15"
1215 | source = "registry+https://github.com/rust-lang/crates.io-index"
1216 | checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce"
1217 | dependencies = [
1218 | "cc",
1219 | "cfg-if",
1220 | "libc",
1221 | "psm",
1222 | "winapi",
1223 | ]
1224 |
1225 | [[package]]
1226 | name = "static_assertions"
1227 | version = "1.1.0"
1228 | source = "registry+https://github.com/rust-lang/crates.io-index"
1229 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
1230 |
1231 | [[package]]
1232 | name = "string_cache"
1233 | version = "0.8.7"
1234 | source = "registry+https://github.com/rust-lang/crates.io-index"
1235 | checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
1236 | dependencies = [
1237 | "new_debug_unreachable",
1238 | "once_cell",
1239 | "parking_lot",
1240 | "phf_shared 0.10.0",
1241 | "precomputed-hash",
1242 | "serde",
1243 | ]
1244 |
1245 | [[package]]
1246 | name = "string_cache_codegen"
1247 | version = "0.5.2"
1248 | source = "registry+https://github.com/rust-lang/crates.io-index"
1249 | checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
1250 | dependencies = [
1251 | "phf_generator 0.10.0",
1252 | "phf_shared 0.10.0",
1253 | "proc-macro2",
1254 | "quote",
1255 | ]
1256 |
1257 | [[package]]
1258 | name = "string_enum"
1259 | version = "0.4.4"
1260 | source = "registry+https://github.com/rust-lang/crates.io-index"
1261 | checksum = "05e383308aebc257e7d7920224fa055c632478d92744eca77f99be8fa1545b90"
1262 | dependencies = [
1263 | "proc-macro2",
1264 | "quote",
1265 | "swc_macros_common",
1266 | "syn 2.0.77",
1267 | ]
1268 |
1269 | [[package]]
1270 | name = "supports-color"
1271 | version = "1.3.1"
1272 | source = "registry+https://github.com/rust-lang/crates.io-index"
1273 | checksum = "8ba6faf2ca7ee42fdd458f4347ae0a9bd6bcc445ad7cb57ad82b383f18870d6f"
1274 | dependencies = [
1275 | "atty",
1276 | "is_ci",
1277 | ]
1278 |
1279 | [[package]]
1280 | name = "supports-hyperlinks"
1281 | version = "1.2.0"
1282 | source = "registry+https://github.com/rust-lang/crates.io-index"
1283 | checksum = "590b34f7c5f01ecc9d78dba4b3f445f31df750a67621cf31626f3b7441ce6406"
1284 | dependencies = [
1285 | "atty",
1286 | ]
1287 |
1288 | [[package]]
1289 | name = "supports-unicode"
1290 | version = "1.0.2"
1291 | source = "registry+https://github.com/rust-lang/crates.io-index"
1292 | checksum = "a8b945e45b417b125a8ec51f1b7df2f8df7920367700d1f98aedd21e5735f8b2"
1293 | dependencies = [
1294 | "atty",
1295 | ]
1296 |
1297 | [[package]]
1298 | name = "swc_atoms"
1299 | version = "0.5.9"
1300 | source = "registry+https://github.com/rust-lang/crates.io-index"
1301 | checksum = "9f54563d7dcba626d4acfe14ed12def7ecc28e004debe3ecd2c3ee07cc47e449"
1302 | dependencies = [
1303 | "once_cell",
1304 | "rustc-hash",
1305 | "serde",
1306 | "string_cache",
1307 | "string_cache_codegen",
1308 | "triomphe",
1309 | ]
1310 |
1311 | [[package]]
1312 | name = "swc_atoms"
1313 | version = "0.6.7"
1314 | source = "registry+https://github.com/rust-lang/crates.io-index"
1315 | checksum = "bb6567e4e67485b3e7662b486f1565bdae54bd5b9d6b16b2ba1a9babb1e42125"
1316 | dependencies = [
1317 | "bytecheck",
1318 | "hstr",
1319 | "once_cell",
1320 | "rkyv",
1321 | "rustc-hash",
1322 | "serde",
1323 | ]
1324 |
1325 | [[package]]
1326 | name = "swc_common"
1327 | version = "0.32.1"
1328 | source = "registry+https://github.com/rust-lang/crates.io-index"
1329 | checksum = "9c84742fc22df1c293da5354c1cc8a5b45a045e9dc941005c1fd9cb4e9bdabc1"
1330 | dependencies = [
1331 | "ast_node",
1332 | "better_scoped_tls",
1333 | "cfg-if",
1334 | "either",
1335 | "from_variant",
1336 | "new_debug_unreachable",
1337 | "num-bigint",
1338 | "once_cell",
1339 | "rustc-hash",
1340 | "serde",
1341 | "siphasher",
1342 | "string_cache",
1343 | "swc_atoms 0.5.9",
1344 | "swc_eq_ignore_macros",
1345 | "swc_visit",
1346 | "tracing",
1347 | "unicode-width",
1348 | "url",
1349 | ]
1350 |
1351 | [[package]]
1352 | name = "swc_common"
1353 | version = "0.33.26"
1354 | source = "registry+https://github.com/rust-lang/crates.io-index"
1355 | checksum = "a2f9706038906e66f3919028f9f7a37f3ed552f1b85578e93f4468742e2da438"
1356 | dependencies = [
1357 | "anyhow",
1358 | "ast_node",
1359 | "atty",
1360 | "better_scoped_tls",
1361 | "bytecheck",
1362 | "cfg-if",
1363 | "either",
1364 | "from_variant",
1365 | "new_debug_unreachable",
1366 | "num-bigint",
1367 | "once_cell",
1368 | "parking_lot",
1369 | "rkyv",
1370 | "rustc-hash",
1371 | "serde",
1372 | "siphasher",
1373 | "sourcemap 8.0.1",
1374 | "swc_atoms 0.6.7",
1375 | "swc_eq_ignore_macros",
1376 | "swc_visit",
1377 | "termcolor",
1378 | "tracing",
1379 | "unicode-width",
1380 | "url",
1381 | ]
1382 |
1383 | [[package]]
1384 | name = "swc_core"
1385 | version = "0.90.37"
1386 | source = "registry+https://github.com/rust-lang/crates.io-index"
1387 | checksum = "ecbbbf25e5d035165bde87f2388f9fbe6d5ce38ddd2c6cb9f24084823a9c0044"
1388 | dependencies = [
1389 | "once_cell",
1390 | "swc_atoms 0.6.7",
1391 | "swc_common 0.33.26",
1392 | "swc_ecma_ast 0.112.8",
1393 | "swc_ecma_transforms_base",
1394 | "swc_ecma_transforms_testing",
1395 | "swc_ecma_visit",
1396 | "swc_plugin",
1397 | "swc_plugin_macro",
1398 | "swc_plugin_proxy",
1399 | "vergen",
1400 | ]
1401 |
1402 | [[package]]
1403 | name = "swc_ecma_ast"
1404 | version = "0.109.1"
1405 | source = "registry+https://github.com/rust-lang/crates.io-index"
1406 | checksum = "e063a1614daed3ea8be56e5dd8edb17003409088d2fc9ce4aca3378879812607"
1407 | dependencies = [
1408 | "bitflags 2.6.0",
1409 | "is-macro",
1410 | "num-bigint",
1411 | "scoped-tls",
1412 | "string_enum",
1413 | "swc_atoms 0.5.9",
1414 | "swc_common 0.32.1",
1415 | "unicode-id",
1416 | ]
1417 |
1418 | [[package]]
1419 | name = "swc_ecma_ast"
1420 | version = "0.112.8"
1421 | source = "registry+https://github.com/rust-lang/crates.io-index"
1422 | checksum = "d1d5c33c22ad50e8e34b3080a6fb133316d2eaa7d00400fc5018151f5ca44c5a"
1423 | dependencies = [
1424 | "bitflags 2.6.0",
1425 | "bytecheck",
1426 | "is-macro",
1427 | "num-bigint",
1428 | "phf",
1429 | "rkyv",
1430 | "scoped-tls",
1431 | "string_enum",
1432 | "swc_atoms 0.6.7",
1433 | "swc_common 0.33.26",
1434 | "unicode-id-start",
1435 | ]
1436 |
1437 | [[package]]
1438 | name = "swc_ecma_codegen"
1439 | version = "0.145.5"
1440 | source = "registry+https://github.com/rust-lang/crates.io-index"
1441 | checksum = "547ed57b827ea4df3e2c27cea153482f8b2ce2d271ae30c456fbb2d5a5ecc19d"
1442 | dependencies = [
1443 | "memchr",
1444 | "num-bigint",
1445 | "once_cell",
1446 | "rustc-hash",
1447 | "serde",
1448 | "sourcemap 6.4.1",
1449 | "swc_atoms 0.5.9",
1450 | "swc_common 0.32.1",
1451 | "swc_ecma_ast 0.109.1",
1452 | "swc_ecma_codegen_macros",
1453 | "tracing",
1454 | ]
1455 |
1456 | [[package]]
1457 | name = "swc_ecma_codegen"
1458 | version = "0.148.18"
1459 | source = "registry+https://github.com/rust-lang/crates.io-index"
1460 | checksum = "154d03dc43e4033b668bc5021bd67088ff27f0d8da054348b5cd4e6fe94e7f26"
1461 | dependencies = [
1462 | "memchr",
1463 | "num-bigint",
1464 | "once_cell",
1465 | "rustc-hash",
1466 | "serde",
1467 | "sourcemap 8.0.1",
1468 | "swc_atoms 0.6.7",
1469 | "swc_common 0.33.26",
1470 | "swc_ecma_ast 0.112.8",
1471 | "swc_ecma_codegen_macros",
1472 | "tracing",
1473 | ]
1474 |
1475 | [[package]]
1476 | name = "swc_ecma_codegen_macros"
1477 | version = "0.7.7"
1478 | source = "registry+https://github.com/rust-lang/crates.io-index"
1479 | checksum = "859fabde36db38634f3fad548dd5e3410c1aebba1b67a3c63e67018fa57a0bca"
1480 | dependencies = [
1481 | "proc-macro2",
1482 | "quote",
1483 | "swc_macros_common",
1484 | "syn 2.0.77",
1485 | ]
1486 |
1487 | [[package]]
1488 | name = "swc_ecma_parser"
1489 | version = "0.143.16"
1490 | source = "registry+https://github.com/rust-lang/crates.io-index"
1491 | checksum = "40b7faa481ac015b330f1c4bc8df2c9947242020e23ccdb10bc7a8ef84342509"
1492 | dependencies = [
1493 | "either",
1494 | "new_debug_unreachable",
1495 | "num-bigint",
1496 | "num-traits",
1497 | "phf",
1498 | "serde",
1499 | "smallvec",
1500 | "smartstring",
1501 | "stacker",
1502 | "swc_atoms 0.6.7",
1503 | "swc_common 0.33.26",
1504 | "swc_ecma_ast 0.112.8",
1505 | "tracing",
1506 | "typed-arena",
1507 | ]
1508 |
1509 | [[package]]
1510 | name = "swc_ecma_testing"
1511 | version = "0.22.23"
1512 | source = "registry+https://github.com/rust-lang/crates.io-index"
1513 | checksum = "dbe778ce5eae6a7e620e1f6b5326e78f00203c4548e0c659fd22da8be0538fd1"
1514 | dependencies = [
1515 | "anyhow",
1516 | "hex",
1517 | "sha2",
1518 | "testing",
1519 | "tracing",
1520 | ]
1521 |
1522 | [[package]]
1523 | name = "swc_ecma_transforms_base"
1524 | version = "0.137.21"
1525 | source = "registry+https://github.com/rust-lang/crates.io-index"
1526 | checksum = "660badfe2eed8b6213ec9dcd71aa0786f8fb46ffa012e0313bcba1fe4a9a5c73"
1527 | dependencies = [
1528 | "better_scoped_tls",
1529 | "bitflags 2.6.0",
1530 | "indexmap",
1531 | "once_cell",
1532 | "phf",
1533 | "rustc-hash",
1534 | "serde",
1535 | "smallvec",
1536 | "swc_atoms 0.6.7",
1537 | "swc_common 0.33.26",
1538 | "swc_ecma_ast 0.112.8",
1539 | "swc_ecma_parser",
1540 | "swc_ecma_utils",
1541 | "swc_ecma_visit",
1542 | "tracing",
1543 | ]
1544 |
1545 | [[package]]
1546 | name = "swc_ecma_transforms_testing"
1547 | version = "0.140.18"
1548 | source = "registry+https://github.com/rust-lang/crates.io-index"
1549 | checksum = "7c0ea6f85b7bf04391a172d7a369e49865effa77ec3a6cd0e969a274cfcb982d"
1550 | dependencies = [
1551 | "ansi_term",
1552 | "anyhow",
1553 | "base64",
1554 | "hex",
1555 | "serde",
1556 | "serde_json",
1557 | "sha2",
1558 | "sourcemap 8.0.1",
1559 | "swc_common 0.33.26",
1560 | "swc_ecma_ast 0.112.8",
1561 | "swc_ecma_codegen 0.148.18",
1562 | "swc_ecma_parser",
1563 | "swc_ecma_testing",
1564 | "swc_ecma_transforms_base",
1565 | "swc_ecma_utils",
1566 | "swc_ecma_visit",
1567 | "tempfile",
1568 | "testing",
1569 | ]
1570 |
1571 | [[package]]
1572 | name = "swc_ecma_utils"
1573 | version = "0.127.20"
1574 | source = "registry+https://github.com/rust-lang/crates.io-index"
1575 | checksum = "15d40abfc4f3a7bfdf54d11ac705cc9dd0836c48bf085b359143b4d40b50cb31"
1576 | dependencies = [
1577 | "indexmap",
1578 | "num_cpus",
1579 | "once_cell",
1580 | "rustc-hash",
1581 | "swc_atoms 0.6.7",
1582 | "swc_common 0.33.26",
1583 | "swc_ecma_ast 0.112.8",
1584 | "swc_ecma_visit",
1585 | "tracing",
1586 | "unicode-id",
1587 | ]
1588 |
1589 | [[package]]
1590 | name = "swc_ecma_visit"
1591 | version = "0.98.7"
1592 | source = "registry+https://github.com/rust-lang/crates.io-index"
1593 | checksum = "93692bdcdbb63db8f5e10fea5d202b5487cb27eb443aec424f4335c88f9864af"
1594 | dependencies = [
1595 | "num-bigint",
1596 | "swc_atoms 0.6.7",
1597 | "swc_common 0.33.26",
1598 | "swc_ecma_ast 0.112.8",
1599 | "swc_visit",
1600 | "tracing",
1601 | ]
1602 |
1603 | [[package]]
1604 | name = "swc_eq_ignore_macros"
1605 | version = "0.1.4"
1606 | source = "registry+https://github.com/rust-lang/crates.io-index"
1607 | checksum = "63db0adcff29d220c3d151c5b25c0eabe7e32dd936212b84cdaa1392e3130497"
1608 | dependencies = [
1609 | "proc-macro2",
1610 | "quote",
1611 | "syn 2.0.77",
1612 | ]
1613 |
1614 | [[package]]
1615 | name = "swc_error_reporters"
1616 | version = "0.17.20"
1617 | source = "registry+https://github.com/rust-lang/crates.io-index"
1618 | checksum = "72100a5f7b0c178adf7bcc5e7c8ad9d4180f499a5f5bae9faf3f417c7cbc4915"
1619 | dependencies = [
1620 | "anyhow",
1621 | "miette",
1622 | "once_cell",
1623 | "parking_lot",
1624 | "swc_common 0.33.26",
1625 | ]
1626 |
1627 | [[package]]
1628 | name = "swc_macros_common"
1629 | version = "0.3.13"
1630 | source = "registry+https://github.com/rust-lang/crates.io-index"
1631 | checksum = "f486687bfb7b5c560868f69ed2d458b880cebc9babebcb67e49f31b55c5bf847"
1632 | dependencies = [
1633 | "proc-macro2",
1634 | "quote",
1635 | "syn 2.0.77",
1636 | ]
1637 |
1638 | [[package]]
1639 | name = "swc_plugin"
1640 | version = "0.90.0"
1641 | source = "registry+https://github.com/rust-lang/crates.io-index"
1642 | checksum = "ca5df720531bfbd7ceb1139319c39c20c446abfb8f7e0eb47b104205a71152b4"
1643 | dependencies = [
1644 | "once_cell",
1645 | ]
1646 |
1647 | [[package]]
1648 | name = "swc_plugin_macro"
1649 | version = "0.9.16"
1650 | source = "registry+https://github.com/rust-lang/crates.io-index"
1651 | checksum = "3232db481484070637b20a155c064096c0ea1ba04fa2247b89b618661b3574f4"
1652 | dependencies = [
1653 | "proc-macro2",
1654 | "quote",
1655 | "syn 2.0.77",
1656 | ]
1657 |
1658 | [[package]]
1659 | name = "swc_plugin_proxy"
1660 | version = "0.41.7"
1661 | source = "registry+https://github.com/rust-lang/crates.io-index"
1662 | checksum = "7e09ebf5da9eb13f431ebfb916cd3378a87ffae927ba896261ebc9dc094457ae"
1663 | dependencies = [
1664 | "better_scoped_tls",
1665 | "rkyv",
1666 | "swc_common 0.33.26",
1667 | "swc_ecma_ast 0.112.8",
1668 | "swc_trace_macro",
1669 | "tracing",
1670 | ]
1671 |
1672 | [[package]]
1673 | name = "swc_trace_macro"
1674 | version = "0.1.3"
1675 | source = "registry+https://github.com/rust-lang/crates.io-index"
1676 | checksum = "ff9719b6085dd2824fd61938a881937be14b08f95e2d27c64c825a9f65e052ba"
1677 | dependencies = [
1678 | "proc-macro2",
1679 | "quote",
1680 | "syn 2.0.77",
1681 | ]
1682 |
1683 | [[package]]
1684 | name = "swc_visit"
1685 | version = "0.5.14"
1686 | source = "registry+https://github.com/rust-lang/crates.io-index"
1687 | checksum = "043d11fe683dcb934583ead49405c0896a5af5face522e4682c16971ef7871b9"
1688 | dependencies = [
1689 | "either",
1690 | "swc_visit_macros",
1691 | ]
1692 |
1693 | [[package]]
1694 | name = "swc_visit_macros"
1695 | version = "0.5.13"
1696 | source = "registry+https://github.com/rust-lang/crates.io-index"
1697 | checksum = "92807d840959f39c60ce8a774a3f83e8193c658068e6d270dbe0a05e40e90b41"
1698 | dependencies = [
1699 | "Inflector",
1700 | "proc-macro2",
1701 | "quote",
1702 | "swc_macros_common",
1703 | "syn 2.0.77",
1704 | ]
1705 |
1706 | [[package]]
1707 | name = "syn"
1708 | version = "1.0.109"
1709 | source = "registry+https://github.com/rust-lang/crates.io-index"
1710 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
1711 | dependencies = [
1712 | "proc-macro2",
1713 | "quote",
1714 | "unicode-ident",
1715 | ]
1716 |
1717 | [[package]]
1718 | name = "syn"
1719 | version = "2.0.77"
1720 | source = "registry+https://github.com/rust-lang/crates.io-index"
1721 | checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
1722 | dependencies = [
1723 | "proc-macro2",
1724 | "quote",
1725 | "unicode-ident",
1726 | ]
1727 |
1728 | [[package]]
1729 | name = "tap"
1730 | version = "1.0.1"
1731 | source = "registry+https://github.com/rust-lang/crates.io-index"
1732 | checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
1733 |
1734 | [[package]]
1735 | name = "tempfile"
1736 | version = "3.8.0"
1737 | source = "registry+https://github.com/rust-lang/crates.io-index"
1738 | checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
1739 | dependencies = [
1740 | "cfg-if",
1741 | "fastrand",
1742 | "redox_syscall",
1743 | "rustix",
1744 | "windows-sys",
1745 | ]
1746 |
1747 | [[package]]
1748 | name = "termcolor"
1749 | version = "1.3.0"
1750 | source = "registry+https://github.com/rust-lang/crates.io-index"
1751 | checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64"
1752 | dependencies = [
1753 | "winapi-util",
1754 | ]
1755 |
1756 | [[package]]
1757 | name = "terminal_size"
1758 | version = "0.1.17"
1759 | source = "registry+https://github.com/rust-lang/crates.io-index"
1760 | checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
1761 | dependencies = [
1762 | "libc",
1763 | "winapi",
1764 | ]
1765 |
1766 | [[package]]
1767 | name = "testing"
1768 | version = "0.35.25"
1769 | source = "registry+https://github.com/rust-lang/crates.io-index"
1770 | checksum = "15028f8ec7f95006f4e00e6c5ab6620f322bc6dc208a6cba09afa36375981cec"
1771 | dependencies = [
1772 | "ansi_term",
1773 | "cargo_metadata 0.15.4",
1774 | "difference",
1775 | "once_cell",
1776 | "pretty_assertions",
1777 | "regex",
1778 | "serde",
1779 | "serde_json",
1780 | "swc_common 0.33.26",
1781 | "swc_error_reporters",
1782 | "testing_macros",
1783 | "tracing",
1784 | "tracing-subscriber",
1785 | ]
1786 |
1787 | [[package]]
1788 | name = "testing_macros"
1789 | version = "0.2.14"
1790 | source = "registry+https://github.com/rust-lang/crates.io-index"
1791 | checksum = "a39660370116afe46d5ff8bcb01b7afe2140dda3137ef5cb1914681e37a4ee06"
1792 | dependencies = [
1793 | "anyhow",
1794 | "glob",
1795 | "once_cell",
1796 | "proc-macro2",
1797 | "quote",
1798 | "regex",
1799 | "relative-path",
1800 | "syn 2.0.77",
1801 | ]
1802 |
1803 | [[package]]
1804 | name = "textwrap"
1805 | version = "0.15.2"
1806 | source = "registry+https://github.com/rust-lang/crates.io-index"
1807 | checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d"
1808 | dependencies = [
1809 | "smawk",
1810 | "unicode-linebreak",
1811 | "unicode-width",
1812 | ]
1813 |
1814 | [[package]]
1815 | name = "thiserror"
1816 | version = "1.0.49"
1817 | source = "registry+https://github.com/rust-lang/crates.io-index"
1818 | checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4"
1819 | dependencies = [
1820 | "thiserror-impl",
1821 | ]
1822 |
1823 | [[package]]
1824 | name = "thiserror-impl"
1825 | version = "1.0.49"
1826 | source = "registry+https://github.com/rust-lang/crates.io-index"
1827 | checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc"
1828 | dependencies = [
1829 | "proc-macro2",
1830 | "quote",
1831 | "syn 2.0.77",
1832 | ]
1833 |
1834 | [[package]]
1835 | name = "thread_local"
1836 | version = "1.1.7"
1837 | source = "registry+https://github.com/rust-lang/crates.io-index"
1838 | checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
1839 | dependencies = [
1840 | "cfg-if",
1841 | "once_cell",
1842 | ]
1843 |
1844 | [[package]]
1845 | name = "tinyvec"
1846 | version = "1.6.0"
1847 | source = "registry+https://github.com/rust-lang/crates.io-index"
1848 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
1849 | dependencies = [
1850 | "tinyvec_macros",
1851 | ]
1852 |
1853 | [[package]]
1854 | name = "tinyvec_macros"
1855 | version = "0.1.1"
1856 | source = "registry+https://github.com/rust-lang/crates.io-index"
1857 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
1858 |
1859 | [[package]]
1860 | name = "tracing"
1861 | version = "0.1.40"
1862 | source = "registry+https://github.com/rust-lang/crates.io-index"
1863 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
1864 | dependencies = [
1865 | "pin-project-lite",
1866 | "tracing-attributes",
1867 | "tracing-core",
1868 | ]
1869 |
1870 | [[package]]
1871 | name = "tracing-attributes"
1872 | version = "0.1.27"
1873 | source = "registry+https://github.com/rust-lang/crates.io-index"
1874 | checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
1875 | dependencies = [
1876 | "proc-macro2",
1877 | "quote",
1878 | "syn 2.0.77",
1879 | ]
1880 |
1881 | [[package]]
1882 | name = "tracing-core"
1883 | version = "0.1.32"
1884 | source = "registry+https://github.com/rust-lang/crates.io-index"
1885 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
1886 | dependencies = [
1887 | "once_cell",
1888 | "valuable",
1889 | ]
1890 |
1891 | [[package]]
1892 | name = "tracing-log"
1893 | version = "0.2.0"
1894 | source = "registry+https://github.com/rust-lang/crates.io-index"
1895 | checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
1896 | dependencies = [
1897 | "log",
1898 | "once_cell",
1899 | "tracing-core",
1900 | ]
1901 |
1902 | [[package]]
1903 | name = "tracing-subscriber"
1904 | version = "0.3.18"
1905 | source = "registry+https://github.com/rust-lang/crates.io-index"
1906 | checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
1907 | dependencies = [
1908 | "matchers",
1909 | "nu-ansi-term",
1910 | "once_cell",
1911 | "regex",
1912 | "sharded-slab",
1913 | "smallvec",
1914 | "thread_local",
1915 | "tracing",
1916 | "tracing-core",
1917 | "tracing-log",
1918 | ]
1919 |
1920 | [[package]]
1921 | name = "triomphe"
1922 | version = "0.1.13"
1923 | source = "registry+https://github.com/rust-lang/crates.io-index"
1924 | checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369"
1925 | dependencies = [
1926 | "serde",
1927 | "stable_deref_trait",
1928 | ]
1929 |
1930 | [[package]]
1931 | name = "typed-arena"
1932 | version = "2.0.2"
1933 | source = "registry+https://github.com/rust-lang/crates.io-index"
1934 | checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
1935 |
1936 | [[package]]
1937 | name = "typenum"
1938 | version = "1.17.0"
1939 | source = "registry+https://github.com/rust-lang/crates.io-index"
1940 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
1941 |
1942 | [[package]]
1943 | name = "typewind-swc"
1944 | version = "0.1.0"
1945 | dependencies = [
1946 | "serde",
1947 | "serde_json",
1948 | "swc_core",
1949 | "swc_ecma_codegen 0.145.5",
1950 | ]
1951 |
1952 | [[package]]
1953 | name = "unicode-bidi"
1954 | version = "0.3.13"
1955 | source = "registry+https://github.com/rust-lang/crates.io-index"
1956 | checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
1957 |
1958 | [[package]]
1959 | name = "unicode-id"
1960 | version = "0.3.4"
1961 | source = "registry+https://github.com/rust-lang/crates.io-index"
1962 | checksum = "b1b6def86329695390197b82c1e244a54a131ceb66c996f2088a3876e2ae083f"
1963 |
1964 | [[package]]
1965 | name = "unicode-id-start"
1966 | version = "1.2.0"
1967 | source = "registry+https://github.com/rust-lang/crates.io-index"
1968 | checksum = "bc3882f69607a2ac8cc4de3ee7993d8f68bb06f2974271195065b3bd07f2edea"
1969 |
1970 | [[package]]
1971 | name = "unicode-ident"
1972 | version = "1.0.12"
1973 | source = "registry+https://github.com/rust-lang/crates.io-index"
1974 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
1975 |
1976 | [[package]]
1977 | name = "unicode-linebreak"
1978 | version = "0.1.5"
1979 | source = "registry+https://github.com/rust-lang/crates.io-index"
1980 | checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
1981 |
1982 | [[package]]
1983 | name = "unicode-normalization"
1984 | version = "0.1.22"
1985 | source = "registry+https://github.com/rust-lang/crates.io-index"
1986 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
1987 | dependencies = [
1988 | "tinyvec",
1989 | ]
1990 |
1991 | [[package]]
1992 | name = "unicode-width"
1993 | version = "0.1.11"
1994 | source = "registry+https://github.com/rust-lang/crates.io-index"
1995 | checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
1996 |
1997 | [[package]]
1998 | name = "url"
1999 | version = "2.4.1"
2000 | source = "registry+https://github.com/rust-lang/crates.io-index"
2001 | checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
2002 | dependencies = [
2003 | "form_urlencoded",
2004 | "idna",
2005 | "percent-encoding",
2006 | ]
2007 |
2008 | [[package]]
2009 | name = "uuid"
2010 | version = "1.4.1"
2011 | source = "registry+https://github.com/rust-lang/crates.io-index"
2012 | checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
2013 |
2014 | [[package]]
2015 | name = "valuable"
2016 | version = "0.1.0"
2017 | source = "registry+https://github.com/rust-lang/crates.io-index"
2018 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
2019 |
2020 | [[package]]
2021 | name = "vergen"
2022 | version = "8.3.2"
2023 | source = "registry+https://github.com/rust-lang/crates.io-index"
2024 | checksum = "2990d9ea5967266ea0ccf413a4aa5c42a93dbcfda9cb49a97de6931726b12566"
2025 | dependencies = [
2026 | "anyhow",
2027 | "cargo_metadata 0.18.1",
2028 | "regex",
2029 | "rustversion",
2030 | ]
2031 |
2032 | [[package]]
2033 | name = "version_check"
2034 | version = "0.9.4"
2035 | source = "registry+https://github.com/rust-lang/crates.io-index"
2036 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
2037 |
2038 | [[package]]
2039 | name = "wasi"
2040 | version = "0.11.0+wasi-snapshot-preview1"
2041 | source = "registry+https://github.com/rust-lang/crates.io-index"
2042 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
2043 |
2044 | [[package]]
2045 | name = "winapi"
2046 | version = "0.3.9"
2047 | source = "registry+https://github.com/rust-lang/crates.io-index"
2048 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
2049 | dependencies = [
2050 | "winapi-i686-pc-windows-gnu",
2051 | "winapi-x86_64-pc-windows-gnu",
2052 | ]
2053 |
2054 | [[package]]
2055 | name = "winapi-i686-pc-windows-gnu"
2056 | version = "0.4.0"
2057 | source = "registry+https://github.com/rust-lang/crates.io-index"
2058 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
2059 |
2060 | [[package]]
2061 | name = "winapi-util"
2062 | version = "0.1.6"
2063 | source = "registry+https://github.com/rust-lang/crates.io-index"
2064 | checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
2065 | dependencies = [
2066 | "winapi",
2067 | ]
2068 |
2069 | [[package]]
2070 | name = "winapi-x86_64-pc-windows-gnu"
2071 | version = "0.4.0"
2072 | source = "registry+https://github.com/rust-lang/crates.io-index"
2073 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
2074 |
2075 | [[package]]
2076 | name = "windows-sys"
2077 | version = "0.48.0"
2078 | source = "registry+https://github.com/rust-lang/crates.io-index"
2079 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
2080 | dependencies = [
2081 | "windows-targets",
2082 | ]
2083 |
2084 | [[package]]
2085 | name = "windows-targets"
2086 | version = "0.48.5"
2087 | source = "registry+https://github.com/rust-lang/crates.io-index"
2088 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
2089 | dependencies = [
2090 | "windows_aarch64_gnullvm",
2091 | "windows_aarch64_msvc",
2092 | "windows_i686_gnu",
2093 | "windows_i686_msvc",
2094 | "windows_x86_64_gnu",
2095 | "windows_x86_64_gnullvm",
2096 | "windows_x86_64_msvc",
2097 | ]
2098 |
2099 | [[package]]
2100 | name = "windows_aarch64_gnullvm"
2101 | version = "0.48.5"
2102 | source = "registry+https://github.com/rust-lang/crates.io-index"
2103 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
2104 |
2105 | [[package]]
2106 | name = "windows_aarch64_msvc"
2107 | version = "0.48.5"
2108 | source = "registry+https://github.com/rust-lang/crates.io-index"
2109 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
2110 |
2111 | [[package]]
2112 | name = "windows_i686_gnu"
2113 | version = "0.48.5"
2114 | source = "registry+https://github.com/rust-lang/crates.io-index"
2115 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
2116 |
2117 | [[package]]
2118 | name = "windows_i686_msvc"
2119 | version = "0.48.5"
2120 | source = "registry+https://github.com/rust-lang/crates.io-index"
2121 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
2122 |
2123 | [[package]]
2124 | name = "windows_x86_64_gnu"
2125 | version = "0.48.5"
2126 | source = "registry+https://github.com/rust-lang/crates.io-index"
2127 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
2128 |
2129 | [[package]]
2130 | name = "windows_x86_64_gnullvm"
2131 | version = "0.48.5"
2132 | source = "registry+https://github.com/rust-lang/crates.io-index"
2133 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
2134 |
2135 | [[package]]
2136 | name = "windows_x86_64_msvc"
2137 | version = "0.48.5"
2138 | source = "registry+https://github.com/rust-lang/crates.io-index"
2139 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
2140 |
2141 | [[package]]
2142 | name = "wyz"
2143 | version = "0.5.1"
2144 | source = "registry+https://github.com/rust-lang/crates.io-index"
2145 | checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
2146 | dependencies = [
2147 | "tap",
2148 | ]
2149 |
2150 | [[package]]
2151 | name = "yansi"
2152 | version = "0.5.1"
2153 | source = "registry+https://github.com/rust-lang/crates.io-index"
2154 | checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
2155 |
--------------------------------------------------------------------------------
/packages/typewind/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "typewind-swc"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [lib]
7 | crate-type = ["cdylib"]
8 | path = "swc/lib.rs"
9 |
10 | [profile.release]
11 | lto = true
12 |
13 | [dependencies]
14 | serde = "1"
15 | serde_json = "1.0.93"
16 | swc_core = { version = "0.90.35", features = ["ecma_plugin_transform"] }
17 | swc_ecma_codegen = "0.145.5"
18 |
19 | # .cargo/config defines few alias to build plugin.
20 | # cargo build-wasi generates wasm-wasi32 binary
21 | # cargo build-wasm32 generates wasm32-unknown-unknown binary.
22 |
--------------------------------------------------------------------------------
/packages/typewind/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The safety of Typescript with the magic of Tailwind.
5 |
6 |
7 | ---
8 |
9 | ## Introduction
10 |
11 | Typewind brings the safety, productivity and intellisense of Typescript over to Tailwind
12 |
13 | ```js
14 | import { tw } from 'typewind';
15 |
16 | const styles = tw.border.hover(tw.border_black);
17 | ```
18 |
19 | ## How it works
20 |
21 | Typewind's compiler is a babel plugin that runs over your code, statically analyses it and converts all the `tw` styles into their corresponding Tailwind classes.
22 |
23 | This results Typewind compiles away, leaving 0 runtime code.
24 |
25 | ```js
26 | import { tw } from 'typewind';
27 |
28 | const styles = tw.border.hover(tw.border_black);
29 |
30 | // ↓ ↓ ↓ ↓ ↓ ↓
31 |
32 | const styles = 'border hover:border-black';
33 | ```
34 |
35 | ## Features
36 |
37 | **Zero bundle size** - Typewind compiles away all the styles used, and converts them to static classes at build
38 |
39 | **Apply variants to multiple styles at once** - Since Typewind uses TS, it allows for more intuitive syntax for applying variants
40 |
41 | ```js
42 | import { tw } from 'typewind';
43 |
44 | const mediaStyles = tw.sm(tw.w_4.mt_3).lg(tw.w_8.mt_6);
45 | const groupInGroups = tw.text_sm.sm(tw.bg_black.hover(tw.bg_white.w_10));
46 | ```
47 |
48 | **Type safety and intellisense** - Using the TS compiler, Typewind is able to provide type safety to tailwind, and provide intellisense & autocomplete for all the classes from tailwind config.
49 |
50 | ```js
51 | import { tw } from 'typewind';
52 |
53 | const styles = tw.border_blackk; // ❌ Property 'border_blackk' does not exist on type 'Typewind'. Did you mean 'border_black'?
54 | ```
55 |
56 | The above code would also return in a build error on running `tsc`
57 |
58 | **Types generated from config** - Type definitions of `tw` are generated directly from your tailwind config, so it is always custom to you, and also creates types for custom theme palette and plugins.
59 |
--------------------------------------------------------------------------------
/packages/typewind/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "typewind",
3 | "version": "0.2.0",
4 | "description": "The safety of Typescript with the magic of Tailwind.",
5 | "types": "dist/index.d.ts",
6 | "main": "dist/index.js",
7 | "homepage": "https://typewind.dev",
8 | "scripts": {
9 | "build": "npm run build:tsup && npm run build:cargo",
10 | "build:tsup": "tsup",
11 | "watch": "npm run build -- --watch",
12 | "release": "release-it",
13 | "build:cargo": "cargo build-wasi --release && cp target/wasm32-wasi/release/typewind_swc.wasm dist"
14 | },
15 | "repository": {
16 | "type": "git",
17 | "url": "https://github.com/mokshit06/typewind.git",
18 | "directory": "packages/typewind"
19 | },
20 | "bin": {
21 | "typewind": "dist/cli.js"
22 | },
23 | "exports": {
24 | ".": {
25 | "types": "./dist/index.d.ts",
26 | "require": "./dist/index.js",
27 | "import": "./dist/index.mjs"
28 | },
29 | "./cn": {
30 | "types": "./dist/cn.d.ts",
31 | "require": "./dist/cn.js",
32 | "import": "./dist/cn.mjs"
33 | },
34 | "./dist/*": "./dist/*",
35 | "./babel": {
36 | "types": "./dist/babel.d.ts",
37 | "default": "./dist/babel.js"
38 | },
39 | "./transform": {
40 | "types": "./dist/transform.d.ts",
41 | "default": "./dist/transform.js"
42 | },
43 | "./swc": "./dist/typewind_swc.wasm"
44 | },
45 | "keywords": [
46 | "typescript",
47 | "tailwind",
48 | "tailwindcss",
49 | "babel-plugin",
50 | "zero-runtime"
51 | ],
52 | "author": "",
53 | "license": "MIT",
54 | "dependencies": {
55 | "@babel/core": "^7.20.12",
56 | "@babel/generator": "^7.20.14",
57 | "@babel/plugin-syntax-jsx": "^7.18.6",
58 | "@babel/preset-typescript": "^7.18.6",
59 | "clsx": "^2.1.1",
60 | "eval": "^0.1.8",
61 | "lightningcss": "^1.19.0",
62 | "tailwind-merge": "^2.3.0",
63 | "tsup": "^8.2.4"
64 | },
65 | "devDependencies": {
66 | "@types/babel__core": "^7.20.0",
67 | "release-it": "^15.6.0"
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/packages/typewind/rust-toolchain:
--------------------------------------------------------------------------------
1 | 1.80.0
2 |
--------------------------------------------------------------------------------
/packages/typewind/src/babel.ts:
--------------------------------------------------------------------------------
1 | import { NodePath, PluginObj, PluginPass, types as t } from '@babel/core';
2 | import _eval from 'eval';
3 | import { createTypewindContext } from './utils';
4 | import generator from '@babel/generator';
5 |
6 | export default function headingBabelPlugin(): PluginObj<
7 | PluginPass & { classes: string[] }
8 | > {
9 | const nodesReplaced = new Set();
10 |
11 | return {
12 | name: 'typewind',
13 | pre(state) {
14 | this.classes ??= [];
15 | },
16 | visitor: {
17 | MemberExpression(path, state) {
18 | if (
19 | !t.isIdentifier(path.node.object) ||
20 | path.node.object.name !== 'tw'
21 | // !t.isIdentifier(path.node.property)
22 | )
23 | return;
24 |
25 | let curPath = path as NodePath;
26 | let prevPath: NodePath = undefined!;
27 |
28 | while (
29 | curPath &&
30 | (t.isMemberExpression(curPath.node) ||
31 | (t.isCallExpression(curPath.node) &&
32 | (prevPath == undefined || prevPath.node == curPath.node.callee)))
33 | ) {
34 | prevPath = curPath!;
35 | curPath = curPath.parentPath!;
36 | }
37 |
38 | const code: string = generator(prevPath.node).code;
39 |
40 | const { result } = _eval(
41 | `
42 | const { createTw } = require("typewind/dist/evaluate.js");
43 | const tw = createTw();
44 | try {
45 | let result$$ = ${code};
46 | if (typeof result$$ === 'function' || typeof result$$ === "undefined") {
47 | throw new Error()
48 | } else {
49 | exports.result = result$$.toString();
50 | }
51 | } catch (error) {
52 | throw new Error(\`Error in evaluating typewind expression: ${code.replace(
53 | '`',
54 | '\\`'
55 | )}. \${error}\`)
56 | }
57 | `,
58 | true
59 | ) as { result: string };
60 |
61 | if (prevPath.node && !t.isStringLiteral(prevPath.node)) {
62 | nodesReplaced.add(prevPath.node);
63 | // ignore this 👍
64 | try {
65 | prevPath.replaceWith(t.stringLiteral(result));
66 | } catch {}
67 | }
68 | },
69 | },
70 | };
71 | }
72 |
--------------------------------------------------------------------------------
/packages/typewind/src/cli.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | import fs from 'fs';
4 | import path from 'path';
5 | import { transform } from 'lightningcss';
6 | import { createTypewindContext, loadConfig } from './utils';
7 |
8 | function createDoc(doc: string) {
9 | try {
10 | let cssDoc = `
11 | * \`\`\`css
12 | * ${transform({
13 | filename: 'doc.css',
14 | code: Buffer.from(doc),
15 | })
16 | .code.toString()
17 | .replace(/\n/g, '\n * ')}
18 | * \`\`\`
19 | `;
20 | const config = loadConfig();
21 | if (config.showPixelEquivalents) {
22 | const remMatch = doc.match(/-?[0-9.]+rem/g);
23 | const pxValue = config.rootFontSize;
24 | if (remMatch) {
25 | cssDoc = cssDoc.replace(
26 | /(-?[0-9.]+)rem/g,
27 | // There is a zero-width space between * and / in the closing comment
28 | // without which typescript closes the tsdoc comment
29 | (match, p1) => `${match} /* ${parseFloat(p1) * pxValue}px */`
30 | );
31 | }
32 | }
33 | return cssDoc;
34 | } catch (error) {
35 | return doc;
36 | }
37 | }
38 |
39 | const fmtToTypewind = (s: string) => s.replace(/-/g, '_').replace(/^\@/, '$');
40 |
41 | const objectTemplate = (
42 | props: { prop: string; type: string; doc?: string }[]
43 | ) => {
44 | return `{${props
45 | .map(
46 | ({ prop, type, doc }) =>
47 | `/** ${doc ? createDoc(doc) : ''} */ ${JSON.stringify(prop)}: ${type};`
48 | )
49 | .join('\n')}}`;
50 | };
51 |
52 | const typeTemplate = (
53 | name: string,
54 | props: { prop: string; type: string; doc?: string }[]
55 | ) => `
56 | type ${name} = ${objectTemplate(props)}
57 | `;
58 |
59 | const rootTypeTemplate = ({
60 | others,
61 | types,
62 | modifiers,
63 | colors,
64 | }: {
65 | others: string[];
66 | types: string[];
67 | modifiers: string[];
68 | colors: string[];
69 | }) =>
70 | `type Property = Typewind & string;
71 |
72 | ${others.join('\n')}
73 |
74 | type OpacityMap = {
75 | [K in Opacity]: Property;
76 | } & Record;
77 | type Colors = {
78 | ${colors.map((color) => `${color}: OpacityMap`).join(';\n')}
79 | }
80 |
81 | type Typewind = ${types.join(' & ')} & {
82 | ${modifiers
83 | .map((variant) => `${variant}(style: Property): Property`)
84 | .join(';\n')}
85 | } & {
86 | // [arbitraryVariant: string]: (style: Property) => Property;
87 | } & {
88 | variant(variant: T, style: Property | string): Property;
89 | raw(style: string): Property;
90 | }
91 |
92 | declare const tw: Typewind;
93 |
94 | export { tw };
95 | `;
96 |
97 | function getCandidateItem(
98 | map: Map,
99 | name: string,
100 | rest: string | undefined = undefined
101 | ): { rule: any; rest: string | undefined } {
102 | let rule = map.get(name);
103 |
104 | if (!rule && name.includes('-')) {
105 | const arr = name.split('-');
106 | const key = arr.slice(0, arr.length - 1).join('-');
107 | return getCandidateItem(
108 | map,
109 | key,
110 | [arr[arr.length - 1], rest].filter(Boolean).join('-')
111 | );
112 | }
113 |
114 | return { rule, rest };
115 | }
116 |
117 | export async function generateTypes() {
118 | const ctx = createTypewindContext();
119 |
120 | // only exists to generate rule-map for swc plugin
121 | // const candidateRuleMap = ctx.candidateRuleMap;
122 |
123 | // const candidateObj = Object.fromEntries(
124 | // [...candidateRuleMap.entries()]
125 | // .map(([k, rules]) => {
126 | // return [
127 | // k,
128 | // rules
129 | // .filter(
130 | // ([rule]: any) => rule.options?.values
131 | // // rule.options?.values.every1((v: any) => typeof v === 'string')
132 | // )
133 | // .map(([rule]: any) => Object.keys(rule.options?.values)),
134 | // ];
135 | // })
136 | // .filter(([k, v]) => v.length > 0)
137 | // );
138 |
139 | // fs.writeFileSync('./map.json', JSON.stringify(candidateObj));
140 |
141 | const classList = ctx.getClassList() as string[];
142 |
143 | const opacityMap = ctx.tailwindConfig.theme.opacity;
144 | const flatColorsList: string[] = [];
145 |
146 | for (const [k, v] of Object.entries(ctx.tailwindConfig.theme.colors)) {
147 | if (typeof v === 'object') {
148 | for (const col in v) {
149 | flatColorsList.push(k + '-' + col);
150 | }
151 | } else {
152 | flatColorsList.push(k);
153 | }
154 | }
155 |
156 | const classesWithStandardSyntax = classList.filter((s) => !/\.|\//.test(s));
157 | const classesWithCandidateItem = classesWithStandardSyntax.map((s) => {
158 | return [s, getCandidateItem(ctx.candidateRuleMap, s)] as const;
159 | });
160 |
161 | const colorSet = new Set();
162 | const standard = typeTemplate(
163 | 'Standard',
164 | classesWithCandidateItem.map(([s, { rule: rules, rest }]) => {
165 | let css = '';
166 |
167 | if (rules) {
168 | for (const rule of rules) {
169 | const [info, ruleOrFn] = rule;
170 |
171 | if (typeof ruleOrFn === 'function') {
172 | const types = info.options.types;
173 | const isColor = types.some(
174 | (t: Record) => t.type == 'color'
175 | );
176 |
177 | if (isColor && rest && flatColorsList.includes(rest)) {
178 | const key = fmtToTypewind(s) + '$';
179 |
180 | colorSet.add(key);
181 | }
182 |
183 | const [ruleSet] = ruleOrFn(rest ?? 'DEFAULT', {});
184 | if (ruleSet) {
185 | css += fmtRuleToCss(ruleSet);
186 | }
187 | }
188 | if (typeof ruleOrFn == 'object') {
189 | css += fmtNode(ruleOrFn) + '\n';
190 | }
191 | }
192 | }
193 |
194 | return { prop: fmtToTypewind(s), type: 'Property', doc: css };
195 | })
196 | );
197 | const candidates = [...ctx.candidateRuleMap.entries()];
198 | const arbitraryStyles = [];
199 | for (const [name, rules] of candidates) {
200 | const ident = fmtToTypewind(name) + '_';
201 | const styles: string[] = [];
202 |
203 | for (const [rule, fn] of rules) {
204 | if (
205 | !rule.options ||
206 | !rule.options.values ||
207 | Object.keys(rule.options.values).length == 0
208 | )
209 | continue;
210 |
211 | styles.push(
212 | objectTemplate(
213 | Object.keys(rule.options.values).map((val) => {
214 | const [ruleSet] = fn(val, {});
215 |
216 | return {
217 | prop: val,
218 | type: 'Property',
219 | doc: fmtRuleToCss(ruleSet),
220 | };
221 | })
222 | )
223 | );
224 | }
225 |
226 | arbitraryStyles.push({
227 | prop: ident,
228 | type: styles.join(' & ') + ' & Record',
229 | doc: undefined,
230 | });
231 | }
232 |
233 | const arbitrary = typeTemplate('Arbitrary', arbitraryStyles);
234 |
235 | const modifiers = [...ctx.variantMap.keys(), 'important']
236 | // Remove * from the list of modifiers to avoid syntax error
237 | .filter((s) => s !== '*')
238 | .map((s) => {
239 | s = /^\d/.test(s) ? `_${s}` : s;
240 |
241 | return fmtToTypewind(s);
242 | });
243 |
244 | const root = rootTypeTemplate({
245 | others: [
246 | standard,
247 | arbitrary,
248 | `type Opacity = ${Object.keys(opacityMap)
249 | .map((k) => JSON.stringify(k))
250 | .join(' | ')}`,
251 | ],
252 | types: ['Standard', 'Arbitrary', 'Colors'],
253 | modifiers,
254 | colors: [...colorSet].map((k) => JSON.stringify(k)),
255 | });
256 |
257 | fs.writeFileSync(
258 | path.join(require.resolve('typewind'), '../index.d.ts'),
259 | root,
260 | 'utf8'
261 | );
262 | }
263 |
264 | function fmtRuleset(rule: any) {
265 | return (
266 | '{' +
267 | Object.entries(rule)
268 | .map(([prop, value]): any => {
269 | if (!value) return '';
270 | if (typeof value === 'object') return `${prop} ${fmtRuleset(value)}`;
271 |
272 | return `${prop}: ${value}`;
273 | })
274 | .join(';') +
275 | '}'
276 | );
277 | }
278 |
279 | function fmtNode(node: any) {
280 | if (node.type === 'atrule') {
281 | return `\\@${node.name} ${node.params} {${node.nodes
282 | .map(fmtNode)
283 | .join('')}}`;
284 | }
285 | if (node.type === 'decl') {
286 | return `${node.prop}: ${node.value};`;
287 | }
288 | if (node.type === 'rule') {
289 | return `${node.selector} {${node.nodes.map(fmtNode).join('')}}`;
290 | }
291 | }
292 |
293 | function fmtRuleToCss(ruleSet: any) {
294 | const selector = Object.keys(ruleSet)[0];
295 | return `${selector} ${fmtRuleset(ruleSet[selector])}`;
296 | }
297 |
298 | generateTypes().catch((err) => {
299 | console.error(err);
300 | process.exit(1);
301 | });
302 |
--------------------------------------------------------------------------------
/packages/typewind/src/cn.ts:
--------------------------------------------------------------------------------
1 | import { clsx, type ClassValue } from 'clsx';
2 | import { twMerge } from 'tailwind-merge';
3 | import { typewind_id } from './runtime';
4 |
5 | export function cn(...inputs: ClassValue[]) {
6 | return twMerge(
7 | clsx(
8 | inputs.map((input) => {
9 | if (!input) return input;
10 | if (typeof input === 'function' && (input as any)[typewind_id]) {
11 | return input.toString();
12 | }
13 |
14 | return input;
15 | })
16 | )
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/packages/typewind/src/evaluate.ts:
--------------------------------------------------------------------------------
1 | import { createTypewindContext } from './utils';
2 | const ctx = createTypewindContext();
3 | const { candidateRuleMap, variantMap } = ctx;
4 |
5 | function fmtArbitraryRule(name: string, value: string, candidateRuleMap: any) {
6 | const classes = [];
7 | const rules = candidateRuleMap.get(name);
8 |
9 | if (rules) {
10 | const isKnownValue = rules.some(
11 | ([rule]: any) => value in rule.options.values
12 | );
13 |
14 | classes.push(`${name}-${isKnownValue ? value : `[${value}]`}`);
15 | }
16 |
17 | return classes.join(' ');
18 | }
19 |
20 | const fmtToTailwind = (s: string) =>
21 | s.replace(/_/g, '-').replace(/^\$/, '@').replace(/\$/, '/');
22 |
23 | export const createTw: any = () => {
24 | const twUsed = (classes = new Set()) => {
25 | const target = {
26 | classes,
27 | // prevProp is for keeping track of dynamic values
28 | // if previous acces ends with _ then its dynamic
29 | prevProp: undefined as string | undefined,
30 | // proxy can't be used as string so convert it
31 | toString() {
32 | return [...target.classes].join(' ');
33 | },
34 | };
35 |
36 | const thisTw: any = new Proxy(target, {
37 | get(target, p, recv) {
38 | // @ts-ignore
39 | // just returns the above toString method
40 | if (p === 'toString') return Reflect.get(...arguments);
41 |
42 | // remove symbols
43 | if (typeof p !== 'string') return null;
44 |
45 | // changes _ to -
46 | const name = fmtToTailwind(p);
47 |
48 | if (target.prevProp?.endsWith('-')) {
49 | target.classes.add(
50 | fmtArbitraryRule(target.prevProp.slice(0, -1), p, candidateRuleMap)
51 | );
52 | } else if (target.prevProp?.endsWith('/')) {
53 | target.classes.add(`${target.prevProp}${name}`);
54 | } else if (!name.endsWith('-') && !name.endsWith('/')) {
55 | function spreadModifier(prefix: string, chunks: any) {
56 | for (const chunk of chunks.toString().split(' ')) {
57 | target.classes.add(`${prefix}${chunk}`);
58 | }
59 |
60 | return thisTw;
61 | }
62 |
63 | if (name === 'raw') {
64 | return (style: string) => spreadModifier('', style);
65 | }
66 |
67 | if (name === 'variant') {
68 | return (modifier: string, classes: any) =>
69 | spreadModifier(`[${modifier}]:`, classes);
70 | }
71 |
72 | if (variantMap.has(name) || name === 'important') {
73 | const prefix = name === 'important' ? '!' : `${name}:`;
74 |
75 | return (arg: any) => spreadModifier(prefix, arg);
76 | }
77 |
78 | target.classes.add(name);
79 | }
80 |
81 | target.prevProp = name as string;
82 |
83 | return thisTw;
84 | },
85 | });
86 |
87 | return thisTw;
88 | };
89 |
90 | const tw = new Proxy(
91 | {},
92 | {
93 | get(_target, p) {
94 | // @ts-ignore
95 | if (typeof p !== 'string') return Reflect.get(...arguments);
96 |
97 | return twUsed()[p];
98 | },
99 | }
100 | );
101 |
102 | return tw;
103 | };
104 |
--------------------------------------------------------------------------------
/packages/typewind/src/index.ts:
--------------------------------------------------------------------------------
1 | import { createRuntimeTw } from './runtime';
2 |
3 | declare const typewind: unique symbol;
4 |
5 | // make brand/opaque type so that typescript lsp shows error as TypewindError and not Message
6 | type TypewindError = { [typewind]: T };
7 |
8 | export const tw =
9 | createRuntimeTw() as TypewindError<"Typewind's types haven't been generated. Run `npx typewind generate` or follow the docs at https://typewind.dev/docs/installation">;
10 |
--------------------------------------------------------------------------------
/packages/typewind/src/runtime.ts:
--------------------------------------------------------------------------------
1 | const fmtToTailwind = (s: string) =>
2 | s.replace(/_/g, '-').replace(/^\$/, '@').replace(/\$/, '/');
3 |
4 | type ToStringable = { toString(): string };
5 |
6 | export const typewind_id = Symbol.for('typewind_style');
7 |
8 | export function createRuntimeTw() {
9 | const twUsed = (classes = new Set()) => {
10 | // needs to be a function so it's callable
11 | const target = Object.assign(() => {}, {
12 | classes,
13 | prevProp: undefined as string | undefined,
14 | maybeVariant: undefined as string | undefined,
15 | // proxy can't be used as string so convert it
16 | [Symbol.toPrimitive]() {
17 | if (target.maybeVariant) {
18 | target.classes.add(target.maybeVariant);
19 | target.maybeVariant = undefined;
20 | }
21 |
22 | return [...target.classes].join(' ');
23 | },
24 | });
25 |
26 | function spreadModifier(prefix: string, chunks: ToStringable) {
27 | for (const chunk of chunks.toString().split(' ')) {
28 | target.classes.add(`${prefix}${chunk}`);
29 | }
30 | }
31 |
32 | const thisTw: any = new Proxy(target, {
33 | get(target, p, _recv) {
34 | if (p === typewind_id) {
35 | return true;
36 | }
37 |
38 | if (p === 'toString' || p === 'valueOf' || p === Symbol.toPrimitive) {
39 | return target[Symbol.toPrimitive];
40 | }
41 |
42 | const isStrProp = ''[p as any] !== undefined;
43 | if (isStrProp) {
44 | const prim = target[Symbol.toPrimitive]();
45 | const value = prim[p as Exclude];
46 | return typeof value === 'function' ? value.bind(prim) : value;
47 | }
48 |
49 | if (typeof p !== 'string') return null;
50 |
51 | const name = fmtToTailwind(p);
52 |
53 | if (target.prevProp?.endsWith('-')) {
54 | target.classes.add(`${target.prevProp.slice(0, -1)}-[${p}]`);
55 | } else if (target.prevProp?.endsWith('/')) {
56 | target.classes.add(`${target.prevProp}${name}`);
57 | } else if (!name.endsWith('-') && !name.endsWith('/')) {
58 | if (target.maybeVariant) {
59 | target.classes.add(target.maybeVariant);
60 | target.maybeVariant = undefined;
61 | }
62 |
63 | if (name === 'raw') {
64 | return (style: ToStringable) => {
65 | spreadModifier('', style);
66 | return thisTw;
67 | };
68 | }
69 |
70 | if (name === 'variant') {
71 | return (modifier: string, classes: ToStringable) => {
72 | spreadModifier(`[${modifier}]:`, classes);
73 | return thisTw;
74 | };
75 | }
76 |
77 | if (name === 'important') {
78 | return (style: ToStringable) => {
79 | spreadModifier('!', style);
80 | return thisTw;
81 | };
82 | }
83 |
84 | target.maybeVariant = name;
85 | }
86 |
87 | target.prevProp = name;
88 |
89 | return thisTw;
90 | },
91 | apply(target, _thisArg, [style]) {
92 | const prefix = target.maybeVariant;
93 |
94 | if (!prefix) {
95 | throw new Error(
96 | 'Typewind Error: unreachable code path, `maybeVariant` is undefined'
97 | );
98 | }
99 |
100 | target.maybeVariant = undefined;
101 |
102 | if (!style) {
103 | throw new Error(
104 | `Typewind Error: Passing a class to \`${prefix}\` is required`
105 | );
106 | }
107 |
108 | spreadModifier(`${prefix}:`, style);
109 |
110 | return thisTw;
111 | },
112 | getPrototypeOf() {
113 | return String.prototype;
114 | },
115 | });
116 |
117 | return thisTw;
118 | };
119 |
120 | const tw = new Proxy(
121 | {},
122 | {
123 | get(_target, p) {
124 | // @ts-ignore
125 | if (typeof p !== 'string') return Reflect.get(...arguments);
126 |
127 | return twUsed()[p];
128 | },
129 | }
130 | );
131 |
132 | return tw;
133 | }
134 |
--------------------------------------------------------------------------------
/packages/typewind/src/transform.ts:
--------------------------------------------------------------------------------
1 | import * as babel from '@babel/core';
2 | import { TransformerFn } from 'tailwindcss/types/config';
3 |
4 | export const transformBabel = (ext: string, content: string) => {
5 | const config: babel.TransformOptions = {
6 | filename: `typewind.${ext}`,
7 | plugins: ['typewind/babel'],
8 | };
9 | if (ext === 'ts' || ext === 'tsx') {
10 | config.presets = ['@babel/preset-typescript'];
11 | }
12 |
13 | if (ext === 'js' || ext === 'jsx') {
14 | config.plugins?.push('@babel/plugin-syntax-jsx');
15 | }
16 |
17 | const res = babel.transformSync(content, config);
18 |
19 | if (res?.code == undefined) {
20 | throw new Error('Failed to transform file');
21 | }
22 |
23 | return res.code;
24 | };
25 |
26 | export const typewindTransforms: Record = {
27 | tsx: (content) => transformBabel('tsx', content),
28 | ts: (content) => transformBabel('ts', content),
29 | jsx: (content) => transformBabel('jsx', content),
30 | js: (content) => transformBabel('js', content),
31 | };
32 |
--------------------------------------------------------------------------------
/packages/typewind/src/utils.ts:
--------------------------------------------------------------------------------
1 | import _eval from 'eval';
2 | import path from 'path';
3 | import resolveConfig from 'tailwindcss/resolveConfig.js';
4 | import { buildSync } from 'esbuild';
5 | import fs from 'fs';
6 | // @ts-ignore
7 | import { createContext } from 'tailwindcss/lib/lib/setupContextUtils.js';
8 |
9 | export function loadConfig(): {
10 | configPath: string;
11 | showPixelEquivalents: boolean;
12 | rootFontSize: number;
13 | } {
14 | const pkg = require(path.join(process.cwd(), 'package.json'));
15 |
16 | return {
17 | configPath: './tailwind.config.js',
18 | showPixelEquivalents: false,
19 | rootFontSize: 16,
20 | ...pkg?.typewind,
21 | };
22 | }
23 |
24 | function getConfigPath() {
25 | const config = loadConfig();
26 |
27 | for (const configFile of [
28 | config.configPath,
29 | './tailwind.config.ts',
30 | './tailwind.config.js',
31 | './tailwind.config.cjs',
32 | ]) {
33 | try {
34 | const configPath = path.join(process.cwd(), configFile);
35 | fs.accessSync(configPath);
36 | return configPath;
37 | } catch (err) {}
38 | }
39 |
40 | throw new Error(
41 | 'No tailwind config file found!\nIf your tailwind config file is not on the same folder, check: https://typewind.dev/docs/installation/custom-config-file-path'
42 | );
43 | }
44 |
45 | export function createTypewindContext() {
46 | const configFile = getConfigPath();
47 | let pkgJSON;
48 |
49 | try {
50 | pkgJSON = require(path.join(process.cwd(), 'package.json'));
51 | } catch {
52 | pkgJSON = {};
53 | }
54 |
55 | let config: any;
56 | if (configFile.endsWith('.ts')) {
57 | const preprocessedConfig = buildSync({
58 | entryPoints: [configFile],
59 | write: false,
60 | bundle: true,
61 | format: 'cjs',
62 | target: 'node14',
63 | platform: 'node',
64 | external: ['node_modules/*'],
65 | }).outputFiles[0].text;
66 |
67 | config = _eval(preprocessedConfig, true) as any;
68 | } else {
69 | config = require(configFile);
70 | }
71 |
72 | const userConfig = resolveConfig(config);
73 |
74 | return createContext(userConfig);
75 | }
76 |
--------------------------------------------------------------------------------
/packages/typewind/swc/lib.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 |
3 | use serde::Deserialize;
4 | use swc_core::plugin::{plugin_transform, proxies::TransformPluginProgramMetadata};
5 | use swc_core::{
6 | common::DUMMY_SP,
7 | ecma::{
8 | ast::Program,
9 | ast::*,
10 | transforms::testing::test,
11 | visit::{as_folder, FoldWith, VisitMut, VisitMutWith},
12 | },
13 | };
14 |
15 | #[derive(Deserialize)]
16 | struct CandidateValueMap(HashMap>>);
17 |
18 | impl Default for CandidateValueMap {
19 | fn default() -> Self {
20 | setup_rule_map()
21 | }
22 | }
23 |
24 | fn fmt_to_tailwind(str: &str) -> String {
25 | str.chars()
26 | .map(|c| match c {
27 | '$' => '@',
28 | '_' => '-',
29 | c => c,
30 | })
31 | .collect()
32 | }
33 |
34 | fn inner_most_is_tw(expr: &Expr) -> bool {
35 | match expr {
36 | Expr::Ident(ident) => ident.sym == *"tw",
37 | Expr::Member(member_expr) => inner_most_is_tw(&*member_expr.obj),
38 | Expr::Call(call_expr) => call_expr
39 | .callee
40 | .as_expr()
41 | .and_then(|expr| Some(inner_most_is_tw(&**expr)))
42 | .unwrap_or(false),
43 | _ => return false,
44 | }
45 | }
46 |
47 | fn analyse_expr(v: &mut TransformVisitor, wr: &mut Vec, e: &Expr) {
48 | match e {
49 | Expr::Member(member_expr) => {
50 | let style = match &member_expr.prop {
51 | MemberProp::Ident(ident) => fmt_to_tailwind(ident.sym.as_ref()),
52 | MemberProp::Computed(computed) => {
53 | match computed.expr.as_lit().expect("Only literal values allowed") {
54 | Lit::Str(str) => str.value.to_string(),
55 | _ => panic!("Only string literal values allowed"),
56 | }
57 | }
58 | _ => panic!("Private values not allowed"),
59 | };
60 |
61 | if member_expr.prop.is_computed() {
62 | v.style_queue.push_str(&style);
63 | } else if !v.style_queue.is_empty() {
64 | let maybe_arbitrary_val = v.style_queue.as_str();
65 | let without_suffix = &style[..style.len() - 1];
66 |
67 | let CandidateValueMap(rule_map) = &v.rule_map;
68 |
69 | // @ means $ here as for opacity or named container queries etc.
70 | // its being replaced to @ by the fmt_to_tailwind fn
71 | if style.ends_with("@") {
72 | wr.push(format!(
73 | "{}{}/{}",
74 | v.get_prefix(),
75 | without_suffix,
76 | maybe_arbitrary_val
77 | ));
78 | } else if let Some(rules) = rule_map.get(without_suffix) {
79 | let is_known_value = rules.iter().any(|rule| {
80 | if rule.contains(&maybe_arbitrary_val.to_string()) {
81 | true
82 | } else {
83 | false
84 | }
85 | });
86 |
87 | if is_known_value {
88 | wr.push(format!(
89 | "{}{}{}",
90 | v.get_prefix(),
91 | style,
92 | maybe_arbitrary_val
93 | ));
94 | } else {
95 | wr.push(format!(
96 | "{}{}[{}]",
97 | v.get_prefix(),
98 | style,
99 | maybe_arbitrary_val
100 | ));
101 | }
102 | }
103 |
104 | v.style_queue.clear()
105 | } else {
106 | wr.push(format!("{}{}", v.get_prefix(), style));
107 | }
108 |
109 | analyse_expr(v, wr, &*member_expr.obj)
110 | }
111 | Expr::Call(call_expr) => {
112 | let CallExpr { callee, args, .. } = call_expr;
113 |
114 | let callee_member = callee
115 | .as_expr()
116 | .expect("callee can only be expr")
117 | .as_member()
118 | .expect("only member expr allowed");
119 |
120 | analyse_expr(v, wr, &callee_member.obj);
121 |
122 | let style = fmt_to_tailwind(
123 | callee_member
124 | .prop
125 | .as_ident()
126 | .expect("callee can only be identifier")
127 | .sym
128 | .as_ref(),
129 | );
130 |
131 | if style == "raw" {
132 | let style = match &args
133 | .get(0)
134 | .expect("style not specified")
135 | .expr
136 | .as_lit()
137 | .expect("Only literal values allowed")
138 | {
139 | Lit::Str(str) => str.value.to_string(),
140 | _ => panic!("Only string literal values allowed"),
141 | };
142 |
143 | wr.push(style);
144 | } else if style == "variant" {
145 | let prefix = match &args
146 | .get(0)
147 | .expect("variant not specified")
148 | .expr
149 | .as_lit()
150 | .expect("Only literal values allowed")
151 | {
152 | Lit::Str(str) => format!("[{}]:", str.value.as_ref()),
153 | _ => panic!("Only string literal values allowed"),
154 | };
155 |
156 | v.cur_prefix.push(prefix);
157 |
158 | analyse_expr(v, wr, &*args.get(1).expect("style not specified").expr);
159 |
160 | v.cur_prefix.pop();
161 | } else {
162 | v.cur_prefix.push(if style == "important" {
163 | "!".to_string()
164 | } else {
165 | format!("{}:", style)
166 | });
167 |
168 | analyse_expr(v, wr, &*args.get(0).expect("style not specified").expr);
169 |
170 | v.cur_prefix.pop();
171 | }
172 | }
173 | _ => {}
174 | }
175 | }
176 |
177 | #[derive(Default)]
178 | pub struct TransformVisitor {
179 | cur_prefix: Vec,
180 | inside_tw: bool,
181 | style_queue: String,
182 | rule_map: CandidateValueMap,
183 | }
184 |
185 | impl TransformVisitor {
186 | pub fn new() -> Self {
187 | Self::default()
188 | }
189 |
190 | pub fn get_prefix(&self) -> String {
191 | self.cur_prefix.join("")
192 | }
193 | }
194 |
195 | impl VisitMut for TransformVisitor {
196 | fn visit_mut_expr(&mut self, e: &mut Expr) {
197 | if (e.is_call() || e.is_member()) && !self.inside_tw && inner_most_is_tw(&e) {
198 | self.inside_tw = true;
199 |
200 | let mut wr = Vec::::new();
201 | analyse_expr(self, &mut wr, &e);
202 |
203 | *e = Expr::Lit(Lit::Str(Str {
204 | span: DUMMY_SP,
205 | value: wr.join(" ").into(),
206 | raw: None,
207 | }));
208 |
209 | self.inside_tw = false;
210 | } else {
211 | e.visit_mut_children_with(self)
212 | }
213 | }
214 | }
215 |
216 | #[plugin_transform]
217 | pub fn process_transform(program: Program, _metadata: TransformPluginProgramMetadata) -> Program {
218 | program.fold_with(&mut as_folder(TransformVisitor::new()))
219 | }
220 |
221 | fn setup_rule_map() -> CandidateValueMap {
222 | serde_json::from_str::(include_str!("./value.json")).unwrap()
223 | }
224 |
225 | test!(
226 | Default::default(),
227 | |_| as_folder(TransformVisitor::new()),
228 | boo,
229 | r#"let style = tw.flex.$lg(tw.bg_black$['20']).md(tw.important(tw.works).text_["18px"].text_["red-200"]).variant('&:nth-child(3)', tw.underline).raw("s-1/2")"#
230 | );
231 |
--------------------------------------------------------------------------------
/packages/typewind/tests/__swc_snapshots__/swc/lib.rs/boo.js:
--------------------------------------------------------------------------------
1 | let style = "flex @lg:bg-black/20 md:text-red-200 md:text-[18px] md:!works [&:nth-child(3)]:underline s-1/2";
2 |
--------------------------------------------------------------------------------
/packages/typewind/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": [
3 | "src/**/*.ts"
4 | ],
5 | "exclude": [
6 | "node_modules",
7 | "dist"
8 | ],
9 | "compilerOptions": {
10 | "isolatedModules": true,
11 | "esModuleInterop": true,
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "target": "ESNext",
15 | "strict": true,
16 | "allowJs": true,
17 | "skipLibCheck": true
18 | }
19 | }
--------------------------------------------------------------------------------
/packages/typewind/tsup.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'tsup';
2 | import { createRequire } from 'module';
3 |
4 | export default defineConfig({
5 | entry: [
6 | 'src/index.ts',
7 | 'src/cli.ts',
8 | 'src/babel.ts',
9 | 'src/evaluate.ts',
10 | 'src/transform.ts',
11 | 'src/cn.ts',
12 | ],
13 | splitting: false,
14 | clean: true,
15 | platform: 'node',
16 | external: ['typewind', 'tailwindcss', 'esbuild'],
17 | format: ['cjs', 'esm'],
18 | target: 'esnext',
19 | dts: true,
20 | });
21 |
--------------------------------------------------------------------------------
/site/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["next/babel"],
3 | "plugins": ["typewind/babel"]
4 | }
5 |
--------------------------------------------------------------------------------
/site/.gitignore:
--------------------------------------------------------------------------------
1 | .next
2 | node_modules
3 |
--------------------------------------------------------------------------------
/site/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Shu Ding
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/site/README.md:
--------------------------------------------------------------------------------
1 | # Nextra Docs Template
2 |
3 | This is a template for creating documentation with [Nextra](https://nextra.site).
4 |
5 | [**Live Demo →**](https://nextra-docs-template.vercel.app)
6 |
7 | [](https://nextra-docs-template.vercel.app)
8 |
9 | ## Quick Start
10 |
11 | Click the button to clone this repository and deploy it on Vercel:
12 |
13 | [](https://vercel.com/new/clone?s=https%3A%2F%2Fgithub.com%2Fshuding%2Fnextra-docs-template&showOptionalTeamCreation=false)
14 |
15 | ## Local Development
16 |
17 | First, run `pnpm i` to install the dependencies.
18 |
19 | Then, run `pnpm dev` to start the development server and visit localhost:3000.
20 |
21 | ## License
22 |
23 | This project is licensed under the MIT License.
24 |
--------------------------------------------------------------------------------
/site/components/CodeOutput.tsx:
--------------------------------------------------------------------------------
1 | import { tw } from 'typewind';
2 |
3 | export const CodeOutput = ({ children }: { children: React.ReactNode }) => {
4 | return (
5 |
8 | {children}
9 |
10 | );
11 | };
12 |
--------------------------------------------------------------------------------
/site/components/Features.tsx:
--------------------------------------------------------------------------------
1 | import { FiCode } from 'react-icons/fi';
2 | import { SiTailwindcss, SiTypescript } from 'react-icons/si';
3 | import { MdExtensionOff } from 'react-icons/md';
4 | import { RiSettingsFill } from 'react-icons/ri';
5 | import { CiFolderOff } from 'react-icons/ci';
6 | import { tw } from 'typewind';
7 |
8 | type FeatureCardProps = {
9 | icon: React.ReactNode;
10 | title: string;
11 | description: React.ReactNode;
12 | };
13 |
14 | export const Features = () => {
15 | const features: FeatureCardProps[] = [
16 | {
17 | icon: ,
18 | title: 'Zero Bundle Size',
19 | description: (
20 | <>
21 | Typewind compiles away all the styles used, and converts them to
22 | static classes at build time.
23 | >
24 | ),
25 | },
26 | {
27 | icon: ,
28 | title: 'Apply variants to multiple styles at once',
29 | description: (
30 | <>
31 | Typewind provides an intuitive syntax to apply variants to multiple
32 | styles.
33 | >
34 | ),
35 | },
36 | {
37 | icon: ,
38 | title: 'Typesafe',
39 | description: (
40 | <>
41 | Using TS intellisense, Typewind is able to provide type safety to
42 | tailwind, and provide autocomplete for all the classes from{' '}
43 |
49 | tailwind.config.js
50 |
51 | >
52 | ),
53 | },
54 | {
55 | icon: ,
56 | title: 'Types generated from config',
57 | description: (
58 | <>
59 | Type definitions of{' '}
60 |
66 | tw
67 |
{' '}
68 | are generated from your `tailwind.config.js`, and also creates types
69 | for custom theme palette and plugins.
70 | >
71 | ),
72 | },
73 | {
74 | icon: ,
75 | title: 'No need of extensions',
76 | description: (
77 | <>
78 | Type definitions along with CSS Docs are generated from your tailwind
79 | config and work using editors's built-in IntelliSense, and doesn't
80 | require extra extensions.
81 | >
82 | ),
83 | },
84 | {
85 | icon: ,
86 | title: 'Supports all frameworks',
87 | description: (
88 | <>
89 | Typewind works with most Javascript/Typescript frameworks and build
90 | tools like NextJS, SolidStart, Vite, etc.
91 | >
92 | ),
93 | },
94 | ];
95 |
96 | return (
97 |
98 |
103 | Why Typewind?
104 |
105 |
106 |
111 | {features.map((feature, index) => (
112 |
113 | ))}
114 |
115 |
116 |
117 | );
118 | };
119 |
120 | const FeatureCard = ({ icon, title, description }: FeatureCardProps) => {
121 | return (
122 |
127 |
132 | {icon}
133 |
134 |
{title}
135 |
{description}
136 |
137 | );
138 | };
139 |
--------------------------------------------------------------------------------
/site/components/Home.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link';
2 | import { tw } from 'typewind';
3 | import { Features } from './Features';
4 |
5 | export default function Home() {
6 | return (
7 |
12 |
13 |
18 | Bringing typesafety to Tailwind
19 |
20 |
21 |
22 |
27 | Introducing Typewind, the magic of Tailwind combined with the{' '}
28 |
34 | safety
35 | {' '}
36 | of Typescript
37 |
38 |
39 |
40 |
41 |
97 |
106 |
107 |
108 | );
109 | }
110 |
--------------------------------------------------------------------------------
/site/components/Stackblitz.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { tw } from 'typewind';
3 |
4 | const fileMap = {
5 | vite: 'src/App.tsx',
6 | next: 'pages/index.tsx',
7 | };
8 |
9 | export function Stackblitz({ example }: { example: keyof typeof fileMap }) {
10 | return (
11 |
12 |
18 |
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/site/components/Tweet.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 |
3 | export default function Tweet() {
4 | const [isClient, setIsClient] = useState(false);
5 |
6 | useEffect(() => {
7 | setIsClient(true);
8 | }, []);
9 |
10 | if (!isClient) return null;
11 |
12 | return (
13 | <>
14 |
15 |
16 | here's an idea{' '}
17 | pic.twitter.com/L74inu8TKW
18 |
19 | — Colin McDonnell (@colinhacks){' '}
20 |
21 | January 17, 2023
22 |
23 | {' '}
24 |
29 | >
30 | );
31 | }
32 |
--------------------------------------------------------------------------------
/site/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/site/next.config.mjs:
--------------------------------------------------------------------------------
1 | import nextra from "nextra";
2 |
3 | const withNextra = nextra({
4 | theme: "nextra-theme-docs",
5 | themeConfig: "./theme.config.tsx",
6 | defaultShowCopyCode: true,
7 | });
8 |
9 | export default withNextra();
10 |
--------------------------------------------------------------------------------
/site/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "site",
3 | "version": "0.0.1",
4 | "description": "Typewind Docs",
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "postinstall": "typewind generate"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/shuding/nextra-docs-template.git"
14 | },
15 | "author": "",
16 | "license": "MIT",
17 | "dependencies": {
18 | "@vercel/analytics": "^0.1.8",
19 | "date-fns": "^2.29.3",
20 | "micromark-extension-mdxjs-esm": "^1.0.3",
21 | "next": "^13.0.6",
22 | "nextra": "2.2.16",
23 | "nextra-theme-docs": "2.2.16",
24 | "react": "^18.2.0",
25 | "react-dom": "^18.2.0",
26 | "react-icons": "^4.7.1",
27 | "typewind": "^0.1.0"
28 | },
29 | "devDependencies": {
30 | "@types/node": "18.11.10",
31 | "autoprefixer": "^10.4.13",
32 | "postcss": "^8.4.21",
33 | "tailwindcss": "^3.2.4",
34 | "typescript": "^4.9.3"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/site/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import '../styles.css';
2 | import 'nextra-theme-docs/style.css';
3 | import Script from 'next/script';
4 | import Head from 'next/head';
5 | import { Analytics } from '@vercel/analytics/react';
6 |
7 | export default function Nextra({ Component, pageProps }) {
8 | const getLayout = Component.getLayout || (page => page);
9 | return getLayout(
10 | <>
11 |
12 |
13 |
18 |
22 |
23 |
24 |
25 |
26 | >
27 | );
28 | }
29 |
--------------------------------------------------------------------------------
/site/pages/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": {
3 | "title": "Home",
4 | "hidden": true,
5 | "display": "hidden",
6 | "theme": {
7 | "layout": "raw"
8 | }
9 | },
10 | "docs": {
11 | "title": "Documentation",
12 | "type": "page"
13 | }
14 | }
--------------------------------------------------------------------------------
/site/pages/docs/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": "Introduction",
3 | "installation": "Installation",
4 | "usage": "Usage",
5 | "transpilers": "Transpilers",
6 | "examples": "Examples",
7 | "advanced": "Advanced"
8 | }
9 |
--------------------------------------------------------------------------------
/site/pages/docs/advanced/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "configuration": "Configuration",
3 | "escape-hatch": "Escape Hatch",
4 | "custom-config-file-path": "Custom Config File Path",
5 | "rem-to-px": "Rem to Px"
6 | }
7 |
--------------------------------------------------------------------------------
/site/pages/docs/advanced/configuration.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Configuration
3 | ---
4 |
5 | import { Tab, Tabs, Callout } from 'nextra-theme-docs';
6 |
7 | ## Configuration
8 | The configuration for Typewind is present at the `package.json`
9 | ```json filename="package.json"
10 | {
11 | "typewind": {
12 | "configPath": "./tailwind.config.js",
13 | "showPixelEquivalents": false,
14 | "rootFontSize": 16,
15 | }
16 | }
17 | ```
18 |
19 |
20 | The values listed above are the default values set by Typewind.
21 |
22 |
--------------------------------------------------------------------------------
/site/pages/docs/advanced/custom-config-file-path.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Custom Config File Path
3 | ---
4 |
5 | ## Custom Config File Path
6 |
7 | If you're using monorepo or your tailwind config file is just in another folder, you can use this feature to change the path
8 |
9 | You'll just need to add the following config to your `package.json` file.
10 | ```json filename="package.json"
11 | {
12 | "typewind": {
13 | "configPath": "./path/to/your/tailwind.config.cjs"
14 | }
15 | }
16 | ```
17 |
--------------------------------------------------------------------------------
/site/pages/docs/advanced/escape-hatch.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Escape Hatch
3 | ---
4 |
5 | import { Tabs, Tab, Callout } from 'nextra-theme-docs';
6 | import { CodeOutput } from '../../../components/CodeOutput';
7 |
8 |
9 | ## Escape Hatch
10 |
11 | Typewind provides an escape hatch as well, which directly adds the given string to the output. This is not recommended, but can be useful in [some cases](https://typewind.dev/docs/transpilers/swc#swc-caveat).
12 |
13 | ```jsx /text_['20px']/
14 | import { tw } from 'typewind';
15 |
16 | export default function App() {
17 | return (
18 | Click Me
19 | );
20 | }
21 | ```
22 |
23 |
24 |
25 | ```tsx
26 | Click Me
27 | ```
28 |
29 |
30 |
31 | Click Me
32 |
33 |
34 |
35 |
36 |
37 | For more reference, checkout the [Tailwind Docs for Arbitrary
38 | Values](https://tailwindcss.com/docs/adding-custom-styles#using-arbitrary-values).
39 |
40 |
--------------------------------------------------------------------------------
/site/pages/docs/advanced/rem-to-px.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Rem to Px
3 | ---
4 |
5 | ## Custom Config File Path
6 |
7 | In the hover docs for the typewind classes, you can choose to see the `px` equivalents of the `rem` values set by Tailwind by adding the following.
8 |
9 | ```json filename="package.json"
10 | {
11 | "typewind": {
12 | "showPixelEquivalents": true,
13 | "rootFontSize": 18
14 | }
15 | }
16 | ```
17 |
18 | By default, `showPixelEquivalents` is false and `rootFontSize` is 16 (which is the standard value, unless reset by the user).
19 |
--------------------------------------------------------------------------------
/site/pages/docs/examples/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "vite": "Vite",
3 | "next": "NextJS"
4 | }
5 |
--------------------------------------------------------------------------------
/site/pages/docs/examples/next.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: NextJS Example
3 | ---
4 |
5 | import { Stackblitz } from "../../../components/Stackblitz.tsx";
6 |
7 | # NextJS Example
8 |
9 |
10 |
--------------------------------------------------------------------------------
/site/pages/docs/examples/vite.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Vite Example
3 | ---
4 |
5 | import { Stackblitz } from "../../../components/Stackblitz.tsx";
6 |
7 | # Vite Example
8 |
9 |
10 |
--------------------------------------------------------------------------------
/site/pages/docs/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Introduction
3 | ---
4 |
5 | import Tweet from '../../components/Tweet';
6 |
7 | # Typewind
8 |
9 | ## Introduction
10 |
11 |
12 | 
13 |
14 |
15 | Typewind is a **typesafe** and **zero-runtime** version of Tailwind CSS, a utility-first CSS framework that can be composed to build any design, directly in your markup.
16 |
17 | {
18 |
19 |
20 |
}
21 |
22 | ## Tailwind CSS
23 |
24 | Typewind is built on top of Tailwind CSS. For more information on Tailwind CSS, please visit their [documentation](https://tailwindcss.com/docs).
25 |
26 | ## Acknowledgements
27 |
28 | - [Colin McDonnell](https://twitter.com/colinhacks)
29 |
30 | This project was was inspired by Colin's [tweet](https://twitter.com/colinhacks/status/1615154756204523521) on what tailwind with type safety and proper autocompletion would look like.
31 |
--------------------------------------------------------------------------------
/site/pages/docs/installation.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Installation
3 | ---
4 |
5 | import { Tab, Tabs, Callout, Cards, Card, Steps } from 'nextra-theme-docs';
6 |
7 | # Get started with Typewind
8 |
9 | ## Setup Tailwind
10 |
11 | Make sure you have Tailwind setup. You can follow the [official Tailwind Installation docs](https://tailwindcss.com/docs/installation) to get started.
12 |
13 | ## Installation
14 |
15 | Install `typewind` via npm
16 |
17 | ```fish filename="Terminal" copy
18 | npm install typewind
19 | ```
20 |
21 | ## Generating type definitions
22 |
23 | `typewind generate` goes through your `tailwind.config.js` and generates type definitions and css docs based on your theme. This means that the type definitions will be custom to your configuration, and include styles for plugins etc.
24 |
25 | ```fish filename="Terminal" copy
26 | npx typewind generate
27 | ```
28 |
29 |
30 | These definitions need to be generated each time you install a new package via
31 | npm, or edit `tailwind.config.js`
32 |
33 |
34 | It is recommended to set this as your `postinstall` script:-
35 |
36 | ```json filename="package.json"
37 | {
38 | "scripts": {
39 | "postinstall": "typewind generate"
40 | }
41 | }
42 | ```
43 |
44 | ## Quick Start
45 |
46 |
47 | ### Setup transpiler
48 | Typewind has support for both Babel and SWC.
49 |
50 |
60 |
65 |
66 | }
67 | title="Babel"
68 | href="/docs/transpilers/babel"
69 | >
70 |
80 |
85 |
86 | }
87 | title="SWC"
88 | href="/docs/transpilers/swc"
89 | >
90 |
91 |
92 | ### Add transformer
93 |
94 | Add the `typewind` transformers in your `tailwind.config.js`.
95 |
96 | ```js /typewindTransforms/ filename="tailwind.config.js" copy
97 | const { typewindTransforms } = require('typewind/transform');
98 |
99 | /** @type {import('tailwindcss').Config} \*/
100 | module.exports = {
101 | content: {
102 | files: ['./src/**/*.{js,jsx,ts,tsx}'],
103 | transform: typewindTransforms,
104 | },
105 | };
106 | ```
107 |
108 |
--------------------------------------------------------------------------------
/site/pages/docs/transpilers/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "babel": "Babel",
3 | "swc": "SWC"
4 | }
5 |
--------------------------------------------------------------------------------
/site/pages/docs/transpilers/babel.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Babel
3 | ---
4 |
5 | import { Callout } from 'nextra-theme-docs';
6 |
7 | ## Babel
8 |
9 | Add the `typewind` plugin to your `.babelrc`.
10 |
11 | ```json filename=".babelrc" copy {3}
12 | {
13 | "presets": [],
14 | "plugins": ["typewind/babel"]
15 | }
16 | ```
17 |
18 |
19 | Some frameworks like Vite have a different way of editting your babel plugin,
20 | so make sure to take a look at their docs first.
21 |
22 |
--------------------------------------------------------------------------------
/site/pages/docs/transpilers/swc.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: SWC
3 | ---
4 |
5 | import { Callout } from 'nextra-theme-docs';
6 |
7 | ## SWC
8 |
9 | ### NextJS
10 |
11 | Add the `typewind` plugin to your `next.config.js`.
12 |
13 | ```js filename="next.config.js" copy {5}
14 | /** @type {import('next').NextConfig} */
15 | const nextConfig = {
16 | reactStrictMode: true,
17 | experimental: {
18 | swcPlugins: [['typewind/swc', {}]],
19 | },
20 | };
21 |
22 | module.exports = nextConfig;
23 | ```
24 |
25 | ### Standalone SWC
26 |
27 | Add the `typewind` plugin to your `.swcrc`.
28 |
29 | ```json filename=".swcrc" copy {4}
30 | {
31 | "jsc": {
32 | "experimental": {
33 | "plugins": [["typewind/swc", {}]]
34 | }
35 | }
36 | }
37 | ```
38 |
39 |
40 |
41 | The SWC transpiler compiled directly to WASM binary and can't read the Tailwind config file, so arbitrary values only work for predefined tailwind values.
42 |
43 |
44 |
--------------------------------------------------------------------------------
/site/pages/docs/usage.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Usage
3 | ---
4 |
5 | import { Tabs, Tab, Callout } from 'nextra-theme-docs';
6 | import { CodeOutput } from '../../components/CodeOutput';
7 |
8 | # Usage
9 |
10 | ## Example
11 |
12 | ```jsx
13 | import { tw } from 'typewind';
14 |
15 | export default function App() {
16 | return (
17 |
22 |
23 | Hello World
24 |
25 |
26 | );
27 | }
28 | ```
29 |
30 |
31 |
32 | ```jsx
33 |
36 |
37 | Hello World
38 |
39 |
40 | ```
41 |
42 |
43 |
44 |
47 |
48 | Hello World
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/site/pages/docs/usage/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "normal-usage": "Normal Usage",
3 | "modifiers": "Modifiers",
4 | "important-modifier": "Important Modifier",
5 | "arbitrary-values": "Arbitrary Values",
6 | "arbitrary-variants": "Arbitrary Variants",
7 | "container-queries": "Container Queries"
8 | }
9 |
--------------------------------------------------------------------------------
/site/pages/docs/usage/arbitrary-values.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Arbitrary Values
3 | ---
4 |
5 | import { Tabs, Tab, Callout } from 'nextra-theme-docs';
6 | import { CodeOutput } from '../../../components/CodeOutput';
7 |
8 | ## Arbitrary Values
9 |
10 | You can also pass arbitrary values to the `tw` proxy using the same familiar `[]` syntax which tailwind provides us with.
11 |
12 | ```jsx /text_['20px']/
13 | import { tw } from 'typewind';
14 |
15 | export default function App() {
16 | return (
17 | Click Me
18 | );
19 | }
20 | ```
21 |
22 |
23 |
24 | ```tsx
25 | Click Me
26 | ```
27 |
28 |
29 |
30 | Click Me
31 |
32 |
33 |
34 |
35 |
36 | For more reference, checkout the [Tailwind Docs for Arbitrary
37 | Values](https://tailwindcss.com/docs/adding-custom-styles#using-arbitrary-values).
38 |
39 |
--------------------------------------------------------------------------------
/site/pages/docs/usage/arbitrary-variants.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Arbitrary Variants
3 | ---
4 |
5 | import { Tabs, Tab, Callout } from 'nextra-theme-docs';
6 | import { CodeOutput } from '../../../components/CodeOutput';
7 |
8 | ## Arbitrary Variants
9 | Tailwind v3.1 released [support for Arbitrary Variants](https://tailwindcss.com/docs/hover-focus-and-other-states#using-arbitrary-variants).
10 | You can use the `variant()` function to work with arbitrary variants, which takes in the variant as the first argument and the Typewind classes as the second.
11 |
12 | ```jsx /text_['20px']/
13 | import { tw } from 'typewind';
14 |
15 | export default function App() {
16 | return (
17 |
18 | {Array(5)
19 | .fill(' ')
20 | .map((_, i) => (
21 |
28 | Item {i}
29 |
30 | ))}
31 |
32 | );
33 | }
34 | ```
35 |
36 |
37 | Note that here, the modifiers passed in are the exact same as their Tailwind counterparts and do not use the `_` syntax typically used by Typewind.
38 |
39 |
40 |
41 |
42 | ```tsx
43 |
44 | {Array(5)
45 | .fill(' ')
46 | .map((_, i) => (
47 |
51 | Item {i}
52 |
53 | ))}
54 |
55 | ```
56 |
57 |
58 |
59 |
60 | {Array(5)
61 | .fill(' ')
62 | .map((_, i) => (
63 |
67 | Item {i}
68 |
69 | ))}
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | For more reference, checkout the [Tailwind Docs for Arbitrary
78 | Variants](https://tailwindcss.com/docs/hover-focus-and-other-states#using-arbitrary-variants).
79 |
80 |
--------------------------------------------------------------------------------
/site/pages/docs/usage/container-queries.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Container Queries
3 | ---
4 |
5 | import { Tabs, Tab, Callout } from 'nextra-theme-docs';
6 | import { CodeOutput } from '../../../components/CodeOutput';
7 |
8 | ## Container Queries
9 |
10 | [Container Queries](https://github.com/tailwindlabs/tailwindcss-container-queries) is a plugin for Tailwind v3.2+ that provides utilities for [container queries](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries).
11 | Tailwind decided to use a new `@` syntax to differentiate it from media queries. In Typewind, just replace the `@` with `$` and you should be good to go!
12 |
13 | ```jsx
14 | import { tw } from 'typewind';
15 |
16 | export default function App() {
17 | return (
18 |
19 |
20 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Animi, non.
21 |
22 |
23 | );
24 | }
25 | ```
26 |
27 |
28 |
29 | ```tsx
30 |
31 |
32 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Animi, non.
33 |
34 |
35 | ```
36 |
37 |
38 |
39 |
40 |
41 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Animi, non.
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | For any other plugin which uses `@` in the classes, use `$` instead.
51 |
52 |
53 | Typewind does not support named container queries yet. If you would like to contribute, feel free to start a discussion on [Github](https://github.com/mokshit06/typewind).
54 |
55 |
--------------------------------------------------------------------------------
/site/pages/docs/usage/important-modifier.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Important Modifier
3 | ---
4 |
5 | import { Tabs, Tab, Callout } from 'nextra-theme-docs';
6 | import { CodeOutput } from '../../../components/CodeOutput';
7 |
8 | ## Important Modifier
9 |
10 | To specify a class to be important, you can wrap it inside the `tw.important()` modifier.
11 |
12 | ```jsx /tw.important/
13 | import { tw } from 'typewind';
14 |
15 | export default function Button() {
16 | return (
17 |
20 | Click Me
21 |
22 | );
23 | }
24 | ```
25 |
26 |
27 |
28 | ```tsx
29 |
30 | Click Me
31 |
32 | ```
33 |
34 |
35 |
36 |
37 | Click Me
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/site/pages/docs/usage/modifiers.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Modifiers
3 | ---
4 |
5 | import { Tabs, Tab, Callout } from 'nextra-theme-docs';
6 | import { CodeOutput } from '../../../components/CodeOutput';
7 |
8 | ## Modifiers
9 |
10 | [Pseudo-classes](https://tailwindcss.com/docs/hover-focus-and-other-states#pseudo-classes) like `:hover` and `:focus`, [Pseudo-elements](https://tailwindcss.com/docs/hover-focus-and-other-states#pseudo-elements) like `::before`, `::after`,
11 | `::placeholder` and `::selection`, [Media and feature queries](https://tailwindcss.com/docs/hover-focus-and-other-states#media-and-feature-queries) and [Attribute Selectors](https://tailwindcss.com/docs/hover-focus-and-other-states#attribute-selectors) are available as a function.
12 |
13 | Typewind also have a `dark` function which is used to apply styles when the user is in dark mode.
14 |
15 | ```jsx /md(tw.py_4.px_5)/ {7,9}
16 | import { tw } from 'typewind';
17 |
18 | export default function Button() {
19 | return (
20 |
26 | Click Me
27 |
28 | );
29 | }
30 | ```
31 |
32 |
33 |
34 | ```tsx
35 |
36 | Click Me
37 |
38 | ```
39 |
40 |
41 |
42 |
43 | Click Me
44 |
45 |
46 |
47 |
48 |
49 |
50 | For more reference, checkout the Tailwind docs for [Handling Hover, Focus, and
51 | Other States](https://tailwindcss.com/docs/hover-focus-and-other-states),
52 | [Responsive Design](https://tailwindcss.com/docs/responsive-design), and [Dark
53 | Mode](https://tailwindcss.com/docs/dark-mode).
54 |
55 |
56 |
57 | **Differences from Tailwind**:
58 | Because of the way Typewind works, you cannot use `tw.2xl()` for responsiveness but will have to use `tw._2xl(){:jsx}`.
59 |
60 |
61 |
--------------------------------------------------------------------------------
/site/pages/docs/usage/normal-usage.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Normal Usage
3 | ---
4 |
5 | import { Tabs, Tab, Callout } from 'nextra-theme-docs';
6 | import { CodeOutput } from '../../../components/CodeOutput';
7 |
8 | # Normal Usage
9 |
10 | All the utility classes provided by Tailwind are available in the `tw` proxy, and can be chained one after another. They can be found in the [Tailwind Docs](https://tailwindcss.com/docs/utility-first).
11 |
12 |
13 | The hyphens(`-`) in the tailwind classes is replaced with an underscore(`_`)
14 |
15 |
16 | ```jsx
17 | import { tw } from 'typewind';
18 |
19 | export default function Button() {
20 | return (
21 |
22 | Click Me
23 |
24 | );
25 | }
26 | ```
27 |
28 |
29 |
30 | ```jsx
31 | Click Me
32 | ```
33 |
34 |
35 |
36 | Click Me
37 |
38 |
39 |
40 |
41 |
42 | All the utility classes provided by Tailwind are available in the{' '}
43 | tw
proxy. They can be found in the [Tailwind
44 | Docs](https://tailwindcss.com/docs/utility-first).
45 |
46 |
47 |
48 | **Differences from Tailwind**
49 | - For classes that have decimals or a `/` in
50 | them, for eg. in `inset-1/2`, use the syntax for arbitrary values, like
51 | `tw.inset_["1/2"]`. Read more about arbitrary values
52 | [here](/docs/usage/arbitrary-values).
53 | - Classes which start with negative values like `-mt-1` start with an `_` in Typewind. For eg. `tw._mt_1`.
54 |
55 |
56 | ## Color Opacity
57 | You can add an opacity using the Typewind opacity shorthand, as demonstrated in the example.
58 |
59 | ```jsx
60 | import { tw } from 'typewind';
61 |
62 | export default function Button() {
63 | return (
64 |
65 | Click Me
66 |
67 | );
68 | }
69 | ```
70 |
71 |
72 |
73 | ```jsx
74 | Click Me
75 | ```
76 |
77 |
78 |
79 | Click Me
80 |
81 |
82 |
83 |
84 |
85 | This works with all the color related classes like `text-`, `bg-`, `border-`, etc. For more information, check out the [Tailwind docs for opacity shorthand](https://tailwindcss.com/docs/text-color#changing-the-opacity).
86 |
87 |
--------------------------------------------------------------------------------
/site/pages/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Typesafe Tailwind
3 | ---
4 |
5 | import Home from '../components/Home';
6 |
7 |
8 |
--------------------------------------------------------------------------------
/site/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/site/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mokshit06/typewind/68f453eecde4b99668d835b3a7516edc4f759b69/site/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/site/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mokshit06/typewind/68f453eecde4b99668d835b3a7516edc4f759b69/site/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/site/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mokshit06/typewind/68f453eecde4b99668d835b3a7516edc4f759b69/site/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/site/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mokshit06/typewind/68f453eecde4b99668d835b3a7516edc4f759b69/site/public/favicon-16x16.png
--------------------------------------------------------------------------------
/site/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mokshit06/typewind/68f453eecde4b99668d835b3a7516edc4f759b69/site/public/favicon-32x32.png
--------------------------------------------------------------------------------
/site/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mokshit06/typewind/68f453eecde4b99668d835b3a7516edc4f759b69/site/public/favicon.ico
--------------------------------------------------------------------------------
/site/public/preview.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mokshit06/typewind/68f453eecde4b99668d835b3a7516edc4f759b69/site/public/preview.mov
--------------------------------------------------------------------------------
/site/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Typewind",
3 | "short_name": "Typewind",
4 | "icons": [
5 | {
6 | "src": "/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "/android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "theme_color": "#37BCF8",
17 | "background_color": "#111111",
18 | "display": "standalone"
19 | }
20 |
--------------------------------------------------------------------------------
/site/public/typewind-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mokshit06/typewind/68f453eecde4b99668d835b3a7516edc4f759b69/site/public/typewind-logo.png
--------------------------------------------------------------------------------
/site/public/typewind-share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mokshit06/typewind/68f453eecde4b99668d835b3a7516edc4f759b69/site/public/typewind-share.png
--------------------------------------------------------------------------------
/site/styles.css:
--------------------------------------------------------------------------------
1 | @tailwind utilities;
2 |
3 | html {
4 | font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
5 | Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif,
6 | Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
7 | }
8 |
9 | body {
10 | background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, #111 300px),
11 | fixed 0 0 / 20px 20px radial-gradient(#3e3e3e 1px, transparent 0),
12 | fixed 10px 10px / 20px 20px radial-gradient(#3e3e3e 1px, transparent 0);
13 | }
14 |
15 | iframe#twitter-widget-0 {
16 | border-radius: 12px;
17 | }
18 |
19 | .nextra-callout ul {
20 | margin: 0 !important;
21 | }
22 |
--------------------------------------------------------------------------------
/site/tailwind.config.js:
--------------------------------------------------------------------------------
1 | const { typewindTransforms } = require('typewind/transform');
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | content: {
6 | files: [
7 | './pages/**/*.{js,ts,jsx,tsx,mdx}',
8 | './components/**/*.{js,ts,jsx,tsx,mdx}',
9 | './theme.config.tsx',
10 | './styles.css',
11 | ],
12 | transform: typewindTransforms,
13 | },
14 | theme: {
15 | extend: {},
16 | },
17 | plugins: [],
18 | };
19 |
--------------------------------------------------------------------------------
/site/theme.config.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { DocsThemeConfig, useConfig } from 'nextra-theme-docs';
3 | import { useRouter } from 'next/router';
4 | import { tw } from 'typewind';
5 |
6 | const config: DocsThemeConfig = {
7 | logo: (
8 |
14 | type
15 |
21 | wind
22 |
23 |
24 | ),
25 | project: {
26 | link: 'https://github.com/mokshit06/typewind',
27 | },
28 | useNextSeoProps() {
29 | const { route } = useRouter();
30 |
31 | if (route === '/')
32 | return {
33 | titleTemplate: 'Typewind – %s',
34 | };
35 |
36 | return {
37 | titleTemplate: '%s – Typewind',
38 | };
39 | },
40 | docsRepositoryBase: 'https://github.com/mokshit06/typewind/blob/main/site',
41 | footer: {
42 | text: (
43 |
72 | ),
73 | },
74 | darkMode: false,
75 | nextThemes: {
76 | defaultTheme: 'dark',
77 | forcedTheme: 'dark',
78 | },
79 | head: () => {
80 | const { frontMatter: meta } = useConfig();
81 | const { title } = meta;
82 |
83 | return (
84 | <>
85 |
86 |
91 |
97 |
103 |
104 |
105 |
106 |
113 |
120 |
121 |
122 |
126 |
134 |
135 | >
136 | );
137 | },
138 | };
139 |
140 | export default config;
141 |
--------------------------------------------------------------------------------
/site/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": false,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "incremental": true,
11 | "esModuleInterop": true,
12 | "module": "esnext",
13 | "moduleResolution": "node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "jsx": "preserve",
17 | "noPropertyAccessFromIndexSignature": true
18 | },
19 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
20 | "exclude": ["node_modules"]
21 | }
22 |
--------------------------------------------------------------------------------
/tests/__snapshots__/transform.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`transformBabel works with arbitrary-values 1`] = `
4 | "import { tw } from 'typewind';
5 | export default function Button() {
6 | return Click Me ;
7 | }"
8 | `;
9 |
10 | exports[`transformBabel works with arbitrary-variants 1`] = `
11 | "import { tw } from 'typewind';
12 | export default function Button() {
13 | return
14 | Click Me
15 | ;
16 | }"
17 | `;
18 |
19 | exports[`transformBabel works with container-queries 1`] = `
20 | "import { tw } from 'typewind';
21 | export default function App() {
22 | return
23 |
24 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Animi, non.
25 |
26 |
;
27 | }"
28 | `;
29 |
30 | exports[`transformBabel works with modifiers 1`] = `
31 | "import { tw } from 'typewind';
32 | export default function Button() {
33 | return
34 | Click Me
35 | ;
36 | }"
37 | `;
38 |
39 | exports[`transformBabel works with normal-usage 1`] = `
40 | "import { tw } from 'typewind';
41 | import './index.css';
42 | export default function App() {
43 | return ;
46 | }"
47 | `;
48 |
49 | exports[`transformBabel works with transform 1`] = `
50 | "import { tw } from 'typewind';
51 | export default function Button() {
52 | console.log("text-red-100");
53 | return Click Me ;
54 | }"
55 | `;
56 |
--------------------------------------------------------------------------------
/tests/fixtures/arbitrary-values/App.tsx:
--------------------------------------------------------------------------------
1 | import { tw } from 'typewind';
2 |
3 | export default function Button() {
4 | return Click Me ;
5 | }
6 |
--------------------------------------------------------------------------------
/tests/fixtures/arbitrary-values/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-arbitrary-values",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "devDependencies": {
7 | "autoprefixer": "^10.4.13",
8 | "postcss": "^8.4.21",
9 | "tailwindcss": "^3.2.4",
10 | "typewind": "*"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/fixtures/arbitrary-values/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | const { typewindTransforms } = require('typewind/transform');
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | content: {
6 | files: ['*.{js,jsx,ts,tsx}'],
7 | transform: typewindTransforms,
8 | },
9 | theme: {
10 | extend: {},
11 | },
12 | plugins: [],
13 | };
14 |
--------------------------------------------------------------------------------
/tests/fixtures/arbitrary-variants/App.tsx:
--------------------------------------------------------------------------------
1 | import { tw } from 'typewind';
2 |
3 | export default function Button() {
4 | return (
5 |
6 | Click Me
7 |
8 | );
9 | }
10 |
--------------------------------------------------------------------------------
/tests/fixtures/arbitrary-variants/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-arbitrary-variants",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "devDependencies": {
7 | "autoprefixer": "^10.4.13",
8 | "postcss": "^8.4.21",
9 | "tailwindcss": "^3.2.4",
10 | "typewind": "*"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/fixtures/arbitrary-variants/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | const { typewindTransforms } = require('typewind/transform');
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | content: {
6 | files: ['*.{js,jsx,ts,tsx}'],
7 | transform: typewindTransforms,
8 | },
9 | theme: {
10 | extend: {},
11 | },
12 | plugins: [],
13 | };
14 |
--------------------------------------------------------------------------------
/tests/fixtures/container-queries/App.tsx:
--------------------------------------------------------------------------------
1 | import { tw } from 'typewind';
2 |
3 | export default function App() {
4 | return (
5 |
6 |
7 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Animi, non.
8 |
9 |
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/tests/fixtures/container-queries/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-container-queries",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "devDependencies": {
7 | "@tailwindcss/container-queries": "^0.1.0",
8 | "autoprefixer": "^10.4.13",
9 | "postcss": "^8.4.21",
10 | "tailwindcss": "^3.2.4",
11 | "typewind": "*"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/tests/fixtures/container-queries/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | const { typewindTransforms } = require('typewind/transform');
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | content: {
6 | files: ['*.{js,jsx,ts,tsx}'],
7 | transform: typewindTransforms,
8 | },
9 | theme: {
10 | extend: {},
11 | },
12 | plugins: [require('@tailwindcss/container-queries')],
13 | };
14 |
--------------------------------------------------------------------------------
/tests/fixtures/modifiers/App.tsx:
--------------------------------------------------------------------------------
1 | import { tw } from 'typewind';
2 |
3 | export default function Button() {
4 | return (
5 |
14 | Click Me
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/tests/fixtures/modifiers/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-modifiers",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "devDependencies": {
7 | "autoprefixer": "^10.4.13",
8 | "postcss": "^8.4.21",
9 | "tailwindcss": "^3.2.4",
10 | "typewind": "*"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/fixtures/modifiers/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | const { typewindTransforms } = require('typewind/transform');
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | content: {
6 | files: ['*.{js,jsx,ts,tsx}'],
7 | transform: typewindTransforms,
8 | },
9 | theme: {
10 | extend: {},
11 | },
12 | plugins: [],
13 | };
14 |
--------------------------------------------------------------------------------
/tests/fixtures/normal-usage/App.tsx:
--------------------------------------------------------------------------------
1 | import { tw } from 'typewind';
2 | import './index.css';
3 |
4 | export default function App() {
5 | return (
6 |
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/tests/fixtures/normal-usage/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-normal-usage",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "devDependencies": {
7 | "autoprefixer": "^10.4.13",
8 | "postcss": "^8.4.21",
9 | "tailwindcss": "^3.2.4",
10 | "typewind": "*"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/fixtures/normal-usage/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | const { typewindTransforms } = require('typewind/transform');
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | content: {
6 | files: ['*.{js,jsx,ts,tsx}'],
7 | transform: typewindTransforms,
8 | },
9 | theme: {
10 | extend: {},
11 | },
12 | plugins: [],
13 | };
14 |
--------------------------------------------------------------------------------
/tests/fixtures/transform/App.tsx:
--------------------------------------------------------------------------------
1 | import { tw } from 'typewind';
2 |
3 | export default function Button() {
4 | console.log(tw.text_red_100);
5 |
6 | return Click Me ;
7 | }
8 |
--------------------------------------------------------------------------------
/tests/fixtures/transform/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-transform",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "devDependencies": {
7 | "autoprefixer": "^10.4.13",
8 | "postcss": "^8.4.21",
9 | "tailwindcss": "^3.2.4",
10 | "typewind": "*"
11 | }
12 | }
--------------------------------------------------------------------------------
/tests/fixtures/transform/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | const { typewindTransforms } = require('typewind/transform');
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | content: {
6 | files: ['*.{js,jsx,ts,tsx}'],
7 | transform: typewindTransforms,
8 | },
9 | theme: {
10 | extend: {},
11 | },
12 | plugins: [],
13 | };
14 |
--------------------------------------------------------------------------------
/tests/transform.test.ts:
--------------------------------------------------------------------------------
1 | // @ts-ignore
2 | import { transformBabel } from 'typewind/transform';
3 | import * as glob from 'glob';
4 | import * as path from 'path';
5 | import * as fs from 'fs';
6 |
7 | function setupTest(fixturesDir: string, dir: string) {
8 | const dirPath = path.join(fixturesDir, dir);
9 | process.chdir(dirPath);
10 |
11 | const files = glob.sync('*.{ts,tsx,js,jsx}', { cwd: dirPath });
12 |
13 | files.forEach(file => {
14 | const filePath = path.join(dirPath, file);
15 | const ext = path.extname(file).slice(1);
16 | const content = fs.readFileSync(filePath, 'utf-8');
17 | const res = transformBabel(ext, content);
18 | expect(res).toBeDefined();
19 | expect(res).toMatchSnapshot();
20 | });
21 | }
22 |
23 | describe('transformBabel', () => {
24 | const cwd = process.cwd();
25 | const fixturesDir = path.join(cwd, 'tests', 'fixtures');
26 |
27 | test('works with container-queries', () => {
28 | setupTest(fixturesDir, 'container-queries');
29 | });
30 |
31 | test('works with arbitrary-values', () => {
32 | setupTest(fixturesDir, 'arbitrary-values');
33 | });
34 |
35 | test('works with arbitrary-variants', () => {
36 | setupTest(fixturesDir, 'arbitrary-variants');
37 | });
38 |
39 | test('works with modifiers', () => {
40 | setupTest(fixturesDir, 'modifiers');
41 | });
42 |
43 | test('works with normal-usage', () => {
44 | setupTest(fixturesDir, 'normal-usage');
45 | });
46 |
47 | test('works with transform', () => {
48 | setupTest(fixturesDir, 'transform');
49 | });
50 | });
51 |
--------------------------------------------------------------------------------