Initial commit
This commit is contained in:
345
skills/shopify-liquid/SKILL.md
Normal file
345
skills/shopify-liquid/SKILL.md
Normal file
@@ -0,0 +1,345 @@
|
||||
---
|
||||
name: shopify-liquid
|
||||
description: Complete Liquid templating language reference including syntax, filters, objects, control flow, loops, and conditionals for Shopify themes. Use when working with .liquid files, creating theme templates, implementing dynamic content, debugging Liquid code, working with sections and snippets, or rendering product/collection/cart data in Shopify stores.
|
||||
---
|
||||
|
||||
# Shopify Liquid Templating
|
||||
|
||||
Expert guidance for Shopify's Liquid templating language including complete syntax reference, filters, objects, and best practices.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Invoke this skill when:
|
||||
|
||||
- Working with `.liquid`, `.css.liquid`, or `.js.liquid` files
|
||||
- Creating or modifying theme templates (product, collection, cart, etc.)
|
||||
- Implementing dynamic content rendering
|
||||
- Using Liquid filters to format data (money, dates, strings)
|
||||
- Accessing Shopify objects (product, collection, cart, customer)
|
||||
- Writing conditional logic or loops in templates
|
||||
- Debugging Liquid syntax errors or output issues
|
||||
- Creating sections or snippets with Liquid logic
|
||||
- Formatting prices, dates, or other data
|
||||
|
||||
## Core Capabilities
|
||||
|
||||
### 1. Liquid Syntax Fundamentals
|
||||
|
||||
Three core syntax types:
|
||||
|
||||
**Output (display values):**
|
||||
```liquid
|
||||
{{ product.title }}
|
||||
{{ product.price | money }}
|
||||
{{ collection.products.size }}
|
||||
```
|
||||
|
||||
**Logic (conditionals and control):**
|
||||
```liquid
|
||||
{% if product.available %}
|
||||
<button>Add to Cart</button>
|
||||
{% else %}
|
||||
<p>Sold Out</p>
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
**Assignment (variables):**
|
||||
```liquid
|
||||
{% assign sale_price = product.price | times: 0.8 %}
|
||||
{% capture full_title %}{{ collection.title }} - {{ product.title }}{% endcapture %}
|
||||
```
|
||||
|
||||
**Whitespace control:**
|
||||
```liquid
|
||||
{%- if condition -%}
|
||||
Content (strips whitespace)
|
||||
{%- endif -%}
|
||||
```
|
||||
|
||||
### 2. Control Flow Tags
|
||||
|
||||
**Conditionals:**
|
||||
- `if/elsif/else/endif` - Standard conditionals
|
||||
- `unless/endunless` - Negated if
|
||||
- `case/when/else/endcase` - Switch statements
|
||||
|
||||
**Logical operators:**
|
||||
- `and`, `or` - Combine conditions
|
||||
- `==`, `!=`, `>`, `<`, `>=`, `<=` - Comparisons
|
||||
- `contains` - Substring/array search
|
||||
|
||||
**Example:**
|
||||
```liquid
|
||||
{% if product.available and product.price < 100 %}
|
||||
Affordable and in stock
|
||||
{% elsif product.available %}
|
||||
Available but pricey
|
||||
{% else %}
|
||||
Out of stock
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
### 3. Iteration (Loops)
|
||||
|
||||
**for loop:**
|
||||
```liquid
|
||||
{% for product in collection.products %}
|
||||
{{ product.title }}
|
||||
{% endfor %}
|
||||
|
||||
{# With modifiers #}
|
||||
{% for product in collection.products limit: 5 offset: 10 reversed %}
|
||||
{{ product.title }}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
**forloop object:**
|
||||
```liquid
|
||||
{% for item in array %}
|
||||
{{ forloop.index }} {# 1-based index #}
|
||||
{{ forloop.index0 }} {# 0-based index #}
|
||||
{{ forloop.first }} {# Boolean: first item #}
|
||||
{{ forloop.last }} {# Boolean: last item #}
|
||||
{{ forloop.length }} {# Total items #}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
**Pagination:**
|
||||
```liquid
|
||||
{% paginate collection.products by 12 %}
|
||||
{% for product in paginate.collection.products %}
|
||||
{% render 'product-card', product: product %}
|
||||
{% endfor %}
|
||||
|
||||
{% if paginate.pages > 1 %}
|
||||
{{ paginate | default_pagination }}
|
||||
{% endif %}
|
||||
{% endpaginate %}
|
||||
```
|
||||
|
||||
### 4. Essential Filters
|
||||
|
||||
**Money formatting:**
|
||||
```liquid
|
||||
{{ 1000 | money }} {# $10.00 #}
|
||||
{{ 1000 | money_without_currency }} {# 10.00 #}
|
||||
{{ 1000 | money_without_trailing_zeros }} {# $10 #}
|
||||
```
|
||||
|
||||
**String manipulation:**
|
||||
```liquid
|
||||
{{ "hello" | upcase }} {# HELLO #}
|
||||
{{ "hello" | capitalize }} {# Hello #}
|
||||
{{ "hello world" | truncate: 8 }} {# hello... #}
|
||||
{{ "a,b,c" | split: "," }} {# ["a","b","c"] #}
|
||||
{{ text | strip_html }} {# Remove HTML tags #}
|
||||
```
|
||||
|
||||
**Array/collection:**
|
||||
```liquid
|
||||
{{ array | first }} {# First element #}
|
||||
{{ array | last }} {# Last element #}
|
||||
{{ array | size }} {# Count #}
|
||||
{{ products | map: "title" }} {# Extract property #}
|
||||
{{ products | where: "vendor", "Nike" }} {# Filter #}
|
||||
{{ products | sort: "price" }} {# Sort #}
|
||||
{{ array | join: ", " }} {# Join with separator #}
|
||||
```
|
||||
|
||||
**Date formatting:**
|
||||
```liquid
|
||||
{{ order.created_at | date: '%B %d, %Y' }} {# November 10, 2025 #}
|
||||
{{ order.created_at | date: '%m/%d/%Y' }} {# 11/10/2025 #}
|
||||
{{ order.created_at | date: '%H:%M %p' }} {# 12:39 PM #}
|
||||
```
|
||||
|
||||
**Image handling:**
|
||||
```liquid
|
||||
{{ product.image | img_url: '500x500' }} {# Resize image #}
|
||||
{{ product.image | img_url: 'medium' }} {# Named size #}
|
||||
{{ 'logo.png' | asset_url }} {# Theme asset CDN #}
|
||||
```
|
||||
|
||||
**Math operations:**
|
||||
```liquid
|
||||
{{ 5 | plus: 3 }} {# 8 #}
|
||||
{{ 5 | minus: 3 }} {# 2 #}
|
||||
{{ 5 | times: 3 }} {# 15 #}
|
||||
{{ 10 | divided_by: 2 }} {# 5 #}
|
||||
{{ 1.567 | round: 2 }} {# 1.57 #}
|
||||
```
|
||||
|
||||
**Chaining filters:**
|
||||
```liquid
|
||||
{{ collection.products | where: "available" | map: "title" | sort | first }}
|
||||
```
|
||||
|
||||
### 5. Key Shopify Objects
|
||||
|
||||
**Product object:**
|
||||
```liquid
|
||||
{{ product.title }}
|
||||
{{ product.price | money }}
|
||||
{{ product.available }} {# Boolean #}
|
||||
{{ product.vendor }}
|
||||
{{ product.type }}
|
||||
{{ product.images }} {# Array #}
|
||||
{{ product.variants }} {# Array #}
|
||||
{{ product.selected_variant }}
|
||||
{{ product.metafields.custom.field }}
|
||||
```
|
||||
|
||||
**Collection object:**
|
||||
```liquid
|
||||
{{ collection.title }}
|
||||
{{ collection.products }} {# Array #}
|
||||
{{ collection.products_count }}
|
||||
{{ collection.all_tags }}
|
||||
{{ collection.sort_by }}
|
||||
{{ collection.filters }}
|
||||
```
|
||||
|
||||
**Cart object (global):**
|
||||
```liquid
|
||||
{{ cart.item_count }}
|
||||
{{ cart.total_price | money }}
|
||||
{{ cart.items }} {# Array of line items #}
|
||||
{{ cart.empty? }} {# Boolean #}
|
||||
```
|
||||
|
||||
**Customer object:**
|
||||
```liquid
|
||||
{{ customer.name }}
|
||||
{{ customer.email }}
|
||||
{{ customer.orders_count }}
|
||||
{{ customer.total_spent | money }}
|
||||
{{ customer.default_address }}
|
||||
```
|
||||
|
||||
**Global objects:**
|
||||
```liquid
|
||||
{{ shop.name }}
|
||||
{{ shop.currency }}
|
||||
{{ shop.url }}
|
||||
{{ request.path }}
|
||||
{{ request.page_type }} {# "product", "collection", etc. #}
|
||||
{{ settings.color_primary }} {# Theme settings #}
|
||||
```
|
||||
|
||||
### 6. Template Inclusion
|
||||
|
||||
**render (isolated scope - PREFERRED):**
|
||||
```liquid
|
||||
{% render 'product-card', product: product, show_price: true %}
|
||||
|
||||
{# Render for each item #}
|
||||
{% render 'product-card' for collection.products as item %}
|
||||
```
|
||||
|
||||
**include (shared scope - LEGACY):**
|
||||
```liquid
|
||||
{% include 'product-details' %}
|
||||
```
|
||||
|
||||
**section (dynamic sections):**
|
||||
```liquid
|
||||
{% section 'featured-product' %}
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Product availability check
|
||||
```liquid
|
||||
{% if product.available %}
|
||||
<button type="submit">Add to Cart</button>
|
||||
{% elsif product.selected_variant.incoming %}
|
||||
<p>Coming {{ product.selected_variant.incoming_date | date: '%B %d' }}</p>
|
||||
{% else %}
|
||||
<p class="sold-out">Sold Out</p>
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
### Price display with sale
|
||||
```liquid
|
||||
{% if product.compare_at_price > product.price %}
|
||||
<span class="sale-price">{{ product.price | money }}</span>
|
||||
<span class="original-price">{{ product.compare_at_price | money }}</span>
|
||||
<span class="savings">Save {{ product.compare_at_price | minus: product.price | money }}</span>
|
||||
{% else %}
|
||||
<span class="price">{{ product.price | money }}</span>
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
### Loop through variants
|
||||
```liquid
|
||||
{% for variant in product.variants %}
|
||||
<option
|
||||
value="{{ variant.id }}"
|
||||
{% unless variant.available %}disabled{% endunless %}
|
||||
>
|
||||
{{ variant.title }} - {{ variant.price | money }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
### Check collection tags
|
||||
```liquid
|
||||
{% if collection.all_tags contains 'sale' %}
|
||||
<div class="sale-banner">Sale items available!</div>
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use whitespace control** (`{%-` and `-%}`) to keep HTML clean
|
||||
2. **Prefer `render` over `include`** for better performance and isolation
|
||||
3. **Cache expensive operations** by assigning to variables
|
||||
4. **Use descriptive variable names** for clarity
|
||||
5. **Leverage filters** instead of complex logic when possible
|
||||
6. **Check for existence** before accessing nested properties
|
||||
7. **Use `default` filter** for fallback values: `{{ product.metafield | default: "N/A" }}`
|
||||
|
||||
## Detailed References
|
||||
|
||||
For comprehensive documentation:
|
||||
|
||||
- **[references/syntax.md](references/syntax.md)** - Complete syntax reference with all tags
|
||||
- **[references/filters.md](references/filters.md)** - All 60+ filters with examples
|
||||
- **[references/objects.md](references/objects.md)** - Complete object property reference
|
||||
|
||||
## Integration with Other Skills
|
||||
|
||||
- **shopify-theme-dev** - Use when working with theme file structure and sections
|
||||
- **shopify-api** - Use when fetching data via Ajax or GraphQL to display in Liquid
|
||||
- **shopify-debugging** - Use when troubleshooting Liquid rendering issues
|
||||
- **shopify-performance** - Use when optimizing Liquid template performance
|
||||
|
||||
## Quick Syntax Reference
|
||||
|
||||
```liquid
|
||||
{# Output #}
|
||||
{{ variable }}
|
||||
{{ product.title | upcase }}
|
||||
|
||||
{# Conditionals #}
|
||||
{% if condition %}...{% elsif %}...{% else %}...{% endif %}
|
||||
{% unless condition %}...{% endunless %}
|
||||
{% case variable %}{% when value %}...{% endcase %}
|
||||
|
||||
{# Loops #}
|
||||
{% for item in array %}...{% endfor %}
|
||||
{% for item in array limit: 5 offset: 10 %}...{% endfor %}
|
||||
{% break %} / {% continue %}
|
||||
|
||||
{# Variables #}
|
||||
{% assign var = value %}
|
||||
{% capture var %}content{% endcapture %}
|
||||
|
||||
{# Inclusion #}
|
||||
{% render 'snippet', param: value %}
|
||||
{% section 'section-name' %}
|
||||
|
||||
{# Comments #}
|
||||
{% comment %}...{% endcomment %}
|
||||
{# Single line #}
|
||||
```
|
||||
873
skills/shopify-liquid/references/filters.md
Normal file
873
skills/shopify-liquid/references/filters.md
Normal file
@@ -0,0 +1,873 @@
|
||||
# Liquid Filters - Complete Reference
|
||||
|
||||
Filters modify output using pipe syntax: `{{ value | filter: parameter }}`
|
||||
|
||||
## String Filters
|
||||
|
||||
### upcase
|
||||
|
||||
Convert to uppercase:
|
||||
|
||||
```liquid
|
||||
{{ "hello world" | upcase }}
|
||||
{# Output: HELLO WORLD #}
|
||||
```
|
||||
|
||||
### downcase
|
||||
|
||||
Convert to lowercase:
|
||||
|
||||
```liquid
|
||||
{{ "HELLO WORLD" | downcase }}
|
||||
{# Output: hello world #}
|
||||
```
|
||||
|
||||
### capitalize
|
||||
|
||||
Capitalize first letter only:
|
||||
|
||||
```liquid
|
||||
{{ "hello world" | capitalize }}
|
||||
{# Output: Hello world #}
|
||||
```
|
||||
|
||||
### reverse
|
||||
|
||||
Reverse string or array:
|
||||
|
||||
```liquid
|
||||
{{ "hello" | reverse }}
|
||||
{# Output: olleh #}
|
||||
|
||||
{{ array | reverse }}
|
||||
{# Reverses array order #}
|
||||
```
|
||||
|
||||
### size
|
||||
|
||||
Get character count or array length:
|
||||
|
||||
```liquid
|
||||
{{ "hello" | size }}
|
||||
{# Output: 5 #}
|
||||
|
||||
{{ collection.products | size }}
|
||||
{# Output: number of products #}
|
||||
```
|
||||
|
||||
### remove
|
||||
|
||||
Remove all occurrences of substring:
|
||||
|
||||
```liquid
|
||||
{{ "hello world world" | remove: "world" }}
|
||||
{# Output: hello #}
|
||||
```
|
||||
|
||||
### remove_first
|
||||
|
||||
Remove first occurrence only:
|
||||
|
||||
```liquid
|
||||
{{ "hello world world" | remove_first: "world" }}
|
||||
{# Output: hello world #}
|
||||
```
|
||||
|
||||
### replace
|
||||
|
||||
Replace all occurrences:
|
||||
|
||||
```liquid
|
||||
{{ "hello" | replace: "l", "L" }}
|
||||
{# Output: heLLo #}
|
||||
```
|
||||
|
||||
### replace_first
|
||||
|
||||
Replace first occurrence only:
|
||||
|
||||
```liquid
|
||||
{{ "hello" | replace_first: "l", "L" }}
|
||||
{# Output: heLlo #}
|
||||
```
|
||||
|
||||
### split
|
||||
|
||||
Split string into array:
|
||||
|
||||
```liquid
|
||||
{{ "a,b,c,d" | split: "," }}
|
||||
{# Output: ["a", "b", "c", "d"] #}
|
||||
|
||||
{% assign tags = "sale,new,featured" | split: "," %}
|
||||
{% for tag in tags %}
|
||||
{{ tag }}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
### strip
|
||||
|
||||
Remove leading and trailing whitespace:
|
||||
|
||||
```liquid
|
||||
{{ " hello " | strip }}
|
||||
{# Output: hello #}
|
||||
```
|
||||
|
||||
### lstrip
|
||||
|
||||
Remove leading whitespace only:
|
||||
|
||||
```liquid
|
||||
{{ " hello " | lstrip }}
|
||||
{# Output: hello #}
|
||||
```
|
||||
|
||||
### rstrip
|
||||
|
||||
Remove trailing whitespace only:
|
||||
|
||||
```liquid
|
||||
{{ " hello " | rstrip }}
|
||||
{# Output: hello #}
|
||||
```
|
||||
|
||||
### truncate
|
||||
|
||||
Limit string length with ellipsis:
|
||||
|
||||
```liquid
|
||||
{{ "hello world" | truncate: 8 }}
|
||||
{# Output: hello... #}
|
||||
|
||||
{{ "hello world" | truncate: 10, "!" }}
|
||||
{# Output: hello worl! #}
|
||||
|
||||
{{ "hello world" | truncate: 50 }}
|
||||
{# Output: hello world (no truncation if shorter) #}
|
||||
```
|
||||
|
||||
### truncatewords
|
||||
|
||||
Limit by word count:
|
||||
|
||||
```liquid
|
||||
{{ "hello world testing" | truncatewords: 2 }}
|
||||
{# Output: hello world... #}
|
||||
|
||||
{{ "hello world testing" | truncatewords: 2, "--" }}
|
||||
{# Output: hello world-- #}
|
||||
```
|
||||
|
||||
### append
|
||||
|
||||
Add string to end:
|
||||
|
||||
```liquid
|
||||
{{ "hello" | append: " world" }}
|
||||
{# Output: hello world #}
|
||||
|
||||
{% assign file_name = "image" | append: ".jpg" %}
|
||||
{# file_name: image.jpg #}
|
||||
```
|
||||
|
||||
### prepend
|
||||
|
||||
Add string to beginning:
|
||||
|
||||
```liquid
|
||||
{{ "world" | prepend: "hello " }}
|
||||
{# Output: hello world #}
|
||||
```
|
||||
|
||||
### newline_to_br
|
||||
|
||||
Convert newlines to `<br>` tags:
|
||||
|
||||
```liquid
|
||||
{{ product.description | newline_to_br }}
|
||||
{# Converts \n to <br> #}
|
||||
```
|
||||
|
||||
### strip_html
|
||||
|
||||
Remove all HTML tags:
|
||||
|
||||
```liquid
|
||||
{{ "<p>Hello <strong>world</strong></p>" | strip_html }}
|
||||
{# Output: Hello world #}
|
||||
```
|
||||
|
||||
### escape
|
||||
|
||||
Escape HTML special characters:
|
||||
|
||||
```liquid
|
||||
{{ "<div>Test</div>" | escape }}
|
||||
{# Output: <div>Test</div> #}
|
||||
```
|
||||
|
||||
### escape_once
|
||||
|
||||
Escape HTML but don't double-escape:
|
||||
|
||||
```liquid
|
||||
{{ "<div>" | escape_once }}
|
||||
{# Output: <div> (not double-escaped) #}
|
||||
```
|
||||
|
||||
### url_encode
|
||||
|
||||
URL-encode string:
|
||||
|
||||
```liquid
|
||||
{{ "hello world" | url_encode }}
|
||||
{# Output: hello+world #}
|
||||
|
||||
{{ "foo@bar.com" | url_encode }}
|
||||
{# Output: foo%40bar.com #}
|
||||
```
|
||||
|
||||
### url_decode
|
||||
|
||||
Decode URL-encoded string:
|
||||
|
||||
```liquid
|
||||
{{ "hello+world" | url_decode }}
|
||||
{# Output: hello world #}
|
||||
```
|
||||
|
||||
### base64_encode
|
||||
|
||||
Encode to base64:
|
||||
|
||||
```liquid
|
||||
{{ "hello" | base64_encode }}
|
||||
{# Output: aGVsbG8= #}
|
||||
```
|
||||
|
||||
### base64_decode
|
||||
|
||||
Decode from base64:
|
||||
|
||||
```liquid
|
||||
{{ "aGVsbG8=" | base64_decode }}
|
||||
{# Output: hello #}
|
||||
```
|
||||
|
||||
### slice
|
||||
|
||||
Extract substring or array slice:
|
||||
|
||||
```liquid
|
||||
{{ "hello" | slice: 0, 3 }}
|
||||
{# Output: hel #}
|
||||
|
||||
{{ "hello" | slice: -3, 3 }}
|
||||
{# Output: llo #}
|
||||
```
|
||||
|
||||
## Numeric Filters
|
||||
|
||||
### abs
|
||||
|
||||
Absolute value:
|
||||
|
||||
```liquid
|
||||
{{ -5 | abs }}
|
||||
{# Output: 5 #}
|
||||
|
||||
{{ 5 | abs }}
|
||||
{# Output: 5 #}
|
||||
```
|
||||
|
||||
### ceil
|
||||
|
||||
Round up to nearest integer:
|
||||
|
||||
```liquid
|
||||
{{ 1.2 | ceil }}
|
||||
{# Output: 2 #}
|
||||
|
||||
{{ 1.9 | ceil }}
|
||||
{# Output: 2 #}
|
||||
```
|
||||
|
||||
### floor
|
||||
|
||||
Round down to nearest integer:
|
||||
|
||||
```liquid
|
||||
{{ 1.9 | floor }}
|
||||
{# Output: 1 #}
|
||||
|
||||
{{ 1.1 | floor }}
|
||||
{# Output: 1 #}
|
||||
```
|
||||
|
||||
### round
|
||||
|
||||
Round to specified decimal places:
|
||||
|
||||
```liquid
|
||||
{{ 1.5 | round }}
|
||||
{# Output: 2 #}
|
||||
|
||||
{{ 1.567 | round: 2 }}
|
||||
{# Output: 1.57 #}
|
||||
|
||||
{{ 1.234 | round: 1 }}
|
||||
{# Output: 1.2 #}
|
||||
```
|
||||
|
||||
### plus
|
||||
|
||||
Addition:
|
||||
|
||||
```liquid
|
||||
{{ 5 | plus: 3 }}
|
||||
{# Output: 8 #}
|
||||
|
||||
{{ product.price | plus: 1000 }}
|
||||
{# Add $10.00 (prices in cents) #}
|
||||
```
|
||||
|
||||
### minus
|
||||
|
||||
Subtraction:
|
||||
|
||||
```liquid
|
||||
{{ 5 | minus: 3 }}
|
||||
{# Output: 2 #}
|
||||
```
|
||||
|
||||
### times
|
||||
|
||||
Multiplication:
|
||||
|
||||
```liquid
|
||||
{{ 5 | times: 3 }}
|
||||
{# Output: 15 #}
|
||||
|
||||
{{ product.price | times: 0.8 }}
|
||||
{# 20% discount #}
|
||||
```
|
||||
|
||||
### divided_by
|
||||
|
||||
Integer division:
|
||||
|
||||
```liquid
|
||||
{{ 10 | divided_by: 2 }}
|
||||
{# Output: 5 #}
|
||||
|
||||
{{ 10 | divided_by: 3 }}
|
||||
{# Output: 3 (integer division) #}
|
||||
|
||||
{{ 10.0 | divided_by: 3 }}
|
||||
{# Output: 3.33... (float division) #}
|
||||
```
|
||||
|
||||
### modulo
|
||||
|
||||
Get remainder:
|
||||
|
||||
```liquid
|
||||
{{ 10 | modulo: 3 }}
|
||||
{# Output: 1 #}
|
||||
|
||||
{# Check if even #}
|
||||
{% if forloop.index | modulo: 2 == 0 %}
|
||||
Even row
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
### at_least
|
||||
|
||||
Ensure minimum value:
|
||||
|
||||
```liquid
|
||||
{{ 1 | at_least: 5 }}
|
||||
{# Output: 5 #}
|
||||
|
||||
{{ 10 | at_least: 5 }}
|
||||
{# Output: 10 #}
|
||||
```
|
||||
|
||||
### at_most
|
||||
|
||||
Ensure maximum value:
|
||||
|
||||
```liquid
|
||||
{{ 100 | at_most: 50 }}
|
||||
{# Output: 50 #}
|
||||
|
||||
{{ 10 | at_most: 50 }}
|
||||
{# Output: 10 #}
|
||||
```
|
||||
|
||||
## Array/Collection Filters
|
||||
|
||||
### first
|
||||
|
||||
Get first element:
|
||||
|
||||
```liquid
|
||||
{{ collection.products | first }}
|
||||
{# Returns first product #}
|
||||
|
||||
{{ "a,b,c" | split: "," | first }}
|
||||
{# Output: a #}
|
||||
```
|
||||
|
||||
### last
|
||||
|
||||
Get last element:
|
||||
|
||||
```liquid
|
||||
{{ collection.products | last }}
|
||||
{# Returns last product #}
|
||||
```
|
||||
|
||||
### join
|
||||
|
||||
Join array with separator:
|
||||
|
||||
```liquid
|
||||
{{ product.tags | join: ", " }}
|
||||
{# Output: sale, new, featured #}
|
||||
```
|
||||
|
||||
### map
|
||||
|
||||
Extract property from each object:
|
||||
|
||||
```liquid
|
||||
{{ collection.products | map: "title" }}
|
||||
{# Returns array of product titles #}
|
||||
|
||||
{{ collection.products | map: "title" | join: ", " }}
|
||||
{# Output: Product 1, Product 2, Product 3 #}
|
||||
```
|
||||
|
||||
### sort
|
||||
|
||||
Sort array by property:
|
||||
|
||||
```liquid
|
||||
{{ collection.products | sort: "price" }}
|
||||
{# Sort by price ascending #}
|
||||
|
||||
{{ collection.products | sort: "title" }}
|
||||
{# Sort alphabetically #}
|
||||
```
|
||||
|
||||
### sort_natural
|
||||
|
||||
Case-insensitive sort:
|
||||
|
||||
```liquid
|
||||
{{ collection.products | sort_natural: "title" }}
|
||||
{# Sorts: Apple, banana, Cherry (natural order) #}
|
||||
```
|
||||
|
||||
### where
|
||||
|
||||
Filter array by property value:
|
||||
|
||||
```liquid
|
||||
{{ collection.products | where: "vendor", "Nike" }}
|
||||
{# Only Nike products #}
|
||||
|
||||
{{ collection.products | where: "available", true }}
|
||||
{# Only available products #}
|
||||
|
||||
{{ collection.products | where: "type", "shoes" | map: "title" }}
|
||||
{# Combine with map #}
|
||||
```
|
||||
|
||||
### uniq
|
||||
|
||||
Remove duplicates:
|
||||
|
||||
```liquid
|
||||
{{ collection.all_vendors | uniq }}
|
||||
{# Unique vendor names #}
|
||||
```
|
||||
|
||||
### limit
|
||||
|
||||
Limit array to N items:
|
||||
|
||||
```liquid
|
||||
{{ collection.products | limit: 5 }}
|
||||
{# First 5 products #}
|
||||
```
|
||||
|
||||
### offset
|
||||
|
||||
Skip first N items:
|
||||
|
||||
```liquid
|
||||
{{ collection.products | offset: 10 }}
|
||||
{# Products from 11th onward #}
|
||||
```
|
||||
|
||||
### concat
|
||||
|
||||
Merge two arrays:
|
||||
|
||||
```liquid
|
||||
{% assign array1 = "a,b,c" | split: "," %}
|
||||
{% assign array2 = "d,e,f" | split: "," %}
|
||||
{{ array1 | concat: array2 | join: ", " }}
|
||||
{# Output: a, b, c, d, e, f #}
|
||||
```
|
||||
|
||||
### compact
|
||||
|
||||
Remove nil values from array:
|
||||
|
||||
```liquid
|
||||
{{ array | compact }}
|
||||
{# Removes nil/null elements #}
|
||||
```
|
||||
|
||||
## Shopify-Specific Filters
|
||||
|
||||
### money
|
||||
|
||||
Format as currency with symbol:
|
||||
|
||||
```liquid
|
||||
{{ 1000 | money }}
|
||||
{# Output: $10.00 #}
|
||||
|
||||
{{ 1599 | money }}
|
||||
{# Output: $15.99 #}
|
||||
```
|
||||
|
||||
### money_without_currency
|
||||
|
||||
Format without currency symbol:
|
||||
|
||||
```liquid
|
||||
{{ 1000 | money_without_currency }}
|
||||
{# Output: 10.00 #}
|
||||
```
|
||||
|
||||
### money_without_trailing_zeros
|
||||
|
||||
Remove unnecessary decimals:
|
||||
|
||||
```liquid
|
||||
{{ 1000 | money_without_trailing_zeros }}
|
||||
{# Output: $10 #}
|
||||
|
||||
{{ 1050 | money_without_trailing_zeros }}
|
||||
{# Output: $10.50 #}
|
||||
```
|
||||
|
||||
### weight_with_unit
|
||||
|
||||
Add weight unit:
|
||||
|
||||
```liquid
|
||||
{{ 500 | weight_with_unit }}
|
||||
{# Output: 500 g #}
|
||||
|
||||
{{ product.variants.first.weight | weight_with_unit }}
|
||||
```
|
||||
|
||||
### asset_url
|
||||
|
||||
Get theme asset CDN URL:
|
||||
|
||||
```liquid
|
||||
{{ 'logo.png' | asset_url }}
|
||||
{# Output: //cdn.shopify.com/s/files/1/0000/0000/t/1/assets/logo.png #}
|
||||
```
|
||||
|
||||
### img_url
|
||||
|
||||
Generate image URL with size:
|
||||
|
||||
```liquid
|
||||
{{ product.featured_image | img_url: '500x500' }}
|
||||
{# Resize to 500x500 #}
|
||||
|
||||
{{ product.featured_image | img_url: 'large' }}
|
||||
{# Named size: pico, icon, thumb, small, compact, medium, large, grande, 1024x1024, 2048x2048 #}
|
||||
|
||||
{{ product.featured_image | img_url: '500x500', crop: 'center' }}
|
||||
{# With crop #}
|
||||
```
|
||||
|
||||
### link_to_type
|
||||
|
||||
Create link to product type collection:
|
||||
|
||||
```liquid
|
||||
{{ product.type | link_to_type }}
|
||||
{# Output: <a href="/collections/types?q=Shoes">Shoes</a> #}
|
||||
```
|
||||
|
||||
### link_to_vendor
|
||||
|
||||
Create link to vendor collection:
|
||||
|
||||
```liquid
|
||||
{{ product.vendor | link_to_vendor }}
|
||||
{# Output: <a href="/collections/vendors?q=Nike">Nike</a> #}
|
||||
```
|
||||
|
||||
### link_to_tag
|
||||
|
||||
Create link to tag filter:
|
||||
|
||||
```liquid
|
||||
{{ tag | link_to_tag: tag }}
|
||||
{# Output: <a href="/collections/all/sale">sale</a> #}
|
||||
```
|
||||
|
||||
### highlight
|
||||
|
||||
Highlight search terms:
|
||||
|
||||
```liquid
|
||||
{{ product.title | highlight: search.terms }}
|
||||
{# Wraps search terms in <strong class="highlight"> tags #}
|
||||
```
|
||||
|
||||
### highlight_active_tag
|
||||
|
||||
Highlight current tag:
|
||||
|
||||
```liquid
|
||||
{{ tag | highlight_active_tag: tag }}
|
||||
{# Wraps current tag in <span class="active"> #}
|
||||
```
|
||||
|
||||
### payment_type_img_url
|
||||
|
||||
Get payment icon URL:
|
||||
|
||||
```liquid
|
||||
{{ 'visa' | payment_type_img_url }}
|
||||
{# Returns Shopify-hosted Visa icon URL #}
|
||||
```
|
||||
|
||||
### placeholder_svg_tag
|
||||
|
||||
Generate placeholder SVG:
|
||||
|
||||
```liquid
|
||||
{{ 'product-1' | placeholder_svg_tag }}
|
||||
{# Generates placeholder product image SVG #}
|
||||
|
||||
{{ 'collection-1' | placeholder_svg_tag: 'custom-class' }}
|
||||
{# With custom CSS class #}
|
||||
```
|
||||
|
||||
### color_to_rgb
|
||||
|
||||
Convert hex to RGB:
|
||||
|
||||
```liquid
|
||||
{{ '#ff0000' | color_to_rgb }}
|
||||
{# Output: rgb(255, 0, 0) #}
|
||||
```
|
||||
|
||||
### color_to_hsl
|
||||
|
||||
Convert hex to HSL:
|
||||
|
||||
```liquid
|
||||
{{ '#ff0000' | color_to_hsl }}
|
||||
{# Output: hsl(0, 100%, 50%) #}
|
||||
```
|
||||
|
||||
### color_extract
|
||||
|
||||
Extract color component:
|
||||
|
||||
```liquid
|
||||
{{ '#ff0000' | color_extract: 'red' }}
|
||||
{# Output: 255 #}
|
||||
```
|
||||
|
||||
### color_brightness
|
||||
|
||||
Calculate brightness:
|
||||
|
||||
```liquid
|
||||
{{ '#ff0000' | color_brightness }}
|
||||
{# Output: brightness value 0-255 #}
|
||||
```
|
||||
|
||||
### color_modify
|
||||
|
||||
Modify color properties:
|
||||
|
||||
```liquid
|
||||
{{ '#ff0000' | color_modify: 'alpha', 0.5 }}
|
||||
{# Adjust alpha channel #}
|
||||
```
|
||||
|
||||
## Date Filters
|
||||
|
||||
### date
|
||||
|
||||
Format date using strftime:
|
||||
|
||||
```liquid
|
||||
{{ order.created_at | date: '%B %d, %Y' }}
|
||||
{# Output: November 10, 2025 #}
|
||||
|
||||
{{ order.created_at | date: '%m/%d/%Y' }}
|
||||
{# Output: 11/10/2025 #}
|
||||
|
||||
{{ order.created_at | date: '%Y-%m-%d %H:%M:%S' }}
|
||||
{# Output: 2025-11-10 14:30:00 #}
|
||||
```
|
||||
|
||||
**Common format codes:**
|
||||
|
||||
- `%Y` - 4-digit year (2025)
|
||||
- `%y` - 2-digit year (25)
|
||||
- `%m` - Month number (11)
|
||||
- `%B` - Full month (November)
|
||||
- `%b` - Short month (Nov)
|
||||
- `%d` - Day of month (10)
|
||||
- `%e` - Day without leading zero (10)
|
||||
- `%A` - Full weekday (Monday)
|
||||
- `%a` - Short weekday (Mon)
|
||||
- `%H` - Hour 24-hour (14)
|
||||
- `%I` - Hour 12-hour (02)
|
||||
- `%M` - Minutes (30)
|
||||
- `%S` - Seconds (45)
|
||||
- `%p` - AM/PM
|
||||
- `%z` - Timezone offset (+0000)
|
||||
|
||||
**Examples:**
|
||||
|
||||
```liquid
|
||||
{{ "now" | date: "%Y-%m-%d" }}
|
||||
{# Current date: 2025-11-10 #}
|
||||
|
||||
{{ article.published_at | date: "%B %d, %Y at %I:%M %p" }}
|
||||
{# November 10, 2025 at 02:30 PM #}
|
||||
```
|
||||
|
||||
## URL Filters
|
||||
|
||||
### url_for_type
|
||||
|
||||
Get collection URL for product type:
|
||||
|
||||
```liquid
|
||||
{{ product.type | url_for_type }}
|
||||
{# Output: /collections/types?q=Shoes #}
|
||||
```
|
||||
|
||||
### url_for_vendor
|
||||
|
||||
Get collection URL for vendor:
|
||||
|
||||
```liquid
|
||||
{{ product.vendor | url_for_vendor }}
|
||||
{# Output: /collections/vendors?q=Nike #}
|
||||
```
|
||||
|
||||
### within
|
||||
|
||||
Scope URL within collection:
|
||||
|
||||
```liquid
|
||||
{{ product.url | within: collection }}
|
||||
{# Output: /collections/sale/products/product-handle #}
|
||||
```
|
||||
|
||||
### default_pagination
|
||||
|
||||
Generate pagination HTML:
|
||||
|
||||
```liquid
|
||||
{{ paginate | default_pagination }}
|
||||
{# Outputs complete pagination HTML #}
|
||||
```
|
||||
|
||||
## Utility Filters
|
||||
|
||||
### default
|
||||
|
||||
Provide fallback value:
|
||||
|
||||
```liquid
|
||||
{{ product.metafield | default: "N/A" }}
|
||||
{# If metafield is nil, outputs "N/A" #}
|
||||
|
||||
{{ variant.title | default: "Default" }}
|
||||
```
|
||||
|
||||
### json
|
||||
|
||||
Convert to JSON:
|
||||
|
||||
```liquid
|
||||
{{ product | json }}
|
||||
{# Outputs product object as JSON string #}
|
||||
|
||||
<script>
|
||||
var productData = {{ product | json }};
|
||||
</script>
|
||||
```
|
||||
|
||||
## Filter Chaining
|
||||
|
||||
Filters execute left-to-right and can be chained:
|
||||
|
||||
```liquid
|
||||
{{ "hello world" | upcase | replace: "WORLD", "SHOPIFY" }}
|
||||
{# Output: HELLO SHOPIFY #}
|
||||
|
||||
{{ collection.products | where: "available" | map: "title" | sort | join: ", " }}
|
||||
{# Filter → extract → sort → join #}
|
||||
|
||||
{{ product.price | times: 0.8 | round: 2 | money }}
|
||||
{# Calculate 20% discount, round, format as money #}
|
||||
|
||||
{{ product.description | strip_html | truncatewords: 50 | escape }}
|
||||
{# Strip HTML → truncate → escape for safety #}
|
||||
```
|
||||
|
||||
## Performance Tips
|
||||
|
||||
1. **Cache filtered results** if used multiple times:
|
||||
|
||||
```liquid
|
||||
{# ❌ Inefficient: #}
|
||||
{% for i in (1..10) %}
|
||||
{{ collection.products | where: "available" | size }}
|
||||
{% endfor %}
|
||||
|
||||
{# ✅ Efficient: #}
|
||||
{% assign available_products = collection.products | where: "available" %}
|
||||
{% for i in (1..10) %}
|
||||
{{ available_products.size }}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
2. **Use `limit` and `offset` filters** instead of manual iteration control
|
||||
|
||||
3. **Combine filters intelligently** to reduce operations:
|
||||
|
||||
```liquid
|
||||
{# ❌ Less efficient: #}
|
||||
{% assign titles = collection.products | map: "title" %}
|
||||
{% assign sorted = titles | sort %}
|
||||
{% assign limited = sorted | limit: 5 %}
|
||||
|
||||
{# ✅ More efficient: #}
|
||||
{% assign limited_titles = collection.products | map: "title" | sort | limit: 5 %}
|
||||
```
|
||||
695
skills/shopify-liquid/references/objects.md
Normal file
695
skills/shopify-liquid/references/objects.md
Normal file
@@ -0,0 +1,695 @@
|
||||
# Liquid Objects - Complete Reference
|
||||
|
||||
## Global Objects (Available Everywhere)
|
||||
|
||||
### shop
|
||||
|
||||
Store-level information:
|
||||
|
||||
```liquid
|
||||
{{ shop.name }} {# Store name #}
|
||||
{{ shop.url }} {# Store URL (https://...) #}
|
||||
{{ shop.description }} {# Store tagline/description #}
|
||||
{{ shop.currency }} {# ISO currency code: USD, GBP, EUR #}
|
||||
{{ shop.money_format }} {# Money format string: ${{amount}} #}
|
||||
{{ shop.permanent_domain }} {# Domain: store.myshopify.com #}
|
||||
{{ shop.domain }} {# Primary domain #}
|
||||
{{ shop.email }} {# Support email #}
|
||||
{{ shop.phone }} {# Support phone #}
|
||||
{{ shop.address }} {# Store address object #}
|
||||
{{ shop.address.city }}
|
||||
{{ shop.address.province }}
|
||||
{{ shop.address.country }}
|
||||
{{ shop.address.zip }}
|
||||
{{ shop.enabled_payment_types }} {# Array of enabled payment methods #}
|
||||
{{ shop.checkout.privacy_policy_url }}
|
||||
{{ shop.checkout.terms_of_service_url }}
|
||||
{{ shop.checkout.refund_policy_url }}
|
||||
```
|
||||
|
||||
### request
|
||||
|
||||
Request context and routing:
|
||||
|
||||
```liquid
|
||||
{{ request.path }} {# Current URL path: /products/handle #}
|
||||
{{ request.host }} {# Current domain #}
|
||||
{{ request.origin }} {# Protocol + host #}
|
||||
{{ request.page_type }} {# "product", "collection", "index", etc. #}
|
||||
{{ request.locale.iso_code }} {# Language: "en", "fr", "es" #}
|
||||
{{ request.locale.root_url }} {# Root URL for locale #}
|
||||
{{ request.design_mode }} {# Boolean: theme editor active #}
|
||||
{{ request.visual_preview_mode }} {# Boolean: theme preview active #}
|
||||
|
||||
{# Query parameters #}
|
||||
{{ request.query_string }} {# Full query string #}
|
||||
|
||||
{# Build canonical URL #}
|
||||
{{ request.canonical_url }} {# Full canonical URL #}
|
||||
{{ request.path_with_query }} {# Path + query string #}
|
||||
```
|
||||
|
||||
### settings
|
||||
|
||||
Theme settings (from settings_schema.json):
|
||||
|
||||
```liquid
|
||||
{# Colors #}
|
||||
{{ settings.color_primary }}
|
||||
{{ settings.color_secondary }}
|
||||
{{ settings.color_body_bg }}
|
||||
|
||||
{# Typography #}
|
||||
{{ settings.type_header_font }}
|
||||
{{ settings.type_body_font }}
|
||||
|
||||
{# Layout #}
|
||||
{{ settings.layout_container_width }}
|
||||
{{ settings.layout_sidebar_enabled }}
|
||||
|
||||
{# Media #}
|
||||
{{ settings.logo }} {# Image object #}
|
||||
{{ settings.logo.src }}
|
||||
{{ settings.logo.width }}
|
||||
{{ settings.logo.height }}
|
||||
{{ settings.logo.alt }}
|
||||
|
||||
{# Text content #}
|
||||
{{ settings.announcement_text }}
|
||||
{{ settings.footer_text }}
|
||||
|
||||
{# Boolean settings #}
|
||||
{% if settings.show_breadcrumbs %}
|
||||
{# Render breadcrumbs #}
|
||||
{% endif %}
|
||||
|
||||
{# URL settings #}
|
||||
{{ settings.social_twitter_link }}
|
||||
{{ settings.social_facebook_link }}
|
||||
```
|
||||
|
||||
### routes
|
||||
|
||||
URL routes to standard pages:
|
||||
|
||||
```liquid
|
||||
{{ routes.root_url }} {# / #}
|
||||
{{ routes.account_url }} {# /account #}
|
||||
{{ routes.account_login_url }} {# /account/login #}
|
||||
{{ routes.account_logout_url }} {# /account/logout #}
|
||||
{{ routes.account_register_url }} {# /account/register #}
|
||||
{{ routes.account_addresses_url }} {# /account/addresses #}
|
||||
{{ routes.collections_url }} {# /collections #}
|
||||
{{ routes.all_products_collection_url }} {# /collections/all #}
|
||||
{{ routes.search_url }} {# /search #}
|
||||
{{ routes.cart_url }} {# /cart #}
|
||||
{{ routes.cart_add_url }} {# /cart/add #}
|
||||
{{ routes.cart_change_url }} {# /cart/change #}
|
||||
{{ routes.cart_clear_url }} {# /cart/clear #}
|
||||
{{ routes.cart_update_url }} {# /cart/update #}
|
||||
```
|
||||
|
||||
### section
|
||||
|
||||
Current section context (within sections):
|
||||
|
||||
```liquid
|
||||
{{ section.id }} {# Unique ID: "section-1234567890" #}
|
||||
{{ section.settings.title }} {# Section setting #}
|
||||
{{ section.settings.background_color }}
|
||||
{{ section.index }} {# Position on page #}
|
||||
{{ section.location }} {# Where section appears #}
|
||||
|
||||
{# Blocks #}
|
||||
{{ section.blocks }} {# Array of blocks #}
|
||||
{{ section.blocks.size }} {# Number of blocks #}
|
||||
|
||||
{% for block in section.blocks %}
|
||||
{{ block.id }}
|
||||
{{ block.type }}
|
||||
{{ block.settings.text }}
|
||||
{{ block.shopify_attributes }} {# Required for theme editor #}
|
||||
{% endfor %}
|
||||
|
||||
{# Blocks by type #}
|
||||
{{ section.blocks_by_type }} {# Organized by type #}
|
||||
```
|
||||
|
||||
### block
|
||||
|
||||
Current block context (within section blocks):
|
||||
|
||||
```liquid
|
||||
{{ block.id }} {# Unique ID: "block-9876543210" #}
|
||||
{{ block.type }} {# Block type name #}
|
||||
{{ block.settings.text }} {# Block setting #}
|
||||
{{ block.shopify_attributes }} {# Required for theme editor #}
|
||||
|
||||
{# Example usage in section #}
|
||||
{% for block in section.blocks %}
|
||||
<div {{ block.shopify_attributes }}>
|
||||
{% case block.type %}
|
||||
{% when 'heading' %}
|
||||
<h2>{{ block.settings.title }}</h2>
|
||||
{% when 'text' %}
|
||||
<p>{{ block.settings.content }}</p>
|
||||
{% endcase %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
## Page Context Objects
|
||||
|
||||
### product
|
||||
|
||||
Product object (on product pages):
|
||||
|
||||
```liquid
|
||||
{# Core properties #}
|
||||
{{ product.id }} {# Numeric ID #}
|
||||
{{ product.title }} {# Product name #}
|
||||
{{ product.handle }} {# URL slug #}
|
||||
{{ product.description }} {# Full HTML description #}
|
||||
{{ product.vendor }} {# Brand/manufacturer #}
|
||||
{{ product.type }} {# Category #}
|
||||
{{ product.url }} {# Product URL #}
|
||||
{{ product.available }} {# Boolean: any variant in stock #}
|
||||
{{ product.published_at }} {# Publication timestamp #}
|
||||
{{ product.created_at }} {# Creation timestamp #}
|
||||
{{ product.updated_at }} {# Last modified timestamp #}
|
||||
|
||||
{# Pricing (in cents) #}
|
||||
{{ product.price }} {# Current variant price #}
|
||||
{{ product.price_min }} {# Cheapest variant #}
|
||||
{{ product.price_max }} {# Most expensive variant #}
|
||||
{{ product.price_varies }} {# Boolean: different prices #}
|
||||
{{ product.compare_at_price }} {# Original price for sales #}
|
||||
{{ product.compare_at_price_min }}
|
||||
{{ product.compare_at_price_max }}
|
||||
{{ product.compare_at_price_varies }}
|
||||
|
||||
{# Images #}
|
||||
{{ product.featured_image }} {# Primary image object #}
|
||||
{{ product.featured_image.src }}
|
||||
{{ product.featured_image.width }}
|
||||
{{ product.featured_image.height }}
|
||||
{{ product.featured_image.alt }}
|
||||
{{ product.featured_image | img_url: '500x500' }}
|
||||
|
||||
{{ product.images }} {# Array of all images #}
|
||||
{{ product.images.size }} {# Image count #}
|
||||
|
||||
{% for image in product.images %}
|
||||
<img src="{{ image | img_url: '300x300' }}" alt="{{ image.alt }}">
|
||||
{% endfor %}
|
||||
|
||||
{{ product.media }} {# Array of all media (images, videos, 3D) #}
|
||||
|
||||
{# Variants #}
|
||||
{{ product.variants }} {# Array of variants #}
|
||||
{{ product.variants.size }} {# Variant count #}
|
||||
{{ product.selected_variant }} {# Currently selected variant #}
|
||||
{{ product.selected_or_first_available_variant }}
|
||||
{{ product.first_available_variant }}
|
||||
{{ product.has_only_default_variant }} {# Boolean: single variant #}
|
||||
|
||||
{# Options #}
|
||||
{{ product.options }} {# Array: ["Size", "Color"] #}
|
||||
{{ product.options_with_values }} {# Array of option objects #}
|
||||
|
||||
{% for option in product.options_with_values %}
|
||||
<label>{{ option.name }}</label>
|
||||
<select>
|
||||
{% for value in option.values %}
|
||||
<option>{{ value }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% endfor %}
|
||||
|
||||
{# Collections #}
|
||||
{{ product.collections }} {# Array of collections #}
|
||||
{{ product.collections.size }}
|
||||
|
||||
{# Tags #}
|
||||
{{ product.tags }} {# Array of tags #}
|
||||
{{ product.tags | join: ", " }}
|
||||
|
||||
{# Custom data #}
|
||||
{{ product.metafields.namespace.key }}
|
||||
{{ product.metafields.custom.field_name }}
|
||||
|
||||
{# Template #}
|
||||
{{ product.template_suffix }} {# Template variant: "alternate" #}
|
||||
```
|
||||
|
||||
### variant
|
||||
|
||||
Variant object (product.variants, product.selected_variant):
|
||||
|
||||
```liquid
|
||||
{{ variant.id }} {# Variant ID #}
|
||||
{{ variant.product_id }} {# Parent product ID #}
|
||||
{{ variant.title }} {# "Red / Medium" #}
|
||||
{{ variant.price }} {# Price in cents #}
|
||||
{{ variant.compare_at_price }} {# Original price #}
|
||||
{{ variant.sku }} {# SKU code #}
|
||||
{{ variant.barcode }} {# Barcode #}
|
||||
{{ variant.weight }} {# Weight in grams #}
|
||||
{{ variant.weight_unit }} {# "kg", "lb", etc. #}
|
||||
{{ variant.weight_in_unit }} {# Weight in configured unit #}
|
||||
|
||||
{# Availability #}
|
||||
{{ variant.available }} {# Boolean: in stock #}
|
||||
{{ variant.inventory_quantity }} {# Current stock level #}
|
||||
{{ variant.inventory_policy }} {# "continue" or "deny" #}
|
||||
{{ variant.inventory_management }} {# "shopify" or null #}
|
||||
|
||||
{# Options #}
|
||||
{{ variant.option1 }} {# First option value: "Red" #}
|
||||
{{ variant.option2 }} {# Second option value: "Medium" #}
|
||||
{{ variant.option3 }} {# Third option value #}
|
||||
{{ variant.options }} {# Array: ["Red", "Medium"] #}
|
||||
|
||||
{# Image #}
|
||||
{{ variant.featured_image }} {# Variant-specific image #}
|
||||
{{ variant.image }} {# Same as featured_image #}
|
||||
|
||||
{# URL #}
|
||||
{{ variant.url }} {# Product URL with variant param #}
|
||||
|
||||
{# Metafields #}
|
||||
{{ variant.metafields.namespace.key }}
|
||||
```
|
||||
|
||||
### collection
|
||||
|
||||
Collection object (on collection pages):
|
||||
|
||||
```liquid
|
||||
{# Core properties #}
|
||||
{{ collection.id }} {# Numeric ID #}
|
||||
{{ collection.title }} {# Collection name #}
|
||||
{{ collection.handle }} {# URL slug #}
|
||||
{{ collection.description }} {# HTML description #}
|
||||
{{ collection.url }} {# Collection URL #}
|
||||
{{ collection.published_at }} {# Publication date #}
|
||||
|
||||
{# Image #}
|
||||
{{ collection.image }} {# Featured image object #}
|
||||
{{ collection.image.src }}
|
||||
{{ collection.image | img_url: '1024x1024' }}
|
||||
|
||||
{# Products #}
|
||||
{{ collection.products }} {# Array of products #}
|
||||
{{ collection.products_count }} {# Current page count #}
|
||||
{{ collection.all_products_count }}{# Total count #}
|
||||
|
||||
{# Filtering & sorting #}
|
||||
{{ collection.all_tags }} {# All tags (max 1000) #}
|
||||
{{ collection.all_types }} {# All product types #}
|
||||
{{ collection.all_vendors }} {# All vendors #}
|
||||
{{ collection.current_type }} {# Active type filter #}
|
||||
{{ collection.current_vendor }} {# Active vendor filter #}
|
||||
{{ collection.sort_by }} {# Current sort method #}
|
||||
{{ collection.default_sort_by }} {# Default sort #}
|
||||
{{ collection.sort_options }} {# Available sort methods #}
|
||||
|
||||
{# Filters (Storefront Filtering) #}
|
||||
{{ collection.filters }} {# Array of filter objects #}
|
||||
|
||||
{% for filter in collection.filters %}
|
||||
{{ filter.label }} {# Filter name #}
|
||||
{{ filter.type }} {# "list", "price_range" #}
|
||||
{{ filter.active_values }} {# Currently active #}
|
||||
{{ filter.values }} {# Available values #}
|
||||
{% endfor %}
|
||||
|
||||
{# Navigation (on product pages within collection) #}
|
||||
{{ collection.next_product }} {# Next product in collection #}
|
||||
{{ collection.previous_product }} {# Previous product #}
|
||||
|
||||
{# Metafields #}
|
||||
{{ collection.metafields.namespace.key }}
|
||||
|
||||
{# Template #}
|
||||
{{ collection.template_suffix }}
|
||||
```
|
||||
|
||||
### cart
|
||||
|
||||
Cart object (global - always available):
|
||||
|
||||
```liquid
|
||||
{# Cart state #}
|
||||
{{ cart.item_count }} {# Total line items #}
|
||||
{{ cart.total_price }} {# Total in cents #}
|
||||
{{ cart.total_weight }} {# Weight sum #}
|
||||
{{ cart.empty? }} {# Boolean: is cart empty #}
|
||||
|
||||
{# Items #}
|
||||
{{ cart.items }} {# Array of line items #}
|
||||
{{ cart.items.size }} {# Number of line items #}
|
||||
|
||||
{% for item in cart.items %}
|
||||
{{ item.product_id }}
|
||||
{{ item.variant_id }}
|
||||
{{ item.title }}
|
||||
{{ item.quantity }}
|
||||
{{ item.price }}
|
||||
{{ item.line_price }} {# price × quantity #}
|
||||
{{ item.image }}
|
||||
{% endfor %}
|
||||
|
||||
{# Notes and attributes #}
|
||||
{{ cart.note }} {# Customer note #}
|
||||
{{ cart.attributes }} {# Custom cart attributes #}
|
||||
|
||||
{# Access specific attribute #}
|
||||
{% if cart.attributes.gift_wrap %}
|
||||
Gift wrap requested
|
||||
{% endif %}
|
||||
|
||||
{# Discounts #}
|
||||
{{ cart.cart_level_discount_applications }}
|
||||
{{ cart.total_discount }} {# Total discount amount #}
|
||||
|
||||
{# Checkout #}
|
||||
{{ cart.requires_shipping }} {# Boolean #}
|
||||
```
|
||||
|
||||
### line_item
|
||||
|
||||
Line item object (cart.items):
|
||||
|
||||
```liquid
|
||||
{% for item in cart.items %}
|
||||
{{ item.id }} {# Line item ID #}
|
||||
{{ item.key }} {# Unique key #}
|
||||
{{ item.product_id }} {# Product ID #}
|
||||
{{ item.variant_id }} {# Variant ID #}
|
||||
|
||||
{# Product info #}
|
||||
{{ item.product }} {# Product object #}
|
||||
{{ item.variant }} {# Variant object #}
|
||||
{{ item.title }} {# Product title #}
|
||||
{{ item.product_title }} {# Same as title #}
|
||||
{{ item.variant_title }} {# Variant options #}
|
||||
|
||||
{# Pricing #}
|
||||
{{ item.quantity }} {# Quantity ordered #}
|
||||
{{ item.price }} {# Price per unit (cents) #}
|
||||
{{ item.line_price }} {# Total: price × quantity #}
|
||||
{{ item.original_price }} {# Before discounts #}
|
||||
{{ item.original_line_price }}
|
||||
{{ item.final_price }} {# After discounts #}
|
||||
{{ item.final_line_price }}
|
||||
|
||||
{# Images #}
|
||||
{{ item.image }} {# Line item image #}
|
||||
{{ item.featured_image.src }}
|
||||
|
||||
{# URL #}
|
||||
{{ item.url }} {# Link to product #}
|
||||
|
||||
{# SKU #}
|
||||
{{ item.sku }} {# Variant SKU #}
|
||||
|
||||
{# Properties (custom line item data) #}
|
||||
{{ item.properties }} {# Hash of properties #}
|
||||
{% for property in item.properties %}
|
||||
{{ property.first }}: {{ property.last }}
|
||||
{% endfor %}
|
||||
|
||||
{# Discounts #}
|
||||
{{ item.discount_allocations }}
|
||||
{% for discount in item.discount_allocations %}
|
||||
{{ discount.amount }}
|
||||
{{ discount.discount_application.title }}
|
||||
{% endfor %}
|
||||
|
||||
{# Fulfillment #}
|
||||
{{ item.requires_shipping }} {# Boolean #}
|
||||
{{ item.taxable }} {# Boolean #}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
### customer
|
||||
|
||||
Customer object (when logged in):
|
||||
|
||||
```liquid
|
||||
{% if customer %}
|
||||
{{ customer.id }} {# Numeric ID #}
|
||||
{{ customer.email }} {# Email address #}
|
||||
{{ customer.first_name }}
|
||||
{{ customer.last_name }}
|
||||
{{ customer.name }} {# Full name #}
|
||||
{{ customer.phone }}
|
||||
|
||||
{# Account status #}
|
||||
{{ customer.has_account }} {# Boolean: registered #}
|
||||
{{ customer.accepts_marketing }} {# Email marketing opt-in #}
|
||||
{{ customer.email_marketing_consent }}
|
||||
|
||||
{# Addresses #}
|
||||
{{ customer.addresses }} {# Array of addresses #}
|
||||
{{ customer.addresses_count }}
|
||||
{{ customer.default_address }} {# Primary address #}
|
||||
|
||||
{% for address in customer.addresses %}
|
||||
{{ address.first_name }}
|
||||
{{ address.last_name }}
|
||||
{{ address.address1 }}
|
||||
{{ address.address2 }}
|
||||
{{ address.city }}
|
||||
{{ address.province }}
|
||||
{{ address.province_code }} {# State/region code #}
|
||||
{{ address.country }}
|
||||
{{ address.country_code }} {# Country code: US, CA, etc. #}
|
||||
{{ address.zip }}
|
||||
{{ address.phone }}
|
||||
{{ address.company }}
|
||||
{% endfor %}
|
||||
|
||||
{# Orders #}
|
||||
{{ customer.orders }} {# Array of orders #}
|
||||
{{ customer.orders_count }} {# Total orders #}
|
||||
{{ customer.total_spent }} {# Lifetime value (cents) #}
|
||||
|
||||
{# Tags #}
|
||||
{{ customer.tags }} {# Array of customer tags #}
|
||||
|
||||
{# Metafields #}
|
||||
{{ customer.metafields.namespace.key }}
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
### order
|
||||
|
||||
Order object (order confirmation, customer account):
|
||||
|
||||
```liquid
|
||||
{{ order.id }} {# Numeric ID #}
|
||||
{{ order.name }} {# Order name: "#1001" #}
|
||||
{{ order.order_number }} {# 1001 #}
|
||||
{{ order.confirmation_number }} {# Unique confirmation #}
|
||||
{{ order.email }} {# Customer email #}
|
||||
{{ order.phone }} {# Customer phone #}
|
||||
{{ order.customer_url }} {# Link to view order #}
|
||||
|
||||
{# Timestamps #}
|
||||
{{ order.created_at }} {# Order date/time #}
|
||||
{{ order.updated_at }}
|
||||
{{ order.cancelled_at }} {# If cancelled #}
|
||||
{{ order.processed_at }}
|
||||
|
||||
{# Customer #}
|
||||
{{ order.customer }} {# Customer object #}
|
||||
{{ order.customer.name }}
|
||||
|
||||
{# Items #}
|
||||
{{ order.line_items }} {# Array of line items #}
|
||||
{{ order.line_items_count }}
|
||||
|
||||
{% for item in order.line_items %}
|
||||
{{ item.title }}
|
||||
{{ item.quantity }}
|
||||
{{ item.price }}
|
||||
{{ item.line_price }}
|
||||
{% endfor %}
|
||||
|
||||
{# Pricing #}
|
||||
{{ order.subtotal_price }} {# Before tax/shipping #}
|
||||
{{ order.total_price }} {# Grand total #}
|
||||
{{ order.tax_price }} {# Total tax #}
|
||||
{{ order.shipping_price }} {# Shipping cost #}
|
||||
{{ order.total_discounts }} {# Discount amount #}
|
||||
|
||||
{# Status #}
|
||||
{{ order.financial_status }} {# "paid", "pending", "refunded" #}
|
||||
{{ order.fulfillment_status }} {# "fulfilled", "partial", null #}
|
||||
{{ order.cancelled }} {# Boolean #}
|
||||
{{ order.cancel_reason }}
|
||||
|
||||
{# Addresses #}
|
||||
{{ order.shipping_address }}
|
||||
{{ order.billing_address }}
|
||||
|
||||
{# Shipping #}
|
||||
{{ order.shipping_method.title }} {# Shipping method name #}
|
||||
{{ order.shipping_method.price }}
|
||||
|
||||
{# Discounts #}
|
||||
{{ order.discount_applications }}
|
||||
{% for discount in order.discount_applications %}
|
||||
{{ discount.title }}
|
||||
{{ discount.total_allocated_amount }}
|
||||
{% endfor %}
|
||||
|
||||
{# Notes #}
|
||||
{{ order.note }} {# Customer note #}
|
||||
{{ order.attributes }} {# Custom attributes #}
|
||||
|
||||
{# Tags #}
|
||||
{{ order.tags }}
|
||||
```
|
||||
|
||||
### article
|
||||
|
||||
Article object (blog post pages):
|
||||
|
||||
```liquid
|
||||
{{ article.id }} {# Numeric ID #}
|
||||
{{ article.title }} {# Article headline #}
|
||||
{{ article.handle }} {# URL slug #}
|
||||
{{ article.content }} {# Full HTML content #}
|
||||
{{ article.excerpt }} {# Summary/teaser #}
|
||||
{{ article.excerpt_or_content }} {# Excerpt if set, else content #}
|
||||
|
||||
{# Author #}
|
||||
{{ article.author }} {# Author name #}
|
||||
{{ article.author_url }} {# Author profile URL #}
|
||||
|
||||
{# Dates #}
|
||||
{{ article.published_at }} {# Publication date #}
|
||||
{{ article.created_at }}
|
||||
{{ article.updated_at }}
|
||||
|
||||
{# URL #}
|
||||
{{ article.url }} {# Article URL #}
|
||||
|
||||
{# Image #}
|
||||
{{ article.image }} {# Featured image #}
|
||||
{{ article.image.src }}
|
||||
{{ article.image | img_url: 'large' }}
|
||||
|
||||
{# Comments #}
|
||||
{{ article.comments }} {# Array of comments #}
|
||||
{{ article.comments_count }}
|
||||
{{ article.comments_enabled }} {# Boolean #}
|
||||
{{ article.moderated }} {# Comment moderation enabled #}
|
||||
|
||||
{# Tags #}
|
||||
{{ article.tags }} {# Array of tags #}
|
||||
|
||||
{# Blog reference #}
|
||||
{{ article.blog }} {# Parent blog object #}
|
||||
{{ article.blog.title }}
|
||||
|
||||
{# Metafields #}
|
||||
{{ article.metafields.namespace.key }}
|
||||
```
|
||||
|
||||
### blog
|
||||
|
||||
Blog object (blog listing page):
|
||||
|
||||
```liquid
|
||||
{{ blog.id }} {# Numeric ID #}
|
||||
{{ blog.title }} {# Blog name #}
|
||||
{{ blog.handle }} {# URL slug #}
|
||||
{{ blog.url }} {# Blog URL #}
|
||||
|
||||
{# Articles #}
|
||||
{{ blog.articles }} {# Array of articles #}
|
||||
{{ blog.articles_count }} {# Total articles #}
|
||||
|
||||
{# Tags #}
|
||||
{{ blog.all_tags }} {# All article tags #}
|
||||
|
||||
{# Metafields #}
|
||||
{{ blog.metafields.namespace.key }}
|
||||
```
|
||||
|
||||
### search
|
||||
|
||||
Search results object:
|
||||
|
||||
```liquid
|
||||
{{ search.performed }} {# Boolean: search executed #}
|
||||
{{ search.results }} {# Results array #}
|
||||
{{ search.results_count }} {# Number of results #}
|
||||
{{ search.terms }} {# Search query #}
|
||||
{{ search.types }} {# Resource types found #}
|
||||
|
||||
{% for item in search.results %}
|
||||
{% case item.object_type %}
|
||||
{% when 'product' %}
|
||||
{{ item.title }}
|
||||
{{ item.price | money }}
|
||||
{% when 'article' %}
|
||||
{{ item.title }}
|
||||
{{ item.excerpt }}
|
||||
{% when 'page' %}
|
||||
{{ item.title }}
|
||||
{{ item.content | strip_html | truncatewords: 50 }}
|
||||
{% endcase %}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
## Metafields
|
||||
|
||||
Access custom data on any object:
|
||||
|
||||
```liquid
|
||||
{# Product metafields #}
|
||||
{{ product.metafields.namespace.key }}
|
||||
{{ product.metafields.custom.warranty_info }}
|
||||
{{ product.metafields.specifications.material }}
|
||||
|
||||
{# Collection metafields #}
|
||||
{{ collection.metafields.seo.custom_title }}
|
||||
|
||||
{# Customer metafields #}
|
||||
{{ customer.metafields.loyalty.points }}
|
||||
|
||||
{# Shop metafields #}
|
||||
{{ shop.metafields.global.announcement }}
|
||||
|
||||
{# Check for existence #}
|
||||
{% if product.metafields.custom.size_guide %}
|
||||
{{ product.metafields.custom.size_guide }}
|
||||
{% endif %}
|
||||
|
||||
{# Use default filter for safety #}
|
||||
{{ product.metafields.custom.field | default: "Not specified" }}
|
||||
```
|
||||
|
||||
## Metaobjects
|
||||
|
||||
Access metaobject definitions:
|
||||
|
||||
```liquid
|
||||
{# Access metaobject by handle #}
|
||||
{% assign testimonial = shop.metaobjects.testimonials['customer-review-1'] %}
|
||||
|
||||
{{ testimonial.name }}
|
||||
{{ testimonial.rating }}
|
||||
{{ testimonial.content }}
|
||||
|
||||
{# Loop through metaobjects #}
|
||||
{% for testimonial in shop.metaobjects.testimonials.values %}
|
||||
{{ testimonial.fields.author }}
|
||||
{{ testimonial.fields.quote }}
|
||||
{% endfor %}
|
||||
```
|
||||
551
skills/shopify-liquid/references/syntax.md
Normal file
551
skills/shopify-liquid/references/syntax.md
Normal file
@@ -0,0 +1,551 @@
|
||||
# Liquid Syntax - Complete Reference
|
||||
|
||||
## Tag Categories
|
||||
|
||||
### Control Flow Tags
|
||||
|
||||
#### if/elsif/else/endif
|
||||
|
||||
```liquid
|
||||
{% if product.available %}
|
||||
<button>Add to Cart</button>
|
||||
{% elsif product.coming_soon %}
|
||||
<p>Coming Soon</p>
|
||||
{% else %}
|
||||
<p>Sold Out</p>
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
**Operators:**
|
||||
- `==` - equals
|
||||
- `!=` - not equals
|
||||
- `>` - greater than
|
||||
- `<` - less than
|
||||
- `>=` - greater than or equal
|
||||
- `<=` - less than or equal
|
||||
- `contains` - substring or array contains
|
||||
- `and` - logical AND
|
||||
- `or` - logical OR
|
||||
|
||||
**Examples:**
|
||||
```liquid
|
||||
{% if product.price > 100 and product.available %}
|
||||
Premium item in stock
|
||||
{% endif %}
|
||||
|
||||
{% if product.tags contains 'sale' or product.type == 'clearance' %}
|
||||
On sale!
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
#### unless
|
||||
|
||||
Negated if statement:
|
||||
|
||||
```liquid
|
||||
{% unless customer.name == blank %}
|
||||
Hello, {{ customer.name }}
|
||||
{% endunless %}
|
||||
|
||||
{# Equivalent to: #}
|
||||
{% if customer.name != blank %}
|
||||
Hello, {{ customer.name }}
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
#### case/when
|
||||
|
||||
Switch-case statement:
|
||||
|
||||
```liquid
|
||||
{% case product.type %}
|
||||
{% when 'shoes' %}
|
||||
<icon>👟</icon>
|
||||
{% when 'boots' %}
|
||||
<icon>👢</icon>
|
||||
{% when 'sneakers' %}
|
||||
<icon>👟</icon>
|
||||
{% else %}
|
||||
<icon>📦</icon>
|
||||
{% endcase %}
|
||||
```
|
||||
|
||||
### Iteration Tags
|
||||
|
||||
#### for loop
|
||||
|
||||
```liquid
|
||||
{% for product in collection.products %}
|
||||
{{ product.title }}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
**Modifiers:**
|
||||
|
||||
```liquid
|
||||
{# Limit to first 5 #}
|
||||
{% for product in collection.products limit: 5 %}
|
||||
{{ product.title }}
|
||||
{% endfor %}
|
||||
|
||||
{# Skip first 10 #}
|
||||
{% for product in collection.products offset: 10 %}
|
||||
{{ product.title }}
|
||||
{% endfor %}
|
||||
|
||||
{# Reverse order #}
|
||||
{% for product in collection.products reversed %}
|
||||
{{ product.title }}
|
||||
{% endfor %}
|
||||
|
||||
{# Combine modifiers #}
|
||||
{% for product in collection.products limit: 5 offset: 10 %}
|
||||
{# Items 11-15 #}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
**forloop object (available inside loops):**
|
||||
|
||||
```liquid
|
||||
{% for item in array %}
|
||||
{{ forloop.index }} {# 1-based: 1, 2, 3, ... #}
|
||||
{{ forloop.index0 }} {# 0-based: 0, 1, 2, ... #}
|
||||
{{ forloop.rindex }} {# Reverse 1-based: 3, 2, 1 #}
|
||||
{{ forloop.rindex0 }} {# Reverse 0-based: 2, 1, 0 #}
|
||||
{{ forloop.first }} {# true on first iteration #}
|
||||
{{ forloop.last }} {# true on last iteration #}
|
||||
{{ forloop.length }} {# Total number of items #}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
**Example usage:**
|
||||
|
||||
```liquid
|
||||
{% for product in collection.products %}
|
||||
{% if forloop.first %}
|
||||
<h2>Featured Product</h2>
|
||||
{% endif %}
|
||||
|
||||
<div class="product-{{ forloop.index }}">
|
||||
{{ product.title }}
|
||||
</div>
|
||||
|
||||
{% if forloop.index == 3 %}
|
||||
<hr> {# Divider after 3rd item #}
|
||||
{% endif %}
|
||||
|
||||
{% if forloop.last %}
|
||||
<p>Showing {{ forloop.length }} products</p>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
#### break and continue
|
||||
|
||||
```liquid
|
||||
{% for product in collection.products %}
|
||||
{% if product.handle == 'target' %}
|
||||
{% break %} {# Exit loop entirely #}
|
||||
{% endif %}
|
||||
|
||||
{% if product.available == false %}
|
||||
{% continue %} {# Skip to next iteration #}
|
||||
{% endif %}
|
||||
|
||||
{{ product.title }}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
#### tablerow
|
||||
|
||||
Creates HTML table rows:
|
||||
|
||||
```liquid
|
||||
{% tablerow product in collection.products cols: 3 %}
|
||||
{{ product.title }}
|
||||
{% endtablerow %}
|
||||
|
||||
{# Output: #}
|
||||
<table>
|
||||
<tr class="row1">
|
||||
<td class="col1">Product 1</td>
|
||||
<td class="col2">Product 2</td>
|
||||
<td class="col3">Product 3</td>
|
||||
</tr>
|
||||
<tr class="row2">
|
||||
<td class="col1">Product 4</td>
|
||||
...
|
||||
</tr>
|
||||
</table>
|
||||
```
|
||||
|
||||
**tablerow object:**
|
||||
|
||||
```liquid
|
||||
{% tablerow product in products cols: 3 limit: 12 %}
|
||||
{{ tablerow.col }} {# Current column (1-based) #}
|
||||
{{ tablerow.col0 }} {# Current column (0-based) #}
|
||||
{{ tablerow.row }} {# Current row (1-based) #}
|
||||
{{ tablerow.index }} {# Item index (1-based) #}
|
||||
{{ tablerow.first }} {# true on first item #}
|
||||
{{ tablerow.last }} {# true on last item #}
|
||||
{{ tablerow.col_first }} {# true on first column #}
|
||||
{{ tablerow.col_last }} {# true on last column #}
|
||||
{% endtablerow %}
|
||||
```
|
||||
|
||||
#### paginate
|
||||
|
||||
For paginating large collections:
|
||||
|
||||
```liquid
|
||||
{% paginate collection.products by 12 %}
|
||||
|
||||
{% for product in paginate.collection.products %}
|
||||
{% render 'product-card', product: product %}
|
||||
{% endfor %}
|
||||
|
||||
{# Pagination controls #}
|
||||
{% if paginate.pages > 1 %}
|
||||
{{ paginate | default_pagination }}
|
||||
{% endif %}
|
||||
|
||||
{% endpaginate %}
|
||||
```
|
||||
|
||||
**paginate object:**
|
||||
|
||||
```liquid
|
||||
{{ paginate.current_page }} {# Current page number #}
|
||||
{{ paginate.pages }} {# Total pages #}
|
||||
{{ paginate.items }} {# Total items #}
|
||||
{{ paginate.page_size }} {# Items per page #}
|
||||
|
||||
{{ paginate.previous.url }} {# Previous page URL (if exists) #}
|
||||
{{ paginate.previous.title }} {# Previous page title #}
|
||||
{{ paginate.previous.is_link }} {# Boolean #}
|
||||
|
||||
{{ paginate.next.url }} {# Next page URL (if exists) #}
|
||||
{{ paginate.next.title }} {# Next page title #}
|
||||
{{ paginate.next.is_link }} {# Boolean #}
|
||||
|
||||
{{ paginate.parts }} {# Array of page links #}
|
||||
```
|
||||
|
||||
**Custom pagination:**
|
||||
|
||||
```liquid
|
||||
{% paginate collection.products by 20 %}
|
||||
|
||||
<div class="pagination">
|
||||
{% if paginate.previous %}
|
||||
<a href="{{ paginate.previous.url }}">← Previous</a>
|
||||
{% endif %}
|
||||
|
||||
{% for part in paginate.parts %}
|
||||
{% if part.is_link %}
|
||||
<a href="{{ part.url }}">{{ part.title }}</a>
|
||||
{% else %}
|
||||
<span class="current">{{ part.title }}</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if paginate.next %}
|
||||
<a href="{{ paginate.next.url }}">Next →</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% endpaginate %}
|
||||
```
|
||||
|
||||
### Variable Assignment
|
||||
|
||||
#### assign
|
||||
|
||||
Single-line variable assignment:
|
||||
|
||||
```liquid
|
||||
{% assign sale_price = product.price | times: 0.8 %}
|
||||
{% assign is_available = product.available %}
|
||||
{% assign product_count = collection.products.size %}
|
||||
{% assign full_name = customer.first_name | append: ' ' | append: customer.last_name %}
|
||||
```
|
||||
|
||||
#### capture
|
||||
|
||||
Multi-line content capture:
|
||||
|
||||
```liquid
|
||||
{% capture product_title %}
|
||||
{{ collection.title }} - {{ product.title }}
|
||||
{% endcapture %}
|
||||
|
||||
{{ product_title }} {# "Summer Sale - Blue T-Shirt" #}
|
||||
|
||||
{% capture greeting %}
|
||||
<h1>Welcome, {{ customer.name }}!</h1>
|
||||
<p>You have {{ customer.orders_count }} orders.</p>
|
||||
{% endcapture %}
|
||||
|
||||
{{ greeting }}
|
||||
```
|
||||
|
||||
#### liquid (multi-statement)
|
||||
|
||||
Cleaner syntax for multiple statements:
|
||||
|
||||
```liquid
|
||||
{% liquid
|
||||
assign product_type = product.type
|
||||
assign is_on_sale = product.on_sale
|
||||
assign sale_percentage = product.discount_percent
|
||||
|
||||
if is_on_sale
|
||||
assign status = 'SALE'
|
||||
else
|
||||
assign status = 'REGULAR'
|
||||
endif
|
||||
|
||||
echo status
|
||||
%}
|
||||
```
|
||||
|
||||
### Template Inclusion
|
||||
|
||||
#### render
|
||||
|
||||
Isolated scope (preferred method):
|
||||
|
||||
```liquid
|
||||
{# Basic usage #}
|
||||
{% render 'product-card', product: product %}
|
||||
|
||||
{# Multiple parameters #}
|
||||
{% render 'product-card',
|
||||
product: product,
|
||||
show_price: true,
|
||||
show_vendor: false,
|
||||
css_class: 'featured'
|
||||
%}
|
||||
|
||||
{# Render for each item #}
|
||||
{% render 'product-card' for collection.products as item %}
|
||||
|
||||
{# Pass arrays #}
|
||||
{% render 'gallery', images: product.images %}
|
||||
```
|
||||
|
||||
**Inside product-card.liquid:**
|
||||
|
||||
```liquid
|
||||
{# Only has access to passed parameters #}
|
||||
<div class="product {% if css_class %}{{ css_class }}{% endif %}">
|
||||
<h3>{{ product.title }}</h3>
|
||||
|
||||
{% if show_price %}
|
||||
<p>{{ product.price | money }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if show_vendor %}
|
||||
<p>{{ product.vendor }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
```
|
||||
|
||||
#### include
|
||||
|
||||
Shared scope (legacy, avoid in new code):
|
||||
|
||||
```liquid
|
||||
{% include 'product-details' %}
|
||||
|
||||
{# Can access all parent template variables #}
|
||||
{# Harder to debug and reason about #}
|
||||
```
|
||||
|
||||
#### section
|
||||
|
||||
Load dynamic sections:
|
||||
|
||||
```liquid
|
||||
{% section 'featured-product' %}
|
||||
{% section 'newsletter-signup' %}
|
||||
```
|
||||
|
||||
### Utility Tags
|
||||
|
||||
#### comment
|
||||
|
||||
Multi-line comments:
|
||||
|
||||
```liquid
|
||||
{% comment %}
|
||||
This entire block is ignored
|
||||
by the Liquid renderer.
|
||||
Use for documentation.
|
||||
{% endcomment %}
|
||||
|
||||
{# Single-line comment #}
|
||||
```
|
||||
|
||||
#### echo
|
||||
|
||||
Output shorthand (alternative to `{{ }}`):
|
||||
|
||||
```liquid
|
||||
{% echo product.title %}
|
||||
{# Equivalent to: {{ product.title }} #}
|
||||
```
|
||||
|
||||
#### raw
|
||||
|
||||
Output Liquid code without processing:
|
||||
|
||||
```liquid
|
||||
{% raw %}
|
||||
{{ This will be output as-is }}
|
||||
{% Liquid tags won't be processed %}
|
||||
{% endraw %}
|
||||
```
|
||||
|
||||
Useful for documentation or code examples.
|
||||
|
||||
## Whitespace Control
|
||||
|
||||
Strip whitespace using hyphens:
|
||||
|
||||
```liquid
|
||||
{%- if condition -%}
|
||||
Content (whitespace stripped on both sides)
|
||||
{%- endif -%}
|
||||
|
||||
{{ "hello" -}}world
|
||||
{# Output: helloworld (no space) #}
|
||||
|
||||
{{- product.title }}
|
||||
{# Strips whitespace before output #}
|
||||
|
||||
{{ product.title -}}
|
||||
{# Strips whitespace after output #}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```liquid
|
||||
{# Without whitespace control: #}
|
||||
{% for item in array %}
|
||||
{{ item }}
|
||||
{% endfor %}
|
||||
|
||||
{# Output has newlines and indentation #}
|
||||
|
||||
{# With whitespace control: #}
|
||||
{%- for item in array -%}
|
||||
{{ item }}
|
||||
{%- endfor -%}
|
||||
|
||||
{# Output is compact #}
|
||||
```
|
||||
|
||||
## Operator Precedence
|
||||
|
||||
**Order of evaluation (right-to-left):**
|
||||
|
||||
```liquid
|
||||
{% if true or false and false %}
|
||||
{# Evaluates as: true or (false and false) = true #}
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
**IMPORTANT:** No parentheses support in Liquid. Break complex conditions into variables:
|
||||
|
||||
```liquid
|
||||
{# ❌ DOESN'T WORK: #}
|
||||
{% if (x > 5 and y < 10) or z == 0 %}
|
||||
|
||||
{# ✅ WORKS: #}
|
||||
{% assign condition1 = false %}
|
||||
{% if x > 5 and y < 10 %}
|
||||
{% assign condition1 = true %}
|
||||
{% endif %}
|
||||
|
||||
{% if condition1 or z == 0 %}
|
||||
{# Logic here #}
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
## Performance Tips
|
||||
|
||||
1. **Cache repeated calculations:**
|
||||
|
||||
```liquid
|
||||
{# ❌ Inefficient: #}
|
||||
{% for i in (1..10) %}
|
||||
{{ collection.products.size }} {# Calculated 10 times #}
|
||||
{% endfor %}
|
||||
|
||||
{# ✅ Efficient: #}
|
||||
{% assign product_count = collection.products.size %}
|
||||
{% for i in (1..10) %}
|
||||
{{ product_count }}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
2. **Use `limit` and `offset` instead of iterating full arrays:**
|
||||
|
||||
```liquid
|
||||
{# ❌ Inefficient: #}
|
||||
{% for product in collection.products %}
|
||||
{% if forloop.index <= 5 %}
|
||||
{{ product.title }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{# ✅ Efficient: #}
|
||||
{% for product in collection.products limit: 5 %}
|
||||
{{ product.title }}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
3. **Prefer `render` over `include`** for better performance and variable scoping
|
||||
|
||||
4. **Use `liquid` tag** for cleaner multi-statement blocks
|
||||
|
||||
## Common Gotchas
|
||||
|
||||
1. **No parentheses in conditions** - Use variables instead
|
||||
2. **Right-to-left evaluation** - Be careful with operator precedence
|
||||
3. **String concatenation** - Use `append` filter or `capture` tag
|
||||
4. **Array/object mutation** - Not possible; create new variables
|
||||
5. **Integer division** - `{{ 5 | divided_by: 2 }}` returns `2`, not `2.5`
|
||||
6. **Truthy/falsy values:**
|
||||
- `false` and `nil` are falsy
|
||||
- Everything else (including `0`, `""`, `[]`) is truthy
|
||||
|
||||
## Debugging Tips
|
||||
|
||||
1. **Output variable types:**
|
||||
|
||||
```liquid
|
||||
{{ product | json }} {# Output entire object as JSON #}
|
||||
{{ product.class }} {# Output object type #}
|
||||
{{ variable.size }} {# Check array/string length #}
|
||||
```
|
||||
|
||||
2. **Check for nil/existence:**
|
||||
|
||||
```liquid
|
||||
{% if product.metafield %}
|
||||
Metafield exists
|
||||
{% else %}
|
||||
Metafield is nil
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
3. **Use default filter for safety:**
|
||||
|
||||
```liquid
|
||||
{{ product.metafield.value | default: "Not set" }}
|
||||
```
|
||||
|
||||
4. **Enable theme preview console** to see Liquid errors in real-time
|
||||
Reference in New Issue
Block a user