tailwind-to-style 2.8.5 → 2.8.8

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
@@ -506,18 +506,29 @@ export default {
506
506
  plugins: [
507
507
  twsxPlugin({
508
508
  inputDir: 'src',
509
- outputDir: 'src/styles'
509
+ outputDir: 'src/styles',
510
+ preserveStructure: false // Set to true to generate CSS next to JS files
510
511
  })
511
512
  ]
512
513
  };
513
514
  ```
514
515
 
515
- After build, individual CSS files will be created in `src/styles/` (e.g., `twsx.card.css`, `twsx.button.css`).
516
+ **Configuration Options:**
517
+ - `inputDir`: Directory to scan for `twsx.*.js` files (default: `'src'`)
518
+ - `outputDir`: Directory where CSS files will be generated (default: `'src/styles'`)
519
+ - `preserveStructure`: Whether to generate CSS files next to their JS counterparts (default: `false`)
520
+
521
+ **Default mode:** CSS files created in `src/styles/` (e.g., `twsx.card.css`, `twsx.button.css`).
522
+ **Preserve structure mode:** CSS files created next to JS files (e.g., `src/components/Card/twsx.card.css`).
523
+
516
524
  Import in your components:
517
525
  ```js
518
- // Import specific CSS files
526
+ // Default mode
519
527
  import './styles/twsx.card.css';
520
528
  import './styles/twsx.button.css';
529
+
530
+ // Preserve structure mode
531
+ import './twsx.card.css'; // If in same directory
521
532
  ```
522
533
 
523
534
  #### Webpack Plugin Usage Example
@@ -530,18 +541,29 @@ module.exports = {
530
541
  plugins: [
531
542
  new TwsxPlugin({
532
543
  inputDir: 'src',
533
- outputDir: 'src/styles'
544
+ outputDir: 'src/styles',
545
+ preserveStructure: false // Set to true to generate CSS next to JS files
534
546
  })
535
547
  ]
536
548
  };
537
549
  ```
538
550
 
539
- After build, individual CSS files will be created in `src/styles/` (e.g., `twsx.card.css`, `twsx.button.css`).
551
+ **Configuration Options:**
552
+ - `inputDir`: Directory to scan for `twsx.*.js` files (default: `'src'`)
553
+ - `outputDir`: Directory where CSS files will be generated (default: `'src/styles'`)
554
+ - `preserveStructure`: Whether to generate CSS files next to their JS counterparts (default: `false`)
555
+
556
+ **Default mode:** CSS files created in `src/styles/` (e.g., `twsx.card.css`, `twsx.button.css`).
557
+ **Preserve structure mode:** CSS files created next to JS files (e.g., `src/components/Card/twsx.card.css`).
558
+
540
559
  Import in your components:
541
560
  ```js
542
- // Import specific CSS files
561
+ // Default mode
543
562
  import './styles/twsx.card.css';
544
563
  import './styles/twsx.button.css';
564
+
565
+ // Preserve structure mode
566
+ import './twsx.card.css'; // If in same directory
545
567
  ```
546
568
 
547
569
  ## Build-Time CSS Generation via Script
@@ -568,25 +590,56 @@ node tailwind-to-style/lib/twsx-cli.js
568
590
  node tailwind-to-style/lib/twsx-cli.js --watch
569
591
  ```
570
592
 
593
+ 4. **Preserve Structure Mode (Generate CSS next to JS files):**
594
+ ```bash
595
+ # One-time build with preserve structure
596
+ node tailwind-to-style/lib/twsx-cli.js --preserve-structure
597
+
598
+ # Watch mode with preserve structure
599
+ node tailwind-to-style/lib/twsx-cli.js --watch --preserve-structure
600
+ ```
601
+
571
602
  You can configure input and output directories using environment variables:
572
603
  ```bash
573
604
  TWSX_INPUT_DIR=src TWSX_OUTPUT_DIR=dist/styles node tailwind-to-style/lib/twsx-cli.js --watch
