Skip to content

Commit 308346c

Browse files
committed
Merge branch 'release-1.2.3'
2 parents f75655e + dfc0e75 commit 308346c

File tree

4 files changed

+180
-156
lines changed

4 files changed

+180
-156
lines changed

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,22 +170,21 @@ export const buttonClasses = {
170170
The default types exported from this package are tailwindcss default ones.
171171
But if you modified some classes in your tailwind config file, you can use the CLI tool to create a file with generated types for these classes.
172172

173-
### Use per project:
173+
### CLI arguments:
174+
175+
- -c --config The name of TailwindCSS config file.
176+
- -o --output _(Optional)_ The name of generated file
174177

175178
Add it in your package.json scripts:
176179

177180
```json
178181
"scripts": {
179-
"generate" : "tailwindcss-classnames"
182+
"generate-types" : "tailwindcss-classnames --config tailwind.config.js"
180183
}
181184
```
182185

183186
or simply run `npx tailwindcss-classnames`
184187

185-
### Install globally:
186-
187-
just `npm i -g tailwindcss-classnames` and run the command where the config file is located.
188-
189188
## Custom typing
190189

191190
By default you have all the classes available as types, though you might not use all of them. You can customize your own by:

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tailwindcss-classnames",
3-
"version": "1.2.2",
3+
"version": "1.2.3",
44
"description": "Functional typed classnames for TailwindCSS",
55
"author": "Christian Alfoni <[email protected]>",
66
"contributors": [
@@ -21,7 +21,7 @@
2121
"build:lib": "tsc --outDir lib --module commonjs",
2222
"build:es": "tsc --outDir es --module es2015",
2323
"build:umd": "npm run build:es && rollup --config && dts-bundle --name dist/bundle --main es --outputAsModuleFolder",
24-
"clean": "rimraf dist es lib coverage",
24+
"clean": "rimraf dist es lib coverage tailwindcss-classnames.ts",
2525
"typecheck": "tsc --noEmit",
2626
"lint": "tslint --project tsconfig.json --format stylish",
2727
"format": "prettier '**/*.{md,js,jsx,json,ts,tsx}' --write",
@@ -47,6 +47,7 @@
4747
],
4848
"dependencies": {
4949
"classnames": "^2.2.6",
50+
"commander": "^5.1.0",
5051
"inquirer": "^7.1.0",
5152
"lodash.isempty": "^4.4.0",
5253
"tslib": "^1.9.3"

src/cli.ts

Lines changed: 40 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,156 +1,48 @@
11
#!/usr/bin/env node
22

3-
/* tslint:disable:no-eval no-console */
4-
import fs from 'fs';
3+
import commander from 'commander';
54
import inquirer from 'inquirer';
6-
import isEmpty from 'lodash.isempty';
7-
8-
import { baseTemplateString, defaultColors, defaultScreens, defaultSpacing, generateTypes } from './utils';
9-
10-
inquirer
11-
.prompt([
12-
{
13-
name: 'configFilename',
14-
type: 'input',
15-
default: 'tailwind.config.js',
16-
message: 'Tailwind configuration filename',
17-
},
18-
{
19-
name: 'outputFilename',
20-
type: 'input',
21-
default: 'tailwindcss-classnames.ts',
22-
message: 'Name of the file with generated types',
23-
},
24-
])
25-
.then(answers => {
26-
fs.readFile(`./${answers.configFilename}`, { encoding: 'utf-8' }, (err, data: any) => {
27-
if (err) {
28-
console.error(err);
29-
}
30-
31-
data = data.replace(/('|")?plugins('|")? *: *\[(.*|\n)*?\],?/g, '');
32-
33-
const CONFIG = eval(data);
34-
const THEME_CONFIG = CONFIG.theme;
35-
const PREFIX_CONFIG = CONFIG.prefix;
36-
const SEPARATOR_CONFIG = CONFIG.separator;
37-
38-
const prefix = isEmpty(PREFIX_CONFIG) ? '' : PREFIX_CONFIG;
39-
const separator = isEmpty(SEPARATOR_CONFIG) ? ':' : SEPARATOR_CONFIG;
40-
const themeColors = isEmpty(THEME_CONFIG?.colors) ? defaultColors : THEME_CONFIG?.colors;
41-
const extendedThemeColors = THEME_CONFIG?.extend?.colors;
42-
const AllColors = extendedThemeColors ? { ...themeColors, ...extendedThemeColors } : themeColors;
43-
44-
const backgroundColors: string[] = [];
45-
const placeholderColors: string[] = [];
46-
const borderColors: string[] = [];
47-
const textColors: string[] = [];
48-
// theme: {
49-
// colors: {
50-
// colorkey: colorVal ( "#fff" | {light: "#fff", lighter: "#f0f0f0",...} )
51-
// }
52-
// }
53-
const colors = Object.keys(AllColors);
54-
for (let i = 0; i < colors.length; i += 1) {
55-
const colorKey = colors[i];
56-
const colorVal = AllColors[colorKey];
57-
if (colorVal instanceof Object) {
58-
const colorVariants = Object.keys(colorVal);
59-
colorVariants.map((variant: string) => {
60-
if (variant === 'default') {
61-
variant = '';
62-
} else {
63-
variant = `-${variant}`;
64-
}
65-
backgroundColors.push(`${prefix}bg-${colorKey}${variant}`);
66-
placeholderColors.push(`${prefix}placeholder-${colorKey}${variant}`);
67-
borderColors.push(`${prefix}border-${colorKey}${variant}`);
68-
textColors.push(`${prefix}text-${colorKey}${variant}`);
69-
});
70-
} else {
71-
backgroundColors.push(`${prefix}bg-${colorKey}`);
72-
placeholderColors.push(`${prefix}placeholder-${colorKey}`);
73-
borderColors.push(`${prefix}border-${colorKey}`);
74-
textColors.push(`${prefix}text-${colorKey}`);
75-
}
76-
}
77-
78-
const themeBreakpoints = isEmpty(THEME_CONFIG?.screens) ? defaultScreens : THEME_CONFIG?.screens;
79-
const extendedThemeBreakpoints = THEME_CONFIG?.extend?.screens;
80-
const breakpoints = extendedThemeBreakpoints
81-
? { ...themeBreakpoints, ...extendedThemeBreakpoints }
82-
: themeBreakpoints;
83-
84-
const breakpointExportStatements: string[] = [];
85-
const breakpointCreateCustomParams: string[] = [];
86-
const breakpointCreateCustomReturns: string[] = [];
87-
const maxWidthByBreakpoints: string[] = [];
88-
89-
Object.keys(breakpoints).map((breakpoint: string) => {
90-
breakpointExportStatements.push(
91-
`export const ${breakpoint}: TPseudoClass = className => ('${prefix}${breakpoint}${separator}' + className) as TTailwindString;`,
92-
);
93-
breakpointCreateCustomParams.push(`${breakpoint}: TPseudoClass<T>;`);
94-
breakpointCreateCustomReturns.push(`${breakpoint},`);
95-
maxWidthByBreakpoints.push(`${prefix}max-w-screen-${breakpoint}`);
96-
});
97-
98-
const themeSpacings = isEmpty(THEME_CONFIG?.spacing) ? defaultSpacing : THEME_CONFIG?.spacing;
99-
const extendedThemeSpacings = THEME_CONFIG?.extend?.spacing;
100-
const allSpacings = extendedThemeSpacings ? { ...themeSpacings, ...extendedThemeSpacings } : themeSpacings;
101-
102-
const paddingSpacings: string[] = [];
103-
const marginSpacings: string[] = [];
104-
const widthSpacings: string[] = [];
105-
const heightSpacings: string[] = [];
106-
107-
const sides = ['', 'y', 'x', 't', 'r', 'b', 'l'];
108-
109-
sides.map(side => {
110-
paddingSpacings.push(`${prefix}p${side}-auto`);
111-
marginSpacings.push(`${prefix}m${side}-auto`);
5+
import { createFileWithGeneratedTypes } from './createFile';
6+
7+
commander
8+
.option('-c, --config <config>', 'Name of the TailwindCSS config file')
9+
.option('-o, --output <output>', 'Name of the file with the generated types', 'tailwindcss-classnames.ts')
10+
.action(({ config, output }) => {
11+
if (config) {
12+
createFileWithGeneratedTypes({
13+
configFilename: config,
14+
outputFilename: output,
11215
});
113-
114-
Object.keys(allSpacings).map((spacing, i) => {
115-
widthSpacings.push(`${prefix}w-${spacing}`);
116-
heightSpacings.push(`${prefix}h-${spacing}`);
117-
sides.map(side => {
118-
paddingSpacings.push(`${prefix}p${side}-${spacing}`);
119-
marginSpacings.push(`${prefix}m${side}-${spacing}`);
120-
if (parseInt(spacing, 10) !== 0 && Object.values(allSpacings)[i] !== 0) {
121-
paddingSpacings.push(`${prefix}-p${side}-${spacing}`);
122-
marginSpacings.push(`${prefix}-m${side}-${spacing}`);
16+
} else {
17+
inquirer
18+
.prompt([
19+
{
20+
name: 'configFilename',
21+
type: 'input',
22+
default: 'tailwind.config.js',
23+
message: 'Tailwind configuration filename',
24+
},
25+
{
26+
name: 'outputFilename',
27+
type: 'input',
28+
default: 'tailwindcss-classnames.ts',
29+
message: 'Name of the file with generated types',
30+
},
31+
])
32+
.then(answers => {
33+
createFileWithGeneratedTypes({
34+
configFilename: answers.configFilename,
35+
outputFilename: answers.outputFilename,
36+
});
37+
})
38+
.catch(error => {
39+
if (error.isTtyError) {
40+
console.error("Prompt couldn't be rendered in the current environment");
41+
} else {
42+
console.error('Something went wrong with the prompt');
12343
}
12444
});
125-
});
126-
127-
const result = baseTemplateString
128-
.replace(/_PREFIX_/g, prefix)
129-
.replace(/_SEPARATOR_/g, separator)
130-
.replace(/MAX_WIDTH_BY_BREAKPOINTS/g, generateTypes(maxWidthByBreakpoints))
131-
.replace(/BREAKPOINT_EXPORT_STATEMENTS/g, breakpointExportStatements.join('\n\n'))
132-
.replace(/BREAKPOINTS_CREATE_CUSTOM_PARAMS/g, breakpointCreateCustomParams.join('\n '))
133-
.replace(/BREAKPOINTS_CREATE_CUSTOM_RETURNS/g, breakpointCreateCustomReturns.join('\n '))
134-
.replace(/PADDINGS/g, generateTypes(paddingSpacings))
135-
.replace(/MARGINS/g, generateTypes(marginSpacings))
136-
.replace(/WIDTH_SPACINGS/g, generateTypes(widthSpacings))
137-
.replace(/HEIGHT_SPACINGS/g, generateTypes(heightSpacings))
138-
.replace(/BACKGROUND_COLORS/g, generateTypes(backgroundColors))
139-
.replace(/PLACEHOLDER_COLORS/g, generateTypes(placeholderColors))
140-
.replace(/BORDER_COLORS/g, generateTypes(borderColors))
141-
.replace(/TEXT_COLORS/g, generateTypes(textColors));
142-
143-
fs.writeFile(`${answers.outputFilename}`, result, 'utf8', error => {
144-
if (error) {
145-
console.error(error);
146-
}
147-
});
148-
});
149-
})
150-
.catch(error => {
151-
if (error.isTtyError) {
152-
console.error("Prompt couldn't be rendered in the current environment");
153-
} else {
154-
console.error('Something went wrong with the prompt');
15545
}
15646
});
47+
48+
commander.parse(process.argv);

src/createFile.ts

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/* tslint:disable:no-eval no-console */
2+
3+
import fs from 'fs';
4+
import isEmpty from 'lodash.isempty';
5+
import { baseTemplateString, defaultColors, defaultScreens, defaultSpacing, generateTypes } from './utils';
6+
7+
interface IOptions {
8+
configFilename: string;
9+
outputFilename: string;
10+
}
11+
12+
export function createFileWithGeneratedTypes({ configFilename, outputFilename }: IOptions) {
13+
fs.readFile(`./${configFilename}`, { encoding: 'utf-8' }, (err, data: any) => {
14+
if (err) {
15+
console.error(err);
16+
}
17+
18+
data = data.replace(/('|")?plugins('|")? *: *\[(.*|\n)*?\],?/g, '');
19+
20+
const CONFIG = eval(data);
21+
const THEME_CONFIG = CONFIG.theme;
22+
const PREFIX_CONFIG = CONFIG.prefix;
23+
const SEPARATOR_CONFIG = CONFIG.separator;
24+
25+
const prefix = isEmpty(PREFIX_CONFIG) ? '' : PREFIX_CONFIG;
26+
const separator = isEmpty(SEPARATOR_CONFIG) ? ':' : SEPARATOR_CONFIG;
27+
const themeColors = isEmpty(THEME_CONFIG?.colors) ? defaultColors : THEME_CONFIG?.colors;
28+
const extendedThemeColors = THEME_CONFIG?.extend?.colors;
29+
const AllColors = extendedThemeColors ? { ...themeColors, ...extendedThemeColors } : themeColors;
30+
31+
const backgroundColors: string[] = [];
32+
const placeholderColors: string[] = [];
33+
const borderColors: string[] = [];
34+
const textColors: string[] = [];
35+
// theme: {
36+
// colors: {
37+
// colorkey: colorVal ( "#fff" | {light: "#fff", lighter: "#f0f0f0",...} )
38+
// }
39+
// }
40+
const colors = Object.keys(AllColors);
41+
for (let i = 0; i < colors.length; i += 1) {
42+
const colorKey = colors[i];
43+
const colorVal = AllColors[colorKey];
44+
if (colorVal instanceof Object) {
45+
const colorVariants = Object.keys(colorVal);
46+
colorVariants.map((variant: string) => {
47+
variant = variant === 'default' ? '' : `-${variant}`;
48+
backgroundColors.push(`${prefix}bg-${colorKey}${variant}`);
49+
placeholderColors.push(`${prefix}placeholder-${colorKey}${variant}`);
50+
borderColors.push(`${prefix}border-${colorKey}${variant}`);
51+
textColors.push(`${prefix}text-${colorKey}${variant}`);
52+
});
53+
} else {
54+
backgroundColors.push(`${prefix}bg-${colorKey}`);
55+
placeholderColors.push(`${prefix}placeholder-${colorKey}`);
56+
borderColors.push(`${prefix}border-${colorKey}`);
57+
textColors.push(`${prefix}text-${colorKey}`);
58+
}
59+
}
60+
61+
const themeBreakpoints = isEmpty(THEME_CONFIG?.screens) ? defaultScreens : THEME_CONFIG?.screens;
62+
const extendedThemeBreakpoints = THEME_CONFIG?.extend?.screens;
63+
const breakpoints = extendedThemeBreakpoints
64+
? { ...themeBreakpoints, ...extendedThemeBreakpoints }
65+
: themeBreakpoints;
66+
67+
const breakpointExportStatements: string[] = [];
68+
const breakpointCreateCustomParams: string[] = [];
69+
const breakpointCreateCustomReturns: string[] = [];
70+
const maxWidthByBreakpoints: string[] = [];
71+
72+
Object.keys(breakpoints).map((breakpoint: string) => {
73+
breakpointExportStatements.push(
74+
`export const ${breakpoint}: TPseudoClass = className => ('${prefix}${breakpoint}${separator}' + className) as TTailwindString;`,
75+
);
76+
breakpointCreateCustomParams.push(`${breakpoint}: TPseudoClass<T>;`);
77+
breakpointCreateCustomReturns.push(`${breakpoint},`);
78+
maxWidthByBreakpoints.push(`${prefix}max-w-screen-${breakpoint}`);
79+
});
80+
81+
const themeSpacings = isEmpty(THEME_CONFIG?.spacing) ? defaultSpacing : THEME_CONFIG?.spacing;
82+
const extendedThemeSpacings = THEME_CONFIG?.extend?.spacing;
83+
const allSpacings = extendedThemeSpacings ? { ...themeSpacings, ...extendedThemeSpacings } : themeSpacings;
84+
85+
const paddingSpacings: string[] = [];
86+
const marginSpacings: string[] = [];
87+
const widthSpacings: string[] = [];
88+
const heightSpacings: string[] = [];
89+
90+
const sides = ['', 'y', 'x', 't', 'r', 'b', 'l'];
91+
92+
sides.map(side => {
93+
paddingSpacings.push(`${prefix}p${side}-auto`);
94+
marginSpacings.push(`${prefix}m${side}-auto`);
95+
});
96+
97+
Object.keys(allSpacings).map((spacing, i) => {
98+
widthSpacings.push(`${prefix}w-${spacing}`);
99+
heightSpacings.push(`${prefix}h-${spacing}`);
100+
sides.map(side => {
101+
paddingSpacings.push(`${prefix}p${side}-${spacing}`);
102+
marginSpacings.push(`${prefix}m${side}-${spacing}`);
103+
if (parseInt(spacing, 10) !== 0 && Object.values(allSpacings)[i] !== 0) {
104+
paddingSpacings.push(`${prefix}-p${side}-${spacing}`);
105+
marginSpacings.push(`${prefix}-m${side}-${spacing}`);
106+
}
107+
});
108+
});
109+
110+
const result = baseTemplateString
111+
.replace(/_PREFIX_/g, prefix)
112+
.replace(/_SEPARATOR_/g, separator)
113+
.replace(/MAX_WIDTH_BY_BREAKPOINTS/g, generateTypes(maxWidthByBreakpoints))
114+
.replace(/BREAKPOINT_EXPORT_STATEMENTS/g, breakpointExportStatements.join('\n\n'))
115+
.replace(/BREAKPOINTS_CREATE_CUSTOM_PARAMS/g, breakpointCreateCustomParams.join('\n '))
116+
.replace(/BREAKPOINTS_CREATE_CUSTOM_RETURNS/g, breakpointCreateCustomReturns.join('\n '))
117+
.replace(/PADDINGS/g, generateTypes(paddingSpacings))
118+
.replace(/MARGINS/g, generateTypes(marginSpacings))
119+
.replace(/WIDTH_SPACINGS/g, generateTypes(widthSpacings))
120+
.replace(/HEIGHT_SPACINGS/g, generateTypes(heightSpacings))
121+
.replace(/BACKGROUND_COLORS/g, generateTypes(backgroundColors))
122+
.replace(/PLACEHOLDER_COLORS/g, generateTypes(placeholderColors))
123+
.replace(/BORDER_COLORS/g, generateTypes(borderColors))
124+
.replace(/TEXT_COLORS/g, generateTypes(textColors));
125+
126+
fs.writeFile(`${outputFilename}`, result, 'utf8', error => {
127+
if (error) {
128+
console.error(error);
129+
}
130+
});
131+
});
132+
}

0 commit comments

Comments
 (0)