Are you happy with your logging solution? Would you help us out by taking a 30-second survey? Click here


Liquid markup language. Safe, customer facing template language for flexible web apps.

Star full 4f7b624809470f25b6493d5a7b30d9b9cb905931146e785d67c86ef0c205a402Star full 4f7b624809470f25b6493d5a7b30d9b9cb905931146e785d67c86ef0c205a402Star full 4f7b624809470f25b6493d5a7b30d9b9cb905931146e785d67c86ef0c205a402Star full 4f7b624809470f25b6493d5a7b30d9b9cb905931146e785d67c86ef0c205a402Star full 4f7b624809470f25b6493d5a7b30d9b9cb905931146e785d67c86ef0c205a402 (1 ratings)
Rated 5.0 out of 5
Subscribe to updates I use liquid

Statistics on liquid

Number of watchers on Github 6193
Number of open issues 117
Average time to close an issue 4 days
Main language Ruby
Average time to merge a PR 2 days
Open pull requests 42+
Closed pull requests 30+
Last commit over 1 year ago
Repo Created over 11 years ago
Repo Last Updated over 1 year ago
Size 4.18 MB
Homepage http://liquidmark...
Organization / Authorshopify
Page Updated
Do you use liquid? Leave a review!
View open issues (117)
View liquid activity
View on github
Fresh, new opensource launches πŸš€πŸš€πŸš€
Trendy new open source projects in your inbox! View examples

Subscribe to our mailing list

Evaluating liquid for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)

Build Status Inline docs

Liquid template engine


Liquid is a template engine which was written with very specific requirements:

  • It has to have beautiful and simple markup. Template engines which don't produce good looking markup are no fun to use.
  • It needs to be non evaling and secure. Liquid templates are made so that users can edit them. You don't want to run code on your server which your users wrote.
  • It has to be stateless. Compile and render steps have to be separate so that the expensive parsing and compiling can be done once and later on you can just render it passing in a hash with local variables and objects.

Why you should use Liquid

  • You want to allow your users to edit the appearance of your application but don't want them to run insecure code on your server.
  • You want to render templates directly from the database.
  • You like smarty (PHP) style template engines.
  • You need a template engine which does HTML just as well as emails.
  • You don't like the markup of your current templating engine.

What does it look like?

<ul id="products">
  {% for product in products %}
      <h2>{{ }}</h2>
      Only {{ product.price | price }}

      {{ product.description | prettyprint | paragraph }}
  {% endfor %}

How to use Liquid

Liquid supports a very simple API based around the Liquid::Template class. For standard use you can just pass it the content of a file and call render with a parameters hash.

@template = Liquid::Template.parse("hi {{name}}") # Parses and compiles the template
@template.render('name' => 'tobi')                # => "hi tobi"

Error Modes

Setting the error mode of Liquid lets you specify how strictly you want your templates to be interpreted. Normally the parser is very lax and will accept almost anything without error. Unfortunately this can make it very hard to debug and can lead to unexpected behaviour.

Liquid also comes with a stricter parser that can be used when editing templates to give better error messages when templates are invalid. You can enable this new parser like this:

Liquid::Template.error_mode = :strict # Raises a SyntaxError when invalid syntax is used
Liquid::Template.error_mode = :warn # Adds errors to template.errors but continues as normal
Liquid::Template.error_mode = :lax # The default mode, accepts almost anything.

If you want to set the error mode only on specific templates you can pass :error_mode as an option to parse:

Liquid::Template.parse(source, :error_mode => :strict)

This is useful for doing things like enabling strict mode only in the theme editor.

It is recommended that you enable :strict or :warn mode on new apps to stop invalid templates from being created. It is also recommended that you use it in the template editors of existing apps to give editors better error messages.

Undefined variables and filters

By default, the renderer doesn't raise or in any other way notify you if some variables or filters are missing, i.e. not passed to the render method. You can improve this situation by passing strict_variables: true and/or strict_filters: true options to the render method. When one of these options is set to true, all errors about undefined variables and undefined filters will be stored in errors array of a Liquid::Template instance. Here are some examples:

template = Liquid::Template.parse("{{x}} {{y}} {{z.a}} {{z.b}}")
template.render({ 'x' => 1, 'z' => { 'a' => 2 } }, { strict_variables: true })
#=> '1  2 ' # when a variable is undefined, it's rendered as nil
#=> [#<Liquid::UndefinedVariable: Liquid error: undefined variable y>, #<Liquid::UndefinedVariable: Liquid error: undefined variable b>]
template = Liquid::Template.parse("{{x | filter1 | upcase}}")
template.render({ 'x' => 'foo' }, { strict_filters: true })
#=> '' # when at least one filter in the filter chain is undefined, a whole expression is rendered as nil
#=> [#<Liquid::UndefinedFilter: Liquid error: undefined filter filter1>]

If you want to raise on a first exception instead of pushing all of them in errors, you can use render! method:

template = Liquid::Template.parse("{{x}} {{y}}")
template.render!({ 'x' => 1}, { strict_variables: true })
#=> Liquid::UndefinedVariable: Liquid error: undefined variable y
liquid open issues Ask a question     (View All Issues)
  • almost 3 years Possible bug with assign precedence in included partials
  • almost 3 years The roadmap for 4.0 release
  • about 3 years How to add external Json as variables to shopify
  • about 3 years Unclosed {% if %} statements return validation errors when they are wrapped in the {% comment %} tag.
  • about 3 years else block in case always executes if it's the first block
  • about 3 years {{ page.....title }} is valid syntax
  • about 3 years Strict parser handles variables that start with contains differently
  • about 3 years Filters page shows raw code for examples after 'floor'
  • over 3 years Additional string filters
  • over 3 years Can we please make the markup property in Liquid::Variable readable? Currently it isn't
  • over 3 years include_raw
  • over 3 years Printing out a variable, where part of the name of it is another variable?
  • over 3 years sort filter options ?
  • over 3 years Best practice for safe dynamic drops?
  • over 3 years The inclusions of .errors makes Liquid::Template non thread-safe?
  • over 3 years Liquid::UndefinedVariable is raised for defined attribute with nil value, when strict_variables: true
  • over 3 years increment/decrement raises ruby error when incorrect argument passed
  • over 3 years [filters: date] Please implement ordinal digits
  • over 3 years [Docs] Add a link to report an issue
  • over 3 years [Docs] Add link to Cheat sheet
  • over 3 years [Docs] Breaking non-wrapping code blocks
  • over 3 years [Docs] Prevent scrolling of content area when navigation is open
  • over 3 years [Docs] Better button wrapping
  • over 3 years [Docs] Better a11y
  • over 3 years Include dynamic filename is not working
  • over 3 years How do we correlate Liquid::Error with input template on parsing time?
  • over 3 years Cannot assign valid string contents
  • over 3 years [request] make arrays in liquid / concat filter
  • over 3 years Custom Liquid::Block tag not working properly inside a for loop tag
  • almost 4 years Slow for loops
liquid open pull requests (View All Pulls)
  • Add format filter
  • Force #to_liquid call in InputIterator#each
  • Add separator to For tag
  • Allow first and last filters to take count argument
  • Allow variable and tag end characters to be quoted.
  • Allow use of curlies in a properly quoted string
  • Add very simple spaceless tag
  • sorting on nested properties
  • Tag formatter/syntax fixer (WIP)
  • Docs Update
  • Fix for loop with reversed and limit.
  • implementation/tests of the template inheritance mechanism
  • Add support for whitespace control character allowing for ERB like trim
  • Fix string methods for cyrillic
  • rubocop 0.39.0, drop support for 2.0 and add 2.3.0 in travis
  • handle nil value for key when strict_variables is on
  • Restore the down arrow in vertical scroll bar
  • Add whitespace control character and associated tests
  • Fix double-adding tokens in raw tags
  • Fix escape_once not working with hex entities or named entities ending with numbers
  • Allow variables to start with contains in strict parser
  • Expand boolean support and force whitespace between lexicals
  • introduce unhandled liquid exception
  • Misc. documentation updates
  • Fixes #784: Filters page shows raw code for examples after 'floor'
  • 828 fix content variable error
  • Clarifies spelling of for’s reversed flag to address #843
  • Clarifies spelling of for’s reversed flag to address #843
  • Add a filter to compute percentages
  • add title case filter
  • Fix Liquid/C BlockBody loading issue
  • Wrap capture example in {% raw %} and highlight it as Liquid
  • Add JSON parse as standard filter
  • Add ability to render {} inside liquid interpolations
  • Be more permisive with comment bodies
  • Fix sort and sort_natural on sorting with non-string and nil values
  • Prefer faster `while true` over `loop do`
  • Add support for iterating ranges with float boundaries.
  • Add to_power as standard filter
  • Make 'include with' different from 'include for'
  • standardfilters: add regex replace/remove filters
  • [CI] Test against Ruby 2.5 version
liquid questions on Stackoverflow (View All Questions)
  • Implementing open-source Ruby modules in .liquid?
  • Why is liquid include statement in Tag markup rather than Output markup
  • Does liquid have an "or if blank?"-type filter?
  • Bootstrap responsive liquid item layout menu
  • Show current date in Coupa/Liquid
  • Error when escaping liquid (gulp-sass, shopify)
  • Less than condition in if loop not working - Liquid HTML
  • creating and accessing arrays in liquid templates
  • Jekyll (Liquid): Setting post state in included templates
  • Stuck trying to get the liquid gem to work in rails
  • Rails 4 integration liquid template error
  • Does liquid work with wysiwyg editors? - rails
  • Liquid template: Get first 5 posts that match criterion
  • Jekyll - Liquid Exception: cannot load such file -- yajl/2.0/yajl
  • How to use multiple arguments in an if statement with Liquid
  • Liquid | Jekyll - For loop with 2 conditions? with limit?
  • Is it possible to edit and preview Shopify Liquid code without using Shopify?
  • Capitalize first letter of each word with liquid syntax?
  • How to get "to" or "from" route within liquid-fire transition?
  • Liquid + Jekyll, "unless" not working inside "for" loop
  • Liquid templates: strange behavior when assigning variables within for loops
  • Computing a Weighted Average with Liquid Template Filters
  • Centering image in columns (liquid layout)
  • Setting up and using liquid
  • Android Studio + Liquid Fun
  • Octopress: Liquid Exception: invalid byte sequence in GB2312, when rake generate
  • Liquid Slider not working properly in chrome extension
  • How to append a variable inside another vaiable name in liquid html
  • Not equal to operator in Liquid
  • Outputting Literal curly braces in Liquid templates
liquid list of languages used
Other projects in Ruby