├── .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 | [![Powered by Vercel](https://raw.githubusercontent.com/mokshit06/typewind/main/.github/powered-by-vercel.svg)](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 | 7 | 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 | [![](.github/screenshot.png)](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/button)](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 |
46 | 56 | Get Started 57 | 68 | 69 | 70 | 71 | 72 | 81 | 92 | 93 | 94 | Github 95 | 96 |
97 |
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 |