hyva-cms-component

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Hyvä CMS Component Creator

Hyvä CMS 组件创建工具

Overview

概述

This skill guides the interactive creation of custom Hyvä CMS components for Magento 2. It supports creating components in new or existing modules, with field presets for common patterns and automatic setup:upgrade execution.
Command execution: For commands that need to run inside the development environment (e.g.,
bin/magento
), use the
hyva-exec-shell-cmd
skill to detect the environment and determine the appropriate command wrapper.
本技能指导用户交互式创建适用于Magento 2的自定义Hyvä CMS组件。它支持在新模块或现有模块中创建组件,提供常见模式的字段预设,并可自动执行setup:upgrade命令。
命令执行: 对于需要在开发环境中运行的命令(如
bin/magento
),请使用
hyva-exec-shell-cmd
技能检测环境并确定合适的命令包装器。

Workflow

工作流程

Step 1: Module Selection

步骤1:模块选择

If not already specified in the prompt, ask the user where to create the component:
Option A: New Module
Ask for both values (do not assume defaults without asking):
  1. Vendor name (e.g.,
    Acme
    ) - Required, no default. Do not suggest a Vendor name, prompt for user input.
  2. Module name - Suggest
    CmsComponents
    as default so user can press Enter to accept
Then use the
hyva-create-module
skill with:
  • dependencies
    :
    ["Hyva_CmsBase"]
  • composer_require
    :
    {"hyva-themes/commerce-module-cms": "^1.0"}
Option B: Existing Module
  • Request the module path (can be in
    app/code/
    ,
    vendor/
    , or custom location)
  • Verify the module has
    Hyva_CmsBase
    as a dependency in
    etc/module.xml
    . If not present, add it.
  • Verify the module has
    hyva-themes/commerce-module-cms
    as a dependency in
    composer.json
    . If not present, add it.
如果用户的提示中未指定,询问用户要在何处创建组件:
选项A:新建模块
询问以下两个值(未获得用户确认前不要假设默认值):
  1. 厂商名称(例如
    Acme
    )- 必填,无默认值。不要建议厂商名称,直接提示用户输入。
  2. 模块名称 - 建议默认值为
    CmsComponents
    ,用户可按Enter键接受
然后使用
hyva-create-module
技能,参数如下:
  • dependencies
    :
    ["Hyva_CmsBase"]
  • composer_require
    :
    {"hyva-themes/commerce-module-cms": "^1.0"}
选项B:现有模块
  • 请求模块路径(可以在
    app/code/
    vendor/
    或自定义位置)
  • 验证模块的
    etc/module.xml
    中是否包含
    Hyva_CmsBase
    作为依赖项。如果没有,添加该依赖。
  • 验证模块的
    composer.json
    中是否包含
    hyva-themes/commerce-module-cms
    作为依赖项。如果没有,添加该依赖。

Step 2: Component Details

步骤2:组件详情

Gather component information:
  1. Component name (snake_case, e.g.,
    feature_card
    )
  2. Label (display name in editor, e.g., "Feature Card")
  3. Category (Layout, Elements, Media, Content, or Other)
  4. Icon - Automatically select an appropriate icon:
    Step 4a: Identify icons already in use Use the
    hyva-cms-components-dump
    skill to dump all current CMS components. Extract all
    icon
    values from the output to build a list of icons already in use by existing components.
    Step 4b: Find available lucide icons List the SVG files in
    vendor/hyva-themes/magento2-theme-module/src/view/base/web/svg/lucide/
    to get the full set of available icons.
    Step 4c: Select the best fitting icon From the available lucide icons that are NOT already in use by another component:
    • Choose the icon whose name best matches the purpose/meaning of the new component
    • Consider semantic meaning (e.g.,
      shopping-cart.svg
      for cart-related,
      image.svg
      for image-related,
      layout-grid.svg
      for grid layouts)
    • Format the selected icon as
      Hyva_Theme::svg/lucide/[icon-name].svg
    If no suitable unused icon can be found, or if the lucide directory doesn't exist, leave the
    icon
    property unset.
