@shohojdhara/atomix 0.4.7 → 0.4.9
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/atomix.config.ts +58 -1
- package/dist/atomix.css +172 -157
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +4 -4
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +33 -0
- package/dist/charts.js +1274 -164
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +33 -10
- package/dist/core.js +1099 -83
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +33 -0
- package/dist/forms.js +2106 -1050
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +42 -1
- package/dist/heavy.js +1663 -638
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +442 -270
- package/dist/index.esm.js +1947 -680
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1982 -712
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +6 -3
- package/scripts/atomix-cli.js +136 -1827
- package/scripts/cli/__tests__/basic.test.js +3 -2
- package/scripts/cli/__tests__/clean.test.js +278 -0
- package/scripts/cli/__tests__/component-validator.test.js +433 -0
- package/scripts/cli/__tests__/generator.test.js +613 -0
- package/scripts/cli/__tests__/glass-motion.test.js +256 -0
- package/scripts/cli/__tests__/integration.test.js +719 -108
- package/scripts/cli/__tests__/migrate.test.js +74 -0
- package/scripts/cli/__tests__/security.test.js +206 -0
- package/scripts/cli/__tests__/test-setup.js +3 -1
- package/scripts/cli/__tests__/theme-bridge.test.js +507 -0
- package/scripts/cli/__tests__/token-provider.test.js +361 -0
- package/scripts/cli/__tests__/utils.test.js +5 -5
- package/scripts/cli/commands/benchmark.js +105 -0
- package/scripts/cli/commands/build-theme.js +115 -0
- package/scripts/cli/commands/clean.js +109 -0
- package/scripts/cli/commands/doctor.js +88 -0
- package/scripts/cli/commands/generate.js +218 -0
- package/scripts/cli/commands/init.js +73 -0
- package/scripts/cli/commands/migrate.js +106 -0
- package/scripts/cli/commands/sync-tokens.js +206 -0
- package/scripts/cli/commands/theme-bridge.js +248 -0
- package/scripts/cli/commands/tokens.js +157 -0
- package/scripts/cli/commands/validate.js +194 -0
- package/scripts/cli/internal/ai-engine.js +156 -0
- package/scripts/cli/internal/compiler.js +114 -0
- package/scripts/cli/internal/component-validator.js +443 -0
- package/scripts/cli/internal/config-loader.js +162 -0
- package/scripts/cli/internal/filesystem.js +158 -0
- package/scripts/cli/internal/generator.js +430 -0
- package/scripts/cli/internal/glass-generator.js +398 -0
- package/scripts/cli/internal/hook-generator.js +369 -0
- package/scripts/cli/internal/hooks.js +61 -0
- package/scripts/cli/internal/itcss-generator.js +565 -0
- package/scripts/cli/internal/motion-generator.js +679 -0
- package/scripts/cli/internal/template-engine.js +301 -0
- package/scripts/cli/internal/theme-bridge.js +664 -0
- package/scripts/cli/internal/tokens/engine.js +122 -0
- package/scripts/cli/internal/tokens/provider.js +34 -0
- package/scripts/cli/internal/tokens/providers/figma.js +50 -0
- package/scripts/cli/internal/tokens/providers/style-dictionary.js +48 -0
- package/scripts/cli/internal/tokens/providers/w3c.js +48 -0
- package/scripts/cli/internal/tokens/token-provider.js +443 -0
- package/scripts/cli/internal/tokens/token-validator.js +513 -0
- package/scripts/cli/internal/validator.js +276 -0
- package/scripts/cli/internal/wizard.js +115 -0
- package/scripts/cli/mappings.js +23 -0
- package/scripts/cli/migration-tools.js +164 -94
- package/scripts/cli/plugins/style-dictionary.js +46 -0
- package/scripts/cli/templates/README.md +525 -95
- package/scripts/cli/templates/common-templates.js +40 -14
- package/scripts/cli/templates/components/react-component.ts +282 -0
- package/scripts/cli/templates/config/project-config.ts +112 -0
- package/scripts/cli/templates/hooks/use-component.ts +477 -0
- package/scripts/cli/templates/index.js +19 -4
- package/scripts/cli/templates/index.ts +171 -0
- package/scripts/cli/templates/next-templates.js +72 -0
- package/scripts/cli/templates/react-templates.js +70 -126
- package/scripts/cli/templates/scss-templates.js +35 -35
- package/scripts/cli/templates/stories/storybook-story.ts +241 -0
- package/scripts/cli/templates/styles/scss-component.ts +255 -0
- package/scripts/cli/templates/tests/vitest-test.ts +229 -0
- package/scripts/cli/templates/token-templates.js +337 -1
- package/scripts/cli/templates/tokens/token-generators.ts +1088 -0
- package/scripts/cli/templates/types/component-types.ts +145 -0
- package/scripts/cli/templates/utils/testing-utils.ts +144 -0
- package/scripts/cli/templates/vanilla-templates.js +39 -0
- package/scripts/cli/token-manager.js +8 -2
- package/scripts/cli/utils/cache-manager.js +240 -0
- package/scripts/cli/utils/detector.js +46 -0
- package/scripts/cli/utils/diagnostics.js +289 -0
- package/scripts/cli/utils/error.js +89 -0
- package/scripts/cli/utils/helpers.js +67 -0
- package/scripts/cli/utils/logger.js +75 -0
- package/scripts/cli/utils/security.js +302 -0
- package/scripts/cli/utils/telemetry.js +115 -0
- package/scripts/cli/utils/validation.js +37 -0
- package/scripts/cli/utils.js +28 -341
- package/src/components/Accordion/Accordion.stories.tsx +0 -18
- package/src/components/Accordion/Accordion.test.tsx +0 -17
- package/src/components/Accordion/Accordion.tsx +0 -4
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +37 -3
- package/src/components/AtomixGlass/AtomixGlass.tsx +143 -31
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +129 -31
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +219 -0
- package/src/components/AtomixGlass/README.md +25 -10
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +216 -0
- package/src/components/AtomixGlass/animation-system.ts +578 -0
- package/src/components/AtomixGlass/shader-utils.ts +4 -1
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +157 -6
- package/src/components/AtomixGlass/stories/Phase1-Animation.stories.tsx +653 -0
- package/src/components/AtomixGlass/stories/Phase1-Test.stories.tsx +95 -0
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +51 -51
- package/src/components/AtomixGlass/stories/shared-components.tsx +6 -0
- package/src/components/Avatar/Avatar.tsx +1 -1
- package/src/components/Button/Button.stories.disabled-link.tsx +10 -0
- package/src/components/Button/Button.stories.tsx +10 -0
- package/src/components/Button/Button.test.tsx +16 -11
- package/src/components/Button/Button.tsx +4 -4
- package/src/components/Card/Card.tsx +1 -1
- package/src/components/Dropdown/Dropdown.tsx +12 -12
- package/src/components/Form/Select.tsx +62 -3
- package/src/components/Modal/Modal.tsx +14 -3
- package/src/components/Navigation/Navbar/Navbar.tsx +44 -0
- package/src/components/Slider/Slider.stories.tsx +3 -3
- package/src/components/Slider/Slider.tsx +38 -0
- package/src/components/Steps/Steps.tsx +3 -3
- package/src/components/Tabs/Tabs.tsx +77 -8
- package/src/components/Testimonial/Testimonial.tsx +1 -1
- package/src/components/TypedButton/TypedButton.stories.tsx +59 -0
- package/src/components/TypedButton/TypedButton.tsx +39 -0
- package/src/components/TypedButton/index.ts +2 -0
- package/src/components/VideoPlayer/VideoPlayer.tsx +11 -4
- package/src/lib/composables/index.ts +4 -7
- package/src/lib/composables/types.ts +45 -0
- package/src/lib/composables/useAccordion.ts +0 -7
- package/src/lib/composables/useAtomixGlass.ts +148 -6
- package/src/lib/composables/useAtomixGlassStyles.ts +9 -7
- package/src/lib/composables/useChartExport.ts +3 -13
- package/src/lib/composables/useDropdown.ts +66 -0
- package/src/lib/composables/useFocusTrap.ts +80 -0
- package/src/lib/composables/usePerformanceMonitor.ts +448 -0
- package/src/lib/composables/useResponsiveGlass.presets.ts +192 -0
- package/src/lib/composables/useResponsiveGlass.ts +441 -0
- package/src/lib/composables/useTooltip.ts +16 -0
- package/src/lib/composables/useTypedButton.ts +66 -0
- package/src/lib/config/index.ts +62 -5
- package/src/lib/constants/components.ts +62 -7
- package/src/lib/theme/devtools/__tests__/useHistory.test.tsx +150 -0
- package/src/lib/theme/tokens/centralized-tokens.ts +120 -0
- package/src/lib/theme/utils/__tests__/domUtils.test.ts +101 -0
- package/src/lib/types/components.ts +37 -11
- package/src/lib/types/glass.ts +35 -0
- package/src/lib/types/index.ts +1 -0
- package/src/lib/utils/displacement-generator.ts +1 -1
- package/src/styles/01-settings/_settings.testtypecheck.scss +53 -0
- package/src/styles/01-settings/_settings.typedbutton.scss +53 -0
- package/src/styles/06-components/_components.atomix-glass.scss +17 -21
- package/src/styles/06-components/_components.edge-panel.scss +1 -5
- package/src/styles/06-components/_components.modal.scss +1 -4
- package/src/styles/06-components/_components.navbar.scss +1 -1
- package/src/styles/06-components/_components.testbutton.scss +212 -0
- package/src/styles/06-components/_components.testtypecheck.scss +212 -0
- package/src/styles/06-components/_components.tooltip.scss +9 -5
- package/src/styles/06-components/_components.typedbutton.scss +212 -0
- package/src/styles/99-utilities/_index.scss +1 -0
- package/src/styles/99-utilities/_utilities.text.scss +1 -1
- package/src/styles/99-utilities/_utilities.touch-target.scss +36 -0
- package/scripts/cli/component-generator.js +0 -564
- package/scripts/cli/interactive-init.js +0 -357
- package/src/styles/06-components/old.chart.styles.scss +0 -2788
|
@@ -4,30 +4,57 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { readFile, writeFile, readdir, lstat } from 'fs/promises';
|
|
7
|
-
import { join, extname, relative } from 'path';
|
|
7
|
+
import { join, extname, relative, basename } from 'path';
|
|
8
8
|
import chalk from 'chalk';
|
|
9
9
|
import ora from 'ora';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
scssVariableMigration
|
|
15
|
-
} from './mappings.js';
|
|
10
|
+
import { filesystem } from './internal/filesystem.js';
|
|
11
|
+
import { AtomixCLIError } from './utils/error.js';
|
|
12
|
+
import { tailwindToAtomix, bootstrapToAtomix, scssVariableMigration } from './mappings.js';
|
|
13
|
+
import { logger } from './utils/logger.js';
|
|
16
14
|
|
|
15
|
+
const sanitizeInput = (input) => input.trim(); // Simple mock if sanitizeInput is missing
|
|
17
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Show a simple side-by-side diff for migration preview
|
|
19
|
+
*/
|
|
20
|
+
function showPreviewDiff(file, original, modified) {
|
|
21
|
+
const originalLines = original.split('\n');
|
|
22
|
+
const modifiedLines = modified.split('\n');
|
|
23
|
+
const diffs = [];
|
|
24
|
+
|
|
25
|
+
for (let i = 0; i < originalLines.length; i++) {
|
|
26
|
+
if (originalLines[i] !== modifiedLines[i]) {
|
|
27
|
+
diffs.push({
|
|
28
|
+
line: i + 1,
|
|
29
|
+
old: originalLines[i].trim(),
|
|
30
|
+
new: modifiedLines[i].trim()
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (diffs.length > 0) {
|
|
36
|
+
console.log(`\n${chalk.bold.blue('Preview for:')} ${chalk.cyan(relative(process.cwd(), file))}`);
|
|
37
|
+
diffs.slice(0, 5).forEach(d => {
|
|
38
|
+
console.log(`${chalk.gray(d.line + ':')} ${chalk.red('- ' + d.old)}`);
|
|
39
|
+
console.log(`${chalk.gray(' ')} ${chalk.green('+ ' + d.new)}`);
|
|
40
|
+
});
|
|
41
|
+
if (diffs.length > 5) {
|
|
42
|
+
console.log(chalk.gray(` ... and ${diffs.length - 5} more changes`));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
18
46
|
|
|
19
47
|
/**
|
|
20
48
|
* Migrate Tailwind classes to Atomix
|
|
21
49
|
*/
|
|
22
50
|
export async function migrateTailwind(sourcePath, options = {}) {
|
|
23
51
|
const sanitizedSource = sanitizeInput(sourcePath);
|
|
24
|
-
const sourceValidation = validatePath(sanitizedSource);
|
|
52
|
+
const sourceValidation = filesystem.validatePath(sanitizedSource);
|
|
25
53
|
if (!sourceValidation.isValid) {
|
|
26
|
-
throw new AtomixCLIError(
|
|
27
|
-
|
|
28
|
-
'
|
|
29
|
-
|
|
30
|
-
);
|
|
54
|
+
throw new AtomixCLIError(sourceValidation.error, 'INVALID_PATH', [
|
|
55
|
+
'Provide a valid path within the project',
|
|
56
|
+
'Check for typos',
|
|
57
|
+
]);
|
|
31
58
|
}
|
|
32
59
|
const safeSource = sourceValidation.safePath;
|
|
33
60
|
const spinner = ora('Migrating from Tailwind CSS...').start();
|
|
@@ -35,19 +62,23 @@ export async function migrateTailwind(sourcePath, options = {}) {
|
|
|
35
62
|
filesProcessed: 0,
|
|
36
63
|
classesReplaced: 0,
|
|
37
64
|
warnings: [],
|
|
38
|
-
errors: []
|
|
65
|
+
errors: [],
|
|
39
66
|
};
|
|
40
67
|
|
|
41
68
|
try {
|
|
42
69
|
const files = await getAllFiles(safeSource, ['.jsx', '.tsx', '.js', '.ts', '.html']);
|
|
43
70
|
|
|
44
|
-
|
|
45
|
-
spinner.text = `Processing ${relative(process.cwd(), file)}...`;
|
|
71
|
+
let processedCount = 0;
|
|
46
72
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
73
|
+
// Process files in batches to prevent "too many open files" errors
|
|
74
|
+
const batchSize = 50;
|
|
75
|
+
for (let i = 0; i < files.length; i += batchSize) {
|
|
76
|
+
const batch = files.slice(i, i + batchSize);
|
|
77
|
+
await Promise.all(batch.map(async (file) => {
|
|
78
|
+
try {
|
|
79
|
+
let content = await readFile(file, 'utf8');
|
|
80
|
+
const originalContent = content;
|
|
81
|
+
let replacementCount = 0;
|
|
51
82
|
|
|
52
83
|
// Replace className attributes
|
|
53
84
|
content = content.replace(/className=["']([^"']+)["']/g, (match, classes) => {
|
|
@@ -71,11 +102,16 @@ export async function migrateTailwind(sourcePath, options = {}) {
|
|
|
71
102
|
}
|
|
72
103
|
|
|
73
104
|
// If no mapping found, keep original
|
|
74
|
-
if (
|
|
105
|
+
if (
|
|
106
|
+
trimmed &&
|
|
107
|
+
!trimmed.startsWith('c-') &&
|
|
108
|
+
!trimmed.startsWith('u-') &&
|
|
109
|
+
!trimmed.startsWith('o-')
|
|
110
|
+
) {
|
|
75
111
|
report.warnings.push({
|
|
76
112
|
file: relative(process.cwd(), file),
|
|
77
113
|
class: trimmed,
|
|
78
|
-
message: 'No Atomix equivalent found'
|
|
114
|
+
message: 'No Atomix equivalent found',
|
|
79
115
|
});
|
|
80
116
|
}
|
|
81
117
|
|
|
@@ -101,8 +137,12 @@ export async function migrateTailwind(sourcePath, options = {}) {
|
|
|
101
137
|
});
|
|
102
138
|
|
|
103
139
|
if (content !== originalContent) {
|
|
104
|
-
if (options.dryRun) {
|
|
105
|
-
|
|
140
|
+
if (options.dryRun || options.preview) {
|
|
141
|
+
if (options.preview) {
|
|
142
|
+
showPreviewDiff(file, originalContent, content);
|
|
143
|
+
} else {
|
|
144
|
+
console.log(chalk.yellow(` Would update: ${file}`));
|
|
145
|
+
}
|
|
106
146
|
} else {
|
|
107
147
|
await writeFile(file, content, 'utf8');
|
|
108
148
|
report.filesProcessed++;
|
|
@@ -110,18 +150,21 @@ export async function migrateTailwind(sourcePath, options = {}) {
|
|
|
110
150
|
}
|
|
111
151
|
}
|
|
112
152
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
153
|
+
processedCount++;
|
|
154
|
+
spinner.text = `Processing files (${processedCount}/${files.length})...`;
|
|
155
|
+
|
|
156
|
+
} catch (error) {
|
|
157
|
+
report.errors.push({
|
|
158
|
+
file: relative(process.cwd(), file),
|
|
159
|
+
error: error.message
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}));
|
|
119
163
|
}
|
|
120
164
|
|
|
121
165
|
spinner.succeed(chalk.green('Tailwind migration complete!'));
|
|
122
166
|
|
|
123
167
|
return report;
|
|
124
|
-
|
|
125
168
|
} catch (error) {
|
|
126
169
|
spinner.fail(chalk.red('Migration failed'));
|
|
127
170
|
throw error;
|
|
@@ -133,13 +176,12 @@ export async function migrateTailwind(sourcePath, options = {}) {
|
|
|
133
176
|
*/
|
|
134
177
|
export async function migrateBootstrap(sourcePath, options = {}) {
|
|
135
178
|
const sanitizedSource = sanitizeInput(sourcePath);
|
|
136
|
-
const sourceValidation = validatePath(sanitizedSource);
|
|
179
|
+
const sourceValidation = filesystem.validatePath(sanitizedSource);
|
|
137
180
|
if (!sourceValidation.isValid) {
|
|
138
|
-
throw new AtomixCLIError(
|
|
139
|
-
|
|
140
|
-
'
|
|
141
|
-
|
|
142
|
-
);
|
|
181
|
+
throw new AtomixCLIError(sourceValidation.error, 'INVALID_PATH', [
|
|
182
|
+
'Provide a valid path within the project',
|
|
183
|
+
'Check for typos',
|
|
184
|
+
]);
|
|
143
185
|
}
|
|
144
186
|
const safeSource = sourceValidation.safePath;
|
|
145
187
|
const spinner = ora('Migrating from Bootstrap...').start();
|
|
@@ -147,19 +189,22 @@ export async function migrateBootstrap(sourcePath, options = {}) {
|
|
|
147
189
|
filesProcessed: 0,
|
|
148
190
|
classesReplaced: 0,
|
|
149
191
|
warnings: [],
|
|
150
|
-
errors: []
|
|
192
|
+
errors: [],
|
|
151
193
|
};
|
|
152
194
|
|
|
153
195
|
try {
|
|
154
196
|
const files = await getAllFiles(safeSource, ['.jsx', '.tsx', '.js', '.ts', '.html']);
|
|
155
197
|
|
|
156
|
-
|
|
157
|
-
spinner.text = `Processing ${relative(process.cwd(), file)}...`;
|
|
198
|
+
let processedCount = 0;
|
|
158
199
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
200
|
+
const batchSize = 50;
|
|
201
|
+
for (let i = 0; i < files.length; i += batchSize) {
|
|
202
|
+
const batch = files.slice(i, i + batchSize);
|
|
203
|
+
await Promise.all(batch.map(async (file) => {
|
|
204
|
+
try {
|
|
205
|
+
let content = await readFile(file, 'utf8');
|
|
206
|
+
const originalContent = content;
|
|
207
|
+
let replacementCount = 0;
|
|
163
208
|
|
|
164
209
|
// Replace className/class attributes
|
|
165
210
|
const classPattern = /(className|class)=["']([^"']+)["']/g;
|
|
@@ -191,11 +236,16 @@ export async function migrateBootstrap(sourcePath, options = {}) {
|
|
|
191
236
|
}
|
|
192
237
|
|
|
193
238
|
// If no mapping found, keep original
|
|
194
|
-
if (
|
|
239
|
+
if (
|
|
240
|
+
trimmed &&
|
|
241
|
+
!trimmed.startsWith('c-') &&
|
|
242
|
+
!trimmed.startsWith('u-') &&
|
|
243
|
+
!trimmed.startsWith('o-')
|
|
244
|
+
) {
|
|
195
245
|
report.warnings.push({
|
|
196
246
|
file: relative(process.cwd(), file),
|
|
197
247
|
class: trimmed,
|
|
198
|
-
message: 'No Atomix equivalent found'
|
|
248
|
+
message: 'No Atomix equivalent found',
|
|
199
249
|
});
|
|
200
250
|
}
|
|
201
251
|
|
|
@@ -206,8 +256,12 @@ export async function migrateBootstrap(sourcePath, options = {}) {
|
|
|
206
256
|
});
|
|
207
257
|
|
|
208
258
|
if (content !== originalContent) {
|
|
209
|
-
if (options.dryRun) {
|
|
210
|
-
|
|
259
|
+
if (options.dryRun || options.preview) {
|
|
260
|
+
if (options.preview) {
|
|
261
|
+
showPreviewDiff(file, originalContent, content);
|
|
262
|
+
} else {
|
|
263
|
+
console.log(chalk.yellow(` Would update: ${file}`));
|
|
264
|
+
}
|
|
211
265
|
} else {
|
|
212
266
|
await writeFile(file, content, 'utf8');
|
|
213
267
|
report.filesProcessed++;
|
|
@@ -215,18 +269,21 @@ export async function migrateBootstrap(sourcePath, options = {}) {
|
|
|
215
269
|
}
|
|
216
270
|
}
|
|
217
271
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
272
|
+
processedCount++;
|
|
273
|
+
spinner.text = `Processing files (${processedCount}/${files.length})...`;
|
|
274
|
+
|
|
275
|
+
} catch (error) {
|
|
276
|
+
report.errors.push({
|
|
277
|
+
file: relative(process.cwd(), file),
|
|
278
|
+
error: error.message
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}));
|
|
224
282
|
}
|
|
225
283
|
|
|
226
284
|
spinner.succeed(chalk.green('Bootstrap migration complete!'));
|
|
227
285
|
|
|
228
286
|
return report;
|
|
229
|
-
|
|
230
287
|
} catch (error) {
|
|
231
288
|
spinner.fail(chalk.red('Migration failed'));
|
|
232
289
|
throw error;
|
|
@@ -238,13 +295,12 @@ export async function migrateBootstrap(sourcePath, options = {}) {
|
|
|
238
295
|
*/
|
|
239
296
|
export async function migrateSCSSVariables(sourcePath, options = {}) {
|
|
240
297
|
const sanitizedSource = sanitizeInput(sourcePath);
|
|
241
|
-
const sourceValidation = validatePath(sanitizedSource);
|
|
298
|
+
const sourceValidation = filesystem.validatePath(sanitizedSource);
|
|
242
299
|
if (!sourceValidation.isValid) {
|
|
243
|
-
throw new AtomixCLIError(
|
|
244
|
-
|
|
245
|
-
'
|
|
246
|
-
|
|
247
|
-
);
|
|
300
|
+
throw new AtomixCLIError(sourceValidation.error, 'INVALID_PATH', [
|
|
301
|
+
'Provide a valid path within the project',
|
|
302
|
+
'Check for typos',
|
|
303
|
+
]);
|
|
248
304
|
}
|
|
249
305
|
const safeSource = sourceValidation.safePath;
|
|
250
306
|
const spinner = ora('Migrating SCSS variables to design tokens...').start();
|
|
@@ -252,19 +308,22 @@ export async function migrateSCSSVariables(sourcePath, options = {}) {
|
|
|
252
308
|
filesProcessed: 0,
|
|
253
309
|
variablesReplaced: 0,
|
|
254
310
|
warnings: [],
|
|
255
|
-
errors: []
|
|
311
|
+
errors: [],
|
|
256
312
|
};
|
|
257
313
|
|
|
258
314
|
try {
|
|
259
315
|
const files = await getAllFiles(safeSource, ['.scss', '.sass', '.css']);
|
|
260
316
|
|
|
261
|
-
|
|
262
|
-
spinner.text = `Processing ${relative(process.cwd(), file)}...`;
|
|
317
|
+
let processedCount = 0;
|
|
263
318
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
319
|
+
const batchSize = 50;
|
|
320
|
+
for (let i = 0; i < files.length; i += batchSize) {
|
|
321
|
+
const batch = files.slice(i, i + batchSize);
|
|
322
|
+
await Promise.all(batch.map(async (file) => {
|
|
323
|
+
try {
|
|
324
|
+
let content = await readFile(file, 'utf8');
|
|
325
|
+
const originalContent = content;
|
|
326
|
+
let replacementCount = 0;
|
|
268
327
|
|
|
269
328
|
// Replace SCSS variables with CSS custom properties
|
|
270
329
|
for (const [scssVar, cssVar] of Object.entries(scssVariableMigration)) {
|
|
@@ -284,15 +343,19 @@ export async function migrateSCSSVariables(sourcePath, options = {}) {
|
|
|
284
343
|
report.warnings.push({
|
|
285
344
|
file: relative(process.cwd(), file),
|
|
286
345
|
variable: varName,
|
|
287
|
-
message: 'No design token equivalent found'
|
|
346
|
+
message: 'No design token equivalent found',
|
|
288
347
|
});
|
|
289
348
|
}
|
|
290
349
|
});
|
|
291
350
|
}
|
|
292
351
|
|
|
293
352
|
if (content !== originalContent) {
|
|
294
|
-
if (options.dryRun) {
|
|
295
|
-
|
|
353
|
+
if (options.dryRun || options.preview) {
|
|
354
|
+
if (options.preview) {
|
|
355
|
+
showPreviewDiff(file, originalContent, content);
|
|
356
|
+
} else {
|
|
357
|
+
console.log(chalk.yellow(` Would update: ${file}`));
|
|
358
|
+
}
|
|
296
359
|
} else {
|
|
297
360
|
await writeFile(file, content, 'utf8');
|
|
298
361
|
report.filesProcessed++;
|
|
@@ -300,18 +363,21 @@ export async function migrateSCSSVariables(sourcePath, options = {}) {
|
|
|
300
363
|
}
|
|
301
364
|
}
|
|
302
365
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
366
|
+
processedCount++;
|
|
367
|
+
spinner.text = `Processing files (${processedCount}/${files.length})...`;
|
|
368
|
+
|
|
369
|
+
} catch (error) {
|
|
370
|
+
report.errors.push({
|
|
371
|
+
file: relative(process.cwd(), file),
|
|
372
|
+
error: error.message
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
}));
|
|
309
376
|
}
|
|
310
377
|
|
|
311
378
|
spinner.succeed(chalk.green('SCSS variable migration complete!'));
|
|
312
379
|
|
|
313
380
|
return report;
|
|
314
|
-
|
|
315
381
|
} catch (error) {
|
|
316
382
|
spinner.fail(chalk.red('Migration failed'));
|
|
317
383
|
throw error;
|
|
@@ -327,22 +393,24 @@ async function getAllFiles(dir, extensions = []) {
|
|
|
327
393
|
async function walk(currentPath) {
|
|
328
394
|
const entries = await readdir(currentPath);
|
|
329
395
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
396
|
+
await Promise.all(
|
|
397
|
+
entries.map(async entry => {
|
|
398
|
+
const fullPath = join(currentPath, entry);
|
|
399
|
+
const stats = await lstat(fullPath);
|
|
333
400
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
401
|
+
if (stats.isDirectory()) {
|
|
402
|
+
// Skip node_modules and hidden directories
|
|
403
|
+
if (!entry.startsWith('.') && entry !== 'node_modules') {
|
|
404
|
+
await walk(fullPath);
|
|
405
|
+
}
|
|
406
|
+
} else if (stats.isFile()) {
|
|
407
|
+
const ext = extname(fullPath);
|
|
408
|
+
if (extensions.length === 0 || extensions.includes(ext)) {
|
|
409
|
+
files.push(fullPath);
|
|
410
|
+
}
|
|
343
411
|
}
|
|
344
|
-
}
|
|
345
|
-
|
|
412
|
+
})
|
|
413
|
+
);
|
|
346
414
|
}
|
|
347
415
|
|
|
348
416
|
await walk(dir);
|
|
@@ -357,7 +425,9 @@ export function displayMigrationReport(report) {
|
|
|
357
425
|
console.log(chalk.gray('='.repeat(50)));
|
|
358
426
|
|
|
359
427
|
console.log(chalk.cyan(`Files processed: ${report.filesProcessed}`));
|
|
360
|
-
console.log(
|
|
428
|
+
console.log(
|
|
429
|
+
chalk.cyan(`Classes/Variables replaced: ${report.classesReplaced || report.variablesReplaced}`)
|
|
430
|
+
);
|
|
361
431
|
|
|
362
432
|
if (report.warnings.length > 0) {
|
|
363
433
|
console.log(chalk.yellow(`\n⚠️ Warnings (${report.warnings.length}):\n`));
|
|
@@ -406,5 +476,5 @@ export default {
|
|
|
406
476
|
migrateTailwind,
|
|
407
477
|
migrateBootstrap,
|
|
408
478
|
migrateSCSSVariables,
|
|
409
|
-
displayMigrationReport
|
|
479
|
+
displayMigrationReport,
|
|
410
480
|
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomix Plugin: Style Dictionary
|
|
3
|
+
* Example plugin showing how to extend CLI functionality
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export default async function styleDictionaryPlugin(api, options = {}) {
|
|
7
|
+
const { logger, hooks } = api;
|
|
8
|
+
|
|
9
|
+
logger.info('Initializing Style Dictionary plugin...');
|
|
10
|
+
|
|
11
|
+
// Register a hook to run before generation
|
|
12
|
+
hooks.register('preGenerate', async (data) => {
|
|
13
|
+
logger.debug(`[StyleDictionary] Pre-generation hook for ${data.name}`);
|
|
14
|
+
|
|
15
|
+
// Example: Add a custom property to the generation data
|
|
16
|
+
return {
|
|
17
|
+
...data,
|
|
18
|
+
styleDictionary: {
|
|
19
|
+
enabled: true,
|
|
20
|
+
version: options.version || 'latest'
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Register a hook for validation
|
|
26
|
+
hooks.register('onValidate', async (report) => {
|
|
27
|
+
logger.debug('[StyleDictionary] Validation hook running');
|
|
28
|
+
|
|
29
|
+
// Add a custom validation check
|
|
30
|
+
if (options.strictMode && !report.styleDictionary) {
|
|
31
|
+
report.issues.push('Missing Style Dictionary configuration');
|
|
32
|
+
report.valid = false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return report;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Register a hook to run after build
|
|
39
|
+
hooks.register('postBuild', async (assets) => {
|
|
40
|
+
logger.info('[StyleDictionary] Post-build processing...');
|
|
41
|
+
// In a real plugin, you might minify assets or upload them here
|
|
42
|
+
return assets;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
logger.debug('Style Dictionary plugin initialized successfully.');
|
|
46
|
+
}
|