Skip to content
CAI
Software that uses CAICheck a score

Shopify/liquid

70.2

Strong · 26 September 2026

6.8k

lines of production code

Ruby

primary language

4

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is the Liquid template engine, a Ruby-based library for parsing and rendering templating syntax. It provides a modernized, high-performance rendering architecture with strict parsing modes, isolated subcontexts for security, and comprehensive profiling tools. The codebase includes a command-line interface for template rendering and a suite of integration and performance benchmarks to ensure reliability and speed.

How it got here

2008 — Liquid 6.0 architecture modernization

10 changes.

The project underwent a major refactoring to introduce Liquid 6.0, featuring a new lexer-based parsing architecture, strict parsing modes, and an Environment abstraction for better performance and safety. This period also involved modernizing the build tooling, updating example code to use current Ruby idioms, and removing legacy components such as the Test::Unit suite and the LiquidView extension.

2009–2014 — Performance benchmarking and test expansion

8 changes.

This period focused on establishing a comprehensive performance benchmarking suite for the Liquid template engine, including tools for profiling execution speed and memory usage against realistic Shopify datasets. It also involved significantly expanding test coverage by adding extensive unit and integration tests for core components, tags, and error handling to ensure stability and correctness.

2020–2026 — Testing infrastructure and CLI tooling

4 changes.

This period focused on expanding test coverage and establishing performance baselines for Liquid's parsing and lexing components. It also introduced a new command-line rendering tool with strict error handling and added spec adapters to validate behavior across different runtime configurations.

Features

Add Shopify performance benchmark suite with Liquid templates and filters

This change introduces a new performance benchmarking suite for Shopify's Liquid implementation. It adds a set of custom Liquid tags and filters (including \paginate\, \comment\_form\, \json\, \money\, \weight\, and various shop/tag helpers) along with a sample YAML database (\vision.database.yml\) and a loader script (\liquid.rb\) to wire them together. The suite is designed to measure rendering performance against a realistic dataset, including handling YAML references via \unsafe\_load\_file\ for Psych 4+ compatibility.

performance/shopify · high confidence

Added Liquid rendering profiler via hook modules

A new profiler has been introduced to capture performance metrics during Liquid template rendering. This is implemented by prepending hook modules to \BlockBody\, \Document\, and \Context\. The \BlockBody\ hook instruments individual node rendering, the \Document\ hook wraps the entire output buffer generation, and the \Context\ hook ensures the profiler instance is correctly propagated to isolated sub-contexts. This allows users to profile template execution without modifying their existing rendering logic.

lib/liquid/profiler · high confidence

New bin/render script with strict parsing and virtual file system support

A new executable script, bin/render, has been added to allow users to render Liquid templates directly from the command line. The script accepts a template file path as an argument, parses it using Liquid version 5.11.0 with the :strict2 error mode to catch template errors early, and supports a virtual file system for loading snippets. It also includes a usage message if no template file is provided.

bin · high confidence

New performance benchmarking and profiling suite

Added a new set of scripts in the performance directory to measure and analyze Liquid's execution speed and memory usage. The suite includes a benchmark runner using benchmark/ips to measure tokenize, parse, render, and combined phases; a memory profiler using memory\_profiler to track allocated and retained memory; and a CPU/object profiler using stackprof. These tools allow developers to simulate real-world rendering scenarios (loading templates from a file system, compiling, and rendering with layouts) to identify performance bottlenecks.

performance · high confidence

Removals

Removal of LiquidView template handler

The LiquidView extension, which previously allowed Rails applications to use Liquid as a template system for .liquid files, has been removed. Users can no longer register or utilize this specific ActionView template handler for rendering Liquid templates within the application.

lib/extras · high confidence

Behavioural changes

Liquid 6.0 introduces a new parsing architecture and Environment abstraction

This release refactors the core Liquid rendering engine, replacing the legacy parser and tag registry with a new, faster lexer-based architecture and a centralized \Liquid::Environment\ for configuration. The new \BlockBody\ class decouples block parsing from tags, while \Liquid::Expression\ and \Liquid::Parser\ handle strict, rigid, and lax parsing modes with improved error reporting and line numbers. Key behavioral changes include the deprecation of the old tag registry in favor of \Environment.register\_tag\, the introduction of \Liquid::Interrupts\ for \break\/\continue\ support, and stricter parsing rules in \strict2\ and \rigid\ modes that reject bare-bracket access and require explicit \self\ usage. The \ForloopDrop\ and \ParseTreeVisitor\ classes provide new ways to access loop metadata and traverse the parse tree, while \PartialCache\ and \I18n\ improvements enhance performance and localization support.

lib/liquid · high confidence

Liquid library modernized with new parsing architecture and strict mode

The Liquid library has been significantly refactored to improve performance, safety, and maintainability. Key changes include the introduction of a new \Liquid::Environment\ for configuration, a restructured parser using \ParseContext\ and \ExpressionParser\ to decouple parsing from rendering, and the addition of strict parsing modes (rejecting bare-bracket syntax) alongside a new \self\ keyword. The update also enables frozen string literals, adds UTF-8 support, implements resource limits to prevent DoS via iteration, and introduces a new \{% render %}\ tag. Users should note that some legacy features like \liquid\_methods\ module extension and the \raw\ literal tag have been removed or replaced.

lib · high confidence

Liquid tags refactored to support strict parsing and isolated subcontexts

