Commit Graph
88 Commits
Author SHA1 Message Date
Tobi Lutke 3befa567b1 Add hermetic template recording and replay 2026-08-07 12:30:55 -04:00
Alok SwamyandClaude Opus 4.6 532b439063 Reject bare-bracket syntax in strict2 and introduce self keyword
Add bare-bracket rejection to Parser#expression in strict2 mode, so that
`['var']` is disallowed and `self['var']` is the required syntax.

- Add `Expression::SELF` constant ('self')
- Add `Parser#reject_bare_brackets` option, checked in `expression`
- Add `ParseContext#reject_bare_brackets?` and `force_reject_bare_brackets`
- Add `VariableLookupDrop` for `self['var']` scope-chain lookups
- Add `Variable#==` for rewriter state comparison
- Update `Context#find_variable` to return `VariableLookupDrop` for `self`

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
2026-03-23 12:13:59 -04:00
Guilherme CarreiroandGitHub 32b50ecafe Bump Liquid to 5.11.0 (#2012)
This commit reverts the Inline Snippets tag (#2001) and bumps
Liquid to 5.11. For now, the inclusion of Inline Snippets
in the latest Liquid release is being treated as a bug.

While #2001 does implement the scope contained in RFC#1916,
we need to take a step back to make sure we’re setting our
sights high enough with this feature, and that we’re truly
supporting theme developers in the ways they need.

If you have any feedback, please leave a comment on RFC#1916.

- Liquid Developer Tools
2025-11-19 18:03:23 +01:00
Julia BoutinandGuilherme Carreiro 0ceeefba02 Implement resource limits and remove leftover string references 2025-10-30 12:00:44 +01:00
Julia BoutinandGuilherme Carreiro 65fb80a347 Render arguments should maintain correct precedence 2025-10-30 12:00:44 +01:00
Julia BoutinandGuilherme Carreiro 12bbbc4537 Create SnippetDrop and set in scope 2025-10-30 12:00:44 +01:00
Guilherme CarreiroandGuilherme Carreiro e413104e78 Remove ExpressionParser in favor of ParseContext#safe_parse 2025-10-27 16:33:31 +01:00
Guilherme CarreiroandGuilherme Carreiro 1bff382ebc Add ExpressionParser and ExpressionConsumer 2025-10-27 16:33:31 +01:00
Michael Go 313d01706a code styling 2025-01-07 14:32:46 -04:00
Michael Go 7c592c1c00 store StringScanner in ParseContext and reuse it through parsing 2025-01-07 14:32:45 -04:00
Michael Go 3c16c27ee1 add StringScannerPool for thread safety 2025-01-07 14:32:07 -04:00
Michael Go 0b1dc295ff fix quirky negative sign expression markup parsing 2025-01-07 14:32:07 -04:00
Michael Go c77ff68573 clean up all warnings by using new Environment 2024-11-04 16:15:05 -04:00
Ian Ker-SeymerandGitHub b0cba0bfd2 Remove Liquid.cache_classes option (#1847) 2024-11-04 14:41:56 -05:00
Michael Go 29986d3704 remove TagRegistry 2024-11-04 15:22:56 -04:00
Ian Ker-SeymerandGitHub fb6634f454 Add concept of Liquid::Environment (#1815)
* Add concept of `Liquid::World`

* Rename `World` to `Environment`
2024-08-07 15:00:44 -04:00
Michael Go 2b40850e4a fix variable lookup parse timing out with missing closing bracket 2023-02-01 19:52:30 -04:00
Michael Go 1aaf6ed019 recursively parse brackets on variable lookup 2023-01-30 20:19:35 -04:00
Dylan Thacker-Smith 7bc14ae2be Remove unused class Liquid::Register to avoid confusion 2022-05-04 17:25:52 -04:00
Dylan Thacker-Smith 41c19929ad Rename and alias Liquid::StaticRegisters to Liquid::Registers 2022-05-04 17:25:52 -04:00
Charles-P. ClermontandDylan Thacker-Smith 1f0a0ad55c Add # inline comment tag.
This commit adds a new tag named `#` that behaves like a comment.

Therefore it behaves as you'd expect any tag would work. The difference
with the comment tag is that the comment is in the tag markup and that
there is no block delimiter.

What it looks like in practice:

```liquid
{%- # this is an inline comment -%}
{% # this too is an inline comment %}

{% liquid
  # required args:
  assign product = product

  # optional args:
  assign should_show_border = should_show_border | default: true
  assign should_show_cursor = should_show_cursor | default: true
%}

{% liquid
  # This is a very long comment that spans multiple lines.
  # It looks very similar to what it would look like if you wrote
  # ruby code instead of liquid. But it doesn't have all the clunk
  # of having an open tag and a close tag with so many characters.
%}
```

Co-authored-by: Dylan Thacker-Smith <[email protected]>
2022-04-28 09:38:44 -04:00
Jean Boussier c588337aac Eagerly cache global filters
Including a module can cause Ruby's global constant cache to be busted
if the included module contain constants. So that's something you don't
want to happen at "runtime", otherwise it will severely degrade performance
and if you are using YJIT or MJIT most of the compiled code will be invalidated.

To limit the impact of this, we can pre-include the global filters,
as they're generally registered during boot, that limits the problem
to non-global filters.
2022-03-01 13:40:40 +01:00
Charles-P. Clermont 1310c4978d Fix kwarg parsing inconsistency with Liquid::C
Liquid::C parses liquid filter arguments with dashes in them, Liquid does not.

For tags that accept kwargs and dumps them on the HTML tag, this is an important feature.

e.g. {{ ... | image_tag: loading: 'lazy', data-something: 'value!' }}

Without this change, Liquid would incorrectly parse the
`data-something` kwarg as a single argument and would skip over the
invalid characters.

See https://github.com/Shopify/theme-check/issues/539 for more context
2022-02-11 15:10:07 -05:00
Ashwin Maroli 740f8759cc Rename constant to RAISE_EXCEPTION_LAMBDA 2020-10-28 23:06:13 +05:30
Ashwin Maroli bfa2df7036 Stash exception_renderer lambda in a constant 2020-10-26 19:44:00 +05:30
Dylan Thacker-SmithandGitHub 2b11efc3ae Fix performance regression from introduction of Template#disable_tags (#1274) 2020-08-18 11:25:51 -04:00
Thierry Joyal c0ffeeef26 [Strainer] Separate factory from template 2020-01-06 17:45:25 +00:00
Martin Morissette d8f31046a9 Introduce template factory 2019-12-17 21:45:08 -05:00
Mike AngellandGitHub 0db9c56f34 Disable rendering of tag based on register (#1162)
* Disable rendering of tag based on register

* Improvements to disable tag

* Resolve disbale tag tests

* Test disable_tags register

* disabled_tags is now always avaiable

* Allow multiple tags to be disabled at once

* Move disabled check to block_body

* Code improvements

* Remove redundant nil check

* Improve disabled tag error output

* Improve disable tag API

* Code improvements

* Switch disabled? to not mutate output

* Fix array handling shortcut in disable_tags
2019-09-26 00:18:30 +10:00
Mike AngellandGitHub d8403af515 Reimplementation of Static Registers (#1157) 2019-09-18 13:25:55 +10:00
0d26f05bb8 Enabled frozen string literals (#1154)
* Enabled frozen string literals

* Update rubocop config

* Prefer string interpolation in simple cases

Co-Authored-By: Dylan Thacker-Smith <[email protected]>
2019-09-18 13:19:45 +10:00
Mike Angell b6547f322e Simplify usage 2019-09-11 04:56:25 +10:00
Samuel 9672ed5285 Add a new {% render %} tag
Example:

```
// the_count.liquid
{{ number }}! Ah ah ah.

// my_template.liquid
{% for number in range (1..3) %}
  {% render "the_count", number: number %}
{% endfor %}

Output:
1! Ah ah ah.
2! Ah ah ah.
3! Ah ah ah.
```

The `render` tag is a more strict version of the `include` tag. It is
designed to isolate itself from the parent rendering context both by
creating a new scope (which does not inherit the parent scope) and by
only inheriting "static" registers.

Static registers are those that do not hold mutable state which could
affect rendering. This again helps `render`ed templates remain entirely
separate from their calling context.

Unlike `include`, `render` does not permit specifying the target
template using a variable, only a string literal. For example, this
means that `{% render my_dynamic_template %}` is invalid syntax. This
will make it possible to statically analyze the dependencies between
templates without making Turing angry.

Note that the `static_environment` of a rendered template is inherited, unlike
the scope and regular environment. This environment is immutable from within the
template.

An alternate syntax, which mimics the `{% include ... for %}` tag is
currently in design discussion.
2019-08-29 16:32:05 -04:00
Stephen Paul Weber 7d13d88258 s/Traversal/ParseTreeVisitor 2018-10-18 09:38:33 -04:00
Stephen Paul Weber c11fc656cf Colocate Traversal classes with classes they traverse
This puts all knowledge of the traversal in the same file, and removes
the need for a CASES registry.
2018-10-18 09:37:48 -04:00
Michael Angell e1d40c7d89 Add whitespace control character and associated tests 2016-06-28 09:15:45 +10:00
Florian Weingarten 79e2d1d8b4 Liquid::TablerowloopDrop 2016-01-08 18:46:23 +00:00
Florian Weingarten e113c891ec Convert forloop hash to drop 2016-01-06 21:30:32 +00:00
Dylan Thacker-Smith cebf75b8d7 Implement line numbers without the Liquid::Token class. 2015-07-08 19:21:59 -04:00
Gaurav Chande 8b98f92c7f Extract tokenize logic from Template to a RubyTokenizer 2015-06-04 04:39:30 +00:00
Florian Weingarten f4724f0db3 Remove support for liquid_methods Module extension 2015-05-14 14:44:19 +00:00
Jean Boussier b31df0fb3d Mordernize code base with __dir__ and require_relative 2015-05-13 15:33:00 -04:00
Justin Li e2f8b28f56 Merge pull request #492 from Shopify/resource-counting-perf
Resource counting perf
2014-12-11 16:05:41 -05:00
Justin Li dd455a6361 Force user to require the profiler themselves 2014-12-04 17:48:26 -05:00
Justin Li 8c70682d6b Don't automatically load hooks 2014-12-04 17:39:41 -05:00
Justin Li db00ec8b32 Move resource limit tracking to its own class 2014-12-04 16:18:09 -05:00
Justin Li c0aab820ed Lazily load profiler hooks 2014-11-12 00:05:01 -05:00
Dylan Thacker-SmithandJustin Li 73fcd42403 Create a BlockBody class to decouple block body parsing from tags. 2014-11-03 17:07:42 -05:00
Tristan HumeandFlorian Weingarten 3a0ee6ae91 Remove parser switching duplication 2014-09-05 14:12:29 +00:00
Florian Weingarten 5eff375094 Optional line numbers for liquid errors 2014-09-05 14:12:29 +00:00