Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:32:51 +08:00
commit 636e443771
13 changed files with 6987 additions and 0 deletions

View 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: &lt;div&gt;Test&lt;/div&gt; #}
```
### escape_once
Escape HTML but don't double-escape:
```liquid
{{ "&lt;div&gt;" | escape_once }}
{# Output: &lt;div&gt; (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 %}
```

View 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 %}
```

View 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