Skip to content

Commit

Permalink
[WIP] include_relative tag support
Browse files Browse the repository at this point in the history
  • Loading branch information
msangel committed Oct 14, 2023
1 parent adc2602 commit 5857938
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 7 deletions.
22 changes: 17 additions & 5 deletions src/main/java/liqp/Template.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@

import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
Expand Down Expand Up @@ -47,6 +43,7 @@ public class Template {


private final long templateSize;
private final String sourceName;

private TemplateContext templateContext = null;

Expand All @@ -63,6 +60,7 @@ public class Template {
this.templateSize = stream.size();
LiquidLexer lexer = new LiquidLexer(stream, this.templateParser.isStripSpacesAroundTags(),
this.templateParser.isStripSingleLine(), blockNames, tagNames);
this.sourceName = IntStream.UNKNOWN_SOURCE_NAME.equals(stream.getSourceName()) ? null : stream.getSourceName();
try {
root = parse(lexer);
} catch (LiquidException e) {
Expand Down Expand Up @@ -355,13 +353,18 @@ public Object renderToObjectUnguarded(Map<String, Object> variables, TemplateCon
variables = templateParser.evaluate(templateParser.mapper, variables);

final NodeVisitor visitor = new NodeVisitor(templateParser.insertions, templateParser.filters, templateParser.liquidStyleInclude);
Deque<String> includeStack = null;
try {
LNode node = visitor.visit(root);
if (parent == null) {
this.templateContext = newRootContext(variables);
} else {
this.templateContext = parent.newChildContext(variables);
}

includeStack = getIncludeStackFromRegistry(templateContext);
includeStack.push(sourceName);

if (this.contextHolder != null) {
contextHolder.setContext(templateContext);
}
Expand All @@ -375,9 +378,18 @@ public Object renderToObjectUnguarded(Map<String, Object> variables, TemplateCon
} else {
throw new RuntimeException(e);
}
} finally {
if (includeStack != null) {
includeStack.pop();
}
}
}

public static Deque<String> getIncludeStackFromRegistry(TemplateContext templateContext) {
Map<String, Deque<String>> registry = templateContext.getRegistry(TemplateContext.REGISTRY_SOURCE_NAME);
return registry.putIfAbsent(TemplateContext.REGISTRY_SOURCE_NAME, new LinkedList<>());
}

/**
* Renders the template using parent context
*
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/liqp/TemplateContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class TemplateContext {
public static final String REGISTRY_FOR = "for";
public static final String REGISTRY_FOR_STACK = "for_stack";
public static final String REGISTRY_ITERATION_PROTECTOR = "iteration_protector";
public static final String REGISTRY_SOURCE_NAME = "registry_source_name";

protected TemplateContext parent;

Expand Down Expand Up @@ -164,7 +165,7 @@ public Map<String, Object> getEnvironmentMap() {
return parent.getRegistry(registryName);
}

if (!Arrays.asList(REGISTRY_CYCLE, REGISTRY_IFCHANGED, REGISTRY_FOR, REGISTRY_FOR_STACK, REGISTRY_ITERATION_PROTECTOR)
if (!Arrays.asList(REGISTRY_CYCLE, REGISTRY_IFCHANGED, REGISTRY_FOR, REGISTRY_FOR_STACK, REGISTRY_ITERATION_PROTECTOR, REGISTRY_SOURCE_NAME)
.contains(registryName)) {
// this checking exists for safety of library, any listed type is expected, not more
throw new RuntimeException("unknown registry type: " + registryName);
Expand Down
12 changes: 11 additions & 1 deletion src/main/java/liqp/tags/Include.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package liqp.tags;

import java.io.File;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -13,12 +14,16 @@ public class Include extends Tag {

@Override
public Object render(TemplateContext context, LNode... nodes) {

Deque<String> includeStackFromRegistry = Template.getIncludeStackFromRegistry(context);
boolean pushedStack = false;
try {
String includeResource = super.asString(nodes[0].render(context), context);

CharStream source = context.getParser().nameResolver.resolve(includeResource);

includeStackFromRegistry.push(source.getSourceName());
pushedStack = true;

Template template = context.getParser().parse(source);

Map<String, Object> variables = new HashMap<String, Object>();
Expand Down Expand Up @@ -47,6 +52,11 @@ public Object render(TemplateContext context, LNode... nodes) {
} else {
return "";
}
} finally {
// flag variable in case exception is thrown before we push to the stack
if (pushedStack) {
includeStackFromRegistry.pop();
}
}
}
}

0 comments on commit 5857938

Please sign in to comment.