Token导航 LogoToken导航TokenDH.com
开发规范需要联网github未标认证来源可访问许可证需确认审计通过

craft-twig-guidelines工艺树枝指南

Agent Skill

craft-twig-guidelines 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

179

周安装

12

GitHub Stars

38

下载量

97
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:craft-twig-guidelines(工艺树枝指南)
来源仓库:https://github.com/michtio/craftcms-claude-skills
仓库路径:skills/craft-twig-guidelines
安装命令:
npx skills add https://github.com/michtio/craftcms-claude-skills --skill craft-twig-guidelines
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/michtio/craftcms-claude-skills --skill craft-twig-guidelines

简介

craft-twig-guidelines 规定 Craft CMS 5 项目中 Twig 模板的编码标准。

  • 适用于所有 Twig 代码,包括组件、视图、布局与部分文件。
  • 强调变量命名、空值处理、空白控制与 include 隔离等可维护性要点。
  • 需与 craft-content-modeling 联动,确保模板与内容模型匹配。
  • 适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

SKILL.md

Twig Coding Standards — Craft CMS 5

Coding conventions for Twig templates in Craft CMS 5 projects. These apply to all Twig code — atomic components, views, layouts, builders, partials.

Companion Skills — Always Load Together

When this skill triggers, also load:

  • craft-site — Template architecture and component patterns. Required when creating or editing components, layouts, views, or builders.
  • craft-content-modeling — Content architecture. Required when template code involves element queries, field access, or section decisions.

For Twig architecture patterns (atomic design, routing, builders), see the craft-site skill. For PHP coding standards, see craft-php-guidelines.

Documentation

Use WebFetch on specific doc pages when something isn't covered here.

Variable Naming

Single-word, descriptive, lowercase preferred. When multi-word is needed, use camelCase.

