From af297bab6a82c864eacfae3d186d7ba5a92a07e0 Mon Sep 17 00:00:00 2001 From: stephanie chou Date: Tue, 29 Sep 2026 12:21:54 -0700 Subject: [PATCH 1/4] Parse section as a standalone tag Ruby Liquid has no block form for section, but the parser treated it as a hybrid tag and scanned forward for a matching endsection on every section tag (both in documents and in {% liquid %} bodies). Files with many section tags parsed in quadratic time. Make section a plain TagKind.Tag and remove the hybrid tag kind. Theme Check still reports a stray endsection as "Unknown tag 'endsection'" by mapping the parser error. --- .changeset/standalone-section-tag.md | 6 + .../liquid-html-parser/specs/architecture.md | 32 +-- .../specs/recursive-descent.md | 1 - packages/liquid-html-parser/src/ast.test.ts | 41 +--- .../src/document/liquid-hybrid.test.ts | 201 ------------------ .../src/document/liquid-hybrid.ts | 96 --------- .../src/document/liquid-lines.ts | 64 ------ .../src/document/liquid-tags.ts | 6 +- .../src/environment.test.ts | 9 - .../liquid-html-parser/src/environment.ts | 1 - .../liquid-html-parser/src/tag-definitions.ts | 9 +- .../src/tags/section.test.ts | 4 +- .../liquid-html-parser/src/tags/section.ts | 6 +- .../src/checks/liquid-syntax-error/index.ts | 3 +- .../src/checks/liquid-syntax-error/section.ts | 31 ++- 15 files changed, 47 insertions(+), 463 deletions(-) create mode 100644 .changeset/standalone-section-tag.md delete mode 100644 packages/liquid-html-parser/src/document/liquid-hybrid.test.ts delete mode 100644 packages/liquid-html-parser/src/document/liquid-hybrid.ts diff --git a/.changeset/standalone-section-tag.md b/.changeset/standalone-section-tag.md new file mode 100644 index 000000000..586c06e8d --- /dev/null +++ b/.changeset/standalone-section-tag.md @@ -0,0 +1,6 @@ +--- +'@shopify/liquid-html-parser': patch +'@shopify/theme-check-common': patch +--- + +Parse `section` as a standalone tag. Removes the hybrid block form, whose forward scan for `{% endsection %}` made files with many `section` tags parse in quadratic time. diff --git a/packages/liquid-html-parser/specs/architecture.md b/packages/liquid-html-parser/specs/architecture.md index a56c2c9e7..bb45a8cb0 100644 --- a/packages/liquid-html-parser/specs/architecture.md +++ b/packages/liquid-html-parser/specs/architecture.md @@ -37,7 +37,6 @@ src/ tokenizer.ts # Source -> Token[] (modal: HTML tag context with =, ", ') html.ts # HTML element, void, self-closing, raw node, comment, doctype, dangling marker parsing liquid-blocks.ts # Block tag body parsing, branched block parsing, finalizeBranch - liquid-hybrid.ts # Hybrid tag parsing (section standalone/block detection) liquid-lines.ts # {% liquid %} line-based parsing, parseLiquidStatement liquid-raw.ts # Raw tag body parsing, Liquid-in-range parsing liquid-tags.ts # Tag dispatch: environment lookup, MarkupParser creation, tolerant fallback @@ -110,7 +109,6 @@ document/parser.ts (DocumentParser) | - node-dispatch.ts: token-type switch -> parse function routing | - liquid-tags.ts: tag dispatch (environment lookup, MarkupParser creation) | - liquid-blocks.ts: block body + branched block parsing - | - liquid-hybrid.ts: hybrid tag (section) standalone/block detection | - liquid-raw.ts: raw tag body extraction + Liquid-in-range parsing | - liquid-variable-output.ts: {{ }} variable output | - liquid-lines.ts: {% liquid %} line-based parsing @@ -156,7 +154,6 @@ The parser calls these utilities while building the AST. | `document/tree-builder.ts` | Utility functions for the parser: `filterChildren`, `ChildFilterMode`, `mergeAdjacentTextNodes`, `mergeAdjacentTextNodesTrimmed`, `mergeAdjacentTextNodesStripEdges`, `compoundNamesMatch`. Pure functions, zero parser state. | Tokenizing. Parsing. Dispatch. | | `document/html.ts` | HTML element parsing (open/close matching, unclosed element handling), void elements, self-closing elements, raw HTML nodes (`