Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ All notable changes to this project will be documented in this file.

## UNRELEASED

- feat: add `mageforge:theme:tokens` command to generate Hyvä design tokens from design.tokens.json or hyva.config.json

## Latest Release

### [0.2.2] - 2025-06-05
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Please ensure that your Magento installation meets this requirement before insta
| `mageforge:theme:list` | Lists all available themes | `m:t:l` |
| `mageforge:theme:build` | Builds selected themes (CSS/TailwindCSS) | `m:t:b`, `frontend:build` |
| `mageforge:theme:watch` | Starts watch mode for theme development | `m:t:w`, `frontend:watch` |
| `mageforge:theme:tokens` | Generate Hyvä design tokens (Hyvä themes only) | `m:t:t` |

---

Expand Down Expand Up @@ -78,7 +79,15 @@ Please ensure that your Magento installation meets this requirement before insta
bin/magento mageforge:theme:watch <theme-code>
```

4. Enjoy automatic CSS rebuilding you work on your theme files!
4. Generate Hyvä design tokens (for Hyvä themes):

```bash
bin/magento mageforge:theme:tokens <theme-code>
```

This creates a `generated/hyva-tokens.css` file from your design tokens configuration.

5. Enjoy automatic CSS rebuilding as you work on your theme files!

## Additional Documentation

Expand Down
83 changes: 81 additions & 2 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,86 @@ bin/magento mageforge:theme:watch [--theme=THEME]

---

### 4. SystemCheckCommand (`mageforge:system:check`)
### 4. TokensCommand (`mageforge:theme:tokens`)

**Purpose**: Generates Hyvä design tokens from design.tokens.json or hyva.config.json configuration files.

**File**: `/src/Console/Command/Theme/TokensCommand.php`

**Dependencies**:
- `ThemePath` - Service to resolve theme paths
- `ThemeList` - Service to retrieve theme information
- `BuilderPool` - Service to verify theme is a Hyvä theme
- `File` - Filesystem driver for checking directories

**Usage**:
```bash
bin/magento mageforge:theme:tokens [<themeCode>]
```

**Implementation Details**:
- If no theme code is provided, displays an interactive prompt to select a theme
- Verifies that the selected theme is a Hyvä theme
- Checks for the presence of the tailwind directory and node_modules
- Executes `npx hyva-tokens` in the theme's tailwind directory
- Generates `generated/hyva-tokens.css` file based on:
- `design.tokens.json` (default)
- `acme.figma-tokens.json` (when configured in hyva.config.json)
- Direct token values in hyva.config.json
- Supports custom CSS selectors (e.g., `:root` for Tailwind v3)

**Token Configuration**:
The command supports various token sources configured in `hyva.config.json`:

1. **Default tokens file**:
```json
{
"tokens": {
"src": "design.tokens.json"
}
}
```

2. **Figma tokens**:
```json
{
"tokens": {
"src": "acme.figma-tokens.json",
"format": "figma"
}
}
```

3. **Inline tokens**:
```json
{
"tokens": {
"values": {
"colors": {
"primary": {
"lighter": "oklch(62.3% 0.214 259.815)",
"DEFAULT": "oklch(54.6% 0.245 262.881)",
"darker": "oklch(37.9% 0.146 265.522)"
}
}
}
}
}
```

4. **Custom CSS selector**:
```json
{
"tokens": {
"src": "design.tokens.json",
"cssSelector": ":root"
}
}
```

---

### 5. SystemCheckCommand (`mageforge:system:check`)

**Purpose**: Displays system information relevant to Magento development.

Expand All @@ -111,7 +190,7 @@ bin/magento mageforge:system:check

---

### 5. VersionCommand (`mageforge:version`)
### 6. VersionCommand (`mageforge:version`)

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

Expand Down
141 changes: 141 additions & 0 deletions src/Console/Command/Theme/TokensCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

declare(strict_types=1);

namespace OpenForgeProject\MageForge\Console\Command\Theme;

use Laravel\Prompts\SelectPrompt;
use Magento\Framework\Console\Cli;
use Magento\Framework\Filesystem\Driver\File;
use Magento\Framework\Shell;
use OpenForgeProject\MageForge\Console\Command\AbstractCommand;
use OpenForgeProject\MageForge\Model\ThemeList;
use OpenForgeProject\MageForge\Model\ThemePath;
use OpenForgeProject\MageForge\Service\ThemeBuilder\BuilderPool;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
* Command for generating Hyvä design tokens
*/
class TokensCommand extends AbstractCommand
{
/**
* @param ThemeList $themeList
* @param ThemePath $themePath
* @param BuilderPool $builderPool
* @param File $fileDriver
* @param Shell $shell
*/
public function __construct(
private readonly ThemeList $themeList,
private readonly ThemePath $themePath,
private readonly BuilderPool $builderPool,
private readonly File $fileDriver,
private readonly Shell $shell,
) {
parent::__construct();
}

/**
* {@inheritdoc}
*/
protected function configure(): void
{
$this->setName($this->getCommandName('theme', 'tokens'))
->setDescription('Generate Hyvä design tokens from design.tokens.json or hyva.config.json')
->addArgument(
'themeCode',
InputArgument::OPTIONAL,
'Theme code to generate tokens for (format: Vendor/theme)'
);
}

/**
* {@inheritdoc}
*/
protected function executeCommand(InputInterface $input, OutputInterface $output): int
{
$themeCode = $input->getArgument('themeCode');
$isVerbose = $this->isVerbose($output);

if (empty($themeCode)) {
$themes = $this->themeList->getAllThemes();
$options = array_map(fn($theme) => $theme->getCode(), $themes);

$themeCodePrompt = new SelectPrompt(
label: 'Select theme to generate tokens for',
options: $options,
scroll: 10,
hint: 'Arrow keys to navigate, Enter to confirm',
);

try {
$themeCode = $themeCodePrompt->prompt();
\Laravel\Prompts\Prompt::terminal()->restoreTty();
} catch (\Exception $e) {
$this->io->error('Interactive mode failed: ' . $e->getMessage());
return Cli::RETURN_FAILURE;
}
}

$themePath = $this->themePath->getPath($themeCode);
if ($themePath === null) {
$this->io->error("Theme $themeCode is not installed.");
return Cli::RETURN_FAILURE;
}

// Check if this is a Hyvä theme
$builder = $this->builderPool->getBuilder($themePath);
if ($builder === null || $builder->getName() !== 'HyvaThemes') {
$this->io->error("Theme $themeCode is not a Hyvä theme. This command only works with Hyvä themes.");
return Cli::RETURN_FAILURE;
}

$tailwindPath = rtrim($themePath, '/') . '/web/tailwind';
if (!$this->fileDriver->isDirectory($tailwindPath)) {
$this->io->error("Tailwind directory not found in: $tailwindPath");
return Cli::RETURN_FAILURE;
}

// Check if node_modules exists
if (!$this->fileDriver->isDirectory($tailwindPath . '/node_modules')) {
$this->io->warning('Node modules not found. Please run: bin/magento mageforge:theme:build ' . $themeCode);
return Cli::RETURN_FAILURE;
}

if ($isVerbose) {
$this->io->section("Generating Hyvä design tokens for theme: $themeCode");
$this->io->text("Working directory: $tailwindPath");
}

// Change to tailwind directory and run npx hyva-tokens
$currentDir = getcwd();
chdir($tailwindPath);

try {
if ($isVerbose) {
$this->io->text('Running npx hyva-tokens...');
}

$this->shell->execute('npx hyva-tokens');

chdir($currentDir);

$this->io->success('Hyvä design tokens generated successfully.');

if ($isVerbose) {
$this->io->newLine();
$this->io->text('The generated file can be found at:');
$this->io->text($tailwindPath . '/generated/hyva-tokens.css');
}

return Cli::RETURN_SUCCESS;
} catch (\Exception $e) {
chdir($currentDir);
$this->io->error('Failed to generate Hyvä design tokens: ' . $e->getMessage());
return Cli::RETURN_FAILURE;
}
}
}
3 changes: 3 additions & 0 deletions src/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
<item name="mageforge_theme_watch"
xsi:type="object"
>OpenForgeProject\MageForge\Console\Command\Theme\WatchCommand</item>
<item name="mageforge_theme_tokens"
xsi:type="object"
>OpenForgeProject\MageForge\Console\Command\Theme\TokensCommand</item>
</argument>
</arguments>
</type>
Expand Down