The Liquid tag library has been significantly refactored to improve parsing strictness, performance, and security. Key changes include the introduction of a \strict2\_parse\ mode for tags like \assign\, \capture\, \for\, \if\, \case\, \cycle\, \include\, and \render\, enabling more robust syntax validation. The \render\ tag now uses isolated subcontexts, preventing snippets from accidentally accessing or modifying outer scope variables, and supports a new \as\ alias syntax. New tags \{% break %}\ and \{% continue %}\ allow control flow within \for\ and \tablerow\ loops. The \increment\ and \decrement\ tags now share variables with each other but remain independent from \assign\ and \capture\. Additionally, the \raw\ and \doc\ tags have been updated to strictly validate their markup, and the \comment\ tag now supports nested comments and raw blocks.

lib/liquid/tags · high confidence

Modernize example server code and add more product data

The example server has been updated to use modern Ruby idioms, including enabling frozen string literals, replacing \File.dirname(\_\FILE\\)\ with \\\dir\\_\, and using \require\_relative\ for cleaner imports. The \example\_servlet\ now exposes additional product data via a new \more\_products\_list\ and a \description\ field, allowing templates to display a broader range of items. Additionally, the \liquid\_servlet\ refactors route parsing to use \Regexp.last\_match\ instead of global variables and standardizes hash syntax.

example/server · high confidence

Modernized project configuration and build tooling

The project has replaced the legacy Hoe-based Rakefile with a modern setup using Rake::TestTask and RuboCop for linting, enabling tests to run across lax, strict, and strict2 parsing modes. Configuration files for RuboCop (including the rubocop-shopify gem and performance cops) and .gitignore have been added, while legacy files like init.rb, the old README, and Manifest.txt have been removed. The .ruby-version file now specifies Ruby 4.0.2, and the license file has been renamed from MIT-LICENSE to LICENSE.

(repo-wide) · high confidence

Update products page to use concatenated product list and split description

The products template now combines the main product list with an additional set of items using the new \concat\ filter, ensuring the catalog count and iteration reflect the full set of products. Additionally, the page title and subheading are now derived from a single description variable by splitting it on the tilde character, allowing for structured display of description parts.

example/server/templates · high confidence

Test coverage

Added Liquid spec adapters for reference implementation and variant testing; Added integration tests for Liquid template engine; Added integration tests for tag disabling functionality; Added performance benchmarks for Liquid expression parsing and lexing; Added performance test templates for Dropify, Ripen, and Tribble themes; Added unit tests for case, comment, doc, for, and if tags; Added unit tests for core Liquid components; Expanded integration test coverage for Liquid template tags; Removal of legacy test utilities; Removed legacy Test::Unit test suite.

Dependencies

Initial gem packaging and dependency configuration

The project introduces its first Gemfile and gemspec, establishing the build and dependency structure for the Liquid template engine. The gemspec defines the core runtime dependencies on \strscan\ (\>= 3.1.1) and \bigdecimal\, while requiring Ruby 3.0.0 or later. The Gemfile configures development and testing tools, including RuboCop 1.82.0 with the Shopify style guide, Minitest for testing, and benchmarking utilities like \benchmark-ips\ and \stackprof\.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.

Score

  • CAI 53 → 70 (+17.5)
  • Rubric changed (rubric-2026.08.15 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 99 → 95 (-4.5)
  • Architecture 94 → 99 (+4.8)
  • Maturity 55 → 54 (-0.9)
  • Readiness 30 → 77 (+47.0)
  • Security 85 → 88 (+2.2)

Resolved (5)

  • Coverage not measured — test suite did not build
  • Dimension evaluation failed
  • No exposed public API
  • No tests found
  • Test reliability not included

New (26)

  • Change coupling: assign.rb ↔ capture.rb (lib/liquid/tags/assign.rb)
  • Comment.parse_body (cognitive 19) (lib/liquid/tags/comment.rb)
  • Confusing naming hierarchy: safe_parse, parse, and inner_parse suggest a complex internal parsing strategy that is exposed publicly. inner_parse is particularly bad API design as it implies internal implementation details. safe_parse vs parse is acceptable if they differ by error handling, but the existence of inner_parse suggests a leaky abstraction.
  • Duplicate intent: Both methods appear to add a new scope to the context stack. In most stack-based interpreters, 'push' and 'stack' are synonyms for the same operation. Having both creates confusion about whether they have different side effects or performance characteristics.
  • Duplicated block (13 lines × 2) (lib/liquid/tags/include.rb)
  • Duplicated block (16 lines × 2) (lib/liquid/tags/include.rb)
  • Expression.parse_number (cognitive 25) (lib/liquid/expression.rb)
  • Expression.parse_number (cyclomatic 19) (lib/liquid/expression.rb)
  • FileTooLong: liquid/standardfilters.rb (lib/liquid/standardfilters.rb)
  • Fork-triggerable workflow runs with an unscoped write token
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • Lexer.tokenize (cognitive 46) (lib/liquid/lexer.rb)
  • Lexer.tokenize (cyclomatic 23) (lib/liquid/lexer.rb)
  • Orphaned files with no living knowledge
  • Signature inconsistency: The Document type has two parse methods with different first argument types (tokens vs tokenizer). While this might be an overload, it is inconsistent with the rest of the API where parsing usually starts from a tokenizer or string, not raw tokens, or vice versa. It suggests a lack of clear entry point for parsing.
  • Template.render (cognitive 16) (lib/liquid/template.rb)
  • Template.render (cyclomatic 17) (lib/liquid/template.rb)
  • TodoComment (lib/liquid/environment.rb)
  • …and 6 more

Changes since last survey

  • 3 commits — 3 feature/other, 0 fixes

By area

  • (root) — 1 commit
  • lib/liquid — 1 commit
  • test/integration — 1 commit

Notable commits

  • change: Bound resource use when iterating ranges (#2117)
  • change: Bump to 5.14.0 (#2121)
  • change: Restore the Liquid CI baseline (#2118)

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

Shopify/liquid was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 26 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 4e39ae4cc3da73921923c0669e0fc84a66b2f696 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-d0929f7ac71f.