Skip to content

Commit 4ae0d1b

Browse files
committed
feat: Add multiline set functionality.
1 parent 9b3e2cf commit 4ae0d1b

File tree

5 files changed

+38
-5
lines changed

5 files changed

+38
-5
lines changed

packages/jinja/src/ast.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ export class SetStatement extends Statement {
5151
override type = "Set";
5252
constructor(
5353
public assignee: Expression,
54-
public value: Expression
54+
public value: Expression | null,
55+
public body: Statement[]
5556
) {
5657
super();
5758
}

packages/jinja/src/lexer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const TOKEN_TYPES = Object.freeze({
3939
Is: "Is",
4040
NotIn: "NotIn",
4141
Else: "Else",
42+
EndSet: "EndSet",
4243
EndIf: "EndIf",
4344
ElseIf: "ElseIf",
4445
EndFor: "EndFor",
@@ -61,6 +62,7 @@ const KEYWORDS = Object.freeze({
6162
is: TOKEN_TYPES.Is,
6263
if: TOKEN_TYPES.If,
6364
else: TOKEN_TYPES.Else,
65+
endset: TOKEN_TYPES.EndSet,
6466
endif: TOKEN_TYPES.EndIf,
6567
elif: TOKEN_TYPES.ElseIf,
6668
endfor: TOKEN_TYPES.EndFor,

packages/jinja/src/parser.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,27 @@ export function parse(tokens: Token[]): Program {
131131

132132
if (is(TOKEN_TYPES.Equals)) {
133133
++current;
134-
const value = parseSetStatement();
134+
const value = parseExpression();
135+
136+
return new SetStatement(left, value, []);
137+
} else {
138+
// parsing multiline set here
139+
const body: Statement[] = [];
140+
expect(TOKEN_TYPES.CloseStatement, "Expected %} token");
141+
while (
142+
!(
143+
tokens[current]?.type === TOKEN_TYPES.OpenStatement &&
144+
tokens[current + 1]?.type === TOKEN_TYPES.EndSet
145+
)
146+
) {
147+
const another = parseAny()
148+
body.push(another);
149+
}
150+
expect(TOKEN_TYPES.OpenStatement, "Expected {% token");
151+
expect(TOKEN_TYPES.EndSet, "Expected endset token");
135152

136-
return new SetStatement(left, value);
153+
return new SetStatement(left, null, body);
137154
}
138-
return left;
139155
}
140156

141157
function parseIfStatement(): If {

packages/jinja/src/runtime.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,8 @@ export class Interpreter {
587587
);
588588
case "join":
589589
return new StringValue(operand.value.map((x) => x.value).join(""));
590+
case "string":
591+
return new StringValue(toJSON(operand));
590592
default:
591593
throw new Error(`Unknown ArrayValue filter: ${filter.value}`);
592594
}
@@ -916,7 +918,7 @@ export class Interpreter {
916918
}
917919

918920
private evaluateSet(node: SetStatement, environment: Environment): NullValue {
919-
const rhs = this.evaluate(node.value, environment);
921+
const rhs = node.value ? this.evaluate(node.value, environment) : this.evaluateBlock(node.body, environment);
920922
if (node.assignee.type === "Identifier") {
921923
const variableName = (node.assignee as Identifier).value;
922924
environment.setVariable(variableName, rhs);

packages/jinja/test/e2e.test.js

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)