@youthfulhps/prettier-plugin-tailwindcss-normalizer 0.3.9 → 0.4.1

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
@@ -45,7 +45,7 @@ Add the plugin to your Prettier configuration:
45
45
 
46
46
  ```javascript
47
47
  module.exports = {
48
- plugins: ['@youthfulhps/prettier-plugin-tailwindcss-normalizer'],
48
+ plugins: ["@youthfulhps/prettier-plugin-tailwindcss-normalizer"],
49
49
  };
50
50
  ```
51
51
 
@@ -59,15 +59,39 @@ npx prettier --write .
59
59
  npx prettier --write src/**/*.{tsx,jsx,html,vue}
60
60
  ```
61
61
 
62
+ ## 🔗 Using with Other Prettier Tailwind Plugins
63
+
64
+ To use this plugin alongside other prettier tailwind plugins, you need to install and configure `prettier-plugin-merge`.
65
+
66
+ ### Installation
67
+
68
+ ```bash
69
+ npm install --save-dev prettier-plugin-merge
70
+ ```
71
+
72
+ ### Configuration
73
+
74
+ In your `.prettierrc.js` file, add `prettier-plugin-merge` as the last item in the plugins array:
75
+
76
+ ```javascript
77
+ module.exports = {
78
+ plugins: [
79
+ "@youthfulhps/prettier-plugin-tailwindcss-normalizer",
80
+ "prettier-plugin-tailwindcss",
81
+ "prettier-plugin-merge",
82
+ ],
83
+ };
84
+ ```
85
+
86
+ > **Note**: `prettier-plugin-merge` is a plugin that enables multiple prettier plugins to work together. When using with other tailwind-related plugins, it should always be placed last in the plugins array.
87
+
62
88
  ## 🎯 Examples
63
89
 
64
90
  ### Before
65
91
 
66
92
  ```jsx
67
93
  <div className="p-[16px] m-[8px] bg-blue-500">
68
- <span className="px-[24px] py-[12px] rounded-[6px]">
69
- Button
70
- </span>
94
+ <span className="px-[24px] py-[12px] rounded-[6px]">Button</span>
71
95
  </div>
72
96
  ```
73
97
 
@@ -75,9 +99,7 @@ npx prettier --write src/**/*.{tsx,jsx,html,vue}
75
99
 
76
100
  ```jsx
77
101
  <div className="p-4 m-2 bg-blue-500">
78
- <span className="px-6 py-3 rounded-md">
79
- Button
80
- </span>
102
+ <span className="px-6 py-3 rounded-md">Button</span>
81
103
  </div>