收集组件信息:
  1. 组件名称(蛇形命名法,例如
    feature_card
  2. 标签(编辑器中的显示名称,例如“Feature Card”)
  3. 分类(Layout、Elements、Media、Content或Other)
  4. 图标 - 自动选择合适的图标:
    步骤4a:识别已使用的图标 使用
    hyva-cms-components-dump
    技能导出所有当前CMS组件。从输出中提取所有
    icon
    值,构建现有组件已使用的图标列表。
    步骤4b:查找可用的lucide图标 列出
    vendor/hyva-themes/magento2-theme-module/src/view/base/web/svg/lucide/
    目录下的SVG文件,获取所有可用的lucide图标。
    步骤4c:选择最合适的图标 从尚未被其他组件使用的可用lucide图标中:
    • 选择名称最符合新组件用途/含义的图标
    • 考虑语义(例如,
      shopping-cart.svg
      用于购物车相关组件,
      image.svg
      用于图片相关组件,
      layout-grid.svg
      用于网格布局组件)
    • 将选中的图标格式化为
      Hyva_Theme::svg/lucide/[icon-name].svg
    如果找不到合适的未使用图标,或lucide目录不存在,则不设置
    icon
    属性。

Step 3: Field Selection

步骤3:字段选择

Offer field presets or custom field creation. See
references/field-types.md
"Field Presets" section for available presets (Basic Card, Image Card, CTA Block, Text Block, Feature Item, Testimonial, Accordion Item) or allow custom field definition.
For custom fields, iterate through each field asking:
  1. Field name (snake_case)
  2. Field type (see
    references/field-types.md
    )
  3. Label
  4. Default value (optional)
  5. Required? (yes/no) - Note: This will be added as
    attributes.required
    , NOT as a direct field property
  6. Any additional attributes (these go in the
    attributes
    object)
提供字段预设或自定义字段创建功能。请查看
references/field-types.md
的“Field Presets”部分获取可用预设(Basic Card、Image Card、CTA Block、Text Block、Feature Item、Testimonial、Accordion Item),或允许用户自定义字段。
对于自定义字段,逐个询问以下信息:
  1. 字段名称(蛇形命名法)
  2. 字段类型(请查看
    references/field-types.md
  3. 标签
  4. 默认值(可选)
  5. 是否必填?(是/否)- 注意:此设置将添加到
    attributes.required
    中,而不是作为直接字段属性
  6. 任何其他属性(这些将放入
    attributes
    对象中)

Step 4: Variant Support

步骤4:变体支持

Ask if the component needs template variants:
  • If yes: Gather variant names and labels (e.g., default, compact, wide). See
    references/variant-support.md
    for configuration details.
  • If no: Use single template
询问组件是否需要模板变体:
  • 如果:收集变体名称和标签(例如default、compact、wide)。请查看
    references/variant-support.md
    获取配置详情。
  • 如果:使用单个模板

Step 5: Generate Files

步骤5:生成文件

Create the required files:
创建所需文件:

For New Modules

对于新模块

The
hyva-create-module
skill creates the base module structure. Then add the CMS-specific directories:
app/code/[Vendor]/[Module]/
├── registration.php          # Created by hyva-create-module
├── composer.json             # Created by hyva-create-module
├── etc/
│   ├── module.xml            # Created by hyva-create-module
│   └── hyva_cms/
│       └── components.json   # Create this
└── view/
    └── frontend/
        └── templates/
            └── elements/
                └── [component-name].phtml (or [component-name]/ for variants)
hyva-create-module
技能会创建基础模块结构。然后添加CMS特定目录:
app/code/[Vendor]/[Module]/
├── registration.php          # 由hyva-create-module创建
├── composer.json             # 由hyva-create-module创建
├── etc/
│   ├── module.xml            # 由hyva-create-module创建
│   └── hyva_cms/
│       └── components.json   # 需要创建此文件
└── view/
    └── frontend/
        └── templates/
            └── elements/
                └── [component-name].phtml(或[component-name]/目录用于变体)

For Existing Modules

对于现有模块

Create or update:
  • etc/hyva_cms/components.json
    (merge with existing if present)
  • view/frontend/templates/elements/[component-name].phtml
创建或更新:
  • etc/hyva_cms/components.json
    (如果已存在则合并内容)
  • view/frontend/templates/elements/[component-name].phtml

Step 6: Run Setup

步骤6:运行安装命令

After creating files, run
bin/magento setup:upgrade
using the appropriate command wrapper detected by the
hyva-exec-shell-cmd
skill.
创建文件后,使用
hyva-exec-shell-cmd
技能检测到的合适命令包装器运行
bin/magento setup:upgrade

File Generation Details

文件生成详情

components.json Structure

components.json 结构

json
{
    "[component_name]": {
        "label": "[Label]",
        "category": "[Category]",
        "template": "[Vendor]_[Module]::elements/[component-name].phtml",
        "content": {
            // Generated fields
        },
        "design": {
            "includes": [
                "Hyva_CmsBase::etc/hyva_cms/default_design.json",
                "Hyva_CmsBase::etc/hyva_cms/default_design_typography.json"
            ]
        },
        "advanced": {
            "includes": [
                "Hyva_CmsBase::etc/hyva_cms/default_advanced.json"
            ]
        }
    }
}
json
{
    "[component_name]": {
        "label": "[Label]",
        "category": "[Category]",
        "template": "[Vendor]_[Module]::elements/[component-name].phtml",
        "content": {
            // 生成的字段
        },
        "design": {
            "includes": [
                "Hyva_CmsBase::etc/hyva_cms/default_design.json",
                "Hyva_CmsBase::etc/hyva_cms/default_design_typography.json"
            ]
        },
        "advanced": {
            "includes": [
                "Hyva_CmsBase::etc/hyva_cms/default_advanced.json"
            ]
        }
    }
}

Valid Component Properties

有效的组件属性

IMPORTANT: Only specific properties are allowed at the component level. See
references/component-schema.md
for the complete schema reference.
Key properties:
label
(required),
category
,
template
,
icon
,
children
,
require_parent
,
content
,
design
,
advanced
,
disabled
,
custom_properties
.
Invalid properties that will cause schema errors:
  • hidden
    - Does not exist. Use
    require_parent: true
    for child-only components, or
    disabled: true
  • Any property not listed in the schema reference
重要提示: 组件级别仅允许特定属性。请查看
references/component-schema.md
获取完整的架构参考。
关键属性:
label
(必填)、
category
template
icon
children
require_parent
content
design
advanced
disabled
custom_properties
会导致架构错误的无效属性:
  • hidden
    - 不存在此属性。对于仅作为子组件的组件,使用
    require_parent: true
    ;或使用
    disabled: true
  • 任何未在架构参考中列出的属性

Children Configuration (CRITICAL)

子组件配置(关键)

IMPORTANT:
children
is a ROOT-LEVEL component property, NOT a field type within
content
,
design
, or
advanced
.
INCORRECT ❌:
json
{
    "my_component": {
        "content": {
            "items": {
                "type": "children",
                "label": "Items"
            }
        }
    }
}
CORRECT ✅:
json
{
    "my_component": {
        "label": "My Component",
        "children": {
            "config": {
                "accepts": ["child_component"],
                "max_children": 10
            }
        },
        "content": {
            "title": {
                "type": "text",
                "label": "Title"
            }
        }
    }
}
In templates, access children via
$block->getData('children')
, NOT via a custom field name.
重要提示:
children
是根级别的组件属性,而不是
content
design
advanced
中的字段类型。
错误示例 ❌:
json
{
    "my_component": {
        "content": {
            "items": {
                "type": "children",
                "label": "Items"
            }
        }
    }
}
正确示例 ✅:
json
{
    "my_component": {
        "label": "My Component",
        "children": {
            "config": {
                "accepts": ["child_component"],
                "max_children": 10
            }
        },
        "content": {
            "title": {
                "type": "text",
                "label": "Title"
            }
        }
    }
}
在模板中,通过
$block->getData('children')
访问子组件,而不是通过自定义字段名称。

Field Validation (CRITICAL)

字段验证(关键)

IMPORTANT: Field validation attributes like
required
must be placed in the
attributes
object, NOT as direct field properties.
INCORRECT ❌:
json
{
    "title": {
        "type": "text",
        "label": "Title",
        "required": true
    }
}
CORRECT ✅:
json
{
    "title": {
        "type": "text",
        "label": "Title",
        "attributes": {
            "required": true
        }
    }
}
Other validation attributes that go in
attributes
:
  • required
    (boolean)
  • minlength
    /
    maxlength
    (string)
  • min
    /
    max
    (for numbers)
  • pattern
    (regex string)
  • placeholder
    (string)
  • comment
    (help text)
  • Custom data attributes for validation messages
重要提示: 字段验证属性如
required
必须放在
attributes
对象中,而不是作为直接字段属性。
错误示例 ❌:
json
{
    "title": {
        "type": "text",
        "label": "Title",
        "required": true
    }
}
正确示例 ✅:
json
{
    "title": {
        "type": "text",
        "label": "Title",
        "attributes": {
            "required": true
        }
    }
}
其他需要放入
attributes
的验证属性:
  • required
    (布尔值)
  • minlength
    /
    maxlength
    (字符串)
  • min
    /
    max
    (用于数字字段)
  • pattern
    (正则表达式字符串)
  • placeholder
    (字符串)
  • comment
    (帮助文本)
  • 用于验证消息的自定义数据属性

Child-Only Components

仅子组件

For components that should only be used as children of other components (like list items), use
require_parent: true
:
json
{
    "my_list_item": {
        "label": "My List Item",
        "category": "Elements",
        "require_parent": true,
        "template": false,
        "content": {
            "title": {"type": "text", "label": "Title"}
        }
    },
    "my_list": {
        "label": "My List",
        "category": "Elements",
        "template": "Vendor_Module::elements/my-list.phtml",
        "children": {
            "config": {
                "accepts": ["my_list_item"]
            }
        }
    }
}
When
template: false
, the parent component renders the child data directly (NOT using
$block->createChildHtml()
). See "Rendering Children with template: false" below.
对于仅应作为其他组件子组件使用的组件(如列表项),使用
require_parent: true
json
{
    "my_list_item": {
        "label": "My List Item",
        "category": "Elements",
        "require_parent": true,
        "template": false,
        "content": {
            "title": {"type": "text", "label": "Title"}
        }
    },
    "my_list": {
        "label": "My List",
        "category": "Elements",
        "template": "Vendor_Module::elements/my-list.phtml",
        "children": {
            "config": {
                "accepts": ["my_list_item"]
            }
        }
    }
}
template: false
时,父组件直接渲染子组件数据(不使用
$block->createChildHtml()
)。请查看下方的“使用template: false渲染子组件”部分。

PHTML Template Structure

PHTML模板结构

Every template must start with this header:
php
<?php
declare(strict_types=1);

use Hyva\CmsLiveviewEditor\Block\Element;
use Hyva\Theme\Model\ViewModelRegistry;
use Magento\Framework\Escaper;

/** @var Element $block */
/** @var Escaper $escaper */
/** @var ViewModelRegistry $viewModels */
Additional requirements:
  1. $block->getEditorAttrs()
    on root element
  2. $block->getEditorAttrs('field_name')
    on editable elements
  3. Proper escaping with
    $escaper->escapeHtml()
    and
    $escaper->escapeHtmlAttr()
每个模板必须以以下头部开头:
php
<?php
declare(strict_types=1);

use Hyva\CmsLiveviewEditor\Block\Element;
use Hyva\Theme\Model\ViewModelRegistry;
use Magento\Framework\Escaper;

/** @var Element $block */
/** @var Escaper $escaper */
/** @var ViewModelRegistry $viewModels */
其他要求:
  1. 根元素使用
    $block->getEditorAttrs()
  2. 可编辑元素使用
    $block->getEditorAttrs('field_name')
  3. 使用
    $escaper->escapeHtml()
    $escaper->escapeHtmlAttr()
    正确转义内容

Template Patterns by Field Type

按字段类型划分的模板模式

Text fields:
php
$title = $block->getData('title');
// In template:
<?php if ($title): ?>
    <h2 <?= /** @noEscape */ $block->getEditorAttrs('title') ?>>
        <?= $escaper->escapeHtml($title) ?>
    </h2>
<?php endif; ?>
Richtext/HTML fields:
php
$content = $block->getData('content');
// In template (no escaping for richtext):
<?php if ($content): ?>
    <div <?= /** @noEscape */ $block->getEditorAttrs('content') ?>>
        <?= /** @noEscape */ $content ?>
    </div>
<?php endif; ?>
Image fields:
Use the
hyva-render-media-image
skill for rendering images. It provides the complete API reference and code patterns for the
\Hyva\Theme\ViewModel\Media
view model.
Add these imports when rendering images:
php
// Additional imports for templates with images:
use Hyva\Theme\ViewModel\Media;

/** @var Media $mediaViewModel */
$mediaViewModel = $viewModels->require(Media::class);
The data from
$block->getData('image')
can be passed directly to
getResponsivePictureHtml()
:
php
$image = $block->getData('image');

// In template:
<?php if ($image): ?>
    <?= /** @noEscape */ $mediaViewModel->getResponsivePictureHtml(
        $image,
        ['class' => 'w-full h-auto', 'loading' => 'lazy']
    ) ?>
<?php endif; ?>
For responsive images with separate desktop and mobile sources, see the
hyva-render-media-image
skill.
Link fields:
php
$link = $block->getData('link');
$linkData = $link ? $block->getLinkData($link) : null;
// In template:
<?php if ($linkData): ?>
    <a href="<?= $escaper->escapeUrl($linkData['url']) ?>"
       <?php if (!empty($linkData['target'])): ?>target="<?= $escaper->escapeHtmlAttr($linkData['target']) ?>"<?php endif; ?>>
        <?= $escaper->escapeHtml($linkData['title'] ?: 'Read more') ?>
    </a>
<?php endif; ?>
Boolean fields:
php
$showTitle = (bool) $block->getData('show_title');
// In template:
<?php if ($showTitle && $title): ?>
    <!-- title markup -->
<?php endif; ?>
Select fields:
php
$style = $block->getData('style') ?: 'default';
$styleClasses = match($style) {
    'primary' => 'bg-blue-600 text-white',
    'secondary' => 'bg-gray-200 text-gray-800',
    default => 'bg-white text-gray-600'
};
Children fields (with their own templates):
When child components have their own templates (default behavior), use
$block->createChildHtml()
:
php
$children = $block->getData('children') ?: [];
// In template:
<?php foreach ($children as $index => $child): ?>
    <?= /** @noEscape */ $block->createChildHtml($child, 'child-' . $index) ?>
<?php endforeach; ?>
Rendering Children with
template: false
:
When child components have
"template": false
, the parent component renders them directly. Child data is flat - field values are directly on the child array, NOT nested under a
content
key.
php
$children = $block->getData('children') ?: [];

// In template - iterate and access child data directly:
<?php foreach ($children as $elementData): ?>
    <?php
    // Access fields directly on $elementData (NOT $elementData['content']['field'])
    $image = $elementData['image'] ?? null;
    $title = $elementData['title'] ?? '';
    $description = $elementData['description'] ?? '';

    // Each child has a 'uid' for editor attributes
    $childUid = $elementData['uid'];
    ?>
    <div <?= /** @noEscape */ $block->getEditorAttrs('', $childUid) ?>>
        <?php if (!empty($image['src'])): ?>
            <?php // For image rendering patterns, see the hyva-render-media-image skill ?>
            <?= /** @noEscape */ $mediaViewModel->getResponsivePictureHtml(
                [$block->getResponsiveImageData($image)],
                ['alt' => $image['alt'] ?? '', 'class' => 'w-full h-auto', 'loading' => 'lazy']
            ) ?>
        <?php endif; ?>
        <p <?= /** @noEscape */ $block->getEditorAttrs('title', $childUid) ?>>
            <?= $escaper->escapeHtml($title) ?>
        </p>
    </div>
<?php endforeach; ?>
Key points for
template: false
children:
  • Child field data is flat: use
    $elementData['field_name']
    , NOT
    $elementData['content']['field_name']
  • Each child has a
    uid
    property for editor attributes
  • Use
    $block->getEditorAttrs('field_name', $childUid)
    to enable live editing of child fields
  • Use
    $block->getEditorAttrs('', $childUid)
    on the child's root element
  • For images, check
    !empty($image['src'])
    and use
    $block->getResponsiveImageData($image)
    to process the image data
  • For advanced image rendering patterns (responsive breakpoints, etc.), see the
    hyva-render-media-image
    skill
文本字段:
php
$title = $block->getData('title');
// 在模板中:
<?php if ($title): ?>
    <h2 <?= /** @noEscape */ $block->getEditorAttrs('title') ?>>
        <?= $escaper->escapeHtml($title) ?>
    </h2>
<?php endif; ?>
富文本/HTML字段:
php
$content = $block->getData('content');
// 在模板中(富文本不需要转义):
<?php if ($content): ?>
    <div <?= /** @noEscape */ $block->getEditorAttrs('content') ?>>
        <?= /** @noEscape */ $content ?>
    </div>
<?php endif; ?>
图片字段:
使用
hyva-render-media-image
技能渲染图片。该技能提供了
\Hyva\Theme\ViewModel\Media
视图模型的完整API参考和代码模式。
渲染图片时添加以下导入:
php
// 图片模板的额外导入:
use Hyva\Theme\ViewModel\Media;

/** @var Media $mediaViewModel */
$mediaViewModel = $viewModels->require(Media::class);
$block->getData('image')
获取的数据可直接传递给
getResponsivePictureHtml()
php
$image = $block->getData('image');

// 在模板中:
<?php if ($image): ?>
    <?= /** @noEscape */ $mediaViewModel->getResponsivePictureHtml(
        $image,
        ['class' => 'w-full h-auto', 'loading' => 'lazy']
    ) ?>
<?php endif; ?>
对于包含独立桌面和移动端资源的响应式图片,请查看
hyva-render-media-image
技能。
链接字段:
php
$link = $block->getData('link');
$linkData = $link ? $block->getLinkData($link) : null;
// 在模板中:
<?php if ($linkData): ?>
    <a href="<?= $escaper->escapeUrl($linkData['url']) ?>"
       <?php if (!empty($linkData['target'])): ?>target="<?= $escaper->escapeHtmlAttr($linkData['target']) ?>"<?php endif; ?>>
        <?= $escaper->escapeHtml($linkData['title'] ?: 'Read more') ?>
    </a>
<?php endif; ?>
布尔字段:
php
$showTitle = (bool) $block->getData('show_title');
// 在模板中:
<?php if ($showTitle && $title): ?>
    <!-- 标题标记 -->
<?php endif; ?>
选择字段:
php
$style = $block->getData('style') ?: 'default';
$styleClasses = match($style) {
    'primary' => 'bg-blue-600 text-white',
    'secondary' => 'bg-gray-200 text-gray-800',
    default => 'bg-white text-gray-600'
};
子组件字段(带有自身模板):
当子组件有自身模板时(默认行为),使用
$block->createChildHtml()
php
$children = $block->getData('children') ?: [];
// 在模板中:
<?php foreach ($children as $index => $child): ?>
    <?= /** @noEscape */ $block->createChildHtml($child, 'child-' . $index) ?>
<?php endforeach; ?>
使用
template: false
渲染子组件:
当子组件设置
"template": false
时,父组件直接渲染它们。子组件数据是扁平化的 - 字段值直接在子组件数组中,而不是嵌套在
content
键下。
php
$children = $block->getData('children') ?: [];

// 在模板中 - 遍历并直接访问子组件数据:
<?php foreach ($children as $elementData): ?>
    <?php
    // 直接在$elementData上访问字段(不是$elementData['content']['field'])
    $image = $elementData['image'] ?? null;
    $title = $elementData['title'] ?? '';
    $description = $elementData['description'] ?? '';

    // 每个子组件都有一个用于编辑器属性的'uid'
    $childUid = $elementData['uid'];
    ?>
    <div <?= /** @noEscape */ $block->getEditorAttrs('', $childUid) ?>>
        <?php if (!empty($image['src'])): ?>
            <?php // 图片渲染模式请查看hyva-render-media-image技能 ?>
            <?= /** @noEscape */ $mediaViewModel->getResponsivePictureHtml(
                [$block->getResponsiveImageData($image)],
                ['alt' => $image['alt'] ?? '', 'class' => 'w-full h-auto', 'loading' => 'lazy']
            ) ?>
        <?php endif; ?>
        <p <?= /** @noEscape */ $block->getEditorAttrs('title', $childUid) ?>>
            <?= $escaper->escapeHtml($title) ?>
        </p>
    </div>
<?php endforeach; ?>
template: false
子组件的关键点:
  • 子组件字段数据是扁平化的:使用
    $elementData['field_name']
    ,而不是
    $elementData['content']['field_name']
  • 每个子组件都有一个
    uid
    属性用于编辑器属性
  • 使用
    $block->getEditorAttrs('field_name', $childUid)
    启用子组件字段的实时编辑
  • 在子组件的根元素上使用
    $block->getEditorAttrs('', $childUid)
  • 对于图片,检查
    !empty($image['src'])
    并使用
    $block->getResponsiveImageData($image)
    处理图片数据
  • 对于高级图片渲染模式(响应式断点等),请查看
    hyva-render-media-image
    技能

Resources

资源

references/critical-patterns.md

references/critical-patterns.md

READ THIS FIRST - Essential patterns and common mistakes including:
  • Correct
    children
    configuration (root-level vs field type)
  • Proper field validation with
    attributes
  • Default value syntax
  • Quick checklist before generating components
Read this file before generating any component to avoid common errors.
请首先阅读此文档 - 包含关键模式和常见错误,包括:
  • 正确的
    children
    配置(根级别 vs 字段类型)
  • 使用
    attributes
    进行正确的字段验证
  • 默认值语法
  • 生成组件前的快速检查清单
在生成任何组件前,请阅读此文档以避免常见错误。

references/example-component.md

references/example-component.md

Complete end-to-end example showing a Feature Card component with:
  • Full
    components.json
    definition
  • Matching PHTML template with all field types
  • Supporting module files (registration.php, module.xml, composer.json)
  • Directory structure overview
Read this file when you need a reference for how all the pieces fit together.
完整的端到端示例,展示了一个Feature Card组件,包括:
  • 完整的
    components.json
    定义
  • 匹配所有字段类型的PHTML模板
  • 支持模块文件(registration.php、module.xml、composer.json)
  • 目录结构概述
当您需要了解所有部分如何组合时,请阅读此文档。

references/component-schema.md

references/component-schema.md

Complete schema reference for component declarations, auto-generated from the Hyvä CMS JSON schema. Includes:
  • Valid component-level properties
  • Field declaration properties
  • All field types
  • Validation attributes
Read this file when validating component structure or when encountering schema validation errors.
Run
scripts/update_component_schema.php
after Hyvä CMS updates to regenerate.
组件声明的完整架构参考,由Hyvä CMS JSON架构自动生成。包括:
  • 有效的组件级别属性
  • 字段声明属性
  • 所有字段类型
  • 验证属性
当验证组件结构或遇到架构验证错误时,请阅读此文档。
Hyvä CMS更新后,请运行
scripts/update_component_schema.php
重新生成此文档。

references/field-types.md

references/field-types.md

Complete reference for all supported field types including:
  • Field configuration syntax
  • All available field types with examples
  • Validation attributes
  • Conditional visibility (show_if/hide_if)
  • Field presets for common patterns
Read this file when generating field configurations.
所有支持字段类型的完整参考,包括:
  • 字段配置语法
  • 所有可用字段类型及示例
  • 验证属性
  • 条件可见性(show_if/hide_if)
  • 常见模式的字段预设
当生成字段配置时,请阅读此文档。

references/variant-support.md

references/variant-support.md

Guide for implementing template variants including:
  • Directory structure for variant templates
  • Variant field configuration in components.json
  • Template implementation patterns
  • Common variant patterns and best practices
Read this file when the user wants multiple layout options for a component.
实现模板变体的指南,包括:
  • 变体模板的目录结构
  • components.json中的变体字段配置
  • 模板实现模式
  • 常见变体模式和最佳实践
当用户需要组件的多个布局选项时,请阅读此文档。

references/troubleshooting.md

references/troubleshooting.md

Solutions for common issues including:
  • Schema validation errors
  • Component not visible in editor
  • Template not rendering
  • Live editor not working
  • Image display issues
  • Fallbacks when dependent skills are unavailable
Read this file when encountering errors during component creation or testing.
常见问题的解决方案,包括:
  • 架构验证错误
  • 组件在编辑器中不可见
  • 模板未渲染
  • 实时编辑器不工作
  • 图片显示问题
  • 依赖技能不可用时的回退方案
当组件创建或测试过程中遇到错误时,请阅读此文档。

scripts/update_component_schema.php

scripts/update_component_schema.php

PHP script that reads the Hyvä CMS JSON schema files and regenerates
references/component-schema.md
. Run after upgrading
hyva-themes/commerce-module-cms
to ensure documentation stays current.
PHP脚本,读取Hyvä CMS JSON架构文件并重新生成
references/component-schema.md
。升级
hyva-themes/commerce-module-cms
后请运行此脚本,确保文档保持最新。

assets/templates/component/template.phtml.tpl

assets/templates/component/template.phtml.tpl

Base PHTML structure for CMS components.
Placeholders:
  • {{CONTENT_FIELDS}}
    - PHP variable declarations
  • {{TEMPLATE_BODY}}
    - HTML template content
CMS组件的基础PHTML结构。
占位符:
  • {{CONTENT_FIELDS}}
    - PHP变量声明
  • {{TEMPLATE_BODY}}
    - HTML模板内容

Important Guidelines

重要指南

  1. Always use
    getEditorAttrs()
    on the root element and on each editable field element
  2. Never use
    <script>
    tags
    in templates - use Alpine.js via
    alpine:init
    event
  3. Escape all user content with appropriate escaper methods
  4. Use meaningful default values for better merchant experience
  5. Include design/advanced sections via includes for consistency
  6. Validate component names are snake_case with only lowercase letters, numbers, and underscores
  7. CRITICAL: Use
    default_value
    key, NOT
    default
    - The correct JSON key for default values is
    default_value
    (with underscore), not
    default
    . Example:
    "default_value": "My Title"
    ✅, NOT
    "default": "My Title"
  8. CRITICAL:
    children
    is a root-level property, NOT a field type
    - Never use
    "type": "children"
    in content/design/advanced. Declare
    children
    at component root level. Access via
    $block->getData('children')
    in templates.
  9. CRITICAL: Validation goes in
    attributes
    , NOT as direct properties
    - Use
    "attributes": {"required": true}
    ✅, NOT
    "required": true
    ❌. All HTML5 validation attributes (required, minlength, maxlength, pattern, min, max) must be inside the
    attributes
    object.
<!-- Copyright © Hyvä Themes https://hyva.io. All rights reserved. Licensed under OSL 3.0 -->
  1. 始终在根元素和每个可编辑字段元素上使用
    getEditorAttrs()
  2. 模板中切勿使用
    <script>
    标签
    - 通过
    alpine:init
    事件使用Alpine.js
  3. 使用适当的转义方法转义所有用户内容
  4. 使用有意义的默认值以提升商家体验
  5. 通过includes包含design/advanced部分以保持一致性
  6. 验证组件名称是否为蛇形命名法,仅包含小写字母、数字和下划线
  7. 关键:使用
    default_value
    键,而非
    default
    - 默认值的正确JSON键是
    default_value
    (带下划线),而非
    default
    。示例:
    "default_value": "My Title"
    ✅,而非
    "default": "My Title"
  8. 关键:
    children
    是根级别属性,而非字段类型
    - 切勿在content/design/advanced中使用
    "type": "children"
    。在组件根级别声明
    children
    。在模板中通过
    $block->getData('children')
    访问。
  9. 关键:验证属性放入
    attributes
    中,而非直接作为字段属性
    - 使用
    "attributes": {"required": true}
    ✅,而非
    "required": true
    ❌。所有HTML5验证属性(required、minlength、maxlength、pattern、min、max)必须放在
    attributes
    对象中。
<!-- Copyright © Hyvä Themes https://hyva.io. All rights reserved. Licensed under OSL 3.0 -->