diff --git a/grammar/liquid-html.ohm b/grammar/liquid-html.ohm index bfec19d8..3c2802e1 100644 --- a/grammar/liquid-html.ohm +++ b/grammar/liquid-html.ohm @@ -53,6 +53,7 @@ Liquid <: Helpers { | liquidTagDecrement | liquidTagEcho | liquidTagElse + | liquidTagElseif | liquidTagElsif | liquidTagInclude | liquidTagIncrement @@ -157,6 +158,7 @@ Liquid <: Helpers { liquidTagOpenIf = liquidTagOpenRule<"if", liquidTagOpenConditionalMarkup> liquidTagOpenUnless = liquidTagOpenRule<"unless", liquidTagOpenConditionalMarkup> liquidTagElsif = liquidTagRule<"elsif", liquidTagOpenConditionalMarkup> + liquidTagElseif = liquidTagRule<"elseif", liquidTagOpenConditionalMarkup> liquidTagBreak = liquidTagRule<"break", empty> liquidTagContinue = liquidTagRule<"continue", empty> diff --git a/src/constants.evaluate.ts b/src/constants.evaluate.ts index a3b76349..29b165c1 100644 --- a/src/constants.evaluate.ts +++ b/src/constants.evaluate.ts @@ -49,6 +49,7 @@ export const CSS_DISPLAY_LIQUID_TAGS: Record = { if: 'inline', unless: 'inline', else: 'inline', + elseif: 'inline', elsif: 'inline', case: 'inline', when: 'inline', diff --git a/src/parser/grammar.ts b/src/parser/grammar.ts index 4ed9fc3e..cf6bd941 100644 --- a/src/parser/grammar.ts +++ b/src/parser/grammar.ts @@ -51,7 +51,6 @@ export const TAGS_WITHOUT_MARKUP = [ 'style', 'schema', 'javascript', - 'else', 'break', 'continue', 'comment', diff --git a/src/parser/stage-1-cst.ts b/src/parser/stage-1-cst.ts index 7452844c..df480e91 100644 --- a/src/parser/stage-1-cst.ts +++ b/src/parser/stage-1-cst.ts @@ -231,6 +231,8 @@ export interface ConcreteLiquidTagOpenUnless NamedTags.unless, ConcreteLiquidCondition[] > {} +export interface ConcreteLiquidTagElseif + extends ConcreteLiquidTagNode {} export interface ConcreteLiquidTagElsif extends ConcreteLiquidTagNode {} @@ -296,6 +298,7 @@ export type ConcreteLiquidTagNamed = | ConcreteLiquidTagEcho | ConcreteLiquidTagIncrement | ConcreteLiquidTagDecrement + | ConcreteLiquidTagElseif | ConcreteLiquidTagElsif | ConcreteLiquidTagInclude | ConcreteLiquidTagLayout @@ -709,6 +712,7 @@ function toCST( liquidTagWhenMarkup: 0, liquidTagOpenIf: 0, liquidTagOpenUnless: 0, + liquidTagElseif: 0, liquidTagElsif: 0, liquidTagElse: 0, liquidTagOpenConditionalMarkup: 0, diff --git a/src/parser/stage-2-ast.ts b/src/parser/stage-2-ast.ts index 96e2f881..317e2da2 100644 --- a/src/parser/stage-2-ast.ts +++ b/src/parser/stage-2-ast.ts @@ -272,6 +272,8 @@ export interface LiquidTagTablerow export interface LiquidTagIf extends LiquidTagConditional {} export interface LiquidTagUnless extends LiquidTagConditional {} +export interface LiquidBranchElseif + extends LiquidBranchNode {} export interface LiquidBranchElsif extends LiquidBranchNode {} export interface LiquidTagConditional @@ -335,7 +337,10 @@ export type LiquidBranch = | LiquidBranchUnnamed | LiquidBranchBaseCase | LiquidBranchNamed; -export type LiquidBranchNamed = LiquidBranchElsif | LiquidBranchWhen; +export type LiquidBranchNamed = + | LiquidBranchElseif + | LiquidBranchElsif + | LiquidBranchWhen; interface LiquidBranchNode extends ASTNode { @@ -561,16 +566,16 @@ function isLiquidBranchDisguisedAsTag( ): node is LiquidTagBaseCase { return ( node.type === NodeTypes.LiquidTag && - ['else', 'elsif', 'when'].includes(node.name) + ['else', 'elseif', 'elsif', 'when'].includes(node.name) ); } function isConcreteLiquidBranchDisguisedAsTag( node: LiquidHtmlConcreteNode, -): node is ConcreteLiquidNode & { name: 'else' | 'eslif' | 'when' } { +): node is ConcreteLiquidNode & { name: 'else' | 'elseif' | 'eslif' | 'when' } { return ( node.type === ConcreteNodeTypes.LiquidTag && - ['else', 'eslif', 'when'].includes(node.name) + ['else', 'elseif', 'eslif', 'when'].includes(node.name) ); } @@ -1184,6 +1189,7 @@ function toNamedLiquidTag( }; } + case NamedTags.elseif: case NamedTags.elsif: { return { ...liquidBranchBaseAttributes(node), diff --git a/src/printer/print/liquid.ts b/src/printer/print/liquid.ts index 0f359dc9..47f5e027 100644 --- a/src/printer/print/liquid.ts +++ b/src/printer/print/liquid.ts @@ -214,6 +214,7 @@ function printNamedLiquidBlockStart( } case NamedTags.if: + case NamedTags.elseif: case NamedTags.elsif: case NamedTags.unless: { const trailingWhitespace = [ diff --git a/src/types.ts b/src/types.ts index e409e804..70c0b260 100644 --- a/src/types.ts +++ b/src/types.ts @@ -76,6 +76,7 @@ export enum NamedTags { cycle = 'cycle', decrement = 'decrement', echo = 'echo', + elseif = 'elseif', elsif = 'elsif', for = 'for', form = 'form', diff --git a/test/issue-6/fixed.liquid b/test/issue-6/fixed.liquid new file mode 100644 index 00000000..0017a83d --- /dev/null +++ b/test/issue-6/fixed.liquid @@ -0,0 +1,15 @@ +It should not remove the "if" from "else if" tags +{% if condition1 %} + Condition1 is truthy +{% else if condition2 %} + Condition2 is truthy +{% endif %} + +It should format elseif tags +{% if condition1 %} + Condition1 is truthy +{% elseif condition2 %} + Condition2 is truthy +{% else %} + Something else +{% endif %} diff --git a/test/issue-6/index.liquid b/test/issue-6/index.liquid new file mode 100644 index 00000000..4651b2c1 --- /dev/null +++ b/test/issue-6/index.liquid @@ -0,0 +1,15 @@ +It should not remove the "if" from "else if" tags +{% if condition1 %} + Condition1 is truthy +{% else if condition2 %} + Condition2 is truthy +{% endif %} + +It should format elseif tags +{% if condition1 %} + Condition1 is truthy + {% elseif condition2 %} + Condition2 is truthy +{% else %} + Something else +{% endif %} diff --git a/test/issue-6/index.spec.ts b/test/issue-6/index.spec.ts new file mode 100644 index 00000000..4587999a --- /dev/null +++ b/test/issue-6/index.spec.ts @@ -0,0 +1,6 @@ +import { assertFormattedEqualsFixed } from '../test-helpers'; +import * as path from 'path'; + +describe(`Unit: ${path.basename(__dirname)}`, () => { + assertFormattedEqualsFixed(__dirname); +}); diff --git a/test/liquid-tag-else/fixed.liquid b/test/liquid-tag-else/fixed.liquid index d8730940..8a8ecdfb 100644 --- a/test/liquid-tag-else/fixed.liquid +++ b/test/liquid-tag-else/fixed.liquid @@ -12,9 +12,18 @@ printWidth: 1 hello {% endif %} -It should strip extraneous args +It should preserve extraneous args to avoid silent code changes printWidth: 1 {% if false %} -{% else %} +{% else huh?? %} hello {% endif %} + +It should preserve 'else if' syntax to avoid removing expressions +printWidth: 80 +{% if condition1 %} + Condition1 is truthy +{% else if condition2 %} + Condition2 is truthy +{% endif %} + diff --git a/test/liquid-tag-else/index.liquid b/test/liquid-tag-else/index.liquid index eb2e6cf7..65457a9b 100644 --- a/test/liquid-tag-else/index.liquid +++ b/test/liquid-tag-else/index.liquid @@ -6,6 +6,15 @@ It should support missing whitespace printWidth: 1 {% if false %} {%-else-%} hello {% endif %} -It should strip extraneous args +It should preserve extraneous args to avoid silent code changes printWidth: 1 {% if false %} {% else huh?? %} hello {% endif %} + +It should preserve 'else if' syntax to avoid removing expressions +printWidth: 80 +{% if condition1 %} +Condition1 is truthy +{% else if condition2 %} +Condition2 is truthy +{% endif %} + diff --git a/test/liquid-tag-elseif/fixed.liquid b/test/liquid-tag-elseif/fixed.liquid new file mode 100644 index 00000000..2d4e6b61 --- /dev/null +++ b/test/liquid-tag-elseif/fixed.liquid @@ -0,0 +1,31 @@ +It should correctly format elseif statements at same level as if/else +{% if condition1 %} + Condition1 is truthy +{% elseif condition2 %} + Condition2 is truthy +{% else %} + Something else +{% endif %} + +It should handle multiple elseif branches +{% if condition1 %} + Result 1 +{% elseif condition2 %} + Result 2 +{% elseif condition3 %} + Result 3 +{% else %} + Default result +{% endif %} + +It should handle complex conditions in elseif +{% if x > 10 %} + Large +{% elseif x > 5 and x <= 10 %} + Medium +{% elseif x > 0 %} + Small +{% else %} + Zero or negative +{% endif %} + diff --git a/test/liquid-tag-elseif/index.liquid b/test/liquid-tag-elseif/index.liquid new file mode 100644 index 00000000..eead11ab --- /dev/null +++ b/test/liquid-tag-elseif/index.liquid @@ -0,0 +1,31 @@ +It should correctly format elseif statements at same level as if/else +{% if condition1 %} +Condition1 is truthy +{% elseif condition2 %} +Condition2 is truthy +{% else %} +Something else +{% endif %} + +It should handle multiple elseif branches +{% if condition1 %} +Result 1 +{% elseif condition2 %} +Result 2 +{% elseif condition3 %} +Result 3 +{% else %} +Default result +{% endif %} + +It should handle complex conditions in elseif +{% if x > 10 %} +Large +{% elseif x > 5 and x <= 10 %} +Medium +{% elseif x > 0 %} +Small +{% else %} +Zero or negative +{% endif %} + diff --git a/test/liquid-tag-elseif/index.spec.ts b/test/liquid-tag-elseif/index.spec.ts new file mode 100644 index 00000000..4587999a --- /dev/null +++ b/test/liquid-tag-elseif/index.spec.ts @@ -0,0 +1,6 @@ +import { assertFormattedEqualsFixed } from '../test-helpers'; +import * as path from 'path'; + +describe(`Unit: ${path.basename(__dirname)}`, () => { + assertFormattedEqualsFixed(__dirname); +}); diff --git a/test/liquid-tag-no-argument/fixed.liquid b/test/liquid-tag-no-argument/fixed.liquid index 9391b3f3..a1b21380 100644 --- a/test/liquid-tag-no-argument/fixed.liquid +++ b/test/liquid-tag-no-argument/fixed.liquid @@ -10,8 +10,8 @@ It should strip arguments from javascript tags {% javascript %} {% endjavascript %} -It should strip arguments from else tags -{% if cond %}{% else %}{% endif %} +It should preserve arguments from else tags to avoid silent code changes +{% if cond %}{% else what %}{% endif %} It should strip arguments from break tags {% break %} diff --git a/test/liquid-tag-no-argument/index.liquid b/test/liquid-tag-no-argument/index.liquid index 4fcd4ea5..08bff7b1 100644 --- a/test/liquid-tag-no-argument/index.liquid +++ b/test/liquid-tag-no-argument/index.liquid @@ -10,7 +10,7 @@ It should strip arguments from javascript tags {% javascript what %} {% endjavascript %} -It should strip arguments from else tags +It should preserve arguments from else tags to avoid silent code changes {% if cond %}{% else what %}{% endif %} It should strip arguments from break tags