diff --git a/pom.xml b/pom.xml
index a5503f051..27b09a6e3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
com.hubspot.jinjava
jinjava
- 2.8.4-SNAPSHOT
+ 3.0.0-SNAPSHOT
${project.groupId}:${project.artifactId}
Jinja templating engine implemented in Java
diff --git a/src/main/java/com/hubspot/jinjava/LegacyOverrides.java b/src/main/java/com/hubspot/jinjava/LegacyOverrides.java
index c29fcd711..0cb6e661a 100644
--- a/src/main/java/com/hubspot/jinjava/LegacyOverrides.java
+++ b/src/main/java/com/hubspot/jinjava/LegacyOverrides.java
@@ -146,6 +146,10 @@ public Builder withUseSnakeCasePropertyNaming(boolean useSnakeCasePropertyNaming
return this;
}
+ /**
+ * Use {@link com.hubspot.jinjava.features.BuiltInFeatures#WHITESPACE_REQUIRED_WITHIN_TOKENS} instead
+ */
+ @Deprecated
public Builder withWhitespaceRequiredWithinTokens(
boolean whitespaceRequiredWithinTokens
) {
diff --git a/src/main/java/com/hubspot/jinjava/features/BuiltInFeatures.java b/src/main/java/com/hubspot/jinjava/features/BuiltInFeatures.java
new file mode 100644
index 000000000..7722c601e
--- /dev/null
+++ b/src/main/java/com/hubspot/jinjava/features/BuiltInFeatures.java
@@ -0,0 +1,11 @@
+package com.hubspot.jinjava.features;
+
+public interface BuiltInFeatures {
+ String WHITESPACE_REQUIRED_WITHIN_TOKENS = "whitespace_required_within_tokens";
+ String FIXED_DATE_TIME_FILTER_NULL_ARG = "FIXED_DATE_TIME_FILTER_NULL_ARG";
+ String ECHO_UNDEFINED = "echoUndefined";
+ String PREVENT_ACCIDENTAL_EXPRESSIONS = "PREVENT_ACCIDENTAL_EXPRESSIONS";
+ String IGNORE_NESTED_INTERPRETATION_PARSE_ERRORS =
+ "IGNORE_NESTED_INTERPRETATION_PARSE_ERRORS";
+ String OUTPUT_UNDEFINED_VARIABLES_ERROR = "OUTPUT_UNDEFINED_VARIABLES_ERROR";
+}
diff --git a/src/main/java/com/hubspot/jinjava/features/DateTimeFeatureActivationStrategy.java b/src/main/java/com/hubspot/jinjava/features/DateTimeFeatureActivationStrategy.java
index 8fba08836..c50e4f679 100644
--- a/src/main/java/com/hubspot/jinjava/features/DateTimeFeatureActivationStrategy.java
+++ b/src/main/java/com/hubspot/jinjava/features/DateTimeFeatureActivationStrategy.java
@@ -20,6 +20,11 @@ public boolean isActive(Context context) {
return ZonedDateTime.now().isAfter(activateAt);
}
+ @Override
+ public boolean isActive() {
+ return false; // Not usable without context
+ }
+
public ZonedDateTime getActivateAt() {
return activateAt;
}
diff --git a/src/main/java/com/hubspot/jinjava/features/FeatureActivationStrategy.java b/src/main/java/com/hubspot/jinjava/features/FeatureActivationStrategy.java
index 2abdd59de..6ba27b206 100644
--- a/src/main/java/com/hubspot/jinjava/features/FeatureActivationStrategy.java
+++ b/src/main/java/com/hubspot/jinjava/features/FeatureActivationStrategy.java
@@ -3,5 +3,9 @@
import com.hubspot.jinjava.interpret.Context;
public interface FeatureActivationStrategy {
- boolean isActive(Context context);
+ default boolean isActive(Context context) {
+ return isActive();
+ }
+
+ boolean isActive();
}
diff --git a/src/main/java/com/hubspot/jinjava/features/FeatureConfig.java b/src/main/java/com/hubspot/jinjava/features/FeatureConfig.java
index cf3653d3d..7038592ce 100644
--- a/src/main/java/com/hubspot/jinjava/features/FeatureConfig.java
+++ b/src/main/java/com/hubspot/jinjava/features/FeatureConfig.java
@@ -1,8 +1,10 @@
package com.hubspot.jinjava.features;
import com.google.common.collect.ImmutableMap;
+import com.hubspot.jinjava.interpret.Context;
import java.util.HashMap;
import java.util.Map;
+import java.util.function.Function;
public class FeatureConfig {
@@ -24,6 +26,25 @@ public static class Builder {
private final Map features = new HashMap<>();
+ @Deprecated
+ public Builder add(String name, Function strategyFunction) {
+ features.put(
+ name,
+ new FeatureActivationStrategy() {
+ @Override
+ public boolean isActive(Context context) {
+ return strategyFunction.apply(context);
+ }
+
+ @Override
+ public boolean isActive() {
+ return false;
+ }
+ }
+ );
+ return this;
+ }
+
public Builder add(String name, FeatureActivationStrategy strategy) {
features.put(name, strategy);
return this;
diff --git a/src/main/java/com/hubspot/jinjava/features/FeatureStrategies.java b/src/main/java/com/hubspot/jinjava/features/FeatureStrategies.java
index 9171c2e91..8ae4025f4 100644
--- a/src/main/java/com/hubspot/jinjava/features/FeatureStrategies.java
+++ b/src/main/java/com/hubspot/jinjava/features/FeatureStrategies.java
@@ -2,6 +2,6 @@
public class FeatureStrategies {
- public static final FeatureActivationStrategy INACTIVE = c -> false;
- public static final FeatureActivationStrategy ACTIVE = c -> true;
+ public static final FeatureActivationStrategy INACTIVE = () -> false;
+ public static final FeatureActivationStrategy ACTIVE = () -> true;
}
diff --git a/src/main/java/com/hubspot/jinjava/features/Features.java b/src/main/java/com/hubspot/jinjava/features/Features.java
index 9cba433ed..5e311f322 100644
--- a/src/main/java/com/hubspot/jinjava/features/Features.java
+++ b/src/main/java/com/hubspot/jinjava/features/Features.java
@@ -14,6 +14,10 @@ public boolean isActive(String featureName, Context context) {
return getActivationStrategy(featureName).isActive(context);
}
+ public boolean isActive(String featureName) {
+ return getActivationStrategy(featureName).isActive();
+ }
+
public FeatureActivationStrategy getActivationStrategy(String featureName) {
return featureConfig.getFeature(featureName);
}
diff --git a/src/main/java/com/hubspot/jinjava/interpret/JinjavaInterpreter.java b/src/main/java/com/hubspot/jinjava/interpret/JinjavaInterpreter.java
index ed643e06b..3577a8729 100644
--- a/src/main/java/com/hubspot/jinjava/interpret/JinjavaInterpreter.java
+++ b/src/main/java/com/hubspot/jinjava/interpret/JinjavaInterpreter.java
@@ -30,6 +30,7 @@
import com.hubspot.jinjava.el.ExpressionResolver;
import com.hubspot.jinjava.el.ext.DeferredParsingException;
import com.hubspot.jinjava.el.ext.ExtendedParser;
+import com.hubspot.jinjava.features.BuiltInFeatures;
import com.hubspot.jinjava.interpret.AutoCloseableSupplier.AutoCloseableImpl;
import com.hubspot.jinjava.interpret.Context.TemporaryValueClosable;
import com.hubspot.jinjava.interpret.ContextConfigurationIF.ErrorHandlingStrategyIF;
@@ -87,9 +88,9 @@ public class JinjavaInterpreter implements PyishSerializable {
"ignored_output_from_extends";
public static final String OUTPUT_UNDEFINED_VARIABLES_ERROR =
- "OUTPUT_UNDEFINED_VARIABLES_ERROR";
+ BuiltInFeatures.OUTPUT_UNDEFINED_VARIABLES_ERROR;
public static final String IGNORE_NESTED_INTERPRETATION_PARSE_ERRORS =
- "IGNORE_NESTED_INTERPRETATION_PARSE_ERRORS";
+ BuiltInFeatures.IGNORE_NESTED_INTERPRETATION_PARSE_ERRORS;
private final Multimap blocks = ArrayListMultimap.create();
private final LinkedList extendParentRoots = new LinkedList<>();
private final Map revertibleObjects = new HashMap<>();
@@ -288,9 +289,7 @@ public String renderFlat(String template, long renderLimit) {
private TemporaryValueClosable ignoreParseErrorsIfActivated() {
return config
.getFeatures()
- .getActivationStrategy(
- JinjavaInterpreter.IGNORE_NESTED_INTERPRETATION_PARSE_ERRORS
- )
+ .getActivationStrategy(BuiltInFeatures.IGNORE_NESTED_INTERPRETATION_PARSE_ERRORS)
.isActive(context)
? context.withErrorHandlingStrategy(ErrorHandlingStrategyIF.ignoreAll())
: TemporaryValueClosable.noOp();
@@ -664,7 +663,7 @@ public Object retraceVariable(String variable, int lineNumber, int startPosition
if (
getConfig()
.getFeatures()
- .getActivationStrategy(OUTPUT_UNDEFINED_VARIABLES_ERROR)
+ .getActivationStrategy(BuiltInFeatures.OUTPUT_UNDEFINED_VARIABLES_ERROR)
.isActive(context)
) {
addError(
diff --git a/src/main/java/com/hubspot/jinjava/lib/expression/DefaultExpressionStrategy.java b/src/main/java/com/hubspot/jinjava/lib/expression/DefaultExpressionStrategy.java
index 1754f455f..96140b745 100644
--- a/src/main/java/com/hubspot/jinjava/lib/expression/DefaultExpressionStrategy.java
+++ b/src/main/java/com/hubspot/jinjava/lib/expression/DefaultExpressionStrategy.java
@@ -1,5 +1,6 @@
package com.hubspot.jinjava.lib.expression;
+import com.hubspot.jinjava.features.BuiltInFeatures;
import com.hubspot.jinjava.features.FeatureActivationStrategy;
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
import com.hubspot.jinjava.lib.filter.EscapeFilter;
@@ -12,7 +13,7 @@
public class DefaultExpressionStrategy implements ExpressionStrategy {
private static final long serialVersionUID = 436239440273704843L;
- public static final String ECHO_UNDEFINED = "echoUndefined";
+ public static final String ECHO_UNDEFINED = BuiltInFeatures.ECHO_UNDEFINED;
public RenderedOutputNode interpretOutput(
ExpressionToken master,
@@ -26,7 +27,7 @@ public RenderedOutputNode interpretOutput(
final FeatureActivationStrategy feat = interpreter
.getConfig()
.getFeatures()
- .getActivationStrategy(ECHO_UNDEFINED);
+ .getActivationStrategy(BuiltInFeatures.ECHO_UNDEFINED);
if (var == null && feat.isActive(interpreter.getContext())) {
return new RenderedOutputNode(master.getImage());
diff --git a/src/main/java/com/hubspot/jinjava/lib/filter/BetweenTimesFilter.java b/src/main/java/com/hubspot/jinjava/lib/filter/BetweenTimesFilter.java
index 2154578ca..878fe2533 100644
--- a/src/main/java/com/hubspot/jinjava/lib/filter/BetweenTimesFilter.java
+++ b/src/main/java/com/hubspot/jinjava/lib/filter/BetweenTimesFilter.java
@@ -1,10 +1,9 @@
package com.hubspot.jinjava.lib.filter;
-import static com.hubspot.jinjava.lib.filter.time.DateTimeFormatHelper.FIXED_DATE_TIME_FILTER_NULL_ARG;
-
import com.hubspot.jinjava.doc.annotations.JinjavaDoc;
import com.hubspot.jinjava.doc.annotations.JinjavaParam;
import com.hubspot.jinjava.doc.annotations.JinjavaSnippet;
+import com.hubspot.jinjava.features.BuiltInFeatures;
import com.hubspot.jinjava.features.DateTimeFeatureActivationStrategy;
import com.hubspot.jinjava.features.FeatureActivationStrategy;
import com.hubspot.jinjava.interpret.InvalidArgumentException;
@@ -91,7 +90,7 @@ private ZonedDateTime getZonedDateTime(Object var, String position) {
FeatureActivationStrategy feat = interpreter
.getConfig()
.getFeatures()
- .getActivationStrategy(FIXED_DATE_TIME_FILTER_NULL_ARG);
+ .getActivationStrategy(BuiltInFeatures.FIXED_DATE_TIME_FILTER_NULL_ARG);
if (feat.isActive(interpreter.getContext())) {
var = ((DateTimeFeatureActivationStrategy) feat).getActivateAt();
diff --git a/src/main/java/com/hubspot/jinjava/lib/filter/UnixTimestampFilter.java b/src/main/java/com/hubspot/jinjava/lib/filter/UnixTimestampFilter.java
index 930a7597e..e1fe8f298 100644
--- a/src/main/java/com/hubspot/jinjava/lib/filter/UnixTimestampFilter.java
+++ b/src/main/java/com/hubspot/jinjava/lib/filter/UnixTimestampFilter.java
@@ -1,10 +1,9 @@
package com.hubspot.jinjava.lib.filter;
-import static com.hubspot.jinjava.lib.filter.time.DateTimeFormatHelper.FIXED_DATE_TIME_FILTER_NULL_ARG;
-
import com.hubspot.jinjava.doc.annotations.JinjavaDoc;
import com.hubspot.jinjava.doc.annotations.JinjavaParam;
import com.hubspot.jinjava.doc.annotations.JinjavaSnippet;
+import com.hubspot.jinjava.features.BuiltInFeatures;
import com.hubspot.jinjava.features.DateTimeFeatureActivationStrategy;
import com.hubspot.jinjava.features.FeatureActivationStrategy;
import com.hubspot.jinjava.interpret.InvalidArgumentException;
@@ -40,7 +39,7 @@ public Object filter(Object var, JinjavaInterpreter interpreter, String... args)
FeatureActivationStrategy feat = interpreter
.getConfig()
.getFeatures()
- .getActivationStrategy(FIXED_DATE_TIME_FILTER_NULL_ARG);
+ .getActivationStrategy(BuiltInFeatures.FIXED_DATE_TIME_FILTER_NULL_ARG);
if (feat.isActive(interpreter.getContext())) {
var = ((DateTimeFeatureActivationStrategy) feat).getActivateAt();
diff --git a/src/main/java/com/hubspot/jinjava/lib/filter/time/DateTimeFormatHelper.java b/src/main/java/com/hubspot/jinjava/lib/filter/time/DateTimeFormatHelper.java
index 6d65d3821..4fa1786db 100644
--- a/src/main/java/com/hubspot/jinjava/lib/filter/time/DateTimeFormatHelper.java
+++ b/src/main/java/com/hubspot/jinjava/lib/filter/time/DateTimeFormatHelper.java
@@ -1,6 +1,7 @@
package com.hubspot.jinjava.lib.filter.time;
import com.hubspot.jinjava.JinjavaConfig;
+import com.hubspot.jinjava.features.BuiltInFeatures;
import com.hubspot.jinjava.features.DateTimeFeatureActivationStrategy;
import com.hubspot.jinjava.features.FeatureActivationStrategy;
import com.hubspot.jinjava.interpret.InvalidArgumentException;
@@ -21,7 +22,7 @@
public final class DateTimeFormatHelper {
public static final String FIXED_DATE_TIME_FILTER_NULL_ARG =
- "FIXED_DATE_TIME_FILTER_NULL_ARG";
+ BuiltInFeatures.FIXED_DATE_TIME_FILTER_NULL_ARG;
private final String name;
private final Function cannedFormatterFunction;
@@ -118,7 +119,7 @@ public Object checkForNullVar(Object var, String name) {
FeatureActivationStrategy feat = interpreter
.getConfig()
.getFeatures()
- .getActivationStrategy(FIXED_DATE_TIME_FILTER_NULL_ARG);
+ .getActivationStrategy(BuiltInFeatures.FIXED_DATE_TIME_FILTER_NULL_ARG);
return feat.isActive(interpreter.getContext())
? ((DateTimeFeatureActivationStrategy) feat).getActivateAt()
diff --git a/src/main/java/com/hubspot/jinjava/lib/fn/Functions.java b/src/main/java/com/hubspot/jinjava/lib/fn/Functions.java
index fc41b6470..3bf154bfe 100644
--- a/src/main/java/com/hubspot/jinjava/lib/fn/Functions.java
+++ b/src/main/java/com/hubspot/jinjava/lib/fn/Functions.java
@@ -1,13 +1,12 @@
package com.hubspot.jinjava.lib.fn;
-import static com.hubspot.jinjava.lib.filter.time.DateTimeFormatHelper.FIXED_DATE_TIME_FILTER_NULL_ARG;
-
import com.google.common.collect.Lists;
import com.hubspot.jinjava.JinjavaConfig;
import com.hubspot.jinjava.doc.annotations.JinjavaDoc;
import com.hubspot.jinjava.doc.annotations.JinjavaParam;
import com.hubspot.jinjava.doc.annotations.JinjavaSnippet;
import com.hubspot.jinjava.el.ext.NamedParameter;
+import com.hubspot.jinjava.features.BuiltInFeatures;
import com.hubspot.jinjava.features.DateTimeFeatureActivationStrategy;
import com.hubspot.jinjava.features.FeatureActivationStrategy;
import com.hubspot.jinjava.interpret.DeferredValueException;
@@ -229,7 +228,7 @@ public static String dateTimeFormat(Object var, String... format) {
FeatureActivationStrategy feat = interpreter
.getConfig()
.getFeatures()
- .getActivationStrategy(FIXED_DATE_TIME_FILTER_NULL_ARG);
+ .getActivationStrategy(BuiltInFeatures.FIXED_DATE_TIME_FILTER_NULL_ARG);
if (feat.isActive(interpreter.getContext())) {
var = ((DateTimeFeatureActivationStrategy) feat).getActivateAt();
diff --git a/src/main/java/com/hubspot/jinjava/tree/output/OutputList.java b/src/main/java/com/hubspot/jinjava/tree/output/OutputList.java
index ef2967e96..1d3b84710 100644
--- a/src/main/java/com/hubspot/jinjava/tree/output/OutputList.java
+++ b/src/main/java/com/hubspot/jinjava/tree/output/OutputList.java
@@ -1,5 +1,6 @@
package com.hubspot.jinjava.tree.output;
+import com.hubspot.jinjava.features.BuiltInFeatures;
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
import com.hubspot.jinjava.interpret.OutputTooBigException;
import com.hubspot.jinjava.interpret.TemplateError;
@@ -11,7 +12,7 @@
public class OutputList {
public static final String PREVENT_ACCIDENTAL_EXPRESSIONS =
- "PREVENT_ACCIDENTAL_EXPRESSIONS";
+ BuiltInFeatures.PREVENT_ACCIDENTAL_EXPRESSIONS;
private final List nodes = new LinkedList<>();
private final List blocks = new LinkedList<>();
private final long maxOutputSize;
@@ -58,7 +59,7 @@ public String getValue() {
.filter(config ->
config
.getFeatures()
- .getActivationStrategy(PREVENT_ACCIDENTAL_EXPRESSIONS)
+ .getActivationStrategy(BuiltInFeatures.PREVENT_ACCIDENTAL_EXPRESSIONS)
.isActive(null)
)
.map(config ->
diff --git a/src/main/java/com/hubspot/jinjava/tree/parse/TokenScanner.java b/src/main/java/com/hubspot/jinjava/tree/parse/TokenScanner.java
index e189e6df8..e8973d5d3 100644
--- a/src/main/java/com/hubspot/jinjava/tree/parse/TokenScanner.java
+++ b/src/main/java/com/hubspot/jinjava/tree/parse/TokenScanner.java
@@ -19,6 +19,7 @@
import com.google.common.collect.AbstractIterator;
import com.hubspot.jinjava.JinjavaConfig;
+import com.hubspot.jinjava.features.BuiltInFeatures;
public class TokenScanner extends AbstractIterator {
@@ -93,7 +94,12 @@ private Token getNextToken() {
if (currPost < length) {
c = is[currPost];
boolean startTokenFound = true;
- if (config.getLegacyOverrides().isWhitespaceRequiredWithinTokens()) {
+ if (
+ config
+ .getFeatures()
+ .isActive(BuiltInFeatures.WHITESPACE_REQUIRED_WITHIN_TOKENS) ||
+ config.getLegacyOverrides().isWhitespaceRequiredWithinTokens()
+ ) {
boolean hasNextChar = (currPost + 1) < length;
boolean nextCharIsWhitespace = hasNextChar && (' ' == is[currPost + 1]);
startTokenFound = nextCharIsWhitespace;
diff --git a/src/test/java/com/hubspot/jinjava/FeaturesTest.java b/src/test/java/com/hubspot/jinjava/FeaturesTest.java
index 19291da5a..eaaa63269 100644
--- a/src/test/java/com/hubspot/jinjava/FeaturesTest.java
+++ b/src/test/java/com/hubspot/jinjava/FeaturesTest.java
@@ -47,7 +47,7 @@ public void setUp() throws Exception {
ZonedDateTime.of(LocalDateTime.MAX, ZoneId.systemDefault())
)
)
- .add(DELEGATING, d -> delegateActive)
+ .add(DELEGATING, () -> delegateActive)
.build()
);
}