1111# variables ({{ ... }}, {% echo %}) are never blank, so their errors always
1212# print.
1313#
14- # MODE MATRIX (decided 2026-07-05): suppression is a LAX-MODE compatibility
15- # behavior. In strict and strict2 the error text must SURFACE even for blank
16- # bodies — silent failure of an erroring condition is not acceptable in the
17- # strict modes. NOTE: reference liquid currently suppresses in every parse
18- # mode (BlockBody.rescue_render_node's `unless blank_tag` guard, kept for
19- # backwards compatibility); the strict/strict2 specs below therefore define
20- # required behavior beyond current reference conformance.
14+ # MODE MATRIX:
15+ # - lax inline-error mode preserves the historical blank-body suppression.
16+ # - strict inline-error mode also preserves that historical suppression for
17+ # backwards compatibility.
18+ # - strict2 is the new behavior: blank bodies must NOT suppress inline error
19+ # text. If an error is evaluated, strict2 should make it visible.
20+ # - raised-error mode is separate from inline-error output. With raised errors
21+ # enabled, all modes raise; blank-body suppression only controls rendered
22+ # inline error TEXT.
2123#
22- # All lax expectations in this file were validated verbatim against reference
23- # liquid (line_numbers: true) .
24+ # Lax/strict expectations were validated against current reference liquid.
25+ # Strict2 expectations intentionally define the new desired behavior .
2426
2527specs :
2628
@@ -155,31 +157,44 @@ specs:
155157 ERROR TEXT of a blank tag is suppressed; evaluation and side effects are
156158 unchanged.
157159
158- # ── Strict modes: suppression does NOT apply ──────────────── ────────────────
160+ # ── Strict mode: historical inline-error suppression remains ────────────────
159161
160- - name : blank_if_body_shows_error_text_strict
162+ - name : blank_if_body_suppresses_error_text_strict
161163 template : " {% if 5 > \" x\" %}{% endif %}"
162164 error_mode : :strict
163165 render_errors : true
164- expected : " Liquid error (line 1): comparison of Integer with String failed"
166+ expected : " "
167+ complexity : 750
168+ hint : |
169+ QUIRK: strict mode still preserves the historical inline-error text
170+ suppression for blank block bodies. The condition is evaluated and the
171+ error is recorded/raised in raised-error mode, but render_errors/inline
172+ output stays empty for compatibility.
173+
174+ - name : blank_unless_body_suppresses_error_text_strict
175+ template : " {% unless 5 > \" x\" %} {% endunless %}"
176+ error_mode : :strict
177+ render_errors : true
178+ expected : " "
165179 complexity : 750
166180 hint : |
167- In strict mode the blank-body suppression does NOT apply: an erroring
168- condition surfaces its error text even when the body is blank. Silent
169- failure is a lax-only compatibility behavior. (Reference liquid currently
170- suppresses here too — this spec defines the required strict behavior.)
181+ Whitespace-only unless bodies are blank in strict mode too. This documents
182+ the compatibility behavior that strict2 intentionally changes.
171183
172- - name : blank_for_body_shows_error_text_strict
184+ - name : blank_for_body_suppresses_error_text_strict
173185 template : " {% for i in (1..3) offset: xs %}{% endfor %}"
174186 environment :
175187 xs : " bad"
176188 error_mode : :strict
177189 render_errors : true
178- expected : " Liquid error (line 1): invalid integer "
190+ expected : " "
179191 complexity : 750
180192 hint : |
181- Same rule for loops: strict mode surfaces the invalid-offset error even
182- with a blank body.
193+ QUIRK: strict-mode inline-error suppression applies to blank for bodies.
194+ The invalid offset is evaluated, but because the body is blank the inline
195+ "Liquid error (...)" text is not written to output.
196+
197+ # ── strict2: blank bodies must not suppress inline errors ───────────────────
183198
184199- name : blank_if_body_shows_error_text_strict2
185200 template : " {% if 5 > \" x\" %}{% endif %}"
@@ -188,5 +203,151 @@ specs:
188203 expected : " Liquid error (line 1): comparison of Integer with String failed"
189204 complexity : 750
190205 hint : |
191- strict2 follows strict: no blank-body suppression. Every erroring
192- condition is visible.
206+ NEW STRICT2 CONTRACT: strict2 stops the historical blank-body suppression.
207+ The body is blank, but the condition still errors, so inline-error output
208+ must include the "Liquid error (...)" text.
209+
210+ - name : whitespace_if_body_shows_error_text_strict2
211+ template : " {% if 5 > \" x\" %} {% endif %}"
212+ error_mode : strict2
213+ render_errors : true
214+ expected : " Liquid error (line 1): comparison of Integer with String failed"
215+ complexity : 750
216+ hint : |
217+ NEW STRICT2 CONTRACT: whitespace-only text is blank for lax/strict
218+ compatibility, but strict2 must not hide the condition error text.
219+
220+ - name : assign_if_body_shows_error_text_strict2
221+ template : " {% if 5 > \" x\" %}{% assign a = 1 %}{% endif %}"
222+ error_mode : strict2
223+ render_errors : true
224+ expected : " Liquid error (line 1): comparison of Integer with String failed"
225+ complexity : 750
226+ hint : |
227+ NEW STRICT2 CONTRACT: assign nodes produce no output and used to make the
228+ body blank enough to suppress inline errors. strict2 should surface the
229+ error text anyway.
230+
231+ - name : comment_if_body_shows_error_text_strict2
232+ template : " {% if 5 > \" x\" %}{% comment %}c{% endcomment %}{% endif %}"
233+ error_mode : strict2
234+ render_errors : true
235+ expected : " Liquid error (line 1): comparison of Integer with String failed"
236+ complexity : 750
237+ hint : |
238+ NEW STRICT2 CONTRACT: comments are blank output, but strict2 should not use
239+ blankness as a reason to hide an erroring condition.
240+
241+ - name : capture_if_body_shows_error_text_strict2
242+ template : " {% if 5 > \" x\" %}{% capture c %}text{% endcapture %}{% endif %}"
243+ error_mode : strict2
244+ render_errors : true
245+ expected : " Liquid error (line 1): comparison of Integer with String failed"
246+ complexity : 750
247+ hint : |
248+ NEW STRICT2 CONTRACT: capture writes to a variable, not output. That made
249+ it blank for historical suppression, but strict2 should still render the
250+ condition error text.
251+
252+ - name : blank_unless_body_shows_error_text_strict2
253+ template : " {% unless 5 > \" x\" %} {% endunless %}"
254+ error_mode : strict2
255+ render_errors : true
256+ expected : " Liquid error (line 1): comparison of Integer with String failed"
257+ complexity : 750
258+ hint : |
259+ NEW STRICT2 CONTRACT: unless follows if. A blank unless body does not hide
260+ the error text from evaluating its condition.
261+
262+ - name : blank_for_body_shows_error_text_strict2
263+ template : " {% for i in (1..3) offset: xs %}{% endfor %}"
264+ environment :
265+ xs : " bad"
266+ error_mode : strict2
267+ render_errors : true
268+ expected : " Liquid error (line 1): invalid integer"
269+ complexity : 750
270+ hint : |
271+ NEW STRICT2 CONTRACT: for follows the same rule. A blank body should not
272+ hide an invalid offset error in strict2.
273+
274+ # ── Raised-error mode: blankness never swallows the exception ───────────────
275+
276+ - name : blank_if_body_raises_error_lax
277+ template : " {% if 5 > \" x\" %}{% endif %}"
278+ error_mode : :lax
279+ errors :
280+ render_error :
281+ - Liquid::ArgumentError
282+ - comparison of Integer with String failed
283+ complexity : 750
284+ hint : |
285+ Blank-body suppression only affects inline rendered error TEXT. With raised
286+ errors enabled, the evaluated condition raises even in lax mode.
287+
288+ - name : blank_if_body_raises_error_strict
289+ template : " {% if 5 > \" x\" %}{% endif %}"
290+ error_mode : :strict
291+ errors :
292+ render_error :
293+ - Liquid::ArgumentError
294+ - comparison of Integer with String failed
295+ complexity : 750
296+ hint : |
297+ Strict raised-error mode raises the condition error. There is no output
298+ suppression path because rendering aborts with the exception.
299+
300+ - name : blank_if_body_raises_error_strict2
301+ template : " {% if 5 > \" x\" %}{% endif %}"
302+ error_mode : strict2
303+ errors :
304+ render_error :
305+ - Liquid::ArgumentError
306+ - comparison of Integer with String failed
307+ complexity : 750
308+ hint : |
309+ strict2 also raises when strict_errors are enabled. The strict2 inline
310+ behavior differs from lax/strict, but raised-error behavior is the same:
311+ evaluated errors raise.
312+
313+ - name : blank_for_body_raises_error_lax
314+ template : " {% for i in (1..3) offset: xs %}{% endfor %}"
315+ environment :
316+ xs : " bad"
317+ error_mode : :lax
318+ errors :
319+ render_error :
320+ - Liquid::ArgumentError
321+ - invalid integer
322+ complexity : 750
323+ hint : |
324+ The invalid offset is evaluated before the loop body. Inline lax mode may
325+ hide the rendered text for blank bodies, but raised-error mode still raises.
326+
327+ - name : blank_for_body_raises_error_strict
328+ template : " {% for i in (1..3) offset: xs %}{% endfor %}"
329+ environment :
330+ xs : " bad"
331+ error_mode : :strict
332+ errors :
333+ render_error :
334+ - Liquid::ArgumentError
335+ - invalid integer
336+ complexity : 750
337+ hint : |
338+ Strict raised-error mode raises the invalid offset even though the body is
339+ blank.
340+
341+ - name : blank_for_body_raises_error_strict2
342+ template : " {% for i in (1..3) offset: xs %}{% endfor %}"
343+ environment :
344+ xs : " bad"
345+ error_mode : strict2
346+ errors :
347+ render_error :
348+ - Liquid::ArgumentError
349+ - invalid integer
350+ complexity : 750
351+ hint : |
352+ strict2 raised-error mode raises the invalid offset. The strict2 contract
353+ also surfaces this error in inline-error mode.
0 commit comments