Skip to content

Commit 68ee6bf

Browse files
Copilotdermatz
andauthored
Add mageforge:hyva:tokens command for Hyvä design token generation (#58)
* Initial plan * #add-hyva-token-command - Create TokensCommand for generating Hyvä design tokens Co-authored-by: dermatz <[email protected]> * #add-hyva-token-command - Fix variable naming and improve documentation Co-authored-by: dermatz <[email protected]> * #add-hyva-token-command - Use Shell service for better security and consistency Co-authored-by: dermatz <[email protected]> * #add-hyva-token-command - Update CHANGELOG.md with new feature Co-authored-by: dermatz <[email protected]> * ✨ feat: rename command to generate Hyvä design tokens --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: dermatz <[email protected]> Co-authored-by: Mathias Elle <[email protected]> Co-authored-by: Mathias Elle <[email protected]>
1 parent 8d92503 commit 68ee6bf

File tree

5 files changed

+257
-3
lines changed

5 files changed

+257
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ All notable changes to this project will be documented in this file.
66

77
## UNRELEASED
88

9+
910
### Added
1011

12+
- feat: add `mageforge:theme:tokens` command to generate Hyvä design tokens from design.tokens.json or hyva.config.json
1113
- feat: add `mageforge:hyva:compatibility:check` command to add a Hyvä compatibility checker
1214
- Scans Magento modules for Hyvä theme compatibility issues
1315
- Detects RequireJS, Knockout.js, jQuery, and UI Components usage

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ Please ensure that your Magento installation meets this requirement before insta
3737
| `mageforge:theme:list` | Lists all available themes | `m:t:l` |
3838
| `mageforge:theme:build` | Builds selected themes (CSS/TailwindCSS) | `m:t:b`, `frontend:build` |
3939
| `mageforge:theme:watch` | Starts watch mode for theme development | `m:t:w`, `frontend:watch` |
40-
| `mageforge:static:clean` | Clean static files, cache and generated files for a theme | `frontend:clean` |
40+
| `mageforge:hyva:tokens` | Generate Hyvä design tokens (Hyvä themes only) | `m:h:t` |
41+
| `mageforge:static:clean` | Clean static files, cache and generated files for a theme | `m:st:c`,`frontend:clean` |
4142

4243
---
4344

@@ -79,7 +80,15 @@ Please ensure that your Magento installation meets this requirement before insta
7980
bin/magento mageforge:theme:watch <theme-code>
8081
```
8182

82-
4. Enjoy automatic CSS rebuilding you work on your theme files!
83+
4. Generate Hyvä design tokens (for Hyvä themes):
84+
85+
```bash
86+
bin/magento mageforge:hyva:tokens <theme-code>
87+
```
88+
89+
This creates a `generated/hyva-tokens.css` file from your design tokens configuration.
90+
91+
5. Enjoy automatic CSS rebuilding as you work on your theme files!
8392

8493
## Additional Documentation
8594

docs/commands.md

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,16 +101,19 @@ bin/magento mageforge:theme:watch [--theme=THEME]
101101
**File**: `/src/Console/Command/Static/CleanCommand.php`
102102

103103
**Dependencies**:
104+
104105
- `Filesystem` - Magento filesystem component for file operations
105106
- `ThemeList` - Service to retrieve theme information
106107
- `ThemePath` - Service to resolve theme paths
107108

108109
**Usage**:
110+
109111
```bash
110112
bin/magento mageforge:static:clean [<themename>]
111113
```
112114

113115
**Implementation Details**:
116+
114117
- If no theme name is provided:
115118
- In interactive terminals, displays an interactive prompt to select the theme to clean
116119
- In non-interactive environments, prints the list of available themes and exits, requiring an explicit theme name
@@ -157,7 +160,7 @@ bin/magento mageforge:system:check
157160

158161
---
159162

160-
### 6. VersionCommand (`mageforge:version`)
163+
### 5. VersionCommand (`mageforge:version`)
161164

162165
**Purpose**: Displays the current and latest version of the MageForge module.
163166

@@ -308,6 +311,80 @@ _PHTML Files (.phtml)_:
308311

309312
---
310313

314+
### 7. TokensCommand (`mageforge:hyva:tokens`)
315+
316+
**Purpose**: Generates Hyvä design tokens from design.tokens.json or hyva.config.json configuration files.
317+
318+
**File**: `/src/Console/Command/Theme/TokensCommand.php`
319+
320+
**Dependencies**:
321+
322+
- `ThemeList` - Service to retrieve theme information
323+
- `ThemePath` - Service to resolve theme paths
324+
- `BuilderPool` - Service to verify Hyvä theme type
325+
- `File` - Filesystem driver for directory checks
326+
- `Shell` - Shell command executor
327+
328+
**Usage**:
329+
330+
```bash
331+
bin/magento mageforge:hyva:tokens [<themeCode>]
332+
```
333+
334+
**Aliases**:
335+
336+
- `m:h:t`
337+
338+
**Arguments**:
339+
340+
- `themeCode` (optional) - Theme code in format Vendor/theme
341+
342+
**Examples**:
343+
344+
```bash
345+
# Interactive mode - select theme from list
346+
bin/magento m:h:t
347+
348+
# Direct execution
349+
bin/magento mageforge:hyva:tokens Hyva/default
350+
```
351+
352+
**Implementation Details**:
353+
354+
- If no theme code is provided, displays an interactive prompt to select a Hyvä theme
355+
- Validates that the theme is installed and is a Hyvä theme
356+
- Checks if the theme has been built (node_modules exists)
357+
- Changes to the theme's `web/tailwind` directory
358+
- Executes `npx hyva-tokens` to generate design tokens
359+
- For themes in `app/design/frontend/`:
360+
- Generates tokens in `web/tailwind/generated/hyva-tokens.css`
361+
- For vendor themes (in `vendor/` directory):
362+
- Generates tokens in `web/tailwind/generated/hyva-tokens.css` first
363+
- Copies the generated file to `var/generated/hyva-token/{ThemeCode}/hyva-tokens.css`
364+
- Displays a note informing that tokens were saved to var/generated location
365+
- Returns success status code or error message
366+
367+
**Requirements**:
368+
369+
- Theme must be a Hyvä theme
370+
- Theme must be built first (`mageforge:theme:build`)
371+
- Node.js and npm must be available
372+
- `hyva-tokens` package must be installed (via theme build)
373+
374+
**Output Locations**:
375+
376+
- **Custom themes** (app/design): `{theme-path}/web/tailwind/generated/hyva-tokens.css`
377+
- **Vendor themes** (vendor/): `var/generated/hyva-token/{ThemeCode}/hyva-tokens.css`
378+
379+
**Error Handling**:
380+
381+
- Returns error if theme is not installed
382+
- Returns error if theme is not a Hyvä theme
383+
- Returns warning if node_modules not found (build required)
384+
- Returns error if tailwind directory doesn't exist
385+
386+
---
387+
311388
## Command Services
312389

313390
The commands rely on several services for their functionality:
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenForgeProject\MageForge\Console\Command\Theme;
6+
7+
use Laravel\Prompts\SelectPrompt;
8+
use Magento\Framework\Console\Cli;
9+
use Magento\Framework\Filesystem\Driver\File;
10+
use Magento\Framework\Shell;
11+
use OpenForgeProject\MageForge\Console\Command\AbstractCommand;
12+
use OpenForgeProject\MageForge\Model\ThemeList;
13+
use OpenForgeProject\MageForge\Model\ThemePath;
14+
use OpenForgeProject\MageForge\Service\ThemeBuilder\BuilderPool;
15+
use Symfony\Component\Console\Input\InputArgument;
16+
use Symfony\Component\Console\Input\InputInterface;
17+
use Symfony\Component\Console\Output\OutputInterface;
18+
19+
/**
20+
* Command for generating Hyvä design tokens
21+
*/
22+
class TokensCommand extends AbstractCommand
23+
{
24+
/**
25+
* @param ThemeList $themeList
26+
* @param ThemePath $themePath
27+
* @param BuilderPool $builderPool
28+
* @param File $fileDriver
29+
* @param Shell $shell
30+
*/
31+
public function __construct(
32+
private readonly ThemeList $themeList,
33+
private readonly ThemePath $themePath,
34+
private readonly BuilderPool $builderPool,
35+
private readonly File $fileDriver,
36+
private readonly Shell $shell,
37+
) {
38+
parent::__construct();
39+
}
40+
41+
/**
42+
* {@inheritdoc}
43+
*/
44+
protected function configure(): void
45+
{
46+
$this->setName($this->getCommandName('hyva', 'tokens'))
47+
->setAliases(['m:h:t'])
48+
->setDescription('Generate Hyvä design tokens from design.tokens.json or hyva.config.json')
49+
->addArgument(
50+
'themeCode',
51+
InputArgument::OPTIONAL,
52+
'Theme code to generate tokens for (format: Vendor/theme)'
53+
);
54+
}
55+
56+
/**
57+
* {@inheritdoc}
58+
*/
59+
protected function executeCommand(InputInterface $input, OutputInterface $output): int
60+
{
61+
$themeCode = $input->getArgument('themeCode');
62+
$isVerbose = $this->isVerbose($output);
63+
64+
if (empty($themeCode)) {
65+
$themes = $this->themeList->getAllThemes();
66+
$options = array_map(fn($theme) => $theme->getCode(), $themes);
67+
68+
$themeCodePrompt = new SelectPrompt(
69+
label: 'Select theme to generate tokens for',
70+
options: $options,
71+
scroll: 10,
72+
hint: 'Arrow keys to navigate, Enter to confirm',
73+
);
74+
75+
try {
76+
$themeCode = $themeCodePrompt->prompt();
77+
\Laravel\Prompts\Prompt::terminal()->restoreTty();
78+
} catch (\Exception $e) {
79+
$this->io->error('Interactive mode failed: ' . $e->getMessage());
80+
return Cli::RETURN_FAILURE;
81+
}
82+
}
83+
84+
$themePath = $this->themePath->getPath($themeCode);
85+
if ($themePath === null) {
86+
$this->io->error("Theme $themeCode is not installed.");
87+
return Cli::RETURN_FAILURE;
88+
}
89+
90+
// Check if this is a Hyvä theme
91+
$builder = $this->builderPool->getBuilder($themePath);
92+
if ($builder === null || $builder->getName() !== 'HyvaThemes') {
93+
$this->io->error("Theme $themeCode is not a Hyvä theme. This command only works with Hyvä themes.");
94+
return Cli::RETURN_FAILURE;
95+
}
96+
97+
$tailwindPath = rtrim($themePath, '/') . '/web/tailwind';
98+
if (!$this->fileDriver->isDirectory($tailwindPath)) {
99+
$this->io->error("Tailwind directory not found in: $tailwindPath");
100+
return Cli::RETURN_FAILURE;
101+
}
102+
103+
// Check if node_modules exists
104+
if (!$this->fileDriver->isDirectory($tailwindPath . '/node_modules')) {
105+
$this->io->warning('Node modules not found. Please run: bin/magento mageforge:theme:build ' . $themeCode);
106+
return Cli::RETURN_FAILURE;
107+
}
108+
109+
if ($isVerbose) {
110+
$this->io->section("Generating Hyvä design tokens for theme: $themeCode");
111+
$this->io->text("Working directory: $tailwindPath");
112+
}
113+
114+
// Change to tailwind directory and run npx hyva-tokens
115+
$currentDir = getcwd();
116+
chdir($tailwindPath);
117+
118+
try {
119+
if ($isVerbose) {
120+
$this->io->text('Running npx hyva-tokens...');
121+
}
122+
123+
$this->shell->execute('npx hyva-tokens');
124+
125+
chdir($currentDir);
126+
127+
// Determine output path based on theme location
128+
$isVendorTheme = str_contains($themePath, '/vendor/');
129+
$sourceFilePath = $tailwindPath . '/generated/hyva-tokens.css';
130+
131+
if ($isVendorTheme) {
132+
// Store in var/generated/hyva-token/{ThemeCode}/ for vendor themes
133+
$varGeneratedPath = $currentDir . '/var/generated/hyva-token/' . str_replace('/', '/', $themeCode);
134+
135+
if (!$this->fileDriver->isDirectory($varGeneratedPath)) {
136+
$this->fileDriver->createDirectory($varGeneratedPath, 0755);
137+
}
138+
139+
$generatedFilePath = $varGeneratedPath . '/hyva-tokens.css';
140+
141+
// Copy file to var/generated location
142+
if ($this->fileDriver->isExists($sourceFilePath)) {
143+
$this->fileDriver->copy($sourceFilePath, $generatedFilePath);
144+
}
145+
146+
$this->io->success('Hyvä design tokens generated successfully.');
147+
$this->io->note('This is a vendor theme. Tokens have been saved to var/generated/hyva-token/ instead.');
148+
$this->io->text('Generated file: ' . $generatedFilePath);
149+
} else {
150+
$generatedFilePath = $sourceFilePath;
151+
$this->io->success('Hyvä design tokens generated successfully.');
152+
$this->io->text('Generated file: ' . $generatedFilePath);
153+
}
154+
155+
$this->io->newLine();
156+
157+
return Cli::RETURN_SUCCESS;
158+
} catch (\Exception $e) {
159+
chdir($currentDir);
160+
$this->io->error('Failed to generate Hyvä design tokens: ' . $e->getMessage());
161+
return Cli::RETURN_FAILURE;
162+
}
163+
}
164+
}

src/etc/di.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
OpenForgeProject\MageForge\Console\Command\Static\CleanCommand</item>
2222
<item name="mageforge_hyva_compatibility_check" xsi:type="object">
2323
OpenForgeProject\MageForge\Console\Command\Hyva\CompatibilityCheckCommand</item>
24+
<item name="mageforge_theme_tokens" xsi:type="object">
25+
OpenForgeProject\MageForge\Console\Command\Theme\TokensCommand</item>
2426
</argument>
2527
</arguments>
2628
</type>

0 commit comments

Comments
 (0)