{"id":13449772,"url":"https://github.com/dylanirlbeck/tailwind-ppx","last_synced_at":"2026-01-14T10:56:44.271Z","repository":{"id":47864163,"uuid":"256399677","full_name":"dylanirlbeck/tailwind-ppx","owner":"dylanirlbeck","description":"A Reason/OCaml Pre-Processor eXtension (PPX) that validates your Tailwind classes at compile-time.","archived":true,"fork":false,"pushed_at":"2021-08-16T19:18:38.000Z","size":7882,"stargazers_count":151,"open_issues_count":19,"forks_count":15,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-20T05:23:40.362Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Reason","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dylanirlbeck.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-17T04:18:39.000Z","updated_at":"2025-08-05T19:37:00.000Z","dependencies_parsed_at":"2022-09-14T09:50:48.044Z","dependency_job_id":null,"html_url":"https://github.com/dylanirlbeck/tailwind-ppx","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/dylanirlbeck/tailwind-ppx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanirlbeck%2Ftailwind-ppx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanirlbeck%2Ftailwind-ppx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanirlbeck%2Ftailwind-ppx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanirlbeck%2Ftailwind-ppx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dylanirlbeck","download_url":"https://codeload.github.com/dylanirlbeck/tailwind-ppx/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanirlbeck%2Ftailwind-ppx/sbom","scorecard":{"id":362168,"data":{"date":"2025-08-11","repo":{"name":"github.com/dylanirlbeck/tailwind-ppx","commit":"c3ec90e9cb8d0edf821468a909f070506c5ffe4d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Code-Review","score":4,"reason":"Found 9/21 approved changesets -- score normalized to 4","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/lint_pr.yml:1","Warn: no topLevel permission defined: .github/workflows/pipeline.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint_pr.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/lint_pr.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint_pr.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/lint_pr.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint_pr.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/lint_pr.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint_pr.yml:58: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/lint_pr.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:62: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:82: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:97: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:100: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:104: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:109: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:114: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:136: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:140: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:154: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:158: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:183: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:186: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:191: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:199: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pipeline.yml:209: update your workflow using https://app.stepsecurity.io/secureworkflow/dylanirlbeck/tailwind-ppx/pipeline.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/lint_pr.yml:17","Warn: npmCommand not pinned by hash: .github/workflows/pipeline.yml:27","Warn: npmCommand not pinned by hash: .github/workflows/pipeline.yml:163","Warn: npmCommand not pinned by hash: .github/workflows/pipeline.yml:167","Info:   0 out of  24 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v0.8.4 not signed: https://api.github.com/repos/dylanirlbeck/tailwind-ppx/releases/34540686","Warn: release artifact v0.8.3 not signed: https://api.github.com/repos/dylanirlbeck/tailwind-ppx/releases/31903910","Warn: release artifact v0.8.2 not signed: https://api.github.com/repos/dylanirlbeck/tailwind-ppx/releases/30335254","Warn: release artifact v0.8.1 not signed: https://api.github.com/repos/dylanirlbeck/tailwind-ppx/releases/30032220","Warn: release artifact v0.8.0 not signed: https://api.github.com/repos/dylanirlbeck/tailwind-ppx/releases/29900465","Warn: release artifact v0.8.4 does not have provenance: https://api.github.com/repos/dylanirlbeck/tailwind-ppx/releases/34540686","Warn: release artifact v0.8.3 does not have provenance: https://api.github.com/repos/dylanirlbeck/tailwind-ppx/releases/31903910","Warn: release artifact v0.8.2 does not have provenance: https://api.github.com/repos/dylanirlbeck/tailwind-ppx/releases/30335254","Warn: release artifact v0.8.1 does not have provenance: https://api.github.com/repos/dylanirlbeck/tailwind-ppx/releases/30032220","Warn: release artifact v0.8.0 does not have provenance: https://api.github.com/repos/dylanirlbeck/tailwind-ppx/releases/29900465"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 19 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"30 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-w8qv-6jwh-64r5","Warn: Project is vulnerable to: GHSA-257v-vj4p-3w2h","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-5fw9-fq32-wv5p","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-566m-qj78-rww5","Warn: Project is vulnerable to: GHSA-7fh5-64p2-3v2j","Warn: Project is vulnerable to: GHSA-hwj9-h5mp-3pm3","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7","Warn: Project is vulnerable to: GHSA-6fc8-4gx4-v693","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T11:05:59.794Z","repository_id":47864163,"created_at":"2025-08-18T11:05:59.794Z","updated_at":"2025-08-18T11:05:59.794Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28417773,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T06:00:55.780Z","updated_at":"2026-01-14T10:56:44.255Z","avatar_url":"https://github.com/dylanirlbeck.png","language":"Reason","funding_links":[],"categories":["PPXs","Running the update","Reason"],"sub_categories":["By Popularity"],"readme":"**Note: As of 08/16/2021, `tailwind-ppx` is now in archive-mode. I have been out of the Reason/ReScript community for some time now, but if anyone wants to take over as owner please let me know. Thank you to all involved for making this project successful.**\n\n---\n\n# tailwind-ppx\n[![Actions Status](https://github.com/dylanirlbeck/tailwind-ppx/workflows/CI/badge.svg)](https://github.com/dylanirlbeck/tailwind-ppx/actions)\n[![NPM Version](https://badge.fury.io/js/%40dylanirlbeck%2Ftailwind-ppx.svg)](https://badge.fury.io/js/%40dylanirlbeck%2Ftailwind-ppx)\n[![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-)\n\nA Reason/OCaml [Pre-Processor eXtension (PPX)](https://blog.hackages.io/reasonml-ppx-8ecd663d5640) that validates your Tailwind classes at compile-time. \n\n\u003cp align=\"center\"\u003e\u003cimg src=\"assets/demo.png\" /\u003e\u003c/p\u003e\n\n## Table of Contents\n\n- [Features (Current and Upcoming)](#features)\n- [Usage](#usage)\n- [Configuration](#configuration)\n- [Installation](#installation)\n- [Frequently Asked Questions (FAQ)](#faq)\n- [Developing](#developing)\n- [Contributors](#contributors-)\n- [Examples and Related Projects](#other)\n\n## Features\n\n**Current**\n\n- Checks for invalid class names (and suggestions for valid ones!)\n- Checks for duplicate class names\n- Always in-sync with your `tailwind.css` file (just make sure to re-build!)\n- [Automatic purging of unused class names](#getting-ready-for-production) (with PurgeCSS and `tailwind-ppx`'s custom extractor function)\n- [Ships with an integration script](#integration-script) that converts all your\n  existing `className=\"...\"` to `className=[%tw \"...\"]`\n\n**Upcoming**\n\n- [Better integration with PostCSS](https://github.com/dylanirlbeck/tailwind-ppx/issues/62)\n- Checks for redundant class names (like having both `flex-row` and `flex-col`)\n- Checks for class name dependencies (like having `flex-row` without `flex`)\n\nIf you have ideas for new features, please [open an issue](https://github.com/dylanirlbeck/tailwind-ppx/issues)!\n\n## Usage\n\n`tailwind_ppx` implements a ppx (`%tw`) that validates your Tailwind CSS classes at compile time.\n\nFor example, for the following (condensed) `tailwind.css` file:\n\n```css\n.flex {\n  display: flex;\n}\n\n.flex-row {\n  flex-direction: row;\n}\n```\n\n`tailwind-ppx` will provide validation for your desired class names. See these\nexamples:\n\n```reason\n// Example 1\n\u003cComponent className=[%tw \"flex flex-row\"] /\u003e // This is ok!\n\n// Example 2\n\u003cComponent className=[%tw \"flex flex-ro\"] /\u003e // ERROR: Class name not found: flex-ro. Did you mean flex-row?\n\n// Example 3\n\u003cComponent className=[%tw \"flex flex-row flex\"] /\u003e // ERROR: Duplicate class name: flex\n```\n\nFinally, `tailwind-ppx` requires your **generated** `tailwind.css` file to exist somewhere in the\nproject hierarchy. Though not required, it's recommended that you [configure the\npath](#-path) to your `tailwind.css` file (relative to your project root).\n\n### Getting ready for production\n\nAs [outlined in the Tailwind docs](https://tailwindcss.com/docs/controlling-file-size/), when preparing for production you'll want to make sure that the only CSS from Tailwind that ends up in your bundle is CSS that you _actually use_ in your code.\n\nFirst, take a second to read the [section on setting up Purgecss from the Tailwind docs](https://tailwindcss.com/docs/controlling-file-size/#setting-up-purgecss). In order to help with the process outlined in the docs, this package ships with a default extractor function that'll take care of ensuring that any CSS from Tailwind that you aren't using with this PPX can be purged from your production CSS bundle. You enable it by slightly modifying the official example of how to set up your `postcss.config.js`:\n\n```javascript\n// postcss.config.js\nconst purgecss = require(\"@fullhuman/postcss-purgecss\")({\n  // Specify the paths to all ReasonML code where you're using this PPX.\n  content: [\"./src/**/*.re\"],\n\n  // Include the extractor from this package\n  defaultExtractor: require(\"@dylanirlbeck/tailwind-ppx\").extractor\n});\n\nmodule.exports = {\n  plugins: [\n    require(\"tailwindcss\"),\n    require(\"autoprefixer\"),\n    ...(process.env.NODE_ENV === \"production\" ? [purgecss] : [])\n  ]\n};\n```\n\nDoing this will ensure that you only ship CSS from Tailwind to production that you're actually using with this PPX.\n\n### Moving or changing your `tailwind.css` file\n\nIf your `tailwind.css` file changes (or you move it) you'll need to rebuild your\nproject - for example, `bsb -clean-world` and `bsb -make-world` if in BuckleScript.\nAt this time, `tailwind-ppx` does not automatically watch for changes, though this is on\nthe roadmap.\n\nAlternatively, you can add the following rules to you bsconfig.json to re-trigger builds\n\n```json\n{\n  \"sources\": [\n    {\n      \"dir\": \"src\",\n      \"subdirs\": true,\n      \"generators\": [\n        {\n          \"name\": \"gen-tailwind\",\n          \"edge\": [\"tailwind.css\", \":\", \"styles.css\"]\n        }\n      ]\n    }\n  ],\n  \"generators\": [\n    {\n      \"name\": \"gen-tailwind\",\n      \"command\": \"tailwindcss build $in -o $out\"\n    }\n  ]\n}\n```\n\nIf you have a custom tailwind config file, you'll need to pass it to the tailwindcss command:\n\n```json\n{\n  \"name\": \"gen-tailwind\",\n  \"command\": \"tailwindcss build $in -o $out -c ../../tailwind.config.js\"\n}\n```\n\nYou might have to [specify the path to `tailwind.css`](#-path).\n\n### Autocompletion (Neovim only)\n\nIf you're a Neovim user, you can download the [`coc-tailwindcss`](https://github.com/iamcco/coc-tailwindcss) extension to get class name autocompletion while using `tailwind-ppx` - just make sure to define a `tailwind.config.js` file. See the example below!\n\n\u003cimg src=\"assets/autocompletion.png\" height=\"600\" width=\"800\"\u003e\n\n### Ignore `.tailwind_ppx_cache` in your version control\n\n`tailwind-ppx` will generate a `.tailwind_ppx_cache` folder in your project root\nto optimize the validation performance. If you're using a version control\nsystem, you don't need to check it in.\n\n## Configuration\n\n### -path\n\nBy default, `tailwind-ppx` looks for your `tailwind.css` file in the root\ndirectory. If `tailwind.css` lives elsewhere (or the name of your generated CSS file is different), you'll need to specify the file path in your `bsconfig.json`.\n\n```json\n\"ppx-flags\": [\n  [\"tailwind-ppx\", \"-path ../path/to/tailwind.css\",]\n],\n```\n\n## Installation\n\nThe most likely use case for `tailwind-ppx` is inside ReasonReact projects\n(using BuckleScript). To get started, we recommend cloning our [demo\nproject](https://github.com/dylanirlbeck/tailwind-ppx-demo).\n\n### With `yarn` or `npm` on Bucklescript projects (recommended)\n\nInstall the PPX with `yarn` or `npm`\n\n```bash\nyarn add --dev @dylanirlbeck/tailwind-ppx\n# Or\nnpm install --dev @dylanirlbeck/tailwind-ppx\n```\n\nAnd add the PPX in your `bsconfig.json` file:\n\n```json\n{\n  \"ppx-flags\": [\"tailwind-ppx\"]\n}\n```\n\n### Integration script\n\nThe `@dylanirlbeck/tailwind-ppx` NPM package ships with an executable that, when\nrun in a BuckleScript project, turns all instances of `className=\"...\"` into\n`className=[%tw \"...\"]`. The script is designed to make it easy to immediately\nintroduce `tailwind-ppx` into an existing codebase.\n\nYou can use this script by running the following command from the root of your\nproject (just make sure you've installed the NPM package).\n\n```\nyarn use-tailwind-ppx\n# Or\nnpx use-tailwind-ppx\n```\n\n\u003e Note that you'll need both a `bsconfig.json` to exist in the project hierarchy\n\u003e and compiled project with `bsb -make-world` (so the `lib/` directory exists in\n\u003e the project root) for the script to work properly.\n\n## FAQ\n\n- **How can I conditionally add classes?**\n\n  This feature is out of scope for `tailwind-ppx`; instead, we recommend you use\n  [`re-classnames`](https://github.com/MinimaHQ/re-classnames) in combination\n  with `tailwind-ppx`. See the example below:\n\n  ```reason\n  module SomeComponent = {\n    [@react.component]\n    let make = (~someBool) =\u003e {\n      let className =\n        Cn.(\n          [%tw \"text-blue-500\"]-\u003eon(someBool)\n          + [%tw \"text-gray-500\"]-\u003eon(!someBool)\n        );\n      \u003cdiv className /\u003e;\n    };\n  };\n  ```\n\n- **How can I use custom CSS classes?**\n\n  `tailwind-ppx` directly parses your generated `tailwind.css` file, which means\n  that **all** CSS classes will be validated by the PPX, including custom class\n  names defined in your base `index.css/styles.css` file. In short, if the class\n  is in your `tailwind.css` file, it will be validated correctly by the ppx.\n\n  Example:\n\n  ```reason\n  \u003cComponent className=[%tw \"flex flex-row customLayou\"] /\u003e // ERROR: Class name not found: customLayou. Did you mean customLayout?\n  ```\n\n## Developing\n\nAfter cloning the repository, you should run `esy` to install the project dependencies. After that, you should be good to start developing!\n\n### Relevant commands\n\n- `esy build` -\u003e Builds the project\n- `esy format` -\u003e Formats the entire project with `ocamlformat` and `refmt`\n- `esy watch` -\u003e Watches for changes to Reason/OCaml files in the entire project, including in the `/test` directory\n- `esy test_native` -\u003e Runs the native tests (in `test/native`)\n- `cd test/bucklescript \u0026\u0026 yarn test` -\u003e Runs the BuckleScript tests (in `test/bucklescript`)\n\n\u003e Note that if you pull requests are not formatted properly, or the `esy.lock`\n\u003e is out-of-date, GitHub actions will automatically format your code by pushing\n\u003e up a new commit.\n\n### Releasing (for maintainers)\n\n1. Bump the version of the ppx in `esy.json` on `master` (we use [semantic versioning](https://semver.org/))\n2. Create and push a new tag\n\n```\n$ git checkout master\n$ git tag vx.y.z\n$ git push origin vx.y.z\n```\n\n3. [Create detailed release notes](https://github.com/dylanirlbeck/tailwind-ppx/releases) for the new version, following the `Added/Changed/Fixed/Removed` format. Note that the new version of the PPX will automatically be pushed to NPM and a release will be created on GitHub.\n4. Make sure that for any merged pull requests/closed issues were noticed by the `all-contributors` bot -- see [this PR](https://github.com/dylanirlbeck/tailwind-ppx/pull/116#issuecomment-657551562) for an example of adding a new contributor who's PR was merged.\n\n## Contributors ✨\n\nThanks goes to these wonderful people:\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://dev.to/dylanirlbeck\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/35497479?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eDylan Irlbeck \u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=dylanirlbeck\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=dylanirlbeck\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/tatchi\"\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/5595092?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eCorentin Leruth\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=tatchi\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#ideas-tatchi\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"#maintenance-tatchi\" title=\"Maintenance\"\u003e🚧\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://twitter.com/___zth___\"\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/1457626?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eGabriel Nordeborn\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=zth\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#ideas-zth\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/bdunn313\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/867683?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eBrad Dunn\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=bdunn313\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/issues?q=author%3Abdunn313\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://infinitetree.eu/\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/45546?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eThomas Coopman\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/issues?q=author%3Atcoopman\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e \u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=tcoopman\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"http://prometheansacrifice.me/\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/3097018?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eManas\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=prometheansacrifice\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://peterp.me\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/1211905?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ePeter Piekarczyk\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#ideas-peterpme\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/pckilgore\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/2559043?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ePatrick Kilgore\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=pckilgore\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/azkane\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/3322582?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eahzm\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=azkane\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=azkane\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#ideas-azkane\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/joprice\"\u003e\u003cimg src=\"https://avatars1.githubusercontent.com/u/2175555?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eJoseph Price\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=joprice\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://twitter.com/_danchenkov\"\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/2461813?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eVladimir Danchenkov\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=vdanchenkov\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://jonas.zeitler.se/\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/1719257?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eJonas Zeitler\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=J-Zeitler\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/lozlow\"\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/386319?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ePete Shaw\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/dylanirlbeck/tailwind-ppx/commits?author=lozlow\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-enable --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!\n\n## Other\n\n### Examples\n\nThese projects are using `tailwind-ppx` throughout the code base:\n\n- [my-first-pr](https://github.com/dylanirlbeck/my-first-pr)\n\n### Related Projects\n\nThe following amazing projects provided a lot of inspiration; I recommend you check them out!\n\n- [ocaml-css-parser](https://github.com/astrada/ocaml-css-parser)\n- [styled-ppx](https://github.com/davesnx/styled-ppx)\n- [graphql-ppx](https://github.com/reasonml-community/graphql_ppx)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdylanirlbeck%2Ftailwind-ppx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdylanirlbeck%2Ftailwind-ppx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdylanirlbeck%2Ftailwind-ppx/lists"}