Skip to content

Auto-escaping

{{ customer.first_name }}

If a shopper signs up as <script>alert(1)</script>, Shopify would print a script into your page; Sooquna prints &lt;script&gt;alert(1)&lt;/script&gt;, which shows as text. You get protection from cross-site scripting without remembering | escape everywhere.

Values Sooquna knows are safe HTML are printed as HTML:

  • Rich text the merchant wrote, cleaned of scripts when saved: product.description, page.content, article.content, collection.description, and richtext, inline_richtext and html settings.
  • HTML built by filters: image_tag, stylesheet_tag, script_tag, link_to, time_tag, placeholder_svg_tag, payment_type_svg_tag, format_address, default_pagination, highlight, structured_data, newline_to_br, and the text of escape and json.
  • Translations whose key ends in _html, with their variables escaped.
  • Theme output: content_for_header, content_for_layout, sections, blocks and snippets.

A filter that works on text turns trusted HTML into text, and the text is escaped:

{{ product.description }} {%- comment -%} HTML {%- endcomment -%}
{{ product.description | replace: 'Soft', 'Very soft' }} {%- comment -%} escaped: tags show as text {%- endcomment -%}
{{ product.description | strip_html | truncate: 120 }} {%- comment -%} plain text: correct {%- endcomment -%}

So: strip the HTML before you shorten or change rich text, or keep the HTML as it is.

There’s no raw filter, and safe exists only for compatibility: neither turns text into HTML. (The raw tag is different: it prints Liquid code without running it.) If you need markup from data, build it from parts:

<a href="{{ product.url }}" title="{{ product.title }}">{{ product.title }}</a>

Each value is escaped for its place, and the markup is your own.

Shopify code In Sooquna
{{ title | escape }} Works (escaped once). {{ title }} does the same.
{{ product.description }} Works.
{{ settings.text | append: '<br>' }} The <br> shows as text. Put markup outside the output: {{ settings.text }}<br>.
{{ product.description | truncatewords: 30 }} Shows tags as text. Use {{ product.description | strip_html | truncatewords: 30 }}.
{{ 'x' | t }} with HTML in the value Rename the key to end in _html.
<script>var p = {{ product | json }};</script> Works: json is safe inside <script>.

Was this page helpful?