{# Correct #}
{% set heading = entry.title %}
{% set image = entry.heroImage.one() %}
{% set items = navigation.links.all() %}
{% set element = props.get('url') ? 'a' : 'span' %}
{% set buttonText = entry.callToAction %}
{% set containerClass = 'max-w-3xl' %}

{# Wrong — abbreviations #}
{% set el = props.get('url') ? 'a' : 'span' %}
{% set btn = entry.callToAction %}
{% set nav = navigation.links.all() %}

{# Wrong — snake_case #}
{% set button_text = entry.callToAction %}
{% set container_class = 'max-w-3xl' %}

No abbreviations: element not el, button not btn, navigation not nav, description not desc.

Prefer single-word names when context makes the meaning clear (e.g. heading inside a component is better than sectionHeading). But multi-word camelCase is perfectly fine when needed for clarity.

Null Handling

?? is the default. Always safe, always portable.

??? (empty coalesce) is acceptable if the project already has nystudio107/craft-empty-coalesce or nystudio107/craft-seomatic installed — both provide the operator. But never install a plugin just for ???. Check composer.json first.

{# Always correct #}
{% set heading = entry.heading ?? '' %}
{% set image = entry.heroImage.one() ?? null %}
{{ props.get('label') ?? 'Default' }}

{# OK if empty-coalesce or SEOmatic is installed — checks empty, not just null #}
{% set heading = entry.heading ??? '' %}

{# Wrong — verbose, unnecessary #}
{% if entry.heading is defined and entry.heading is not null %}
{% if entry.heading is not defined %}

Twig 3.21.x (Craft 5) does not have the nullsafe operator (?.). That requires Twig 3.23+. Use ?? and ternaries instead:

{# Can't do this yet #}
{{ entry?.author?.fullName }}

{# Do this instead #}
{{ entry.author.fullName ?? '' }}

Whitespace Control

Use {%- and {{- for whitespace trimming. Never use {%- minify -%}.

{# Correct — surgical whitespace control #}
{%- set heading = entry.title -%}
{%- if heading -%}
    {{- heading -}}
{%- endif -%}

{# Wrong — deprecated minification approach #}
{%- minify -%}
    {% set heading = entry.title %}
{%- endminify -%}

Apply whitespace control on tags that produce unwanted blank lines in output. Not every tag needs it — use where visible output whitespace matters.

Include Isolation

Every {% include %} MUST use only. No exceptions.

{# Correct — explicit, isolated #}
{%- include '_atoms/buttons/button--primary' with {
    text: entry.title,
    url: entry.url,
} only -%}

{# Wrong — ambient variables leak in #}
{%- include '_atoms/buttons/button--primary' with {
    text: entry.title,
    url: entry.url,
} -%}

Without only, a component can silently depend on variables from its parent scope, creating invisible coupling.

No Macros for Components

Never use {% macro %} for UI components. Macros don't support extends/block and their scoping model differs from includes.

{# Wrong — macro for a component #}
{% macro button(text, url) %}
    <a href="{{ url }}">{{ text }}</a>
{% endmacro %}

{# Correct — include with isolation #}
{%- include '_atoms/buttons/button--primary' with {
    text: text,
    url: url,
} only -%}

Macros are acceptable for utility functions that return strings (e.g., formatting helpers), not for rendering UI.

Comment Headers

Every component file gets a section header comment:

{# =========================================================================
   Component Name
   Brief description of what this component does.
   ========================================================================= #}

Props files, variant files, views, layouts — all get headers. The ========= separator matches the PHP convention from craft-php-guidelines.

Craft Twig Helpers

{% tag %} — Polymorphic Elements

Primary tool for rendering elements whose tag name depends on props.

{%- set element = props.get('url') ? 'a' : 'span' -%}

{%- tag element with {
    class: classes.implode(' '),
    href: props.get('url') ?? false,
    target: props.get('target') ?? false,
    rel: props.get('rel') ?? false,
    aria: {
        label: props.get('label') ?? false,
    },
} -%}
    {{ props.get('text') }}
{%- endtag -%}

Rules:

  • Variable name must be descriptive: element, heading, wrapper. Never el, hd.
  • false omits an attribute entirely from the rendered HTML.
  • null also omits. Use false when explicitly excluding, null when absent.
  • class accepts arrays with automatic falsy filtering.
  • aria and data accept nested hashes that expand to aria-* / data-* attributes.

tag() — Inline Element Function

For simple elements without complex inner content:

{{ tag('span', { class: 'sr-only', text: '(opens in new window)' }) }}
{{ tag('img', { src: image.url, alt: image.title, loading: 'lazy' }) }}
{{ tag('i', { class: ['fa-solid', icon], aria: { hidden: 'true' } }) }}
  • text: key = HTML-encoded content.
  • html: key = raw HTML content (trusted input only).
  • Self-closing elements (img, input, br) handled automatically.

attr() — Attribute Strings

For building attributes in non-tag contexts:

<div{{ attr({ class: ['card', active ? 'card--active'], data: { id: entry.id } }) }}>

Returns a space-prefixed attribute string. Same false-means-omit and class array filtering as {% tag %}.

|attr Filter

For merging attributes onto existing HTML strings:

{{ svg('@webroot/icons/check.svg')|attr({ class: 'w-4 h-4', aria: { hidden: 'true' } }) }}

|parseAttr Filter

For extracting attributes from an HTML string into a hash for manipulation:

{% set attributes = '<div class="foo" data-id="1">'|parseAttr %}
{# attributes = { class: 'foo', data: { id: '1' } } #}

|append Filter

For adding content to an element string:

{{ svg('@webroot/icons/logo.svg')|append('<title>Company Logo</title>', 'replace') }}

svg() Function

{{ svg('@webroot/icons/logo.svg') }}
{{ svg(entry.svgField.one()) }}

Combine with |attr for classes and aria attributes. Use |append for accessible labels inside the SVG.

collect() Conventions

collect() wraps a Twig hash into a Collection object. Primary use cases:

Props collection

{%- set props = collect({
    heading: heading ?? null,
    content: content ?? null,
    utilities: utilities ?? null,
}) -%}

{# Access with get() #}
{{ props.get('heading') }}
{{ props.get('size', 'text-base') }}

{# Merge additional props #}
{%- set props = props.merge({ icon: icon ?? null }) -%}

Class collection (named keys)

{%- set classes = collect({
    layout: 'flex items-center gap-2',
    color: 'bg-brand-primary text-white',
    hover: 'hover:bg-brand-accent',
    utilities: props.get('utilities'),
}) -%}

class="{{ classes.implode(' ') }}"

Null values in collect() produce harmless extra spaces when joined — browsers normalize whitespace in class attributes. Use classes.filter(v => v).implode(' ') if you want pristine output for devMode inspection, but plain implode(' ') is fine for production.

Entry queries as Collections

{# .collect instead of .all() when you need Collection methods #}
{%- set entries = craft.entries.section('blog').eagerly().collect -%}
{%- set featured = entries.filter(e => e.featured).first -%}

Common Pitfalls

  1. ??? operator without the plugin — requires nystudio107/craft-empty-coalesce or nystudio107/craft-seomatic. Check composer.json before using. Default to ??.
  2. snake_case variables — use camelCase: heroImage not hero_image.
  3. Missing only — silent variable leaking, invisible coupling.
  4. {%- minify -%} — deprecated. Use {%- whitespace control.
  5. Abbreviationsel, btn, nav, desc, ctr → spell it out.
  6. is not defined — verbose null checking. ?? handles it.
  7. Macros as components — wrong scoping, no extends/block support.
  8. Hardcoded colors in class stringsbg-yellow-600bg-brand-accent.
  9. String concatenation for classes'flex ' ~ extraClass → use collect({}) with named keys.
  10. options.x pattern — old macro convention. Use direct variable names.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

38.14%
按下载量换算37

Claude

29.5%
按下载量换算29

Cursor

18.84%
按下载量换算18

Gemini CLI

8.89%
按下载量换算9

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills