@udixio/tailwind 1.3.0 → 1.4.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/dist/index.js DELETED
@@ -1,410 +0,0 @@
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);
4
- import plugin from "tailwindcss/plugin";
5
- import * as fs from "fs";
6
- import { replaceInFileSync } from "replace-in-file";
7
- import * as console from "node:console";
8
- import { resolve, join, dirname, normalize } from "pathe";
9
- import { fileURLToPath } from "url";
10
- import path from "path";
11
- import { PluginAbstract, FontPlugin, PluginImplAbstract } from "@udixio/theme";
12
- const defaultConfig = {
13
- statePrefix: "state",
14
- disabledStyles: {
15
- textOpacity: 0.38,
16
- backgroundOpacity: 0.12
17
- },
18
- transition: {
19
- duration: 150
20
- }
21
- };
22
- const state = plugin.withOptions(({ colorKeys }) => {
23
- const resolved = {
24
- ...defaultConfig,
25
- disabledStyles: {
26
- ...defaultConfig.disabledStyles,
27
- ...{}
28
- },
29
- transition: {
30
- ...defaultConfig.transition,
31
- ...{}
32
- }
33
- };
34
- return ({ addComponents }) => {
35
- const newComponents = {};
36
- for (const isGroup of [false, true]) {
37
- const group = isGroup ? "group-" : "";
38
- for (const colorName of colorKeys) {
39
- const className = `.${group}${resolved.statePrefix}-${colorName}`;
40
- newComponents[className] = {
41
- [`@apply ${group}hover:bg-${colorName}/[0.08]`]: {},
42
- [`@apply ${group}active:bg-${colorName}/[0.12]`]: {},
43
- [`@apply ${group}focus-visible:bg-${colorName}/[0.12]`]: {},
44
- [`@apply transition-colors`]: {},
45
- [`@apply duration-${resolved.transition.duration}`]: {},
46
- [`@apply ${group}disabled:text-on-surface/[${resolved.disabledStyles.textOpacity}]`]: {},
47
- [`@apply ${group}disabled:bg-on-surface/[${resolved.disabledStyles.backgroundOpacity}]`]: {}
48
- };
49
- }
50
- }
51
- for (const colorName of colorKeys) {
52
- for (const stateName of ["hover", "active", "focus", "disabled"]) {
53
- const className = `.${stateName}-${resolved.statePrefix}-${colorName}`;
54
- if (stateName === "disabled") {
55
- newComponents[className] = {
56
- [`@apply text-on-surface/[${resolved.disabledStyles.textOpacity}]`]: {},
57
- [`@apply bg-on-surface/[${resolved.disabledStyles.backgroundOpacity}]`]: {}
58
- };
59
- } else {
60
- const opacity = stateName === "hover" ? 0.08 : 0.12;
61
- newComponents[className] = {
62
- [`@apply bg-${colorName}/[${opacity}]`]: {}
63
- };
64
- }
65
- }
66
- }
67
- addComponents(newComponents);
68
- };
69
- });
70
- const font = plugin.withOptions((options) => {
71
- return ({
72
- addUtilities,
73
- theme
74
- }) => {
75
- const { fontStyles, responsiveBreakPoints } = options;
76
- const pixelUnit = "rem";
77
- const newUtilities = {};
78
- const baseTextStyle = (sizeValue) => ({
79
- fontSize: sizeValue.fontSize + pixelUnit,
80
- fontWeight: sizeValue.fontWeight,
81
- lineHeight: sizeValue.lineHeight + pixelUnit,
82
- letterSpacing: sizeValue.letterSpacing ? sizeValue.letterSpacing + pixelUnit : null,
83
- fontFamily: theme("fontFamily." + sizeValue.fontFamily)
84
- });
85
- const responsiveTextStyle = (sizeValue, breakPointName, breakPointRatio) => ({
86
- [`@media (min-width: ${theme("screens." + breakPointName, {})})`]: {
87
- fontSize: sizeValue.fontSize * breakPointRatio + pixelUnit,
88
- lineHeight: sizeValue.lineHeight * breakPointRatio + pixelUnit
89
- }
90
- });
91
- for (const [roleName, roleValue] of Object.entries(fontStyles)) {
92
- for (const [sizeName, sizeValue] of Object.entries(roleValue)) {
93
- newUtilities[`.text-${roleName}-${sizeName}`] = {
94
- ...baseTextStyle(sizeValue),
95
- ...Object.entries(responsiveBreakPoints).reduce(
96
- (acc, [breakPointName, breakPointRatio]) => ({
97
- ...acc,
98
- ...responsiveTextStyle(
99
- sizeValue,
100
- breakPointName,
101
- breakPointRatio
102
- )
103
- }),
104
- {}
105
- )
106
- };
107
- }
108
- }
109
- addUtilities(newUtilities);
110
- };
111
- });
112
- const shadow = plugin(
113
- ({ addUtilities }) => {
114
- addUtilities({
115
- [".shadow"]: {
116
- boxShadow: "0 4px 10px #00000008, 0 0 2px #0000000f, 0 2px 6px #0000001f"
117
- },
118
- [".shadow-1"]: {
119
- boxShadow: "0px 1px 3px 1px rgba(0, 0, 0, 0.15), 0px 1px 2px 0px rgba(0, 0, 0, 0.30)"
120
- },
121
- [".shadow-2"]: {
122
- boxShadow: "0px 2px 6px 2px rgba(0, 0, 0, 0.15), 0px 1px 2px 0px rgba(0, 0, 0, 0.30)"
123
- },
124
- [".shadow-3"]: {
125
- boxShadow: "0px 1px 3px 0px rgba(0, 0, 0, 0.30), 0px 4px 8px 3px rgba(0, 0, 0, 0.15)"
126
- },
127
- [".shadow-4"]: {
128
- boxShadow: "0px 2px 3px 0px rgba(0, 0, 0, 0.30), 0px 6px 10px 4px rgba(0, 0, 0, 0.15)"
129
- },
130
- [".box-shadow-5"]: {
131
- boxShadow: "0px 4px 4px 0px rgba(0, 0, 0, 0.30), 0px 8px 12px 6px rgba(0, 0, 0, 0.15)"
132
- }
133
- });
134
- }
135
- );
136
- const main = plugin.withOptions((args) => {
137
- const configCss = args;
138
- const fontStyles = {};
139
- configCss.fontStyles.forEach((line) => {
140
- const [styleToken, ...properties] = line.split(" ");
141
- const [roleToken, sizeToken] = styleToken.split("-");
142
- fontStyles[roleToken] ?? (fontStyles[roleToken] = {});
143
- properties.forEach((properties2) => {
144
- var _a;
145
- (_a = fontStyles[roleToken])[sizeToken] ?? (_a[sizeToken] = {});
146
- const [key, value] = properties2.slice(0, -1).split("[");
147
- fontStyles[roleToken][sizeToken][key] = value;
148
- });
149
- });
150
- let breakPointsCss = configCss.responsiveBreakPoints;
151
- if (!Array.isArray(breakPointsCss)) {
152
- breakPointsCss = [breakPointsCss];
153
- }
154
- const responsiveBreakPoints = {};
155
- breakPointsCss.forEach((line) => {
156
- const [key, value] = line.split(" ");
157
- responsiveBreakPoints[key] = value;
158
- });
159
- const options = {
160
- colorKeys: configCss.colorKeys,
161
- fontStyles,
162
- responsiveBreakPoints
163
- };
164
- return (api) => {
165
- font(options).handler(api);
166
- state(options).handler(api);
167
- shadow.handler(api);
168
- };
169
- });
170
- const normalizePath = (filePath) => {
171
- try {
172
- if (filePath.startsWith("file://")) {
173
- return normalize(fileURLToPath(filePath));
174
- }
175
- return normalize(filePath);
176
- } catch (error) {
177
- console.warn(
178
- `Warning: Could not process path ${filePath}, treating as regular path`
179
- );
180
- return normalize(filePath);
181
- }
182
- };
183
- const safeExistsSync = (filePath) => {
184
- return fs.existsSync(normalizePath(filePath));
185
- };
186
- const safeReadFileSync = (filePath, encoding = "utf8") => {
187
- return fs.readFileSync(normalizePath(filePath), encoding);
188
- };
189
- const safeWriteFileSync = (filePath, data) => {
190
- const normalizedPath = normalizePath(filePath);
191
- const dirPath = dirname(normalizedPath);
192
- if (!fs.existsSync(dirPath)) {
193
- fs.mkdirSync(dirPath, { recursive: true });
194
- }
195
- fs.writeFileSync(normalizedPath, data);
196
- };
197
- const createOrUpdateFile = (filePath, content) => {
198
- try {
199
- const normalizedPath = normalizePath(filePath);
200
- if (!safeExistsSync(filePath)) {
201
- safeWriteFileSync(filePath, content);
202
- console.log(`✅ File successfully created: ${normalizedPath}`);
203
- } else {
204
- console.log(`⚠️ File already exists: ${normalizedPath}`);
205
- replaceFileContent(filePath, /[\s\S]*/, content);
206
- }
207
- } catch (error) {
208
- console.error("❌ Error while creating the file:", error);
209
- }
210
- };
211
- const getFileContent = (filePath, searchPattern) => {
212
- try {
213
- const normalizedPath = normalizePath(filePath);
214
- if (!safeExistsSync(filePath)) {
215
- console.error(`❌ The specified file does not exist: ${normalizedPath}`);
216
- return null;
217
- }
218
- const fileContent = safeReadFileSync(filePath);
219
- if (searchPattern) {
220
- if (typeof searchPattern === "string") {
221
- const found = fileContent.includes(searchPattern) ? searchPattern : false;
222
- console.log(
223
- found ? `✅ The file contains the specified string: "${searchPattern}"` : `⚠️ The file does NOT contain the specified string: "${searchPattern}"`
224
- );
225
- return found;
226
- } else {
227
- const match = fileContent.match(searchPattern);
228
- if (match) {
229
- console.log(`✅ Found match: "${match[0]}"`);
230
- return match[0];
231
- } else {
232
- console.log(
233
- `⚠️ No match found for the pattern: "${searchPattern.toString()}"`
234
- );
235
- return false;
236
- }
237
- }
238
- }
239
- console.log(`✅ File content successfully retrieved.`);
240
- return fileContent;
241
- } catch (error) {
242
- console.error("❌ An error occurred while processing the file:", error);
243
- return null;
244
- }
245
- };
246
- const replaceFileContent = (filePath, searchPattern, replacement) => {
247
- try {
248
- const normalizedPath = normalizePath(filePath);
249
- const results = replaceInFileSync({
250
- files: normalizedPath,
251
- from: searchPattern,
252
- to: replacement
253
- });
254
- if (results.length > 0 && results[0].hasChanged) {
255
- console.log(
256
- `✅ Content successfully replaced in the file: ${normalizedPath}`
257
- );
258
- } else {
259
- console.log(
260
- `⚠️ No replacement made. Here are some possible reasons:
261
- - The pattern ${searchPattern} was not found.
262
- - The file might already contain the expected content.`
263
- );
264
- }
265
- } catch (error) {
266
- console.error("❌ Error while replacing the file content:", error);
267
- }
268
- };
269
- const findTailwindCssFile = (startDir, searchPattern) => {
270
- const normalizedStartDir = normalizePath(startDir);
271
- console.log("Recherche du fichier contenant le motif...", normalizedStartDir);
272
- const stack = [normalizedStartDir];
273
- while (stack.length > 0) {
274
- const currentDir = stack.pop();
275
- let files;
276
- try {
277
- files = fs.readdirSync(currentDir);
278
- } catch (error) {
279
- console.error(
280
- `Erreur lors de la lecture du répertoire ${currentDir}:`,
281
- error
282
- );
283
- continue;
284
- }
285
- for (const file of files) {
286
- const filePath = join(currentDir, file);
287
- let stats;
288
- try {
289
- stats = fs.statSync(filePath);
290
- } catch (error) {
291
- console.error(`Erreur lors de l'accès à ${filePath}:`, error);
292
- continue;
293
- }
294
- if (stats.isDirectory()) {
295
- if (file !== "node_modules" && !file.startsWith(".")) {
296
- stack.push(filePath);
297
- }
298
- } else if (stats.isFile() && (file.endsWith(".css") || file.endsWith(".scss") || file.endsWith(".sass"))) {
299
- try {
300
- console.log(`Analyse du fichier : ${filePath}`);
301
- const content = safeReadFileSync(filePath);
302
- const hasMatch = typeof searchPattern === "string" ? content.includes(searchPattern) : searchPattern.test(content);
303
- if (hasMatch) {
304
- console.log("Fichier trouvé :", filePath);
305
- return filePath;
306
- }
307
- } catch (readError) {
308
- console.error(`Erreur lors de la lecture de ${filePath}:`, readError);
309
- }
310
- }
311
- }
312
- }
313
- throw new Error(
314
- `Impossible de trouver un fichier contenant "${searchPattern}" dans "${normalizedStartDir}".`
315
- );
316
- };
317
- function findProjectRoot(startPath) {
318
- const normalizedStartPath = normalizePath(startPath);
319
- let currentPath = resolve(normalizedStartPath);
320
- while (!fs.existsSync(join(currentPath, "package.json"))) {
321
- const parentPath = dirname(currentPath);
322
- if (currentPath === parentPath) {
323
- throw new Error("Impossible de localiser la racine du projet.");
324
- }
325
- currentPath = parentPath;
326
- }
327
- return currentPath;
328
- }
329
- class TailwindPlugin extends PluginAbstract {
330
- constructor() {
331
- super(...arguments);
332
- __publicField(this, "dependencies", [FontPlugin]);
333
- __publicField(this, "name", "tailwind");
334
- __publicField(this, "pluginClass", TailwindImplPlugin);
335
- }
336
- }
337
- class TailwindImplPlugin extends PluginImplAbstract {
338
- onInit() {
339
- var _a;
340
- (_a = this.options).responsiveBreakPoints ?? (_a.responsiveBreakPoints = {
341
- lg: 1.125
342
- });
343
- }
344
- onLoad() {
345
- let udixioCssPath = this.options.styleFilePath;
346
- const projectRoot = findProjectRoot(path.resolve());
347
- if (!udixioCssPath) {
348
- const searchPattern = /@import ["']tailwindcss["'];/;
349
- const replacement = `@import 'tailwindcss';
350
- @import "./udixio.css";`;
351
- const tailwindCssPath = findTailwindCssFile(projectRoot, searchPattern);
352
- udixioCssPath = path.join(tailwindCssPath, "../udixio.css");
353
- if (!getFileContent(tailwindCssPath, /@import\s+"\.\/udixio\.css";/)) {
354
- replaceFileContent(tailwindCssPath, searchPattern, replacement);
355
- }
356
- }
357
- const colors = {};
358
- for (const isDark of [false, true]) {
359
- this.api.themes.update({ isDark });
360
- for (const [key, value] of this.api.colors.getColors().entries()) {
361
- const newKey = key.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase();
362
- colors[newKey] ?? (colors[newKey] = { light: "", dark: "" });
363
- colors[newKey][isDark ? "dark" : "light"] = value.getHex();
364
- }
365
- }
366
- const { fontStyles, fontFamily } = this.api.plugins.getPlugin(FontPlugin).getInstance().getFonts();
367
- const configCss = {
368
- colorKeys: Object.keys(colors).join(", "),
369
- fontStyles: Object.entries(fontStyles).map(
370
- ([fontRole, fontStyle]) => Object.entries(fontStyle).map(
371
- ([fontSize, fontStyle2]) => `${fontRole}-${fontSize} ${Object.entries(fontStyle2).map(([name, value]) => `${name}[${value}]`).join(" ")}`
372
- ).join(", ")
373
- ).join(", "),
374
- responsiveBreakPoints: Object.entries(
375
- this.options.responsiveBreakPoints ?? {}
376
- ).map(([key, value]) => `${key} ${value}`).join(", ")
377
- };
378
- createOrUpdateFile(
379
- udixioCssPath,
380
- `
381
- @plugin "@udixio/tailwind" {
382
- colorKeys: ${configCss.colorKeys};
383
- fontStyles: ${configCss.fontStyles};
384
- responsiveBreakPoints: ${configCss.responsiveBreakPoints};
385
- }
386
- @custom-variant dark (&:where(.dark, .dark *));
387
- @theme {
388
- --color-*: initial;
389
- ${Object.entries(colors).map(([key, value]) => `--color-${key}: ${value.light};`).join("\n ")}
390
- }
391
- @layer theme {
392
- .dark {
393
- ${Object.entries(colors).map(([key, value]) => `--color-${key}: ${value.dark};`).join("\n ")}
394
- }
395
- }
396
- @theme {
397
- ${Object.entries(fontFamily).map(
398
- ([key, values]) => `--font-${key}: ${values.map((value) => `"${value}"`).join(", ")};`
399
- ).join("\n ")}
400
- }
401
- `
402
- );
403
- }
404
- }
405
- export {
406
- TailwindPlugin,
407
- main as default,
408
- font,
409
- state
410
- };
@@ -1,16 +0,0 @@
1
- import { FontPlugin, PluginAbstract, PluginImplAbstract } from '@udixio/theme';
2
- interface TailwindPluginOptions {
3
- responsiveBreakPoints?: Record<string, number>;
4
- styleFilePath?: string;
5
- }
6
- export declare class TailwindPlugin extends PluginAbstract<TailwindImplPlugin, TailwindPluginOptions> {
7
- dependencies: (typeof FontPlugin)[];
8
- name: string;
9
- pluginClass: typeof TailwindImplPlugin;
10
- }
11
- declare class TailwindImplPlugin extends PluginImplAbstract<TailwindPluginOptions> {
12
- onInit(): void;
13
- onLoad(): void;
14
- }
15
- export {};
16
- //# sourceMappingURL=tailwind.plugin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tailwind.plugin.d.ts","sourceRoot":"","sources":["../src/tailwind.plugin.ts"],"names":[],"mappings":"AAQA,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;CA+FP"}
package/src/file.ts DELETED
@@ -1,227 +0,0 @@
1
- import * as fs from 'fs';
2
- import { replaceInFileSync } from 'replace-in-file';
3
- import * as console from 'node:console';
4
- import { dirname, join, normalize, resolve } from 'pathe';
5
- import { fileURLToPath } from 'url';
6
-
7
- // Fonction utilitaire universelle de normalisation des chemins
8
- const normalizePath = (filePath: string): string => {
9
- try {
10
- if (filePath.startsWith('file://')) {
11
- return normalize(fileURLToPath(filePath));
12
- }
13
- return normalize(filePath);
14
- } catch (error) {
15
- console.warn(
16
- `Warning: Could not process path ${filePath}, treating as regular path`,
17
- );
18
- return normalize(filePath);
19
- }
20
- };
21
-
22
- // Wrapper sécurisé pour fs.existsSync
23
- const safeExistsSync = (filePath: string): boolean => {
24
- return fs.existsSync(normalizePath(filePath));
25
- };
26
-
27
- // Wrapper sécurisé pour fs.readFileSync
28
- const safeReadFileSync = (
29
- filePath: string,
30
- encoding: BufferEncoding = 'utf8',
31
- ): string => {
32
- return fs.readFileSync(normalizePath(filePath), encoding);
33
- };
34
-
35
- // Wrapper sécurisé pour fs.writeFileSync
36
- const safeWriteFileSync = (filePath: string, data: string): void => {
37
- const normalizedPath = normalizePath(filePath);
38
- const dirPath = dirname(normalizedPath);
39
-
40
- if (!fs.existsSync(dirPath)) {
41
- fs.mkdirSync(dirPath, { recursive: true });
42
- }
43
-
44
- fs.writeFileSync(normalizedPath, data);
45
- };
46
-
47
- export const createOrUpdateFile = (filePath: string, content: string): void => {
48
- try {
49
- const normalizedPath = normalizePath(filePath);
50
-
51
- if (!safeExistsSync(filePath)) {
52
- safeWriteFileSync(filePath, content);
53
- console.log(`✅ File successfully created: ${normalizedPath}`);
54
- } else {
55
- console.log(`⚠️ File already exists: ${normalizedPath}`);
56
- replaceFileContent(filePath, /[\s\S]*/, content);
57
- }
58
- } catch (error) {
59
- console.error('❌ Error while creating the file:', error);
60
- }
61
- };
62
-
63
- export const getFileContent = (
64
- filePath: string,
65
- searchPattern?: RegExp | string,
66
- ): string | false | null => {
67
- try {
68
- const normalizedPath = normalizePath(filePath);
69
-
70
- // Vérifier si le fichier existe
71
- if (!safeExistsSync(filePath)) {
72
- console.error(`❌ The specified file does not exist: ${normalizedPath}`);
73
- return null;
74
- }
75
-
76
- // Lire le contenu du fichier entier
77
- const fileContent = safeReadFileSync(filePath);
78
-
79
- // Si un motif est fourni, chercher le texte correspondant
80
- if (searchPattern) {
81
- if (typeof searchPattern === 'string') {
82
- const found = fileContent.includes(searchPattern)
83
- ? searchPattern
84
- : false;
85
- console.log(
86
- found
87
- ? `✅ The file contains the specified string: "${searchPattern}"`
88
- : `⚠️ The file does NOT contain the specified string: "${searchPattern}"`,
89
- );
90
- return found;
91
- } else {
92
- const match = fileContent.match(searchPattern);
93
- if (match) {
94
- console.log(`✅ Found match: "${match[0]}"`);
95
- return match[0]; // Retourner le texte trouvé
96
- } else {
97
- console.log(
98
- `⚠️ No match found for the pattern: "${searchPattern.toString()}"`,
99
- );
100
- return false; // Aucune correspondance trouvée
101
- }
102
- }
103
- }
104
-
105
- // Si aucun motif n'est fourni, retourner tout le contenu
106
- console.log(`✅ File content successfully retrieved.`);
107
- return fileContent;
108
- } catch (error) {
109
- console.error('❌ An error occurred while processing the file:', error);
110
- return null;
111
- }
112
- };
113
-
114
- export const replaceFileContent = (
115
- filePath: string,
116
- searchPattern: RegExp | string,
117
- replacement: string,
118
- ): void => {
119
- try {
120
- const normalizedPath = normalizePath(filePath);
121
-
122
- const results = replaceInFileSync({
123
- files: normalizedPath,
124
- from: searchPattern,
125
- to: replacement,
126
- });
127
-
128
- if (results.length > 0 && results[0].hasChanged) {
129
- console.log(
130
- `✅ Content successfully replaced in the file: ${normalizedPath}`,
131
- );
132
- } else {
133
- console.log(
134
- `⚠️ No replacement made. Here are some possible reasons:\n- The pattern ${searchPattern} was not found.\n- The file might already contain the expected content.`,
135
- );
136
- }
137
- } catch (error) {
138
- console.error('❌ Error while replacing the file content:', error);
139
- }
140
- };
141
-
142
- export const findTailwindCssFile = (
143
- startDir: string,
144
- searchPattern: RegExp | string,
145
- ): string | never => {
146
- const normalizedStartDir = normalizePath(startDir);
147
- console.log('Recherche du fichier contenant le motif...', normalizedStartDir);
148
-
149
- const stack = [normalizedStartDir]; // Pile pour éviter une récursion implicite.
150
-
151
- while (stack.length > 0) {
152
- const currentDir = stack.pop()!; // Récupérer un répertoire de la pile.
153
-
154
- let files: string[];
155
- try {
156
- files = fs.readdirSync(currentDir);
157
- } catch (error) {
158
- console.error(
159
- `Erreur lors de la lecture du répertoire ${currentDir}:`,
160
- error,
161
- );
162
- continue;
163
- }
164
-
165
- for (const file of files) {
166
- const filePath = join(currentDir, file);
167
-
168
- let stats: fs.Stats;
169
- try {
170
- stats = fs.statSync(filePath);
171
- } catch (error) {
172
- console.error(`Erreur lors de l'accès à ${filePath}:`, error);
173
- continue; // Ignorer toute erreur d'accès.
174
- }
175
-
176
- // Ignorer le dossier `node_modules` et autres fichiers inutiles.
177
- if (stats.isDirectory()) {
178
- if (file !== 'node_modules' && !file.startsWith('.')) {
179
- stack.push(filePath); // Empiler seulement les dossiers valides.
180
- }
181
- } else if (
182
- stats.isFile() &&
183
- (file.endsWith('.css') ||
184
- file.endsWith('.scss') ||
185
- file.endsWith('.sass'))
186
- ) {
187
- try {
188
- console.log(`Analyse du fichier : ${filePath}`);
189
- const content = safeReadFileSync(filePath);
190
-
191
- // Gérer les deux types de searchPattern
192
- const hasMatch =
193
- typeof searchPattern === 'string'
194
- ? content.includes(searchPattern)
195
- : searchPattern.test(content);
196
-
197
- if (hasMatch) {
198
- console.log('Fichier trouvé :', filePath);
199
- return filePath; // Retour dès qu'un fichier valide est identifié.
200
- }
201
- } catch (readError) {
202
- console.error(`Erreur lors de la lecture de ${filePath}:`, readError);
203
- }
204
- }
205
- }
206
- }
207
-
208
- throw new Error(
209
- `Impossible de trouver un fichier contenant "${searchPattern}" dans "${normalizedStartDir}".`,
210
- );
211
- };
212
-
213
- export function findProjectRoot(startPath: string): string {
214
- const normalizedStartPath = normalizePath(startPath);
215
- let currentPath = resolve(normalizedStartPath);
216
-
217
- // Boucle jusqu'à trouver un package.json ou jusqu'à arriver à la racine du système
218
- while (!fs.existsSync(join(currentPath, 'package.json'))) {
219
- const parentPath = dirname(currentPath);
220
- if (currentPath === parentPath) {
221
- throw new Error('Impossible de localiser la racine du projet.');
222
- }
223
- currentPath = parentPath;
224
- }
225
-
226
- return currentPath;
227
- }
package/src/index.test.ts DELETED
@@ -1,5 +0,0 @@
1
- import { it } from 'vitest';
2
-
3
- it.skip('this test is skipped', () => {
4
- // Skipped test
5
- });