82
104
  ```
83
105
 
@@ -131,8 +153,74 @@ The plugin is designed to be safe and only transforms class-related attributes:
131
153
 
132
154
  ## 🔧 Configuration
133
155
 
156
+ ### Basic Configuration
157
+
134
158
  The plugin works out of the box with default settings. No additional configuration is required.
135
159
 
160
+ ### Custom Spacing Unit
161
+
162
+ If you've customized your Tailwind CSS spacing scale, you can configure the plugin to match your custom spacing unit.
163
+
164
+ By default, Tailwind uses **4px** as the base spacing unit (e.g., `p-1` = 4px, `p-2` = 8px). If you've changed this in your Tailwind configuration, you should update the `customSpacingUnit` option.
165
+
166
+ **`.prettierrc.js`**
167
+
168
+ ```javascript
169
+ module.exports = {
170
+ plugins: ["@youthfulhps/prettier-plugin-tailwindcss-normalizer"],
171
+ customSpacingUnit: 8, // Change to match your Tailwind spacing scale
172
+ };
173
+ ```
174
+
175
+ **`tailwind.config.js` (Example with 8px base unit)**
176
+
177
+ ```javascript
178
+ module.exports = {
179
+ theme: {
180
+ extend: {
181
+ spacing: {
182
+ 1: "8px", // 8px * 1
183
+ 2: "16px", // 8px * 2
184
+ 3: "24px", // 8px * 3
185
+ 4: "32px", // 8px * 4
186
+ // ... etc
187
+ },
188
+ },
189
+ },
190
+ };
191
+ ```
192
+
193
+ **Tailwind CSS v4 (`global.css` or similar)**
194
+
195
+ ```css
196
+ @theme {
197
+ --spacing: 1px;
198
+ /* ... etc */
199
+ }
200
+ ```
201
+
202
+ **Example with `customSpacingUnit: 8`**
203
+
204
+ ```jsx
205
+ // Before
206
+ <div className="p-[8px] m-[16px] gap-[24px]">Content</div>
207
+
208
+ // After (with customSpacingUnit: 8)
209
+ <div className="p-1 m-2 gap-3">Content</div>
210
+ ```
211
+
212
+ **Example with default `customSpacingUnit: 4`**
213
+
214
+ ```jsx
215
+ // Before
216
+ <div className="p-[4px] m-[8px] gap-[12px]">Content</div>
217
+
218
+ // After (with customSpacingUnit: 4)
219
+ <div className="p-1 m-2 gap-3">Content</div>
220
+ ```
221
+
222
+ See the [examples/custom-spacing](./examples/custom-spacing) directory for a complete working example.
223
+
136
224
  > **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
225
 
138
226
  ## 🧪 Testing
package/dist/index.d.ts CHANGED
@@ -1,3 +1,7 @@
1
- import { CompatPlugin } from "./types/prettier-compat";
2
- declare const plugin: CompatPlugin;
3
- export default plugin;
1
+ import { CompatParser } from "./types/prettier-compat";
2
+ declare const parsers: Record<string, CompatParser>, languages: {
3
+ name: string;
4
+ parsers: string[];
5
+ extensions: string[];
6
+ }[] | undefined, options: Record<string, any> | undefined;
7
+ export { parsers, languages, options };
package/dist/index.js CHANGED
@@ -1,13 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.options = exports.languages = exports.parsers = void 0;
3
4
  const ast_transformer_1 = require("./ast-transformer");
4
5
  const version_utils_1 = require("./utils/version-utils");
6
+ const normalizer_1 = require("./normalizer");
5
7
  function createParser(parserName, fileType) {
6
8
  const baseParser = (0, version_utils_1.safeLoadParser)(parserName, fileType);
7
9
  return {
8
10
  ...baseParser,
9
- astFormat: parserName,
10
11
  preprocess: (text, options) => {
12
+ const pluginOptions = {
13
+ customSpacingUnit: options.customSpacingUnit,
14
+ };
15
+ (0, normalizer_1.setPluginOptions)(pluginOptions);
11
16
  return (0, ast_transformer_1.transformByFileType)(text, options.filepath || `file.${fileType}`);
12
17
  },
13
18
  };
@@ -36,46 +41,42 @@ const plugin = {
36
41
  },
37
42
  {
38
43
  name: "TypeScript",
39
- parsers: ["babel-ts"],
44
+ parsers: ["typescript"],
40
45
  extensions: [".ts", ".tsx"],
41
46
  },
42
47
  ],
43
48
  parsers: {
44
- html: createParser("html", "html"),
45
- vue: createParser("html", "vue"),
46
- angular: createParser("angular", "html"),
49
+ html: {
50
+ ...createParser("html", "html"),
51
+ astFormat: "html",
52
+ },
53
+ vue: {
54
+ ...createParser("html", "vue"),
55
+ astFormat: "vue",
56
+ },
57
+ angular: {
58
+ ...createParser("angular", "html"),
59
+ astFormat: "html",
60
+ },
47
61
  babel: {
48
- ...createParser("babel", "jsx"),
49
- parse: (text, options) => {
50
- const filepath = options.filepath || "";
51
- if (filepath.endsWith(".jsx") || filepath.endsWith(".tsx")) {
52
- const transformedText = (0, ast_transformer_1.transformByFileType)(text, filepath);
53
- const baseParser = (0, version_utils_1.safeLoadParser)("babel");
54
- return baseParser.parse
55
- ? baseParser.parse(transformedText, options)
56
- : text;
57
- }
58
- const baseParser = (0, version_utils_1.safeLoadParser)("babel");
59
- return baseParser.parse ? baseParser.parse(text, options) : text;
60
- },
62
+ ...createParser("babel", "babel"),
63
+ astFormat: "estree",
61
64
  },
62
- "babel-ts": {
63
- ...createParser("babel", "tsx"),
64
- parse: (text, options) => {
65
- const filepath = options.filepath || "";
66
- if (filepath.endsWith(".tsx")) {
67
- const transformedText = (0, ast_transformer_1.transformByFileType)(text, filepath);
68
- const baseParser = (0, version_utils_1.safeLoadParser)("babel", "babel-ts");
69
- return baseParser.parse
70
- ? baseParser.parse(transformedText, options)
71
- : text;
72
- }
73
- const baseParser = (0, version_utils_1.safeLoadParser)("babel", "babel-ts");
74
- return baseParser.parse ? baseParser.parse(text, options) : text;
75
- },
65
+ typescript: {
66
+ ...createParser("typescript", "typescript"),
67
+ astFormat: "estree",
68
+ },
69
+ },
70
+ options: {
71
+ customSpacingUnit: {
72
+ type: "int",
73
+ category: "Tailwind",
74
+ default: 4,
75
+ description: "Custom spacing unit in pixels (default: 4). Tailwind uses 4px as the base unit (e.g., p-1 = 4px). Change this if you've customized Tailwind's spacing scale.",
76
76
  },
77
77
  },
78
- printers: {},
79
78
  };
80
- module.exports = plugin;
81
- exports.default = plugin;
79
+ const { parsers, languages, options } = plugin;
80
+ exports.parsers = parsers;
81
+ exports.languages = languages;
82
+ exports.options = options;
@@ -1,3 +1,5 @@
1
+ import { PluginOptions } from "./types";
2
+ export declare function setPluginOptions(options?: PluginOptions): void;
1
3
  export declare function normalizeClassAttribute(content: string): string;
2
4
  export declare function normalizeClassNames(classNames: string): string;
3
5
  export declare function normalizeClassName(className: string): string;
@@ -1,9 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setPluginOptions = setPluginOptions;
3
4
  exports.normalizeClassAttribute = normalizeClassAttribute;
4
5
  exports.normalizeClassNames = normalizeClassNames;
5
6
  exports.normalizeClassName = normalizeClassName;
6
7
  const mappings_1 = require("./mappings");
8
+ const spacing_generator_1 = require("./utils/spacing-generator");
9
+ let currentMappings = mappings_1.TAILWIND_MAPPINGS;
10
+ function setPluginOptions(options = {}) {
11
+ if (options.customSpacingUnit && options.customSpacingUnit !== 4) {
12
+ const customSpacingMappings = (0, spacing_generator_1.generateSpacingMappings)(options.customSpacingUnit);
13
+ currentMappings = {
14
+ ...mappings_1.TAILWIND_MAPPINGS,
15
+ ...customSpacingMappings,
16
+ };
17
+ }
18
+ else {
19
+ currentMappings = mappings_1.TAILWIND_MAPPINGS;
20
+ }
21
+ }
7
22
  function normalizeClassAttribute(content) {
8
23
  let result = content;
9
24
  const classAttributeRegex = /class\s*=\s*["']([^"']*?)["']/g;
@@ -115,7 +130,7 @@ function normalizeClassName(className) {
115
130
  return className;
116
131
  }
117
132
  function findStandardMapping(prefix, value) {
118
- const mappings = mappings_1.TAILWIND_MAPPINGS[prefix];
133
+ const mappings = currentMappings[prefix];
119
134
  if (!mappings) {
120
135
  return null;
121
136
  }
package/dist/types.d.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  export type ValueMapping = Record<string, string>;
2
+ export interface PluginOptions {
3
+ customSpacingUnit?: number;
4
+ }
2
5
  export type TailwindMapping = {
3
6
  p?: ValueMapping;
4
7
  px?: ValueMapping;
@@ -0,0 +1,2 @@
1
+ import { ValueMapping } from "../types";
2
+ export declare function generateSpacingMappings(customUnit?: number): Record<string, ValueMapping>;
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateSpacingMappings = generateSpacingMappings;
4
+ function generateSpacingMappings(customUnit = 4) {
5
+ const spacingPrefixes = [
6
+ "p",
7
+ "px",
8
+ "py",
9
+ "pt",
10
+ "pr",
11
+ "pb",
12
+ "pl",
13
+ "ps",
14
+ "pe",
15
+ "m",
16
+ "mx",
17
+ "my",
18
+ "mt",
19
+ "mr",
20
+ "mb",
21
+ "ml",
22
+ "ms",
23
+ "me",
24
+ "gap",
25
+ "gap-x",
26
+ "gap-y",
27
+ "space-x",
28
+ "space-y",
29
+ "w",
30
+ "h",
31
+ "size",
32
+ "min-w",
33
+ "max-w",
34
+ "min-h",
35
+ "max-h",
36
+ "top",
37
+ "right",
38
+ "bottom",
39
+ "left",
40
+ "scroll-m",
41
+ "scroll-p",
42
+ ];
43
+ const standardScales = [
44
+ { scale: "0", multiplier: 0 },
45
+ { scale: "0.5", multiplier: 0.5 },
46
+ { scale: "1", multiplier: 1 },
47
+ { scale: "1.5", multiplier: 1.5 },
48
+ { scale: "2", multiplier: 2 },
49
+ { scale: "2.5", multiplier: 2.5 },
50
+ { scale: "3", multiplier: 3 },
51
+ { scale: "3.5", multiplier: 3.5 },
52
+ { scale: "4", multiplier: 4 },
53
+ { scale: "5", multiplier: 5 },
54
+ { scale: "6", multiplier: 6 },
55
+ { scale: "7", multiplier: 7 },
56
+ { scale: "8", multiplier: 8 },
57
+ { scale: "9", multiplier: 9 },
58
+ { scale: "10", multiplier: 10 },
59
+ { scale: "11", multiplier: 11 },
60
+ { scale: "12", multiplier: 12 },
61
+ { scale: "14", multiplier: 14 },
62
+ { scale: "16", multiplier: 16 },
63
+ { scale: "20", multiplier: 20 },
64
+ { scale: "24", multiplier: 24 },
65
+ { scale: "28", multiplier: 28 },
66
+ { scale: "32", multiplier: 32 },
67
+ { scale: "36", multiplier: 36 },
68
+ { scale: "40", multiplier: 40 },
69
+ { scale: "44", multiplier: 44 },
70
+ { scale: "48", multiplier: 48 },
71
+ { scale: "52", multiplier: 52 },
72
+ { scale: "56", multiplier: 56 },
73
+ { scale: "60", multiplier: 60 },
74
+ { scale: "64", multiplier: 64 },
75
+ { scale: "72", multiplier: 72 },
76
+ { scale: "80", multiplier: 80 },
77
+ { scale: "96", multiplier: 96 },
78
+ ];
79
+ const fractionalPrefixes = ["py", "my"];
80
+ const result = {};
81
+ spacingPrefixes.forEach((prefix) => {
82
+ const mapping = {};
83
+ const supportsFractional = fractionalPrefixes.includes(prefix);
84
+ const supportsNegative = [
85
+ "m",
86
+ "mx",
87
+ "my",
88
+ "mt",
89
+ "mr",
90
+ "mb",
91
+ "ml",
92
+ "ms",
93
+ "me",
94
+ "top",
95
+ "right",
96
+ "bottom",
97
+ "left",
98
+ ].includes(prefix);
99
+ standardScales.forEach(({ scale, multiplier }) => {
100
+ if (!supportsFractional && scale.includes(".")) {
101
+ return;
102
+ }
103
+ const pixelValue = multiplier * customUnit;
104
+ const pixelKey = `${pixelValue}px`;
105
+ mapping[pixelKey] = `${prefix}-${scale}`;
106
+ if (supportsNegative && scale !== "0") {
107
+ const negativePixelValue = -pixelValue;
108
+ const negativePixelKey = `${negativePixelValue}px`;
109
+ mapping[negativePixelKey] = `-${prefix}-${scale}`;
110
+ }
111
+ });
112
+ mapping["1px"] = `${prefix}-px`;
113
+ result[prefix] = mapping;
114
+ });
115
+ return result;
116
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youthfulhps/prettier-plugin-tailwindcss-normalizer",
3
- "version": "0.3.9",
3
+ "version": "0.4.1",
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",