@youthfulhps/prettier-plugin-tailwindcss-normalizer 0.3.4 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,204 @@
1
1
  # prettier-plugin-tailwindcss-normalizer
2
2
 
3
- A Prettier plugin that normalizes Tailwind CSS arbitrary values into standard utility classes.
3
+ [![npm version](https://badge.fury.io/js/%40youthfulhps%2Fprettier-plugin-tailwindcss-normalizer.svg)](https://badge.fury.io/js/%40youthfulhps%2Fprettier-plugin-tailwindcss-normalizer)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ A Prettier plugin that automatically normalizes Tailwind CSS arbitrary values into standard utility classes, helping maintain consistent and optimized CSS across your project.
7
+
8
+ > **⚠️ Important**: This plugin requires **Prettier v3.0.0 or higher**. It does not support Prettier v2.
9
+
10
+ ## ✨ Features
11
+
12
+ - **Automatic Normalization**: Converts arbitrary values like `p-[4px]` to standard classes like `p-1`
13
+ - **Multi-Framework Support**: Works with HTML, React/JSX, Vue.js, and Angular
14
+ - **Safe Transformation**: Only transforms class attributes, leaving comments, text, and other attributes untouched
15
+ - **Comprehensive Mapping**: Supports padding, margin, sizing, typography, borders, shadows, and more
16
+ - **Prettier v3+ Only**: Built specifically for Prettier v3.0.0 and above (v2 not supported)
17
+
18
+ ## 🚀 Installation
19
+
20
+ **Prerequisites**: Make sure you have Prettier v3.0.0 or higher installed.
21
+
22
+ ```bash
23
+ # Install Prettier v3+ (if not already installed)
24
+ npm install --save-dev prettier@^3.0.0
25
+
26
+ # Install the plugin
27
+ npm install --save-dev @youthfulhps/prettier-plugin-tailwindcss-normalizer
28
+ ```
29
+
30
+ ## 📖 Usage
31
+
32
+ ### 1. Configure Prettier
33
+
34
+ Add the plugin to your Prettier configuration:
35
+
36
+ **`.prettierrc`**
37
+
38
+ ```json
39
+ {
40
+ "plugins": ["@youthfulhps/prettier-plugin-tailwindcss-normalizer"]
41
+ }
42
+ ```
43
+
44
+ **`prettier.config.js`**
45
+
46
+ ```javascript
47
+ module.exports = {
48
+ plugins: ['@youthfulhps/prettier-plugin-tailwindcss-normalizer'],
49
+ };
50
+ ```
51
+
52
+ ### 2. Run Prettier
53
+
54
+ ```bash
55
+ # Format all files
56
+ npx prettier --write .
57
+
58
+ # Format specific files
59
+ npx prettier --write src/**/*.{tsx,jsx,html,vue}
60
+ ```
61
+
62
+ ## 🎯 Examples
63
+
64
+ ### Before
65
+
66
+ ```jsx
67
+ <div className="p-[16px] m-[8px] bg-blue-500">
68
+ <span className="px-[24px] py-[12px] rounded-[6px]">
69
+ Button
70
+ </span>
71
+ </div>
72
+ ```
73
+
74
+ ### After
75
+
76
+ ```jsx
77
+ <div className="p-4 m-2 bg-blue-500">
78
+ <span className="px-6 py-3 rounded-md">
79
+ Button
80
+ </span>
81
+ </div>
82
+ ```
83
+
84
+ ## 🛡️ Safety Features
85
+
86
+ The plugin is designed to be safe and only transforms class-related attributes:
87
+
88
+ ### ✅ What Gets Transformed
89
+
90
+ - `className` attributes in JSX/TSX
91
+ - `class` attributes in HTML
92
+ - `:class` and `v-bind:class` in Vue
93
+ - `[class]` in Angular
94
+ - String literals in template literals
95
+ - Function calls like `clsx()`, `classnames()`, `cn()`
96
+
97
+ ### ❌ What Stays Untouched
98
+
99
+ - Comments and documentation
100
+ - Regular text content
101
+ - Other HTML attributes (`title`, `data-*`, etc.)
102
+ - JavaScript strings and variables
103
+ - CSS in `<style>` tags
104
+
105
+ ## 📋 Supported Mappings
106
+
107
+ ### Spacing
108
+
109
+ - **Padding**: `p-[4px]` → `p-1`, `px-[16px]` → `px-4`
110
+ - **Margin**: `m-[8px]` → `m-2`, `my-[12px]` → `my-3`
111
+ - **Gap**: `gap-[8px]` → `gap-2`, `gap-x-[16px]` → `gap-x-4`
112
+
113
+ ### Sizing
114
+
115
+ - **Width**: `w-[100px]` → `w-25`, `w-[200px]` → `w-50`
116
+ - **Height**: `h-[50px]` → `h-12.5`, `h-[100px]` → `h-25`
117
+
118
+ ### Typography
119
+
120
+ - **Font Size**: `text-[14px]` → `text-sm`, `text-[18px]` → `text-lg`
121
+
122
+ ### Layout
123
+
124
+ - **Border Radius**: `rounded-[4px]` → `rounded`, `rounded-[6px]` → `rounded-md`
125
+ - **Border Width**: `border-[1px]` → `border`, `border-[2px]` → `border-2`
126
+
127
+ ### Effects
128
+
129
+ - **Box Shadow**: `shadow-[0_1px_3px_rgba(0,0,0,0.1)]` → `shadow-sm`
130
+ - **Opacity**: `opacity-[0.5]` → `opacity-50`
131
+
132
+ ## 🔧 Configuration
133
+
134
+ The plugin works out of the box with default settings. No additional configuration is required.
135
+
136
+ > **Note**: This plugin is optimized for Prettier v3+ and takes advantage of the new plugin architecture. If you're using Prettier v2, please upgrade to v3 or use an alternative solution.
137
+
138
+ ## 🧪 Testing
139
+
140
+ The plugin includes comprehensive tests covering:
141
+
142
+ - Various file formats (HTML, JSX, TSX, Vue)
143
+ - Edge cases and complex scenarios
144
+ - Safety features and non-transformation cases
145
+ - Different Tailwind CSS patterns
146
+
147
+ Run tests:
148
+
149
+ ```bash
150
+ npm test
151
+ ```
152
+
153
+ ## 📁 File Support
154
+
155
+ | Format | Extension | Support |
156
+ | --------- | ----------------- | ------- |
157
+ | HTML | `.html` | ✅ |
158
+ | React JSX | `.jsx` | ✅ |
159
+ | React TSX | `.tsx` | ✅ |
160
+ | Vue | `.vue` | ✅ |
161
+ | Angular | `.component.html` | ✅ |
162
+
163
+ ## 🤝 Contributing
164
+
165
+ Contributions are welcome! Please feel free to submit a Pull Request.
166
+
167
+ 1. Fork the repository
168
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
169
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
170
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
171
+ 5. Open a Pull Request
172
+
173
+ ## 📄 License
174
+
175
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
176
+
177
+ ## 🙏 Acknowledgments
178
+
179
+ - Built for the Prettier ecosystem
180
+ - Inspired by Tailwind CSS best practices
181
+ - Thanks to all contributors and users
182
+
183
+ ## 📞 Support
184
+
185
+ If you encounter any issues or have questions:
186
+
187
+ 1. Check the [Issues](https://github.com/youthfulhps/prettier-plugin-tailwindcss-normalizer/issues) page
188
+ 2. Create a new issue with detailed information
189
+ 3. Provide examples of your code and expected behavior
190
+
191
+ ### Common Issues
192
+
193
+ **Q: The plugin doesn't work with Prettier v2**
194
+ A: This plugin requires Prettier v3.0.0 or higher. Please upgrade your Prettier version.
195
+
196
+ **Q: How do I check my Prettier version?**
197
+ A: Run `npx prettier --version` to check your current Prettier version.
198
+
199
+ **Q: Can I use this with Prettier v2?**
200
+ A: No, this plugin is built specifically for Prettier v3+ and will not work with v2.
201
+
202
+ ---
203
+
204
+ **Made with ❤️ for the developer community**
package/dist/index.js CHANGED
@@ -2,6 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const ast_transformer_1 = require("./ast-transformer");
4
4
  const version_utils_1 = require("./utils/version-utils");
5
+ function createParser(parserName, fileType) {
6
+ const baseParser = (0, version_utils_1.safeLoadParser)(parserName, fileType);
7
+ return {
8
+ ...baseParser,
9
+ preprocess: (text, options) => {
10
+ return (0, ast_transformer_1.transformByFileType)(text, options.filepath || `file.${fileType}`);
11
+ },
12
+ };
13
+ }
5
14
  const plugin = {
6
15
  languages: [
7
16
  {
@@ -31,42 +40,37 @@ const plugin = {
31
40
  },
32
41
  ],
33
42
  parsers: {
34
- html: {
35
- ...(0, version_utils_1.safeLoadParser)("html"),
36
- preprocess: (text, options) => {
37
- return (0, ast_transformer_1.transformByFileType)(text, options.filepath || "file.html");
38
- },
39
- },
40
- vue: {
41
- ...(0, version_utils_1.safeLoadParser)("html", "vue"),
42
- preprocess: (text, options) => {
43
- return (0, ast_transformer_1.transformByFileType)(text, options.filepath || "file.vue");
44
- },
45
- },
46
- angular: {
47
- ...(0, version_utils_1.safeLoadParser)("angular"),
48
- preprocess: (text, options) => {
49
- return (0, ast_transformer_1.transformByFileType)(text, options.filepath || "file.html");
50
- },
51
- },
43
+ html: createParser("html", "html"),
44
+ vue: createParser("html", "vue"),
45
+ angular: createParser("angular", "html"),
52
46
  babel: {
53
- ...(0, version_utils_1.safeLoadParser)("babel"),
54
- preprocess: (text, options) => {
47
+ ...createParser("babel", "jsx"),
48
+ parse: (text, options) => {
55
49
  const filepath = options.filepath || "";
56
50
  if (filepath.endsWith(".jsx") || filepath.endsWith(".tsx")) {
57
- return (0, ast_transformer_1.transformByFileType)(text, filepath);
51
+ const transformedText = (0, ast_transformer_1.transformByFileType)(text, filepath);
52
+ const baseParser = (0, version_utils_1.safeLoadParser)("babel");
53
+ return baseParser.parse
54
+ ? baseParser.parse(transformedText, options)
55
+ : text;
58
56
  }
59
- return text;
57
+ const baseParser = (0, version_utils_1.safeLoadParser)("babel");
58
+ return baseParser.parse ? baseParser.parse(text, options) : text;
60
59
  },
61
60
  },
62
61
  "babel-ts": {
63
- ...(0, version_utils_1.safeLoadParser)("babel", "babel-ts"),
64
- preprocess: (text, options) => {
62
+ ...createParser("babel", "tsx"),
63
+ parse: (text, options) => {
65
64
  const filepath = options.filepath || "";
66
65
  if (filepath.endsWith(".tsx")) {
67
- return (0, ast_transformer_1.transformByFileType)(text, filepath);
66
+ const transformedText = (0, ast_transformer_1.transformByFileType)(text, filepath);
67
+ const baseParser = (0, version_utils_1.safeLoadParser)("babel", "babel-ts");
68
+ return baseParser.parse
69
+ ? baseParser.parse(transformedText, options)
70
+ : text;
68
71
  }
69
- return text;
72
+ const baseParser = (0, version_utils_1.safeLoadParser)("babel", "babel-ts");
73
+ return baseParser.parse ? baseParser.parse(text, options) : text;
70
74
  },
71
75
  },
72
76
  },
@@ -1,6 +1,4 @@
1
1
  export declare function getPrettierMajorVersion(): number;
2
- export declare function isPrettierV2(): boolean;
3
- export declare function isPrettierV3Plus(): boolean;
4
2
  export declare function loadParser(parserName: string): any;
5
3
  export declare function getParserFromParsers(parsers: any, parserName: string): any;
6
4
  export declare function safeLoadParser(parserName: string, specificParser?: string): any;
@@ -1,54 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getPrettierMajorVersion = getPrettierMajorVersion;
4
- exports.isPrettierV2 = isPrettierV2;
5
- exports.isPrettierV3Plus = isPrettierV3Plus;
6
4
  exports.loadParser = loadParser;
7
5
  exports.getParserFromParsers = getParserFromParsers;
8
6
  exports.safeLoadParser = safeLoadParser;
9
- let prettierVersion = null;
10
7
  function getPrettierMajorVersion() {
11
- if (prettierVersion !== null) {
12
- return prettierVersion;
13
- }
14
- try {
15
- const prettier = require("prettier");
16
- if (prettier.version) {
17
- const majorVersion = parseInt(prettier.version.split(".")[0]);
18
- prettierVersion = majorVersion;
19
- return majorVersion;
20
- }
21
- const prettierPackageJson = require("prettier/package.json");
22
- if (prettierPackageJson.version) {
23
- const majorVersion = parseInt(prettierPackageJson.version.split(".")[0]);
24
- prettierVersion = majorVersion;
25
- return majorVersion;
26
- }
27
- prettierVersion = 3;
28
- return 3;
29
- }
30
- catch (error) {
31
- prettierVersion = 3;
32
- return 3;
33
- }
34
- }
35
- function isPrettierV2() {
36
- return getPrettierMajorVersion() === 2;
37
- }
38
- function isPrettierV3Plus() {
39
- return getPrettierMajorVersion() >= 3;
8
+ return 3;
40
9
  }
41
10
  function loadParser(parserName) {
42
- const majorVersion = getPrettierMajorVersion();
43
- const pathsToTry = [];
44
- if (majorVersion >= 3) {
45
- pathsToTry.push(`prettier/plugins/${parserName}`);
46
- pathsToTry.push(`prettier/parser-${parserName}`);
47
- }
48
- else {
49
- pathsToTry.push(`prettier/parser-${parserName}`);
50
- pathsToTry.push(`prettier/plugins/${parserName}`);
51
- }
11
+ const pathsToTry = [
12
+ `prettier/plugins/${parserName}`,
13
+ `prettier/parser-${parserName}`,
14
+ ];
52
15
  let lastError = null;
53
16
  for (const path of pathsToTry) {
54
17
  try {
@@ -60,7 +23,6 @@ function loadParser(parserName) {
60
23
  }
61
24
  }
62
25
  throw new Error(`Failed to load parser: ${parserName}. ` +
63
- `Prettier version: ${majorVersion}. ` +
64
26
  `Tried paths: ${pathsToTry.join(", ")}. ` +
65
27
  `Last error: ${lastError?.message}`);
66
28
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youthfulhps/prettier-plugin-tailwindcss-normalizer",
3
- "version": "0.3.4",
3
+ "version": "0.3.7",
4
4
  "description": "A Prettier plugin that normalizes Tailwind CSS arbitrary values into standard utility classes.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -39,7 +39,7 @@
39
39
  "author": "Your Name",
40
40
  "license": "MIT",
41
41
  "peerDependencies": {
42
- "prettier": ">=2.0.0"
42
+ "prettier": ">=3.0.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/jest": "^29.5.8",
@@ -48,7 +48,7 @@
48
48
  "@typescript-eslint/parser": "^7.0.0",
49
49
  "eslint": "^8.57.1",
50
50
  "jest": "^29.7.0",
51
- "prettier": "^3.1.0",
51
+ "prettier": "^3.0.0",
52
52
  "ts-jest": "^29.1.1",
53
53
  "typescript": "^5.2.2"
54
54
  },