From f5c7fa2240f518ccae8a538daad216d8850503c3 Mon Sep 17 00:00:00 2001 From: James Meng Date: Mon, 2 Dec 2024 18:22:03 -0800 Subject: [PATCH 01/10] --wip-- [skip ci] Add doc param tag --- .../grammar/liquid-html.ohm | 9 ++++++++- .../src/stage-1-cst.spec.ts | 20 +++++++++---------- .../liquid-html-parser/src/stage-1-cst.ts | 17 ++++++++++++++++ 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/packages/liquid-html-parser/grammar/liquid-html.ohm b/packages/liquid-html-parser/grammar/liquid-html.ohm index 5d6481c26..f9254d34d 100644 --- a/packages/liquid-html-parser/grammar/liquid-html.ohm +++ b/packages/liquid-html-parser/grammar/liquid-html.ohm @@ -389,7 +389,14 @@ LiquidStatement <: Liquid { } LiquidDoc <: Helpers { - Node := (TextNode)* + Node := (LiquidDocNode | TextNode)* + LiquidDocNode = + | descriptionNode + | paramNode + + descriptionNode = (~("@param") any)+ + paramNode = "@param" space + paramName = letter* } LiquidHTML <: Liquid { diff --git a/packages/liquid-html-parser/src/stage-1-cst.spec.ts b/packages/liquid-html-parser/src/stage-1-cst.spec.ts index 7f02c68a8..ace6e0e51 100644 --- a/packages/liquid-html-parser/src/stage-1-cst.spec.ts +++ b/packages/liquid-html-parser/src/stage-1-cst.spec.ts @@ -984,7 +984,10 @@ describe('Unit: Stage 1 (CST)', () => { it('should parse doc tags', () => { for (const { toCST, expectPath } of testCases) { - const testStr = `{% doc -%} Renders loading-spinner. {%- enddoc %}`; + const testStr = `{% doc -%} + Renders loading-spinner. + @param + {%- enddoc %}`; cst = toCST(testStr); expectPath(cst, '0.type').to.equal('LiquidRawTag'); @@ -998,15 +1001,12 @@ describe('Unit: Stage 1 (CST)', () => { expectPath(cst, '0.blockStartLocEnd').to.equal(0 + '{% doc -%}'.length); expectPath(cst, '0.blockEndLocStart').to.equal(testStr.length - '{%- enddoc %}'.length); expectPath(cst, '0.blockEndLocEnd').to.equal(testStr.length); - expectPath(cst, '0.children').to.deep.equal([ - { - locEnd: 35, - locStart: 11, - source: '{% doc -%} Renders loading-spinner. {%- enddoc %}', - type: 'TextNode', - value: 'Renders loading-spinner.', - }, - ]); + expectPath(cst, '0.children').to.have.lengthOf(2); + expectPath(cst, '0.children.0.type').to.equal('TextNode'); + // this is too permissive rn + expectPath(cst, '0.children.0.value').to.equal('Renders loading-spinner.'); + expectPath(cst, '0.children.1.type').to.equal('ParamNode'); + expectPath(cst, '0.children.1.value').to.equal('@param'); } }); diff --git a/packages/liquid-html-parser/src/stage-1-cst.ts b/packages/liquid-html-parser/src/stage-1-cst.ts index 4fdeffb8c..54fb6553d 100644 --- a/packages/liquid-html-parser/src/stage-1-cst.ts +++ b/packages/liquid-html-parser/src/stage-1-cst.ts @@ -83,6 +83,7 @@ export enum ConcreteNodeTypes { PaginateMarkup = 'PaginateMarkup', RenderVariableExpression = 'RenderVariableExpression', ContentForNamedArgument = 'ContentForNamedArgument', + ParamNode = 'ParamNode', } export const LiquidLiteralValues = { @@ -1315,6 +1316,22 @@ function toLiquidDocAST(source: string, matchingSource: string, offset: number) locEnd, source, }, + descriptionNode: { + type: ConcreteNodeTypes.TextNode, + value: function () { + return (this as any).sourceString; + }, + locStart, + locEnd, + source, + }, + paramNode: { + type: ConcreteNodeTypes.ParamNode, + value: 0, + locStart, + locEnd, + source, + }, }; return toAST(res, LiquidDocMappings); From 6ac5abfaf8e22971aa45e07f113dbb8c83991ea1 Mon Sep 17 00:00:00 2001 From: James Meng Date: Tue, 3 Dec 2024 15:02:46 -0800 Subject: [PATCH 02/10] Implement fallbackNode for LiquidDoc --- packages/liquid-html-parser/grammar/liquid-html.ohm | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/liquid-html-parser/grammar/liquid-html.ohm b/packages/liquid-html-parser/grammar/liquid-html.ohm index f9254d34d..c3e513292 100644 --- a/packages/liquid-html-parser/grammar/liquid-html.ohm +++ b/packages/liquid-html-parser/grammar/liquid-html.ohm @@ -391,11 +391,9 @@ LiquidStatement <: Liquid { LiquidDoc <: Helpers { Node := (LiquidDocNode | TextNode)* LiquidDocNode = - | descriptionNode - | paramNode + | fallbackNode - descriptionNode = (~("@param") any)+ - paramNode = "@param" space + fallbackNode = "@" paramName paramName = letter* } From e38d40fec15dca7a782c560c076581fcceff0405 Mon Sep 17 00:00:00 2001 From: James Meng Date: Tue, 3 Dec 2024 15:37:38 -0800 Subject: [PATCH 03/10] Enhance Liquid HTML Parser: Introduce paramNode and update CST tests - Added `paramNode` to the grammar for LiquidDoc, allowing for parameter definitions in doc tags. - Updated the parsing logic to recognize and handle `@param` syntax correctly. - Modified CST tests to validate the new structure, ensuring proper identification of `LiquidDocParamNode` and associated text nodes. - Refactored existing tests to align with the new parsing rules and improve accuracy. --- .../grammar/liquid-html.ohm | 6 +++-- .../src/stage-1-cst.spec.ts | 25 ++++++++++------- .../liquid-html-parser/src/stage-1-cst.ts | 27 +++++++------------ 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/packages/liquid-html-parser/grammar/liquid-html.ohm b/packages/liquid-html-parser/grammar/liquid-html.ohm index c3e513292..7cb62f317 100644 --- a/packages/liquid-html-parser/grammar/liquid-html.ohm +++ b/packages/liquid-html-parser/grammar/liquid-html.ohm @@ -391,10 +391,12 @@ LiquidStatement <: Liquid { LiquidDoc <: Helpers { Node := (LiquidDocNode | TextNode)* LiquidDocNode = + | paramNode | fallbackNode - fallbackNode = "@" paramName - paramName = letter* + fallbackNode = "@" anyExceptStar + paramNode = "@param" space* paramNodeName + paramNodeName = anyExceptStar } LiquidHTML <: Liquid { diff --git a/packages/liquid-html-parser/src/stage-1-cst.spec.ts b/packages/liquid-html-parser/src/stage-1-cst.spec.ts index ace6e0e51..b5f21991a 100644 --- a/packages/liquid-html-parser/src/stage-1-cst.spec.ts +++ b/packages/liquid-html-parser/src/stage-1-cst.spec.ts @@ -985,14 +985,15 @@ describe('Unit: Stage 1 (CST)', () => { it('should parse doc tags', () => { for (const { toCST, expectPath } of testCases) { const testStr = `{% doc -%} - Renders loading-spinner. - @param - {%- enddoc %}`; + @param asdf + @unsupported + {%- enddoc %}`; cst = toCST(testStr); + expectPath(cst, '0.type').to.equal('LiquidRawTag'); expectPath(cst, '0.name').to.equal('doc'); - expectPath(cst, '0.body').to.include('Renders loading-spinner'); + expectPath(cst, '0.body').to.include('@param asdf'); expectPath(cst, '0.whitespaceStart').to.equal(''); expectPath(cst, '0.whitespaceEnd').to.equal('-'); expectPath(cst, '0.delimiterWhitespaceStart').to.equal('-'); @@ -1001,12 +1002,16 @@ describe('Unit: Stage 1 (CST)', () => { expectPath(cst, '0.blockStartLocEnd').to.equal(0 + '{% doc -%}'.length); expectPath(cst, '0.blockEndLocStart').to.equal(testStr.length - '{%- enddoc %}'.length); expectPath(cst, '0.blockEndLocEnd').to.equal(testStr.length); - expectPath(cst, '0.children').to.have.lengthOf(2); - expectPath(cst, '0.children.0.type').to.equal('TextNode'); - // this is too permissive rn - expectPath(cst, '0.children.0.value').to.equal('Renders loading-spinner.'); - expectPath(cst, '0.children.1.type').to.equal('ParamNode'); - expectPath(cst, '0.children.1.value').to.equal('@param'); + + expectPath(cst, '0.children.0.type').to.equal('LiquidDocParamNode'); + expectPath(cst, '0.children.0.locStart').to.equal(testStr.indexOf('@param')); + expectPath(cst, '0.children.0.locEnd').to.equal(testStr.indexOf('asdf') + 'asdf'.length); + + expectPath(cst, '0.children.1.type').to.equal('TextNode'); + expectPath(cst, '0.children.1.locStart').to.equal(testStr.indexOf('@unsupported')); + expectPath(cst, '0.children.1.locEnd').to.equal( + testStr.indexOf('@unsupported') + '@unsupported'.length, + ); } }); diff --git a/packages/liquid-html-parser/src/stage-1-cst.ts b/packages/liquid-html-parser/src/stage-1-cst.ts index 54fb6553d..93f88789f 100644 --- a/packages/liquid-html-parser/src/stage-1-cst.ts +++ b/packages/liquid-html-parser/src/stage-1-cst.ts @@ -83,7 +83,8 @@ export enum ConcreteNodeTypes { PaginateMarkup = 'PaginateMarkup', RenderVariableExpression = 'RenderVariableExpression', ContentForNamedArgument = 'ContentForNamedArgument', - ParamNode = 'ParamNode', + + LiquidDocParamNode = 'LiquidDocParamNode', } export const LiquidLiteralValues = { @@ -106,6 +107,11 @@ export interface ConcreteBasicNode { locEnd: number; } +export interface ConcreteLiquidDocParamNode + extends ConcreteBasicNode { + name: string; +} + export interface ConcreteHtmlNodeBase extends ConcreteBasicNode { attrList?: ConcreteAttributeNode[]; } @@ -1307,27 +1313,14 @@ function toLiquidDocAST(source: string, matchingSource: string, offset: number) const LiquidDocMappings: Mapping = { Node: 0, - TextNode: { - type: ConcreteNodeTypes.TextNode, - value: function () { - return (this as any).sourceString; - }, + paramNode: { + type: ConcreteNodeTypes.LiquidDocParamNode, locStart, locEnd, source, }, - descriptionNode: { + fallbackNode: { type: ConcreteNodeTypes.TextNode, - value: function () { - return (this as any).sourceString; - }, - locStart, - locEnd, - source, - }, - paramNode: { - type: ConcreteNodeTypes.ParamNode, - value: 0, locStart, locEnd, source, From f8672f26ca37f7a62735de1a6e3373d3f7286cbd Mon Sep 17 00:00:00 2001 From: James Meng Date: Wed, 4 Dec 2024 09:25:23 -0800 Subject: [PATCH 04/10] Introduce LiquidDocCST and LiquidDocConcrete --- packages/liquid-html-parser/src/stage-1-cst.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/liquid-html-parser/src/stage-1-cst.ts b/packages/liquid-html-parser/src/stage-1-cst.ts index 93f88789f..b33777f43 100644 --- a/packages/liquid-html-parser/src/stage-1-cst.ts +++ b/packages/liquid-html-parser/src/stage-1-cst.ts @@ -447,10 +447,14 @@ export type LiquidConcreteNode = | ConcreteTextNode | ConcreteYamlFrontmatterNode; +export type LiquidDocConcreteNode = ConcreteLiquidDocParamNode; + export type LiquidHtmlCST = LiquidHtmlConcreteNode[]; export type LiquidCST = LiquidConcreteNode[]; +export type LiquidDocCST = LiquidDocConcreteNode[]; + interface Mapping { [k: string]: number | TemplateMapping | TopLevelFunctionMapping; } From f7fa51d929d024a85b2ad9cc962c1e733a984baf Mon Sep 17 00:00:00 2001 From: James Meng Date: Wed, 4 Dec 2024 09:27:41 -0800 Subject: [PATCH 05/10] Add liquidDocParam handling to stage2 AST - Updated the `toLiquidDocAST` function to include handling for `@param` syntax and fallback text node --- .../liquid-html-parser/src/stage-1-cst.ts | 13 +++++++++++ .../src/stage-2-ast.spec.ts | 23 +++++++++---------- .../liquid-html-parser/src/stage-2-ast.ts | 20 ++++++++++++++-- packages/liquid-html-parser/src/types.ts | 1 + 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/packages/liquid-html-parser/src/stage-1-cst.ts b/packages/liquid-html-parser/src/stage-1-cst.ts index b33777f43..242725e41 100644 --- a/packages/liquid-html-parser/src/stage-1-cst.ts +++ b/packages/liquid-html-parser/src/stage-1-cst.ts @@ -1317,14 +1317,27 @@ function toLiquidDocAST(source: string, matchingSource: string, offset: number) const LiquidDocMappings: Mapping = { Node: 0, + textNode: { + type: ConcreteNodeTypes.TextNode, + value: function () { + return (this as any).sourceString; + }, + locStart, + locEnd, + source, + }, paramNode: { type: ConcreteNodeTypes.LiquidDocParamNode, + name: 0, locStart, locEnd, source, }, fallbackNode: { type: ConcreteNodeTypes.TextNode, + value: function () { + return (this as any).sourceString; + }, locStart, locEnd, source, diff --git a/packages/liquid-html-parser/src/stage-2-ast.spec.ts b/packages/liquid-html-parser/src/stage-2-ast.spec.ts index 84848ccb2..ed1c2467f 100644 --- a/packages/liquid-html-parser/src/stage-2-ast.spec.ts +++ b/packages/liquid-html-parser/src/stage-2-ast.spec.ts @@ -1229,22 +1229,21 @@ describe('Unit: Stage 2 (AST)', () => { expectPath(ast, 'children.0.body.type').toEqual('RawMarkup'); expectPath(ast, 'children.0.body.nodes').toEqual([]); - ast = toLiquidAST(`{% doc -%} single line doc {%- enddoc %}`); + ast = toLiquidAST(` + {% doc -%} + @param asdf + @unsupported this node falls back to a text node + {%- enddoc %} + `); expectPath(ast, 'children.0.type').to.eql('LiquidRawTag'); expectPath(ast, 'children.0.name').to.eql('doc'); - expectPath(ast, 'children.0.body.value').to.eql(' single line doc '); - expectPath(ast, 'children.0.body.nodes.0.type').toEqual('TextNode'); + expectPath(ast, 'children.0.body.nodes.0.type').to.eql('LiquidDocParamNode'); + expectPath(ast, 'children.0.body.nodes.0.name').to.eql('@param'); - ast = toLiquidAST(`{% doc -%} - multi line doc - multi line doc - {%- enddoc %}`); - expectPath(ast, 'children.0.type').to.eql('LiquidRawTag'); - expectPath(ast, 'children.0.name').to.eql('doc'); - expectPath(ast, 'children.0.body.nodes.0.value').to.eql( - `multi line doc\n multi line doc`, + expectPath(ast, 'children.0.body.nodes.1.type').to.eql('TextNode'); + expectPath(ast, 'children.0.body.nodes.1.value').to.eql( + '@unsupported this node falls back to a text node', ); - expectPath(ast, 'children.0.body.nodes.0.type').toEqual('TextNode'); }); it('should parse unclosed tables with assignments', () => { diff --git a/packages/liquid-html-parser/src/stage-2-ast.ts b/packages/liquid-html-parser/src/stage-2-ast.ts index 15c7e61cb..370f08790 100644 --- a/packages/liquid-html-parser/src/stage-2-ast.ts +++ b/packages/liquid-html-parser/src/stage-2-ast.ts @@ -73,6 +73,7 @@ import { LiquidHtmlConcreteNode, ConcreteLiquidTagBaseCase, ConcreteLiquidTagContentForMarkup, + LiquidDocCST, } from './stage-1-cst'; import { Comparators, NamedTags, NodeTypes, nonTraversableProperties, Position } from './types'; import { assertNever, deepGet, dropLast } from './utils'; @@ -107,7 +108,8 @@ export type LiquidHtmlNode = | RenderVariableExpression | LiquidLogicalExpression | LiquidComparison - | TextNode; + | TextNode + | LiquidDocParamNode; /** The root node of all LiquidHTML ASTs. */ export interface DocumentNode extends ASTNode { @@ -754,6 +756,10 @@ export interface TextNode extends ASTNode { value: string; } +export interface LiquidDocParamNode extends ASTNode { + name: string; +} + export interface ASTNode { /** * The type of the node, as a string. @@ -1103,7 +1109,7 @@ export function cstToAst( } function buildAst( - cst: LiquidHtmlCST | LiquidCST | ConcreteAttributeNode[], + cst: LiquidHtmlCST | LiquidCST | LiquidDocCST | ConcreteAttributeNode[], options: ASTBuildOptions, ) { const builder = new ASTBuilder(cst[0].source); @@ -1268,6 +1274,16 @@ function buildAst( break; } + case ConcreteNodeTypes.LiquidDocParamNode: { + builder.push({ + type: NodeTypes.LiquidDocParamNode, + name: node.name, + position: position(node), + source: node.source, + }); + break; + } + default: { assertNever(node); } diff --git a/packages/liquid-html-parser/src/types.ts b/packages/liquid-html-parser/src/types.ts index 29648aebb..49efa1bf3 100644 --- a/packages/liquid-html-parser/src/types.ts +++ b/packages/liquid-html-parser/src/types.ts @@ -44,6 +44,7 @@ export enum NodeTypes { RawMarkup = 'RawMarkup', RenderMarkup = 'RenderMarkup', RenderVariableExpression = 'RenderVariableExpression', + LiquidDocParamNode = 'LiquidDocParamNode', } // These are officially supported with special node types From f6f2bb50f2ce394beefcd26ea999486296803d14 Mon Sep 17 00:00:00 2001 From: James Meng Date: Wed, 4 Dec 2024 11:42:24 -0800 Subject: [PATCH 06/10] Prettier - Add CSS Handling --- .../src/printer/preprocess/augment-with-css-properties.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/prettier-plugin-liquid/src/printer/preprocess/augment-with-css-properties.ts b/packages/prettier-plugin-liquid/src/printer/preprocess/augment-with-css-properties.ts index cc16285e5..4ad565c6d 100644 --- a/packages/prettier-plugin-liquid/src/printer/preprocess/augment-with-css-properties.ts +++ b/packages/prettier-plugin-liquid/src/printer/preprocess/augment-with-css-properties.ts @@ -128,6 +128,7 @@ function getCssDisplay(node: AugmentedNode, options: LiquidParserO case NodeTypes.RenderVariableExpression: case NodeTypes.LogicalExpression: case NodeTypes.Comparison: + case NodeTypes.LiquidDocParamNode: return 'should not be relevant'; default: @@ -233,6 +234,7 @@ function getNodeCssStyleWhiteSpace( case NodeTypes.RenderVariableExpression: case NodeTypes.LogicalExpression: case NodeTypes.Comparison: + case NodeTypes.LiquidDocParamNode: return 'should not be relevant'; default: From 81e0868c1cf756beffd7ea18c60039824ddf54bc Mon Sep 17 00:00:00 2001 From: James Meng Date: Wed, 4 Dec 2024 11:49:24 -0800 Subject: [PATCH 07/10] Enhance LiquidCompletionParams: Add handling for LiquidDocParamNode in LiquidCompletionParams --- .../src/completions/params/LiquidCompletionParams.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/theme-language-server-common/src/completions/params/LiquidCompletionParams.ts b/packages/theme-language-server-common/src/completions/params/LiquidCompletionParams.ts index 75d6e1e75..9ed9bcaf0 100644 --- a/packages/theme-language-server-common/src/completions/params/LiquidCompletionParams.ts +++ b/packages/theme-language-server-common/src/completions/params/LiquidCompletionParams.ts @@ -402,7 +402,8 @@ function findCurrentNode( case NodeTypes.TextNode: case NodeTypes.LiquidLiteral: case NodeTypes.String: - case NodeTypes.Number: { + case NodeTypes.Number: + case NodeTypes.LiquidDocParamNode: { break; } From 219095fa3911f526413ca7b33f071e6f11c20a0f Mon Sep 17 00:00:00 2001 From: James Meng Date: Thu, 5 Dec 2024 14:48:51 -0800 Subject: [PATCH 08/10] Add LiquidCST to union of LiquidHTMLCST types --- packages/liquid-html-parser/src/stage-1-cst.ts | 7 +++---- packages/liquid-html-parser/src/stage-2-ast.ts | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/liquid-html-parser/src/stage-1-cst.ts b/packages/liquid-html-parser/src/stage-1-cst.ts index 242725e41..9b8b9b4d8 100644 --- a/packages/liquid-html-parser/src/stage-1-cst.ts +++ b/packages/liquid-html-parser/src/stage-1-cst.ts @@ -447,13 +447,12 @@ export type LiquidConcreteNode = | ConcreteTextNode | ConcreteYamlFrontmatterNode; -export type LiquidDocConcreteNode = ConcreteLiquidDocParamNode; - -export type LiquidHtmlCST = LiquidHtmlConcreteNode[]; +export type LiquidHtmlCST = LiquidHtmlConcreteNode[] | LiquidDocCST; export type LiquidCST = LiquidConcreteNode[]; -export type LiquidDocCST = LiquidDocConcreteNode[]; +type LiquidDocCST = LiquidDocConcreteNode[]; +export type LiquidDocConcreteNode = ConcreteLiquidDocParamNode; interface Mapping { [k: string]: number | TemplateMapping | TopLevelFunctionMapping; diff --git a/packages/liquid-html-parser/src/stage-2-ast.ts b/packages/liquid-html-parser/src/stage-2-ast.ts index 370f08790..bc6dced7b 100644 --- a/packages/liquid-html-parser/src/stage-2-ast.ts +++ b/packages/liquid-html-parser/src/stage-2-ast.ts @@ -73,7 +73,6 @@ import { LiquidHtmlConcreteNode, ConcreteLiquidTagBaseCase, ConcreteLiquidTagContentForMarkup, - LiquidDocCST, } from './stage-1-cst'; import { Comparators, NamedTags, NodeTypes, nonTraversableProperties, Position } from './types'; import { assertNever, deepGet, dropLast } from './utils'; @@ -1109,7 +1108,7 @@ export function cstToAst( } function buildAst( - cst: LiquidHtmlCST | LiquidCST | LiquidDocCST | ConcreteAttributeNode[], + cst: LiquidHtmlCST | LiquidCST | ConcreteAttributeNode[], options: ASTBuildOptions, ) { const builder = new ASTBuilder(cst[0].source); From 68227c49fc2e71ce1d5e0bd0c59b9e8a947321bd Mon Sep 17 00:00:00 2001 From: James Meng Date: Thu, 5 Dec 2024 14:49:17 -0800 Subject: [PATCH 09/10] Add LiquidDocParamNode case to print function --- .../prettier-plugin-liquid/src/printer/printer-liquid-html.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/prettier-plugin-liquid/src/printer/printer-liquid-html.ts b/packages/prettier-plugin-liquid/src/printer/printer-liquid-html.ts index 3905c8008..146812c81 100644 --- a/packages/prettier-plugin-liquid/src/printer/printer-liquid-html.ts +++ b/packages/prettier-plugin-liquid/src/printer/printer-liquid-html.ts @@ -547,6 +547,10 @@ function printNode( return [...doc, ...lookups]; } + case NodeTypes.LiquidDocParamNode: { + return node.name; + } + default: { return assertNever(node); } From 0f17fef487b299b2a17ff9a81838bc580dd0aa94 Mon Sep 17 00:00:00 2001 From: James Meng Date: Wed, 4 Dec 2024 16:51:16 -0800 Subject: [PATCH 10/10] Add basic prettier support for doc tag --- packages/liquid-html-parser/src/stage-1-cst.ts | 2 ++ packages/liquid-html-parser/src/stage-2-ast.ts | 2 ++ .../src/printer/print/liquid.ts | 12 +++++++++++- .../src/printer/printer-liquid-html.ts | 9 ++++++++- .../src/test/liquid-doc/fixed.liquid | 9 +++++++++ .../src/test/liquid-doc/index.liquid | 9 +++++++++ .../src/test/liquid-doc/index.spec.ts | 7 +++++++ 7 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 packages/prettier-plugin-liquid/src/test/liquid-doc/fixed.liquid create mode 100644 packages/prettier-plugin-liquid/src/test/liquid-doc/index.liquid create mode 100644 packages/prettier-plugin-liquid/src/test/liquid-doc/index.spec.ts diff --git a/packages/liquid-html-parser/src/stage-1-cst.ts b/packages/liquid-html-parser/src/stage-1-cst.ts index 9b8b9b4d8..40b0d12cb 100644 --- a/packages/liquid-html-parser/src/stage-1-cst.ts +++ b/packages/liquid-html-parser/src/stage-1-cst.ts @@ -110,6 +110,7 @@ export interface ConcreteBasicNode { export interface ConcreteLiquidDocParamNode extends ConcreteBasicNode { name: string; + value: string; } export interface ConcreteHtmlNodeBase extends ConcreteBasicNode { @@ -1328,6 +1329,7 @@ function toLiquidDocAST(source: string, matchingSource: string, offset: number) paramNode: { type: ConcreteNodeTypes.LiquidDocParamNode, name: 0, + value: 2, locStart, locEnd, source, diff --git a/packages/liquid-html-parser/src/stage-2-ast.ts b/packages/liquid-html-parser/src/stage-2-ast.ts index bc6dced7b..a89defbea 100644 --- a/packages/liquid-html-parser/src/stage-2-ast.ts +++ b/packages/liquid-html-parser/src/stage-2-ast.ts @@ -757,6 +757,7 @@ export interface TextNode extends ASTNode { export interface LiquidDocParamNode extends ASTNode { name: string; + value: string; } export interface ASTNode { @@ -1279,6 +1280,7 @@ function buildAst( name: node.name, position: position(node), source: node.source, + value: node.value, }); break; } diff --git a/packages/prettier-plugin-liquid/src/printer/print/liquid.ts b/packages/prettier-plugin-liquid/src/printer/print/liquid.ts index 778c7262e..ad1ff03bc 100644 --- a/packages/prettier-plugin-liquid/src/printer/print/liquid.ts +++ b/packages/prettier-plugin-liquid/src/printer/print/liquid.ts @@ -1,4 +1,4 @@ -import { NodeTypes, NamedTags, isBranchedTag } from '@shopify/liquid-html-parser'; +import { NodeTypes, NamedTags, isBranchedTag, RawMarkup } from '@shopify/liquid-html-parser'; import { Doc, doc } from 'prettier'; import { @@ -490,6 +490,16 @@ export function printLiquidRawTag( return [blockStart, ...body, blockEnd]; } +export function printLiquidDoc( + path: AstPath, + _options: LiquidParserOptions, + print: LiquidPrinter, + _args: LiquidPrinterArgs, +) { + const body = path.map((p: any) => print(p), 'nodes'); + return [indent([hardline, body]), hardline]; +} + function innerLeadingWhitespace(node: LiquidTag | LiquidBranch) { if (!node.firstChild) { if (node.isDanglingWhitespaceSensitive && node.hasDanglingWhitespace) { diff --git a/packages/prettier-plugin-liquid/src/printer/printer-liquid-html.ts b/packages/prettier-plugin-liquid/src/printer/printer-liquid-html.ts index 146812c81..92797d8c6 100644 --- a/packages/prettier-plugin-liquid/src/printer/printer-liquid-html.ts +++ b/packages/prettier-plugin-liquid/src/printer/printer-liquid-html.ts @@ -1,5 +1,6 @@ import { getConditionalComment, + LiquidDocParamNode, NodeTypes, Position, RawMarkupKinds, @@ -30,6 +31,7 @@ import { LiquidTag, LiquidVariableOutput, nonTraversableProperties, + RawMarkup, TextNode, } from '../types'; import { assertNever } from '../utils'; @@ -40,6 +42,7 @@ import { printChildren } from './print/children'; import { printElement } from './print/element'; import { printLiquidBranch, + printLiquidDoc, printLiquidRawTag, printLiquidTag, printLiquidVariableOutput, @@ -210,6 +213,10 @@ function printNode( } case NodeTypes.RawMarkup: { + if (node.parentNode?.name === 'doc') { + return printLiquidDoc(path as AstPath, options, print, args); + } + const isRawMarkupIdentationSensitive = () => { switch (node.kind) { case RawMarkupKinds.typescript: @@ -548,7 +555,7 @@ function printNode( } case NodeTypes.LiquidDocParamNode: { - return node.name; + return [node.name, ' ', node.value]; } default: { diff --git a/packages/prettier-plugin-liquid/src/test/liquid-doc/fixed.liquid b/packages/prettier-plugin-liquid/src/test/liquid-doc/fixed.liquid new file mode 100644 index 000000000..c11d85f6f --- /dev/null +++ b/packages/prettier-plugin-liquid/src/test/liquid-doc/fixed.liquid @@ -0,0 +1,9 @@ +It should indent the body +{% doc %} + @param body +{% enddoc %} + +It should not dedent to root +{% doc %} + @param body +{% enddoc %} diff --git a/packages/prettier-plugin-liquid/src/test/liquid-doc/index.liquid b/packages/prettier-plugin-liquid/src/test/liquid-doc/index.liquid new file mode 100644 index 000000000..45638eb76 --- /dev/null +++ b/packages/prettier-plugin-liquid/src/test/liquid-doc/index.liquid @@ -0,0 +1,9 @@ +It should indent the body +{% doc %} +@param body +{% enddoc %} + +It should not dedent to root +{% doc %} + @param body +{% enddoc %} diff --git a/packages/prettier-plugin-liquid/src/test/liquid-doc/index.spec.ts b/packages/prettier-plugin-liquid/src/test/liquid-doc/index.spec.ts new file mode 100644 index 000000000..bf0e16d16 --- /dev/null +++ b/packages/prettier-plugin-liquid/src/test/liquid-doc/index.spec.ts @@ -0,0 +1,7 @@ +import { test } from 'vitest'; +import { assertFormattedEqualsFixed } from '../test-helpers'; +import * as path from 'path'; + +test('Unit: liquid-doc', async () => { + await assertFormattedEqualsFixed(__dirname); +});