@shohojdhara/atomix 0.3.14 → 0.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/CHANGELOG.md +20 -0
- package/build-tools/EXAMPLES.md +372 -0
- package/build-tools/README.md +242 -0
- package/build-tools/__tests__/error-handler.test.js +230 -0
- package/build-tools/__tests__/index.test.js +141 -0
- package/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/build-tools/__tests__/utils.test.js +161 -0
- package/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/build-tools/error-handler.js +308 -0
- package/build-tools/index.d.ts +44 -0
- package/build-tools/index.js +88 -0
- package/build-tools/package.json +50 -0
- package/build-tools/rollup-plugin.js +236 -0
- package/build-tools/types.d.ts +163 -0
- package/build-tools/utils.js +203 -0
- package/build-tools/vite-plugin.js +161 -0
- package/build-tools/webpack-loader.js +123 -0
- package/dist/atomix.css +21044 -2618
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +77 -3
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/EXAMPLES.md +372 -0
- package/dist/build-tools/README.md +242 -0
- package/dist/build-tools/__tests__/error-handler.test.js +230 -0
- package/dist/build-tools/__tests__/index.test.js +141 -0
- package/dist/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/dist/build-tools/__tests__/utils.test.js +161 -0
- package/dist/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/dist/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/dist/build-tools/error-handler.js +308 -0
- package/dist/build-tools/index.d.ts +44 -0
- package/dist/build-tools/index.js +88 -0
- package/dist/build-tools/package.json +50 -0
- package/dist/build-tools/rollup-plugin.js +236 -0
- package/dist/build-tools/types.d.ts +163 -0
- package/dist/build-tools/utils.js +203 -0
- package/dist/build-tools/vite-plugin.js +161 -0
- package/dist/build-tools/webpack-loader.js +123 -0
- package/dist/charts.d.ts +1 -1
- package/dist/charts.js +86 -57
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +136 -112
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +2 -5
- package/dist/forms.js +140 -128
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +1 -1
- package/dist/heavy.js +136 -112
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +152 -78
- package/dist/index.esm.js +346 -340
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +359 -353
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/layout.js.map +1 -1
- package/dist/theme.d.ts +9 -9
- package/dist/theme.js.map +1 -1
- package/package.json +23 -8
- package/scripts/atomix-cli.js +170 -73
- package/scripts/cli/__tests__/README.md +81 -0
- package/scripts/cli/__tests__/basic.test.js +115 -0
- package/scripts/cli/__tests__/component-generator.test.js +332 -0
- package/scripts/cli/__tests__/integration.test.js +327 -0
- package/scripts/cli/__tests__/test-setup.js +133 -0
- package/scripts/cli/__tests__/token-manager.test.js +251 -0
- package/scripts/cli/__tests__/utils.test.js +161 -0
- package/scripts/cli/component-generator.js +253 -299
- package/scripts/cli/dependency-checker.js +355 -0
- package/scripts/cli/interactive-init.js +46 -5
- package/scripts/cli/template-manager.js +0 -2
- package/scripts/cli/templates/common-templates.js +636 -0
- package/scripts/cli/templates/composable-templates.js +148 -126
- package/scripts/cli/templates/index.js +23 -16
- package/scripts/cli/templates/project-templates.js +151 -23
- package/scripts/cli/templates/react-templates.js +280 -210
- package/scripts/cli/templates/scss-templates.js +90 -91
- package/scripts/cli/templates/testing-templates.js +206 -27
- package/scripts/cli/templates/testing-utils.js +278 -0
- package/scripts/cli/templates/types-templates.js +70 -56
- package/scripts/cli/theme-bridge.js +8 -2
- package/scripts/cli/token-manager.js +318 -206
- package/scripts/cli/utils.js +0 -1
- package/src/components/Accordion/Accordion.stories.tsx +358 -850
- package/src/components/Accordion/Accordion.test.tsx +70 -50
- package/src/components/Accordion/Accordion.tsx +99 -94
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +1 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +80 -39
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +103 -81
- package/src/components/AtomixGlass/GlassFilter.tsx +9 -16
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +8 -7
- package/src/components/AtomixGlass/glass-utils.ts +6 -5
- package/src/components/AtomixGlass/shader-utils.ts +133 -52
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +131 -0
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +2957 -2853
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -1
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +348 -0
- package/src/components/AtomixGlass/stories/Performance.stories.tsx +103 -0
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +51 -36
- package/src/components/AtomixGlass/stories/{ShaderVariants.stories.tsx → Shaders.stories.tsx} +2 -2
- package/src/components/AtomixGlass/stories/shared-components.tsx +90 -190
- package/src/components/Avatar/Avatar.stories.tsx +195 -0
- package/src/components/Avatar/Avatar.tsx +58 -56
- package/src/components/Badge/Badge.stories.tsx +122 -352
- package/src/components/Badge/Badge.test.tsx +41 -41
- package/src/components/Badge/Badge.tsx +64 -62
- package/src/components/Block/Block.stories.tsx +30 -11
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +142 -23
- package/src/components/Breadcrumb/Breadcrumb.tsx +62 -60
- package/src/components/Button/Button.stories.tsx +454 -1126
- package/src/components/Button/Button.test.tsx +123 -0
- package/src/components/Button/Button.tsx +88 -60
- package/src/components/Button/ButtonGroup.stories.tsx +376 -215
- package/src/components/Button/ButtonGroup.tsx +4 -15
- package/src/components/Callout/Callout.stories.tsx +316 -568
- package/src/components/Card/Card.stories.tsx +292 -81
- package/src/components/Card/Card.tsx +30 -14
- package/src/components/Chart/AreaChart.tsx +1 -1
- package/src/components/Chart/CandlestickChart.tsx +23 -16
- package/src/components/Chart/Chart.stories.tsx +153 -16
- package/src/components/Chart/Chart.tsx +40 -44
- package/src/components/Chart/ChartRenderer.tsx +39 -12
- package/src/components/Chart/ChartToolbar.tsx +21 -5
- package/src/components/Chart/DonutChart.tsx +1 -1
- package/src/components/Chart/FunnelChart.tsx +4 -1
- package/src/components/Chart/GaugeChart.tsx +3 -1
- package/src/components/Chart/HeatmapChart.tsx +50 -37
- package/src/components/Chart/LineChart.tsx +3 -2
- package/src/components/Chart/MultiAxisChart.tsx +24 -16
- package/src/components/Chart/RadarChart.tsx +19 -17
- package/src/components/Chart/ScatterChart.tsx +29 -21
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +152 -66
- package/src/components/ColorModeToggle/ColorModeToggle.tsx +15 -3
- package/src/components/Countdown/Countdown.stories.tsx +114 -7
- package/src/components/DataTable/DataTable.stories.tsx +349 -144
- package/src/components/DataTable/DataTable.test.tsx +26 -148
- package/src/components/DataTable/DataTable.tsx +485 -456
- package/src/components/DatePicker/DatePicker.stories.tsx +310 -1066
- package/src/components/DatePicker/DatePicker.tsx +31 -26
- package/src/components/Dropdown/Dropdown.stories.tsx +153 -36
- package/src/components/Dropdown/Dropdown.tsx +313 -299
- package/src/components/EdgePanel/EdgePanel.stories.tsx +221 -25
- package/src/components/EdgePanel/EdgePanel.tsx +1 -3
- package/src/components/Footer/Footer.stories.tsx +396 -327
- package/src/components/Footer/Footer.tsx +130 -128
- package/src/components/Footer/FooterLink.tsx +2 -2
- package/src/components/Form/Checkbox.stories.tsx +140 -6
- package/src/components/Form/Checkbox.test.tsx +63 -0
- package/src/components/Form/Checkbox.tsx +122 -78
- package/src/components/Form/Form.stories.tsx +110 -19
- package/src/components/Form/FormGroup.stories.tsx +127 -4
- package/src/components/Form/Input.stories.tsx +22 -39
- package/src/components/Form/Input.test.tsx +38 -44
- package/src/components/Form/Radio.stories.tsx +146 -17
- package/src/components/Form/Radio.tsx +68 -66
- package/src/components/Form/Select.stories.tsx +140 -8
- package/src/components/Form/Select.tsx +184 -182
- package/src/components/Form/Textarea.stories.tsx +149 -6
- package/src/components/Form/Textarea.test.tsx +27 -32
- package/src/components/Hero/Hero.stories.tsx +372 -38
- package/src/components/Hero/Hero.tsx +201 -55
- package/src/components/Icon/index.ts +7 -1
- package/src/components/List/List.stories.tsx +141 -3
- package/src/components/List/List.tsx +19 -23
- package/src/components/Modal/Modal.stories.tsx +183 -43
- package/src/components/Modal/Modal.tsx +130 -127
- package/src/components/Navigation/Menu/MegaMenu.tsx +70 -70
- package/src/components/Navigation/Nav/NavDropdown.tsx +1 -5
- package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +128 -28
- package/src/components/Navigation/SideMenu/SideMenu.tsx +5 -7
- package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -5
- package/src/components/Pagination/Pagination.stories.tsx +7 -4
- package/src/components/Pagination/Pagination.tsx +199 -202
- package/src/components/PhotoViewer/PhotoViewer.tsx +4 -1
- package/src/components/Popover/Popover.stories.tsx +354 -97
- package/src/components/Popover/Popover.tsx +41 -37
- package/src/components/Progress/Progress.stories.tsx +160 -7
- package/src/components/River/River.stories.tsx +3 -2
- package/src/components/SectionIntro/SectionIntro.stories.tsx +239 -47
- package/src/components/Slider/Slider.stories.tsx +12 -4
- package/src/components/Spinner/Spinner.stories.tsx +104 -8
- package/src/components/Spinner/Spinner.test.tsx +23 -23
- package/src/components/Spinner/Spinner.tsx +43 -46
- package/src/components/Steps/Steps.stories.tsx +173 -42
- package/src/components/Tabs/Tabs.stories.tsx +141 -12
- package/src/components/Tabs/Tabs.tsx +74 -72
- package/src/components/Testimonial/Testimonial.stories.tsx +120 -3
- package/src/components/Todo/Todo.stories.tsx +198 -9
- package/src/components/Toggle/Toggle.stories.tsx +137 -36
- package/src/components/Toggle/Toggle.test.tsx +65 -70
- package/src/components/Toggle/Toggle.tsx +4 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +194 -100
- package/src/components/Tooltip/Tooltip.tsx +104 -106
- package/src/components/Upload/Upload.stories.tsx +241 -150
- package/src/components/Upload/Upload.tsx +287 -283
- package/src/components/VideoPlayer/VideoPlayer.tsx +6 -1
- package/src/components/index.ts +13 -2
- package/src/layouts/Grid/Grid.stories.tsx +9 -3
- package/src/layouts/MasonryGrid/MasonryGrid.tsx +5 -1
- package/src/lib/README.md +2 -2
- package/src/lib/__tests__/theme-tools.test.ts +219 -0
- package/src/lib/composables/index.ts +2 -2
- package/src/lib/composables/shared-mouse-tracker.ts +13 -14
- package/src/lib/composables/useAtomixGlass.ts +126 -97
- package/src/lib/composables/useChartExport.ts +3 -8
- package/src/lib/composables/useDataTable.ts +72 -43
- package/src/lib/composables/useHero.ts +58 -14
- package/src/lib/composables/useHeroBackgroundSlider.ts +2 -9
- package/src/lib/composables/useInput.ts +10 -8
- package/src/lib/composables/useSideMenu.ts +6 -5
- package/src/lib/composables/useTooltip.ts +1 -2
- package/src/lib/composables/useVideoPlayer.ts +44 -35
- package/src/lib/config/index.ts +154 -154
- package/src/lib/constants/components.ts +9 -32
- package/src/lib/constants/cssVariables.ts +29 -29
- package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +2 -6
- package/src/lib/hooks/index.ts +1 -1
- package/src/lib/hooks/useComponentCustomization.ts +11 -17
- package/src/lib/hooks/usePerformanceMonitor.ts +6 -7
- package/src/lib/patterns/__tests__/slots.test.ts +1 -1
- package/src/lib/patterns/index.ts +1 -1
- package/src/lib/patterns/slots.tsx +8 -13
- package/src/lib/storybook/InteractiveDemo.tsx +13 -18
- package/src/lib/storybook/PreviewContainer.tsx +1 -1
- package/src/lib/storybook/VariantsGrid.tsx +3 -7
- package/src/lib/storybook/index.ts +1 -1
- package/src/lib/theme/adapters/cssVariableMapper.ts +47 -74
- package/src/lib/theme/adapters/index.ts +3 -9
- package/src/lib/theme/adapters/themeAdapter.ts +41 -26
- package/src/lib/theme/config/index.ts +1 -1
- package/src/lib/theme/config/types.ts +2 -2
- package/src/lib/theme/config/validator.ts +10 -5
- package/src/lib/theme/constants/constants.ts +2 -2
- package/src/lib/theme/constants/index.ts +1 -2
- package/src/lib/theme/core/__tests__/createTheme.test.ts +20 -22
- package/src/lib/theme/core/composeTheme.ts +32 -26
- package/src/lib/theme/core/createTheme.ts +1 -1
- package/src/lib/theme/core/createThemeObject.ts +308 -301
- package/src/lib/theme/core/index.ts +3 -3
- package/src/lib/theme/devtools/CLI.ts +107 -105
- package/src/lib/theme/devtools/Comparator.tsx +50 -32
- package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +50 -48
- package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +257 -63
- package/src/lib/theme/devtools/Inspector.tsx +75 -60
- package/src/lib/theme/devtools/LiveEditor.tsx +97 -76
- package/src/lib/theme/devtools/Preview.tsx +150 -106
- package/src/lib/theme/devtools/ThemeValidator.ts +29 -21
- package/src/lib/theme/devtools/index.ts +3 -9
- package/src/lib/theme/devtools/useHistory.ts +23 -21
- package/src/lib/theme/errors/errors.ts +12 -11
- package/src/lib/theme/errors/index.ts +2 -7
- package/src/lib/theme/generators/generateCSS.ts +9 -13
- package/src/lib/theme/generators/generateCSSNested.ts +1 -6
- package/src/lib/theme/generators/generateCSSVariables.ts +673 -630
- package/src/lib/theme/generators/index.ts +1 -4
- package/src/lib/theme/i18n/index.ts +1 -1
- package/src/lib/theme/i18n/rtl.ts +13 -13
- package/src/lib/theme/index.ts +7 -16
- package/src/lib/theme/runtime/ThemeApplicator.ts +4 -4
- package/src/lib/theme/runtime/ThemeContext.tsx +1 -1
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +19 -23
- package/src/lib/theme/runtime/ThemeProvider.tsx +230 -239
- package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +1 -1
- package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +24 -29
- package/src/lib/theme/runtime/index.ts +2 -5
- package/src/lib/theme/runtime/useTheme.ts +18 -18
- package/src/lib/theme/runtime/useThemeTokens.ts +22 -22
- package/src/lib/theme/test/testTheme.ts +15 -16
- package/src/lib/theme/tokens/index.ts +2 -7
- package/src/lib/theme/tokens/tokens.ts +25 -24
- package/src/lib/theme/types.ts +428 -411
- package/src/lib/theme/utils/__tests__/themeValidation.test.ts +3 -3
- package/src/lib/theme/utils/componentTheming.ts +18 -18
- package/src/lib/theme/utils/domUtils.ts +277 -289
- package/src/lib/theme/utils/index.ts +1 -2
- package/src/lib/theme/utils/injectCSS.ts +10 -14
- package/src/lib/theme/utils/naming.ts +20 -16
- package/src/lib/theme/utils/themeHelpers.ts +10 -12
- package/src/lib/theme/utils/themeUtils.ts +85 -86
- package/src/lib/theme/utils/themeValidation.ts +82 -33
- package/src/lib/theme-tools.ts +8 -6
- package/src/lib/types/components.ts +172 -71
- package/src/lib/types/partProps.ts +1 -1
- package/src/lib/utils/__tests__/csv.test.ts +45 -0
- package/src/lib/utils/componentUtils.ts +8 -12
- package/src/lib/utils/csv.ts +19 -0
- package/src/lib/utils/dataTableExport.ts +2 -15
- package/src/lib/utils/fontPreloader.ts +10 -19
- package/src/lib/utils/icons.ts +4 -1
- package/src/lib/utils/index.ts +2 -6
- package/src/lib/utils/memoryMonitor.ts +10 -8
- package/src/lib/utils/themeNaming.ts +2 -2
- package/src/styles/01-settings/_index.scss +1 -1
- package/src/styles/01-settings/_settings.accordion.scss +28 -7
- package/src/styles/01-settings/_settings.colors.scss +11 -11
- package/src/styles/01-settings/_settings.design-tokens.scss +61 -50
- package/src/styles/01-settings/_settings.navbar.scss +1 -1
- package/src/styles/01-settings/_settings.spacing.scss +3 -4
- package/src/styles/01-settings/_settings.tooltip.scss +1 -1
- package/src/styles/01-settings/_settings.typography.scss +4 -4
- package/src/styles/02-tools/_tools.button.scss +51 -21
- package/src/styles/02-tools/_tools.utility-api.scss +38 -12
- package/src/styles/03-generic/_generic.root.scss +4 -3
- package/src/styles/06-components/_components.accordion.scss +56 -14
- package/src/styles/06-components/_components.atomix-glass.scss +13 -9
- package/src/styles/06-components/_components.button.scss +16 -4
- package/src/styles/06-components/_components.callout.scss +27 -21
- package/src/styles/06-components/_components.card.scss +5 -14
- package/src/styles/06-components/_components.chart.scss +22 -19
- package/src/styles/06-components/_components.checkbox.scss +25 -17
- package/src/styles/06-components/_components.color-mode-toggle.scss +3 -1
- package/src/styles/06-components/_components.edge-panel.scss +9 -2
- package/src/styles/06-components/_components.footer.scss +1 -1
- package/src/styles/06-components/_components.side-menu.scss +5 -5
- package/src/styles/06-components/_components.toggle.scss +18 -0
- package/src/styles/06-components/_index.scss +1 -1
- package/src/styles/06-components/old.chart.styles.scss +0 -2
- package/src/styles/99-utilities/_index.scss +2 -0
- package/src/styles/99-utilities/_utilities.border.scss +69 -27
- package/src/styles/99-utilities/_utilities.display.scss +1 -1
- package/src/styles/99-utilities/_utilities.opacity.scss +10 -0
- package/src/styles/99-utilities/_utilities.position.scss +16 -9
- package/src/styles/99-utilities/_utilities.scss +2 -0
- package/src/styles/99-utilities/_utilities.sizes.scss +47 -18
- package/src/styles/99-utilities/_utilities.spacing.scss +118 -66
- package/src/styles/99-utilities/_utilities.text-gradient.scss +45 -0
- package/src/styles/99-utilities/_utilities.text.scss +67 -46
- package/themes/dark-complementary/README.md +98 -0
- package/themes/dark-complementary/index.scss +158 -0
- package/themes/default-light/README.md +81 -0
- package/themes/default-light/index.scss +154 -0
- package/themes/high-contrast/README.md +105 -0
- package/themes/high-contrast/index.scss +172 -0
- package/themes/test-theme/README.md +38 -0
- package/themes/test-theme/index.scss +47 -0
- package/scripts/cli/templates-original-backup.js +0 -1655
- package/scripts/cli/templates_backup.js +0 -684
- package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +0 -1438
- package/src/lib/composables/useButton.ts +0 -93
- package/src/lib/composables/useCheckbox.ts +0 -70
|
@@ -2,49 +2,208 @@
|
|
|
2
2
|
* Design Token Manager for Atomix Design System
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { readFile, writeFile
|
|
6
|
-
import {
|
|
5
|
+
import { readFile, writeFile } from 'fs/promises';
|
|
6
|
+
import { resolve, basename } from 'path';
|
|
7
7
|
import { existsSync } from 'fs';
|
|
8
8
|
import chalk from 'chalk';
|
|
9
9
|
import ora from 'ora';
|
|
10
10
|
import boxen from 'boxen';
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Utility function to safely call spinner methods
|
|
14
|
+
*/
|
|
15
|
+
function safeSpinnerCall(spinner, method, ...args) {
|
|
16
|
+
if (typeof spinner[method] === 'function') {
|
|
17
|
+
return spinner[method](...args);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Utility function to safely call chalk methods
|
|
23
|
+
*/
|
|
24
|
+
function safeChalkCall(chalkObj, methodChain, text) {
|
|
25
|
+
try {
|
|
26
|
+
// Split method chain like 'bold.cyan' into ['bold', 'cyan']
|
|
27
|
+
const methods = methodChain.split('.');
|
|
28
|
+
let result = chalkObj;
|
|
29
|
+
|
|
30
|
+
for (const method of methods) {
|
|
31
|
+
if (typeof result[method] === 'function') {
|
|
32
|
+
result = result[method];
|
|
33
|
+
} else {
|
|
34
|
+
// If any method in the chain doesn't exist, return the text as-is
|
|
35
|
+
return text;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return result(text);
|
|
40
|
+
} catch (e) {
|
|
41
|
+
// If anything goes wrong, return the text as-is
|
|
42
|
+
return text;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
12
46
|
/**
|
|
13
47
|
* Token categories in the design system
|
|
14
48
|
*/
|
|
49
|
+
let projectRoot = '';
|
|
50
|
+
|
|
51
|
+
export function setProjectRoot(path) {
|
|
52
|
+
projectRoot = path;
|
|
53
|
+
}
|
|
54
|
+
|
|
15
55
|
const tokenCategories = {
|
|
16
56
|
colors: {
|
|
17
|
-
path
|
|
57
|
+
get path() { return resolve(projectRoot, 'src/styles/01-settings/_settings.colors.scss'); },
|
|
18
58
|
prefix: '--atomix-color',
|
|
19
59
|
description: 'Color palette tokens'
|
|
20
60
|
},
|
|
21
61
|
typography: {
|
|
22
|
-
path
|
|
62
|
+
get path() { return resolve(projectRoot, 'src/styles/01-settings/_settings.typography.scss'); },
|
|
23
63
|
prefix: '--atomix-font',
|
|
24
64
|
description: 'Typography scale tokens'
|
|
25
65
|
},
|
|
26
66
|
spacing: {
|
|
27
|
-
path
|
|
67
|
+
get path() { return resolve(projectRoot, 'src/styles/01-settings/_settings.spacing.scss'); },
|
|
28
68
|
prefix: '--atomix-space',
|
|
29
69
|
description: 'Spacing scale tokens'
|
|
30
70
|
},
|
|
31
71
|
radius: {
|
|
32
|
-
path
|
|
72
|
+
get path() { return resolve(projectRoot, 'src/styles/01-settings/_settings.border-radius.scss'); },
|
|
33
73
|
prefix: '--atomix-radius',
|
|
34
74
|
description: 'Border radius tokens'
|
|
35
75
|
},
|
|
36
76
|
shadows: {
|
|
37
|
-
path
|
|
77
|
+
get path() { return resolve(projectRoot, 'src/styles/01-settings/_settings.box-shadow.scss'); },
|
|
38
78
|
prefix: '--atomix-shadow',
|
|
39
79
|
description: 'Box shadow tokens'
|
|
40
80
|
},
|
|
41
81
|
breakpoints: {
|
|
42
|
-
path
|
|
82
|
+
get path() { return resolve(projectRoot, 'src/styles/01-settings/_settings.breakpoints.scss'); },
|
|
43
83
|
prefix: '--atomix-breakpoint',
|
|
44
84
|
description: 'Responsive breakpoint tokens'
|
|
45
85
|
}
|
|
46
86
|
};
|
|
47
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Parse tokens from content based on category
|
|
90
|
+
*/
|
|
91
|
+
function parseTokens(content, category) {
|
|
92
|
+
const tokens = {};
|
|
93
|
+
let count = 0;
|
|
94
|
+
|
|
95
|
+
// Extract SCSS variables
|
|
96
|
+
const scssVarPattern = /\$([a-z0-9-]+):\s*(.+?);/gi;
|
|
97
|
+
let match;
|
|
98
|
+
while ((match = scssVarPattern.exec(content)) !== null) {
|
|
99
|
+
const name = `$${match[1]}`;
|
|
100
|
+
let value = match[2].trim();
|
|
101
|
+
|
|
102
|
+
// Check for !default flag in value
|
|
103
|
+
if (value.endsWith('!default')) {
|
|
104
|
+
value = value.replace(/\s*!default$/i, '').trim();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
tokens[name] = value;
|
|
108
|
+
count++;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Extract CSS custom properties
|
|
112
|
+
const cssVarPattern = /(--[a-z0-9-]+):\s*(.+?);/gi;
|
|
113
|
+
while ((match = cssVarPattern.exec(content)) !== null) {
|
|
114
|
+
const name = match[1];
|
|
115
|
+
const value = match[2].trim();
|
|
116
|
+
tokens[name] = value;
|
|
117
|
+
count++;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
tokens,
|
|
122
|
+
count,
|
|
123
|
+
description: tokenCategories[category]?.description || 'Unknown category',
|
|
124
|
+
path: tokenCategories[category]?.path || 'Unknown path'
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Validate a token file for common issues
|
|
130
|
+
*/
|
|
131
|
+
function validateTokenFile(content, category, filePath) {
|
|
132
|
+
const issues = [];
|
|
133
|
+
const warnings = [];
|
|
134
|
+
let count = 0;
|
|
135
|
+
|
|
136
|
+
// Special handling for breakpoints which uses a map structure
|
|
137
|
+
if (category === 'breakpoints') {
|
|
138
|
+
// Count map entries in breakpoints
|
|
139
|
+
const mapPattern = /\$[a-z0-9_-]+:\s*\(([\s\S]*?)\)/gi;
|
|
140
|
+
let match;
|
|
141
|
+
while ((match = mapPattern.exec(content)) !== null) {
|
|
142
|
+
// Count entries inside the map
|
|
143
|
+
const mapContent = match[1];
|
|
144
|
+
const entryMatches = mapContent.match(/[\w-]+:\s*[^,}]+/g);
|
|
145
|
+
count += entryMatches ? entryMatches.length : 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return { issues, warnings, count };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Count tokens for non-breakpoint categories
|
|
152
|
+
const scssVarPattern = /\$([a-z0-9-]+):\s*(.+?);/gi;
|
|
153
|
+
let match;
|
|
154
|
+
while ((match = scssVarPattern.exec(content)) !== null) {
|
|
155
|
+
count++;
|
|
156
|
+
|
|
157
|
+
let value = match[2].trim();
|
|
158
|
+
let hasDefault = false;
|
|
159
|
+
|
|
160
|
+
// Check for !default flag in value
|
|
161
|
+
if (value.toLowerCase().endsWith('!default')) {
|
|
162
|
+
hasDefault = true;
|
|
163
|
+
value = value.replace(/\s*!default$/i, '').trim();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Check for missing !default flag
|
|
167
|
+
if (!hasDefault) { // !default is not present
|
|
168
|
+
issues.push({
|
|
169
|
+
category: 'missing-default',
|
|
170
|
+
issue: `Missing !default flag for variable $${match[1]}`,
|
|
171
|
+
file: filePath,
|
|
172
|
+
fix: `Add !default to the variable: $${match[1]}: ${value} !default;`
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Check for hardcoded values that should be tokens
|
|
177
|
+
if (/#[0-9a-fA-F]{3,6}|rgb\(|rgba\(|hsl\(|hsla\(/.test(value)) {
|
|
178
|
+
warnings.push({
|
|
179
|
+
category: 'hardcoded-value',
|
|
180
|
+
issue: `Hardcoded color value detected in $${match[1]}`,
|
|
181
|
+
file: filePath,
|
|
182
|
+
values: [value],
|
|
183
|
+
fix: `Consider using a token instead of hardcoded value`
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Check for naming conventions
|
|
189
|
+
const namingPattern = /\$([a-z0-9-]+)/gi;
|
|
190
|
+
while ((match = namingPattern.exec(content)) !== null) {
|
|
191
|
+
const varName = match[1];
|
|
192
|
+
|
|
193
|
+
// Check if name contains uppercase letters
|
|
194
|
+
if (/[A-Z]/.test(varName)) {
|
|
195
|
+
issues.push({
|
|
196
|
+
category: 'naming-convention',
|
|
197
|
+
issue: `Variable name $${varName} contains uppercase letters`,
|
|
198
|
+
file: filePath,
|
|
199
|
+
fix: `Use lowercase and hyphens: $${varName.toLowerCase()}`
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return { issues, warnings, count };
|
|
205
|
+
}
|
|
206
|
+
|
|
48
207
|
/**
|
|
49
208
|
* Extract tokens from SCSS file
|
|
50
209
|
*/
|
|
@@ -57,7 +216,7 @@ async function extractTokensFromFile(filePath) {
|
|
|
57
216
|
const tokens = {};
|
|
58
217
|
|
|
59
218
|
// Extract SCSS variables
|
|
60
|
-
const scssVarPattern = /\$([a-
|
|
219
|
+
const scssVarPattern = /\$([a-z0-9-]+):\s*([^;!]+)(?:\s*!default)?;/gi;
|
|
61
220
|
let match;
|
|
62
221
|
while ((match = scssVarPattern.exec(content)) !== null) {
|
|
63
222
|
tokens[`$${match[1]}`] = {
|
|
@@ -83,217 +242,167 @@ async function extractTokensFromFile(filePath) {
|
|
|
83
242
|
}
|
|
84
243
|
|
|
85
244
|
/**
|
|
86
|
-
*
|
|
245
|
+
* Load all design tokens from SCSS files
|
|
87
246
|
*/
|
|
88
|
-
export async function listTokens(
|
|
89
|
-
const spinner = ora('Loading design tokens...')
|
|
247
|
+
export async function listTokens(categories = Object.keys(tokenCategories)) {
|
|
248
|
+
const spinner = ora('Loading design tokens...');
|
|
249
|
+
safeSpinnerCall(spinner, 'start');
|
|
90
250
|
|
|
91
251
|
try {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const categories = category
|
|
96
|
-
? [category]
|
|
97
|
-
: Object.keys(tokenCategories);
|
|
252
|
+
const tokens = {};
|
|
253
|
+
let categoryCount = 0;
|
|
254
|
+
let tokenCount = 0;
|
|
98
255
|
|
|
99
256
|
for (const cat of categories) {
|
|
100
257
|
if (!tokenCategories[cat]) {
|
|
101
|
-
spinner
|
|
258
|
+
safeSpinnerCall(spinner, 'warn', safeChalkCall(chalk, 'yellow', `Unknown category: ${cat}`));
|
|
102
259
|
continue;
|
|
103
260
|
}
|
|
104
261
|
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (tokens) {
|
|
110
|
-
results[cat] = {
|
|
111
|
-
description,
|
|
112
|
-
path: path,
|
|
113
|
-
tokens: tokens,
|
|
114
|
-
count: Object.keys(tokens).length
|
|
115
|
-
};
|
|
262
|
+
const fullPath = tokenCategories[cat].path;
|
|
263
|
+
|
|
264
|
+
if (!existsSync(fullPath)) {
|
|
265
|
+
continue;
|
|
116
266
|
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
spinner.stop();
|
|
120
267
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
268
|
+
const content = await readFile(fullPath, 'utf8');
|
|
269
|
+
const categoryTokens = parseTokens(content, cat);
|
|
270
|
+
|
|
271
|
+
if (Object.keys(categoryTokens).length > 0) {
|
|
272
|
+
tokens[cat] = categoryTokens;
|
|
273
|
+
categoryCount++;
|
|
274
|
+
tokenCount += Object.keys(categoryTokens).length;
|
|
275
|
+
}
|
|
126
276
|
}
|
|
127
277
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
278
|
+
safeSpinnerCall(spinner, 'succeed', safeChalkCall(chalk, 'green', 'Tokens loaded successfully'));
|
|
279
|
+
|
|
280
|
+
// Show summary
|
|
281
|
+
if (categoryCount === 0) {
|
|
282
|
+
console.log(safeChalkCall(chalk, 'yellow', '\n⚠️ No design tokens found'));
|
|
283
|
+
console.log(safeChalkCall(chalk, 'gray', 'Make sure you are in an Atomix project directory'));
|
|
284
|
+
} else {
|
|
285
|
+
console.log(safeChalkCall(chalk, 'bold.cyan', '\n📐 Design Tokens\n'));
|
|
286
|
+
|
|
287
|
+
for (const [category, data] of Object.entries(tokens)) {
|
|
288
|
+
console.log(boxen(
|
|
289
|
+
safeChalkCall(chalk, 'bold', category.toUpperCase()) + '\n' +
|
|
290
|
+
safeChalkCall(chalk, 'gray', data.description) + '\n\n' +
|
|
291
|
+
safeChalkCall(chalk, 'cyan', `Tokens: ${data.count}\n`) +
|
|
292
|
+
safeChalkCall(chalk, 'gray', `File: ${data.path}`),
|
|
293
|
+
{ padding: 1, borderColor: 'blue', borderStyle: 'round' }
|
|
294
|
+
));
|
|
295
|
+
|
|
296
|
+
// Log first 5 tokens as examples
|
|
297
|
+
const tokenEntries = Object.entries(data.tokens).slice(0, 5);
|
|
298
|
+
for (const [name, value] of tokenEntries) {
|
|
299
|
+
console.log(` ${safeChalkCall(chalk, 'green', name)}: ${safeChalkCall(chalk, 'white', value)}`);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (Object.keys(data.tokens).length > 5) {
|
|
303
|
+
console.log(safeChalkCall(chalk, 'gray', ` ... and ${Object.keys(data.tokens).length - 5} more\n`));
|
|
141
304
|
}
|
|
142
|
-
));
|
|
143
|
-
|
|
144
|
-
// Show first 5 tokens as examples
|
|
145
|
-
const tokenEntries = Object.entries(data.tokens).slice(0, 5);
|
|
146
|
-
tokenEntries.forEach(([name, info]) => {
|
|
147
|
-
const value = info.value.length > 30
|
|
148
|
-
? info.value.substring(0, 30) + '...'
|
|
149
|
-
: info.value;
|
|
150
|
-
console.log(` ${chalk.green(name)}: ${chalk.white(value)}`);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
if (Object.keys(data.tokens).length > 5) {
|
|
154
|
-
console.log(chalk.gray(` ... and ${Object.keys(data.tokens).length - 5} more\n`));
|
|
155
|
-
} else {
|
|
156
|
-
console.log();
|
|
157
305
|
}
|
|
158
306
|
}
|
|
159
307
|
|
|
160
|
-
return
|
|
308
|
+
return { tokens, categoryCount, tokenCount };
|
|
161
309
|
|
|
162
310
|
} catch (error) {
|
|
163
|
-
spinner
|
|
311
|
+
safeSpinnerCall(spinner, 'fail', safeChalkCall(chalk, 'red', 'Failed to load tokens'));
|
|
164
312
|
throw error;
|
|
165
313
|
}
|
|
166
314
|
}
|
|
167
315
|
|
|
168
316
|
/**
|
|
169
|
-
* Validate design
|
|
317
|
+
* Validate tokens according to design system standards
|
|
170
318
|
*/
|
|
171
|
-
export async function validateTokens(options = {}) {
|
|
172
|
-
const spinner = ora('Validating design tokens...')
|
|
319
|
+
export async function validateTokens(categories = Object.keys(tokenCategories), options = {}) {
|
|
320
|
+
const spinner = ora('Validating design tokens...');
|
|
321
|
+
safeSpinnerCall(spinner, 'start');
|
|
173
322
|
|
|
174
323
|
try {
|
|
175
|
-
|
|
176
|
-
|
|
324
|
+
let issues = [];
|
|
325
|
+
let warnings = [];
|
|
177
326
|
let totalTokens = 0;
|
|
178
327
|
|
|
179
|
-
for (const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (!existsSync(fullPath)) {
|
|
183
|
-
issues.push({
|
|
184
|
-
category,
|
|
185
|
-
issue: 'Token file missing',
|
|
186
|
-
file: config.path,
|
|
187
|
-
fix: `Create file: ${config.path}`
|
|
188
|
-
});
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const tokens = await extractTokensFromFile(fullPath);
|
|
193
|
-
if (tokens) {
|
|
194
|
-
totalTokens += Object.keys(tokens).length;
|
|
195
|
-
|
|
196
|
-
// Check for hardcoded values
|
|
197
|
-
const content = await readFile(fullPath, 'utf8');
|
|
198
|
-
|
|
199
|
-
// Check for hardcoded colors
|
|
200
|
-
if (category === 'colors') {
|
|
201
|
-
const hardcodedColors = content.match(/#[0-9a-fA-F]{3,8}(?![0-9a-fA-F])/g);
|
|
202
|
-
if (hardcodedColors) {
|
|
203
|
-
const uniqueColors = [...new Set(hardcodedColors)];
|
|
204
|
-
warnings.push({
|
|
205
|
-
category,
|
|
206
|
-
issue: `Found ${uniqueColors.length} hardcoded color values`,
|
|
207
|
-
values: uniqueColors.slice(0, 3),
|
|
208
|
-
fix: 'Use color tokens or CSS custom properties'
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Check for hardcoded pixel values
|
|
214
|
-
if (category === 'spacing' || category === 'typography') {
|
|
215
|
-
const hardcodedPixels = content.match(/\d+px/g);
|
|
216
|
-
if (hardcodedPixels) {
|
|
217
|
-
const uniquePixels = [...new Set(hardcodedPixels)];
|
|
218
|
-
warnings.push({
|
|
219
|
-
category,
|
|
220
|
-
issue: `Found ${uniquePixels.length} hardcoded pixel values`,
|
|
221
|
-
values: uniquePixels.slice(0, 3),
|
|
222
|
-
fix: 'Use spacing tokens or rem units'
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
}
|
|
328
|
+
for (const cat of categories) {
|
|
329
|
+
if (!tokenCategories[cat]) continue;
|
|
226
330
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if (scssVars && (!defaultFlags || defaultFlags.length < scssVars.length)) {
|
|
231
|
-
warnings.push({
|
|
232
|
-
category,
|
|
233
|
-
issue: 'Some SCSS variables missing !default flag',
|
|
234
|
-
fix: 'Add !default to allow theme overrides'
|
|
235
|
-
});
|
|
236
|
-
}
|
|
331
|
+
const fullPath = tokenCategories[cat].path;
|
|
332
|
+
|
|
333
|
+
if (!existsSync(fullPath)) continue;
|
|
237
334
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
fix: `Should start with "${config.prefix}"`
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
335
|
+
const content = await readFile(fullPath, 'utf8');
|
|
336
|
+
const { issues: catIssues, warnings: catWarnings, count: catCount } = validateTokenFile(content, cat, fullPath);
|
|
337
|
+
|
|
338
|
+
issues = [...issues, ...catIssues];
|
|
339
|
+
warnings = [...warnings, ...catWarnings];
|
|
340
|
+
totalTokens += catCount;
|
|
249
341
|
}
|
|
250
342
|
|
|
251
|
-
spinner.stop();
|
|
252
|
-
|
|
253
|
-
// Display validation results
|
|
254
|
-
console.log(chalk.bold.cyan('\n🔍 Token Validation Report\n'));
|
|
255
|
-
|
|
256
343
|
if (issues.length === 0 && warnings.length === 0) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
chalk.
|
|
262
|
-
{
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
));
|
|
344
|
+
safeSpinnerCall(spinner, 'succeed', safeChalkCall(chalk, 'green', 'All tokens are valid!'));
|
|
345
|
+
|
|
346
|
+
console.log(safeChalkCall(chalk, 'bold.cyan', '\n🔍 Token Validation Report\n'));
|
|
347
|
+
console.log(
|
|
348
|
+
safeChalkCall(chalk, 'bold.green', '✅ All tokens valid!\n\n') +
|
|
349
|
+
safeChalkCall(chalk, 'gray', `Total tokens: ${totalTokens}\n`) +
|
|
350
|
+
safeChalkCall(chalk, 'gray', 'All naming conventions followed\n') +
|
|
351
|
+
safeChalkCall(chalk, 'gray', 'No hardcoded values found')
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
console.log(safeChalkCall(chalk, 'gray', '─'.repeat(50)));
|
|
355
|
+
|
|
356
|
+
return { isValid: true, issues: [], warnings: [] };
|
|
268
357
|
} else {
|
|
358
|
+
const status = issues.length > 0 ? 'fail' : 'warn';
|
|
359
|
+
safeSpinnerCall(spinner, status, safeChalkCall(chalk, 'red', `Found ${issues.length} issues and ${warnings.length} warnings`));
|
|
360
|
+
|
|
361
|
+
console.log(safeChalkCall(chalk, 'bold.cyan', '\n🔍 Token Validation Report\n'));
|
|
362
|
+
|
|
269
363
|
if (issues.length > 0) {
|
|
270
|
-
console.log(chalk
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
console.log(chalk
|
|
275
|
-
|
|
364
|
+
console.log(safeChalkCall(chalk, 'bold.red', `❌ Issues (${issues.length}):\n`));
|
|
365
|
+
|
|
366
|
+
for (let i = 0; i < Math.min(issues.length, 5); i++) {
|
|
367
|
+
const issue = issues[i];
|
|
368
|
+
console.log(safeChalkCall(chalk, 'red', ` ${i + 1}. [${issue.category}] ${issue.issue}`));
|
|
369
|
+
console.log(safeChalkCall(chalk, 'gray', ` File: ${issue.file}`));
|
|
370
|
+
console.log(safeChalkCall(chalk, 'yellow', ` Fix: ${issue.fix}\n`));
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (issues.length > 5) {
|
|
374
|
+
console.log(safeChalkCall(chalk, 'gray', `... and ${issues.length - 5} more\n`));
|
|
375
|
+
}
|
|
276
376
|
}
|
|
277
|
-
|
|
377
|
+
|
|
278
378
|
if (warnings.length > 0) {
|
|
279
|
-
console.log(chalk
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
379
|
+
console.log(safeChalkCall(chalk, 'bold.yellow', `⚠️ Warnings (${warnings.length}):\n`));
|
|
380
|
+
|
|
381
|
+
for (let i = 0; i < Math.min(warnings.length, 5); i++) {
|
|
382
|
+
const warning = warnings[i];
|
|
383
|
+
console.log(safeChalkCall(chalk, 'yellow', ` ${i + 1}. [${warning.category}] ${warning.issue}`));
|
|
384
|
+
console.log(safeChalkCall(chalk, 'gray', ` File: ${warning.file}`));
|
|
385
|
+
if (warning.values && warning.values.length > 0) {
|
|
386
|
+
console.log(safeChalkCall(chalk, 'gray', ` Examples: ${warning.values.join(', ')}`));
|
|
284
387
|
}
|
|
285
|
-
console.log(chalk
|
|
286
|
-
}
|
|
388
|
+
console.log(safeChalkCall(chalk, 'cyan', ` Fix: ${warning.fix}\n`));
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (warnings.length > 5) {
|
|
392
|
+
console.log(safeChalkCall(chalk, 'gray', `... and ${warnings.length - 5} more\n`));
|
|
393
|
+
}
|
|
287
394
|
}
|
|
288
|
-
|
|
289
|
-
console.log(chalk
|
|
290
|
-
|
|
395
|
+
|
|
396
|
+
console.log(safeChalkCall(chalk, 'gray', '─'.repeat(50)));
|
|
397
|
+
|
|
398
|
+
if (options.fix) {
|
|
399
|
+
console.log(safeChalkCall(chalk, 'yellow', '\n💡 Run with --fix to automatically fix some issues'));
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
return { isValid: false, issues, warnings };
|
|
291
403
|
}
|
|
292
|
-
|
|
293
|
-
return { issues, warnings, totalTokens };
|
|
294
|
-
|
|
295
404
|
} catch (error) {
|
|
296
|
-
spinner
|
|
405
|
+
safeSpinnerCall(spinner, 'fail', safeChalkCall(chalk, 'red', 'Validation failed'));
|
|
297
406
|
throw error;
|
|
298
407
|
}
|
|
299
408
|
}
|
|
@@ -302,14 +411,15 @@ export async function validateTokens(options = {}) {
|
|
|
302
411
|
* Export tokens to different formats
|
|
303
412
|
*/
|
|
304
413
|
export async function exportTokens(format = 'json', outputPath = null) {
|
|
305
|
-
const spinner = ora(`Exporting tokens as ${format.toUpperCase()}...`)
|
|
414
|
+
const spinner = ora(`Exporting tokens as ${format.toUpperCase()}...`);
|
|
415
|
+
safeSpinnerCall(spinner, 'start');
|
|
306
416
|
|
|
307
417
|
try {
|
|
308
418
|
const allTokens = {};
|
|
309
419
|
|
|
310
420
|
// Collect all tokens
|
|
311
421
|
for (const [category, config] of Object.entries(tokenCategories)) {
|
|
312
|
-
const fullPath =
|
|
422
|
+
const fullPath = config.path;
|
|
313
423
|
const tokens = await extractTokensFromFile(fullPath);
|
|
314
424
|
|
|
315
425
|
if (tokens) {
|
|
@@ -388,7 +498,7 @@ export async function exportTokens(format = 'json', outputPath = null) {
|
|
|
388
498
|
const finalPath = outputPath || filename;
|
|
389
499
|
await writeFile(finalPath, output, 'utf8');
|
|
390
500
|
|
|
391
|
-
spinner
|
|
501
|
+
safeSpinnerCall(spinner, 'succeed', safeChalkCall(chalk, 'green', `✓ Exported tokens to ${finalPath}`));
|
|
392
502
|
|
|
393
503
|
// Show summary
|
|
394
504
|
const categoryCount = Object.keys(allTokens).length;
|
|
@@ -397,14 +507,14 @@ export async function exportTokens(format = 'json', outputPath = null) {
|
|
|
397
507
|
0
|
|
398
508
|
);
|
|
399
509
|
|
|
400
|
-
console.log(chalk
|
|
401
|
-
console.log(chalk
|
|
402
|
-
console.log(chalk
|
|
510
|
+
console.log(safeChalkCall(chalk, 'gray', `\n Categories: ${categoryCount}`));
|
|
511
|
+
console.log(safeChalkCall(chalk, 'gray', ` Total tokens: ${tokenCount}`));
|
|
512
|
+
console.log(safeChalkCall(chalk, 'gray', ` Format: ${format.toUpperCase()}`));
|
|
403
513
|
|
|
404
514
|
return { path: finalPath, tokens: allTokens };
|
|
405
515
|
|
|
406
516
|
} catch (error) {
|
|
407
|
-
spinner
|
|
517
|
+
safeSpinnerCall(spinner, 'fail', safeChalkCall(chalk, 'red', 'Export failed'));
|
|
408
518
|
throw error;
|
|
409
519
|
}
|
|
410
520
|
}
|
|
@@ -413,7 +523,8 @@ export async function exportTokens(format = 'json', outputPath = null) {
|
|
|
413
523
|
* Import tokens from file
|
|
414
524
|
*/
|
|
415
525
|
export async function importTokens(filePath, options = {}) {
|
|
416
|
-
const spinner = ora('Importing design tokens...')
|
|
526
|
+
const spinner = ora('Importing design tokens...');
|
|
527
|
+
safeSpinnerCall(spinner, 'start');
|
|
417
528
|
|
|
418
529
|
try {
|
|
419
530
|
if (!existsSync(filePath)) {
|
|
@@ -472,17 +583,17 @@ export async function importTokens(filePath, options = {}) {
|
|
|
472
583
|
throw new Error(`Unsupported file type: ${extension}`);
|
|
473
584
|
}
|
|
474
585
|
|
|
475
|
-
spinner
|
|
586
|
+
safeSpinnerCall(spinner, 'text', 'Updating token files...');
|
|
476
587
|
|
|
477
588
|
// Update token files
|
|
478
589
|
for (const [category, categoryTokens] of Object.entries(tokens)) {
|
|
479
590
|
if (!tokenCategories[category]) {
|
|
480
|
-
console.warn(chalk
|
|
591
|
+
console.warn(safeChalkCall(chalk, 'yellow', `\n⚠️ Unknown category: ${category} (skipped)`));
|
|
481
592
|
continue;
|
|
482
593
|
}
|
|
483
594
|
|
|
484
595
|
const config = tokenCategories[category];
|
|
485
|
-
const fullPath =
|
|
596
|
+
const fullPath = config.path;
|
|
486
597
|
|
|
487
598
|
// Generate SCSS content
|
|
488
599
|
let scssContent = `// ${config.description}\n`;
|
|
@@ -501,15 +612,15 @@ export async function importTokens(filePath, options = {}) {
|
|
|
501
612
|
}
|
|
502
613
|
|
|
503
614
|
if (options.dryRun) {
|
|
504
|
-
console.log(chalk
|
|
505
|
-
console.log(chalk
|
|
615
|
+
console.log(safeChalkCall(chalk, 'yellow', `\n Would update: ${config.path}`));
|
|
616
|
+
console.log(safeChalkCall(chalk, 'gray', scssContent.substring(0, 200) + '...'));
|
|
506
617
|
} else {
|
|
507
618
|
await writeFile(fullPath, scssContent, 'utf8');
|
|
508
|
-
console.log(chalk
|
|
619
|
+
console.log(safeChalkCall(chalk, 'green', ` ✓ Updated ${config.path}`));
|
|
509
620
|
}
|
|
510
621
|
}
|
|
511
622
|
|
|
512
|
-
spinner
|
|
623
|
+
safeSpinnerCall(spinner, 'succeed', safeChalkCall(chalk, 'green', '✓ Tokens imported successfully'));
|
|
513
624
|
|
|
514
625
|
// Show summary
|
|
515
626
|
const categoryCount = Object.keys(tokens).length;
|
|
@@ -518,20 +629,20 @@ export async function importTokens(filePath, options = {}) {
|
|
|
518
629
|
0
|
|
519
630
|
);
|
|
520
631
|
|
|
521
|
-
console.log(chalk
|
|
522
|
-
console.log(chalk
|
|
632
|
+
console.log(safeChalkCall(chalk, 'gray', `\n Categories imported: ${categoryCount}`));
|
|
633
|
+
console.log(safeChalkCall(chalk, 'gray', ` Total tokens: ${tokenCount}`));
|
|
523
634
|
|
|
524
635
|
if (!options.dryRun) {
|
|
525
|
-
console.log(chalk
|
|
526
|
-
console.log(chalk
|
|
527
|
-
console.log(chalk
|
|
528
|
-
console.log(chalk
|
|
636
|
+
console.log(safeChalkCall(chalk, 'cyan', '\n💡 Next steps:'));
|
|
637
|
+
console.log(safeChalkCall(chalk, 'gray', ' 1. Review the updated token files'));
|
|
638
|
+
console.log(safeChalkCall(chalk, 'gray', ' 2. Rebuild your themes: atomix build-theme <theme>'));
|
|
639
|
+
console.log(safeChalkCall(chalk, 'gray', ' 3. Test your components with new tokens'));
|
|
529
640
|
}
|
|
530
641
|
|
|
531
642
|
return { tokens, categoryCount, tokenCount };
|
|
532
643
|
|
|
533
644
|
} catch (error) {
|
|
534
|
-
spinner
|
|
645
|
+
safeSpinnerCall(spinner, 'fail', safeChalkCall(chalk, 'red', 'Import failed'));
|
|
535
646
|
throw error;
|
|
536
647
|
}
|
|
537
648
|
}
|
|
@@ -540,12 +651,13 @@ export async function importTokens(filePath, options = {}) {
|
|
|
540
651
|
* Automatically fix issues in token files
|
|
541
652
|
*/
|
|
542
653
|
export async function fixTokens(options = {}) {
|
|
543
|
-
const spinner = ora('Attempting to fix design tokens...')
|
|
654
|
+
const spinner = ora('Attempting to fix design tokens...');
|
|
655
|
+
safeSpinnerCall(spinner, 'start');
|
|
544
656
|
let totalFixed = 0;
|
|
545
657
|
|
|
546
658
|
try {
|
|
547
659
|
for (const [category, config] of Object.entries(tokenCategories)) {
|
|
548
|
-
const fullPath =
|
|
660
|
+
const fullPath = config.path;
|
|
549
661
|
|
|
550
662
|
if (!existsSync(fullPath)) continue;
|
|
551
663
|
|
|
@@ -554,7 +666,7 @@ export async function fixTokens(options = {}) {
|
|
|
554
666
|
let fileFixedCount = 0;
|
|
555
667
|
|
|
556
668
|
// 1. Fix missing !default flags
|
|
557
|
-
const defaultFixed = content.replace(/(\$[a-z-]+:\s*[
|
|
669
|
+
const defaultFixed = content.replace(/(\$[a-z-]+:\s*[^;!\n]+)(;\s*)(?!\s*!default)/gi, (match, p1, p2) => {
|
|
558
670
|
fileFixedCount++;
|
|
559
671
|
return `${p1} !default${p2}`;
|
|
560
672
|
});
|
|
@@ -595,15 +707,15 @@ export async function fixTokens(options = {}) {
|
|
|
595
707
|
await writeFile(fullPath, content, 'utf8');
|
|
596
708
|
}
|
|
597
709
|
totalFixed += fileFixedCount;
|
|
598
|
-
console.log(chalk
|
|
710
|
+
console.log(safeChalkCall(chalk, 'green', ` ✓ Fixed ${fileFixedCount} issues in ${config.path}`));
|
|
599
711
|
}
|
|
600
712
|
}
|
|
601
713
|
|
|
602
|
-
spinner
|
|
714
|
+
safeSpinnerCall(spinner, 'succeed', safeChalkCall(chalk, 'green', `✓ Successfully fixed ${totalFixed} issues!`));
|
|
603
715
|
return { totalFixed };
|
|
604
716
|
|
|
605
717
|
} catch (error) {
|
|
606
|
-
spinner
|
|
718
|
+
safeSpinnerCall(spinner, 'fail', safeChalkCall(chalk, 'red', 'Fix operation failed'));
|
|
607
719
|
throw error;
|
|
608
720
|
}
|
|
609
721
|
}
|