574
605
  ```
575
606
 
576
- 4. After running, individual CSS files will be available in the output directory (default: `src/styles/`):
607
+ Or use environment variables for preserve structure:
608
+ ```bash
609
+ TWSX_PRESERVE_STRUCTURE=true node tailwind-to-style/lib/twsx-cli.js --watch
610
+ ```
611
+
612
+ 5. **Output locations:**
577
613
 
614
+ **Default mode:** CSS files will be in the output directory (default: `src/styles/`):
578
615
  ```
579
616
  src/styles/twsx.card.css
580
617
  src/styles/twsx.button.css
581
618
  ```
582
619
 
620
+ **Preserve structure mode:** CSS files will be generated next to their JS counterparts:
621
+ ```
622
+ src/components/Button/twsx.button.js → src/components/Button/twsx.button.css
623
+ src/components/Card/twsx.card.js → src/components/Card/twsx.card.css
624
+ ```
625
+
583
626
  5. Import the generated CSS files in your components:
584
627
 
628
+ **Default mode:**
585
629
  ```js
586
630
  import './styles/twsx.card.css';
587
631
  import './styles/twsx.button.css';
588
632
  ```
589
633
 
634
+ **Preserve structure mode:**
635
+ ```js
636
+ // In src/components/Button/Button.jsx
637
+ import './twsx.button.css';
638
+
639
+ // In src/components/Card/Card.jsx
640
+ import './twsx.card.css';
641
+ ```
642
+
590
643
  #### Usage in Different Projects
591
644
 
592
645
  **React/Next.js/Vue/Any Project:**
@@ -602,6 +655,8 @@ npm install tailwind-to-style
602
655
  "scripts": {
603
656
  "twsx:build": "node node_modules/tailwind-to-style/lib/twsx-cli.js",
604
657
  "twsx:watch": "node node_modules/tailwind-to-style/lib/twsx-cli.js --watch",
658
+ "twsx:preserve": "node node_modules/tailwind-to-style/lib/twsx-cli.js --preserve-structure",
659
+ "twsx:dev": "node node_modules/tailwind-to-style/lib/twsx-cli.js --watch --preserve-structure",
605
660
  "dev": "npm run twsx:watch & next dev"
606
661
  }
607
662
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * tailwind-to-style v2.8.5
2
+ * tailwind-to-style v2.8.8
3
3
  * Convert tailwind classes to inline style
4
4
  *
5
5
  * @author Bigetion
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * tailwind-to-style v2.8.5
2
+ * tailwind-to-style v2.8.8
3
3
  * Convert tailwind classes to inline style
4
4
  *
5
5
  * @author Bigetion
package/dist/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * tailwind-to-style v2.8.5
2
+ * tailwind-to-style v2.8.8
3
3
  * Convert tailwind classes to inline style
4
4
  *
5
5
  * @author Bigetion
package/lib/twsx-cli.js CHANGED
@@ -18,12 +18,13 @@ function findTwsxFiles(dir, files = []) {
18
18
  return files;
19
19
  }
20
20
 
21
- async function buildTwsx(inputDir, outputDir) {
21
+ async function buildTwsx(inputDir, outputDir, preserveStructure = false) {
22
22
  try {
23
23
  const twsxFiles = findTwsxFiles(inputDir);
24
24
  const generatedCssFiles = [];
25
25
 
26
26
  // Generate CSS from JS files
27
+ let cssWrittenCount = 0;
27
28
  for (const filePath of twsxFiles) {
28
29
  try {
29
30
  const styleModule = await import(
@@ -32,10 +33,19 @@ async function buildTwsx(inputDir, outputDir) {
32
33
  const styleObj = styleModule.default || styleModule;
33
34
  const css = twsx(styleObj, { inject: false });
34
35
  const fileName = path.basename(filePath).replace(/\.js$/, ".css");
35
- const cssFilePath = path.join(outputDir, fileName);
36
+
37
+ let cssFilePath;
38
+ if (preserveStructure) {
39
+ // Generate CSS in the same directory as the JS file
40
+ cssFilePath = filePath.replace(/\.js$/, ".css");
41
+ } else {
42
+ // Generate CSS in the output directory
43
+ cssFilePath = path.join(outputDir, fileName);
44
+ }
45
+
36
46
  fs.writeFileSync(cssFilePath, css);
37
- generatedCssFiles.push(fileName);
38
- console.log(`[twsx-cli] CSS written to ${cssFilePath}`);
47
+ generatedCssFiles.push(preserveStructure ? cssFilePath : fileName);
48
+ cssWrittenCount++;
39
49
  } catch (err) {
40
50
  console.error(
41
51
  `[twsx-cli] Error importing or processing ${filePath}:`,
@@ -43,9 +53,19 @@ async function buildTwsx(inputDir, outputDir) {
43
53
  );
44
54
  }
45
55
  }
56
+ if (cssWrittenCount > 0) {
57
+ const green = "\x1b[32m";
58
+ const reset = "\x1b[0m";
59
+ const check = green + "✔" + reset;
60
+ const now = new Date();
61
+ const time = now.toLocaleTimeString();
62
+ console.log(
63
+ `[twsx-cli] ${check} CSS updated in ${cssWrittenCount} file(s) at ${time}`
64
+ );
65
+ }
46
66
 
47
67
  // Clean up orphaned CSS files
48
- if (fs.existsSync(outputDir)) {
68
+ if (!preserveStructure && fs.existsSync(outputDir)) {
49
69
  const existingCssFiles = fs
50
70
  .readdirSync(outputDir)
51
71
  .filter((file) => file.startsWith("twsx.") && file.endsWith(".css"));
@@ -57,6 +77,33 @@ async function buildTwsx(inputDir, outputDir) {
57
77
  console.log(`[twsx-cli] Removed orphaned CSS: ${cssFilePath}`);
58
78
  }
59
79
  }
80
+ } else if (preserveStructure) {
81
+ // Clean up orphaned CSS files in preserve structure mode
82
+ const twsxFiles = findTwsxFiles(inputDir);
83
+ const expectedCssFiles = twsxFiles.map((file) =>
84
+ file.replace(/\.js$/, ".css")
85
+ );
86
+
87
+ // Find and remove orphaned CSS files
88
+ function cleanupOrphanedCss(dir) {
89
+ if (!fs.existsSync(dir)) return;
90
+
91
+ const items = fs.readdirSync(dir);
92
+ for (const item of items) {
93
+ const fullPath = path.join(dir, item);
94
+ const stat = fs.statSync(fullPath);
95
+ if (stat.isDirectory()) {
96
+ cleanupOrphanedCss(fullPath);
97
+ } else if (item.startsWith("twsx.") && item.endsWith(".css")) {
98
+ if (!expectedCssFiles.includes(fullPath)) {
99
+ fs.unlinkSync(fullPath);
100
+ console.log(`[twsx-cli] Removed orphaned CSS: ${fullPath}`);
101
+ }
102
+ }
103
+ }
104
+ }
105
+
106
+ cleanupOrphanedCss(inputDir);
60
107
  }
61
108
  } catch (err) {
62
109
  console.error("[twsx-cli] Error scanning for twsx files:", err);
@@ -67,38 +114,59 @@ const inputDir =
67
114
  process.env.TWSX_INPUT_DIR || path.resolve(process.cwd(), "src");
68
115
  const outputDir =
69
116
  process.env.TWSX_OUTPUT_DIR || path.resolve(process.cwd(), "src/styles");
70
- const watchMode = process.argv.includes("--watch") || process.env.TWSX_WATCH === "true";
117
+ const watchMode =
118
+ process.argv.includes("--watch") || process.env.TWSX_WATCH === "true";
119
+ const preserveStructure =
120
+ process.argv.includes("--preserve-structure") ||
121
+ process.env.TWSX_PRESERVE_STRUCTURE === "true";
71
122
 
72
- if (!fs.existsSync(outputDir)) {
123
+ if (!preserveStructure && !fs.existsSync(outputDir)) {
73
124
  fs.mkdirSync(outputDir, { recursive: true });
74
125
  }
75
126
 
76
127
  // Initial build
77
128
  (async () => {
78
129
  try {
79
- await buildTwsx(inputDir, outputDir);
130
+ await buildTwsx(inputDir, outputDir, preserveStructure);
80
131
  console.log(`[twsx-cli] Initial build completed`);
81
132
 
82
133
  if (watchMode) {
83
134
  console.log(`[twsx-cli] Watching for changes in ${inputDir}...`);
84
-
135
+
85
136
  const watcher = chokidar.watch(`${inputDir}/**/twsx.*.js`, {
86
137
  ignored: /node_modules/,
87
138
  persistent: true,
88
139
  });
89
140
 
141
+ let changeTimeout = null;
142
+ let pendingChange = false;
143
+ function triggerBatchBuild() {
144
+ if (changeTimeout) clearTimeout(changeTimeout);
145
+ changeTimeout = setTimeout(async () => {
146
+ pendingChange = false;
147
+ const green = "\x1b[32m";
148
+ const reset = "\x1b[0m";
149
+ const check = green + "✔" + reset;
150
+ const now = new Date();
151
+ const time = now.toLocaleTimeString();
152
+ console.log(
153
+ `[twsx-cli] ${check} Detected changes, updating CSS at ${time}`
154
+ );
155
+ await buildTwsx(inputDir, outputDir, preserveStructure);
156
+ }, 100);
157
+ }
90
158
  watcher
91
- .on("change", async (filePath) => {
92
- console.log(`[twsx-cli] File changed: ${filePath}`);
93
- await buildTwsx(inputDir, outputDir);
159
+ .on("change", () => {
160
+ pendingChange = true;
161
+ triggerBatchBuild();
94
162
  })
95
- .on("add", async (filePath) => {
96
- console.log(`[twsx-cli] File added: ${filePath}`);
97
- await buildTwsx(inputDir, outputDir);
163
+ .on("add", () => {
164
+ pendingChange = true;
165
+ triggerBatchBuild();
98
166
  })
99
- .on("unlink", async (filePath) => {
100
- console.log(`[twsx-cli] File removed: ${filePath}`);
101
- await buildTwsx(inputDir, outputDir);
167
+ .on("unlink", () => {
168
+ pendingChange = true;
169
+ triggerBatchBuild();
102
170
  });
103
171
 
104
172
  // Keep the process alive
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwind-to-style",
3
- "version": "2.8.5",
3
+ "version": "2.8.8",
4
4
  "description": "Convert tailwind classes to inline style",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -12,8 +12,7 @@
12
12
  "README.md",
13
13
  "LICENSE",
14
14
  "plugins",
15
- "lib",
16
- "twsx.css"
15
+ "lib"
17
16
  ],
18
17
  "bin": {
19
18
  "twsx-cli": "./lib/twsx-cli.js"
@@ -17,12 +17,13 @@ function findTwsxFiles(dir, files = []) {
17
17
  return files;
18
18
  }
19
19
 
20
- async function buildTwsx(inputDir, outputDir) {
20
+ async function buildTwsx(inputDir, outputDir, preserveStructure = false) {
21
21
  try {
22
22
  const twsxFiles = findTwsxFiles(inputDir);
23
23
  const generatedCssFiles = [];
24
24
 
25
25
  // Generate CSS from JS files
26
+ let cssWrittenCount = 0;
26
27
  for (const filePath of twsxFiles) {
27
28
  try {
28
29
  const styleModule = await import(
@@ -31,9 +32,25 @@ async function buildTwsx(inputDir, outputDir) {
31
32
  const styleObj = styleModule.default || styleModule;
32
33
  const css = twsx(styleObj, { inject: false });
33
34
  const fileName = path.basename(filePath).replace(/\.js$/, ".css");
34
- const cssFilePath = path.join(outputDir, fileName);
35
+
36
+ let cssFilePath;
37
+ if (preserveStructure) {
38
+ // Generate CSS file next to the JS file
39
+ cssFilePath = filePath.replace(/\.js$/, ".css");
40
+ } else {
41
+ // Generate CSS file in the output directory
42
+ cssFilePath = path.join(outputDir, fileName);
43
+ }
44
+
45
+ // Ensure the directory exists
46
+ const cssDir = path.dirname(cssFilePath);
47
+ if (!fs.existsSync(cssDir)) {
48
+ fs.mkdirSync(cssDir, { recursive: true });
49
+ }
50
+
35
51
  fs.writeFileSync(cssFilePath, css);
36
- generatedCssFiles.push(fileName);
52
+ generatedCssFiles.push(cssFilePath);
53
+ cssWrittenCount++;
37
54
  } catch (err) {
38
55
  console.error(
39
56
  `[vite-twsx] Error importing or processing ${filePath}:`,
@@ -41,32 +58,60 @@ async function buildTwsx(inputDir, outputDir) {
41
58
  );
42
59
  }
43
60
  }
61
+ if (cssWrittenCount > 0) {
62
+ const green = "\x1b[32m";
63
+ const reset = "\x1b[0m";
64
+ const check = green + "✔" + reset;
65
+ const now = new Date();
66
+ const time = now.toLocaleTimeString();
67
+ console.log(
68
+ `[vite-twsx] ${check} CSS updated in ${cssWrittenCount} file(s) at ${time}`
69
+ );
70
+ }
44
71
 
45
72
  // Clean up orphaned CSS files
46
- if (fs.existsSync(outputDir)) {
47
- const existingCssFiles = fs
48
- .readdirSync(outputDir)
49
- .filter((file) => file.startsWith("twsx.") && file.endsWith(".css"));
73
+ if (preserveStructure) {
74
+ // For preserve structure mode, clean up next to JS files
75
+ const allJsFiles = findTwsxFiles(inputDir);
76
+ for (const jsFile of allJsFiles) {
77
+ const cssFile = jsFile.replace(/\.js$/, ".css");
78
+ if (fs.existsSync(cssFile) && !generatedCssFiles.includes(cssFile)) {
79
+ fs.unlinkSync(cssFile);
80
+ }
81
+ }
82
+ } else {
83
+ // For normal mode, clean up in output directory
84
+ if (fs.existsSync(outputDir)) {
85
+ const existingCssFiles = fs
86
+ .readdirSync(outputDir)
87
+ .filter((file) => file.startsWith("twsx.") && file.endsWith(".css"));
50
88
 
51
- for (const cssFile of existingCssFiles) {
52
- if (!generatedCssFiles.includes(cssFile)) {
89
+ for (const cssFile of existingCssFiles) {
53
90
  const cssFilePath = path.join(outputDir, cssFile);
54
- fs.unlinkSync(cssFilePath);
91
+ if (!generatedCssFiles.includes(cssFilePath)) {
92
+ fs.unlinkSync(cssFilePath);
93
+ }
55
94
  }
56
95
  }
57
96
  }
97
+
98
+ return { generatedCssFiles };
58
99
  } catch (err) {
59
100
  console.error("[vite-twsx] Error scanning for twsx files:", err);
101
+ return { generatedCssFiles: [] };
60
102
  }
61
- return null;
62
103
  }
63
104
 
64
105
  export default function twsxPlugin(options = {}) {
65
106
  const inputDir = options.inputDir || path.resolve(process.cwd(), "src");
66
107
  const outputDir =
67
108
  options.outputDir || path.resolve(process.cwd(), "src/styles");
109
+ const preserveStructure = options.preserveStructure || false;
68
110
 
69
- if (!fs.existsSync(outputDir)) {
111
+ // Keep track of generated files to avoid triggering on our own changes
112
+ const generatedFiles = new Set();
113
+
114
+ if (!preserveStructure && !fs.existsSync(outputDir)) {
70
115
  fs.mkdirSync(outputDir, { recursive: true });
71
116
  }
72
117
 
@@ -74,16 +119,42 @@ export default function twsxPlugin(options = {}) {
74
119
  name: "vite-twsx",
75
120
  async buildStart() {
76
121
  try {
77
- await buildTwsx(inputDir, outputDir);
122
+ const result = await buildTwsx(inputDir, outputDir, preserveStructure);
123
+ // Track generated CSS files
124
+ if (result && result.generatedCssFiles) {
125
+ result.generatedCssFiles.forEach((file) => generatedFiles.add(file));
126
+ }
78
127
  } catch (err) {
79
128
  console.error("[vite-twsx] Error writing CSS:", err);
80
129
  }
81
130
  },
82
- async handleHotUpdate() {
83
- try {
84
- await buildTwsx(inputDir, outputDir);
85
- } catch (err) {
86
- console.error("[vite-twsx] Error updating CSS:", err);
131
+ async handleHotUpdate({ file, server }) {
132
+ // Skip if this is a CSS file we generated
133
+ if (generatedFiles.has(file)) {
134
+ return [];
135
+ }
136
+
137
+ // Only process .js files that start with "twsx."
138
+ if (file.endsWith(".js") && path.basename(file).startsWith("twsx.")) {
139
+ try {
140
+ const result = await buildTwsx(
141
+ inputDir,
142
+ outputDir,
143
+ preserveStructure
144
+ );
145
+
146
+ // Update our tracking of generated files
147
+ if (result && result.generatedCssFiles) {
148
+ generatedFiles.clear();
149
+ result.generatedCssFiles.forEach((f) => generatedFiles.add(f));
150
+ }
151
+
152
+ // Return empty array to prevent default HMR handling
153
+ return [];
154
+ } catch (err) {
155
+ console.error("[vite-twsx] Error updating CSS:", err);
156
+ return [];
157
+ }
87
158
  }
88
159
  },
89
160
  };
@@ -17,12 +17,13 @@ function findTwsxFiles(dir, files = []) {
17
17
  return files;
18
18
  }
19
19
 
20
- async function buildTwsx(inputDir, outputDir) {
20
+ async function buildTwsx(inputDir, outputDir, preserveStructure = false) {
21
21
  try {
22
22
  const twsxFiles = findTwsxFiles(inputDir);
23
23
  const generatedCssFiles = [];
24
24
 
25
25
  // Generate CSS from JS files
26
+ let cssWrittenCount = 0;
26
27
  for (const filePath of twsxFiles) {
27
28
  try {
28
29
  const styleModule = await import(
@@ -31,9 +32,25 @@ async function buildTwsx(inputDir, outputDir) {
31
32
  const styleObj = styleModule.default || styleModule;
32
33
  const css = twsx(styleObj, { inject: false });
33
34
  const fileName = path.basename(filePath).replace(/\.js$/, ".css");
34
- const cssFilePath = path.join(outputDir, fileName);
35
+
36
+ let cssFilePath;
37
+ if (preserveStructure) {
38
+ // Generate CSS file next to the JS file
39
+ cssFilePath = filePath.replace(/\.js$/, ".css");
40
+ } else {
41
+ // Generate CSS file in the output directory
42
+ cssFilePath = path.join(outputDir, fileName);
43
+ }
44
+
45
+ // Ensure the directory exists
46
+ const cssDir = path.dirname(cssFilePath);
47
+ if (!fs.existsSync(cssDir)) {
48
+ fs.mkdirSync(cssDir, { recursive: true });
49
+ }
50
+
35
51
  fs.writeFileSync(cssFilePath, css);
36
- generatedCssFiles.push(fileName);
52
+ generatedCssFiles.push(preserveStructure ? cssFilePath : fileName);
53
+ cssWrittenCount++;
37
54
  } catch (err) {
38
55
  console.error(
39
56
  `[webpack-twsx] Error importing or processing ${filePath}:`,
@@ -41,18 +58,43 @@ async function buildTwsx(inputDir, outputDir) {
41
58
  );
42
59
  }
43
60
  }
61
+ if (cssWrittenCount > 0) {
62
+ const green = "\x1b[32m";
63
+ const reset = "\x1b[0m";
64
+ const check = green + "✔" + reset;
65
+ const now = new Date();
66
+ const time = now.toLocaleTimeString();
67
+ console.log(
68
+ `[webpack-twsx] ${check} CSS updated in ${cssWrittenCount} file(s) at ${time}`
69
+ );
70
+ }
44
71
 
45
72
  // Clean up orphaned CSS files
46
- if (fs.existsSync(outputDir)) {
47
- const existingCssFiles = fs.readdirSync(outputDir).filter((file) => {
48
- return file.startsWith("twsx.") && file.endsWith(".css");
49
- });
73
+ if (preserveStructure) {
74
+ // For preserve structure mode, clean up next to JS files
75
+ const allJsFiles = findTwsxFiles(inputDir);
76
+ for (const jsFile of allJsFiles) {
77
+ const cssFile = jsFile.replace(/\.js$/, ".css");
78
+ if (fs.existsSync(cssFile) && !generatedCssFiles.includes(cssFile)) {
79
+ fs.unlinkSync(cssFile);
80
+ }
81
+ }
82
+ } else {
83
+ // For normal mode, clean up in output directory
84
+ if (fs.existsSync(outputDir)) {
85
+ const existingCssFiles = fs.readdirSync(outputDir).filter((file) => {
86
+ return file.startsWith("twsx.") && file.endsWith(".css");
87
+ });
50
88
 
51
- if (Array.isArray(existingCssFiles) && Array.isArray(generatedCssFiles)) {
52
- for (const cssFile of existingCssFiles) {
53
- if (!generatedCssFiles.includes(cssFile)) {
54
- const cssFilePath = path.join(outputDir, cssFile);
55
- fs.unlinkSync(cssFilePath);
89
+ if (
90
+ Array.isArray(existingCssFiles) &&
91
+ Array.isArray(generatedCssFiles)
92
+ ) {
93
+ for (const cssFile of existingCssFiles) {
94
+ if (!generatedCssFiles.includes(cssFile)) {
95
+ const cssFilePath = path.join(outputDir, cssFile);
96
+ fs.unlinkSync(cssFilePath);
97
+ }
56
98
  }
57
99
  }
58
100
  }
@@ -67,7 +109,9 @@ class TwsxPlugin {
67
109
  this.inputDir = options.inputDir || path.resolve(process.cwd(), "src");
68
110
  this.outputDir =
69
111
  options.outputDir || path.resolve(process.cwd(), "src/styles");
70
- if (!fs.existsSync(this.outputDir)) {
112
+ this.preserveStructure = options.preserveStructure || false;
113
+
114
+ if (!this.preserveStructure && !fs.existsSync(this.outputDir)) {
71
115
  fs.mkdirSync(this.outputDir, { recursive: true });
72
116
  }
73
117
  }
@@ -75,14 +119,14 @@ class TwsxPlugin {
75
119
  apply(compiler) {
76
120
  compiler.hooks.beforeCompile.tapPromise("TwsxPlugin", async () => {
77
121
  try {
78
- await buildTwsx(this.inputDir, this.outputDir);
122
+ await buildTwsx(this.inputDir, this.outputDir, this.preserveStructure);
79
123
  } catch (err) {
80
124
  console.error("[webpack-twsx] Error writing CSS:", err);
81
125
  }
82
126
  });
83
127
  compiler.hooks.watchRun.tapPromise("TwsxPlugin", async () => {
84
128
  try {
85
- await buildTwsx(this.inputDir, this.outputDir);
129
+ await buildTwsx(this.inputDir, this.outputDir, this.preserveStructure);
86
130
  } catch (err) {
87
131
  console.error("[webpack-twsx] Error updating CSS:", err);
88
132
  }
package/twsx.css DELETED
File without changes