mcpField
T
twig-templating

twig-templating

github.com/gkastanis開発1838 回インストール28 週間前に更新
リポジトリ

twig-templating について

Drupal のテーマ開発者向け Twig テンプレート資料です。テンプレート名、サジェスト、フィルター、プリプロセス関数を扱い、ロジックの分離やアセット管理、エスケープ、BEM の規約を示します。

主な機能

  1. 01Twig テンプレートの命名と構造
  2. 02一般的なフィルターと Drupal 関数
  3. 03テンプレートサジェストとプリプロセス関数
  4. 04BEM コンポーネント規約
  5. 05アセット管理と安全対策

活用シーン

  1. 01Drupal コンテンツタイプ用テンプレートの作成
  2. 02テーマコンポーネントの CSS と JS の整理
  3. 03テンプレート処理のプリプロセス関数への移動

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/gkastanis/drupal-workflow --skill twig-templating

インストール後、Claude Code で/twig-templatingを入力して読み込まれたか確認します。

詳細

Twig テンプレート

アセットには必ず {{ attach_library() }} を使用してください。インラインの CSS/JS は使用しないでください。カスタムクラスには必ず BEM 命名規則を使用してください。テンプレート内の複雑なロジックは避け、プリプロセス関数を優先してください。ユーザー入力に |raw を使用しないでください。

テンプレートの命名規則

Drupal では、候補名に基づいてテンプレートが検索されます。

node.html.twig                    # Base node template.
node--article.html.twig           # Article content type.
node--article--teaser.html.twig   # Article teaser view mode.
node--42.html.twig                # Specific node by ID.

block.html.twig                   # Base block template.
block--system-branding-block.html.twig  # Specific block.

field.html.twig                   # Base field template.
field--field-image.html.twig      # Specific field.
field--node--field-image--article.html.twig  # Field + bundle.

page.html.twig                    # Base page template.
page--front.html.twig             # Front page.
page--node--42.html.twig          # Specific node page.

テンプレートの構造

{# node--article.html.twig #}
{% set classes = [
  'node',
  'node--' ~ node.bundle,
  node.isPromoted() ? 'node--promoted',
  node.isSticky() ? 'node--sticky',
  view_mode ? 'node--' ~ view_mode,
] %}

<article{{ attributes.addClass(classes) }}>
  {% if label %}
    <h2{{ title_attributes }}>
      <a href="{{ url }}" rel="bookmark">{{ label }}</a>
    </h2>
  {% endif %}

  <div{{ content_attributes.addClass('node__content') }}>
    {{ content }}
  </div>
</article>

よく使うフィルター

フィルター用途例
`t`文字列を翻訳
`raw`自動エスケープを無効化(注意)
`escape`明示的にエスケープ
`clean_class`CSS で安全なクラス
`clean_id`HTML で安全な ID
`date`日付をフォーマット
`length`配列/文字列の長さ
`without`フィールドを除いてレンダリング
`safe_join`区切り文字で配列を結合

Drupal 固有の関数

{# Attach library assets. #}
{{ attach_library('my_theme/component') }}

{# Link to a route. #}
{{ path('entity.node.canonical', {'node': nid}) }}

{# Create a link. #}
{{ link('Click here', url) }}

{# Translate with context. #}
{{ 'Submit'|t({}, {'context': 'my_module'}) }}

{# Access Drupal URL. #}
{{ url('<front>') }}

{# File URL from URI. #}
{{ file_url(node.field_image.entity.fileuri) }}

プリプロセス関数

/**
 * Implements hook_preprocess_HOOK() for node templates.
 */
function my_theme_preprocess_node(array &$variables): void {
  $node = $variables['node'];

  // Add custom variables.
  $variables['reading_time'] = ceil(str_word_count(strip_tags($node->body->value)) / 200);

  // Add conditional classes.
  if ($node->isPublished()) {
    $variables['attributes']['class'][] = 'node--published';
  }
}

テンプレート候補

/**
 * Implements hook_theme_suggestions_HOOK_alter() for node templates.
 */
function my_theme_theme_suggestions_node_alter(array &$suggestions, array $variables): void {
  $node = $variables['elements']['#node'];

  // Add suggestion based on custom field value.
  if ($node->hasField('field_layout') && !$node->get('field_layout')->isEmpty()) {
    $layout = $node->get('field_layout')->value;
    $suggestions[] = 'node__' . $node->bundle() . '__' . $layout;
  }
}

BEM コンポーネントのパターン

{# components/card.html.twig #}
{% set card_classes = [
  'card',
  variant ? 'card--' ~ variant,
  size ? 'card--' ~ size,
] %}

<div{{ attributes.addClass(card_classes) }}>
  {% if image %}
    <div class="card__image">
      {{ image }}
    </div>
  {% endif %}

  <div class="card__content">
    {% if title %}
      <h3 class="card__title">{{ title }}</h3>
    {% endif %}

    {% if body %}
      <div class="card__body">{{ body }}</div>
    {% endif %}
  </div>

  {% if actions %}
    <div class="card__actions">{{ actions }}</div>
  {% endif %}
</div>

テンプレートのベストプラクティス

  1. Twig 内のロジックは最小限にし、複雑なロジックはプリプロセス関数に記述してください。
  2. BEM 命名規則(block__element--modifier)を使用してください。
  3. コンポーネントのアセットには必ず {{ attach_library() }} を使用してください。
  4. 翻訳可能な文字列にはすべて |t フィルターを使用してください。
  5. テンプレートにはデータのみを渡し、Twig 内でデータを取得しないでください。
  6. 本番環境の設定では Twig デバッグを無効にしてください。
  7. 特定のフィールドを除外するには {{ content|without('field_name') }} を使用してください。

コメント