HubLチートシート
HubSpot Markup Languageを1ページに。構文、よく使うフィルター・関数・タグ、モジュールフィールドの仕組みを、それぞれ例とともに紹介します。
- HubL(HubSpot Markup Language)は、HubSpot CMSのテーマ、モジュール、パーシャル、メールで使うテンプレート言語です。
- HubSpotがJavaで実装したJinjaであるJinjavaをベースにしているため、Jinjaの書き方の多くがそのまま使えます。
- HubLはHubSpotのサーバー上でレンダリングされ、訪問者が目にするのは完成したHTMLだけです。
- HubLはtransjtが書くので、エクスポートしたモジュールはすべてフィールドが接続済みです。このチートシートは、HubLを調整したいときにお使いください。
区切り文字
| 構文 | 役割 |
|---|---|
{{ ... }} | 式を出力します(変数、フィールド、関数の結果など)。 |
{% ... %} | 文またはタグ:if、for、set、module、include… |
{# ... #} | コメント。ページには出力されません。 |
{%- ... -%} | 空白の制御:ハイフンを付けると、タグの前または後の空白が取り除かれます。 |
{# A module's heading field #}
<h1>{{ module.heading }}</h1>
変数
独自の変数はsetで設定します。文字列、数値、ブール値、リスト、辞書は、Jinjaと同じように使えます。
{% set title = "Pricing" %}
{% set sizes = [480, 960, 1440] %}
{% set button = {"label": "Start free", "url": "/start/"} %}
{{ title ~ " | transjt" }} {# ~ joins strings #}
{{ sizes[0] }} {# 480 #}
{{ button.label }} {# or button["label"] #}
{% do sizes.append(1920) %} {# change a list in place #}
HubSpotは、すべてのページで次の変数を提供します。
| 変数 | 内容 |
|---|---|
content | ページまたはブログ記事:content.absolute_url、content.name、content.publish_date… |
page_meta.html_title、page_meta.meta_description | ページ設定のタイトルとメタディスクリプション。 |
request | リクエスト:request.path、request.domain、request.query_dict(クエリ文字列を辞書にしたもの)。 |
local_dt | アカウントのタイムゾーンでの現在の日時。 |
theme | テーマのfields.jsonにある設定:theme.colors.primary.colorなど。名前はテーマでの命名どおりです。 |
module | モジュール内で、そのフィールドの値:module.heading、module.image.src… |
contact | パーソナライズ用の、既知の訪問者のコンタクトプロパティ:contact.firstname。 |
is_in_editor | ページがHubSpotのエディターで開かれている間はtrueになります。 |
contact、local_dt、request.query_dict、today()は訪問ごとに変わるため、これらを使ったページは、HubSpotのプリレンダリングキャッシュから完全には配信できません。必要な場所でだけ使ってください。ifとfor
{% if module.items %}
<ul>
{% for item in module.items %}
<li class="{{ 'is-first' if loop.first else '' }}">{{ loop.index }}. {{ item.title }}</li>
{% endfor %}
</ul>
{% elif is_in_editor %}
<p>Add an item in the sidebar.</p>
{% else %}
{# Nothing to show on the live page #}
{% endif %}
- ループ内:
loop.index(1始まり)、loop.index0(0始まり)、loop.first、loop.last、loop.length。 {% unless condition %} … {% endunless %}はifの逆です。- テストは英語の文のように書けます:
{% if module.subtitle is defined %}、is string、is number、is even、is divisibleby 3。 - 演算子:
==、!=、and、or、not、in。
フィルター
フィルターはパイプの後に書いて値を変換します({{ value|filter }})。複数のフィルターは、左から右へ順につなげられます。
| フィルター | 例 | 結果 |
|---|---|---|
default | {{ module.label|default("Read more", true) }} | 値がない場合の代替値。trueを付けると、値が空の場合にも適用 |
upper、lower、capitalize、title | {{ "hubl"|upper }} | HUBL |
truncate | {{ text|truncate(120) }} | 単語の区切りで120文字に切り詰め、末尾に「...」を付加 |
truncatehtml | {{ module.text|truncatehtml(200) }} | リッチテキストを短縮し、タグを正しく閉じた状態に保つ |
striptags | {{ module.text|striptags }} | HTMLを除いたプレーンテキスト |
escape_html、escape_attr、escape_url | alt="{{ module.alt|escape_attr }}" | HTMLのテキスト、属性、URLで安全に出力 |
replace | {{ "a-b"|replace("-", " ") }} | a b |
split、join | {{ "a,b"|split(",")|join(" · ") }} | a · b |
length | {{ module.items|length }} | 項目の数 |
sort | {{ posts|sort(False, False, "name") }} | 属性で並べ替え(逆順、大文字と小文字の区別、属性) |
selectattr、map | {{ items|selectattr("featured")|map("title")|join(", ") }} | featuredに該当する項目のタイトル |
format_datetime | {{ content.publish_date|format_datetime("medium", "Europe/Berlin") }} | 指定したタイムゾーンで書式設定した日時(指定がなければUTC) |
int、float、round | {{ "3.7"|float|round }} | 4 |
tojson | {{ module|tojson }} | スクリプト用に、値をJSONにしたもの |
pprint | {{ module|pprint }} | デバッグ用に、値を型とともに出力 |
関数
| 関数 | 役割 |
|---|---|
get_asset_url("../css/main.css") | テーマ内のファイルの公開URL。 |
require_css(url)、require_js(url) | スタイルシートをheadに、スクリプトをbodyの終了タグの前に読み込みます。何度呼び出しても、読み込まれるのは1ページにつき1回だけです。 |
resize_image_url(url, 800) | ファイルマネージャーの画像を、幅800ピクセルにリサイズしたコピー。 |
menu("main") | 名前またはIDで指定したナビゲーションメニュー(子項目を含む)。独自のマークアップで使います。 |
blog_recent_posts("default", 3) | デフォルトのブログの最新記事3件。 |
blog_popular_posts("default", 5) | 過去1年間で最も読まれた記事5件。6時間ごとに更新されます。 |
hubdb_table_rows(table, "orderBy=name&limit=10") | HubDBテーブルの行を、クエリ文字列でフィルター・並べ替えして取得します(Content Hub ProfessionalまたはEnterprise)。 |
color_variant("#FF00F4", -40) | 色を明るく(正の値)または暗く(負の値)したもの。 |
today()、unixtimestamp(local_dt) | 今日の日付。日付をミリ秒単位のUnixタイムスタンプにしたもの。 |
{% for post in blog_recent_posts("default", 3) %}
<a href="{{ post.absolute_url }}">{{ post.name }}</a>
{% endfor %}
タグ
| タグ | 役割 |
|---|---|
{% module "hero" path="../modules/hero" %} | テンプレート内の固定位置にモジュールを配置します。 |
{% dnd_area "main" %} … {% end_dnd_area %} | 編集者がページエディターで中身を入れるドラッグ&ドロップエリア。中にはdnd_section、dnd_row、dnd_column、dnd_moduleを入れます。 |
{% include "../partials/footer.html" %} | 別のファイルを挿入します。 |
{% global_partial path="../partials/header.html" %} | 一度編集すれば、すべてのページで共有されるパーシャル。 |
{% extends "./layouts/base.html" %}と{% block body %} | テンプレートの継承:ページがレイアウトのブロックを埋めます。 |
{% macro button(label, url) %} | パラメーター付きの再利用できるスニペット。{% from "/my-theme/macros.html" import button %}で共有します(パスはデザインマネージャー上のファイルのパス)。 |
{% require_css %} … {% end_require_css %} | headに移される<style>ブロックで、中でHubLを使えます。関数とは異なり、呼び出すたびに追加されます。 |
{% raw %} … {% endraw %} | 中のHubLを実行せず、書かれたとおりに内容を出力します。 |
すべてのページテンプレートには、{{ standard_header_includes }}を閉じタグ</head>の前に、{{ standard_footer_includes }}を閉じタグ</body>の前に入れる必要があります。これらは、HubSpot自体のスクリプト、スタイル、トラッキングを読み込みます。
<!--
templateType: page
isAvailableForNewContent: true
label: Landing page
-->
{% extends "./layouts/base.html" %}
{% block body %}
{% dnd_area "main" label="Main" %}
{% dnd_section %}
{% dnd_column %}
{% dnd_row %}
{% dnd_module path="@hubspot/rich_text" %}{% end_dnd_module %}
{% end_dnd_row %}
{% end_dnd_column %}
{% end_dnd_section %}
{% end_dnd_area %}
{% endblock %}
モジュールとフィールド
モジュールは名前が.moduleで終わるフォルダーで、module.html(HubL)、module.css、module.js、fields.json、meta.jsonを含みます。module.htmlでは、各フィールドをmodule.+フィールド名で参照します。
| フィールドの種類 | HubL |
|---|---|
| テキスト、リッチテキスト | {{ module.heading }}、{{ module.text }} |
| 画像 | module.image.src、.alt、.width、.height |
| リンク | module.link.url.href、module.link.open_in_new_tab |
| 色 | module.color.color、module.color.opacity |
| 選択肢、ブール値 | {{ module.style }}、{% if module.show_button %} |
繰り返しフィールド(occurrenceを持つフィールド) | {% for item in module.items %} |
{% set img = module.image %}
<section class="hero hero--{{ name }}">
{% inline_text field="heading" value="{{ module.heading }}" %}
{% if img.src %}
<img src="{{ img.src }}" alt="{{ img.alt|escape_attr }}" width="{{ img.width }}" height="{{ img.height }}" loading="lazy">
{% endif %}
</section>
{{ name }}は、モジュールインスタンスの一意の名前です。CSSを1つのインスタンスだけに適用するときに使います。inline_textとinline_rich_textを使うと、エディターでページ上のフィールドを直接編集できるようになります。module.cssではHubLがほとんど使えず(module_asset_urlなどのヘルパーのみ)、フィールドの値も読み取れません。module.jsではHubLは一切使えません。フィールドの値を使うには、{% require_css %}ブロックをmodule.htmlに置きます。- フィールドで選んだ色をインラインの
style=""で出力すると、モジュールのCSSより優先されます。スタイルが変わらないときは、まずmodule.htmlを確認してください。
デバッグ
{{ module|pprint }}は、値をその型とともにページ上に直接出力します。公開する前に削除してください。- 公開中のページのURLに
?hsDebug=trueを付けると、CSSとJavaScriptが圧縮・結合されずに読み込まれ、キャッシュは一切使われません。また、ページのソースの末尾に、HubLのエラーと警告、レンダリング時間、ページをプリレンダリングできるかどうかが表示されます。 - デザインマネージャーでは、編集中のファイルでHubLのエラーが表示されます。HubSpot CLIでは、
hs cms lint <path>でファイルをチェックでき、アップロード時には致命的なエラーがターミナルに表示されます。 - 更新したモジュールやテンプレートを使っているページは、HubSpotが自動的に再レンダリングします。これには数分かかることがあります。公開中のページに古いバージョンが表示されたままなら、もう一度公開してください。
transjtテーマのHubL
デザインやAIで作ったサイトをエクスポートすると、transjtがテーマを書き上げます。ドラッグ&ドロップエリアを備えたテンプレートと、セクションごとに1つのモジュールで、各モジュールのテキスト、画像、リンク、色はフィールドになります。マーケティングチームはページエディターでそのフィールドを編集するので、誰もHubLを書く必要はありません。
テーマを自分で調整するときは、独自のCSSとJavaScriptをcustom.cssとcustom.jsに書いてください。再エクスポートしても、そのまま残ります。詳しくはHubSpot開発者向けとHubSpotでテーマを使うをご覧ください。
HubLの完全なリファレンスは、HubSpotの開発者向けドキュメントにあります。