├── .babelrc ├── .eslintignore ├── .eslintrc.json ├── .github └── workflows │ ├── pr.yml │ └── release.yml ├── .gitignore ├── .lintstagedrc.js ├── .prettierignore ├── .prettierrc.json ├── README.md ├── jest.config.js ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── index.js ├── options.js ├── parser.js ├── regex.json ├── sorter.json └── utils │ └── sort.js ├── test ├── mocks │ ├── babel │ │ ├── default_behaviour_formatted.js │ │ ├── default_behaviour_unformatted.js │ │ ├── no_duplicate_unknown_formatted.js │ │ ├── no_duplicate_unknown_unformatted.js │ │ ├── no_remove_duplicate_formatted.js │ │ ├── no_remove_duplicate_unformatted.js │ │ ├── remove_duplicate_formatted.js │ │ └── remove_duplicate_unformatted.js │ ├── css │ │ ├── default_behaviour_formatted.css │ │ ├── default_behaviour_unformatted.css │ │ ├── no_duplicate_unknown_formatted.css │ │ ├── no_duplicate_unknown_unformatted.css │ │ ├── no_remove_duplicate_formatted.css │ │ ├── no_remove_duplicate_unformatted.css │ │ ├── remove_duplicate_formatted.css │ │ └── remove_duplicate_unformatted.css │ ├── customRegex.json │ ├── flow │ │ ├── default_behaviour_formatted.js │ │ ├── default_behaviour_unformatted.js │ │ ├── no_duplicate_unknown_formatted.js │ │ ├── no_duplicate_unknown_unformatted.js │ │ ├── no_remove_duplicate_formatted.js │ │ ├── no_remove_duplicate_unformatted.js │ │ ├── remove_duplicate_formatted.js │ │ └── remove_duplicate_unformatted.js │ ├── html │ │ ├── custom_regex_formatted.html │ │ ├── custom_regex_unformatted.html │ │ ├── default_behaviour_formatted.html │ │ ├── default_behaviour_unformatted.html │ │ ├── no_duplicate_unknown_formatted.html │ │ ├── no_duplicate_unknown_unformatted.html │ │ ├── no_remove_duplicate_formatted.html │ │ ├── no_remove_duplicate_unformatted.html │ │ ├── remove_duplicate_formatted.html │ │ └── remove_duplicate_unformatted.html │ ├── less │ │ ├── default_behaviour_formatted.less │ │ ├── default_behaviour_unformatted.less │ │ ├── no_duplicate_unknown_formatted.less │ │ ├── no_duplicate_unknown_unformatted.less │ │ ├── no_remove_duplicate_formatted.less │ │ ├── no_remove_duplicate_unformatted.less │ │ ├── remove_duplicate_formatted.less │ │ └── remove_duplicate_unformatted.less │ ├── regexMalformed.json │ ├── scss │ │ ├── default_behaviour_formatted.scss │ │ ├── default_behaviour_unformatted.scss │ │ ├── no_duplicate_unknown_formatted.scss │ │ ├── no_duplicate_unknown_unformatted.scss │ │ ├── no_remove_duplicate_formatted.scss │ │ ├── no_remove_duplicate_unformatted.scss │ │ ├── remove_duplicate_formatted.scss │ │ └── remove_duplicate_unformatted.scss │ ├── sorterMalformed.json │ ├── typescript │ │ ├── default_behaviour_formatted.tsx │ │ ├── default_behaviour_unformatted.tsx │ │ ├── no_duplicate_unknown_formatted.tsx │ │ ├── no_duplicate_unknown_unformatted.tsx │ │ ├── no_remove_duplicate_formatted.tsx │ │ ├── no_remove_duplicate_unformatted.tsx │ │ ├── remove_duplicate_formatted.tsx │ │ └── remove_duplicate_unformatted.tsx │ └── vue │ │ ├── default_behaviour_formatted.vue │ │ ├── default_behaviour_unformatted.vue │ │ ├── no_duplicate_unknown_formatted.vue │ │ ├── no_duplicate_unknown_unformatted.vue │ │ ├── no_remove_duplicate_formatted.vue │ │ ├── no_remove_duplicate_unformatted.vue │ │ ├── remove_duplicate_formatted.vue │ │ └── remove_duplicate_unformatted.vue └── plugin.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env", { "targets": ["last 2 versions"] }]], 3 | "ignore": ["./test/mocks/"] 4 | } 5 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | test/mocks/babel 3 | test/mocks/flow -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "sourceType": "module", 4 | "ecmaVersion": 2020 5 | }, 6 | "env": { 7 | "es6": true, 8 | "jest": true, 9 | "node": true 10 | }, 11 | "extends": [ 12 | "eslint:recommended", 13 | "plugin:react/recommended", 14 | "plugin:react-hooks/recommended", 15 | "plugin:@typescript-eslint/recommended", 16 | "prettier" 17 | ], 18 | "plugins": ["prettier"], 19 | "rules": { 20 | "no-console": "error", 21 | "no-debugger": "error" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | name: PR 2 | on: 3 | pull_request: 4 | types: [opened, synchronize, reopened] 5 | 6 | env: 7 | NODE_VERSION: '12.x' 8 | 9 | jobs: 10 | setup: 11 | name: Setup 12 | runs-on: ubuntu-latest 13 | timeout-minutes: 5 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - uses: actions/setup-node@v1 18 | with: 19 | node-version: '${{ env.NODE_VERSION }}' 20 | 21 | - name: Cache node modules 22 | id: cache 23 | uses: actions/cache@v1 24 | with: 25 | path: node_modules 26 | key: ${{ runner.os }}-node_modules-${{ hashFiles('**/yarn.lock') }} 27 | 28 | - name: Install Dependencies 29 | if: steps.cache.outputs.cache-hit != 'true' 30 | run: yarn 31 | 32 | eslint: 33 | name: Eslint 34 | runs-on: ubuntu-latest 35 | needs: [setup] 36 | timeout-minutes: 5 37 | steps: 38 | - uses: actions/checkout@v2 39 | with: 40 | fetch-depth: 0 41 | 42 | - uses: actions/setup-node@v1 43 | with: 44 | node-version: '${{ env.NODE_VERSION }}' 45 | 46 | - name: Fetch all branches 47 | run: | 48 | git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/* 49 | - name: Cache node modules 50 | uses: actions/cache@v1 51 | with: 52 | path: node_modules 53 | key: ${{ runner.os }}-node_modules-${{ hashFiles('**/yarn.lock') }} 54 | 55 | - name: Run Eslint 56 | run: yarn lint:ci -- $(git diff --diff-filter d --name-only origin/${{ github.base_ref }}...HEAD -- '*.js' '*.jsx') 57 | 58 | tests: 59 | name: Tests 60 | runs-on: ubuntu-latest 61 | needs: [setup] 62 | timeout-minutes: 5 63 | steps: 64 | - uses: actions/checkout@v2 65 | 66 | - uses: actions/setup-node@v1 67 | with: 68 | node-version: '${{ env.NODE_VERSION }}' 69 | 70 | - name: Cache node modules 71 | uses: actions/cache@v1 72 | with: 73 | path: node_modules 74 | key: ${{ runner.os }}-node_modules-${{ hashFiles('**/yarn.lock') }} 75 | 76 | - name: Run Tests 77 | run: yarn test:ci 78 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | release: 8 | runs-on: ubuntu-16.04 9 | steps: 10 | - uses: actions/checkout@v2 11 | - uses: actions/setup-node@v1 12 | with: 13 | node-version: '12' 14 | - run: yarn 15 | - run: yarn test:ci 16 | - name: Build 17 | run: yarn build 18 | - name: Release 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} 21 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 22 | run: npx semantic-release 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #IDE 2 | .vscode 3 | 4 | #test 5 | coverage 6 | 7 | #dep 8 | node_modules 9 | 10 | #build 11 | dist 12 | 13 | report* -------------------------------------------------------------------------------- /.lintstagedrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | '**/*.js': (files) => [`eslint --quiet --fix ${files.join(' ')}`, `jest --passWithNoTests`], 3 | '**/*.{md,js,json,yml,html,css,pcss}': (files) => [`prettier --write ${files.join(' ')}`] 4 | } 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | coverage -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSpacing": true, 4 | "printWidth": 120, 5 | "semi": false, 6 | "singleQuote": true, 7 | "tabWidth": 4, 8 | "trailingComma": "none", 9 | "useTabs": true, 10 | "overrides": [ 11 | { 12 | "files": "*.md", 13 | "options": { 14 | "tabWidth": 2, 15 | "useTabs": false 16 | } 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | Prettier 4 | Tailwind 6 |
7 | 8 |

Prettier Tailwind Plugin

9 | 10 |

11 | 12 | 13 | code style: prettier 14 | 15 | 16 | npm version 17 | 18 | semantic release 19 |
20 |

21 | 22 | > "Make it work, make it right, make it fast" 23 | > 24 | > - [Kent Beck](https://en.wikipedia.org/wiki/Kent_Beck) 25 | 26 | ## Intro 27 | 28 | Prettier is an opinionated code formatter. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary. 29 | 30 | This plugin adds support for the Tailwind CSS library. 31 | 32 | ### How it works 33 | 34 | This plugin will sort tailwind classes as [headwind](https://github.com/heybourn/headwind) does and will also remove duplicates classes. 35 | 36 | Actually the plugin works for the following languages: 37 | 38 | 1. `html` 39 | 2. `js` 40 | 3. `jsx` 41 | 4. `ts` 42 | 5. `tsx` 43 | 6. `vue` 44 | 45 | ### Input 46 | 47 | ```html 48 |
49 |

Hello World

50 |
51 | ``` 52 | 53 | ### Output 54 | 55 | ```html 56 |
57 |

Hello World

58 |
59 | ``` 60 | 61 | ## Install 62 | 63 | Install prettier-plugin-tailwind-css: 64 | 65 | ``` 66 | npm install --save-dev prettier-plugin-tailwind-css 67 | ``` 68 | 69 | ``` 70 | yarn add -D prettier-plugin-tailwind-css 71 | ``` 72 | 73 | ## Configuration 74 | 75 | Prettier for Tailwind supports the following options. 76 | 77 | | Name | Default | Description | 78 | | ------------------------- | ------------------- | --------------------------------------------------------------------------------------------------- | 79 | | `removeDuplicatesClasses` | `true` | If set to `"true"`, all duplicate classes found will be deleted | 80 | | `classRegex` | `./src/regex.json` | See [file](https://raw.githubusercontent.com/marcosvega91/prettier-tailwind/master/src/regex.json) | 81 | | `classSorter` | `./src/sorter.json` | See [file](https://raw.githubusercontent.com/marcosvega91/prettier-tailwind/master/src/sorter.json) | 82 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'node', 3 | rootDir: '.', 4 | testMatch: ['/test/**/*.js'], 5 | moduleFileExtensions: ['js'], 6 | collectCoverage: false, 7 | collectCoverageFrom: ['src/**/*.js'], 8 | transformIgnorePatterns: ['/test/mocks'], 9 | testPathIgnorePatterns: ['/test/mocks'] 10 | } 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "prettier-plugin-tailwind-css", 3 | "version": "0.0.5-development", 4 | "main": "dist/index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "build": "./node_modules/.bin/rollup -c", 8 | "test": "jest --watch", 9 | "test:ci": "jest --ci", 10 | "prettier": "prettier --write .", 11 | "lint": "eslint .", 12 | "lint:ci": "eslint", 13 | "semantic-release": "semantic-release" 14 | }, 15 | "dependencies": { 16 | "prettier": "^2.0.5" 17 | }, 18 | "devDependencies": { 19 | "@babel/core": "^7.11.4", 20 | "@babel/preset-env": "^7.11.0", 21 | "@rollup/plugin-babel": "^5.2.0", 22 | "@types/jest": "^26.0.10", 23 | "@types/node": "^14.6.0", 24 | "@types/prettier": "^2.0.2", 25 | "@types/react": "^16.9.46", 26 | "@typescript-eslint/eslint-plugin": "^3.9.1", 27 | "@typescript-eslint/parser": "^3.9.1", 28 | "babel-cli": "^6.26.0", 29 | "babel-jest": "^26.3.0", 30 | "eslint": "^7.7.0", 31 | "eslint-config-prettier": "^6.11.0", 32 | "eslint-plugin-prettier": "^3.1.4", 33 | "eslint-plugin-react": "^7.20.6", 34 | "eslint-plugin-react-hooks": "^4.1.0", 35 | "husky": "^4.2.5", 36 | "jest": "^26.4.2", 37 | "lint-staged": "^10.2.11", 38 | "react": "^16.13.1", 39 | "rollup": "^2.26.5", 40 | "rollup-plugin-copy": "^3.3.0", 41 | "semantic-release": "^17.1.1", 42 | "typescript": "^4.0.2" 43 | }, 44 | "husky": { 45 | "hooks": { 46 | "pre-commit": "lint-staged" 47 | } 48 | }, 49 | "repository": { 50 | "type": "git", 51 | "url": "https://github.com/marcosvega91/prettier-tailwind.git" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from '@rollup/plugin-babel' 2 | import copy from 'rollup-plugin-copy' 3 | 4 | export default { 5 | external: ['prettier/parser-html', 'prettier/parser-flow', 'prettier/parser-babel'], 6 | input: 'src/index.js', 7 | output: { 8 | file: './dist/index.js', 9 | format: 'cjs' 10 | }, 11 | sourceMap: 'inline', 12 | plugins: [ 13 | copy({ 14 | targets: [ 15 | { src: 'src/sorter.json', dest: 'dist/' }, 16 | { src: 'src/regex.json', dest: 'dist/' } 17 | ] 18 | }), 19 | babel({ 20 | exclude: 'node_modules/**', 21 | presets: [['@babel/preset-env', { modules: false }]] 22 | }) 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import prettierParserHTML from 'prettier/parser-html' 2 | import prettierParserFlow from 'prettier/parser-flow' 3 | import prettierParserTypescript from 'prettier/parser-typescript' 4 | import prettierParserBabel from 'prettier/parser-babel' 5 | import prettierParserPostCss from 'prettier/parser-postcss' 6 | import { getParse } from './parser' 7 | import { options } from './options' 8 | 9 | const languages = [ 10 | { 11 | name: 'Tailwind JS/JSX', 12 | extensions: ['.jsx', '.js'], 13 | parsers: ['flow'] 14 | }, 15 | { 16 | name: 'Tailwind TS/TSX', 17 | extensions: ['.tsx', '.ts'], 18 | parsers: ['typescript'] 19 | }, 20 | { 21 | name: 'Tailwind HTML', 22 | extensions: ['.html'], 23 | parsers: ['html'] 24 | }, 25 | { 26 | name: 'Tailwind Vue', 27 | extensions: ['.vue'], 28 | parsers: ['vue'] 29 | }, 30 | { 31 | name: 'Tailwind CSS', 32 | extensions: ['.css'], 33 | parsers: ['css'] 34 | }, 35 | { 36 | name: 'Tailwind SCSS', 37 | extensions: ['.scss'], 38 | parsers: ['scss'] 39 | }, 40 | { 41 | name: 'Tailwind Less', 42 | extensions: ['.less'], 43 | parsers: ['less'] 44 | } 45 | ] 46 | const parsers = { 47 | html: { 48 | ...prettierParserHTML.parsers.html, 49 | parse: getParse('html', prettierParserHTML.parsers.html.parse) 50 | }, 51 | flow: { 52 | ...prettierParserFlow.parsers.flow, 53 | parse: getParse('javascriptreact', prettierParserFlow.parsers.flow.parse) 54 | }, 55 | typescript: { 56 | ...prettierParserTypescript.parsers.typescript, 57 | parse: getParse('typescriptreact', prettierParserTypescript.parsers.typescript.parse) 58 | }, 59 | babel: { 60 | ...prettierParserBabel.parsers.babel, 61 | parse: getParse('javascriptreact', prettierParserBabel.parsers.babel.parse) 62 | }, 63 | vue: { 64 | ...prettierParserHTML.parsers.vue, 65 | parse: getParse('html', prettierParserHTML.parsers.vue.parse) 66 | }, 67 | css: { 68 | ...prettierParserPostCss.parsers.css, 69 | parse: getParse('css', prettierParserPostCss.parsers.css.parse) 70 | }, 71 | scss: { 72 | ...prettierParserPostCss.parsers.scss, 73 | parse: getParse('scss', prettierParserPostCss.parsers.scss.parse) 74 | }, 75 | less: { 76 | ...prettierParserPostCss.parsers.less, 77 | parse: getParse('less', prettierParserPostCss.parsers.less.parse) 78 | } 79 | } 80 | 81 | const plugin = { 82 | languages, 83 | parsers, 84 | options 85 | } 86 | export default plugin 87 | -------------------------------------------------------------------------------- /src/options.js: -------------------------------------------------------------------------------- 1 | export const options = { 2 | removeDuplicatesClasses: { 3 | type: 'boolean', 4 | default: true, 5 | description: 'remove duplicates classes' 6 | }, 7 | classRegex: { 8 | type: 'path', 9 | default: `${__dirname}/regex.json`, 10 | description: 'regex expression to find classes' 11 | }, 12 | classSorter: { 13 | type: 'path', 14 | default: `${__dirname}/sorter.json`, 15 | description: 'order of the classes' 16 | } 17 | } 18 | 19 | export default options 20 | -------------------------------------------------------------------------------- /src/parser.js: -------------------------------------------------------------------------------- 1 | import { sortClassInText } from './utils/sort' 2 | import fs from 'fs' 3 | 4 | export function getParse(language, defaultParse) { 5 | return (text, parsers, options) => { 6 | let sortedText = text 7 | if (fs.existsSync(options.classRegex) && fs.existsSync(options.classSorter)) { 8 | const classRegex = JSON.parse(fs.readFileSync(options.classRegex, 'utf8')) 9 | const classSorter = JSON.parse(fs.readFileSync(options.classSorter, 'utf8')) 10 | 11 | if (language in classRegex && Array.isArray(classSorter)) { 12 | const classWrapperRegex = new RegExp(classRegex[language], 'gi') 13 | sortedText = sortClassInText(text, classWrapperRegex, classSorter, { 14 | removeDuplicates: options.removeDuplicatesClasses 15 | }) 16 | } 17 | } 18 | 19 | const result = defaultParse(sortedText, parsers, options) 20 | 21 | return result 22 | } 23 | } 24 | 25 | export default { 26 | getParse 27 | } 28 | -------------------------------------------------------------------------------- /src/regex.json: -------------------------------------------------------------------------------- 1 | { 2 | "vue": "\\bclass\\s*=\\s*[\\\"\\']([_a-zA-Z0-9\\s\\-\\:\\/]+)[\\\"\\']", 3 | "html": "\\bclass\\s*=\\s*[\\\"\\']([_a-zA-Z0-9\\s\\-\\:\\/]+)[\\\"\\']", 4 | "css": "@apply\\s*([_a-zA-Z0-9\\s\\-\\:\\/]+)", 5 | "scss": "@apply\\s*([_a-zA-Z0-9\\s\\-\\:\\/]+)", 6 | "less": "@apply\\s*([_a-zA-Z0-9\\s\\-\\:\\/]+)", 7 | "javascriptreact": "(?:\\bclassName\\s*=\\s*[\\\"\\']([_a-zA-Z0-9\\s\\-\\:\\/]+)[\\\"\\'])|(?:\\btw\\s*`([_a-zA-Z0-9\\s\\-\\:\\/]*)`)", 8 | "typescriptreact": "(?:\\bclassName\\s*=\\s*[\\\"\\']([_a-zA-Z0-9\\s\\-\\:\\/]+)[\\\"\\'])|(?:\\btw\\s*`([_a-zA-Z0-9\\s\\-\\:\\/]*)`)" 9 | } 10 | -------------------------------------------------------------------------------- /src/sorter.json: -------------------------------------------------------------------------------- 1 | [ 2 | "container", 3 | "box-border", 4 | "box-content", 5 | "static", 6 | "fixed", 7 | "absolute", 8 | "relative", 9 | "sticky", 10 | "inset-0", 11 | "inset-x-0", 12 | "inset-y-0", 13 | "inset-x-auto", 14 | "inset-y-auto", 15 | "inset-auto", 16 | "top-0", 17 | "bottom-0", 18 | "left-0", 19 | "right-0", 20 | "top-auto", 21 | "bottom-auto", 22 | "left-auto", 23 | "right-auto", 24 | "z-0", 25 | "z-10", 26 | "z-20", 27 | "z-30", 28 | "z-40", 29 | "z-50", 30 | "z-auto", 31 | "flex", 32 | "inline-flex", 33 | "grid", 34 | "inline-grid", 35 | "table-caption", 36 | "table-column", 37 | "table-column-group", 38 | "table-footer-group", 39 | "table-header-group", 40 | "table-row-group", 41 | "flex-row", 42 | "flex-row-reverse", 43 | "flex-col", 44 | "flex-col-reverse", 45 | "flex-no-wrap", 46 | "flex-wrap", 47 | "flex-wrap-reverse", 48 | "items-stretch", 49 | "items-start", 50 | "items-center", 51 | "items-end", 52 | "items-baseline", 53 | "content-start", 54 | "content-center", 55 | "content-end", 56 | "content-between", 57 | "content-around", 58 | "self-auto", 59 | "self-start", 60 | "self-center", 61 | "self-end", 62 | "self-stretch", 63 | "justify-start", 64 | "justify-center", 65 | "justify-end", 66 | "justify-between", 67 | "justify-around", 68 | "flex-1", 69 | "flex-auto", 70 | "flex-initial", 71 | "flex-none", 72 | "flex-grow", 73 | "flex-grow-0", 74 | "flex-shrink", 75 | "flex-shrink-0", 76 | "order-first", 77 | "order-last", 78 | "order-none", 79 | "order-1", 80 | "order-2", 81 | "order-3", 82 | "order-4", 83 | "order-5", 84 | "order-6", 85 | "order-7", 86 | "order-8", 87 | "order-9", 88 | "order-10", 89 | "order-11", 90 | "order-12", 91 | "visible", 92 | "invisible", 93 | "hidden", 94 | "block", 95 | "flow-root", 96 | "inline-block", 97 | "inline", 98 | "table", 99 | "table-row", 100 | "table-cell", 101 | "clearfix", 102 | "float-left", 103 | "float-right", 104 | "float-none", 105 | "clear-right", 106 | "clear-both", 107 | "clear-none", 108 | "object-contain", 109 | "object-cover", 110 | "object-fill", 111 | "object-none", 112 | "object-scale-down", 113 | "object-bottom", 114 | "object-center", 115 | "object-left", 116 | "object-left-bottom", 117 | "object-left-top", 118 | "object-right", 119 | "object-right-bottom", 120 | "object-right-top", 121 | "object-top", 122 | "w-0", 123 | "w-1", 124 | "w-2", 125 | "w-3", 126 | "w-4", 127 | "w-5", 128 | "w-6", 129 | "w-8", 130 | "w-10", 131 | "w-12", 132 | "w-16", 133 | "w-20", 134 | "w-24", 135 | "w-32", 136 | "w-40", 137 | "w-48", 138 | "w-56", 139 | "w-64", 140 | "w-auto", 141 | "w-px", 142 | "w-1/2", 143 | "w-1/3", 144 | "w-2/3", 145 | "w-1/4", 146 | "w-2/4", 147 | "w-3/4", 148 | "w-1/5", 149 | "w-2/5", 150 | "w-3/5", 151 | "w-4/5", 152 | "w-1/6", 153 | "w-2/6", 154 | "w-3/6", 155 | "w-4/6", 156 | "w-5/6", 157 | "w-1/12", 158 | "w-2/12", 159 | "w-3/12", 160 | "w-4/12", 161 | "w-5/12", 162 | "w-6/12", 163 | "w-7/12", 164 | "w-8/12", 165 | "w-9/12", 166 | "w-10/12", 167 | "w-11/12", 168 | "w-full", 169 | "w-screen", 170 | "h-0", 171 | "h-1", 172 | "h-2", 173 | "h-3", 174 | "h-4", 175 | "h-5", 176 | "h-6", 177 | "h-8", 178 | "h-10", 179 | "h-12", 180 | "h-16", 181 | "h-20", 182 | "h-24", 183 | "h-32", 184 | "h-40", 185 | "h-48", 186 | "h-56", 187 | "h-64", 188 | "h-auto", 189 | "h-px", 190 | "h-full", 191 | "h-screen", 192 | "max-w-xs", 193 | "max-w-sm", 194 | "max-w-md", 195 | "max-w-lg", 196 | "max-w-xl", 197 | "max-w-2xl", 198 | "max-w-3xl", 199 | "max-w-4xl", 200 | "max-w-5xl", 201 | "max-w-6xl", 202 | "max-w-full", 203 | "max-w-screen-sm", 204 | "max-w-screen-md", 205 | "max-w-screen-lg", 206 | "max-w-screen-xl", 207 | "max-h-full", 208 | "max-h-screen", 209 | "min-w-0", 210 | "min-w-full", 211 | "min-h-0", 212 | "min-h-full", 213 | "min-h-screen", 214 | "grid-flow-row", 215 | "grid-flow-col", 216 | "grid-flow-row-dense", 217 | "grid-flow-col-dense", 218 | "grid-cols-1", 219 | "grid-cols-2", 220 | "grid-cols-3", 221 | "grid-cols-4", 222 | "grid-cols-5", 223 | "grid-cols-6", 224 | "grid-cols-7", 225 | "grid-cols-8", 226 | "grid-cols-9", 227 | "grid-cols-10", 228 | "grid-cols-11", 229 | "grid-cols-12", 230 | "grid-cols-none", 231 | "col-auto", 232 | "col-span-1", 233 | "col-span-2", 234 | "col-span-3", 235 | "col-span-4", 236 | "col-span-5", 237 | "col-span-6", 238 | "col-span-7", 239 | "col-span-8", 240 | "col-span-9", 241 | "col-span-10", 242 | "col-span-11", 243 | "col-span-12", 244 | "col-start-1", 245 | "col-start-2", 246 | "col-start-3", 247 | "col-start-4", 248 | "col-start-5", 249 | "col-start-6", 250 | "col-start-7", 251 | "col-start-8", 252 | "col-start-9", 253 | "col-start-10", 254 | "col-start-11", 255 | "col-start-12", 256 | "col-start-13", 257 | "col-start-auto", 258 | "col-end-1", 259 | "col-end-2", 260 | "col-end-3", 261 | "col-end-4", 262 | "col-end-5", 263 | "col-end-6", 264 | "col-end-7", 265 | "col-end-8", 266 | "col-end-9", 267 | "col-end-10", 268 | "col-end-11", 269 | "col-end-12", 270 | "col-end-13", 271 | "col-end-auto", 272 | "grid-rows-1", 273 | "grid-rows-2", 274 | "grid-rows-3", 275 | "grid-rows-4", 276 | "grid-rows-5", 277 | "grid-rows-6", 278 | "grid-rows-none", 279 | "row-auto", 280 | "row-span-1", 281 | "row-span-2", 282 | "row-span-3", 283 | "row-span-4", 284 | "row-span-5", 285 | "row-span-6", 286 | "row-start-1", 287 | "row-start-2", 288 | "row-start-3", 289 | "row-start-4", 290 | "row-start-5", 291 | "row-start-6", 292 | "row-start-7", 293 | "row-start-auto", 294 | "row-end-1", 295 | "row-end-2", 296 | "row-end-3", 297 | "row-end-4", 298 | "row-end-5", 299 | "row-end-6", 300 | "row-end-7", 301 | "row-end-auto", 302 | "gap-0", 303 | "gap-1", 304 | "gap-2", 305 | "gap-3", 306 | "gap-4", 307 | "gap-5", 308 | "gap-6", 309 | "gap-8", 310 | "gap-10", 311 | "gap-12", 312 | "gap-16", 313 | "gap-20", 314 | "gap-24", 315 | "gap-32", 316 | "gap-40", 317 | "gap-48", 318 | "gap-56", 319 | "gap-64", 320 | "gap-px", 321 | "row-gap-0", 322 | "row-gap-1", 323 | "row-gap-2", 324 | "row-gap-3", 325 | "row-gap-4", 326 | "row-gap-5", 327 | "row-gap-6", 328 | "row-gap-8", 329 | "row-gap-10", 330 | "row-gap-12", 331 | "row-gap-16", 332 | "row-gap-20", 333 | "row-gap-24", 334 | "row-gap-32", 335 | "row-gap-40", 336 | "row-gap-48", 337 | "row-gap-56", 338 | "row-gap-64", 339 | "row-gap-px", 340 | "col-gap-0", 341 | "col-gap-1", 342 | "col-gap-2", 343 | "col-gap-3", 344 | "col-gap-4", 345 | "col-gap-5", 346 | "col-gap-6", 347 | "col-gap-8", 348 | "col-gap-10", 349 | "col-gap-12", 350 | "col-gap-16", 351 | "col-gap-20", 352 | "col-gap-24", 353 | "col-gap-32", 354 | "col-gap-40", 355 | "col-gap-48", 356 | "col-gap-56", 357 | "col-gap-64", 358 | "col-gap-px", 359 | "p-0", 360 | "p-1", 361 | "p-2", 362 | "p-3", 363 | "p-4", 364 | "p-5", 365 | "p-6", 366 | "p-8", 367 | "p-10", 368 | "p-12", 369 | "p-16", 370 | "p-20", 371 | "p-24", 372 | "p-32", 373 | "p-40", 374 | "p-48", 375 | "p-56", 376 | "p-64", 377 | "p-px", 378 | "px-0", 379 | "px-1", 380 | "px-2", 381 | "px-3", 382 | "px-4", 383 | "px-5", 384 | "px-6", 385 | "px-8", 386 | "px-10", 387 | "px-12", 388 | "px-16", 389 | "px-20", 390 | "px-24", 391 | "px-32", 392 | "px-40", 393 | "px-48", 394 | "px-56", 395 | "px-64", 396 | "px-px", 397 | "py-0", 398 | "py-1", 399 | "py-2", 400 | "py-3", 401 | "py-4", 402 | "py-5", 403 | "py-6", 404 | "py-8", 405 | "py-10", 406 | "py-12", 407 | "py-16", 408 | "py-20", 409 | "py-24", 410 | "py-32", 411 | "py-40", 412 | "py-48", 413 | "py-56", 414 | "py-64", 415 | "py-px", 416 | "pt-0", 417 | "pt-1", 418 | "pt-2", 419 | "pt-3", 420 | "pt-4", 421 | "pt-5", 422 | "pt-6", 423 | "pt-8", 424 | "pt-10", 425 | "pt-12", 426 | "pt-16", 427 | "pt-20", 428 | "pt-24", 429 | "pt-32", 430 | "pt-40", 431 | "pt-48", 432 | "pt-56", 433 | "pt-64", 434 | "pt-px", 435 | "pb-0", 436 | "pb-1", 437 | "pb-2", 438 | "pb-3", 439 | "pb-4", 440 | "pb-5", 441 | "pb-6", 442 | "pb-8", 443 | "pb-10", 444 | "pb-12", 445 | "pb-16", 446 | "pb-20", 447 | "pb-24", 448 | "pb-32", 449 | "pb-40", 450 | "pb-48", 451 | "pb-56", 452 | "pb-64", 453 | "pb-px", 454 | "pl-0", 455 | "pl-1", 456 | "pl-2", 457 | "pl-3", 458 | "pl-4", 459 | "pl-5", 460 | "pl-6", 461 | "pl-8", 462 | "pl-10", 463 | "pl-12", 464 | "pl-16", 465 | "pl-20", 466 | "pl-24", 467 | "pl-32", 468 | "pl-40", 469 | "pl-48", 470 | "pl-56", 471 | "pl-64", 472 | "pl-px", 473 | "pr-0", 474 | "pr-1", 475 | "pr-2", 476 | "pr-3", 477 | "pr-4", 478 | "pr-5", 479 | "pr-6", 480 | "pr-8", 481 | "pr-10", 482 | "pr-12", 483 | "pr-16", 484 | "pr-20", 485 | "pr-24", 486 | "pr-32", 487 | "pr-40", 488 | "pr-48", 489 | "pr-56", 490 | "pr-64", 491 | "pr-px", 492 | "m-0", 493 | "m-1", 494 | "m-2", 495 | "m-3", 496 | "m-4", 497 | "m-5", 498 | "m-6", 499 | "m-8", 500 | "m-10", 501 | "m-12", 502 | "m-16", 503 | "m-20", 504 | "m-24", 505 | "m-32", 506 | "m-40", 507 | "m-48", 508 | "m-56", 509 | "m-64", 510 | "m-auto", 511 | "m-px", 512 | "mx-0", 513 | "mx-1", 514 | "mx-2", 515 | "mx-3", 516 | "mx-4", 517 | "mx-5", 518 | "mx-6", 519 | "mx-8", 520 | "mx-10", 521 | "mx-12", 522 | "mx-16", 523 | "mx-20", 524 | "mx-24", 525 | "mx-32", 526 | "mx-40", 527 | "mx-48", 528 | "mx-56", 529 | "mx-64", 530 | "mx-auto", 531 | "mx-px", 532 | "my-0", 533 | "my-1", 534 | "my-2", 535 | "my-3", 536 | "my-4", 537 | "my-5", 538 | "my-6", 539 | "my-8", 540 | "my-10", 541 | "my-12", 542 | "my-16", 543 | "my-20", 544 | "my-24", 545 | "my-32", 546 | "my-40", 547 | "my-48", 548 | "my-56", 549 | "my-64", 550 | "my-auto", 551 | "my-px", 552 | "mt-0", 553 | "mt-1", 554 | "mt-2", 555 | "mt-3", 556 | "mt-4", 557 | "mt-5", 558 | "mt-6", 559 | "mt-8", 560 | "mt-10", 561 | "mt-12", 562 | "mt-16", 563 | "mt-20", 564 | "mt-24", 565 | "mt-32", 566 | "mt-40", 567 | "mt-48", 568 | "mt-56", 569 | "mt-64", 570 | "mt-auto", 571 | "mt-px", 572 | "mb-0", 573 | "mb-1", 574 | "mb-2", 575 | "mb-3", 576 | "mb-4", 577 | "mb-5", 578 | "mb-6", 579 | "mb-8", 580 | "mb-10", 581 | "mb-12", 582 | "mb-16", 583 | "mb-20", 584 | "mb-24", 585 | "mb-32", 586 | "mb-40", 587 | "mb-48", 588 | "mb-56", 589 | "mb-64", 590 | "mb-auto", 591 | "mb-px", 592 | "ml-0", 593 | "ml-1", 594 | "ml-2", 595 | "ml-3", 596 | "ml-4", 597 | "ml-5", 598 | "ml-6", 599 | "ml-8", 600 | "ml-10", 601 | "ml-12", 602 | "ml-16", 603 | "ml-20", 604 | "ml-24", 605 | "ml-32", 606 | "ml-40", 607 | "ml-48", 608 | "ml-56", 609 | "ml-64", 610 | "ml-auto", 611 | "ml-px", 612 | "mr-0", 613 | "mr-1", 614 | "mr-2", 615 | "mr-3", 616 | "mr-4", 617 | "mr-5", 618 | "mr-6", 619 | "mr-8", 620 | "mr-10", 621 | "mr-12", 622 | "mr-16", 623 | "mr-20", 624 | "mr-24", 625 | "mr-32", 626 | "mr-40", 627 | "mr-48", 628 | "mr-56", 629 | "mr-64", 630 | "mr-auto", 631 | "mr-px", 632 | "-m-0", 633 | "-m-1", 634 | "-m-2", 635 | "-m-3", 636 | "-m-4", 637 | "-m-5", 638 | "-m-6", 639 | "-m-8", 640 | "-m-10", 641 | "-m-12", 642 | "-m-16", 643 | "-m-20", 644 | "-m-24", 645 | "-m-32", 646 | "-m-40", 647 | "-m-48", 648 | "-m-56", 649 | "-m-64", 650 | "-m-px", 651 | "-mx-0", 652 | "-mx-1", 653 | "-mx-2", 654 | "-mx-3", 655 | "-mx-4", 656 | "-mx-5", 657 | "-mx-6", 658 | "-mx-8", 659 | "-mx-10", 660 | "-mx-12", 661 | "-mx-16", 662 | "-mx-20", 663 | "-mx-24", 664 | "-mx-32", 665 | "-mx-40", 666 | "-mx-48", 667 | "-mx-56", 668 | "-mx-64", 669 | "-mx-px", 670 | "-my-0", 671 | "-my-1", 672 | "-my-2", 673 | "-my-3", 674 | "-my-4", 675 | "-my-5", 676 | "-my-6", 677 | "-my-8", 678 | "-my-10", 679 | "-my-12", 680 | "-my-16", 681 | "-my-20", 682 | "-my-24", 683 | "-my-32", 684 | "-my-40", 685 | "-my-48", 686 | "-my-56", 687 | "-my-64", 688 | "-my-px", 689 | "-mt-0", 690 | "-mt-1", 691 | "-mt-2", 692 | "-mt-3", 693 | "-mt-4", 694 | "-mt-5", 695 | "-mt-6", 696 | "-mt-8", 697 | "-mt-10", 698 | "-mt-12", 699 | "-mt-16", 700 | "-mt-20", 701 | "-mt-24", 702 | "-mt-32", 703 | "-mt-40", 704 | "-mt-48", 705 | "-mt-56", 706 | "-mt-64", 707 | "-mt-px", 708 | "-mb-0", 709 | "-mb-1", 710 | "-mb-2", 711 | "-mb-3", 712 | "-mb-4", 713 | "-mb-5", 714 | "-mb-6", 715 | "-mb-8", 716 | "-mb-10", 717 | "-mb-12", 718 | "-mb-16", 719 | "-mb-20", 720 | "-mb-24", 721 | "-mb-32", 722 | "-mb-40", 723 | "-mb-48", 724 | "-mb-56", 725 | "-mb-64", 726 | "-mb-px", 727 | "-ml-0", 728 | "-ml-1", 729 | "-ml-2", 730 | "-ml-3", 731 | "-ml-4", 732 | "-ml-5", 733 | "-ml-6", 734 | "-ml-8", 735 | "-ml-10", 736 | "-ml-12", 737 | "-ml-16", 738 | "-ml-20", 739 | "-ml-24", 740 | "-ml-32", 741 | "-ml-40", 742 | "-ml-48", 743 | "-ml-56", 744 | "-ml-64", 745 | "-ml-px", 746 | "-mr-0", 747 | "-mr-1", 748 | "-mr-2", 749 | "-mr-3", 750 | "-mr-4", 751 | "-mr-5", 752 | "-mr-6", 753 | "-mr-8", 754 | "-mr-10", 755 | "-mr-12", 756 | "-mr-16", 757 | "-mr-20", 758 | "-mr-24", 759 | "-mr-32", 760 | "-mr-40", 761 | "-mr-48", 762 | "-mr-56", 763 | "-mr-64", 764 | "-mr-px", 765 | "space-x-0", 766 | "space-x-1", 767 | "space-x-2", 768 | "space-x-3", 769 | "space-x-4", 770 | "space-x-5", 771 | "space-x-6", 772 | "space-x-8", 773 | "space-x-10", 774 | "space-x-12", 775 | "space-x-16", 776 | "space-x-20", 777 | "space-x-24", 778 | "space-x-32", 779 | "space-x-40", 780 | "space-x-48", 781 | "space-x-56", 782 | "space-x-64", 783 | "space-x-px", 784 | "-space-x-1", 785 | "-space-x-2", 786 | "-space-x-3", 787 | "-space-x-4", 788 | "-space-x-5", 789 | "-space-x-6", 790 | "-space-x-8", 791 | "-space-x-10", 792 | "-space-x-12", 793 | "-space-x-16", 794 | "-space-x-20", 795 | "-space-x-24", 796 | "-space-x-32", 797 | "-space-x-40", 798 | "-space-x-48", 799 | "-space-x-56", 800 | "-space-x-64", 801 | "-space-x-px", 802 | "space-y-0", 803 | "space-y-1", 804 | "space-y-2", 805 | "space-y-3", 806 | "space-y-4", 807 | "space-y-5", 808 | "space-y-6", 809 | "space-y-8", 810 | "space-y-10", 811 | "space-y-12", 812 | "space-y-16", 813 | "space-y-20", 814 | "space-y-24", 815 | "space-y-32", 816 | "space-y-40", 817 | "space-y-48", 818 | "space-y-56", 819 | "space-y-64", 820 | "space-y-px", 821 | "-space-y-1", 822 | "-space-y-2", 823 | "-space-y-3", 824 | "-space-y-4", 825 | "-space-y-5", 826 | "-space-y-6", 827 | "-space-y-8", 828 | "-space-y-10", 829 | "-space-y-12", 830 | "-space-y-16", 831 | "-space-y-20", 832 | "-space-y-24", 833 | "-space-y-32", 834 | "-space-y-40", 835 | "-space-y-48", 836 | "-space-y-56", 837 | "-space-y-64", 838 | "-space-y-px", 839 | "space-x-reverse", 840 | "space-y-reverse", 841 | "overflow-auto", 842 | "overflow-hidden", 843 | "overflow-visible", 844 | "overflow-scroll", 845 | "overflow-x-auto", 846 | "overflow-x-hidden", 847 | "overflow-x-visible", 848 | "overflow-x-scroll", 849 | "overflow-y-auto", 850 | "overflow-y-hidden", 851 | "overflow-y-visible", 852 | "overflow-y-scroll", 853 | "scrolling-touch", 854 | "scrolling-auto", 855 | "font-sans", 856 | "font-serif", 857 | "font-mono", 858 | "text-xs", 859 | "text-sm", 860 | "text-base", 861 | "text-lg", 862 | "text-xl", 863 | "text-2xl", 864 | "text-3xl", 865 | "text-4xl", 866 | "text-5xl", 867 | "text-6xl", 868 | "antialiased", 869 | "subpixel-antialiased", 870 | "italic", 871 | "not-italic", 872 | "font-hairline", 873 | "font-thin", 874 | "font-light", 875 | "font-normal", 876 | "font-medium", 877 | "font-semibold", 878 | "font-bold", 879 | "font-extrabold", 880 | "font-black", 881 | "leading-none", 882 | "leading-tight", 883 | "leading-snug", 884 | "leading-normal", 885 | "leading-relaxed", 886 | "leading-loose", 887 | "leading-3", 888 | "leading-4", 889 | "leading-5", 890 | "leading-6", 891 | "leading-7", 892 | "leading-8", 893 | "leading-9", 894 | "leading-10", 895 | "tracking-tighter", 896 | "tracking-tight", 897 | "tracking-normal", 898 | "tracking-wide", 899 | "tracking-wider", 900 | "tracking-widest", 901 | "prose-sm", 902 | "prose", 903 | "prose-lg", 904 | "prose-xl", 905 | "prose-2xl", 906 | "text-left", 907 | "text-center", 908 | "text-right", 909 | "text-justify", 910 | "text-transparent", 911 | "text-current", 912 | "text-black", 913 | "text-white", 914 | "text-gray-100", 915 | "text-gray-200", 916 | "text-gray-300", 917 | "text-gray-400", 918 | "text-gray-500", 919 | "text-gray-600", 920 | "text-gray-700", 921 | "text-gray-800", 922 | "text-gray-900", 923 | "text-red-100", 924 | "text-red-200", 925 | "text-red-300", 926 | "text-red-400", 927 | "text-red-500", 928 | "text-red-600", 929 | "text-red-700", 930 | "text-red-800", 931 | "text-red-900", 932 | "text-orange-100", 933 | "text-orange-200", 934 | "text-orange-300", 935 | "text-orange-400", 936 | "text-orange-500", 937 | "text-orange-600", 938 | "text-orange-700", 939 | "text-orange-800", 940 | "text-orange-900", 941 | "text-yellow-100", 942 | "text-yellow-200", 943 | "text-yellow-300", 944 | "text-yellow-400", 945 | "text-yellow-500", 946 | "text-yellow-600", 947 | "text-yellow-700", 948 | "text-yellow-800", 949 | "text-yellow-900", 950 | "text-green-100", 951 | "text-green-200", 952 | "text-green-300", 953 | "text-green-400", 954 | "text-green-500", 955 | "text-green-600", 956 | "text-green-700", 957 | "text-green-800", 958 | "text-green-900", 959 | "text-teal-100", 960 | "text-teal-200", 961 | "text-teal-300", 962 | "text-teal-400", 963 | "text-teal-500", 964 | "text-teal-600", 965 | "text-teal-700", 966 | "text-teal-800", 967 | "text-teal-900", 968 | "text-blue-100", 969 | "text-blue-200", 970 | "text-blue-300", 971 | "text-blue-400", 972 | "text-blue-500", 973 | "text-blue-600", 974 | "text-blue-700", 975 | "text-blue-800", 976 | "text-blue-900", 977 | "text-indigo-100", 978 | "text-indigo-200", 979 | "text-indigo-300", 980 | "text-indigo-400", 981 | "text-indigo-500", 982 | "text-indigo-600", 983 | "text-indigo-700", 984 | "text-indigo-800", 985 | "text-indigo-900", 986 | "text-purple-100", 987 | "text-purple-200", 988 | "text-purple-300", 989 | "text-purple-400", 990 | "text-purple-500", 991 | "text-purple-600", 992 | "text-purple-700", 993 | "text-purple-800", 994 | "text-purple-900", 995 | "text-pink-100", 996 | "text-pink-200", 997 | "text-pink-300", 998 | "text-pink-400", 999 | "text-pink-500", 1000 | "text-pink-600", 1001 | "text-pink-700", 1002 | "text-pink-800", 1003 | "text-pink-900", 1004 | "text-opacity-0", 1005 | "text-opacity-25", 1006 | "text-opacity-50", 1007 | "text-opacity-75", 1008 | "text-opacity-100", 1009 | "placeholder-transparent", 1010 | "placeholder-current", 1011 | "placeholder-black", 1012 | "placeholder-white", 1013 | "placeholder-gray-100", 1014 | "placeholder-gray-200", 1015 | "placeholder-gray-300", 1016 | "placeholder-gray-400", 1017 | "placeholder-gray-500", 1018 | "placeholder-gray-600", 1019 | "placeholder-gray-700", 1020 | "placeholder-gray-800", 1021 | "placeholder-gray-900", 1022 | "placeholder-red-100", 1023 | "placeholder-red-200", 1024 | "placeholder-red-300", 1025 | "placeholder-red-400", 1026 | "placeholder-red-500", 1027 | "placeholder-red-600", 1028 | "placeholder-red-700", 1029 | "placeholder-red-800", 1030 | "placeholder-red-900", 1031 | "placeholder-orange-100", 1032 | "placeholder-orange-200", 1033 | "placeholder-orange-300", 1034 | "placeholder-orange-400", 1035 | "placeholder-orange-500", 1036 | "placeholder-orange-600", 1037 | "placeholder-orange-700", 1038 | "placeholder-orange-800", 1039 | "placeholder-orange-900", 1040 | "placeholder-yellow-100", 1041 | "placeholder-yellow-200", 1042 | "placeholder-yellow-300", 1043 | "placeholder-yellow-400", 1044 | "placeholder-yellow-500", 1045 | "placeholder-yellow-600", 1046 | "placeholder-yellow-700", 1047 | "placeholder-yellow-800", 1048 | "placeholder-yellow-900", 1049 | "placeholder-green-100", 1050 | "placeholder-green-200", 1051 | "placeholder-green-300", 1052 | "placeholder-green-400", 1053 | "placeholder-green-500", 1054 | "placeholder-green-600", 1055 | "placeholder-green-700", 1056 | "placeholder-green-800", 1057 | "placeholder-green-900", 1058 | "placeholder-teal-100", 1059 | "placeholder-teal-200", 1060 | "placeholder-teal-300", 1061 | "placeholder-teal-400", 1062 | "placeholder-teal-500", 1063 | "placeholder-teal-600", 1064 | "placeholder-teal-700", 1065 | "placeholder-teal-800", 1066 | "placeholder-teal-900", 1067 | "placeholder-blue-100", 1068 | "placeholder-blue-200", 1069 | "placeholder-blue-300", 1070 | "placeholder-blue-400", 1071 | "placeholder-blue-500", 1072 | "placeholder-blue-600", 1073 | "placeholder-blue-700", 1074 | "placeholder-blue-800", 1075 | "placeholder-blue-900", 1076 | "placeholder-indigo-100", 1077 | "placeholder-indigo-200", 1078 | "placeholder-indigo-300", 1079 | "placeholder-indigo-400", 1080 | "placeholder-indigo-500", 1081 | "placeholder-indigo-600", 1082 | "placeholder-indigo-700", 1083 | "placeholder-indigo-800", 1084 | "placeholder-indigo-900", 1085 | "placeholder-purple-100", 1086 | "placeholder-purple-200", 1087 | "placeholder-purple-300", 1088 | "placeholder-purple-400", 1089 | "placeholder-purple-500", 1090 | "placeholder-purple-600", 1091 | "placeholder-purple-700", 1092 | "placeholder-purple-800", 1093 | "placeholder-purple-900", 1094 | "placeholder-pink-100", 1095 | "placeholder-pink-200", 1096 | "placeholder-pink-300", 1097 | "placeholder-pink-400", 1098 | "placeholder-pink-500", 1099 | "placeholder-pink-600", 1100 | "placeholder-pink-700", 1101 | "placeholder-pink-800", 1102 | "placeholder-pink-900", 1103 | "placeholder-opacity-0", 1104 | "placeholder-opacity-25", 1105 | "placeholder-opacity-50", 1106 | "placeholder-opacity-75", 1107 | "placeholder-opacity-100", 1108 | "placeholder-left", 1109 | "placeholder-center", 1110 | "placeholder-right", 1111 | "placeholder-justify", 1112 | "underline", 1113 | "line-through", 1114 | "no-underline", 1115 | "uppercase", 1116 | "lowercase", 1117 | "capitalize", 1118 | "normal-case", 1119 | "break-normal", 1120 | "break-words", 1121 | "break-all", 1122 | "truncate", 1123 | "whitespace-normal", 1124 | "whitespace-no-wrap", 1125 | "whitespace-pre", 1126 | "whitespace-pre-line", 1127 | "whitespace-pre-wrap", 1128 | "align-baseline", 1129 | "align-top", 1130 | "align-middle", 1131 | "align-bottom", 1132 | "align-text-top", 1133 | "align-text-bottom", 1134 | "list-none", 1135 | "list-disc", 1136 | "list-decimal", 1137 | "list-inside", 1138 | "list-outside", 1139 | "transition-none", 1140 | "transition-all", 1141 | "transition", 1142 | "transition-colors", 1143 | "transition-opacity", 1144 | "transition-shadow", 1145 | "transition-transform", 1146 | "duration-75", 1147 | "duration-100", 1148 | "duration-150", 1149 | "duration-200", 1150 | "duration-300", 1151 | "duration-500", 1152 | "duration-700", 1153 | "duration-1000", 1154 | "ease-linear", 1155 | "ease-in", 1156 | "ease-out", 1157 | "ease-in-out", 1158 | "delay-75", 1159 | "delay-100", 1160 | "delay-150", 1161 | "delay-200", 1162 | "delay-300", 1163 | "delay-500", 1164 | "delay-700", 1165 | "delay-1000", 1166 | "origin-center", 1167 | "origin-top", 1168 | "origin-top-right", 1169 | "origin-right", 1170 | "origin-bottom-right", 1171 | "origin-bottom", 1172 | "origin-bottom-left", 1173 | "origin-left", 1174 | "origin-top-left", 1175 | "transform", 1176 | "scale-0", 1177 | "scale-50", 1178 | "scale-75", 1179 | "scale-90", 1180 | "scale-95", 1181 | "scale-100", 1182 | "scale-105", 1183 | "scale-110", 1184 | "scale-125", 1185 | "scale-150", 1186 | "scale-x-0", 1187 | "scale-x-50", 1188 | "scale-x-75", 1189 | "scale-x-90", 1190 | "scale-x-95", 1191 | "scale-x-100", 1192 | "scale-x-105", 1193 | "scale-x-110", 1194 | "scale-x-125", 1195 | "scale-x-150", 1196 | "scale-y-0", 1197 | "scale-y-50", 1198 | "scale-y-75", 1199 | "scale-y-90", 1200 | "scale-y-95", 1201 | "scale-y-100", 1202 | "scale-y-105", 1203 | "scale-y-110", 1204 | "scale-y-125", 1205 | "scale-y-150", 1206 | "rotate-0", 1207 | "rotate-45", 1208 | "rotate-90", 1209 | "rotate-180", 1210 | "-rotate-180", 1211 | "-rotate-90", 1212 | "-rotate-45", 1213 | "translate-x-0", 1214 | "translate-x-1", 1215 | "translate-x-2", 1216 | "translate-x-3", 1217 | "translate-x-4", 1218 | "translate-x-5", 1219 | "translate-x-6", 1220 | "translate-x-8", 1221 | "translate-x-10", 1222 | "translate-x-12", 1223 | "translate-x-16", 1224 | "translate-x-20", 1225 | "translate-x-24", 1226 | "translate-x-32", 1227 | "translate-x-40", 1228 | "translate-x-48", 1229 | "translate-x-56", 1230 | "translate-x-64", 1231 | "translate-x-px", 1232 | "-translate-x-1", 1233 | "-translate-x-2", 1234 | "-translate-x-3", 1235 | "-translate-x-4", 1236 | "-translate-x-5", 1237 | "-translate-x-6", 1238 | "-translate-x-8", 1239 | "-translate-x-10", 1240 | "-translate-x-12", 1241 | "-translate-x-16", 1242 | "-translate-x-20", 1243 | "-translate-x-24", 1244 | "-translate-x-32", 1245 | "-translate-x-40", 1246 | "-translate-x-48", 1247 | "-translate-x-56", 1248 | "-translate-x-64", 1249 | "-translate-x-px", 1250 | "-translate-x-full", 1251 | "-translate-x-1/2", 1252 | "translate-x-1/2", 1253 | "translate-x-full", 1254 | "translate-y-0", 1255 | "translate-y-1", 1256 | "translate-y-2", 1257 | "translate-y-3", 1258 | "translate-y-4", 1259 | "translate-y-5", 1260 | "translate-y-6", 1261 | "translate-y-8", 1262 | "translate-y-10", 1263 | "translate-y-12", 1264 | "translate-y-16", 1265 | "translate-y-20", 1266 | "translate-y-24", 1267 | "translate-y-32", 1268 | "translate-y-40", 1269 | "translate-y-48", 1270 | "translate-y-56", 1271 | "translate-y-64", 1272 | "translate-y-px", 1273 | "-translate-y-1", 1274 | "-translate-y-2", 1275 | "-translate-y-3", 1276 | "-translate-y-4", 1277 | "-translate-y-5", 1278 | "-translate-y-6", 1279 | "-translate-y-8", 1280 | "-translate-y-10", 1281 | "-translate-y-12", 1282 | "-translate-y-16", 1283 | "-translate-y-20", 1284 | "-translate-y-24", 1285 | "-translate-y-32", 1286 | "-translate-y-40", 1287 | "-translate-y-48", 1288 | "-translate-y-56", 1289 | "-translate-y-64", 1290 | "-translate-y-px", 1291 | "-translate-y-full", 1292 | "-translate-y-1/2", 1293 | "translate-y-1/2", 1294 | "translate-y-full", 1295 | "skew-x-0", 1296 | "skew-x-3", 1297 | "skew-x-6", 1298 | "skew-x-12", 1299 | "-skew-x-12", 1300 | "-skew-x-6", 1301 | "-skew-x-3", 1302 | "skew-y-0", 1303 | "skew-y-3", 1304 | "skew-y-6", 1305 | "skew-y-12", 1306 | "-skew-y-12", 1307 | "-skew-y-6", 1308 | "-skew-y-3", 1309 | "bg-fixed", 1310 | "bg-local", 1311 | "bg-scroll", 1312 | "bg-transparent", 1313 | "bg-current", 1314 | "bg-black", 1315 | "bg-white", 1316 | "bg-gray-100", 1317 | "bg-gray-200", 1318 | "bg-gray-300", 1319 | "bg-gray-400", 1320 | "bg-gray-500", 1321 | "bg-gray-600", 1322 | "bg-gray-700", 1323 | "bg-gray-800", 1324 | "bg-gray-900", 1325 | "bg-red-100", 1326 | "bg-red-200", 1327 | "bg-red-300", 1328 | "bg-red-400", 1329 | "bg-red-500", 1330 | "bg-red-600", 1331 | "bg-red-700", 1332 | "bg-red-800", 1333 | "bg-red-900", 1334 | "bg-orange-100", 1335 | "bg-orange-200", 1336 | "bg-orange-300", 1337 | "bg-orange-400", 1338 | "bg-orange-500", 1339 | "bg-orange-600", 1340 | "bg-orange-700", 1341 | "bg-orange-800", 1342 | "bg-orange-900", 1343 | "bg-yellow-100", 1344 | "bg-yellow-200", 1345 | "bg-yellow-300", 1346 | "bg-yellow-400", 1347 | "bg-yellow-500", 1348 | "bg-yellow-600", 1349 | "bg-yellow-700", 1350 | "bg-yellow-800", 1351 | "bg-yellow-900", 1352 | "bg-green-100", 1353 | "bg-green-200", 1354 | "bg-green-300", 1355 | "bg-green-400", 1356 | "bg-green-500", 1357 | "bg-green-600", 1358 | "bg-green-700", 1359 | "bg-green-800", 1360 | "bg-green-900", 1361 | "bg-teal-100", 1362 | "bg-teal-200", 1363 | "bg-teal-300", 1364 | "bg-teal-400", 1365 | "bg-teal-500", 1366 | "bg-teal-600", 1367 | "bg-teal-700", 1368 | "bg-teal-800", 1369 | "bg-teal-900", 1370 | "bg-blue-100", 1371 | "bg-blue-200", 1372 | "bg-blue-300", 1373 | "bg-blue-400", 1374 | "bg-blue-500", 1375 | "bg-blue-600", 1376 | "bg-blue-700", 1377 | "bg-blue-800", 1378 | "bg-blue-900", 1379 | "bg-indigo-100", 1380 | "bg-indigo-200", 1381 | "bg-indigo-300", 1382 | "bg-indigo-400", 1383 | "bg-indigo-500", 1384 | "bg-indigo-600", 1385 | "bg-indigo-700", 1386 | "bg-indigo-800", 1387 | "bg-indigo-900", 1388 | "bg-purple-100", 1389 | "bg-purple-200", 1390 | "bg-purple-300", 1391 | "bg-purple-400", 1392 | "bg-purple-500", 1393 | "bg-purple-600", 1394 | "bg-purple-700", 1395 | "bg-purple-800", 1396 | "bg-purple-900", 1397 | "bg-pink-100", 1398 | "bg-pink-200", 1399 | "bg-pink-300", 1400 | "bg-pink-400", 1401 | "bg-pink-500", 1402 | "bg-pink-600", 1403 | "bg-pink-700", 1404 | "bg-pink-800", 1405 | "bg-pink-900", 1406 | "bg-opacity-0", 1407 | "bg-opacity-25", 1408 | "bg-opacity-50", 1409 | "bg-opacity-75", 1410 | "bg-opacity-100", 1411 | "bg-bottom", 1412 | "bg-center", 1413 | "bg-left", 1414 | "bg-left-bottom", 1415 | "bg-left-top", 1416 | "bg-right", 1417 | "bg-right-bottom", 1418 | "bg-right-top", 1419 | "bg-top", 1420 | "bg-repeat", 1421 | "bg-no-repeat", 1422 | "bg-repeat-x", 1423 | "bg-repeat-y", 1424 | "bg-repeat-round", 1425 | "bg-repeat-space", 1426 | "bg-auto", 1427 | "bg-cover", 1428 | "bg-contain", 1429 | "border", 1430 | "border-0", 1431 | "border-2", 1432 | "border-4", 1433 | "border-8", 1434 | "border-t", 1435 | "border-t-0", 1436 | "border-t-2", 1437 | "border-t-4", 1438 | "border-t-8", 1439 | "border-b", 1440 | "border-b-0", 1441 | "border-b-2", 1442 | "border-b-4", 1443 | "border-b-8", 1444 | "border-l", 1445 | "border-l-0", 1446 | "border-l-2", 1447 | "border-l-4", 1448 | "border-l-8", 1449 | "border-r", 1450 | "border-r-0", 1451 | "border-r-2", 1452 | "border-r-4", 1453 | "border-r-8", 1454 | "border-collapse", 1455 | "border-separate", 1456 | "border-transparent", 1457 | "border-current", 1458 | "border-black", 1459 | "border-white", 1460 | "border-gray-100", 1461 | "border-gray-200", 1462 | "border-gray-300", 1463 | "border-gray-400", 1464 | "border-gray-500", 1465 | "border-gray-600", 1466 | "border-gray-700", 1467 | "border-gray-800", 1468 | "border-gray-900", 1469 | "border-red-100", 1470 | "border-red-200", 1471 | "border-red-300", 1472 | "border-red-400", 1473 | "border-red-500", 1474 | "border-red-600", 1475 | "border-red-700", 1476 | "border-red-800", 1477 | "border-red-900", 1478 | "border-orange-100", 1479 | "border-orange-200", 1480 | "border-orange-300", 1481 | "border-orange-400", 1482 | "border-orange-500", 1483 | "border-orange-600", 1484 | "border-orange-700", 1485 | "border-orange-800", 1486 | "border-orange-900", 1487 | "border-yellow-100", 1488 | "border-yellow-200", 1489 | "border-yellow-300", 1490 | "border-yellow-400", 1491 | "border-yellow-500", 1492 | "border-yellow-600", 1493 | "border-yellow-700", 1494 | "border-yellow-800", 1495 | "border-yellow-900", 1496 | "border-green-100", 1497 | "border-green-200", 1498 | "border-green-300", 1499 | "border-green-400", 1500 | "border-green-500", 1501 | "border-green-600", 1502 | "border-green-700", 1503 | "border-green-800", 1504 | "border-green-900", 1505 | "border-teal-100", 1506 | "border-teal-200", 1507 | "border-teal-300", 1508 | "border-teal-400", 1509 | "border-teal-500", 1510 | "border-teal-600", 1511 | "border-teal-700", 1512 | "border-teal-800", 1513 | "border-teal-900", 1514 | "border-blue-100", 1515 | "border-blue-200", 1516 | "border-blue-300", 1517 | "border-blue-400", 1518 | "border-blue-500", 1519 | "border-blue-600", 1520 | "border-blue-700", 1521 | "border-blue-800", 1522 | "border-blue-900", 1523 | "border-indigo-100", 1524 | "border-indigo-200", 1525 | "border-indigo-300", 1526 | "border-indigo-400", 1527 | "border-indigo-500", 1528 | "border-indigo-600", 1529 | "border-indigo-700", 1530 | "border-indigo-800", 1531 | "border-indigo-900", 1532 | "border-purple-100", 1533 | "border-purple-200", 1534 | "border-purple-300", 1535 | "border-purple-400", 1536 | "border-purple-500", 1537 | "border-purple-600", 1538 | "border-purple-700", 1539 | "border-purple-800", 1540 | "border-purple-900", 1541 | "border-pink-100", 1542 | "border-pink-200", 1543 | "border-pink-300", 1544 | "border-pink-400", 1545 | "border-pink-500", 1546 | "border-pink-600", 1547 | "border-pink-700", 1548 | "border-pink-800", 1549 | "border-pink-900", 1550 | "border-opacity-0", 1551 | "border-opacity-25", 1552 | "border-opacity-50", 1553 | "border-opacity-75", 1554 | "border-opacity-100", 1555 | "border-solid", 1556 | "border-dashed", 1557 | "border-dotted", 1558 | "border-double", 1559 | "border-none", 1560 | "divide-x-0", 1561 | "divide-x-2", 1562 | "divide-x-4", 1563 | "divide-x-8", 1564 | "divide-x", 1565 | "divide-y-0", 1566 | "divide-y-2", 1567 | "divide-y-4", 1568 | "divide-y-8", 1569 | "divide-y", 1570 | "divide-x-reverse", 1571 | "divide-y-reverse", 1572 | "divide-transparent", 1573 | "divide-current", 1574 | "divide-black", 1575 | "divide-white", 1576 | "divide-gray-100", 1577 | "divide-gray-200", 1578 | "divide-gray-300", 1579 | "divide-gray-400", 1580 | "divide-gray-500", 1581 | "divide-gray-600", 1582 | "divide-gray-700", 1583 | "divide-gray-800", 1584 | "divide-gray-900", 1585 | "divide-red-100", 1586 | "divide-red-200", 1587 | "divide-red-300", 1588 | "divide-red-400", 1589 | "divide-red-500", 1590 | "divide-red-600", 1591 | "divide-red-700", 1592 | "divide-red-800", 1593 | "divide-red-900", 1594 | "divide-orange-100", 1595 | "divide-orange-200", 1596 | "divide-orange-300", 1597 | "divide-orange-400", 1598 | "divide-orange-500", 1599 | "divide-orange-600", 1600 | "divide-orange-700", 1601 | "divide-orange-800", 1602 | "divide-orange-900", 1603 | "divide-yellow-100", 1604 | "divide-yellow-200", 1605 | "divide-yellow-300", 1606 | "divide-yellow-400", 1607 | "divide-yellow-500", 1608 | "divide-yellow-600", 1609 | "divide-yellow-700", 1610 | "divide-yellow-800", 1611 | "divide-yellow-900", 1612 | "divide-green-100", 1613 | "divide-green-200", 1614 | "divide-green-300", 1615 | "divide-green-400", 1616 | "divide-green-500", 1617 | "divide-green-600", 1618 | "divide-green-700", 1619 | "divide-green-800", 1620 | "divide-green-900", 1621 | "divide-teal-100", 1622 | "divide-teal-200", 1623 | "divide-teal-300", 1624 | "divide-teal-400", 1625 | "divide-teal-500", 1626 | "divide-teal-600", 1627 | "divide-teal-700", 1628 | "divide-teal-800", 1629 | "divide-teal-900", 1630 | "divide-blue-100", 1631 | "divide-blue-200", 1632 | "divide-blue-300", 1633 | "divide-blue-400", 1634 | "divide-blue-500", 1635 | "divide-blue-600", 1636 | "divide-blue-700", 1637 | "divide-blue-800", 1638 | "divide-blue-900", 1639 | "divide-indigo-100", 1640 | "divide-indigo-200", 1641 | "divide-indigo-300", 1642 | "divide-indigo-400", 1643 | "divide-indigo-500", 1644 | "divide-indigo-600", 1645 | "divide-indigo-700", 1646 | "divide-indigo-800", 1647 | "divide-indigo-900", 1648 | "divide-purple-100", 1649 | "divide-purple-200", 1650 | "divide-purple-300", 1651 | "divide-purple-400", 1652 | "divide-purple-500", 1653 | "divide-purple-600", 1654 | "divide-purple-700", 1655 | "divide-purple-800", 1656 | "divide-purple-900", 1657 | "divide-pink-100", 1658 | "divide-pink-200", 1659 | "divide-pink-300", 1660 | "divide-pink-400", 1661 | "divide-pink-500", 1662 | "divide-pink-600", 1663 | "divide-pink-700", 1664 | "divide-pink-800", 1665 | "divide-pink-900", 1666 | "rounded-none", 1667 | "rounded-sm", 1668 | "rounded", 1669 | "rounded-md", 1670 | "rounded-lg", 1671 | "rounded-full", 1672 | "rounded-t-none", 1673 | "rounded-t-sm", 1674 | "rounded-t", 1675 | "rounded-t-lg", 1676 | "rounded-t-full", 1677 | "rounded-b-none", 1678 | "rounded-b-sm", 1679 | "rounded-b", 1680 | "rounded-b-lg", 1681 | "rounded-b-full", 1682 | "rounded-l-none", 1683 | "rounded-l-sm", 1684 | "rounded-l", 1685 | "rounded-l-lg", 1686 | "rounded-l-full", 1687 | "rounded-r-none", 1688 | "rounded-r-sm", 1689 | "rounded-r", 1690 | "rounded-r-lg", 1691 | "rounded-r-full", 1692 | "rounded-tl-none", 1693 | "rounded-tl-sm", 1694 | "rounded-tl", 1695 | "rounded-tl-lg", 1696 | "rounded-tl-full", 1697 | "rounded-tr-none", 1698 | "rounded-tr-sm", 1699 | "rounded-tr", 1700 | "rounded-tr-lg", 1701 | "rounded-tr-full", 1702 | "rounded-bl-none", 1703 | "rounded-bl-sm", 1704 | "rounded-bl", 1705 | "rounded-bl-lg", 1706 | "rounded-bl-full", 1707 | "rounded-br-none", 1708 | "rounded-br-sm", 1709 | "rounded-br", 1710 | "rounded-br-lg", 1711 | "rounded-br-full", 1712 | "shadow-xs", 1713 | "shadow-sm", 1714 | "shadow", 1715 | "shadow-md", 1716 | "shadow-lg", 1717 | "shadow-xl", 1718 | "shadow-2xl", 1719 | "shadow-inner", 1720 | "shadow-outline", 1721 | "shadow-none", 1722 | "outline-none", 1723 | "opacity-0", 1724 | "opacity-25", 1725 | "opacity-50", 1726 | "opacity-75", 1727 | "opacity-100", 1728 | "table-auto", 1729 | "table-fixed", 1730 | "appearance-none", 1731 | "cursor-auto", 1732 | "cursor-default", 1733 | "cursor-pointer", 1734 | "cursor-wait", 1735 | "cursor-move", 1736 | "cursor-not-allowed", 1737 | "pointer-events-none", 1738 | "pointer-events-auto", 1739 | "resize-none", 1740 | "resize", 1741 | "resize-x", 1742 | "resize-y", 1743 | "select-none", 1744 | "select-text", 1745 | "select-all", 1746 | "select-auto", 1747 | "sr-only", 1748 | "not-sr-only", 1749 | "fill-current", 1750 | "stroke-current", 1751 | "stroke-0", 1752 | "stroke-1", 1753 | "stroke-2", 1754 | "clear-left" 1755 | ] 1756 | -------------------------------------------------------------------------------- /src/utils/sort.js: -------------------------------------------------------------------------------- 1 | const sortClassArray = (classArray, sortOrder) => [ 2 | ...classArray.filter((el) => sortOrder.indexOf(el) === -1), 3 | ...classArray 4 | .filter((el) => sortOrder.indexOf(el) !== -1) 5 | .sort((a, b) => sortOrder.indexOf(a) - sortOrder.indexOf(b)) 6 | ] 7 | 8 | const removeDuplicates = (classArray) => [...new Set(classArray)] 9 | 10 | export const sortClassString = (classString, sortOrder, { shouldRemoveDuplicates = false } = {}) => { 11 | let classArray = classString.split(/\s+/g) 12 | 13 | if (shouldRemoveDuplicates) { 14 | classArray = removeDuplicates(classArray) 15 | } 16 | 17 | classArray = sortClassArray(classArray, sortOrder) 18 | return classArray.join(' ') 19 | } 20 | 21 | export const sortClassInText = (text, regex, classSorter, { removeDuplicates = true } = {}) => { 22 | let classWrapper 23 | while ((classWrapper = regex.exec(text)) !== null) { 24 | const wrapperMatch = classWrapper[0] 25 | const valueMatchIndex = classWrapper.findIndex((match, idx) => idx !== 0 && match) 26 | const valueMatch = classWrapper[valueMatchIndex] 27 | 28 | const startPosition = classWrapper.index + wrapperMatch.lastIndexOf(valueMatch) 29 | const endPosition = startPosition + valueMatch.length 30 | 31 | const sortedClasses = sortClassString(text.substring(startPosition, endPosition), classSorter, { 32 | shouldRemoveDuplicates: removeDuplicates 33 | }) 34 | 35 | const beforeClass = text.substring(0, startPosition) 36 | const afterClass = text.substring(endPosition) 37 | text = `${beforeClass}${sortedClasses}${afterClass}` 38 | } 39 | 40 | return text 41 | } 42 | -------------------------------------------------------------------------------- /test/mocks/babel/default_behaviour_formatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/babel/default_behaviour_unformatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/babel/no_duplicate_unknown_formatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/babel/no_duplicate_unknown_unformatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/babel/no_remove_duplicate_formatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/babel/no_remove_duplicate_unformatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/babel/remove_duplicate_formatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/babel/remove_duplicate_unformatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/css/default_behaviour_formatted.css: -------------------------------------------------------------------------------- 1 | a { 2 | @apply flex items-center justify-between h-16 max-w-6xl mx-auto; 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/css/default_behaviour_unformatted.css: -------------------------------------------------------------------------------- 1 | a { 2 | @apply mx-auto flex justify-between items-center max-w-6xl h-16; 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/css/no_duplicate_unknown_formatted.css: -------------------------------------------------------------------------------- 1 | a { 2 | @apply unknown; 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/css/no_duplicate_unknown_unformatted.css: -------------------------------------------------------------------------------- 1 | a { 2 | @apply unknown; 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/css/no_remove_duplicate_formatted.css: -------------------------------------------------------------------------------- 1 | a { 2 | @apply dupplicate dupplicate; 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/css/no_remove_duplicate_unformatted.css: -------------------------------------------------------------------------------- 1 | a { 2 | @apply dupplicate dupplicate; 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/css/remove_duplicate_formatted.css: -------------------------------------------------------------------------------- 1 | a { 2 | @apply dupplicate; 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/css/remove_duplicate_unformatted.css: -------------------------------------------------------------------------------- 1 | a { 2 | @apply dupplicate dupplicate; 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/customRegex.json: -------------------------------------------------------------------------------- 1 | { 2 | "html": "\\bmy-custom-attribute\\s*=\\s*[\\\"\\']([_a-zA-Z0-9\\s\\-\\:\\/]+)[\\\"\\']" 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/flow/default_behaviour_formatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/flow/default_behaviour_unformatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/flow/no_duplicate_unknown_formatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/flow/no_duplicate_unknown_unformatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/flow/no_remove_duplicate_formatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/flow/no_remove_duplicate_unformatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/flow/remove_duplicate_formatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/flow/remove_duplicate_unformatted.js: -------------------------------------------------------------------------------- 1 | function App() { 2 | render(
) 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/html/custom_regex_formatted.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /test/mocks/html/custom_regex_unformatted.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /test/mocks/html/default_behaviour_formatted.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /test/mocks/html/default_behaviour_unformatted.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /test/mocks/html/no_duplicate_unknown_formatted.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /test/mocks/html/no_duplicate_unknown_unformatted.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /test/mocks/html/no_remove_duplicate_formatted.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /test/mocks/html/no_remove_duplicate_unformatted.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /test/mocks/html/remove_duplicate_formatted.html: -------------------------------------------------------------------------------- 1 |

2 | -------------------------------------------------------------------------------- /test/mocks/html/remove_duplicate_unformatted.html: -------------------------------------------------------------------------------- 1 |

2 | -------------------------------------------------------------------------------- /test/mocks/less/default_behaviour_formatted.less: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply flex items-center justify-between h-16 max-w-6xl mx-auto; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/less/default_behaviour_unformatted.less: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply mx-auto flex justify-between items-center max-w-6xl h-16; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/less/no_duplicate_unknown_formatted.less: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply unknown; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/less/no_duplicate_unknown_unformatted.less: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply unknown; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/less/no_remove_duplicate_formatted.less: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply dupplicate dupplicate; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/less/no_remove_duplicate_unformatted.less: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply dupplicate dupplicate; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/less/remove_duplicate_formatted.less: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply dupplicate; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/less/remove_duplicate_unformatted.less: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply dupplicate dupplicate; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/regexMalformed.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "value" 3 | } 4 | -------------------------------------------------------------------------------- /test/mocks/scss/default_behaviour_formatted.scss: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply flex items-center justify-between h-16 max-w-6xl mx-auto; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/scss/default_behaviour_unformatted.scss: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply mx-auto flex justify-between items-center max-w-6xl h-16; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/scss/no_duplicate_unknown_formatted.scss: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply unknown; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/scss/no_duplicate_unknown_unformatted.scss: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply unknown; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/scss/no_remove_duplicate_formatted.scss: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply dupplicate dupplicate; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/scss/no_remove_duplicate_unformatted.scss: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply dupplicate dupplicate; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/scss/remove_duplicate_formatted.scss: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply dupplicate; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/scss/remove_duplicate_unformatted.scss: -------------------------------------------------------------------------------- 1 | div { 2 | a { 3 | @apply dupplicate dupplicate; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mocks/sorterMalformed.json: -------------------------------------------------------------------------------- 1 | 1234 2 | -------------------------------------------------------------------------------- /test/mocks/typescript/default_behaviour_formatted.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react' 2 | 3 | const App: FC = () => { 4 | return

5 | } 6 | export default App 7 | -------------------------------------------------------------------------------- /test/mocks/typescript/default_behaviour_unformatted.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react' 2 | 3 | const App: FC = () => { 4 | return
5 | } 6 | export default App 7 | -------------------------------------------------------------------------------- /test/mocks/typescript/no_duplicate_unknown_formatted.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react' 2 | 3 | const App: FC = () => { 4 | return
5 | } 6 | export default App 7 | -------------------------------------------------------------------------------- /test/mocks/typescript/no_duplicate_unknown_unformatted.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react' 2 | 3 | const App: FC = () => { 4 | return
5 | } 6 | export default App 7 | -------------------------------------------------------------------------------- /test/mocks/typescript/no_remove_duplicate_formatted.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react' 2 | 3 | const App: FC = () => { 4 | return
5 | } 6 | export default App 7 | -------------------------------------------------------------------------------- /test/mocks/typescript/no_remove_duplicate_unformatted.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react' 2 | 3 | const App: FC = () => { 4 | return
5 | } 6 | export default App 7 | -------------------------------------------------------------------------------- /test/mocks/typescript/remove_duplicate_formatted.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react' 2 | 3 | const App: FC = () => { 4 | return
5 | } 6 | export default App 7 | -------------------------------------------------------------------------------- /test/mocks/typescript/remove_duplicate_unformatted.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react' 2 | 3 | const App: FC = () => { 4 | return
5 | } 6 | export default App 7 | -------------------------------------------------------------------------------- /test/mocks/vue/default_behaviour_formatted.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /test/mocks/vue/default_behaviour_unformatted.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /test/mocks/vue/no_duplicate_unknown_formatted.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /test/mocks/vue/no_duplicate_unknown_unformatted.vue: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /test/mocks/vue/no_remove_duplicate_formatted.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /test/mocks/vue/no_remove_duplicate_unformatted.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /test/mocks/vue/remove_duplicate_formatted.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /test/mocks/vue/remove_duplicate_unformatted.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /test/plugin.js: -------------------------------------------------------------------------------- 1 | import prettier from 'prettier' 2 | import plugin from '../src/' 3 | import fs from 'fs' 4 | import prettierOptions from '../.prettierrc.json' 5 | 6 | function testOnLanguage(identifier, language, parser, options = {}) { 7 | const unformatted = fs.readFileSync(`${__dirname}/mocks/${parser}/${identifier}_unformatted.${language}`, 'utf8') 8 | const formatted = fs.readFileSync(`${__dirname}/mocks/${parser}/${identifier}_formatted.${language}`, 'utf8') 9 | const output = prettier.format(unformatted, { 10 | parser, 11 | plugins: [plugin], 12 | ...prettierOptions, 13 | ...options 14 | }) 15 | expect(output).toEqual(formatted) 16 | } 17 | 18 | it('should sort classes correctly', () => { 19 | testOnLanguage('default_behaviour', 'html', 'html') 20 | testOnLanguage('default_behaviour', 'js', 'babel') 21 | testOnLanguage('default_behaviour', 'js', 'flow') 22 | testOnLanguage('default_behaviour', 'tsx', 'typescript') 23 | testOnLanguage('default_behaviour', 'vue', 'vue') 24 | testOnLanguage('default_behaviour', 'css', 'css') 25 | testOnLanguage('default_behaviour', 'scss', 'scss') 26 | testOnLanguage('default_behaviour', 'less', 'less') 27 | }) 28 | 29 | it('should remove duplicate classes by default', () => { 30 | testOnLanguage('remove_duplicate', 'html', 'html') 31 | testOnLanguage('remove_duplicate', 'js', 'babel') 32 | testOnLanguage('remove_duplicate', 'js', 'flow') 33 | testOnLanguage('remove_duplicate', 'tsx', 'typescript') 34 | testOnLanguage('remove_duplicate', 'css', 'css') 35 | testOnLanguage('remove_duplicate', 'scss', 'scss') 36 | testOnLanguage('remove_duplicate', 'less', 'less') 37 | }) 38 | 39 | it('should not duplicate classes when are unknown', () => { 40 | testOnLanguage('no_duplicate_unknown', 'html', 'html') 41 | testOnLanguage('no_duplicate_unknown', 'js', 'babel') 42 | testOnLanguage('no_duplicate_unknown', 'js', 'flow') 43 | testOnLanguage('no_duplicate_unknown', 'tsx', 'typescript') 44 | testOnLanguage('no_duplicate_unknown', 'css', 'css') 45 | testOnLanguage('no_duplicate_unknown', 'scss', 'scss') 46 | testOnLanguage('no_duplicate_unknown', 'less', 'less') 47 | }) 48 | 49 | it('should not remove duplicates if options i set to false', () => { 50 | testOnLanguage('no_remove_duplicate', 'html', 'html', { 51 | removeDuplicatesClasses: false 52 | }) 53 | testOnLanguage('no_remove_duplicate', 'js', 'babel', { 54 | removeDuplicatesClasses: false 55 | }) 56 | testOnLanguage('no_remove_duplicate', 'js', 'flow', { 57 | removeDuplicatesClasses: false 58 | }) 59 | testOnLanguage('no_remove_duplicate', 'tsx', 'typescript', { 60 | removeDuplicatesClasses: false 61 | }) 62 | testOnLanguage('no_remove_duplicate', 'css', 'css', { 63 | removeDuplicatesClasses: false 64 | }) 65 | testOnLanguage('no_remove_duplicate', 'scss', 'scss', { 66 | removeDuplicatesClasses: false 67 | }) 68 | testOnLanguage('no_remove_duplicate', 'less', 'less', { 69 | removeDuplicatesClasses: false 70 | }) 71 | }) 72 | 73 | it('should not throw error if regex are malformed', () => { 74 | expect(() => { 75 | prettier.format('
', { 76 | parser: 'html', 77 | plugins: [plugin], 78 | ...prettierOptions, 79 | classRegex: `notexist.json` 80 | }) 81 | }).not.toThrow() 82 | 83 | expect(() => { 84 | prettier.format('
', { 85 | parser: 'html', 86 | plugins: [plugin], 87 | ...prettierOptions, 88 | classRegex: `${__dirname}/mocks/regexMalformed.json` 89 | }) 90 | }).not.toThrow() 91 | }) 92 | 93 | it('should not throw error if sorter is malformed', () => { 94 | expect(() => { 95 | prettier.format('
', { 96 | parser: 'html', 97 | plugins: [plugin], 98 | ...prettierOptions, 99 | classSorter: `notexist.json` 100 | }) 101 | }).not.toThrow() 102 | 103 | expect(() => { 104 | prettier.format('
', { 105 | parser: 'html', 106 | plugins: [plugin], 107 | ...prettierOptions, 108 | classSorter: `${__dirname}/mocks/sorterMalformed.json` 109 | }) 110 | }).not.toThrow() 111 | }) 112 | 113 | it('should support custom regex', () => { 114 | testOnLanguage('custom_regex', 'html', 'html', { 115 | classRegex: `${__dirname}/mocks/customRegex.json` 116 | }) 117 | }) 118 | --------------------------------------------------------------------------------