-
-
Notifications
You must be signed in to change notification settings - Fork 38
/
GeneratedFileWriter.ts
137 lines (121 loc) · 4.32 KB
/
GeneratedFileWriter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import {promises as fs} from 'fs';
import colors from 'colors';
import {baseTemplateString} from '../lib/baseTemplateString';
import {ClassesGenerator} from './ClassesGenerator';
type TCliOptions = {
configFilename: string | void;
outputFilename: string | void;
customClassesFilename: string | void;
};
export class GeneratedFileWriter {
private readonly _configFilename: string | void;
private readonly _outputFilename: string | void;
private readonly _customClassesFilename: string | void;
private _configFileData = '';
constructor(options: TCliOptions) {
this._configFilename = options.configFilename;
this._outputFilename = options.outputFilename;
this._customClassesFilename = options.customClassesFilename;
}
public write = async (): Promise<void> => {
// Check for missing cli options
if (this.missingCliOptionError().length > 0) {
this.printCliMessage('error', this.missingCliOptionError());
}
// Check for invalid custom classes file content
if (!!this._customClassesFilename) {
return fs
.readFile(`./${this._customClassesFilename}`)
.then(data => {
if (!data.toString().includes('export default')) {
this.printCliMessage(
'error',
'The type having the custom classes must be a default export',
);
return;
}
})
.catch(error => {
this.printCliMessage('error', `Unable to read the file with custom types. ${error}`);
return;
});
}
// If everything goes well, read the tailwind config file
await this.readTailwindConfigFile();
// Then create a file with the generated types
fs.writeFile(`${this._outputFilename}`, this.generateFileContent(), 'utf8')
.then(() => {
this.printCliMessage(
'success',
`Types has successfully been generated in ${this._outputFilename} file.`,
);
})
.catch(error => {
this.printCliMessage('error', error);
});
};
private missingCliOptionError = (): string => {
if (!this._configFilename) return 'tailwindcss config file name or path is not provided';
if (!this._outputFilename)
return 'Please provide a valid filename to add generated types to it';
return '';
};
private readTailwindConfigFile = async (): Promise<void> => {
try {
this._configFileData = await fs.readFile(`./${this._configFilename}`, {encoding: 'utf-8'});
} catch (err) {
this.printCliMessage('error', `Error Reading: "./${this._configFilename}"`);
}
};
private generateFileContent = (): string => {
return (
baseTemplateString
// Add all generated classnames types
.replace(
/___ALL_CLASSES___/g,
new ClassesGenerator(
eval(this._configFileData.replace(/(['"])?plugins(['"])? *: *\[(.*|\n)*?],?/g, '')),
).generate(),
)
// Add typing support for first-party plugins if found in the config
.replace(
/CUSTOM_FORMS_PLUGIN_TYPE/g,
this._configFileData.includes('@tailwindcss/custom-forms')
? '\n | TCustomFormsPluginClasses'
: '',
)
.replace(
/TYPOGRAPHY_PLUGIN_TYPE/g,
this._configFileData.includes('@tailwindcss/typography')
? '\n | TTypographyPluginClasses'
: '',
)
// Append the custom classes types from external file if provided.
.replace(
/IMPORTED_T_CUSTOM_CLASSES/g,
!!this._customClassesFilename ? '\n | TCustomClassesFromExternalFile' : '',
)
.replace(
/T_CUSTOM_CLASSES_IMPORT_STATEMENT/g,
!!this._customClassesFilename
? `import TCustomClassesFromExternalFile from './${this._customClassesFilename}';`
: '',
)
);
};
private printCliMessage = (type: 'error' | 'success', message: string): void => {
const formattedMessage = '\n\n' + message + '\n' + '\n\n';
switch (type) {
case 'success':
console.log(colors.black.bgGreen(formattedMessage));
break;
case 'error':
console.error(colors.white.bgRed(formattedMessage));
break;
default:
console.log(formattedMessage);
break;
}
};
}