@udixio/tailwind 0.5.2 → 1.0.0
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/.eslintrc.mjs +22 -0
- package/CHANGELOG.md +61 -0
- package/dist/file.d.ts.map +1 -0
- package/{index.cjs → dist/index.cjs} +165 -149
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/{index.js → dist/index.js} +165 -149
- package/dist/plugins-tailwind/index.d.ts.map +1 -0
- package/{src → dist}/tailwind.plugin.d.ts +1 -2
- package/dist/tailwind.plugin.d.ts.map +1 -0
- package/package.json +11 -6
- package/src/file.ts +126 -0
- package/src/index.test.ts +5 -0
- package/src/index.ts +5 -0
- package/src/main.ts +52 -0
- package/src/plugins-tailwind/font.ts +61 -0
- package/src/plugins-tailwind/index.ts +2 -0
- package/src/plugins-tailwind/state.ts +75 -0
- package/src/tailwind.plugin.ts +130 -0
- package/tsconfig.json +16 -0
- package/tsconfig.lib.json +37 -0
- package/tsconfig.spec.json +36 -0
- package/vite.config.ts +54 -0
- package/src/file.d.ts.map +0 -1
- package/src/index.d.ts +0 -6
- package/src/index.d.ts.map +0 -1
- package/src/main.d.ts +0 -3
- package/src/main.d.ts.map +0 -1
- package/src/plugins-tailwind/font.d.ts +0 -4
- package/src/plugins-tailwind/font.d.ts.map +0 -1
- package/src/plugins-tailwind/index.d.ts.map +0 -1
- package/src/plugins-tailwind/state.d.ts +0 -3
- package/src/plugins-tailwind/state.d.ts.map +0 -1
- package/src/tailwind.plugin.d.ts.map +0 -1
- /package/{LICENSE → dist/LICENSE} +0 -0
- /package/{src → dist}/file.d.ts +0 -0
- /package/{src → dist}/plugins-tailwind/index.d.ts +0 -0
|
@@ -1,9 +1,144 @@
|
|
|
1
|
-
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2
4
|
import plugin from "tailwindcss/plugin";
|
|
3
5
|
import * as fs from "fs";
|
|
4
6
|
import * as path from "path";
|
|
5
7
|
import path__default from "path";
|
|
6
8
|
import { replaceInFileSync } from "replace-in-file";
|
|
9
|
+
import { PluginAbstract, FontPlugin, PluginImplAbstract } from "@udixio/theme";
|
|
10
|
+
const defaultConfig = {
|
|
11
|
+
statePrefix: "state",
|
|
12
|
+
disabledStyles: {
|
|
13
|
+
textOpacity: 0.38,
|
|
14
|
+
backgroundOpacity: 0.12
|
|
15
|
+
},
|
|
16
|
+
transition: {
|
|
17
|
+
duration: 150
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const state = plugin.withOptions(({ colorKeys }) => {
|
|
21
|
+
const resolved = {
|
|
22
|
+
...defaultConfig,
|
|
23
|
+
disabledStyles: {
|
|
24
|
+
...defaultConfig.disabledStyles,
|
|
25
|
+
...{}
|
|
26
|
+
},
|
|
27
|
+
transition: {
|
|
28
|
+
...defaultConfig.transition,
|
|
29
|
+
...{}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
return ({ addComponents }) => {
|
|
33
|
+
const newComponents = {};
|
|
34
|
+
for (const isGroup of [false, true]) {
|
|
35
|
+
const group = isGroup ? "group-" : "";
|
|
36
|
+
for (const colorName of colorKeys) {
|
|
37
|
+
const className = `.${group}${resolved.statePrefix}-${colorName}`;
|
|
38
|
+
newComponents[className] = {
|
|
39
|
+
[`@apply ${group}hover:bg-${colorName}/[0.08]`]: {},
|
|
40
|
+
[`@apply ${group}active:bg-${colorName}/[0.12]`]: {},
|
|
41
|
+
[`@apply ${group}focus-visible:bg-${colorName}/[0.12]`]: {},
|
|
42
|
+
[`@apply transition-colors`]: {},
|
|
43
|
+
[`@apply duration-${resolved.transition.duration}`]: {},
|
|
44
|
+
[`@apply ${group}disabled:text-on-surface/[${resolved.disabledStyles.textOpacity}]`]: {},
|
|
45
|
+
[`@apply ${group}disabled:bg-on-surface/[${resolved.disabledStyles.backgroundOpacity}]`]: {}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
for (const colorName of colorKeys) {
|
|
50
|
+
for (const stateName of ["hover", "active", "focus", "disabled"]) {
|
|
51
|
+
const className = `.${stateName}-${resolved.statePrefix}-${colorName}`;
|
|
52
|
+
if (stateName === "disabled") {
|
|
53
|
+
newComponents[className] = {
|
|
54
|
+
[`@apply text-on-surface/[${resolved.disabledStyles.textOpacity}]`]: {},
|
|
55
|
+
[`@apply bg-on-surface/[${resolved.disabledStyles.backgroundOpacity}]`]: {}
|
|
56
|
+
};
|
|
57
|
+
} else {
|
|
58
|
+
const opacity = stateName === "hover" ? 0.08 : 0.12;
|
|
59
|
+
newComponents[className] = {
|
|
60
|
+
[`@apply bg-${colorName}/[${opacity}]`]: {}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
addComponents(newComponents);
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
const font = plugin.withOptions((options) => {
|
|
69
|
+
return ({
|
|
70
|
+
addUtilities,
|
|
71
|
+
theme
|
|
72
|
+
}) => {
|
|
73
|
+
const { fontStyles, responsiveBreakPoints } = options;
|
|
74
|
+
const pixelUnit = "rem";
|
|
75
|
+
const newUtilities = {};
|
|
76
|
+
const baseTextStyle = (sizeValue) => ({
|
|
77
|
+
fontSize: sizeValue.fontSize + pixelUnit,
|
|
78
|
+
fontWeight: sizeValue.fontWeight,
|
|
79
|
+
lineHeight: sizeValue.lineHeight + pixelUnit,
|
|
80
|
+
letterSpacing: sizeValue.letterSpacing ? sizeValue.letterSpacing + pixelUnit : null,
|
|
81
|
+
fontFamily: theme("fontFamily." + sizeValue.fontFamily)
|
|
82
|
+
});
|
|
83
|
+
const responsiveTextStyle = (sizeValue, breakPointName, breakPointRatio) => ({
|
|
84
|
+
[`@media (min-width: ${theme("screens." + breakPointName, {})})`]: {
|
|
85
|
+
fontSize: sizeValue.fontSize * breakPointRatio + pixelUnit,
|
|
86
|
+
lineHeight: sizeValue.lineHeight * breakPointRatio + pixelUnit
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
for (const [roleName, roleValue] of Object.entries(fontStyles)) {
|
|
90
|
+
for (const [sizeName, sizeValue] of Object.entries(roleValue)) {
|
|
91
|
+
newUtilities[`.text-${roleName}-${sizeName}`] = {
|
|
92
|
+
...baseTextStyle(sizeValue),
|
|
93
|
+
...Object.entries(responsiveBreakPoints).reduce(
|
|
94
|
+
(acc, [breakPointName, breakPointRatio]) => ({
|
|
95
|
+
...acc,
|
|
96
|
+
...responsiveTextStyle(
|
|
97
|
+
sizeValue,
|
|
98
|
+
breakPointName,
|
|
99
|
+
breakPointRatio
|
|
100
|
+
)
|
|
101
|
+
}),
|
|
102
|
+
{}
|
|
103
|
+
)
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
addUtilities(newUtilities);
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
const main = plugin.withOptions((args) => {
|
|
111
|
+
const configCss = args;
|
|
112
|
+
const fontStyles = {};
|
|
113
|
+
configCss.fontStyles.forEach((line) => {
|
|
114
|
+
const [styleToken, ...properties] = line.split(" ");
|
|
115
|
+
const [roleToken, sizeToken] = styleToken.split("-");
|
|
116
|
+
fontStyles[roleToken] ?? (fontStyles[roleToken] = {});
|
|
117
|
+
properties.forEach((properties2) => {
|
|
118
|
+
var _a;
|
|
119
|
+
(_a = fontStyles[roleToken])[sizeToken] ?? (_a[sizeToken] = {});
|
|
120
|
+
const [key, value] = properties2.slice(0, -1).split("[");
|
|
121
|
+
fontStyles[roleToken][sizeToken][key] = value;
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
let breakPointsCss = configCss.responsiveBreakPoints;
|
|
125
|
+
if (!Array.isArray(breakPointsCss)) {
|
|
126
|
+
breakPointsCss = [breakPointsCss];
|
|
127
|
+
}
|
|
128
|
+
const responsiveBreakPoints = {};
|
|
129
|
+
breakPointsCss.forEach(([key, value]) => {
|
|
130
|
+
responsiveBreakPoints[key] = value;
|
|
131
|
+
});
|
|
132
|
+
const options = {
|
|
133
|
+
colorKeys: configCss.colorKeys,
|
|
134
|
+
fontStyles,
|
|
135
|
+
responsiveBreakPoints
|
|
136
|
+
};
|
|
137
|
+
return (api) => {
|
|
138
|
+
font(options).handler(api);
|
|
139
|
+
state(options).handler(api);
|
|
140
|
+
};
|
|
141
|
+
});
|
|
7
142
|
const createOrUpdateFile = (filePath, content) => {
|
|
8
143
|
try {
|
|
9
144
|
if (!fs.existsSync(filePath)) {
|
|
@@ -93,122 +228,12 @@ const findTailwindCssFile = (startDir, searchPattern) => {
|
|
|
93
228
|
}
|
|
94
229
|
return null;
|
|
95
230
|
};
|
|
96
|
-
const state = (colorKeys) => plugin((pluginArgs) => {
|
|
97
|
-
addAllNewComponents(
|
|
98
|
-
pluginArgs,
|
|
99
|
-
{
|
|
100
|
-
statePrefix: "state",
|
|
101
|
-
disabledStyles: {
|
|
102
|
-
textOpacity: 0.38,
|
|
103
|
-
backgroundOpacity: 0.12
|
|
104
|
-
},
|
|
105
|
-
transition: {
|
|
106
|
-
duration: 150
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
colorKeys
|
|
110
|
-
);
|
|
111
|
-
}, {});
|
|
112
|
-
const addAllNewComponents = ({ addComponents }, { statePrefix, disabledStyles, transition }, colorKeys) => {
|
|
113
|
-
const newComponents = {};
|
|
114
|
-
for (const isGroup of [false, true]) {
|
|
115
|
-
const group = isGroup ? "group-" : "";
|
|
116
|
-
for (const colorName of colorKeys) {
|
|
117
|
-
const className = `.${group}${statePrefix}-${colorName}`;
|
|
118
|
-
newComponents[className] = {
|
|
119
|
-
[`@apply ${group}hover:bg-${colorName}/[0.08]`]: {},
|
|
120
|
-
[`@apply ${group}active:bg-${colorName}/[0.12]`]: {},
|
|
121
|
-
[`@apply ${group}focus-visible:bg-${colorName}/[0.12]`]: {}
|
|
122
|
-
};
|
|
123
|
-
if (transition) {
|
|
124
|
-
newComponents[className][`@apply transition-colors`] = {};
|
|
125
|
-
newComponents[className][`@apply duration-${transition.duration}`] = {};
|
|
126
|
-
}
|
|
127
|
-
if (disabledStyles) {
|
|
128
|
-
newComponents[className][`@apply ${group}disabled:text-on-surface/[${disabledStyles.textOpacity}]`] = {};
|
|
129
|
-
newComponents[className][`@apply ${group}disabled:bg-on-surface/[${disabledStyles.backgroundOpacity}]`] = {};
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
for (const colorName of colorKeys) {
|
|
134
|
-
for (const stateName of ["hover", "active", "focus", "disabled"]) {
|
|
135
|
-
const className = `.${stateName}-${statePrefix}-${colorName}`;
|
|
136
|
-
if (stateName === "active" || stateName === "focus") {
|
|
137
|
-
newComponents[className] = {
|
|
138
|
-
[`@apply bg-${colorName}/[0.12]`]: {}
|
|
139
|
-
};
|
|
140
|
-
} else if (stateName === "hover") {
|
|
141
|
-
newComponents[className] = {
|
|
142
|
-
[`@apply bg-${colorName}/[0.08]`]: {}
|
|
143
|
-
};
|
|
144
|
-
} else if (stateName === "disabled") {
|
|
145
|
-
newComponents[className] = {
|
|
146
|
-
[`@apply text-on-surface/[${disabledStyles.textOpacity}]`]: {}
|
|
147
|
-
};
|
|
148
|
-
newComponents[className] = {
|
|
149
|
-
[`@apply bg-on-surface/[${disabledStyles.backgroundOpacity}]`]: {}
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
addComponents(newComponents);
|
|
155
|
-
};
|
|
156
|
-
const font = (fontStyles, responsiveBreakPoints) => {
|
|
157
|
-
const createUtilities = ({ theme }) => {
|
|
158
|
-
const pixelUnit = "rem";
|
|
159
|
-
const newUtilities = {};
|
|
160
|
-
const baseTextStyle = (sizeValue) => ({
|
|
161
|
-
fontSize: sizeValue.fontSize + pixelUnit,
|
|
162
|
-
fontWeight: sizeValue.fontWeight,
|
|
163
|
-
lineHeight: sizeValue.lineHeight + pixelUnit,
|
|
164
|
-
letterSpacing: sizeValue.letterSpacing ? sizeValue.letterSpacing + pixelUnit : null,
|
|
165
|
-
fontFamily: theme("fontFamily." + sizeValue.fontFamily)
|
|
166
|
-
});
|
|
167
|
-
const responsiveTextStyle = (sizeValue, breakPointName, breakPointRatio) => ({
|
|
168
|
-
[`@media (min-width: ${theme("screens." + breakPointName, {})})`]: {
|
|
169
|
-
fontSize: sizeValue.fontSize * breakPointRatio + pixelUnit,
|
|
170
|
-
lineHeight: sizeValue.lineHeight * breakPointRatio + pixelUnit
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
for (const [roleName, roleValue] of Object.entries(fontStyles)) {
|
|
174
|
-
for (const [sizeName, sizeValue] of Object.entries(roleValue)) {
|
|
175
|
-
newUtilities[".text-" + roleName + "-" + sizeName] = {
|
|
176
|
-
...baseTextStyle(sizeValue),
|
|
177
|
-
...Object.entries(responsiveBreakPoints).reduce(
|
|
178
|
-
(acc, [breakPointName, breakPointRatio]) => {
|
|
179
|
-
acc = {
|
|
180
|
-
...acc,
|
|
181
|
-
...responsiveTextStyle(
|
|
182
|
-
sizeValue,
|
|
183
|
-
breakPointName,
|
|
184
|
-
breakPointRatio
|
|
185
|
-
)
|
|
186
|
-
};
|
|
187
|
-
return acc;
|
|
188
|
-
},
|
|
189
|
-
{}
|
|
190
|
-
)
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return newUtilities;
|
|
195
|
-
};
|
|
196
|
-
return plugin(
|
|
197
|
-
({
|
|
198
|
-
addUtilities,
|
|
199
|
-
theme
|
|
200
|
-
}) => {
|
|
201
|
-
const newUtilities = createUtilities({ theme });
|
|
202
|
-
addUtilities(newUtilities);
|
|
203
|
-
}
|
|
204
|
-
);
|
|
205
|
-
};
|
|
206
231
|
class TailwindPlugin extends PluginAbstract {
|
|
207
232
|
constructor() {
|
|
208
233
|
super(...arguments);
|
|
209
|
-
this
|
|
210
|
-
this
|
|
211
|
-
this
|
|
234
|
+
__publicField(this, "dependencies", [FontPlugin]);
|
|
235
|
+
__publicField(this, "name", "tailwind");
|
|
236
|
+
__publicField(this, "pluginClass", TailwindImplPlugin);
|
|
212
237
|
}
|
|
213
238
|
}
|
|
214
239
|
class TailwindImplPlugin extends PluginImplAbstract {
|
|
@@ -218,13 +243,11 @@ class TailwindImplPlugin extends PluginImplAbstract {
|
|
|
218
243
|
lg: 1.125
|
|
219
244
|
});
|
|
220
245
|
}
|
|
221
|
-
|
|
222
|
-
const searchKeyword =
|
|
246
|
+
onLoad() {
|
|
247
|
+
const searchKeyword = "@import 'tailwindcss';";
|
|
223
248
|
const tailwindCssPath = this.options.styleFilePath ?? findTailwindCssFile(process.cwd(), searchKeyword);
|
|
224
249
|
if (!tailwindCssPath) {
|
|
225
|
-
throw new Error(
|
|
226
|
-
'The style file containing the Udixio plugin was not found.\n Please use it first. (@plugin "@udixio/tailwind")'
|
|
227
|
-
);
|
|
250
|
+
throw new Error("The style file containing tailwind was not found.");
|
|
228
251
|
}
|
|
229
252
|
const searchPattern = /@import ["']tailwindcss["'];/;
|
|
230
253
|
const replacement = `@import 'tailwindcss';
|
|
@@ -243,12 +266,28 @@ class TailwindImplPlugin extends PluginImplAbstract {
|
|
|
243
266
|
}
|
|
244
267
|
}
|
|
245
268
|
const { fontStyles, fontFamily } = this.api.plugins.getPlugin(FontPlugin).getInstance().getFonts();
|
|
269
|
+
const configCss = {
|
|
270
|
+
colorKeys: Object.keys(colors).join(", "),
|
|
271
|
+
fontStyles: Object.entries(fontStyles).map(
|
|
272
|
+
([fontRole, fontStyle]) => Object.entries(fontStyle).map(
|
|
273
|
+
([fontSize, fontStyle2]) => `${fontRole}-${fontSize} ${Object.entries(fontStyle2).map(([name, value]) => `${name}[${value}]`).join(" ")}`
|
|
274
|
+
).join(", ")
|
|
275
|
+
).join(", "),
|
|
276
|
+
responsiveBreakPoints: Object.entries(
|
|
277
|
+
this.options.responsiveBreakPoints ?? {}
|
|
278
|
+
).map(([key, value]) => `${key} ${value}`).join(", ")
|
|
279
|
+
};
|
|
246
280
|
createOrUpdateFile(
|
|
247
281
|
path__default.join(cssFilePath, "udixio.css"),
|
|
248
282
|
`
|
|
283
|
+
@plugin "@udixio/tailwind" {
|
|
284
|
+
colorKeys: ${configCss.colorKeys};
|
|
285
|
+
fontStyles: ${configCss.fontStyles};
|
|
286
|
+
responsiveBreakPoints: ${configCss.responsiveBreakPoints};
|
|
287
|
+
}
|
|
249
288
|
@custom-variant dark (&:where(.dark, .dark *));
|
|
250
289
|
@theme {
|
|
251
|
-
|
|
290
|
+
--color-*: initial;
|
|
252
291
|
${Object.entries(colors).map(([key, value]) => `--color-${key}: ${value.light};`).join("\n ")}
|
|
253
292
|
}
|
|
254
293
|
@layer theme {
|
|
@@ -256,41 +295,18 @@ class TailwindImplPlugin extends PluginImplAbstract {
|
|
|
256
295
|
${Object.entries(colors).map(([key, value]) => `--color-${key}: ${value.dark};`).join("\n ")}
|
|
257
296
|
}
|
|
258
297
|
}
|
|
298
|
+
@theme {
|
|
299
|
+
${Object.entries(fontFamily).map(
|
|
300
|
+
([key, values]) => `--font-${key}: ${values.map((value) => `"${value}"`).join(", ")};`
|
|
301
|
+
).join("\n ")}
|
|
302
|
+
}
|
|
259
303
|
`
|
|
260
304
|
);
|
|
261
|
-
const plugins = [
|
|
262
|
-
state(Object.keys(colors)),
|
|
263
|
-
font(fontStyles, this.options.responsiveBreakPoints)
|
|
264
|
-
];
|
|
265
|
-
return plugin.withOptions(
|
|
266
|
-
// 1) factory(options) → la fonction “handler” du plugin
|
|
267
|
-
(options = {}) => {
|
|
268
|
-
return async function(api) {
|
|
269
|
-
plugins.forEach((plugin2) => {
|
|
270
|
-
plugin2.handler(api);
|
|
271
|
-
});
|
|
272
|
-
};
|
|
273
|
-
},
|
|
274
|
-
// 2) config(options) → objet à merger dans tailwind.config
|
|
275
|
-
(options = {}) => {
|
|
276
|
-
return {
|
|
277
|
-
theme: {
|
|
278
|
-
fontFamily
|
|
279
|
-
}
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
);
|
|
283
305
|
}
|
|
284
306
|
}
|
|
285
|
-
const createTheme = async () => {
|
|
286
|
-
const app = await bootstrapFromConfig();
|
|
287
|
-
const plugin2 = app.plugins.getPlugin(TailwindPlugin).getInstance();
|
|
288
|
-
return plugin2.load();
|
|
289
|
-
};
|
|
290
307
|
export {
|
|
291
308
|
TailwindPlugin,
|
|
292
|
-
|
|
293
|
-
createTheme as default,
|
|
309
|
+
main as default,
|
|
294
310
|
font,
|
|
295
311
|
state
|
|
296
312
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins-tailwind/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { default as plugin } from 'tailwindcss/plugin';
|
|
2
1
|
import { FontPlugin, PluginAbstract, PluginImplAbstract } from '@udixio/theme';
|
|
3
2
|
interface TailwindPluginOptions {
|
|
4
3
|
responsiveBreakPoints?: Record<string, number>;
|
|
@@ -11,7 +10,7 @@ export declare class TailwindPlugin extends PluginAbstract<TailwindImplPlugin, T
|
|
|
11
10
|
}
|
|
12
11
|
declare class TailwindImplPlugin extends PluginImplAbstract<TailwindPluginOptions> {
|
|
13
12
|
onInit(): void;
|
|
14
|
-
|
|
13
|
+
onLoad(): void;
|
|
15
14
|
}
|
|
16
15
|
export {};
|
|
17
16
|
//# sourceMappingURL=tailwind.plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tailwind.plugin.d.ts","sourceRoot":"","sources":["../src/tailwind.plugin.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAG/E,UAAU,qBAAqB;IAE7B,qBAAqB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;CAExB;AAED,qBAAa,cAAe,SAAQ,cAAc,CAChD,kBAAkB,EAClB,qBAAqB,CACtB;IACQ,YAAY,wBAAgB;IAC5B,IAAI,SAAc;IACzB,WAAW,4BAAsB;CAClC;AAED,cAAM,kBAAmB,SAAQ,kBAAkB,CAAC,qBAAqB,CAAC;IACxE,MAAM;IAMN,MAAM;CAgGP"}
|
package/package.json
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@udixio/tailwind",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"main": "
|
|
6
|
-
"
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
7
8
|
"exports": {
|
|
9
|
+
"./package.json": "./package.json",
|
|
8
10
|
".": {
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
+
"development": "./src/index.ts",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs",
|
|
15
|
+
"default": "./dist/index.js"
|
|
11
16
|
}
|
|
12
17
|
},
|
|
13
18
|
"dependencies": {
|
|
14
19
|
"tslib": "^2.3.0",
|
|
15
|
-
"@udixio/theme": "0.
|
|
20
|
+
"@udixio/theme": "1.0.0"
|
|
16
21
|
},
|
|
17
22
|
"repository": {
|
|
18
23
|
"type": "git",
|
package/src/file.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { replaceInFileSync } from 'replace-in-file';
|
|
4
|
+
|
|
5
|
+
export const createOrUpdateFile = (filePath: string, content: string): void => {
|
|
6
|
+
try {
|
|
7
|
+
if (!fs.existsSync(filePath)) {
|
|
8
|
+
// Create the folder if necessary.
|
|
9
|
+
const dirPath = path.dirname(filePath);
|
|
10
|
+
if (!fs.existsSync(dirPath)) {
|
|
11
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Create the file with the provided content.
|
|
15
|
+
fs.writeFileSync(filePath, content);
|
|
16
|
+
console.log(`✅ File successfully created: ${filePath}`);
|
|
17
|
+
} else {
|
|
18
|
+
console.log(`⚠️ File already exists: ${filePath}`);
|
|
19
|
+
replaceFileContent(filePath, /[\s\S]*/, content);
|
|
20
|
+
}
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error('❌ Error while creating the file:', error);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const getFileContent = (
|
|
27
|
+
filePath: string,
|
|
28
|
+
searchPattern?: RegExp | string,
|
|
29
|
+
): string | false | null => {
|
|
30
|
+
try {
|
|
31
|
+
// Vérifier si le fichier existe
|
|
32
|
+
if (!fs.existsSync(filePath)) {
|
|
33
|
+
console.error(`❌ The specified file does not exist: ${filePath}`);
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Lire le contenu du fichier entier
|
|
38
|
+
const fileContent = fs.readFileSync(filePath, 'utf8');
|
|
39
|
+
|
|
40
|
+
// Si un motif est fourni, chercher le texte correspondant
|
|
41
|
+
if (searchPattern) {
|
|
42
|
+
if (typeof searchPattern === 'string') {
|
|
43
|
+
const found = fileContent.includes(searchPattern)
|
|
44
|
+
? searchPattern
|
|
45
|
+
: false;
|
|
46
|
+
console.log(
|
|
47
|
+
found
|
|
48
|
+
? `✅ The file contains the specified string: "${searchPattern}"`
|
|
49
|
+
: `⚠️ The file does NOT contain the specified string: "${searchPattern}"`,
|
|
50
|
+
);
|
|
51
|
+
return found;
|
|
52
|
+
} else {
|
|
53
|
+
const match = fileContent.match(searchPattern);
|
|
54
|
+
if (match) {
|
|
55
|
+
console.log(`✅ Found match: "${match[0]}"`);
|
|
56
|
+
return match[0]; // Retourner le texte trouvé
|
|
57
|
+
} else {
|
|
58
|
+
console.log(
|
|
59
|
+
`⚠️ No match found for the pattern: "${searchPattern.toString()}"`,
|
|
60
|
+
);
|
|
61
|
+
return false; // Aucune correspondance trouvée
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Si aucun motif n'est fourni, retourner tout le contenu
|
|
67
|
+
console.log(`✅ File content successfully retrieved.`);
|
|
68
|
+
return fileContent;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error('❌ An error occurred while processing the file:', error);
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const replaceFileContent = (
|
|
76
|
+
filePath: string,
|
|
77
|
+
searchPattern: RegExp | string,
|
|
78
|
+
replacement: string,
|
|
79
|
+
): void => {
|
|
80
|
+
try {
|
|
81
|
+
const results = replaceInFileSync({
|
|
82
|
+
files: filePath,
|
|
83
|
+
from: searchPattern,
|
|
84
|
+
to: replacement,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (results.length > 0 && results[0].hasChanged) {
|
|
88
|
+
console.log(`✅ Content successfully replaced in the file: ${filePath}`);
|
|
89
|
+
} else {
|
|
90
|
+
console.log(
|
|
91
|
+
`⚠️ No replacement made. Here are some possible reasons:\n- The pattern ${searchPattern} was not found.\n- The file might already contain the expected content.`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error('❌ Error while replacing the file content:', error);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
export const findTailwindCssFile = (
|
|
99
|
+
startDir: string,
|
|
100
|
+
searchPattern: string,
|
|
101
|
+
): string | null => {
|
|
102
|
+
const files = fs.readdirSync(startDir);
|
|
103
|
+
|
|
104
|
+
for (const file of files) {
|
|
105
|
+
const filePath = path.join(startDir, file);
|
|
106
|
+
const stats = fs.statSync(filePath);
|
|
107
|
+
|
|
108
|
+
if (stats.isDirectory()) {
|
|
109
|
+
// Appeler récursivement si c'est un dossier
|
|
110
|
+
const result = findTailwindCssFile(filePath, searchPattern);
|
|
111
|
+
if (result) return result;
|
|
112
|
+
} else if (
|
|
113
|
+
file.endsWith('.css') ||
|
|
114
|
+
file.endsWith('.scss') ||
|
|
115
|
+
file.endsWith('.sass')
|
|
116
|
+
) {
|
|
117
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
118
|
+
if (content.includes(searchPattern)) {
|
|
119
|
+
console.log('File found:\n', filePath);
|
|
120
|
+
return filePath;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return null;
|
|
126
|
+
};
|
package/src/index.ts
ADDED
package/src/main.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import plugin, { PluginAPI } from 'tailwindcss/plugin';
|
|
2
|
+
import {
|
|
3
|
+
font,
|
|
4
|
+
FontPluginOptions,
|
|
5
|
+
state,
|
|
6
|
+
StateOptions,
|
|
7
|
+
} from './plugins-tailwind';
|
|
8
|
+
|
|
9
|
+
export type ConfigJs = FontPluginOptions & StateOptions;
|
|
10
|
+
export type ConfigCss = {
|
|
11
|
+
colorKeys: string[];
|
|
12
|
+
fontStyles: string[];
|
|
13
|
+
responsiveBreakPoints: string[];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const main = plugin.withOptions<ConfigJs>((args) => {
|
|
17
|
+
const configCss = args as unknown as ConfigCss;
|
|
18
|
+
|
|
19
|
+
const fontStyles: any = {};
|
|
20
|
+
|
|
21
|
+
configCss.fontStyles.forEach((line) => {
|
|
22
|
+
const [styleToken, ...properties] = line.split(' ');
|
|
23
|
+
const [roleToken, sizeToken] = styleToken.split('-');
|
|
24
|
+
|
|
25
|
+
fontStyles[roleToken] ??= {};
|
|
26
|
+
properties.forEach((properties) => {
|
|
27
|
+
fontStyles[roleToken][sizeToken] ??= {};
|
|
28
|
+
const [key, value] = properties.slice(0, -1).split('[');
|
|
29
|
+
fontStyles[roleToken][sizeToken][key] = value;
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
let breakPointsCss = configCss.responsiveBreakPoints;
|
|
34
|
+
if (!Array.isArray(breakPointsCss)) {
|
|
35
|
+
breakPointsCss = [breakPointsCss];
|
|
36
|
+
}
|
|
37
|
+
const responsiveBreakPoints: any = {};
|
|
38
|
+
breakPointsCss.forEach(([key, value]) => {
|
|
39
|
+
responsiveBreakPoints[key] = value;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const options: ConfigJs = {
|
|
43
|
+
colorKeys: configCss.colorKeys,
|
|
44
|
+
fontStyles: fontStyles,
|
|
45
|
+
responsiveBreakPoints,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return (api: PluginAPI) => {
|
|
49
|
+
font(options).handler(api);
|
|
50
|
+
state(options).handler(api);
|
|
51
|
+
};
|
|
52
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { FontRole, FontSize, FontStyle } from '@udixio/theme';
|
|
2
|
+
import plugin, { PluginAPI } from 'tailwindcss/plugin';
|
|
3
|
+
|
|
4
|
+
export interface FontPluginOptions {
|
|
5
|
+
fontStyles: Record<FontRole, Record<FontSize, FontStyle>>;
|
|
6
|
+
responsiveBreakPoints: Record<string, number>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const font = plugin.withOptions((options: FontPluginOptions) => {
|
|
10
|
+
return ({
|
|
11
|
+
addUtilities,
|
|
12
|
+
theme,
|
|
13
|
+
}: Pick<PluginAPI, 'addUtilities' | 'theme'>) => {
|
|
14
|
+
const { fontStyles, responsiveBreakPoints } = options;
|
|
15
|
+
|
|
16
|
+
const pixelUnit = 'rem';
|
|
17
|
+
const newUtilities: Record<string, any> = {};
|
|
18
|
+
|
|
19
|
+
const baseTextStyle = (sizeValue: FontStyle) => ({
|
|
20
|
+
fontSize: sizeValue.fontSize + pixelUnit,
|
|
21
|
+
fontWeight: sizeValue.fontWeight as unknown as any,
|
|
22
|
+
lineHeight: sizeValue.lineHeight + pixelUnit,
|
|
23
|
+
letterSpacing: sizeValue.letterSpacing
|
|
24
|
+
? sizeValue.letterSpacing + pixelUnit
|
|
25
|
+
: null,
|
|
26
|
+
fontFamily: theme('fontFamily.' + sizeValue.fontFamily),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const responsiveTextStyle = (
|
|
30
|
+
sizeValue: FontStyle,
|
|
31
|
+
breakPointName: string,
|
|
32
|
+
breakPointRatio: number,
|
|
33
|
+
) => ({
|
|
34
|
+
[`@media (min-width: ${theme('screens.' + breakPointName, {})})`]: {
|
|
35
|
+
fontSize: sizeValue.fontSize * breakPointRatio + pixelUnit,
|
|
36
|
+
lineHeight: sizeValue.lineHeight * breakPointRatio + pixelUnit,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
for (const [roleName, roleValue] of Object.entries(fontStyles)) {
|
|
41
|
+
for (const [sizeName, sizeValue] of Object.entries(roleValue)) {
|
|
42
|
+
newUtilities[`.text-${roleName}-${sizeName}`] = {
|
|
43
|
+
...baseTextStyle(sizeValue),
|
|
44
|
+
...Object.entries(responsiveBreakPoints).reduce(
|
|
45
|
+
(acc, [breakPointName, breakPointRatio]) => ({
|
|
46
|
+
...acc,
|
|
47
|
+
...responsiveTextStyle(
|
|
48
|
+
sizeValue,
|
|
49
|
+
breakPointName,
|
|
50
|
+
breakPointRatio,
|
|
51
|
+
),
|
|
52
|
+
}),
|
|
53
|
+
{},
|
|
54
|
+
),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
addUtilities(newUtilities);
|
|
60
|
+
};
|
|
61
|
+
});
|