Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-unused-assign-inline-liquid-style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/liquid-html-parser': patch
---

Fix false-positive UnusedAssign warnings for variables used inside a `style` block within an inline `{% liquid %}` tag. The inline-liquid raw-tag CST mapping parsed every raw-tag body as plain text, so variable references inside `{% liquid ... style ... echo foo ... endstyle %}` never became AST nodes and checks that walk the tree saw no usage. The mapping now mirrors the top-level `liquidRawTagImpl` behavior: `schema` and `raw` remain text, all other raw tags are parsed as Liquid so references inside `style` and friends are preserved. Fixes Shopify/theme-tools#465.
40 changes: 32 additions & 8 deletions packages/liquid-html-parser/src/stage-1-cst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1212,14 +1212,38 @@ function toCST<T>(
name: 0,
body: 4,
children(nodes) {
return toCST(
source,
grammars,
TextNodeGrammar,
['HelperMappings'],
nodes[4].sourceString,
offset + nodes[4].source.startIdx,
);
const nameNode = nodes[0];
const rawMarkupStringNode = nodes[4];
switch (nameNode.sourceString) {
// {% schema %} parses its content as a string and should not be visited
case 'schema':
// {% raw %} accepts syntax errors, we shouldn't try to parse that
case 'raw': {
return toCST(
source,
grammars,
TextNodeGrammar,
['HelperMappings'],
rawMarkupStringNode.sourceString,
offset + rawMarkupStringNode.source.startIdx,
);
}

// Match the top-level liquidRawTagImpl behavior so variables
// referenced inside {% liquid ... style ... endstyle %} are
// detected as used by checks that walk the AST. The body is
// still inline-liquid, so re-parse with LiquidStatement.
default: {
return toCST(
source,
grammars,
grammars.LiquidStatement,
['HelperMappings', 'LiquidMappings', 'LiquidStatement'],
rawMarkupStringNode.sourceString,
offset + rawMarkupStringNode.source.startIdx,
);
}
}
},
whitespaceStart: null,
whitespaceEnd: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,25 @@ describe('Module: UnusedAssign', () => {
}
});

it('should not report unused assigns for variables used inside a style block within {% liquid %}', async () => {
const sourceCode = `
{%- liquid
assign shopName = shop.name
capture example
echo 'Shopify'
endcapture

style
echo example
echo shopName
endstyle
-%}
`;

const offenses = await runLiquidCheck(UnusedAssign, sourceCode);
expect(offenses).to.be.empty;
});

it('should not report unused assigns for things used in a HTML raw-like tag', async () => {
const tags = ['style', 'script'];
for (const tag of tags) {
Expand Down
Loading