diff --git a/.changeset/little-boxes-shave.md b/.changeset/little-boxes-shave.md new file mode 100644 index 000000000..c80027861 --- /dev/null +++ b/.changeset/little-boxes-shave.md @@ -0,0 +1,5 @@ +--- +'@shopify/theme-check-common': patch +--- + +Allow Liquid in "liquid" input type diff --git a/packages/theme-check-common/src/checks/liquid-free-settings/index.spec.ts b/packages/theme-check-common/src/checks/liquid-free-settings/index.spec.ts index e58352523..c4d27b11c 100644 --- a/packages/theme-check-common/src/checks/liquid-free-settings/index.spec.ts +++ b/packages/theme-check-common/src/checks/liquid-free-settings/index.spec.ts @@ -51,6 +51,29 @@ describe('LiquidFreeSettings validation', () => { expect(offenses).to.have.length(0); }); + it(`should not report errors for valid settings with liquid type field in ${path} bucket`, async () => { + const theme: MockTheme = { + [`${path}/test-section.liquid`]: ` + {% schema %} + { + "name": "Section name", + "settings": [ + { + "id": "text_value", + "type": "liquid", + "label": "Text Value", + "default": "{% render 'block' %}" + } + ] + } + {% endschema %} + `, + }; + + const offenses = await check(theme, [LiquidFreeSettings]); + expect(offenses).to.have.length(0); + }); + it(`should report an error when settings value contains Liquid logic in ${path} bucket`, async () => { const theme: MockTheme = { [`${path}/test-section.liquid`]: ` diff --git a/packages/theme-check-common/src/checks/liquid-free-settings/index.ts b/packages/theme-check-common/src/checks/liquid-free-settings/index.ts index 592da62ae..ff74e6e1b 100644 --- a/packages/theme-check-common/src/checks/liquid-free-settings/index.ts +++ b/packages/theme-check-common/src/checks/liquid-free-settings/index.ts @@ -40,21 +40,27 @@ export const LiquidFreeSettings: LiquidCheckDefinition = { visit(jsonFile, { Property(schemaNode, ancestors) { - if (isInArrayWithParentKey(ancestors, 'settings') && isLiteralNode(schemaNode.value)) { - const { value, loc } = schemaNode.value; - const propertyValue = schemaNode.key.value; - if ( - typeof value === 'string' && - propertyValue !== 'visible_if' && - value.includes('{%') && - value.includes('%}') - ) { - context.report({ - message: 'Settings values cannot contain liquid logic.', - startIndex: node.blockStartPosition.end + loc!.start.offset, - endIndex: node.blockStartPosition.end + loc!.end.offset, - }); - } + if ( + !isInArrayWithParentKey(ancestors, 'settings') || + !isLiteralNode(schemaNode.value) || + isLiquidType(ancestors) + ) { + return; + } + + const { value, loc } = schemaNode.value; + const propertyValue = schemaNode.key.value; + if ( + typeof value === 'string' && + propertyValue !== 'visible_if' && + value.includes('{%') && + value.includes('%}') + ) { + context.report({ + message: 'Settings values cannot contain liquid logic.', + startIndex: node.blockStartPosition.end + loc!.start.offset, + endIndex: node.blockStartPosition.end + loc!.end.offset, + }); } }, }); @@ -67,6 +73,22 @@ function isLiteralNode(node: JSONNode): node is LiteralNode { return node.type === 'Literal'; } +function isLiquidType(ancestors: JSONNode[]): boolean { + return ancestors.some((ancestor) => { + if (ancestor.type !== 'Object') { + return false; + } + + return ancestor.children.some(({ key, value }) => { + if (key.value !== 'type' || !isLiteralNode(value)) { + return false; + } + + return value.value === 'liquid'; + }); + }); +} + function isInArrayWithParentKey(ancestors: JSONNode[], parentKey: string): boolean { return ancestors.some((ancestor, index) => { const parent = ancestors[index - 1];