├── .blazar-enabled ├── .prettier-java-enabled ├── src ├── test │ ├── resources │ │ ├── tags │ │ │ ├── includetag │ │ │ │ ├── d.jinja │ │ │ │ ├── hello.html │ │ │ │ ├── folder │ │ │ │ │ └── relative-include.html │ │ │ │ ├── raw.html │ │ │ │ ├── errors │ │ │ │ │ ├── error.html │ │ │ │ │ ├── base2.html │ │ │ │ │ └── base.html │ │ │ │ ├── a-includes-b.jinja │ │ │ │ ├── b-includes-a.jinja │ │ │ │ ├── include-with-import.jinja │ │ │ │ ├── includes-relative-path.jinja │ │ │ │ ├── includes-self.jinja │ │ │ │ ├── c-includes-d-twice.jinja │ │ │ │ ├── cat.html │ │ │ │ └── include-tag-dependencies.html │ │ │ ├── extendstag │ │ │ │ ├── hello.html │ │ │ │ ├── a-extends-b.jinja │ │ │ │ ├── b-extends-a.jinja │ │ │ │ ├── errors │ │ │ │ │ ├── no-error.html │ │ │ │ │ ├── error.html │ │ │ │ │ ├── extends-outside-block-error.jinja │ │ │ │ │ ├── extends-block-error.jinja │ │ │ │ │ ├── extends-include-block-error.jinja │ │ │ │ │ ├── outside-block-error.html │ │ │ │ │ ├── extends-no-error.jinja │ │ │ │ │ ├── include-block-error.html │ │ │ │ │ └── block-error.html │ │ │ │ ├── nested-relative-inheritance.html │ │ │ │ ├── tagcycleexception │ │ │ │ │ ├── template-c.jinja │ │ │ │ │ ├── template-d.jinja │ │ │ │ │ ├── template-b.jinja │ │ │ │ │ └── template-a.jinja │ │ │ │ ├── relative │ │ │ │ │ ├── relative-block-2.jinja │ │ │ │ │ ├── nested-relative-extends-2.jinja │ │ │ │ │ ├── nested-relative-extends.jinja │ │ │ │ │ ├── relative-block.jinja │ │ │ │ │ └── relative-extends.jinja │ │ │ │ ├── rec1.jinja │ │ │ │ ├── rec2.jinja │ │ │ │ ├── rec3.jinja │ │ │ │ ├── relative-block-2-base.jinja │ │ │ │ ├── extends-base2.jinja │ │ │ │ ├── extends-self.jinja │ │ │ │ ├── parentvars-settings.html │ │ │ │ ├── parentvars-child.html │ │ │ │ ├── super-child.html │ │ │ │ ├── extends-tag-dependencies.html │ │ │ │ ├── super-base.html │ │ │ │ ├── extends-base1.jinja │ │ │ │ ├── base2-extends-base1.jinja │ │ │ │ ├── parentvars-base.html │ │ │ │ └── base1.jinja │ │ │ ├── eager │ │ │ │ ├── importtag │ │ │ │ │ ├── var-a.jinja │ │ │ │ │ ├── var-b.jinja │ │ │ │ │ ├── variables.jinja │ │ │ │ │ ├── layer-two.jinja │ │ │ │ │ ├── set-two-variables.jinja │ │ │ │ │ ├── import-tree-a.jinja │ │ │ │ │ ├── printer-a.jinja │ │ │ │ │ ├── printer-b.jinja │ │ │ │ │ ├── macro-a.jinja │ │ │ │ │ ├── macro-b.jinja │ │ │ │ │ ├── layer-one.jinja │ │ │ │ │ ├── import-tree-b.jinja │ │ │ │ │ ├── import-tree-c.jinja │ │ │ │ │ ├── import-macro.jinja │ │ │ │ │ ├── import-macro-applies-val.jinja │ │ │ │ │ ├── intermediate-b.jinja │ │ │ │ │ ├── import-macro-and-var.jinja │ │ │ │ │ ├── double-import-macro.jinja │ │ │ │ │ └── import-tree-d.jinja │ │ │ │ ├── settag │ │ │ │ │ ├── evaluates-expression.jinja │ │ │ │ │ ├── evaluates-expression.expected.jinja │ │ │ │ │ ├── handles-multiple-vars.expected.jinja │ │ │ │ │ ├── handles-multiple-vars.jinja │ │ │ │ │ ├── partially-evaluates-deferred-expression.jinja │ │ │ │ │ └── partially-evaluates-deferred-expression.expected.jinja │ │ │ │ ├── iftag │ │ │ │ │ ├── handles-deferred-in-regular.expected.jinja │ │ │ │ │ ├── removes-impossible-if-blocks.expected.jinja │ │ │ │ │ ├── handles-deferred-in-regular.jinja │ │ │ │ │ ├── handles-only-deferred-elif.expected.jinja │ │ │ │ │ ├── handles-only-deferred-elif.jinja │ │ │ │ │ ├── removes-impossible-if-blocks.jinja │ │ │ │ │ ├── handles-deferred-in-eager.expected.jinja │ │ │ │ │ └── handles-deferred-in-eager.jinja │ │ │ │ ├── unlesstag │ │ │ │ │ ├── handles-deferred-in-regular.expected.jinja │ │ │ │ │ ├── handles-deferred-in-regular.jinja │ │ │ │ │ ├── handles-deferred-in-eager.jinja │ │ │ │ │ └── handles-deferred-in-eager.expected.jinja │ │ │ │ ├── includetag │ │ │ │ │ ├── sets-to-deferred.jinja │ │ │ │ │ ├── includes-deferred.jinja │ │ │ │ │ └── includes-deferred.expected.jinja │ │ │ │ ├── fortag │ │ │ │ │ ├── registers-eager-token.jinja │ │ │ │ │ ├── registers-eager-token.expected.jinja │ │ │ │ │ ├── handles-multiple-loop-vars.jinja │ │ │ │ │ ├── handles-multiple-loop-vars.expected.jinja │ │ │ │ │ ├── handles-nested-deferred-for-loop.jinja │ │ │ │ │ └── handles-nested-deferred-for-loop.expected.jinja │ │ │ │ └── extendstag │ │ │ │ │ ├── base.html │ │ │ │ │ ├── defers-block-in-extends-child.expected.expected.jinja │ │ │ │ │ ├── defers-block-in-extends-child.jinja │ │ │ │ │ ├── base-deferred.html │ │ │ │ │ ├── reconstructs-deferred-outside-block.expected.expected.jinja │ │ │ │ │ ├── defers-super-block-with-deferred.jinja │ │ │ │ │ ├── defers-super-block-with-deferred.expected.expected.jinja │ │ │ │ │ ├── throws-when-deferred-extends-tag.jinja │ │ │ │ │ ├── reconstructs-deferred-outside-block.jinja │ │ │ │ │ ├── defers-block-in-extends-child.expected.jinja │ │ │ │ │ ├── defers-super-block-with-deferred.expected.jinja │ │ │ │ │ └── reconstructs-deferred-outside-block.expected.jinja │ │ │ ├── rawtag │ │ │ │ ├── plain.jinja │ │ │ │ ├── tags.jinja │ │ │ │ ├── deferred.jinja │ │ │ │ ├── invalidsyntax.jinja │ │ │ │ ├── nospacing.jinja │ │ │ │ ├── unknowntags.jinja │ │ │ │ ├── invalidsyntax2.jinja │ │ │ │ ├── invalidsyntax3.jinja │ │ │ │ ├── invalidsyntax4.jinja │ │ │ │ ├── invalidsyntax5.jinja │ │ │ │ ├── hubl.jinja │ │ │ │ └── comment.jinja │ │ │ ├── settag │ │ │ │ ├── set-val.jinja │ │ │ │ ├── set-filter-expr.jinja │ │ │ │ ├── set-list-append.jinja │ │ │ │ ├── set-array.jinja │ │ │ │ ├── set-list-modify.jinja │ │ │ │ ├── set-string-concat.jinja │ │ │ │ ├── set-expr-concat.jinja │ │ │ │ ├── set-var-exp.jinja │ │ │ │ ├── set-multivar-unbalanced-vals.jinja │ │ │ │ ├── set-multivar.jinja │ │ │ │ ├── set-multivar-unbalanced-vars.jinja │ │ │ │ ├── set-dictionary.jinja │ │ │ │ └── set-complex-dict.jinja │ │ │ ├── iftag │ │ │ │ ├── if-object.jinja │ │ │ │ ├── if.jinja │ │ │ │ ├── if-non-existent-prop.jinja │ │ │ │ ├── unless.jinja │ │ │ │ ├── if-expr-filter.jinja │ │ │ │ ├── if-true-elif-true.jinja │ │ │ │ ├── if-else.jinja │ │ │ │ ├── if-elif-else.jinja │ │ │ │ └── if-elif-elif-else.jinja │ │ │ ├── importtag │ │ │ │ ├── null-value.jinja │ │ │ │ ├── imports-global-macro.jinja │ │ │ │ ├── imports-macro.jinja │ │ │ │ ├── a-imports-b.jinja │ │ │ │ ├── b-imports-a.jinja │ │ │ │ ├── imports-macro-relative.jinja │ │ │ │ ├── imports-self.jinja │ │ │ │ ├── errors │ │ │ │ │ ├── import-macro.jinja │ │ │ │ │ ├── include.jinja │ │ │ │ │ ├── base.jinja │ │ │ │ │ ├── file-with-error.jinja │ │ │ │ │ └── macro-with-error.jinja │ │ │ │ └── imports-null.jinja │ │ │ ├── fortag │ │ │ │ ├── loop-index-var.jinja │ │ │ │ ├── literal-loop-expr.jinja │ │ │ │ ├── nested-cycle.jinja │ │ │ │ ├── loop-with-scalar.jinja │ │ │ │ ├── nested-fors.jinja │ │ │ │ ├── multiple-loop-vars.jinja │ │ │ │ └── loop-last-var.jinja │ │ │ ├── macrotag │ │ │ │ ├── relative-from.jinja │ │ │ │ ├── from-simple-with-call.jinja │ │ │ │ ├── simple.jinja │ │ │ │ ├── include-two-macros.jinja │ │ │ │ ├── recursion.jinja │ │ │ │ ├── import-macro.jinja │ │ │ │ ├── import-property-global.jinja │ │ │ │ ├── with-args.jinja │ │ │ │ ├── simple-with-call.jinja │ │ │ │ ├── from-a-to-b.jinja │ │ │ │ ├── from-b-to-c.jinja │ │ │ │ ├── from-c-to-a.jinja │ │ │ │ ├── from.jinja │ │ │ │ ├── list_kwargs.jinja │ │ │ │ ├── ending-recursion.jinja │ │ │ │ ├── from-alias-macro.jinja │ │ │ │ ├── from-recursion.jinja │ │ │ │ ├── import.jinja │ │ │ │ ├── simple-no-trim.jinja │ │ │ │ ├── double-import-macro.jinja │ │ │ │ ├── imports-macro-referencing-macro.jinja │ │ │ │ ├── recursion_indirect.jinja │ │ │ │ ├── array-def-val.jinja │ │ │ │ ├── def-vals.jinja │ │ │ │ ├── import-property.jinja │ │ │ │ ├── scoping.jinja │ │ │ │ ├── two-macros.jinja │ │ │ │ ├── pegasus-importable.jinja │ │ │ │ └── macro-referencing-macro.jinja │ │ │ ├── autoescapetag │ │ │ │ └── autoescape.jinja │ │ │ └── calltag │ │ │ │ ├── multiple.jinja │ │ │ │ └── simple.jinja │ │ ├── loader │ │ │ └── cp │ │ │ │ └── foo │ │ │ │ └── bar.jinja │ │ ├── varblocks │ │ │ ├── simplevar.html │ │ │ ├── string-range.html │ │ │ ├── default.html │ │ │ ├── noblocks.html │ │ │ ├── withtags-expected.html │ │ │ ├── withtags.html │ │ │ ├── nestedattrs-expected.html │ │ │ └── nestedattrs.html │ │ ├── eager │ │ │ ├── partially-resolves-eager-set │ │ │ │ └── test.jinja │ │ │ ├── finds-deferred-words-inside-reconstructed-string │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── loads-imported-macro-syntax │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── supplements │ │ │ │ ├── set-val.jinja │ │ │ │ ├── simple-with-call.jinja │ │ │ │ ├── macro-and-set.jinja │ │ │ │ └── deferred-modification.jinja │ │ │ ├── reconstructs-aliased-macro │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── takes-param.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── defers-macro-in-expression │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-clashing-name-in-macro │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-deferred-in-cycle │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── keeps-max-macro-recursion-depth │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── defers-caller │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── defers-loop-setting-meta-context-var │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-block-set-in-deferred-if │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-deferred-in-namespace │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── keeps-meta-context-variables-through-import │ │ │ │ ├── import-target.jinja │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── puts-deferred-imported-macro-in-output │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── eagerly-defers-macro │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-deferred-cycle-as │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── sets-multiple-vars-deferred-in-child │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-unknown-function-errors │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── does-not-reconstruct-variable-in-wrong-scope │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-cycle-with-quote │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-double-import-modification │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── reconstructs-types-properly │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── reconstructs-words-from-inside-nested-expressions │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── uses-unique-macro-names │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── macro-with-filter.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-deferred-from-import-as │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-cycle-in-deferred-for │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── keeps-macro-modifications-in-scope │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── reconstructs-fromed-macro │ │ │ │ ├── has-macro.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── does-not-referential-defer-for-set-vars │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-break-in-deferred-for-loop │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-deferred-break-in-for-loop │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-deferred-continue-in-for-loop │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-deferred-modification-in-caller │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── allows-variable-sharing-alias-name │ │ │ │ ├── test.jinja │ │ │ │ └── filters.jinja │ │ │ ├── defers-changes-within-deferred-set-block │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── runs-for-loop-inside-deferred-for-loop │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── wraps-macro-that-would-change-current-path-in-child-scope │ │ │ │ ├── dir2 │ │ │ │ │ └── included.jinja │ │ │ │ ├── dir1 │ │ │ │ │ └── macro.jinja │ │ │ │ └── test.jinja │ │ │ ├── allows-deferred-lazy-reference-to-get-overridden │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-continue-in-deferred-for-loop │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-deferred-for-loop-var-from-macro │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── reconstructs-value-used-in-deferred-imported-macro │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── uses-deferred-value-in-macro.jinja │ │ │ ├── defers-call-tag-with-deferred-argument │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-non-deferred-import-vars │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── commits-variables-from-do-tag-when-partially-resolved │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-deferred-import-vars │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-complex-raw │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── preserves-value-set-in-if │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── defers-ifchanged │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── fully-defers-filtered-macro │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-set-in-inner-scope │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-eager-print-and-do │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── reconstructs-map-node │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── does-not-override-import-modification-in-for │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-deferred-in-ifchanged │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-loop-var-against-deferred-in-loop │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── reconstructs-namespace-for-set-tags-using-period │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── defers-eager-child-scoped-vars │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── does-not-reconstruct-variable-in-set-in-wrong-scope │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── doesnt-affect-parent-from-eager-if │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── fails-on-modification-in-aliased-macro │ │ │ │ ├── settings.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-same-name-import-var │ │ │ │ ├── test.jinja │ │ │ │ ├── test.expected.expected.jinja │ │ │ │ └── set-var-and-deferred.jinja │ │ │ ├── allows-modification-in-resolved-for-loop │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── doesnt-overwrite-elif │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── has-proper-line-stripping │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── puts-deferred-fromed-macro-in-output │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── reconstructs-block-set-variables-in-for-loop │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── evaluates-non-eager-set │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── correctly-defers-with-multiple-loops │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-set-in-for │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── reconstructs-nested-value-in-string-representation │ │ │ │ └── test.expected.expected.jinja │ │ │ ├── preserves-raw-inside-deferred-set-block │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-auto-escape │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── defers-large-loop │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── doesnt-double-append-in-deferred-set │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── defers-macro-in-for │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── defers-macro-in-if │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── doesnt-double-append-in-deferred-if-tag │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-duplicate-variable-reference-speculative-modification │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── allows-meta-context-var-overriding │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-higher-scope-reference-modification │ │ │ │ └── test.expected.expected.jinja │ │ │ ├── scopes-resetting-bindings │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── doesnt-double-append-in-deferred-macro │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── reverts-modification-with-deferred-loop │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-set-and-modified-in-for │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── prepends-set-if-state-changes │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-non-deferring-cycles │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── reconstructs-block-path-when-deferred │ │ │ │ ├── test.jinja │ │ │ │ ├── base.jinja │ │ │ │ └── test.expected.expected.jinja │ │ │ ├── reverts-simple │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-value-modified-in-macro │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── wraps-certain-output-in-raw │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── reconstructs-block-path-when-deferred-nested │ │ │ │ ├── test.jinja │ │ │ │ ├── base.jinja │ │ │ │ ├── middle.jinja │ │ │ │ └── test.expected.expected.jinja │ │ │ ├── defers-on-immutable-mode │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── eagerly-defers-set │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── handles-import-with-macros-in-deferred-if │ │ │ │ └── test.jinja │ │ │ ├── keeps-scope-isolation-from-for-loops │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── defers-macro-for-do-and-print │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-deferring-loop-variable │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── reconstructs-deferred-variable-eventually │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── reconstructs-null-variables-in-deferred-caller │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── runs-macro-function-in-deferred-execution-mode │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── modifies-variable-in-deferred-macro │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-duplicate-variable-reference-modification │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── does-not-reconstruct-extra-times │ │ │ │ ├── test.expected.jinja │ │ │ │ └── test.jinja │ │ │ ├── only-defers-loop-item-on-current-context │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ │ ├── handles-import-in-deferred-if │ │ │ │ └── test.jinja │ │ │ └── handles-reference-modification-when-source-is-lost │ │ │ │ ├── test.jinja │ │ │ │ └── test.expected.jinja │ │ ├── parse │ │ │ └── tokenizer │ │ │ │ ├── comment-without-whitespace.jinja │ │ │ │ ├── html-with-tag-in-attr.jinja │ │ │ │ ├── comment-plus.jinja │ │ │ │ ├── tag-with-trim-chars.jinja │ │ │ │ ├── multiline-comment.jinja │ │ │ │ ├── whitespace-tags.jinja │ │ │ │ ├── tag-with-quot-in-attr.jinja │ │ │ │ ├── comment-with-tags.jinja │ │ │ │ ├── positions.jinja │ │ │ │ ├── comment-with-start-comment-within.jinja │ │ │ │ ├── whitespace-comment-tags.jinja │ │ │ │ └── tag-with-all-escaped-quotes.jinja │ │ ├── snippets │ │ │ ├── uses-lower-scope-value-in-macro-evaluation.expected.jinja │ │ │ ├── does-not-override-macro-functions-from-higher-scope.expected.jinja │ │ │ ├── does-not-override-call-tag-from-higher-scope.expected.jinja │ │ │ ├── uses-lower-scope-value-in-macro-evaluation.jinja │ │ │ ├── does-not-override-macro-functions-from-higher-scope.jinja │ │ │ └── does-not-override-call-tag-from-higher-scope.jinja │ │ ├── filter │ │ │ ├── complex-chained.jinja │ │ │ ├── urlize.txt │ │ │ ├── render │ │ │ │ └── base.jinja │ │ │ ├── slice-filter-empty.jinja │ │ │ ├── slice-filter-zero.jinja │ │ │ ├── slice-filter-big.jinja │ │ │ ├── slice-filter-negative.jinja │ │ │ ├── slice-filter-replacement.jinja │ │ │ ├── batch-filter.jinja │ │ │ ├── slice-filter.jinja │ │ │ └── groupby-attr.jinja │ │ ├── el │ │ │ └── dict │ │ │ │ └── dict-with-var-refs.fixture │ │ ├── deferred │ │ │ ├── set-within-lower-scope.jinja │ │ │ ├── set-in-deferred.jinja │ │ │ ├── deferred-map-access.jinja │ │ │ ├── vars-in-deferred-node.jinja │ │ │ ├── deferred-macro.jinja │ │ │ └── set-within-lower-scope-twice.jinja │ │ └── logback.xml │ └── java │ │ └── com │ │ └── hubspot │ │ └── jinjava │ │ ├── lib │ │ └── filter │ │ │ └── DAliasedDefaultFilterTest.java │ │ └── BaseJinjavaTest.java └── main │ └── java │ └── com │ └── hubspot │ └── jinjava │ ├── el │ ├── ObjectUnwrapper.java │ ├── ext │ │ ├── DeferredInvocationResolutionException.java │ │ ├── IdentifierPreservationStrategy.java │ │ ├── eager │ │ │ └── EagerExtendedSyntaxBuilder.java │ │ └── StringBuildingOperator.java │ ├── JinjavaNodeProcessor.java │ └── JinjavaObjectUnwrapper.java │ ├── interpret │ ├── errorcategory │ │ ├── TemplateErrorCategory.java │ │ └── BasicTemplateErrorCategory.java │ ├── IndexOutOfRangeException.java │ ├── OneTimeReconstructible.java │ ├── RenderTimings.java │ ├── PartiallyDeferredValue.java │ ├── FromTagCycleException.java │ ├── ImportTagCycleException.java │ ├── MacroTagCycleException.java │ ├── ExtendsTagCycleException.java │ ├── IncludeTagCycleException.java │ ├── DisabledException.java │ ├── InterpreterFactory.java │ ├── CannotReconstructValueException.java │ ├── NotInLoopException.java │ ├── DeferredMacroValueImpl.java │ ├── UnexpectedTokenException.java │ ├── UnknownTokenException.java │ ├── OutputTooBigException.java │ └── JinjavaInterpreterFactory.java │ ├── util │ ├── HasObjectTruthValue.java │ ├── RenderLimitUtils.java │ └── CharArrayUtils.java │ ├── objects │ ├── date │ │ ├── DateTimeProvider.java │ │ ├── CurrentDateTimeProvider.java │ │ └── FixedDateTimeProvider.java │ ├── serialization │ │ └── PyishBlockSetSerializable.java │ ├── PyWrapper.java │ └── SafeString.java │ ├── tree │ ├── output │ │ └── OutputNode.java │ └── parse │ │ ├── UnclosedToken.java │ │ └── WhitespaceControlParser.java │ ├── random │ └── RandomNumberGeneratorStrategy.java │ ├── lib │ ├── tag │ │ ├── FlexibleTag.java │ │ └── eager │ │ │ ├── EagerGenericTag.java │ │ │ └── EagerUnlessTag.java │ ├── filter │ │ ├── CountFilter.java │ │ ├── EAliasedEscapeFilter.java │ │ └── DAliasedDefaultFilter.java │ ├── exptest │ │ ├── IsEqExpTest.java │ │ ├── IsLessThanExpTest.java │ │ ├── IsWithinExpTest.java │ │ ├── IsLessThanSymbolExpTest.java │ │ ├── IsGreaterThanExpTest.java │ │ ├── IsGreaterThanSymbolExpTest.java │ │ ├── IsEqualsSymbolExpTest.java │ │ ├── IsNotEqualToSymbolExpTest.java │ │ ├── IsLessThanOrEqualToSymbolExpTest.java │ │ ├── IsGreaterThanOrEqualToSymbolExpTest.java │ │ └── CollectionExpTest.java │ └── expression │ │ └── ExpressionStrategy.java │ ├── features │ ├── FeatureActivationStrategy.java │ ├── FeatureStrategies.java │ └── Features.java │ ├── loader │ ├── LocationResolver.java │ └── ResourceNotFoundException.java │ ├── mode │ ├── DefaultExecutionMode.java │ └── PreserveRawExecutionMode.java │ └── doc │ ├── annotations │ ├── JinjavaHasCodeBody.java │ ├── JinjavaMetaValue.java │ ├── JinjavaSnippet.java │ ├── JinjavaTextMateSnippet.java │ └── JinjavaParam.java │ ├── JinjavaDocExpTest.java │ ├── JinjavaDocFilter.java │ ├── JinjavaDocFunction.java │ └── JinjavaDocSnippet.java ├── .blazar.yaml ├── jinjava.png ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .gitmodules └── .gitignore /.blazar-enabled: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.prettier-java-enabled: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/d.jinja: -------------------------------------------------------------------------------- 1 | hello -------------------------------------------------------------------------------- /.blazar.yaml: -------------------------------------------------------------------------------- 1 | buildResources: 2 | memoryMb: 10240 3 | -------------------------------------------------------------------------------- /src/test/resources/loader/cp/foo/bar.jinja: -------------------------------------------------------------------------------- 1 | hello world. -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/hello.html: -------------------------------------------------------------------------------- 1 | hello 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/hello.html: -------------------------------------------------------------------------------- 1 | hello 2 | -------------------------------------------------------------------------------- /src/test/resources/varblocks/simplevar.html: -------------------------------------------------------------------------------- 1 | {{ myvar }} -------------------------------------------------------------------------------- /src/test/resources/eager/partially-resolves-eager-set/test.jinja: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/resources/varblocks/string-range.html: -------------------------------------------------------------------------------- 1 | {{ theString[2:5] }} -------------------------------------------------------------------------------- /jinjava.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/jinjava/HEAD/jinjava.png -------------------------------------------------------------------------------- /src/test/resources/varblocks/default.html: -------------------------------------------------------------------------------- 1 | {{ foobar|default('oops') }} -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/var-a.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 'a' %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/var-b.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 'b' %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/folder/relative-include.html: -------------------------------------------------------------------------------- 1 | INCLUDED 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/rawtag/plain.jinja: -------------------------------------------------------------------------------- 1 | {% raw %}hello world.{% endraw %} -------------------------------------------------------------------------------- /src/test/resources/tags/settag/set-val.jinja: -------------------------------------------------------------------------------- 1 | {% set primary_line_height = 42 %} -------------------------------------------------------------------------------- /src/test/resources/parse/tokenizer/comment-without-whitespace.jinja: -------------------------------------------------------------------------------- 1 | ${#array[@]} -------------------------------------------------------------------------------- /src/test/resources/tags/rawtag/tags.jinja: -------------------------------------------------------------------------------- 1 | {% raw %}{{ if list.123 }}foo{% endraw %} -------------------------------------------------------------------------------- /src/test/resources/varblocks/noblocks.html: -------------------------------------------------------------------------------- 1 |

this is a sample entry.

-------------------------------------------------------------------------------- /src/test/resources/eager/finds-deferred-words-inside-reconstructed-string/test.jinja: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/resources/eager/loads-imported-macro-syntax/test.expected.jinja: -------------------------------------------------------------------------------- 1 | Lemonade 2 | -------------------------------------------------------------------------------- /src/test/resources/eager/supplements/set-val.jinja: -------------------------------------------------------------------------------- 1 | {% set primary_line_height = 42 %} -------------------------------------------------------------------------------- /src/test/resources/tags/iftag/if-object.jinja: -------------------------------------------------------------------------------- 1 | {% if foo %} 2 | ifblock 3 | {% endif %} -------------------------------------------------------------------------------- /src/test/resources/tags/iftag/if.jinja: -------------------------------------------------------------------------------- 1 | {% if foo=='bar' %} 2 | ifblock 3 | {% endif %} -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/raw.html: -------------------------------------------------------------------------------- 1 | before{% raw %} raw{% endraw %} after 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/rawtag/deferred.jinja: -------------------------------------------------------------------------------- 1 | {% raw %}{{ deferred }}{% endraw %} 2 | -------------------------------------------------------------------------------- /src/test/resources/eager/finds-deferred-words-inside-reconstructed-string/test.expected.jinja: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/resources/parse/tokenizer/html-with-tag-in-attr.jinja: -------------------------------------------------------------------------------- 1 | bar -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/variables.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = {'foo': {bar: 'here'}} %} -------------------------------------------------------------------------------- /src/test/resources/tags/rawtag/invalidsyntax.jinja: -------------------------------------------------------------------------------- 1 | {%raw%}this is {invalid and wrong{%endraw%} -------------------------------------------------------------------------------- /src/test/resources/tags/rawtag/nospacing.jinja: -------------------------------------------------------------------------------- 1 | {%raw%} 2 | {%print 'foo'%} 3 | {%endraw%} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/rawtag/unknowntags.jinja: -------------------------------------------------------------------------------- 1 | {% raw %}{% footag %}{% bartag %}{% endraw %} -------------------------------------------------------------------------------- /src/test/resources/tags/settag/set-filter-expr.jinja: -------------------------------------------------------------------------------- 1 | {% set ie_max_size = max_size|int - 30 %} -------------------------------------------------------------------------------- /src/test/resources/tags/settag/set-list-append.jinja: -------------------------------------------------------------------------------- 1 | {% set _noop= show_count.append(show) %} -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-aliased-macro/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | resolved3 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/settag/evaluates-expression.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = range(0, bar) %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/a-extends-b.jinja: -------------------------------------------------------------------------------- 1 | {% extends "b-extends-a.jinja" %} 2 | A 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/b-extends-a.jinja: -------------------------------------------------------------------------------- 1 | {% extends "a-extends-b.jinja" %} 2 | B 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/errors/no-error.html: -------------------------------------------------------------------------------- 1 | {% block test %} 2 | {% endblock %} 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/nested-relative-inheritance.html: -------------------------------------------------------------------------------- 1 | {% include "./hello.html" %} -------------------------------------------------------------------------------- /src/test/resources/tags/iftag/if-non-existent-prop.jinja: -------------------------------------------------------------------------------- 1 | {% if settings.foobar %}hello{% endif %} -------------------------------------------------------------------------------- /src/test/resources/tags/iftag/unless.jinja: -------------------------------------------------------------------------------- 1 | {% unless foo=='bar' %} 2 | ifblock 3 | {% endunless %} -------------------------------------------------------------------------------- /src/test/resources/tags/rawtag/invalidsyntax2.jinja: -------------------------------------------------------------------------------- 1 | {%raw%}this is {{ invalid and wrong{%endraw%} -------------------------------------------------------------------------------- /src/test/resources/tags/rawtag/invalidsyntax3.jinja: -------------------------------------------------------------------------------- 1 | {%raw%}this is }invalid and wrong{%endraw%} -------------------------------------------------------------------------------- /src/test/resources/tags/rawtag/invalidsyntax4.jinja: -------------------------------------------------------------------------------- 1 | {%raw%}this is }} invalid and wrong{%endraw%} -------------------------------------------------------------------------------- /src/test/resources/tags/rawtag/invalidsyntax5.jinja: -------------------------------------------------------------------------------- 1 | {%raw%}this is {% invalid and wrong{%endraw%} -------------------------------------------------------------------------------- /src/test/resources/tags/settag/set-array.jinja: -------------------------------------------------------------------------------- 1 | {% set the_list = [1, 2, 3, i_am_seven ] %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/settag/set-list-modify.jinja: -------------------------------------------------------------------------------- 1 | {% set _noop= show_count.set(0, show) %} 2 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-macro-in-expression/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | 2 2 | 6 3 | 10 4 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-clashing-name-in-macro/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | 0 2 | 3 | 1 4 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-in-cycle/test.expected.jinja: -------------------------------------------------------------------------------- 1 | 1 2 | {{ deferred }} 3 | 3 4 | -------------------------------------------------------------------------------- /src/test/resources/eager/keeps-max-macro-recursion-depth/test.expected.jinja: -------------------------------------------------------------------------------- 1 | 3 2 | 2 3 | 1 4 | 0 5 | -------------------------------------------------------------------------------- /src/test/resources/parse/tokenizer/comment-plus.jinja: -------------------------------------------------------------------------------- 1 | {# this is a comment #} 2 | and here's some extra. -------------------------------------------------------------------------------- /src/test/resources/snippets/uses-lower-scope-value-in-macro-evaluation.expected.jinja: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 1 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/iftag/handles-deferred-in-regular.expected.jinja: -------------------------------------------------------------------------------- 1 | Yes {{ deferred }} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/settag/evaluates-expression.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = [0, 1, 2] %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/tagcycleexception/template-c.jinja: -------------------------------------------------------------------------------- 1 | Included text, won't be rendered -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/tagcycleexception/template-d.jinja: -------------------------------------------------------------------------------- 1 | Extended text, will be rendered -------------------------------------------------------------------------------- /src/test/resources/tags/importtag/null-value.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 'foo' %} 2 | {% set bar = null %} 3 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-caller/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | Jack says: 2 | How do I get a foo? 3 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-loop-setting-meta-context-var/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | a 2 | 3 | b 4 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-block-set-in-deferred-if/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | I AM IRON MAN 2 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-in-namespace/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | true 2 | resolved 3 | -------------------------------------------------------------------------------- /src/test/resources/eager/keeps-meta-context-variables-through-import/import-target.jinja: -------------------------------------------------------------------------------- 1 | I am a boring import -------------------------------------------------------------------------------- /src/test/resources/eager/puts-deferred-imported-macro-in-output/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | Hello 4 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/unlesstag/handles-deferred-in-regular.expected.jinja: -------------------------------------------------------------------------------- 1 | Yes {{ deferred }} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/iftag/if-expr-filter.jinja: -------------------------------------------------------------------------------- 1 | {% if items|length %} 2 | ifblock 3 | {% endif %} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/importtag/imports-global-macro.jinja: -------------------------------------------------------------------------------- 1 | {% import "tags/macrotag/simple.jinja" %} 2 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/jinjava/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /src/test/resources/eager/eagerly-defers-macro/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | I am foo 2 | 3 | 4 | No more foo 5 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-cycle-as/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | 1 2 | 3 | hello 4 | 5 | 3 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/sets-multiple-vars-deferred-in-child/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | 1 & 2 2 | 3 & 4 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/fortag/loop-index-var.jinja: -------------------------------------------------------------------------------- 1 | {% for number in [0,1,2,3,4,5] %}{{ loop.index0 }}{% endfor %} -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/errors/error.html: -------------------------------------------------------------------------------- 1 |

2 | Error page 3 |

4 | {{ "test"|add(1) }} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/relative-from.jinja: -------------------------------------------------------------------------------- 1 | {% from "./../simple-with-call.jinja" import getPath %} 2 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-unknown-function-errors/test.expected.jinja: -------------------------------------------------------------------------------- 1 | Some () expression 2 | Nothing: () 3 | -------------------------------------------------------------------------------- /src/test/resources/snippets/does-not-override-macro-functions-from-higher-scope.expected.jinja: -------------------------------------------------------------------------------- 1 | bar 2 | 3 | 2nd foo -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/layer-two.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 'foo val' %} 2 | {% set foo_d = deferred %} 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/set-two-variables.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = deferred %} 2 | {% set bar = 'bar' %} 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/fortag/literal-loop-expr.jinja: -------------------------------------------------------------------------------- 1 | {% for number in [0,1,2,3,4,5] %}{{ number }}{% endfor %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/importtag/imports-macro.jinja: -------------------------------------------------------------------------------- 1 | {% import "tags/macrotag/simple-with-call.jinja" as test %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/a-includes-b.jinja: -------------------------------------------------------------------------------- 1 | {% include "tags/includetag/b-includes-a.jinja" %} 2 | A 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/b-includes-a.jinja: -------------------------------------------------------------------------------- 1 | {% include "tags/includetag/a-includes-b.jinja" %} 2 | B 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/include-with-import.jinja: -------------------------------------------------------------------------------- 1 | {% include "tags/macrotag/simple-with-call.jinja" %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/includes-relative-path.jinja: -------------------------------------------------------------------------------- 1 | {% include "./folder/relative-include.html" %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/from-simple-with-call.jinja: -------------------------------------------------------------------------------- 1 | {% from "simple-with-call.jinja" import getPath %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/simple.jinja: -------------------------------------------------------------------------------- 1 | {% macro getPath() -%} 2 | Hello {{ myname }} 3 | {%- endmacro %} 4 | -------------------------------------------------------------------------------- /src/test/resources/eager/does-not-reconstruct-variable-in-wrong-scope/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | ['a', 'b', 'c', 'd'] 2 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-cycle-with-quote/test.expected.jinja: -------------------------------------------------------------------------------- 1 |
2 |
3 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-double-import-modification/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | b 5 | b 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-types-properly/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {{ {'bool': 'true', 'num': '1'} ~ deferred }} 2 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-words-from-inside-nested-expressions/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | a 2 | {{ foo }} 3 | -------------------------------------------------------------------------------- /src/test/resources/eager/uses-unique-macro-names/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | GOODBYE RESOLVED 2 | 3 | HELLO RESOLVED 4 | -------------------------------------------------------------------------------- /src/test/resources/parse/tokenizer/tag-with-trim-chars.jinja: -------------------------------------------------------------------------------- 1 | {% macro echo(what) -%} 2 | echo {{ what }} 3 | {%- endmacro %} -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/import-tree-a.jinja: -------------------------------------------------------------------------------- 1 | {% set something = 'somn' %} 2 | {% set foo_a = a_val %} 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/printer-a.jinja: -------------------------------------------------------------------------------- 1 | {% macro print(x='A') -%} 2 | A_{{ x }}_A 3 | {%- endmacro %} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/printer-b.jinja: -------------------------------------------------------------------------------- 1 | {% macro print(x='B') -%} 2 | B_{{ x }}_B 3 | {%- endmacro %} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/includetag/sets-to-deferred.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = deferred %} 2 | foo is now {{ deferred }}. 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/settag/handles-multiple-vars.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo, foobar = 3, range(6, deferred) %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/errors/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% set test = 'test' %} 5 | {{ test|add(1) }} 6 | 7 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/relative/relative-block-2.jinja: -------------------------------------------------------------------------------- 1 | {% extends "./../relative-block-2-base.jinja" %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/iftag/if-true-elif-true.jinja: -------------------------------------------------------------------------------- 1 | {% if true %} 2 | one 3 | {% elif true %} 4 | two 5 | {% endif %} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/settag/set-string-concat.jinja: -------------------------------------------------------------------------------- 1 | {% set lw_font_size = "font-size: " ~ lw_font_size_base ~ "px; " %} -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-from-import-as/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | from_foo: Hello 8 2 | from_bar: 27 3 | -------------------------------------------------------------------------------- /src/test/resources/parse/tokenizer/multiline-comment.jinja: -------------------------------------------------------------------------------- 1 | hello world. 2 | {# this is a 3 | multi-line comment. #} 4 | goodbye. -------------------------------------------------------------------------------- /src/test/resources/tags/eager/fortag/registers-eager-token.jinja: -------------------------------------------------------------------------------- 1 | {% for item in deferred %} 2 | {{ 'e' }} 3 | {% endfor %} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/macro-a.jinja: -------------------------------------------------------------------------------- 1 | {% macro doer() %} 2 | I am doer 'A', {{ deferred }} 3 | {% endmacro %} -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/macro-b.jinja: -------------------------------------------------------------------------------- 1 | {% macro doer() %} 2 | I am doer 'b', {{ deferred }} 3 | {% endmacro %} -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/errors/extends-outside-block-error.jinja: -------------------------------------------------------------------------------- 1 | {% extends "/errors/outside-block-error.html" %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/rec1.jinja: -------------------------------------------------------------------------------- 1 | {% extends 'rec2.jinja' %} 2 | {% block body %} 3 | foo 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/rec2.jinja: -------------------------------------------------------------------------------- 1 | {% extends 'rec3.jinja' %} 2 | {% block body %} 3 | foobar 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/rec3.jinja: -------------------------------------------------------------------------------- 1 | {% extends 'rec3.jinja' %} 2 | {% block body %} 3 | baz 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/iftag/if-else.jinja: -------------------------------------------------------------------------------- 1 | {% if foo and foo != '' %} 2 | ifblock 3 | {% else %} 4 | elseblock 5 | {% endif %} -------------------------------------------------------------------------------- /src/test/resources/tags/importtag/a-imports-b.jinja: -------------------------------------------------------------------------------- 1 | {% import "tags/importtag/b-imports-a.jinja" %} 2 | {% set a = "foo" %} 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/importtag/b-imports-a.jinja: -------------------------------------------------------------------------------- 1 | {% import "tags/importtag/a-imports-b.jinja" %} 2 | {% set b = "bar" %} 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/importtag/imports-macro-relative.jinja: -------------------------------------------------------------------------------- 1 | {% import "./../macrotag/simple-with-call.jinja" as test %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/includes-self.jinja: -------------------------------------------------------------------------------- 1 | {% include "tags/includetag/includes-self.jinja" %} 2 | hello world 3 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-cycle-in-deferred-for/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | 2 4 | 2 5 | 3 6 | 3 7 | 1 8 | 1 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/keeps-macro-modifications-in-scope/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 3 5 | 2 6 | 3 7 | 3 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-fromed-macro/has-macro.jinja: -------------------------------------------------------------------------------- 1 | {% macro upper(param) %} 2 | {{ param|upper }} 3 | {% endmacro %} -------------------------------------------------------------------------------- /src/test/resources/tags/eager/fortag/registers-eager-token.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for item in deferred %} 2 | e 3 | {% endfor %} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/layer-one.jinja: -------------------------------------------------------------------------------- 1 | {% set bar = 'bar val' %} 2 | {% import 'layer-two.jinja' as double_child %} -------------------------------------------------------------------------------- /src/test/resources/tags/eager/settag/handles-multiple-vars.jinja: -------------------------------------------------------------------------------- 1 | {% set foo, foobar = bar, range((baz/2 + bar)|int, deferred) %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/errors/extends-block-error.jinja: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% extends "/errors/block-error.html" %} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/relative/nested-relative-extends-2.jinja: -------------------------------------------------------------------------------- 1 | {% extends "./../nested-relative-inheritance.html" %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/relative/nested-relative-extends.jinja: -------------------------------------------------------------------------------- 1 | {% extends "./nested-relative-extends-2.jinja" %} 2 | 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/importtag/imports-self.jinja: -------------------------------------------------------------------------------- 1 | {% import "tags/importtag/imports-self.jinja" %} 2 | {% set c = "hello" %} 3 | -------------------------------------------------------------------------------- /src/test/resources/varblocks/withtags-expected.html: -------------------------------------------------------------------------------- 1 |
2 | {% for topic in topic_list %} 3 | 123 4 | {% endfor %} 5 |
6 | -------------------------------------------------------------------------------- /src/test/resources/varblocks/withtags.html: -------------------------------------------------------------------------------- 1 |
2 | {% for topic in topic_list %} 3 | {{ first }} 4 | {% endfor %} 5 |
6 | -------------------------------------------------------------------------------- /src/test/resources/eager/does-not-referential-defer-for-set-vars/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = deferred %} 2 | {{ foo }} and [1]. 3 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-break-in-deferred-for-loop/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | Start loop 2 | i is: 0 3 | i is: 1 4 | End loop -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-break-in-for-loop/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | Start loop 2 | i is: 0 3 | i is: 1 4 | End loop -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-continue-in-for-loop/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | Start loop 2 | i is: 1 3 | i is: 3 4 | End loop -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-modification-in-caller/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | ['a', 'b', 'c'] 2 | ['a', 'b', 'c', 'd'] 3 | -------------------------------------------------------------------------------- /src/test/resources/eager/loads-imported-macro-syntax/test.jinja: -------------------------------------------------------------------------------- 1 | {%- macro a.b() -%} 2 | Lemonade 3 | {% endmacro %} 4 | {{ a.b() }} 5 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-types-properly/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = {'bool': 'true', 'num': '1'} %} 2 | {{ foo ~ deferred }} 3 | -------------------------------------------------------------------------------- /src/test/resources/parse/tokenizer/whitespace-tags.jinja: -------------------------------------------------------------------------------- 1 |
2 | {% if true %} 3 | yay 4 | {% endif %} 5 |
6 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/settag/partially-evaluates-deferred-expression.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = [range(0,bar), range(0, deferred)] %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/errors/extends-include-block-error.jinja: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "/errors/include-block-error.html" %} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/tagcycleexception/template-b.jinja: -------------------------------------------------------------------------------- 1 | {% import 'tags/extendstag/tagcycleexception/template-c.jinja' %} -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/include-two-macros.jinja: -------------------------------------------------------------------------------- 1 | {% from "tags/macrotag/two-macros.jinja" import macro2 %} 2 | 3 | {{ macro2() }} -------------------------------------------------------------------------------- /src/test/resources/tags/settag/set-expr-concat.jinja: -------------------------------------------------------------------------------- 1 | {% set lw_secondary_font_size = "font-size: " ~ (lw_font_size_base - 2) ~ "px; " %} -------------------------------------------------------------------------------- /src/test/resources/eager/allows-variable-sharing-alias-name/test.jinja: -------------------------------------------------------------------------------- 1 | {% import './filters.jinja' as filters %} 2 | 3 | {{ filters }} 4 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-changes-within-deferred-set-block/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | 1 2 | 3 | 4 | 5 | Bar: [1, 2] 6 | Foo: 2 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/runs-for-loop-inside-deferred-for-loop/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for i in deferred %} 2 | 0 3 | 1 4 | {% endfor %} 5 | -------------------------------------------------------------------------------- /src/test/resources/eager/wraps-macro-that-would-change-current-path-in-child-scope/dir2/included.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = deferred %} 2 | {{ foo }} -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/import-tree-b.jinja: -------------------------------------------------------------------------------- 1 | {% import 'import-tree-a.jinja' as a %} 2 | {% set foo_b = b_val + a.foo_a %} 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/settag/partially-evaluates-deferred-expression.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = [[0, 1, 2], range(0, deferred)] %} 2 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/relative-block-2-base.jinja: -------------------------------------------------------------------------------- 1 | {% block test %} 2 | {% include "./hello.html" %} 3 | {% endblock test %} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/fortag/nested-cycle.jinja: -------------------------------------------------------------------------------- 1 | {% for i in [0, 1, 2, 3, 4] %} 2 | {{ loop.cycle(cycle1, cycle2) }} 3 | {% endfor %} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/recursion.jinja: -------------------------------------------------------------------------------- 1 | {% macro hello() -%} 2 | Hello {{ hello() }} 3 | {%- endmacro %} 4 | 5 | {{ hello() }} 6 | -------------------------------------------------------------------------------- /src/test/resources/snippets/does-not-override-call-tag-from-higher-scope.expected.jinja: -------------------------------------------------------------------------------- 1 | 1st macro 2 | 1st caller 3 | 4 | 2nd macro 5 | 2nd caller -------------------------------------------------------------------------------- /src/test/resources/tags/eager/iftag/removes-impossible-if-blocks.expected.jinja: -------------------------------------------------------------------------------- 1 | {% if deferred %} 2 | 1 3 | {% else %} 4 | 4 5 | {% endif %} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/extends-base2.jinja: -------------------------------------------------------------------------------- 1 | {% extends "base2-extends-base1.jinja" %} 2 | {% block message %}foobar{% endblock %} 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/fortag/loop-with-scalar.jinja: -------------------------------------------------------------------------------- 1 | {% for number in the_list %} 2 |

The Number: {{ number }}

3 | {% endfor %} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/c-includes-d-twice.jinja: -------------------------------------------------------------------------------- 1 | {% include "tags/includetag/d.jinja" %} 2 | {% include "tags/includetag/d.jinja" %} 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/import-macro.jinja: -------------------------------------------------------------------------------- 1 | {% macro print_path_macro(var) %} 2 | {{ var|print_path }} 3 | {{ var }} 4 | {% endmacro %} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/import-property-global.jinja: -------------------------------------------------------------------------------- 1 | {% import "tags/settag/set-var-exp.jinja" %} 2 | 3 | {{ primary_line_height }} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/with-args.jinja: -------------------------------------------------------------------------------- 1 | {% macro section_link(link, text) %} 2 | link: {{ link }}, text: {{ text }} 3 | {% endmacro %} 4 | -------------------------------------------------------------------------------- /src/test/resources/eager/allows-deferred-lazy-reference-to-get-overridden/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | B: ['resolved', 'B']. 2 | A: ['a', 'b', 'A']. 3 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-continue-in-deferred-for-loop/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | Start loop 2 | i is: 1 3 | i is: 3 4 | i is: 5 5 | End loop -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-for-loop-var-from-macro/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | RESOLVED{"A":"A"} 2 | 3 | 4 | 5 | RESOLVED{"B":"B"} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-fromed-macro/test.jinja: -------------------------------------------------------------------------------- 1 | {% from './has-macro.jinja' import upper as to_upper %} 2 | 3 | {{ to_upper(deferred) }} -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-value-used-in-deferred-imported-macro/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | resolved 1 2 | 3 | 4 | resolved resolved 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/import-tree-c.jinja: -------------------------------------------------------------------------------- 1 | {% import 'import-tree-b.jinja' as b %} 2 | {% set foo_c = c_val + b.foo_b + b.a.foo_a %} 3 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/extends-self.jinja: -------------------------------------------------------------------------------- 1 | {% extends "extends-self.jinja" %} 2 | {% block header %} 3 | hello world 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/parentvars-settings.html: -------------------------------------------------------------------------------- 1 | {% set colors = { 2 | 'background': '#f5f5f5' 3 | } %} 4 | {% set foo = 'bar' %} -------------------------------------------------------------------------------- /src/test/resources/tags/importtag/errors/import-macro.jinja: -------------------------------------------------------------------------------- 1 | {% import "tags/importtag/errors/macro-with-error.jinja" %} 2 | 3 | {{ doSomething() }} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/simple-with-call.jinja: -------------------------------------------------------------------------------- 1 | {% macro getPath() -%} 2 | Hello {{ myname }} 3 | {%- endmacro %} 4 | 5 | {{ getPath() }} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/settag/set-var-exp.jinja: -------------------------------------------------------------------------------- 1 | {% set primary_line_height = primary_font_size_num*1.5 %} 2 | {% set secondary_line_height = 1.5 %} 3 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-call-tag-with-deferred-argument/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | resolved 2 | 3 | macro 1 4 | 5 | resolved1 6 | 7 | macro2 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-non-deferred-import-vars/test.expected.jinja: -------------------------------------------------------------------------------- 1 | foo: Hello 3 2 | bar: 22 3 | --- 4 | simple.foo: Hello 7 5 | simple.bar: 26 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/supplements/simple-with-call.jinja: -------------------------------------------------------------------------------- 1 | {% macro getPath() -%} 2 | Hello {{ myname }} 3 | {%- endmacro %} 4 | 5 | {{ getPath() }} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/autoescapetag/autoescape.jinja: -------------------------------------------------------------------------------- 1 | 1. {{ myvar }} 2 | {% autoescape %} 3 | 2. {{ myvar }} 4 | {% endautoescape %} 5 | 3. {{ myvar }} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/import-macro.jinja: -------------------------------------------------------------------------------- 1 | {% macro print_path_macro(var) %} 2 | {{ var|print_path }} 3 | {{ var }} 4 | {% endmacro %} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/importtag/imports-null.jinja: -------------------------------------------------------------------------------- 1 | {% set bar = 'bar' %} 2 | {% import 'tags/importtag/null-value.jinja' %} 3 | {{ foo }} 4 | {{ bar }} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/settag/set-multivar-unbalanced-vals.jinja: -------------------------------------------------------------------------------- 1 | {% set myvar1, myvar2, myvar3, myvar4 = 2 | 'foo', 3 | bar, 4 | "yoooooo" 5 | %} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/commits-variables-from-do-tag-when-partially-resolved/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | L0: ['a'] 2 | L1: ['b'] 3 | L2: ['c', 'resolved'] 4 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-import-vars/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | foo: Hello 4 2 | bar: 23 3 | --- 4 | simple.foo: Hello 8 5 | simple.bar: 27 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/iftag/handles-deferred-in-regular.jinja: -------------------------------------------------------------------------------- 1 | {% if foo %} 2 | Yes {{ deferred }} 3 | {% else %} 4 | No {{ deferred }} 5 | {% endif %} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/fortag/nested-fors.jinja: -------------------------------------------------------------------------------- 1 | {% for i in [0, 1] %} 2 | {% for j in [2, 3] %} 3 | {{ i }}{{ j }} 4 | {% endfor %} 5 | {% endfor %} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/importtag/errors/include.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = "asdfas" %} 2 | 3 | 4 | 5 | 6 | 7 | {% include "tags/importtag/errors/base.jinja" %} 8 | -------------------------------------------------------------------------------- /src/test/resources/tags/settag/set-multivar.jinja: -------------------------------------------------------------------------------- 1 | {% set myvar1, myvar2, myvar3, myvar4 = 2 | 'foo', 3 | bar, 4 | (1, 2, 3, 4), 5 | "yoooooo" 6 | %} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-complex-raw/test.expected.jinja: -------------------------------------------------------------------------------- 1 | 1 2 | {% raw %}\ 3 | {{ 2 }}\ 4 | {% endraw %} 5 | 3 6 | {% raw %}\ 7 | {{ 4 }}\ 8 | {% endraw %} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-cycle-with-quote/test.jinja: -------------------------------------------------------------------------------- 1 | {% for i in range(2) -%} 2 | {% cycle "
",'
' %} 3 | {% endfor %} 4 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-in-cycle/test.jinja: -------------------------------------------------------------------------------- 1 | {%- set foo = [1,2,3] -%} 2 | {%- for item in foo %} 3 | {% cycle item,deferred %} 4 | {%- endfor -%} 5 | -------------------------------------------------------------------------------- /src/test/resources/eager/preserves-value-set-in-if/test.jinja: -------------------------------------------------------------------------------- 1 | 2 2 | {% set foo = 2 %}{% if deferred %} 3 | {% set foo = deferred %} 4 | {% endif %} 5 | {{ foo }} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-aliased-macro/takes-param.jinja: -------------------------------------------------------------------------------- 1 | {% macro takes_param(foo) %} 2 | {% print foo %} 3 | {% endmacro %} 4 | 5 | {% set bar = 'bar' %} -------------------------------------------------------------------------------- /src/test/resources/eager/uses-unique-macro-names/macro-with-filter.jinja: -------------------------------------------------------------------------------- 1 | {% macro foo() -%} 2 | Hello {{ myname }} 3 | {%- endmacro %} 4 | {% set b = foo()|upper %} 5 | -------------------------------------------------------------------------------- /src/test/resources/filter/complex-chained.jinja: -------------------------------------------------------------------------------- 1 | topic.name|replace('&', '&')|replace("'", "'")|replace('"', '"')|replace('<', '<')|replace('>', '>') -------------------------------------------------------------------------------- /src/test/resources/parse/tokenizer/tag-with-quot-in-attr.jinja: -------------------------------------------------------------------------------- 1 | {% widget_block rich_text "module" overrideable=True, label='

We\'ve included a great symbol

' %} -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/import-macro-applies-val.jinja: -------------------------------------------------------------------------------- 1 | {% set val = 5 -%} 2 | {% macro apply(param) -%} 3 | {{ val ~ param }} 4 | {%- endmacro %} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/cat.html: -------------------------------------------------------------------------------- 1 | .^----^. 2 | (= o O =) 3 | (___V__) 4 | ___/' |--| | 5 | / ,._| | | ' 6 | | \__ |__}-|__} 7 | \___)` 8 | -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/errors/base2.html: -------------------------------------------------------------------------------- 1 | {% set test = 1 + 1 %} 2 | {% include "tags/includetag/errors/base.html" %} 3 | 4 | {% set test = 3 + 1 %} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/settag/set-multivar-unbalanced-vars.jinja: -------------------------------------------------------------------------------- 1 | {% set myvar1, myvar2, myvar3 = 2 | 'foo', 3 | bar, 4 | (1, 2, 3, 4), 5 | "yoooooo" 6 | %} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-ifchanged/test.jinja: -------------------------------------------------------------------------------- 1 | {% for item in deferred %} 2 | {% ifchanged item %} 3 | {{ item + (6 * 7) }} 4 | {% endifchanged %} 5 | {% endfor %} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/fully-defers-filtered-macro/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | BAR 2 | A FLASHY RESOLVED. 3 | A flashy resolved. 4 | --- 5 | 6 | A SILLY RESOLVED. -------------------------------------------------------------------------------- /src/test/resources/eager/handles-clashing-name-in-macro/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% macro func(foo) %} 2 | {{ foo }} 3 | {% endmacro %}\ 4 | {{ func(foo=deferred) }} 5 | 1 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-set-in-inner-scope/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for __ignored__ in [0] %} 2 | {% set foo = deferred %} 3 | {{ foo }} 4 | {% endfor %} 5 | 1 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-unknown-function-errors/test.jinja: -------------------------------------------------------------------------------- 1 | Some ({{ unknown(null) }}) expression 2 | {% set foo = unknown(null) -%} 3 | Nothing: ({{ foo }}) 4 | -------------------------------------------------------------------------------- /src/test/resources/eager/supplements/macro-and-set.jinja: -------------------------------------------------------------------------------- 1 | {% macro foo() -%} 2 | Hello {{ myname }} 3 | {%- endmacro %} 4 | {% set bar = myname + 19 %} 5 | {{ foo() }} 6 | -------------------------------------------------------------------------------- /src/test/resources/filter/urlize.txt: -------------------------------------------------------------------------------- 1 | This is some text. Go to http://www.espn.com if you like sports. Check out http://yahoo.com if you like news. I like https://hubspot.com. -------------------------------------------------------------------------------- /src/test/resources/parse/tokenizer/comment-with-tags.jinja: -------------------------------------------------------------------------------- 1 | {% if foo %} 2 |
3 | {# {% if bar %} 4 | {% endif %} #} 5 |
6 | {% endif %} -------------------------------------------------------------------------------- /src/test/resources/tags/eager/unlesstag/handles-deferred-in-regular.jinja: -------------------------------------------------------------------------------- 1 | {% unless foo %} 2 | No {{ deferred }} 3 | {% else %} 4 | Yes {{ deferred }} 5 | {% endif %} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/iftag/if-elif-else.jinja: -------------------------------------------------------------------------------- 1 | {% if foo and foo != '' %} 2 | ifblock 3 | {% elif bar == 'val' %} 4 | elifblock 5 | {% else %} 6 | elseblock 7 | {% endif %} -------------------------------------------------------------------------------- /src/test/resources/tags/importtag/errors/base.jinja: -------------------------------------------------------------------------------- 1 | {% set a = "foo" %} 2 | {% import "tags/importtag/errors/file-with-error.jinja" %} 3 | {% set test = 1 + 2 %} 4 | 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/importtag/errors/file-with-error.jinja: -------------------------------------------------------------------------------- 1 | {% set test = 'test' %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {{ test|add(1) }} 12 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-ifchanged/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for item in deferred %} 2 | {% ifchanged item %} 3 | {{ item + 42 }} 4 | {% endifchanged %} 5 | {% endfor %} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/runs-for-loop-inside-deferred-for-loop/test.jinja: -------------------------------------------------------------------------------- 1 | {% for i in deferred -%} 2 | {% for j in [0, 1] %} 3 | {{ j }} 4 | {%- endfor %} 5 | {% endfor %} 6 | -------------------------------------------------------------------------------- /src/test/resources/filter/render/base.jinja: -------------------------------------------------------------------------------- 1 | Body is: {% block body %} 2 | Base body 3 | {% endblock %} 4 | Footer is: {% block footer %} 5 | Base footer 6 | {% endblock %} 7 | -------------------------------------------------------------------------------- /src/test/resources/tags/fortag/multiple-loop-vars.jinja: -------------------------------------------------------------------------------- 1 | {% for key, value in the_dictionary.items() %} 2 |

{{ key }}: {{ value }}

3 | {% endfor %} 4 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/el/ObjectUnwrapper.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.el; 2 | 3 | public interface ObjectUnwrapper { 4 | Object unwrapObject(Object o); 5 | } 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-cycle-in-deferred-for/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for item in deferred %} 2 | {% cycle '1','2','3' %} 3 | {% cycle '1','2','3' %}\ 4 | {% endfor %} 5 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-eager-print-and-do/test.expected.jinja: -------------------------------------------------------------------------------- 1 | [] 2 | [1,2] 3 | {% print deferred %} 4 | {% do deferred.append(1) %} 5 | {% print deferred.append(2) %} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/preserves-value-set-in-if/test.expected.jinja: -------------------------------------------------------------------------------- 1 | 2 2 | {% set foo = 2 %}\ 3 | {% if deferred %} 4 | {% set foo = deferred %} 5 | {% endif %} 6 | {{ foo }} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-map-node/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | foo ff 2 | bar bb 3 | ['resolved', 'resolved'] 4 | 5 | 6 | foo 7 | bar 8 | ['resolved', 'resolved'] 9 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/fortag/handles-multiple-loop-vars.jinja: -------------------------------------------------------------------------------- 1 | {% for item, item2 in deferred %} 2 | {{ 'e' }} 3 | {{ item }} 4 | {{ item2 }} 5 | g 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/parentvars-child.html: -------------------------------------------------------------------------------- 1 | {% extends "parentvars-base.html" %} 2 | 3 | {% block main_column %} 4 |

{{ s.foo }}

5 | {% endblock %} -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/from-a-to-b.jinja: -------------------------------------------------------------------------------- 1 | {% from "from-b-to-c.jinja" import wrap_padding as wp, spacer %} 2 | 3 | wrap-padding: {{ wp }} 4 | wrap-spacer: {{ spacer() }} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/from-b-to-c.jinja: -------------------------------------------------------------------------------- 1 | {% from "from-c-to-a.jinja" import wrap_padding as wp, spacer %} 2 | 3 | wrap-padding: {{ wp }} 4 | wrap-spacer: {{ spacer() }} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/from-c-to-a.jinja: -------------------------------------------------------------------------------- 1 | {% from "from-c-to-a.jinja" import wrap_padding as wp, spacer %} 2 | 3 | wrap-padding: {{ wp }} 4 | wrap-spacer: {{ spacer() }} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/from.jinja: -------------------------------------------------------------------------------- 1 | {% from "pegasus-importable.jinja" import wrap_padding as wp, spacer %} 2 | 3 | wrap-padding: {{ wp }} 4 | wrap-spacer: {{ spacer() }} 5 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-cycle-as/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = [1,2,3] %} 2 | {%- for item in foo %} 3 | {% cycle item,deferred as c %} 4 | {% cycle c %} 5 | {%- endfor -%} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-set-in-inner-scope/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 1 %} 2 | {% for i in range(1) %} 3 | {% set foo = deferred %} 4 | {{ foo }} 5 | {% endfor %} 6 | {{ foo }} 7 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/fortag/handles-multiple-loop-vars.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for item, item2 in deferred %} 2 | e 3 | {{ item }} 4 | {{ item2 }} 5 | g 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/intermediate-b.jinja: -------------------------------------------------------------------------------- 1 | {% import 'printer-b.jinja' as printer %} 2 | {% macro print(x='inter') -%} 3 | {{ printer.print(x) }} 4 | {%- endmacro %} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/relative/relative-block.jinja: -------------------------------------------------------------------------------- 1 | {% extends "./../super-base.html" %} 2 | {% block sidebar %} 3 | {% include "./../hello.html" %} 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/relative/relative-extends.jinja: -------------------------------------------------------------------------------- 1 | {% extends "./../super-base.html" %} 2 | {% block sidebar %} 3 | This is a relative path extends 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/list_kwargs.jinja: -------------------------------------------------------------------------------- 1 | {% macro list_kwargs() %} 2 | {% for k,v in kwargs.items() %} 3 | {{k}}={{v}} 4 | {% endfor %} 5 | {% endmacro %} 6 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/errorcategory/TemplateErrorCategory.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret.errorcategory; 2 | 3 | public interface TemplateErrorCategory {} 4 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/util/HasObjectTruthValue.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.util; 2 | 3 | public interface HasObjectTruthValue { 4 | boolean getObjectTruthValue(); 5 | } 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/allows-variable-sharing-alias-name/filters.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 123 %} 2 | {% set bar = deferred %} 3 | {% set filters = {} %} 4 | {% do filters.update(deferred) %} 5 | -------------------------------------------------------------------------------- /src/test/resources/eager/does-not-override-import-modification-in-for/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | startab 2 | 3 | startab 4 | 5 | 6 | startab 7 | 8 | startab 9 | 10 | start 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-clashing-name-in-macro/test.jinja: -------------------------------------------------------------------------------- 1 | {% macro func(foo) %} 2 | {{ foo }} 3 | {% endmacro %} 4 | {% set foo = 1 %} 5 | {{ func(foo=deferred) }} 6 | {{ foo }} 7 | -------------------------------------------------------------------------------- /src/test/resources/el/dict/dict-with-var-refs.fixture: -------------------------------------------------------------------------------- 1 | {"seven": i_am_seven, "the_list": the_list, "inner_list_literal": ["heya", False], i_am_seven: 7, "inner_dict": {"car keys": "valuable"} } -------------------------------------------------------------------------------- /src/test/resources/tags/eager/includetag/includes-deferred.jinja: -------------------------------------------------------------------------------- 1 | {%- set foo = 'abc' -%} 2 | Foo begins as: {{ foo }} 3 | {% include "./sets-to-deferred.jinja" %} 4 | Foo ends as: {{ foo }} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/errors/outside-block-error.html: -------------------------------------------------------------------------------- 1 | {% block test %} 2 | {% endblock %} 3 | 4 | 5 | 6 | 7 | 8 | {% set test = 'test' %} 9 | {{ test|add(1) }} 10 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/ending-recursion.jinja: -------------------------------------------------------------------------------- 1 | {% macro hello(count) -%} 2 | Hello {% if count > 0 %}{{ hello(count-1) }}{% endif %} 3 | {%- endmacro %} 4 | 5 | {{ hello(5) }} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/from-alias-macro.jinja: -------------------------------------------------------------------------------- 1 | {% from "pegasus-importable.jinja" import wrap_padding as wp, spacer as sp %} 2 | 3 | wrap-padding: {{ wp }} 4 | wrap-spacer: {{ sp() }} -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/from-recursion.jinja: -------------------------------------------------------------------------------- 1 | {% from "from-recursion.jinja" import wrap_padding as wp, spacer %} 2 | 3 | wrap-padding: {{ wp }} 4 | wrap-spacer: {{ spacer() }} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/import.jinja: -------------------------------------------------------------------------------- 1 | {% import "pegasus-importable.jinja" as pegasus %} 2 | 3 | wrap-padding: {{ pegasus.wrap_padding }} 4 | wrap-spacer: {{ pegasus.spacer() }} 5 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-in-ifchanged/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for __ignored__ in [0] %}\ 2 | {{ deferred[1] }}\ 3 | {{ deferred[2] }}\ 4 | {{ deferred[1] }}\ 5 | {% endfor %} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-loop-var-against-deferred-in-loop/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | item1 resolved.item1resolved 2 | item2 resolved.item2resolved 3 | item3 resolved.item3resolved 4 | -------------------------------------------------------------------------------- /src/test/resources/eager/keeps-max-macro-recursion-depth/test.jinja: -------------------------------------------------------------------------------- 1 | {% macro rec(n) -%} 2 | {{ n }} 3 | {% if n > 0 -%} 4 | {{ rec(n-1) }} 5 | {%- endif -%} 6 | {% endmacro %} 7 | {{ rec(3) }} 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-namespace-for-set-tags-using-period/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | namespace({'a': 'aa', 'b': 'b resolved'} ) 2 | namespace({'c': 'cc', 'd': 'd resolved'} ) 3 | -------------------------------------------------------------------------------- /src/test/resources/eager/supplements/deferred-modification.jinja: -------------------------------------------------------------------------------- 1 | {% if deferred %} 2 | 3 | {% set foo = [foo, 'a']|join('') %} 4 | 5 | {% endif %} 6 | 7 | {% set foo = [foo, 'b']|join('') %} 8 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/import-macro-and-var.jinja: -------------------------------------------------------------------------------- 1 | {% set var = [] -%} 2 | {% macro adjust(val) -%} 3 | {% do var.append(val ~ deferred) -%} 4 | {{ val }} 5 | {%- endmacro %} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/super-child.html: -------------------------------------------------------------------------------- 1 | {% extends "super-base.html" %} 2 | 3 | {% block sidebar %} 4 |

Table Of Contents

5 | 6 | {{ super() }} 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/objects/date/DateTimeProvider.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.objects.date; 2 | 3 | public interface DateTimeProvider { 4 | long getCurrentTimeMillis(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/tree/output/OutputNode.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.tree.output; 2 | 3 | public interface OutputNode { 4 | String getValue(); 5 | 6 | long getSize(); 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-eager-child-scoped-vars/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% if deferred %} 2 | {% set foo = 1 %} 3 | 1 4 | {% endif %} 5 | We don't know if someone wanted to access {{ foo }} here! 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-eager-child-scoped-vars/test.jinja: -------------------------------------------------------------------------------- 1 | {% if deferred %} 2 | {% set foo = 1 %} 3 | {{ foo }} 4 | {% endif %} 5 | We don't know if someone wanted to access {{ foo }} here! 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/does-not-reconstruct-variable-in-set-in-wrong-scope/test.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [] %} 2 | {% set foo %} 3 | {% do my_list.append(deferred) %}a 4 | {% endset %} 5 | {{ my_list }} -------------------------------------------------------------------------------- /src/test/resources/eager/doesnt-affect-parent-from-eager-if/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 1 %} 2 | {% if deferred %} 3 | {% set foo = 2 %} 4 | {% else %} 5 | {% set foo = 3 %} 6 | {% endif %} 7 | {{ foo }} 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/fails-on-modification-in-aliased-macro/settings.jinja: -------------------------------------------------------------------------------- 1 | {% set settings = {} %} 2 | 3 | {% macro load_settings() %} 4 | {% do settings.put('foo', 'bar') %} 5 | {% endmacro %} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-same-name-import-var/test.jinja: -------------------------------------------------------------------------------- 1 | {% if deferred %} 2 | {% import './set-var-and-deferred.jinja' as my_var %} 3 | {{ my_var|dictsort(false, 'key') }} 4 | {% endif %} 5 | -------------------------------------------------------------------------------- /src/test/resources/eager/keeps-meta-context-variables-through-import/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set list = deferred %} 2 | 3 | {% set meta = ['overridden'] %}\ 4 | {% do list.append(meta) %} 5 | {{ list }} -------------------------------------------------------------------------------- /src/test/resources/tags/rawtag/hubl.jinja: -------------------------------------------------------------------------------- 1 | {% raw %} 2 |

Blog Posts

3 | 8 | {% endraw %} -------------------------------------------------------------------------------- /src/test/resources/eager/allows-modification-in-resolved-for-loop/test.expected.jinja: -------------------------------------------------------------------------------- 1 | [[0, [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, [11, [12, [13, [14, [15, [16, [17, [18, [19]]]]]]]]]]]]]]]]]]]], 'END'] 2 | -------------------------------------------------------------------------------- /src/test/resources/eager/doesnt-overwrite-elif/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = [0] %} 2 | {% if foo == [9] %}9{% elif deferred && foo.append(1) %}1{% elif deferred && foo.append(2) %}2{% endif %} 3 | {{ foo }} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/fortag/handles-nested-deferred-for-loop.jinja: -------------------------------------------------------------------------------- 1 | {% for item in food_types %} 2 | {% for bar in deferred %} 3 | pastrami {{ item }}. {{ bar }}! 4 | {% endfor %} 5 | {% endfor %} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/extends-tag-dependencies.html: -------------------------------------------------------------------------------- 1 | {% extends "super-base.html" %} 2 | 3 | 4 | {% block sidebar %} 5 |

Table Of Contents

6 | 7 | {{ super() }} 8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/tagcycleexception/template-a.jinja: -------------------------------------------------------------------------------- 1 | {% extends 'tags/extendstag/tagcycleexception/template-b.jinja' %} 2 | {% extends 'tags/extendstag/tagcycleexception/template-d.jinja' %} -------------------------------------------------------------------------------- /src/test/resources/eager/defers-caller/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for __ignored__ in [0] %}\ 2 | Jack says: 3 | {% for __ignored__ in [0] %}\ 4 | How do I get a {{ deferred }}\ 5 | ?{% endfor %}\ 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/does-not-referential-defer-for-set-vars/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = [] %} 2 | {%- set bar = foo %} 3 | {% do foo.append(1) %} 4 | {% set foo = deferred %} 5 | {{ foo }} and {{ bar }}. 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/doesnt-affect-parent-from-eager-if/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 1 %}\ 2 | {% if deferred %} 3 | {% set foo = 2 %} 4 | {% else %} 5 | {% set foo = 3 %} 6 | {% endif %} 7 | {{ foo }} 8 | -------------------------------------------------------------------------------- /src/test/resources/filter/slice-filter-empty.jinja: -------------------------------------------------------------------------------- 1 | {%- for column in items|slice(2, 'hello') %} 2 | {{ loop.index }} 3 | {%- for item in column %} 4 | {{ item }} 5 | {%- endfor %} 6 | {%- endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/filter/slice-filter-zero.jinja: -------------------------------------------------------------------------------- 1 | {%- for column in items|slice(0, 'hello') %} 2 | {{ loop.index }} 3 | {%- for item in column %} 4 | {{ item }} 5 | {%- endfor %} 6 | {%- endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/parse/tokenizer/positions.jinja: -------------------------------------------------------------------------------- 1 | {% if foo %} 2 | {% if bar %} 3 | {{ 1 }} 4 | {# this is a comment #} 5 | {% endif %} 6 | {% raw %}hello world.{% endraw %} 7 | {% endif 8 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/iftag/handles-only-deferred-elif.expected.jinja: -------------------------------------------------------------------------------- 1 | {% if false %}\ 2 | {% elif deferred > 0 %} 3 | Positive {{ deferred }} 4 | {% else %} 5 | Negative {{ deferred }} 6 | {% endif %} 7 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/simple-no-trim.jinja: -------------------------------------------------------------------------------- 1 | {% macro getPath() %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Hello {{ myname }} 9 | 10 | 11 | 12 | 13 | 14 | {% endmacro %} 15 | -------------------------------------------------------------------------------- /src/test/resources/eager/does-not-reconstruct-variable-in-set-in-wrong-scope/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [] %}\ 2 | {% set foo %} 3 | {% do my_list.append(deferred) %}\ 4 | a 5 | {% endset %} 6 | {{ my_list }} -------------------------------------------------------------------------------- /src/test/resources/eager/has-proper-line-stripping/test.expected.jinja: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3{% if deferred > 0 %}\ 4 | {{ deferred }}\ 5 | {% elif deferred == 0 %}\ 6 | null{% else %}\ 7 | {{ deferred }}\ 8 | {% endif %} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/puts-deferred-fromed-macro-in-output/test.jinja: -------------------------------------------------------------------------------- 1 | {%- from "../supplements/simple-with-call.jinja" import getPath -%} 2 | {%- set myname = deferred + (1 + 2) -%} 3 | {% print getPath() %} 4 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-block-set-variables-in-for-loop/test.jinja: -------------------------------------------------------------------------------- 1 | {% for i in range(deferred) %} 2 | {%- macro foo() %} 3 | {{ deferred }} 4 | {% endmacro %} 5 | {{ foo()|int + 3 }} 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-words-from-inside-nested-expressions/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 'a' %}\ 2 | {% do deferred.append('{{ foo }}\ 3 | ') %} 4 | {{ deferred[0] }} 5 | {% print deferred[0] %} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/wraps-macro-that-would-change-current-path-in-child-scope/dir1/macro.jinja: -------------------------------------------------------------------------------- 1 | {% macro foo_importer() -%} 2 | {%- include "../dir2/included.jinja" -%} 3 | {%- print foo -%} 4 | {%- endmacro %} -------------------------------------------------------------------------------- /src/test/resources/filter/slice-filter-big.jinja: -------------------------------------------------------------------------------- 1 | {%- for column in items|slice(999999999, 'hello') %} 2 | {{ loop.index }} 3 | {%- for item in column %} 4 | {{ item }} 5 | {%- endfor %} 6 | {%- endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/filter/slice-filter-negative.jinja: -------------------------------------------------------------------------------- 1 | {%- for column in items|slice(-1, 'hello') %} 2 | {{ loop.index }} 3 | {%- for item in column %} 4 | {{ item }} 5 | {%- endfor %} 6 | {%- endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/filter/slice-filter-replacement.jinja: -------------------------------------------------------------------------------- 1 | {%- for column in items|slice(2, 'hello') %} 2 | {{ loop.index }} 3 | {%- for item in column %} 4 | {{ item }} 5 | {%- endfor %} 6 | {%- endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/parse/tokenizer/comment-with-start-comment-within.jinja: -------------------------------------------------------------------------------- 1 | {# 6. FOOTER AREA SPECIFIC STYLES 2 | {# Footer Background Color -#}{% color "footer_background_color_def" label="Footer Background Color" -%} -------------------------------------------------------------------------------- /src/test/resources/tags/eager/extendstag/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/iftag/handles-only-deferred-elif.jinja: -------------------------------------------------------------------------------- 1 | {% if false %} 2 | {{ foo }} 3 | {% elif deferred > 0 %} 4 | Positive {{ deferred }} 5 | {% else %} 6 | Negative {{ deferred }} 7 | {% endif %} 8 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/double-import-macro.jinja: -------------------------------------------------------------------------------- 1 | {% import 'import-macro.jinja' -%} 2 | {% macro print_path_macro2(var) -%} 3 | {{ var|print_path }} 4 | {{ print_path_macro(var) }} 5 | {%- endmacro %} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/evaluates-non-eager-set/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for item in [0, 1, 2, 3, 4] + deferred %} 2 | {% if item == 5 %} 3 | It is foo! 4 | {% else %} 5 | It is not foo! 6 | {% endif %} 7 | {% endfor %} 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/fails-on-modification-in-aliased-macro/test.jinja: -------------------------------------------------------------------------------- 1 | {% import './settings.jinja' as shared %} 2 | 3 | {% if deferred %} 4 | {{ shared.load_settings() }} 5 | {% endif %} 6 | {{ shared.settings }} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-block-set-in-deferred-if/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 'empty' %} 2 | {% if deferred %} 3 | {% set foo | upper -%} 4 | {{ 'i am iron man' }} 5 | {%- endset %} 6 | {% endif %} 7 | {{ foo }} 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-break-in-deferred-for-loop/test.jinja: -------------------------------------------------------------------------------- 1 | Start loop 2 | {% for i in deferred -%} 3 | {% if i > 1 -%} 4 | {% break -%} 5 | {% endif -%} 6 | i is: {{ i }} 7 | {% endfor -%} 8 | End loop -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-in-ifchanged/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = [1, 1, 2, 1] %} 2 | {%- for item in foo -%} 3 | {%- ifchanged item- %} 4 | {{ deferred[item] }} 5 | {%- endifchanged -%} 6 | {% endfor%} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/puts-deferred-imported-macro-in-output/test.jinja: -------------------------------------------------------------------------------- 1 | {%- import "../supplements/simple-with-call.jinja" as simple -%} 2 | {%- set myname = deferred + (1 + 2) -%} 3 | {% print simple.getPath() %} 4 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/double-import-macro.jinja: -------------------------------------------------------------------------------- 1 | {% import 'import-macro.jinja' -%} 2 | {% macro print_path_macro2(var) -%} 3 | {{ var|print_path }} 4 | {{ print_path_macro(var) }} 5 | {%- endmacro %} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/iftag/if-elif-elif-else.jinja: -------------------------------------------------------------------------------- 1 | {% if foo and foo != '' %} 2 | ifblock 3 | {% elif bar == 'val' %} 4 | elifblock 5 | {% elif elf == 'true' %} 6 | elif2block 7 | {% else %} 8 | elseblock 9 | {% endif %} -------------------------------------------------------------------------------- /src/test/resources/tags/importtag/errors/macro-with-error.jinja: -------------------------------------------------------------------------------- 1 | {% macro doSomething() %} 2 | {% set test = 'test' %} 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | {{ test|add(1) }} 13 | {% endmacro %} 14 | -------------------------------------------------------------------------------- /src/test/resources/tags/settag/set-dictionary.jinja: -------------------------------------------------------------------------------- 1 | {% set the_dictionary = {"seven": i_am_seven, "the_list": the_list, "inner_list_literal": ["heya", false], "i_am_seven": 7, "inner_dict": {"car keys": "valuable"} } %} 2 | -------------------------------------------------------------------------------- /src/test/resources/eager/doesnt-overwrite-elif/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = [0] %}\ 2 | {% if false %}\ 3 | {% elif deferred && foo.append(1) %}\ 4 | 1{% elif deferred && foo.append(2) %}\ 5 | 2{% endif %} 6 | {{ foo }} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-aliased-macro/test.jinja: -------------------------------------------------------------------------------- 1 | {%- import "./takes-param.jinja" as macros -%} 2 | {%- set myname = deferred + (1 + 2) -%} 3 | {% set answer = macros.takes_param(myname) %} 4 | {{ answer }} 5 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-value-used-in-deferred-imported-macro/test.jinja: -------------------------------------------------------------------------------- 1 | {% import './uses-deferred-value-in-macro.jinja' as macros %} 2 | 3 | {{ macros.getValueAnd(1) }} 4 | {{ macros.getValueAnd(deferred) }} 5 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-value-used-in-deferred-imported-macro/uses-deferred-value-in-macro.jinja: -------------------------------------------------------------------------------- 1 | {% set value = deferred %} 2 | {% macro getValueAnd(other) %} 3 | {{ value ~ ' ' ~ other }} 4 | {% endmacro %} 5 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-words-from-inside-nested-expressions/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 'a' %} 2 | {% set bar = 'b' %} 3 | {% do deferred.append('{{ foo }}') %} 4 | {{ deferred[0] }} 5 | {% print deferred[0] %} 6 | -------------------------------------------------------------------------------- /src/test/resources/parse/tokenizer/whitespace-comment-tags.jinja: -------------------------------------------------------------------------------- 1 |
2 | {# a comment #} 3 | yay 4 | {# another comment 5 | This time, over multiple lines 6 | #} 7 | whoop 8 |
9 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/extendstag/defers-block-in-extends-child.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/extendstag/defers-block-in-extends-child.jinja: -------------------------------------------------------------------------------- 1 | {% extends "../eager/extendstag/base.html" %} 2 | 3 | {%- block sidebar -%} 4 |

Table Of Contents

5 | {{ deferred }} 6 | {%- endblock -%} 7 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/iftag/removes-impossible-if-blocks.jinja: -------------------------------------------------------------------------------- 1 | {% if deferred %} 2 | 1 3 | {% elif false %} 4 | 2 5 | {% elif !foo %} 6 | 3 7 | {% elif true %} 8 | 4 9 | {% else %} 10 | 5 11 | {% endif %} 12 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/errors/extends-no-error.jinja: -------------------------------------------------------------------------------- 1 | {% extends "/errors/no-error.html" %} 2 | 3 | 4 | 5 | 6 | {% block test %} 7 | {% set test = 'test' %} 8 | {{ test|add(1) }} 9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/errors/include-block-error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% block test %} 5 | 6 | 7 | {% include "/errors/error.html" %} 8 | 9 | 10 | 11 | {% endblock %} 12 | 13 | 14 | Blah 15 | 16 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/super-base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/imports-macro-referencing-macro.jinja: -------------------------------------------------------------------------------- 1 | {% import "macro-referencing-macro.jinja" as m %} 2 | 3 | {{ m.uses_public_fn('foo') }} 4 | {{ m.uses_private_fn('bar') }} 5 | {{ m.uses_scoped_var() }} 6 | -------------------------------------------------------------------------------- /src/test/resources/varblocks/nestedattrs-expected.html: -------------------------------------------------------------------------------- 1 |
2 | 123 3 |
4 |
5 | outer 6 |
7 |
8 | middle 9 |
10 |
11 | inner 12 |
13 |
14 | innerer 15 |
16 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/random/RandomNumberGeneratorStrategy.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.random; 2 | 3 | public enum RandomNumberGeneratorStrategy { 4 | THREAD_LOCAL, 5 | CONSTANT_ZERO, 6 | DEFERRED, 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/correctly-defers-with-multiple-loops/test.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [] %} 2 | {% for i in range(2) %} 3 | {% for j in deferred %} 4 | {% do my_list.append(i) %} 5 | {% endfor %} 6 | {% endfor %} 7 | {{ my_list }} -------------------------------------------------------------------------------- /src/test/resources/eager/handles-continue-in-deferred-for-loop/test.jinja: -------------------------------------------------------------------------------- 1 | Start loop 2 | {% for i in deferred -%} 3 | {% if i % 2 == 0 -%} 4 | {% continue -%} 5 | {% endif -%} 6 | i is: {{ i }} 7 | {% endfor -%} 8 | End loop -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-break-in-for-loop/test.jinja: -------------------------------------------------------------------------------- 1 | Start loop 2 | {% for i in range(5) -%} 3 | {% if i > deferred -%} 4 | {% break -%} 5 | {% endif -%} 6 | i is: {{ i }} 7 | {% endfor -%} 8 | End loop -------------------------------------------------------------------------------- /src/test/resources/eager/handles-set-in-for/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set list = [] %}\ 2 | {% for item in deferred %} 3 | {% set count = 0 %} 4 | {% do list.append(0) %} 5 | {% set count = 1 %} 6 | 1 7 | {% endfor %} 8 | {{ list }} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-nested-value-in-string-representation/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | map.foo: Foo is I am foo. 2 | map.bar: Bar is I am bar. 3 | 4 | 5 | 6 | a 7 | 8 | 9 | 10 | 11 | {'b': 'b'} 12 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/extendstag/base-deferred.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/extendstag/reconstructs-deferred-outside-block.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/errors/block-error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% block test %} 15 | {% set test = 'test' %} 16 | {{ test|add(1) }} 17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /src/test/resources/deferred/set-within-lower-scope.jinja: -------------------------------------------------------------------------------- 1 | {% for item in resolved %} 2 | {% set varSetInside = 'inside first scope' %} 3 | {% if deferredValue %} 4 | {{ varSetInside }} 5 | {% endif %} 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-break-in-deferred-for-loop/test.expected.jinja: -------------------------------------------------------------------------------- 1 | Start loop 2 | {% for i in deferred %}\ 3 | {% if i > 1 %}\ 4 | {% break '' %}\ 5 | {% endif %}\ 6 | i is: {{ i }} 7 | {% endfor %}\ 8 | End loop -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "benchmark/liquid"] 2 | path = benchmark/liquid 3 | url = https://github.com/Shopify/liquid.git 4 | [submodule "benchmark/jinja2"] 5 | path = benchmark/jinja2 6 | url = https://github.com/mitsuhiko/jinja2.git 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/evaluates-non-eager-set/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 5.5|int %} 2 | {% for item in range(0, foo) + deferred %} 3 | {% if item == foo %} 4 | It is foo! 5 | {% else %} 6 | It is not foo! 7 | {% endif %} 8 | {% endfor %} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-continue-in-for-loop/test.jinja: -------------------------------------------------------------------------------- 1 | Start loop 2 | {% for i in range(5) -%} 3 | {% if i % deferred == 0 -%} 4 | {% continue -%} 5 | {% endif -%} 6 | i is: {{ i }} 7 | {% endfor -%} 8 | End loop -------------------------------------------------------------------------------- /src/test/resources/eager/has-proper-line-stripping/test.jinja: -------------------------------------------------------------------------------- 1 | 1 2 | {% do 1 -%} 3 | 2 4 | 3{% if deferred > 0 -%} 5 | {{ deferred }} 6 | {%- elif deferred == 0 -%} 7 | null 8 | {%- else -%} 9 | {{ deferred }} 10 | {%- endif %} 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/preserves-raw-inside-deferred-set-block/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo %} 2 | {% if deferred %} 3 | {% raw %}{{ 'fire' }}{% endraw %} 4 | {% else %} 5 | {{ 'water' }} 6 | {% endif %} 7 | {% endset %} 8 | {% print foo %} 9 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/extendstag/defers-super-block-with-deferred.jinja: -------------------------------------------------------------------------------- 1 | {% extends "../eager/extendstag/base-deferred.html" %} 2 | 3 | {%- block sidebar -%} 4 |

Table Of Contents

5 | {{ super() }} 6 | {%- endblock -%} 7 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/iftag/handles-deferred-in-eager.expected.jinja: -------------------------------------------------------------------------------- 1 | {% if 1 == deferred %} 2 | 1 is {{ deferred }} 3 | {% elif deferred > 0 %} 4 | Positive {{ deferred }} 5 | {% else %} 6 | Negative {{ deferred }} 7 | {% endif %} 8 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/iftag/handles-deferred-in-eager.jinja: -------------------------------------------------------------------------------- 1 | {% if foo == deferred %} 2 | {{ foo }} is {{ deferred }} 3 | {% elif deferred > 0 %} 4 | Positive {{ deferred }} 5 | {% else %} 6 | Negative {{ deferred }} 7 | {% endif %} 8 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/tag/FlexibleTag.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.tag; 2 | 3 | import com.hubspot.jinjava.tree.parse.TagToken; 4 | 5 | public interface FlexibleTag { 6 | boolean hasEndTag(TagToken tagToken); 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-caller/test.jinja: -------------------------------------------------------------------------------- 1 | {%- macro says_something(person) -%} 2 | {{ person }} says: 3 | {{ caller() }} 4 | {%- endmacro -%} 5 | {%- call says_something('Jack') -%} 6 | How do I get a {{ deferred }}? 7 | {%- endcall -%} 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-auto-escape/test.jinja: -------------------------------------------------------------------------------- 1 | {% autoescape %} 2 | 1. {% print myvar %} (Only expression nodes get escaped currently) 3 | 2. {% print deferred %} 4 | 3. {{ myvar }} 5 | 4. {{ deferred }} 6 | {% endautoescape %} 7 | 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-block-set-in-deferred-if/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 'empty' %}\ 2 | {% if deferred %} 3 | {% set foo %}\ 4 | i am iron man{% endset %}\ 5 | {% set foo = 'I AM IRON MAN' %} 6 | {% endif %} 7 | {{ foo }} 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-continue-in-deferred-for-loop/test.expected.jinja: -------------------------------------------------------------------------------- 1 | Start loop 2 | {% for i in deferred %}\ 3 | {% if i % 2 == 0 %}\ 4 | {% continue '' %}\ 5 | {% endif %}\ 6 | i is: {{ i }} 7 | {% endfor %}\ 8 | End loop -------------------------------------------------------------------------------- /src/test/resources/eager/handles-set-in-for/test.jinja: -------------------------------------------------------------------------------- 1 | {% set list = [] %} 2 | {% for item in deferred %} 3 | {% set count = 0 %} 4 | {% do list.append(count) %} 5 | {% set count = count + 1 %} 6 | {{ count }} 7 | {% endfor %} 8 | {{ list }} 9 | -------------------------------------------------------------------------------- /src/test/resources/filter/batch-filter.jinja: -------------------------------------------------------------------------------- 1 | 2 | {%- for row in items|batch(3, 'foo') %} 3 | 4 | {%- for column in row %} 5 | 6 | {%- endfor %} 7 | 8 | {%- endfor %} 9 |
{{ column }}
10 | -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/include-tag-dependencies.html: -------------------------------------------------------------------------------- 1 | {% include "tags/includetag/hello.html" %} 2 | {% include "tags/includetag/cat.html" %} 3 | {% include "tags/includetag/hello.html" %} 4 | {% include "tags/includetag/cat.html" %} 5 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/recursion_indirect.jinja: -------------------------------------------------------------------------------- 1 | {% macro hello() -%} 2 | Hello, {{ goodbye() }} 3 | {%- endmacro %} 4 | 5 | {% macro goodbye() -%} 6 | Goodbye, {{ hello() }} 7 | {%- endmacro %} 8 | 9 | {{ goodbye() }} 10 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/unlesstag/handles-deferred-in-eager.jinja: -------------------------------------------------------------------------------- 1 | {% unless foo != deferred %} 2 | {{ foo }} is {{ deferred }} 3 | {% elif deferred > 0 %} 4 | Positive {{ deferred }} 5 | {% else %} 6 | Negative {{ deferred }} 7 | {% endif %} 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-large-loop/test.jinja: -------------------------------------------------------------------------------- 1 | {% for i in range(10) %} 2 | Small {{ i }} {{ deferred }} {{ deferred ~ i }} 3 | {% endfor %} 4 | {% for i in range(500 + 100) %} 5 | Big {{ i }} {{ deferred }} {{ deferred ~ i }} 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/doesnt-double-append-in-deferred-set/test.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [] %} 2 | {% set foo %} 3 | {% do my_list.append('a') %}a 4 | {% if deferred %} 5 | {% do my_list.append('b') %}b 6 | {% endif %} 7 | {% endset %} 8 | {{ my_list }} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/uses-unique-macro-names/test.jinja: -------------------------------------------------------------------------------- 1 | {% set myname = deferred %} 2 | {% macro foo() %} 3 | Goodbye {{ myname }} 4 | {% endmacro %} 5 | {% set a = foo()|upper %} 6 | {% import './macro-with-filter.jinja' %} 7 | {{ a }} 8 | {{ b }} 9 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/unlesstag/handles-deferred-in-eager.expected.jinja: -------------------------------------------------------------------------------- 1 | {% unless 1 != deferred %} 2 | 1 is {{ deferred }} 3 | {% elif deferred > 0 %} 4 | Positive {{ deferred }} 5 | {% else %} 6 | Negative {{ deferred }} 7 | {% endunless %} 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-macro-in-expression/test.jinja: -------------------------------------------------------------------------------- 1 | {%- macro plus(foo, add) -%} 2 | {{ foo + (add|int) }} 3 | {%- endmacro -%} 4 | {{ plus(1, 1) }} 5 | {{ plus(deferred, 1.1) }} 6 | {%- set deferred = deferred + 2 %} 7 | {{ plus(deferred, 3.1) }} 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/doesnt-double-append-in-deferred-set/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = ['a'] %}\ 2 | {% set foo %} 3 | a 4 | {% if deferred %} 5 | {% do my_list.append('b') %}\ 6 | b 7 | {% endif %} 8 | {% endset %} 9 | {{ my_list }} 10 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-continue-in-for-loop/test.expected.jinja: -------------------------------------------------------------------------------- 1 | Start loop 2 | {% for i in [0, 1, 2, 3, 4] %}\ 3 | {% if i % deferred == 0 %}\ 4 | {% continue '' %}\ 5 | {% endif %}\ 6 | i is: {{ i }} 7 | {% endfor %}\ 8 | End loop -------------------------------------------------------------------------------- /src/test/resources/eager/handles-loop-var-against-deferred-in-loop/test.jinja: -------------------------------------------------------------------------------- 1 | {% set items = ['item1', 'item2', 'item3'] %} 2 | {%- for item in items -%} 3 | {{ item }} {{ deferred }}. 4 | {%- set temp = item ~ deferred -%} 5 | {{ temp }} 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/preserves-raw-inside-deferred-set-block/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo %} 2 | {% if deferred %} 3 | {% raw %}\ 4 | {{ 'fire' }}\ 5 | {% endraw %} 6 | {% else %} 7 | water 8 | {% endif %} 9 | {% endset %} 10 | {% print foo %} 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/sets-multiple-vars-deferred-in-child/test.expected.jinja: -------------------------------------------------------------------------------- 1 | 1 & 2{% set bar = 2 %}\ 2 | {% set foo = 3 %}\ 3 | {% if deferred %}\ 4 | {% set bar = 4 %}\ 5 | {% else %}\ 6 | {% set foo = 5 %}\ 7 | {% endif %} 8 | {{ foo }} & {{ bar }} 9 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/extendstag/defers-super-block-with-deferred.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar 3 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-macro-in-for/test.jinja: -------------------------------------------------------------------------------- 1 | {%- macro macro_append(num) -%} 2 | {%- do my_list.append(num) -%}{{ my_list }}{# is a string #} 3 | {%- endmacro -%} 4 | {% for item in macro_append(deferred)|split(',',2) %} 5 | {{ item }} 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-from-import-as/test.jinja: -------------------------------------------------------------------------------- 1 | {%- set myname = deferred + (3 + 4) -%} 2 | {%- from "../supplements/macro-and-set.jinja" import foo as from_foo, bar as from_bar -%} 3 | from_foo: {{ from_foo() }} 4 | from_bar: {{ from_bar }} 5 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-double-import-modification/test.jinja: -------------------------------------------------------------------------------- 1 | {% import "../supplements/deferred-modification.jinja" as bar1 %} 2 | --- 3 | {% import "../supplements/deferred-modification.jinja" as bar2 %} 4 | --- 5 | {{ bar1.foo }} 6 | {{ bar2.foo }} 7 | -------------------------------------------------------------------------------- /src/test/resources/parse/tokenizer/tag-with-all-escaped-quotes.jinja: -------------------------------------------------------------------------------- 1 | {# This print tag is invalid, but it should not cause the rest of the template to break #} 2 | {% print \"foo\" %} 3 | Start 4 | {% if true %} 5 | The dog says: "Woof!" 6 | {% endif %} 7 | End 8 | -------------------------------------------------------------------------------- /src/test/resources/tags/includetag/errors/base.html: -------------------------------------------------------------------------------- 1 |

2 | Test file 3 |

4 | 5 | {% set test = 1 + 1 %} 6 | 7 | {% include "tags/includetag/errors/error.html" %} 8 | 9 |

10 | End test 11 |

12 | 13 | {{ "test"|subtract(1) }} 14 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/array-def-val.jinja: -------------------------------------------------------------------------------- 1 | {% macro prefix(property, value, prefixes = ['webkit', 'moz'], prefixval = false) %} 2 | property: {{ property }}, value: {{ value }}, prefixes: {{ prefixes }}, prefixval: {{ prefixval }} 3 | {% endmacro %} 4 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/features/FeatureActivationStrategy.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.features; 2 | 3 | import com.hubspot.jinjava.interpret.Context; 4 | 5 | public interface FeatureActivationStrategy { 6 | boolean isActive(Context context); 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/deferred/set-in-deferred.jinja: -------------------------------------------------------------------------------- 1 | {% set reference = deferredValue %} 2 | {% if reference == 'resolved' %} 3 | {% set varSetInside = 'set inside' %} 4 | {% set a, b, c = 'x','y','z' %} 5 | {{ a ~ b ~ c }} 6 | {% endif %} 7 | {{ varSetInside }} 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-macro-in-if/test.jinja: -------------------------------------------------------------------------------- 1 | {%- macro macro_append(num) -%} 2 | {%- do my_list.append(num) -%}{{ my_list }}{# is a string #} 3 | {%- endmacro -%} 4 | {% if my_list == macro_append(deferred)|split(',',2) %} 5 | {{ my_list }} 6 | {% endif %} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/doesnt-double-append-in-deferred-if-tag/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = [0, 1] %}\ 2 | {% if deferred == true %} 3 | [0, 1] 4 | {% do foo.append(2) %} 5 | {% else %} 6 | [0, 1] 7 | {% do foo.append(3) %} 8 | {% endif %} 9 | {{ foo }} 10 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-eager-print-and-do/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = [] %} 2 | {% print foo %} 3 | {% do foo.append(bar) %} 4 | {% print foo.append(bar + 1) %} 5 | {% print deferred %} 6 | {% do deferred.append(bar) %} 7 | {% print deferred.append(bar + 1) %} 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/doesnt-double-append-in-deferred-if-tag/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = [0] %} 2 | {% if deferred == foo.append(1) %} 3 | {{ foo }} 4 | {% do foo.append(2) %} 5 | {% else %} 6 | {{ foo }} 7 | {% do foo.append(3) %} 8 | {% endif %} 9 | {{ foo }} 10 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-cycle-in-deferred-for/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = ['1','2','3'] %} 2 | {% set one = '1' %} 3 | {% set two = '2' %} 4 | {% set three = '3' %} 5 | {%- for item in deferred %} 6 | {% cycle foo %} 7 | {% cycle one,two,three %} 8 | {%- endfor -%} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-in-namespace/test.jinja: -------------------------------------------------------------------------------- 1 | {% set ns1 = namespace(a=false) %} 2 | {% set ns2 = namespace() %} 3 | {% do ns2.update({'a': deferred}) %} 4 | {% if deferred %} 5 | {% set ns1.a = true %} 6 | {% endif %} 7 | {{ ns1.a }} 8 | {{ ns2.a }} 9 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/importtag/import-tree-d.jinja: -------------------------------------------------------------------------------- 1 | {% import 'import-tree-c.jinja' as c %} 2 | {% set foo_d = c.foo_c + c.b.foo_b + c.b.a.foo_a %} 3 | {% import 'import-tree-b.jinja' as b2 %} 4 | {% set resolvable = 12345 %} 5 | {% set bar = foo_d + b2.foo_b %} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/fortag/loop-last-var.jinja: -------------------------------------------------------------------------------- 1 | {% for number in the_list %} 2 | {% if loop.last %} 3 | This is the last number, it should be seven: {{ number }} 4 | {% else %} 5 |

The Number: {{ number }}

6 | {% endif %} 7 | {% endfor %} 8 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/IndexOutOfRangeException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | public class IndexOutOfRangeException extends InterpretException { 4 | 5 | public IndexOutOfRangeException(String msg) { 6 | super(msg); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/OneTimeReconstructible.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | public interface OneTimeReconstructible extends DeferredValue { 4 | boolean isReconstructed(); 5 | 6 | void setReconstructed(boolean reconstructed); 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-duplicate-variable-reference-speculative-modification/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = ['a', 1] %}\ 2 | {% set bar = foo %}\ 3 | {% if deferred %} 4 | {% do bar.append(2) %} 5 | {% endif %} 6 | {% do bar.append(3) %} 7 | {{ foo ~ 'and' ~ bar }} 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/keeps-meta-context-variables-through-import/test.jinja: -------------------------------------------------------------------------------- 1 | {% set meta = ['overridden'] %} 2 | {% set list = deferred %} 3 | {% import '../../eager/keeps-meta-context-variables-through-import/import-target.jinja' %} 4 | {% do list.append(meta) %} 5 | {{ list }} -------------------------------------------------------------------------------- /src/test/resources/eager/puts-deferred-fromed-macro-in-output/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set myname = deferred + 3 %}\ 2 | {% set __macro_getPath_1519775617_temp_variable_1__ %}\ 3 | Hello {{ myname }}\ 4 | {% endset %}\ 5 | {% print __macro_getPath_1519775617_temp_variable_1__ %} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/puts-deferred-imported-macro-in-output/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set myname = deferred + 3 %}\ 2 | {% set __macro_getPath_1519775617_temp_variable_1__ %}\ 3 | Hello {{ myname }}\ 4 | {% endset %}\ 5 | {% print __macro_getPath_1519775617_temp_variable_1__ %} 6 | -------------------------------------------------------------------------------- /src/test/resources/snippets/uses-lower-scope-value-in-macro-evaluation.jinja: -------------------------------------------------------------------------------- 1 | {% set val = 1 %} 2 | {% macro foo() -%} 3 | {{ val }} 4 | {%- endmacro %} 5 | {% for i in range(1) %} 6 | {{ foo() }} 7 | {%- set val = 2 %} 8 | {{ foo() }} 9 | {%- endfor %} 10 | {{ val }} 11 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/loader/LocationResolver.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.loader; 2 | 3 | import com.hubspot.jinjava.interpret.JinjavaInterpreter; 4 | 5 | public interface LocationResolver { 6 | String resolve(String path, JinjavaInterpreter interpreter); 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/deferred/deferred-map-access.jinja: -------------------------------------------------------------------------------- 1 | {% set reference = deferredValue %} 2 | {% if reference == 'resolved' %} 3 | {% set varSetInside = imported.map[deferredValue2.nonexistentprop] %} 4 | {{ deferredValue2.nonexistentprop }} 5 | {% endif %} 6 | {{ varSetInside }} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/allows-meta-context-var-overriding/test.expected.jinja: -------------------------------------------------------------------------------- 1 | 0 2 | META 3 | {% for meta in deferred %} 4 | {{ meta }}\ 5 | {% endfor %} 6 | META 7 | {% set meta = [] %}\ 8 | {% if deferred %} 9 | {% do meta.append(1) %} 10 | {% endif %} 11 | {{ meta }} 12 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-higher-scope-reference-modification/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | C: ['a', 'b', 'c']. 2 | B: ['a', 'b', 'c', 'B']. 3 | A: ['a', 'b', 'c', 'B', 'A']. 4 | --- 5 | 6 | C: ['a', 'b', 'c']. 7 | B: ['a', 'b', 'c', 'B']. 8 | A: ['a', 'b', 'c', 'B', 'A']. 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/scopes-resetting-bindings/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [0] %}\ 2 | {% for i in deferred %} 3 | {% for j in deferred %} 4 | {% if deferred %} 5 | {% do my_list.append(1) %} 6 | {% endif %} 7 | {% endfor %} 8 | {% endfor %} 9 | {{ my_list }} 10 | -------------------------------------------------------------------------------- /src/test/resources/filter/slice-filter.jinja: -------------------------------------------------------------------------------- 1 |
2 | {%- for column in items|slice(3) %} 3 | 8 | {%- endfor %} 9 |
-------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/def-vals.jinja: -------------------------------------------------------------------------------- 1 | {% macro article(title, thumb, link, summary, last = false) %} 2 | {% if title %} 3 | title: {{ title }}, thumb: {{ thumb }}, link: {{ link }}, summary: {{ summary }}, last: {{ last }} 4 | {% endif %} 5 | {% endmacro %} 6 | -------------------------------------------------------------------------------- /src/test/resources/tags/rawtag/comment.jinja: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | 3 | 10 | 11 | {% endraw %} 12 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-changes-within-deferred-set-block/test.expected.jinja: -------------------------------------------------------------------------------- 1 | 1 2 | {% set bar = [1] %}\ 3 | {% set foo = '1' %}\ 4 | {% if deferred %} 5 | {% set foo %}\ 6 | 2{% do bar.append(2) %}\ 7 | {% endset %} 8 | {% endif %} 9 | Bar: {{ bar }} 10 | Foo: {{ foo }} 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/doesnt-double-append-in-deferred-macro/test.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [] %} 2 | {% macro foo() %} 3 | {% do my_list.append('a') %}a 4 | {% if deferred %} 5 | {% do my_list.append('b') %}b 6 | {% endif %} 7 | {% endmacro %} 8 | {{ foo() }} 9 | {{ my_list }} 10 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-auto-escape/test.expected.jinja: -------------------------------------------------------------------------------- 1 | 1. foo < bar (Only expression nodes get escaped currently) 2 | 2. {% autoescape %}\ 3 | {% print deferred %}\ 4 | {% endautoescape %} 5 | 3. foo < bar 6 | 4. {% autoescape %}\ 7 | {{ deferred }}\ 8 | {% endautoescape %} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/reverts-modification-with-deferred-loop/test.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [] %} 2 | {% for i in range(2) %} 3 | {% for j in deferred %} 4 | {% if loop.first %} 5 | {% do my_list.append(1) %} 6 | {% endif %} 7 | {% endfor %} 8 | {% endfor %} 9 | {{ my_list }} 10 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/objects/serialization/PyishBlockSetSerializable.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.objects.serialization; 2 | 3 | import com.google.common.annotations.Beta; 4 | 5 | @Beta 6 | public interface PyishBlockSetSerializable { 7 | String getBlockSetBody(); 8 | } 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-in-namespace/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set ns2 = namespace({} ) %}\ 2 | {% do ns2.update({'a': deferred}) %} 3 | {% set ns1 = namespace({'a': false} ) %}\ 4 | {% if deferred %} 5 | {% set ns1.a = true %} 6 | {% endif %} 7 | {{ ns1.a }} 8 | {{ ns2.a }} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-duplicate-variable-reference-speculative-modification/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = ['a'] -%} 2 | {%- set bar = foo -%} 3 | {% do bar.append(1) %} 4 | {% if deferred %} 5 | {% do bar.append(2) %} 6 | {% endif %} 7 | {% do bar.append(3) %} 8 | {{ foo ~ 'and' ~ bar }} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/sets-multiple-vars-deferred-in-child/test.jinja: -------------------------------------------------------------------------------- 1 | {%- set foo, bar = 1, 2 -%} 2 | {{ foo }} & {{ bar }} 3 | {%- set foo = 3 -%} 4 | {%- if deferred -%} 5 | {%- set bar = 4 -%} 6 | {%- else -%} 7 | {%- set foo = 5 -%} 8 | {%- endif %} 9 | {{ foo }} & {{ bar }} 10 | -------------------------------------------------------------------------------- /src/test/resources/tags/calltag/multiple.jinja: -------------------------------------------------------------------------------- 1 | {% macro test1() %}1{{ caller() }}{% endmacro %} 2 | {% macro test2() %}2{{ caller() }}{% endmacro %} 3 | {% macro test3() %}3{{ caller() }}{% endmacro %} 4 | {% call test1() %}{% call test2() %}{% call test3() %}{% endcall %}{% endcall %}{% endcall %} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | .classpath 3 | .project 4 | .settings/ 5 | .externalToolBuilders/ 6 | .factorypath 7 | .checkstyle 8 | 9 | # Intellij 10 | .idea/ 11 | *.iml 12 | *.iws 13 | 14 | # Mac 15 | .DS_Store 16 | 17 | # Maven 18 | dependency-reduced-pom.xml 19 | log/ 20 | target/ 21 | 22 | -------------------------------------------------------------------------------- /src/test/resources/eager/scopes-resetting-bindings/test.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [] %} 2 | {% do my_list.append(0) %} 3 | {% for i in deferred %} 4 | {% for j in deferred %} 5 | {% if deferred %} 6 | {% do my_list.append(1) %} 7 | {% endif %} 8 | {% endfor %} 9 | {% endfor %} 10 | {{ my_list }} -------------------------------------------------------------------------------- /src/test/resources/varblocks/nestedattrs.html: -------------------------------------------------------------------------------- 1 |
2 | {{ first }} 3 |
4 |
5 | {{ nested.val }} 6 |
7 |
8 | {{ nested.child.val }} 9 |
10 |
11 | {{ nested.child.child.val }} 12 |
13 |
14 | {{ nested.child.child.child.val }} 15 |
16 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/features/FeatureStrategies.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.features; 2 | 3 | public class FeatureStrategies { 4 | 5 | public static final FeatureActivationStrategy INACTIVE = c -> false; 6 | public static final FeatureActivationStrategy ACTIVE = c -> true; 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-call-tag-with-deferred-argument/test.jinja: -------------------------------------------------------------------------------- 1 | {% macro repeat(val) %} 2 | {{ val }} 3 | {{ caller() }} 4 | {% endmacro %} 5 | 6 | 7 | {% call repeat(deferred) %} 8 | macro 1 9 | {% call repeat(deferred + 1) %} 10 | macro2 11 | {% endcall %} 12 | {% endcall %} 13 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/import-property.jinja: -------------------------------------------------------------------------------- 1 | {% import "tags/settag/set-var-exp.jinja" as pegasus %} 2 | 3 | {{ pegasus.primary_line_height }} 4 | {{ pegasus.secondary_line_height }} 5 | 6 | {% set expected_to_be_deferred = pegasus.secondary_line_height %} 7 | {{ expected_to_be_deferred }} 8 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/scoping.jinja: -------------------------------------------------------------------------------- 1 | {%- macro foo() -%} 2 | {%- macro foo() -%} 3 | child 4 | {%- endmacro %} 5 | {%- macro bar() -%} 6 | the bar 7 | {%- endmacro -%} 8 | parent & {{ foo() }} & {{ bar() }} 9 | {%- endmacro %} 10 | {{ foo() }}. 11 | {{ foo() }}. 12 | {{ bar() }}. 13 | -------------------------------------------------------------------------------- /src/test/resources/eager/fully-defers-filtered-macro/test.jinja: -------------------------------------------------------------------------------- 1 | {% macro flashy(foo) -%} 2 | {{ foo|upper }} 3 | A flashy {{ deferred }}. 4 | {%- endmacro %} 5 | {{ flashy(flashy('bar')) }} 6 | --- 7 | {% macro silly() -%} 8 | A silly {{ deferred }}. 9 | {%- endmacro %} 10 | {{ silly()|upper }} 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-set-and-modified-in-for/test.jinja: -------------------------------------------------------------------------------- 1 | {% set list = [] %} 2 | {% for item in deferred %} 3 | {% unless count %} 4 | {% set count = 0 %} 5 | {% endunless %} 6 | {% do list.append(count) %} 7 | {% set count = count + 1 %} 8 | {{ count }} 9 | {% endfor %} 10 | {{ list }} 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/prepends-set-if-state-changes/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = [0] %} 2 | {% set deferred = deferred && foo.append(1) %} 3 | {% do foo.append(2) %} 4 | {% set deferred = deferred && foo.append(3) %} 5 | {% print foo.append(4) %} 6 | {% set deferred = deferred && foo.append(5) %} 7 | {{ foo }} 8 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/extendstag/throws-when-deferred-extends-tag.jinja: -------------------------------------------------------------------------------- 1 | {% if deferred %} 2 | {% extends "../eager/extendstag/base.html" %} 3 | {% else %} 4 | {% extends "../eager/extendstag/base.html" %} 5 | {% endif %} 6 | 7 | {%- block sidebar -%} 8 |

Table Of Contents

9 | {%- endblock -%} -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/two-macros.jinja: -------------------------------------------------------------------------------- 1 | {% macro macro1(options={}) %} 2 | 3 | {% endmacro %} 4 | 5 | {% macro macro2(options={}) %} 6 | 7 | 8 | {% call macro1() %}{% endcall %} 9 | {% endmacro %} 10 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-non-deferring-cycles/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = ['1','2','3','4','5'] %} 2 | {% for item in foo %} 3 | start: {% cycle 'start' %} 4 | foo: {% cycle foo %} 5 | one/two: {% cycle 'one','two' %} 6 | {% cycle 'a','b','c' as letter -%} 7 | letter: {% cycle letter %} 8 | {%- endfor -%} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-block-path-when-deferred/test.jinja: -------------------------------------------------------------------------------- 1 | {% extends '../../eager/reconstructs-block-path-when-deferred/base.jinja' %} 2 | {% block body %} 3 | {%- set prefix = deferred ? "current" : "current" -%} 4 | Block's current path is: {{ '{{' + prefix + '_path }}' }} 5 | {% endblock %} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-namespace-for-set-tags-using-period/test.jinja: -------------------------------------------------------------------------------- 1 | {% set ns1 = namespace({'a': 'aa'}) %} 2 | {% set ns1.b = 'b ' ~ deferred %} 3 | 4 | {% set ns2 = namespace({'c': 'cc'}) %} 5 | {% set ns2.d -%} 6 | d {{ deferred }} 7 | {%- endset %} 8 | 9 | {{ ns1 }} 10 | {{ ns2 }} 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/reverts-simple/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for __ignored__ in [0] %} 2 | {% set my_list = [0, 1] %}\ 3 | {% if deferred %} 4 | {% do my_list.append(2) %} 5 | {% endif %} 6 | {% do my_list.append(3) %} 7 | 8 | {% do my_list.append(4) %} 9 | {{ my_list }} 10 | {% endfor %} 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/wraps-macro-that-would-change-current-path-in-child-scope/test.jinja: -------------------------------------------------------------------------------- 1 | Starting current_path: {{ current_path }} 2 | {% from "./dir1/macro.jinja" import foo_importer -%} 3 | Intermediate current_path: {{ current_path }} 4 | {{ foo_importer() }} 5 | Ending current_path: {{ current_path }} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-set-and-modified-in-for/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set list = [] %}\ 2 | {% for item in deferred %} 3 | {% unless count %} 4 | {% set count = 0 %} 5 | {% endunless %} 6 | {% do list.append(count) %} 7 | {% set count = count + 1 %} 8 | {{ count }} 9 | {% endfor %} 10 | {{ list }} 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/prepends-set-if-state-changes/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = [0] %}\ 2 | {% set deferred = deferred && foo.append(1) %} 3 | {% do foo.append(2) %} 4 | {% set deferred = deferred && foo.append(3) %} 5 | {% print foo.append(4) %} 6 | {% set deferred = deferred && foo.append(5) %} 7 | {{ foo }} 8 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/objects/date/CurrentDateTimeProvider.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.objects.date; 2 | 3 | public class CurrentDateTimeProvider implements DateTimeProvider { 4 | 5 | @Override 6 | public long getCurrentTimeMillis() { 7 | return System.currentTimeMillis(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-macro-in-for/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [] %}\ 2 | {% macro macro_append(num) %}\ 3 | {% do my_list.append(num) %}\ 4 | {{ my_list }}\ 5 | {% endmacro %}\ 6 | {% for item in filter:split.filter(macro_append(deferred), ____int3rpr3t3r____, ',', 2) %} 7 | {{ item }} 8 | {% endfor %} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-macro-in-if/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [] %}\ 2 | {% macro macro_append(num) %}\ 3 | {% do my_list.append(num) %}\ 4 | {{ my_list }}\ 5 | {% endmacro %}\ 6 | {% if [] == filter:split.filter(macro_append(deferred), ____int3rpr3t3r____, ',', 2) %} 7 | {{ my_list }} 8 | {% endif %} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-block-set-variables-in-for-loop/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for i in range(deferred) %} 2 | {% set __macro_foo_97643642_temp_variable_0__ %} 3 | {{ deferred }} 4 | {% endset %}\ 5 | {{ filter:int.filter(__macro_foo_97643642_temp_variable_0__, ____int3rpr3t3r____) + 3 }} 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-changes-within-deferred-set-block/test.jinja: -------------------------------------------------------------------------------- 1 | {% set bar = [] %} 2 | {% set foo -%} 3 | 1{% do bar.append(1) %} 4 | {%- endset %} 5 | {{ foo }} 6 | {% if deferred %} 7 | {% set foo -%} 8 | 2{% do bar.append(2) %} 9 | {%- endset %} 10 | {% endif %} 11 | Bar: {{ bar }} 12 | Foo: {{ foo }} 13 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-value-modified-in-macro/test.jinja: -------------------------------------------------------------------------------- 1 | {% set increment = 2 %} 2 | {% macro counter(foo) %} 3 | {% set level = level + increment %} 4 | {% if level < foo %} 5 | {{ counter(foo) }} 6 | {% endif %} 7 | {{ level }} 8 | {% endmacro %} 9 | {{ counter(deferred) }} 10 | 11 | {{ counter(2) }} 12 | -------------------------------------------------------------------------------- /src/test/resources/eager/wraps-certain-output-in-raw/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = '{{ bar }}' %} 2 | {% set bar = '{% print foo %}' %} 3 | {% set foobar = '{% baz %}' %} 4 | {% set baz = 'No raw' %} 5 | {% set vars = [foo, bar, foobar, baz] %} 6 | {%- for var in vars %} 7 | {{ var }} 8 | {% print var %} 9 | {%- endfor -%} 10 | -------------------------------------------------------------------------------- /src/test/resources/snippets/does-not-override-macro-functions-from-higher-scope.jinja: -------------------------------------------------------------------------------- 1 | {% macro foo() %} 2 | 1st foo 3 | {% endmacro %} 4 | {% macro bar() %} 5 | bar 6 | {{ foo() }} 7 | {% endmacro %} 8 | {% for i in range(1) %} 9 | {% macro foo() %} 10 | 2nd foo 11 | {% endmacro %} 12 | {{ bar() }} 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-for-loop-var-from-macro/test.jinja: -------------------------------------------------------------------------------- 1 | {% macro getData() %} 2 | {% macro doIt(val) %} 3 | {{ deferred ~ val|tojson }} 4 | {% endmacro %} 5 | 6 | {% for val in [{'a': 'a'}, {'b': 'b'}] %} 7 | {{ doIt(val)|upper }} 8 | {% endfor %} 9 | {% endmacro %} 10 | 11 | {{ getData()|upper }} 12 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-block-path-when-deferred-nested/test.jinja: -------------------------------------------------------------------------------- 1 | {% extends '../../eager/reconstructs-block-path-when-deferred-nested/middle.jinja' %} 2 | {% block first %} 3 | {%- set prefix = deferred ? "current" : "current" -%} 4 | Child's first current path is: {{ '{{' + prefix + '_path }}' }} 5 | {% endblock %} 6 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-namespace-for-set-tags-using-period/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set ns1 = namespace({'a': 'aa'} ) %}\ 2 | {% set ns1.b = 'b ' ~ deferred %} 3 | 4 | 5 | {% set ns2 = namespace({'c': 'cc'} ) %}\ 6 | {% set ns2.d %}\ 7 | d {{ deferred }}\ 8 | {% endset %} 9 | 10 | {{ ns1 }} 11 | {{ ns2 }} 12 | -------------------------------------------------------------------------------- /src/test/resources/filter/groupby-attr.jinja: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/resources/eager/allows-meta-context-var-overriding/test.jinja: -------------------------------------------------------------------------------- 1 | {% for meta in [0] %} 2 | {{ meta }} 3 | {%- endfor %} 4 | {{ meta }} 5 | {% for meta in deferred %} 6 | {{ meta }} 7 | {%- endfor %} 8 | {{ meta }} 9 | {%- set meta = [] %} 10 | {% if deferred %} 11 | {% do meta.append(1) %} 12 | {% endif %} 13 | {{ meta }} 14 | -------------------------------------------------------------------------------- /src/test/resources/deferred/vars-in-deferred-node.jinja: -------------------------------------------------------------------------------- 1 | {%- set varUsedInForScope = 'outside if statement' -%} 2 | {%- for item in resolved -%} 3 | {%- if deferredValue -%} 4 | {{ varUsedInForScope }} 5 | {%- set varUsedInForScope = ' entered if statement' -%} 6 | {%- endif -%} 7 | 8 | {{ varUsedInForScope }} 9 | {%- endfor -%} 10 | -------------------------------------------------------------------------------- /src/test/resources/eager/correctly-defers-with-multiple-loops/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [] %}\ 2 | {% for __ignored__ in [0] %} 3 | {% for j in deferred %} 4 | {% do my_list.append(0) %} 5 | {% endfor %} 6 | 7 | {% for j in deferred %} 8 | {% do my_list.append(1) %} 9 | {% endfor %} 10 | {% endfor %} 11 | {{ my_list }} 12 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-on-immutable-mode/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 1 %}\ 2 | {% if deferred %} 3 | {% set foo = 2 %} 4 | {% else %} 5 | {% set foo = 3 %} 6 | {% endif %} 7 | {{ foo }} 8 | 9 | {% for __ignored__ in [0] %}\ 10 | {% set bar = 1 + deferred %} 11 | {% set bar = bar + deferred %} 12 | {% endfor %}\ 13 | 1 14 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-on-immutable-mode/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 1 %} 2 | {% if deferred %} 3 | {% set foo = foo + 1 %} 4 | {% else %} 5 | {% set foo = foo + 2 %} 6 | {% endif %} 7 | {{ foo }} 8 | 9 | {% set bar = 1 %} 10 | {%- for item in range(0,2) %} 11 | {%- set bar = bar + deferred %} 12 | {% endfor -%} 13 | {{ bar }} 14 | -------------------------------------------------------------------------------- /src/test/resources/eager/does-not-override-import-modification-in-for/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 'start' %} 2 | {% for i in range(2) %} 3 | {% import "../supplements/deferred-modification.jinja" as bar1 %} 4 | {{ bar1.foo }} 5 | {% import "../supplements/deferred-modification.jinja" as bar2 %} 6 | {{ bar2.foo }} 7 | {% endfor %} 8 | {{ foo }} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/doesnt-double-append-in-deferred-macro/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = ['a'] %}\ 2 | {% set __macro_foo_97643642_temp_variable_0__ %} 3 | a 4 | {% if deferred %} 5 | {% do my_list.append('b') %}\ 6 | b 7 | {% endif %} 8 | {% endset %}\ 9 | {{ __macro_foo_97643642_temp_variable_0__ }} 10 | {{ my_list }} 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/eagerly-defers-set/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = range(0, deferred) %} 2 | {% for item in foo %} 3 | {{ item }} 4 | 5 | Yes bar 6 | 7 | {% if item == 0 %} 8 | At least one: true 9 | {% elif item == 1 %} 10 | Exactly one: true 11 | {% else %} 12 | More than one: true 13 | {% endif %} 14 | {% endfor %} 15 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-block-path-when-deferred/base.jinja: -------------------------------------------------------------------------------- 1 | {% set prefix = deferred ? "current" : "current" %} 2 | Parent's current path is: {{ '{{' + prefix + '_path }}' }} 3 | -----Pre-Block----- 4 | {% block body -%} 5 | {%- endblock %} 6 | -----Post-Block----- 7 | Parent's current path is: {{ '{{' + prefix + '_path }}' }} 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-loop-setting-meta-context-var/test.jinja: -------------------------------------------------------------------------------- 1 | {% macro render(content, query) -%} 2 | {%- if query -%} 3 | {{ content.foo }} 4 | {%- endif -%} 5 | {% endmacro %} 6 | 7 | {% set looper = [{'foo': 'a'}, {'foo': 'b'}] %} 8 | {% for content in looper %} 9 | {{ render(content, deferred) }} 10 | {% endfor %} 11 | 12 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/extendstag/reconstructs-deferred-outside-block.jinja: -------------------------------------------------------------------------------- 1 | {% extends "../eager/extendstag/base.html" %} 2 | {% if deferred %} 3 | {% set foo = 'yes' %} 4 | {% else %} 5 | {% set foo = 'no' %} 6 | {% endif %} 7 | 8 | {%- block sidebar -%} 9 |

Table Of Contents

10 |

{{ foo }}.

11 | {%- endblock -%} 12 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-fromed-macro/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set deferred_import_resource_path = 'eager/reconstructs-fromed-macro/has-macro.jinja' %}\ 2 | {% macro to_upper(param) %} 3 | {{ filter:upper.filter(param, ____int3rpr3t3r____) }} 4 | {% endmacro %}\ 5 | {% set deferred_import_resource_path = null %}\ 6 | {{ to_upper(deferred) }} -------------------------------------------------------------------------------- /src/test/resources/eager/handles-import-with-macros-in-deferred-if/test.jinja: -------------------------------------------------------------------------------- 1 | {% set myname = 'person' %} 2 | {% if deferred %} 3 | {%- import "../supplements/macro-and-set.jinja" as simple -%} 4 | {% else %} 5 | {%- import "../supplements/macro-and-set.jinja" as simple -%} 6 | {% endif %} 7 | simple.foo: {{ simple.foo() }} 8 | simple.bar: {{ simple.bar }} 9 | -------------------------------------------------------------------------------- /src/test/resources/eager/keeps-scope-isolation-from-for-loops/test.jinja: -------------------------------------------------------------------------------- 1 | {% for i in range(deferred) %} 2 | {% set foo = 'a' ~ i %} 3 | {% for j in range(deferred) %} 4 | {% set foo = 'b' ~ j %} 5 | {% for k in range(2) %} 6 | {% set foo = 'c' ~ k %} 7 | {{ foo }} 8 | {% endfor %} 9 | {{ foo }} 10 | {% endfor %} 11 | {{ foo }} 12 | {% endfor %} 13 | -------------------------------------------------------------------------------- /src/test/resources/snippets/does-not-override-call-tag-from-higher-scope.jinja: -------------------------------------------------------------------------------- 1 | {% macro first() -%} 2 | 1st macro 3 | {{ caller() }} 4 | {% endmacro %} 5 | {% call first() -%} 6 | 1st caller 7 | {% macro second() -%} 8 | 2nd macro 9 | {{ caller() }} 10 | {% endmacro %} 11 | {% call second() -%} 12 | 2nd caller 13 | {% endcall %} 14 | {% endcall %} 15 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-macro-for-do-and-print/test.jinja: -------------------------------------------------------------------------------- 1 | {%- macro macro_append(num) -%} 2 | {%- do my_list.append(num) -%}Macro: {{ my_list }} 3 | {%- endmacro -%} 4 | Is ({{ my_list }}), 5 | {% print macro_append(first) %} 6 | Is ({{ my_list }}), 7 | {%- do macro_append(deferred) %} 8 | Is ({{ my_list }}), 9 | {% print macro_append(deferred2) %} 10 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/filter/CountFilter.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.filter; 2 | 3 | import com.hubspot.jinjava.doc.annotations.JinjavaDoc; 4 | 5 | @JinjavaDoc(value = "", aliasOf = "length") 6 | public class CountFilter extends LengthFilter { 7 | 8 | @Override 9 | public String getName() { 10 | return "count"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferring-loop-variable/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = range(2) %} 2 | {% for i in foo %} 3 | {% if deferred && loop.index == 1 -%} 4 | first time! 5 | {% endif %} 6 | {{ loop.index }} 7 | {% endfor %} 8 | {% for i in foo %} 9 | {% if deferred && loop.isLast() -%} 10 | last time! 11 | {% endif %} 12 | {{ loop.index }} 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/exptest/IsEqExpTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.exptest; 2 | 3 | import com.hubspot.jinjava.doc.annotations.JinjavaDoc; 4 | 5 | @JinjavaDoc(value = "", aliasOf = "equalto") 6 | public class IsEqExpTest extends IsEqualToExpTest { 7 | 8 | @Override 9 | public String getName() { 10 | return "eq"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/objects/PyWrapper.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.objects; 2 | 3 | /** 4 | * Marker indicating an object is a python wrapper interface. 5 | * 6 | * Use this on classes which you don't want automatically wrapped into Py* forms (i.e. List types into PyList) 7 | * 8 | * @author jstehler 9 | */ 10 | public interface PyWrapper {} 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-deferred-variable-eventually/test.jinja: -------------------------------------------------------------------------------- 1 | {% macro foo(var) %} 2 | {% do my_list.append(var) %} 3 | {% endmacro %} 4 | 5 | {% macro append_stuff() %} 6 | {% if deferred %} 7 | 8 | {{ foo('b') }} 9 | {{ foo('c') }} 10 | {% endif %} 11 | {% endmacro %} 12 | 13 | {% set my_list = [] %} 14 | {{ append_stuff() }} 15 | 16 | {{ my_list }} -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-null-variables-in-deferred-caller/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% if deferred %} 2 | {% macro foo(var) %} 3 | {% set second_list = [] %} 4 | {% set second_list = [] %}\ 5 | {% do second_list.append(var) %} 6 | {{ caller() }} 7 | {% endmacro %}\ 8 | {% call foo(deferred) %} 9 | [] 10 | {{ second_list }} 11 | {% endcall %} 12 | {% endif %} 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/exptest/IsLessThanExpTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.exptest; 2 | 3 | import com.hubspot.jinjava.doc.annotations.JinjavaDoc; 4 | 5 | @JinjavaDoc(value = "", aliasOf = "lt") 6 | public class IsLessThanExpTest extends IsLtTest { 7 | 8 | @Override 9 | public String getName() { 10 | return "lessthan"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/exptest/IsWithinExpTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.exptest; 2 | 3 | import com.hubspot.jinjava.doc.annotations.JinjavaDoc; 4 | 5 | @JinjavaDoc(value = "", aliasOf = "in") 6 | public class IsWithinExpTest extends IsInExpTest { 7 | 8 | @Override 9 | public String getName() { 10 | return "within"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/eager/commits-variables-from-do-tag-when-partially-resolved/test.jinja: -------------------------------------------------------------------------------- 1 | {% set list0 = ['a'] %}{% do %} 2 | {% set list1 = ['b'] %} 3 | {% set list2 = ['c'] %} 4 | {% do list2.append(deferred) %} 5 | {% unless deferred %} 6 | {% set list0 = ['a', 'a'] %} 7 | {% endunless %} 8 | {% enddo %} 9 | L0: {{ list0 }} 10 | L1: {{ list1 }} 11 | L2: {{ list2 }} 12 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-call-tag-with-deferred-argument/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% macro repeat(val) %} 2 | {{ val }} 3 | {{ caller() }} 4 | {% endmacro %}\ 5 | {% call repeat(deferred) %} 6 | macro 1 7 | {% macro repeat(val) %} 8 | {{ val }} 9 | {{ caller() }} 10 | {% endmacro %}\ 11 | {% call repeat(deferred + 1) %} 12 | macro2 13 | {% endcall %} 14 | {% endcall %} 15 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-modification-in-caller/test.jinja: -------------------------------------------------------------------------------- 1 | {% macro callerino() -%} 2 | {% do my_list.append('b') -%} 3 | {{ caller() }} 4 | {%- do my_list.append('d') -%} 5 | {%- endmacro %} 6 | {% set my_list = ['a'] %} 7 | {% call callerino() -%} 8 | {%- do my_list.append(deferred) -%} 9 | {{ my_list }} 10 | {%- endcall %} 11 | {{ my_list }} 12 | -------------------------------------------------------------------------------- /src/test/resources/eager/runs-macro-function-in-deferred-execution-mode/test.jinja: -------------------------------------------------------------------------------- 1 | {% macro modify(val) %} 2 | {% do holder.update({'val': holder.val + 1}) %} 3 | {% endmacro %} 4 | {% set holder = {'val': -1} %} 5 | {% for i in range(deferred) %} 6 | {% do modify(1) %} 7 | {% if holder.val >= 1 %} 8 | {{ i }} 9 | {% endif %} 10 | {% endfor %} 11 | 12 | {{ holder.val }} 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/exptest/IsLessThanSymbolExpTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.exptest; 2 | 3 | import com.hubspot.jinjava.doc.annotations.JinjavaDoc; 4 | 5 | @JinjavaDoc(value = "", aliasOf = "lt") 6 | public class IsLessThanSymbolExpTest extends IsLtTest { 7 | 8 | @Override 9 | public String getName() { 10 | return "<"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/filter/EAliasedEscapeFilter.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.filter; 2 | 3 | import com.hubspot.jinjava.doc.annotations.JinjavaDoc; 4 | 5 | @JinjavaDoc(value = "", aliasOf = "escape") 6 | public class EAliasedEscapeFilter extends EscapeFilter { 7 | 8 | @Override 9 | public String getName() { 10 | return "e"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/loader/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.loader; 2 | 3 | import java.io.IOException; 4 | 5 | public class ResourceNotFoundException extends IOException { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | public ResourceNotFoundException(String message) { 10 | super(message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-complex-raw/test.jinja: -------------------------------------------------------------------------------- 1 | {%- macro raw_exp(var) -%} 2 | {{ '{% raw %}}} ' ~ var ~ ' {{{% endraw %}' }} 3 | {%- endmacro -%} 4 | {%- macro raw_print(var) -%} 5 | {% print '}} ' ~ var ~ ' {{' %} 6 | {%- endmacro -%} 7 | {{ raw_exp(1)|reverse }} 8 | {% print raw_print(2)|reverse %} 9 | {{ raw_print(3)|reverse }} 10 | {% print raw_exp(4)|reverse %} 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-non-deferring-cycles/test.expected.jinja: -------------------------------------------------------------------------------- 1 | start: start 2 | foo: 1 3 | one/two: one 4 | letter: a 5 | start: start 6 | foo: 2 7 | one/two: two 8 | letter: b 9 | start: start 10 | foo: 3 11 | one/two: one 12 | letter: c 13 | start: start 14 | foo: 4 15 | one/two: two 16 | letter: a 17 | start: start 18 | foo: 5 19 | one/two: one 20 | letter: b 21 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-null-variables-in-deferred-caller/test.jinja: -------------------------------------------------------------------------------- 1 | {% set first_list = [] %} 2 | {% macro foo(var) %} 3 | {% set second_list = [] %} 4 | {% do second_list.append(var) %} 5 | {{ caller() }} 6 | {% endmacro %} 7 | 8 | {% if deferred %} 9 | {% call foo(deferred) %} 10 | {{ first_list }} 11 | {{ second_list }} 12 | {% endcall %} 13 | {% endif %} 14 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/exptest/IsGreaterThanExpTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.exptest; 2 | 3 | import com.hubspot.jinjava.doc.annotations.JinjavaDoc; 4 | 5 | @JinjavaDoc(value = "", aliasOf = "gt") 6 | public class IsGreaterThanExpTest extends IsGtTest { 7 | 8 | @Override 9 | public String getName() { 10 | return "greaterthan"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/exptest/IsGreaterThanSymbolExpTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.exptest; 2 | 3 | import com.hubspot.jinjava.doc.annotations.JinjavaDoc; 4 | 5 | @JinjavaDoc(value = "", aliasOf = "gt") 6 | public class IsGreaterThanSymbolExpTest extends IsGtTest { 7 | 8 | @Override 9 | public String getName() { 10 | return ">"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/filter/DAliasedDefaultFilter.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.filter; 2 | 3 | import com.hubspot.jinjava.doc.annotations.JinjavaDoc; 4 | 5 | @JinjavaDoc(value = "", aliasOf = "default") 6 | public class DAliasedDefaultFilter extends DefaultFilter { 7 | 8 | @Override 9 | public String getName() { 10 | return "d"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-loop-var-against-deferred-in-loop/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for __ignored__ in [0] %}\ 2 | item1 {{ deferred }}\ 3 | .{% set temp = 'item1' ~ deferred %}\ 4 | {{ temp }} 5 | item2 {{ deferred }}\ 6 | .{% set temp = 'item2' ~ deferred %}\ 7 | {{ temp }} 8 | item3 {{ deferred }}\ 9 | .{% set temp = 'item3' ~ deferred %}\ 10 | {{ temp }} 11 | {% endfor %} 12 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-non-deferred-import-vars/test.jinja: -------------------------------------------------------------------------------- 1 | {%- set myname = (1 + 2) -%} 2 | {%- from "../supplements/macro-and-set.jinja" import foo, bar -%} 3 | foo: {{ foo() }} 4 | bar: {{ bar }} 5 | --- 6 | {% set myname = (3 + 4) -%} 7 | {%- import "../supplements/macro-and-set.jinja" as simple -%} 8 | simple.foo: {{ simple.foo() }} 9 | simple.bar: {{ simple.bar }} 10 | -------------------------------------------------------------------------------- /src/test/resources/eager/modifies-variable-in-deferred-macro/test.jinja: -------------------------------------------------------------------------------- 1 | {% macro my_macro(list, other) %} 2 | {% do list.append(other) %} 3 | {% endmacro %} 4 | {% set list = [] %} 5 | {% do my_macro(list, deferred) %} 6 | {{ list }} 7 | {% set var = [] %} 8 | {% do my_macro(var, deferred) %} 9 | {{ var }} 10 | {% set var2 = [] %} 11 | {% do my_macro(var2, 1) %} 12 | {{ var2 }} 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/exptest/IsEqualsSymbolExpTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.exptest; 2 | 3 | import com.hubspot.jinjava.doc.annotations.JinjavaDoc; 4 | 5 | @JinjavaDoc(value = "", aliasOf = "equalto") 6 | public class IsEqualsSymbolExpTest extends IsEqualToExpTest { 7 | 8 | @Override 9 | public String getName() { 10 | return "=="; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/exptest/IsNotEqualToSymbolExpTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.exptest; 2 | 3 | import com.hubspot.jinjava.doc.annotations.JinjavaDoc; 4 | 5 | @JinjavaDoc(value = "", aliasOf = "ne") 6 | public class IsNotEqualToSymbolExpTest extends IsNeExpTest { 7 | 8 | @Override 9 | public String getName() { 10 | return "!="; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/tree/parse/UnclosedToken.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.tree.parse; 2 | 3 | public class UnclosedToken extends TextToken { 4 | 5 | public UnclosedToken( 6 | String image, 7 | int lineNumber, 8 | int startPosition, 9 | TokenScannerSymbols symbols 10 | ) { 11 | super(image, lineNumber, startPosition, symbols); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/resources/eager/eagerly-defers-set/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = range(0, deferred) %} 2 | {% for item in foo %} 3 | {{ item }} 4 | {% if bar %} 5 | Yes bar 6 | {% else %} 7 | No bar 8 | {% endif %} 9 | {% if item == 0 %} 10 | At least one: {{ bar }} 11 | {% elif item == 1 %} 12 | Exactly one: {{ bar }} 13 | {% else %} 14 | More than one: {{ bar }} 15 | {% endif %} 16 | {% endfor %} 17 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-block-path-when-deferred/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | Parent's current path is: eager/reconstructs-block-path-when-deferred/base.jinja 2 | -----Pre-Block----- 3 | Block's current path is: eager/reconstructs-block-path-when-deferred/test.jinja 4 | 5 | -----Post-Block----- 6 | Parent's current path is: eager/reconstructs-block-path-when-deferred/base.jinja 7 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/includetag/includes-deferred.expected.jinja: -------------------------------------------------------------------------------- 1 | Foo begins as: abc 2 | {% set __temp_meta_current_path_38651297__,current_path = current_path,'sets-to-deferred.jinja' %}\ 3 | {% set foo = deferred %} 4 | foo is now {{ deferred }}\ 5 | . 6 | {% set current_path,__temp_meta_current_path_38651297__ = __temp_meta_current_path_38651297__,null %} 7 | Foo ends as: {{ foo }} 8 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/el/ext/DeferredInvocationResolutionException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.el.ext; 2 | 3 | public class DeferredInvocationResolutionException extends DeferredParsingException { 4 | 5 | public DeferredInvocationResolutionException(String invocationResultString) { 6 | super(DeferredInvocationResolutionException.class, invocationResultString); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/RenderTimings.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | import java.util.Map; 4 | 5 | public interface RenderTimings { 6 | void start(JinjavaInterpreter interpreter, String name); 7 | void end(JinjavaInterpreter interpreter, String name); 8 | void end(JinjavaInterpreter interpreter, String name, Map data); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/mode/DefaultExecutionMode.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.mode; 2 | 3 | public class DefaultExecutionMode implements ExecutionMode { 4 | 5 | private static final ExecutionMode INSTANCE = new DefaultExecutionMode(); 6 | 7 | private DefaultExecutionMode() {} 8 | 9 | public static ExecutionMode instance() { 10 | return INSTANCE; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-from-import-as/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set myname = deferred + 7 %}\ 2 | {% do %} 3 | {% set bar = myname + 19 %} 4 | {% for __ignored__ in [0] %}\ 5 | Hello {{ myname }}\ 6 | {% endfor %} 7 | {% set from_bar = bar %}\ 8 | {% enddo %}\ 9 | from_foo: {% for __ignored__ in [0] %}\ 10 | Hello {{ myname }}\ 11 | {% endfor %} 12 | from_bar: {{ from_bar }} 13 | -------------------------------------------------------------------------------- /src/test/resources/eager/keeps-scope-isolation-from-for-loops/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for i in range(deferred) %} 2 | {% set foo = 'a' ~ i %} 3 | {% for j in range(deferred) %} 4 | {% set foo = 'b' ~ j %} 5 | {% for __ignored__ in [0] %} 6 | {% set foo = 'c0' %} 7 | c0 8 | 9 | {% set foo = 'c1' %} 10 | c1 11 | {% endfor %} 12 | {{ foo }} 13 | {% endfor %} 14 | {{ foo }} 15 | {% endfor %} 16 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/exptest/IsLessThanOrEqualToSymbolExpTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.exptest; 2 | 3 | import com.hubspot.jinjava.doc.annotations.JinjavaDoc; 4 | 5 | @JinjavaDoc(value = "", aliasOf = "le") 6 | public class IsLessThanOrEqualToSymbolExpTest extends IsLeTest { 7 | 8 | @Override 9 | public String getName() { 10 | return "<="; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/tag/eager/EagerGenericTag.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.tag.eager; 2 | 3 | import com.google.common.annotations.Beta; 4 | import com.hubspot.jinjava.lib.tag.Tag; 5 | 6 | @Beta 7 | public class EagerGenericTag extends EagerTagDecorator implements Tag { 8 | 9 | public EagerGenericTag(T tag) { 10 | super(tag); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-macro-in-expression/test.expected.jinja: -------------------------------------------------------------------------------- 1 | 2 2 | {% macro plus(foo, add) %}\ 3 | {{ foo + (filter:int.filter(add, ____int3rpr3t3r____)) }}\ 4 | {% endmacro %}\ 5 | {{ plus(deferred, 1.1) }}\ 6 | {% set deferred = deferred + 2 %} 7 | {% macro plus(foo, add) %}\ 8 | {{ foo + (filter:int.filter(add, ____int3rpr3t3r____)) }}\ 9 | {% endmacro %}\ 10 | {{ plus(deferred, 3.1) }} -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-import-vars/test.jinja: -------------------------------------------------------------------------------- 1 | {%- set myname = deferred + (1 + 2) -%} 2 | {%- from "../supplements/macro-and-set.jinja" import foo, bar -%} 3 | foo: {{ foo() }} 4 | bar: {{ bar }} 5 | --- 6 | {% set myname = deferred + (3 + 4) -%} 7 | {%- import "../supplements/macro-and-set.jinja" as simple -%} 8 | simple.foo: {{ simple.foo() }} 9 | simple.bar: {{ simple.bar }} 10 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-same-name-import-var/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | [fn:map_entry('import_resource_path', 'eager/handles-same-name-import-var/set-var-and-deferred.jinja'), fn:map_entry('my_var', {'my_var': {'foo': 'bar'} , 'value': 'resolved', 'import_resource_path': 'eager/handles-same-name-import-var/set-var-and-deferred.jinja'} ), fn:map_entry('path', ''), fn:map_entry('value', 'resolved')] -------------------------------------------------------------------------------- /src/test/resources/eager/keeps-macro-modifications-in-scope/test.jinja: -------------------------------------------------------------------------------- 1 | {%- set list = [] %} 2 | {%- if deferred %} 3 | {%- macro inc(val, depth) %} 4 | {%- do list.append(depth) -%} 5 | {{ depth }} 6 | {%- if depth < 3 %} 7 | {%- set depth = depth + 1 %} 8 | {{ inc(val, depth) }} 9 | {{ inc(val, depth) }} 10 | {%- endif %} 11 | {%- endmacro %} 12 | 13 | {{ inc('a', 1) }} 14 | {% endif %} 15 | 16 | -------------------------------------------------------------------------------- /src/test/resources/eager/wraps-certain-output-in-raw/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% raw %}\ 2 | {{ bar }}\ 3 | {% endraw %} 4 | {% raw %}\ 5 | {{ bar }}\ 6 | {% endraw %} 7 | {% raw %}\ 8 | {% print foo %}\ 9 | {% endraw %} 10 | {% raw %}\ 11 | {% print foo %}\ 12 | {% endraw %} 13 | {% raw %}\ 14 | {% baz %}\ 15 | {% endraw %} 16 | {% raw %}\ 17 | {% baz %}\ 18 | {% endraw %} 19 | No raw 20 | No raw 21 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/exptest/IsGreaterThanOrEqualToSymbolExpTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.exptest; 2 | 3 | import com.hubspot.jinjava.doc.annotations.JinjavaDoc; 4 | 5 | @JinjavaDoc(value = "", aliasOf = "ge") 6 | public class IsGreaterThanOrEqualToSymbolExpTest extends IsGeTest { 7 | 8 | @Override 9 | public String getName() { 10 | return ">="; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/extends-base1.jinja: -------------------------------------------------------------------------------- 1 | {% extends "base1.jinja" %} 2 | {% block title %}Index{% endblock %} 3 | {% block head %} 4 | 7 | {% endblock %} 8 | {% block content %} 9 |

Index

10 |

11 | Welcome on my awesome homepage. 12 |

13 | {% endblock %} -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/PartiallyDeferredValue.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | import com.google.common.annotations.Beta; 4 | 5 | /** 6 | * An interface for a type of DeferredValue that as a whole is not deferred, 7 | * but certain attributes or methods within it are deferred. 8 | */ 9 | @Beta 10 | public interface PartiallyDeferredValue extends DeferredValue {} 11 | -------------------------------------------------------------------------------- /src/test/resources/deferred/deferred-macro.jinja: -------------------------------------------------------------------------------- 1 | {%- macro inc_padding(width) -%} 2 | {%- set padding = padding + width -%} 3 | {{padding}} 4 | {%- endmacro -%} 5 | {{ padding }}, 6 | {%- set padding = inc_padding(added_padding) | int -%} 7 | {{ padding }}, 8 | {%- set padding = inc_padding(deferred) | int -%} 9 | {{ padding}}, 10 | {%- set padding = inc_padding(added_padding) | int -%} 11 | {{ padding }} 12 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferring-loop-variable/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for __ignored__ in [0] %} 2 | {% if deferred && true %}\ 3 | first time! 4 | {% endif %} 5 | 1 6 | 7 | {% if deferred && false %}\ 8 | first time! 9 | {% endif %} 10 | 2 11 | {% endfor %} 12 | {% for i in [0, 1] %} 13 | {% if deferred && loop.isLast() %}\ 14 | last time! 15 | {% endif %} 16 | {{ loop.index }} 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/fortag/handles-nested-deferred-for-loop.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for __ignored__ in [0] %} 2 | {% for bar in deferred %} 3 | pastrami sandwich. {{ bar }}\ 4 | ! 5 | {% endfor %} 6 | 7 | {% for bar in deferred %} 8 | pastrami salad. {{ bar }}\ 9 | ! 10 | {% endfor %} 11 | 12 | {% for bar in deferred %} 13 | pastrami smoothie. {{ bar }}\ 14 | ! 15 | {% endfor %} 16 | {% endfor %} 17 | -------------------------------------------------------------------------------- /src/test/resources/eager/does-not-reconstruct-variable-in-wrong-scope/test.jinja: -------------------------------------------------------------------------------- 1 | {% macro foo(var) %} 2 | {% do my_list.append(var) %} 3 | {% endmacro %} 4 | 5 | {% macro append_stuff() %} 6 | {{ foo('b') }} 7 | {{ foo('c') }} 8 | {% endmacro %} 9 | 10 | {% set my_list = [] %} 11 | {{ foo('a') }} 12 | {% if deferred %} 13 | {{ append_stuff() }} 14 | {% endif %} 15 | {{ foo('d') }} 16 | 17 | {{ my_list }} 18 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/base2-extends-base1.jinja: -------------------------------------------------------------------------------- 1 | {% extends "base1.jinja" %} 2 | {% block title %}Index{% endblock %} 3 | {% block head %} 4 | 7 | {% endblock %} 8 | {% block content %} 9 |

Index

10 |

11 | {% block message %}{% endblock %} 12 |

13 | {% endblock %} -------------------------------------------------------------------------------- /src/test/resources/eager/commits-variables-from-do-tag-when-partially-resolved/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% do %}\ 2 | {% set list1 = ['b'] %}\ 3 | {% set list0 = ['a'] %}\ 4 | {% set list2 = ['c'] %} 5 | 6 | 7 | {% set list2 = ['c'] %}\ 8 | {% do list2.append(deferred) %} 9 | {% unless deferred %} 10 | {% set list0 = ['a', 'a'] %} 11 | {% endunless %} 12 | {% enddo %} 13 | L0: {{ list0 }} 14 | L1: ['b'] 15 | L2: {{ list2 }} -------------------------------------------------------------------------------- /src/test/resources/eager/reverts-modification-with-deferred-loop/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [] %}\ 2 | {% for __ignored__ in [0] %} 3 | {% for j in deferred %} 4 | {% if loop.first %} 5 | {% do my_list.append(1) %} 6 | {% endif %} 7 | {% endfor %} 8 | 9 | {% for j in deferred %} 10 | {% if loop.first %} 11 | {% do my_list.append(1) %} 12 | {% endif %} 13 | {% endfor %} 14 | {% endfor %} 15 | {{ my_list }} 16 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/FromTagCycleException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | public class FromTagCycleException extends TagCycleException { 4 | 5 | private static final long serialVersionUID = -5487642459443650227L; 6 | 7 | public FromTagCycleException(String path, int lineNumber, int startPosition) { 8 | super("From", path, lineNumber, startPosition); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/errorcategory/BasicTemplateErrorCategory.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret.errorcategory; 2 | 3 | public enum BasicTemplateErrorCategory implements TemplateErrorCategory { 4 | CYCLE_DETECTED, 5 | IMPORT_CYCLE_DETECTED, 6 | INCLUDE_CYCLE_DETECTED, 7 | FROM_CYCLE_DETECTED, 8 | UNKNOWN, 9 | UNKNOWN_DATE, 10 | UNKNOWN_LOCALE, 11 | UNKNOWN_PROPERTY, 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/ImportTagCycleException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | public class ImportTagCycleException extends TagCycleException { 4 | 5 | private static final long serialVersionUID = 1092085697026161185L; 6 | 7 | public ImportTagCycleException(String path, int lineNumber, int startPosition) { 8 | super("Import", path, lineNumber, startPosition); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/MacroTagCycleException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | public class MacroTagCycleException extends TagCycleException { 4 | 5 | private static final long serialVersionUID = -7552850581260771832L; 6 | 7 | public MacroTagCycleException(String path, int lineNumber, int startPosition) { 8 | super("Macro", path, lineNumber, startPosition); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/allows-deferred-lazy-reference-to-get-overridden/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set a_list = ['a', 'b'] %}\ 2 | {% for __ignored__ in [0] %} 3 | {% set b_list = a_list %}\ 4 | {% if deferred %} 5 | {% set b_list = [deferred] %} 6 | {% endif %}\ 7 | {% do b_list.append(deferred ? 'B' : '') %} 8 | B: {{ b_list }}\ 9 | .{% endfor %}\ 10 | {% do a_list.append(deferred ? 'A' : '') %} 11 | A: {{ a_list }}\ 12 | . 13 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/ExtendsTagCycleException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | public class ExtendsTagCycleException extends TagCycleException { 4 | 5 | private static final long serialVersionUID = 3183769038400532542L; 6 | 7 | public ExtendsTagCycleException(String path, int lineNumber, int startPosition) { 8 | super("Extends", path, lineNumber, startPosition); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/IncludeTagCycleException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | public class IncludeTagCycleException extends TagCycleException { 4 | 5 | private static final long serialVersionUID = -5487642459443650227L; 6 | 7 | public IncludeTagCycleException(String path, int lineNumber, int startPosition) { 8 | super("Include", path, lineNumber, startPosition); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/eagerly-defers-macro/test.jinja: -------------------------------------------------------------------------------- 1 | {%- macro foo_macro() -%} 2 | {{ foo }} 3 | {%- endmacro -%} 4 | {%- macro bar_macro() -%} 5 | {{ bar }} 6 | {%- endmacro -%} 7 | {% macro big_guy() %} 8 | {% if deferred %} 9 | {%- print foo_macro() -%} 10 | {% else %} 11 | {%- print bar_macro() -%} 12 | {% endif %} 13 | {% endmacro %} 14 | {% print big_guy() %} 15 | {% set foo = 'No more foo' -%} 16 | {% print big_guy() %} 17 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-aliased-macro/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set myname = deferred + 3 %}\ 2 | {% set deferred_import_resource_path = 'eager/reconstructs-aliased-macro/takes-param.jinja' %}\ 3 | {% macro macros.takes_param(foo) %}\ 4 | {% set bar = 'bar' %} 5 | {% print foo %} 6 | {% endmacro %}\ 7 | {% set deferred_import_resource_path = null %}\ 8 | {% set answer = macros.takes_param(myname) %} 9 | {{ answer }} 10 | -------------------------------------------------------------------------------- /src/test/resources/tags/calltag/simple.jinja: -------------------------------------------------------------------------------- 1 | {% macro render_dialog(title, class='dialog') -%} 2 |
3 |

{{ title }}

4 |
5 | {{ caller() }} 6 |
7 |
8 | {%- endmacro %} 9 | 10 | {% call render_dialog('Hello World') %} 11 | This is a simple dialog rendered by using a macro and 12 | a call block. 13 | {% endcall %} 14 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/el/JinjavaNodeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.el; 2 | 3 | import com.hubspot.jinjava.interpret.JinjavaInterpreter; 4 | import com.hubspot.jinjava.tree.Node; 5 | import java.util.function.BiConsumer; 6 | 7 | public class JinjavaNodeProcessor implements BiConsumer { 8 | 9 | @Override 10 | public void accept(Node node, JinjavaInterpreter interpreter) {} 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/deferred/set-within-lower-scope-twice.jinja: -------------------------------------------------------------------------------- 1 | {%- for item in resolved -%} 2 | {%- set varSetInside = 'inside first scope' -%} 3 | {%- if deferredValue -%} 4 | {{ varSetInside }} 5 | {%- endif -%} 6 | {%- endfor -%} 7 | {%- for item in resolved -%} 8 | {%- set varSetInside = 'inside first scope2' -%} 9 | {%- if deferredValue -%} 10 | {{ varSetInside }} 11 | {%- endif -%} 12 | {%- endfor -%} 13 | -------------------------------------------------------------------------------- /src/test/resources/eager/reverts-simple/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 1 %} 2 | {%- for i in range(1) %} 3 | {%- set foo = null %} 4 | {%- set my_list = [] %} 5 | {%- do my_list.append(0) %} 6 | {%- if 5 < 6 %} 7 | {%- do my_list.append(1) %} 8 | {% if deferred %} 9 | {% do my_list.append(2) %} 10 | {% endif %} 11 | {% do my_list.append(3) %} 12 | {% endif %} 13 | {% do my_list.append(4) %} 14 | {{ my_list }} 15 | {% endfor %} 16 | -------------------------------------------------------------------------------- /src/test/resources/eager/runs-macro-function-in-deferred-execution-mode/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set holder = {'val': -1} %}\ 2 | {% for i in range(deferred) %} 3 | {% set __macro_modify_615470226_temp_variable_1__ %} 4 | {% do holder.update({'val': holder.val + 1}) %} 5 | {% endset %}\ 6 | {% do __macro_modify_615470226_temp_variable_1__ %} 7 | {% if holder.val >= 1 %} 8 | {{ i }} 9 | {% endif %} 10 | {% endfor %} 11 | 12 | {{ holder.val }} -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/DisabledException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | public class DisabledException extends InterpretException { 4 | 5 | private final String token; 6 | 7 | public DisabledException(String token) { 8 | super("'" + token + "' is disabled in this context"); 9 | this.token = token; 10 | } 11 | 12 | public String getToken() { 13 | return token; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-block-path-when-deferred-nested/base.jinja: -------------------------------------------------------------------------------- 1 | {% set prefix = deferred ? "current" : "current" %} 2 | Parent's current path is: {{ '{{' + prefix + '_path }}' }} 3 | -----Pre-First----- 4 | {% block first -%} 5 | {%- endblock %} 6 | -----Post-First----- 7 | -----Pre-Second----- 8 | {% block second -%} 9 | {%- endblock %} 10 | -----Post-Second----- 11 | Parent's current path is: {{ '{{' + prefix + '_path }}' }} 12 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/doc/annotations/JinjavaHasCodeBody.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.doc.annotations; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ ElementType.TYPE, ElementType.METHOD }) 10 | public @interface JinjavaHasCodeBody { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/InterpreterFactory.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | import com.hubspot.jinjava.Jinjava; 4 | import com.hubspot.jinjava.JinjavaConfig; 5 | 6 | public interface InterpreterFactory { 7 | JinjavaInterpreter newInstance(JinjavaInterpreter orig); 8 | JinjavaInterpreter newInstance( 9 | Jinjava application, 10 | Context context, 11 | JinjavaConfig renderConfig 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/parentvars-base.html: -------------------------------------------------------------------------------- 1 | {% import "parentvars-settings.html" as s %} 2 | 3 | 4 | 5 | {% block main_column %} 6 | {% endblock %} 7 | 8 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-value-modified-in-macro/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% macro counter(foo) %} 2 | {% set level = level + 2 %} 3 | {% if level < foo %} 4 | {{ counter(foo) }} 5 | {% endif %} 6 | {{ level }} 7 | {% endmacro %}\ 8 | {{ counter(deferred) }} 9 | 10 | {% macro counter(foo) %} 11 | {% set level = level + 2 %} 12 | {% if level < foo %} 13 | {{ counter(foo) }} 14 | {% endif %} 15 | {{ level }} 16 | {% endmacro %}\ 17 | {{ counter(2) }} 18 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/tag/eager/EagerUnlessTag.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.tag.eager; 2 | 3 | import com.google.common.annotations.Beta; 4 | import com.hubspot.jinjava.lib.tag.UnlessTag; 5 | 6 | @Beta 7 | public class EagerUnlessTag extends EagerIfTag { 8 | 9 | public EagerUnlessTag() { 10 | super(new UnlessTag()); 11 | } 12 | 13 | public EagerUnlessTag(UnlessTag unlessTag) { 14 | super(unlessTag); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/resources/eager/allows-deferred-lazy-reference-to-get-overridden/test.jinja: -------------------------------------------------------------------------------- 1 | {% set a_list = [] %} 2 | {%- do a_list.append('a') %} 3 | {%- for i in range(1) %} 4 | {%- set b_list = a_list %} 5 | {%- do b_list.append('b') %} 6 | {% if deferred %} 7 | {% set b_list = [deferred] %} 8 | {% endif %} 9 | {%- do b_list.append(deferred ? 'B' : '') %} 10 | B: {{ b_list }}. 11 | {%- endfor %} 12 | {%- do a_list.append(deferred ? 'A' : '') %} 13 | A: {{ a_list }}. 14 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-duplicate-variable-reference-modification/test.jinja: -------------------------------------------------------------------------------- 1 | {% set the_list = [] %} 2 | {% macro appender(some_list) -%} 3 | {% if deferred %} 4 | {% do some_list.append(deferred) %} 5 | {% endif %} 6 | {%- endmacro %} 7 | {{ appender(the_list) }} 8 | {{ the_list }} 9 | 10 | {% set foo = [] -%} 11 | {%- set bar = foo -%} 12 | {% do foo.append(1) %} 13 | {% do foo.append(deferred) %} 14 | {% do foo.append(2) %} 15 | {{ foo ~ 'and' ~ bar }} 16 | -------------------------------------------------------------------------------- /src/test/resources/eager/allows-modification-in-resolved-for-loop/test.jinja: -------------------------------------------------------------------------------- 1 | {% set list = [] %} 2 | {% set temp = list %} 3 | {# create an object that is too deep for us to reconstruct via check on EagerExpressionResolver.isResolvableObject #} 4 | {% for i in range(20) %} 5 | {% set temp2 = [i] %} 6 | {% do temp.append(temp2) %} 7 | {% set temp = temp2 %} 8 | {% endfor %} 9 | {% for j in range(1) %} 10 | {% do list.append('END') %} 11 | {% endfor %} 12 | {{ list }} 13 | -------------------------------------------------------------------------------- /src/test/resources/eager/does-not-reconstruct-extra-times/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for __ignored__ in [0] %} 2 | 3 | {% set foo = deferred %} 4 | {% endfor %} 5 | 6 | 7 | {% set foo = deferred %} 8 | 9 | 10 | {% for __ignored__ in [0] %} 11 | {% if deferred %} 12 | {{ foo }} 13 | {% set foo = 'second' %} 14 | {% endif %} 15 | {{ foo }} 16 | {% endfor %} 17 | {{ foo }} 18 | 19 | 20 | {% if deferred %} 21 | {% set foo = 'second' %} 22 | {% endif %} 23 | {{ foo }} 24 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/extendstag/defers-block-in-extends-child.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set current_path = '../eager/extendstag/base.html' %}\ 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/objects/date/FixedDateTimeProvider.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.objects.date; 2 | 3 | public class FixedDateTimeProvider implements DateTimeProvider { 4 | 5 | private long currentTimeMillis; 6 | 7 | public FixedDateTimeProvider(long currentTimeMillis) { 8 | this.currentTimeMillis = currentTimeMillis; 9 | } 10 | 11 | @Override 12 | public long getCurrentTimeMillis() { 13 | return currentTimeMillis; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-macro-for-do-and-print/test.expected.jinja: -------------------------------------------------------------------------------- 1 | Is ([]), 2 | Macro: [10] 3 | Is ([10]),{% set my_list = [10] %}\ 4 | {% macro macro_append(num) %}\ 5 | {% do my_list.append(num) %}\ 6 | Macro: {{ my_list }}\ 7 | {% endmacro %}\ 8 | {% do macro_append(deferred) %} 9 | Is ({{ my_list }}\ 10 | ), 11 | {% macro macro_append(num) %}\ 12 | {% do my_list.append(num) %}\ 13 | Macro: {{ my_list }}\ 14 | {% endmacro %}\ 15 | {% print macro_append(deferred2) %} 16 | -------------------------------------------------------------------------------- /src/test/resources/eager/only-defers-loop-item-on-current-context/test.jinja: -------------------------------------------------------------------------------- 1 | {% set outer_val = 'start' %} 2 | {% for def in deferred %} 3 | {% set outer_list = [{'a': ['b']}] %} 4 | {% for map in outer_list %} 5 | {% set inner_list = map.a %} 6 | {% for x in inner_list %} 7 | {# make outer_val a speculative binding #} 8 | {% set outer_val = outer_val ~ '-' %} 9 | {% if outer_val == deferred %} 10 | {{ outer_val }} 11 | {% endif %} 12 | {% endfor %} 13 | {% endfor %} 14 | {% endfor %} -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-map-node/test.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [] %} 2 | {% if deferred %} 3 | {% set foo = {'foo': 'ff', 'bar': 'bb'}.items() %} 4 | {% endif %} 5 | {% for key, val in foo -%} 6 | {% do my_list.append(deferred) %} 7 | {{ key ~ ' ' ~ val }} 8 | {%- endfor %} 9 | {{ my_list }} 10 | {% set my_list = [] %} 11 | {% for i in {'foo': 'ff', 'bar': 'bb'}.items() -%} 12 | {% do my_list.append(deferred) %} 13 | {{ i.key }} 14 | {%- endfor %} 15 | {{ my_list }} 16 | -------------------------------------------------------------------------------- /src/test/resources/eager/eagerly-defers-macro/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set __macro_big_guy_1311704000_temp_variable_0__ %} 2 | {% if deferred %}\ 3 | I am foo{% else %}\ 4 | I am bar{% endif %} 5 | {% endset %}\ 6 | {% print __macro_big_guy_1311704000_temp_variable_0__ %} 7 | {% set __macro_big_guy_1311704000_temp_variable_1__ %} 8 | {% if deferred %}\ 9 | No more foo{% else %}\ 10 | I am bar{% endif %} 11 | {% endset %}\ 12 | {% print __macro_big_guy_1311704000_temp_variable_1__ %} 13 | -------------------------------------------------------------------------------- /src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/doc/annotations/JinjavaMetaValue.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.doc.annotations; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ ElementType.TYPE, ElementType.METHOD }) 10 | public @interface JinjavaMetaValue { 11 | String name(); 12 | 13 | String value(); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/objects/SafeString.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.objects; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | 5 | public class SafeString { 6 | 7 | private final String value; 8 | 9 | public SafeString(String value) { 10 | this.value = value; 11 | } 12 | 13 | @JsonValue 14 | public String getValue() { 15 | return value; 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return value; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-import-in-deferred-if/test.jinja: -------------------------------------------------------------------------------- 1 | {% set primary_line_height = 100 %} 2 | {% set secondary_line_height = 200 %} 3 | {% if deferred %} 4 | {% import "../supplements/set-val.jinja" as simple %} 5 | {% else %} 6 | {% import "../supplements/set-val.jinja" %} 7 | {% endif %} 8 | simple.primary_line_height (deferred): {{ simple.primary_line_height }} 9 | primary_line_height (deferred): {{ primary_line_height }} 10 | secondary_line_height: {{ secondary_line_height }} 11 | -------------------------------------------------------------------------------- /src/test/resources/eager/only-defers-loop-item-on-current-context/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set outer_val = 'start' %}\ 2 | {% for def in deferred %} 3 | {% set outer_list = [{'a': ['b']} ] %} 4 | {% for __ignored__ in [0] %} 5 | {% set map = {'a': ['b']} %}\ 6 | {% set inner_list = map.a %} 7 | {% for x in inner_list %} 8 | 9 | {% set outer_val = outer_val ~ '-' %} 10 | {% if outer_val == deferred %} 11 | {{ outer_val }} 12 | {% endif %} 13 | {% endfor %} 14 | {% endfor %} 15 | {% endfor %} 16 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-block-path-when-deferred-nested/middle.jinja: -------------------------------------------------------------------------------- 1 | {% extends '../../eager/reconstructs-block-path-when-deferred-nested/base.jinja' %} 2 | {% block first %} 3 | {%- set prefix = deferred ? "current" : "current" -%} 4 | Middle's first current path is: {{ '{{' + prefix + '_path }}' }} 5 | {% endblock %} 6 | 7 | {% block second %} 8 | {%- set prefix = deferred ? "current" : "current" -%} 9 | Middle's second current path is: {{ '{{' + prefix + '_path }}' }} 10 | {% endblock %} -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/mode/PreserveRawExecutionMode.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.mode; 2 | 3 | public class PreserveRawExecutionMode implements ExecutionMode { 4 | 5 | private static final ExecutionMode INSTANCE = new PreserveRawExecutionMode(); 6 | 7 | private PreserveRawExecutionMode() {} 8 | 9 | public static ExecutionMode instance() { 10 | return INSTANCE; 11 | } 12 | 13 | @Override 14 | public boolean isPreserveRawTags() { 15 | return true; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/tree/parse/WhitespaceControlParser.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.tree.parse; 2 | 3 | public interface WhitespaceControlParser { 4 | WhitespaceControlParser LENIENT = new LenientWhitespaceControlParser(); 5 | WhitespaceControlParser STRICT = new StrictWhitespaceControlParser(); 6 | 7 | boolean hasLeftTrim(String unwrapped); 8 | String stripLeft(String unwrapped); 9 | 10 | boolean hasRightTrim(String unwrapped); 11 | String stripRight(String unwrapped); 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/extendstag/defers-super-block-with-deferred.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set current_path = '../eager/extendstag/base-deferred.html' %}\ 2 | 3 | 4 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/CannotReconstructValueException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | import com.google.common.annotations.Beta; 4 | 5 | @Beta 6 | public class CannotReconstructValueException extends DeferredValueException { 7 | 8 | public static final String CANNOT_RECONSTRUCT_MESSAGE = "Cannot reconstruct value"; 9 | 10 | public CannotReconstructValueException(String key) { 11 | super(String.format("%s: %s", CANNOT_RECONSTRUCT_MESSAGE, key)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-reference-modification-when-source-is-lost/test.jinja: -------------------------------------------------------------------------------- 1 | {% set a_list = [] %} 2 | {%- do a_list.append('a') %} 3 | {%- for i in range(1) %} 4 | {%- set b_list = a_list %} 5 | {%- do b_list.append(deferred) %} 6 | {% endfor %} 7 | {{ a_list }} 8 | --- 9 | {% for k in range(1) %} 10 | {% set a_list = [] %} 11 | {% for i in range(1) %} 12 | {% if deferred %} 13 | {% set b_list = a_list %} 14 | {% do b_list.append(1) %} 15 | {% endif %} 16 | {% endfor %} 17 | {{ a_list }} 18 | {% endfor %} 19 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-map-node/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% if deferred %} 2 | {% set foo = [fn:map_entry('foo', 'ff'), fn:map_entry('bar', 'bb')] %} 3 | {% endif %} 4 | {% set my_list = [] %}\ 5 | {% for key, val in foo %}\ 6 | {% do my_list.append(deferred) %} 7 | {{ key ~ ' ' ~ val }}\ 8 | {% endfor %} 9 | {{ my_list }} 10 | 11 | {% set my_list = [] %}\ 12 | {% for __ignored__ in [0] %}\ 13 | {% do my_list.append(deferred) %} 14 | foo{% do my_list.append(deferred) %} 15 | bar{% endfor %} 16 | {{ my_list }} 17 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-loop-setting-meta-context-var/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for __ignored__ in [0] %} 2 | {% macro render(content, query) %}\ 3 | {% if query %}\ 4 | {{ content.foo }}\ 5 | {% endif %}\ 6 | {% endmacro %}\ 7 | {% set content = {'foo': 'a'} %}\ 8 | {{ render(content, deferred) }} 9 | 10 | {% macro render(content, query) %}\ 11 | {% if query %}\ 12 | {{ content.foo }}\ 13 | {% endif %}\ 14 | {% endmacro %}\ 15 | {% set content = {'foo': 'b'} %}\ 16 | {{ render(content, deferred) }} 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/expression/ExpressionStrategy.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.expression; 2 | 3 | import com.hubspot.jinjava.interpret.JinjavaInterpreter; 4 | import com.hubspot.jinjava.tree.output.RenderedOutputNode; 5 | import com.hubspot.jinjava.tree.parse.ExpressionToken; 6 | import java.io.Serializable; 7 | 8 | public interface ExpressionStrategy extends Serializable { 9 | RenderedOutputNode interpretOutput( 10 | ExpressionToken master, 11 | JinjavaInterpreter interpreter 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/doc/annotations/JinjavaSnippet.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.doc.annotations; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ ElementType.TYPE, ElementType.METHOD }) 10 | public @interface JinjavaSnippet { 11 | String desc() default ""; 12 | 13 | String code(); 14 | 15 | String output() default ""; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-duplicate-variable-reference-modification/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set the_list = [] %}\ 2 | {% set __macro_appender_2138849093_temp_variable_0__ %}\ 3 | {% set some_list = the_list %}\ 4 | {% if deferred %} 5 | {% do some_list.append(deferred) %} 6 | {% endif %}\ 7 | {% endset %}\ 8 | {{ __macro_appender_2138849093_temp_variable_0__ }} 9 | {{ the_list }} 10 | 11 | 12 | {% set foo = [1] %}\ 13 | {% do foo.append(deferred) %} 14 | {% do foo.append(2) %} 15 | {% set bar = foo %}\ 16 | {{ foo ~ 'and' ~ bar }} 17 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/NotInLoopException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | /** 4 | * Exception thrown when `continue` or `break` is called outside of a loop 5 | */ 6 | public class NotInLoopException extends InterpretException { 7 | 8 | public static final String MESSAGE_PREFIX = "`"; 9 | public static final String MESSAGE_SUFFIX = "` called while not in a for loop"; 10 | 11 | public NotInLoopException(String tagName) { 12 | super(MESSAGE_PREFIX + tagName + MESSAGE_SUFFIX); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/lib/exptest/CollectionExpTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.exptest; 2 | 3 | import com.hubspot.jinjava.el.TruthyTypeConverter; 4 | import com.hubspot.jinjava.el.ext.CollectionMembershipOperator; 5 | 6 | public abstract class CollectionExpTest implements ExpTest { 7 | 8 | protected static final TruthyTypeConverter TYPE_CONVERTER = new TruthyTypeConverter(); 9 | protected static final CollectionMembershipOperator COLLECTION_MEMBERSHIP_OPERATOR = 10 | new CollectionMembershipOperator(); 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-reference-modification-when-source-is-lost/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set a_list = ['a'] %}\ 2 | {% for __ignored__ in [0] %}\ 3 | {% set b_list = a_list %}\ 4 | {% do b_list.append(deferred) %} 5 | {% endfor %} 6 | {{ a_list }} 7 | --- 8 | {% for __ignored__ in [0] %} 9 | 10 | {% set a_list = [] %}\ 11 | {% for __ignored__ in [0] %} 12 | {% if deferred %} 13 | {% set b_list = [] %} 14 | {% set b_list = a_list %}\ 15 | {% do b_list.append(1) %} 16 | {% endif %} 17 | {% endfor %} 18 | {{ a_list }} 19 | {% endfor %} 20 | -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/pegasus-importable.jinja: -------------------------------------------------------------------------------- 1 | {% set wrap_padding = "padding-left:" ~ padding ~ "px;padding-right:" ~ padding ~ "px" %} 2 | 3 | {% macro spacer(orientation = "h", size = padding) %} 4 | {% if orientation == "v" or orientation == "vertical" %} 5 | 6 | {% elif orientation == "h" or orientation == "horizontal" %} 7 | 8 | {% endif %} 9 | {% endmacro %} 10 | 11 | {% macro _private() %} 12 | foovar 13 | {% endmacro %} 14 | -------------------------------------------------------------------------------- /src/test/resources/tags/settag/set-complex-dict.jinja: -------------------------------------------------------------------------------- 1 | {% set styles = { 2 | 'heading': 'color:' ~ colors.blue ~ ';text-shadow:2px 2px 1px rgba(0,0,0,.1);font-family:' ~ fonts.family, 3 | 4 | 'primary_font': 'color:' ~ colors.base ~ ';font-size:' ~ fonts.size ~ 'px;line-height:1.5;font-family:' ~ fonts.family, 5 | 6 | 'secondary_font': 'font-size:' ~ fonts.size_secondary ~ 'px;line-height:1.5;font-family:' ~ fonts.family, 7 | 8 | 'module': 'background:#ffffff;padding:' ~ padding ~ 'px;border:1px solid ' ~ 10 9 | } %} -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/doc/annotations/JinjavaTextMateSnippet.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.doc.annotations; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ ElementType.TYPE, ElementType.METHOD }) 10 | public @interface JinjavaTextMateSnippet { 11 | String desc() default ""; 12 | 13 | String code(); 14 | 15 | String output() default ""; 16 | } 17 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-same-name-import-var/set-var-and-deferred.jinja: -------------------------------------------------------------------------------- 1 | {% if deferred %} 2 | {% do %}{% set path = 'eager/handles-same-name-import-var/set-var-and-deferred.jinja' %}{% set value = null %}{% set my_var = {} %}{% set my_var = {'foo': 'bar'} %}{% set my_var = {'my_var': my_var} %} 3 | {% set value = deferred %}{% do my_var.update({"value": value}) %} 4 | {% do my_var.update({'import_resource_path': 'eager/handles-same-name-import-var/set-var-and-deferred.jinja','value': value}) %}{% set path = '' %}{% enddo %} 5 | {{ my_var }} 6 | {% endif %} 7 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-break-in-for-loop/test.expected.jinja: -------------------------------------------------------------------------------- 1 | Start loop 2 | {% for __ignored__ in [0] %}\ 3 | {% if 0 > deferred %}\ 4 | {% break '' %}\ 5 | {% endif %}\ 6 | i is: 0 7 | {% if 1 > deferred %}\ 8 | {% break '' %}\ 9 | {% endif %}\ 10 | i is: 1 11 | {% if 2 > deferred %}\ 12 | {% break '' %}\ 13 | {% endif %}\ 14 | i is: 2 15 | {% if 3 > deferred %}\ 16 | {% break '' %}\ 17 | {% endif %}\ 18 | i is: 3 19 | {% if 4 > deferred %}\ 20 | {% break '' %}\ 21 | {% endif %}\ 22 | i is: 4 23 | {% endfor %}\ 24 | End loop -------------------------------------------------------------------------------- /src/test/resources/tags/macrotag/macro-referencing-macro.jinja: -------------------------------------------------------------------------------- 1 | {% set scoped_var = "myscopedvar" %} 2 | 3 | {%- macro uses_scoped_var() %} 4 | using scoped var: {{ scoped_var }} 5 | {% endmacro -%} 6 | 7 | {%- macro uses_public_fn(val) %} 8 | using public fn: {{ public(val) }} 9 | {% endmacro -%} 10 | 11 | {%- macro uses_private_fn(val) %} 12 | using private fn: {{ _private(val) }} 13 | {% endmacro -%} 14 | 15 | {%- macro public(val) %}public fn: {{ val }}{% endmacro -%} 16 | 17 | {%- macro _private(val) %}private fn: {{ val }}{% endmacro -%} 18 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/doc/JinjavaDocExpTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.doc; 2 | 3 | import java.util.Map; 4 | 5 | public class JinjavaDocExpTest extends JinjavaDocItem { 6 | 7 | public JinjavaDocExpTest( 8 | String name, 9 | String desc, 10 | String aliasOf, 11 | boolean deprecated, 12 | JinjavaDocParam[] inputs, 13 | JinjavaDocParam[] params, 14 | JinjavaDocSnippet[] snippets, 15 | Map meta 16 | ) { 17 | super(name, desc, aliasOf, deprecated, inputs, params, snippets, meta); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/doc/JinjavaDocFilter.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.doc; 2 | 3 | import java.util.Map; 4 | 5 | public class JinjavaDocFilter extends JinjavaDocItem { 6 | 7 | public JinjavaDocFilter( 8 | String name, 9 | String desc, 10 | String aliasOf, 11 | boolean deprecated, 12 | JinjavaDocParam[] inputs, 13 | JinjavaDocParam[] params, 14 | JinjavaDocSnippet[] snippets, 15 | Map meta 16 | ) { 17 | super(name, desc, aliasOf, deprecated, inputs, params, snippets, meta); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/DeferredMacroValueImpl.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | import com.google.common.annotations.Beta; 4 | 5 | @Beta 6 | public class DeferredMacroValueImpl implements DeferredValue { 7 | 8 | private static final DeferredValue INSTANCE = new DeferredMacroValueImpl(); 9 | 10 | private DeferredMacroValueImpl() {} 11 | 12 | @Override 13 | public Object getOriginalValue() { 14 | return null; 15 | } 16 | 17 | public static DeferredValue instance() { 18 | return INSTANCE; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/doc/JinjavaDocFunction.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.doc; 2 | 3 | import java.util.Map; 4 | 5 | public class JinjavaDocFunction extends JinjavaDocItem { 6 | 7 | public JinjavaDocFunction( 8 | String name, 9 | String desc, 10 | String aliasOf, 11 | boolean deprecated, 12 | JinjavaDocParam[] inputs, 13 | JinjavaDocParam[] params, 14 | JinjavaDocSnippet[] snippets, 15 | Map meta 16 | ) { 17 | super(name, desc, aliasOf, deprecated, inputs, params, snippets, meta); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/resources/eager/handles-deferred-modification-in-caller/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = ['a', 'b'] %}\ 2 | {% set __macro_callerino_729568755_temp_variable_0__ %}\ 3 | {% set __macro_caller_172086791_temp_variable_0__ %}\ 4 | {% do my_list.append(deferred) %}\ 5 | {{ my_list }}\ 6 | {% endset %}\ 7 | {{ __macro_caller_172086791_temp_variable_0__ }}\ 8 | {% do my_list.append('d') %}\ 9 | {% endset %}\ 10 | {% call __macro_callerino_729568755_temp_variable_0__ %}\ 11 | {% do my_list.append(deferred) %}\ 12 | {{ my_list }}\ 13 | {% endcall %} 14 | {{ my_list }} 15 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/UnexpectedTokenException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | public class UnexpectedTokenException extends TemplateSyntaxException { 4 | 5 | private static final long serialVersionUID = 1L; 6 | 7 | private final String token; 8 | 9 | public UnexpectedTokenException(String token, int lineNumber, int startPosition) { 10 | super(token, "Unexpected token: " + token, lineNumber, startPosition); 11 | this.token = token; 12 | } 13 | 14 | public String getToken() { 15 | return token; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/UnknownTokenException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | public class UnknownTokenException extends InterpretException { 4 | 5 | private static final long serialVersionUID = -388757722051666198L; 6 | private final String token; 7 | 8 | public UnknownTokenException(String token, int lineNumber, int startPosition) { 9 | super("Unknown token found: " + token.trim(), lineNumber, startPosition); 10 | this.token = token; 11 | } 12 | 13 | public String getToken() { 14 | return token; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-block-path-when-deferred-nested/test.expected.expected.jinja: -------------------------------------------------------------------------------- 1 | Parent's current path is: eager/reconstructs-block-path-when-deferred-nested/base.jinja 2 | -----Pre-First----- 3 | Child's first current path is: eager/reconstructs-block-path-when-deferred-nested/test.jinja 4 | 5 | -----Post-First----- 6 | -----Pre-Second----- 7 | Middle's second current path is: eager/reconstructs-block-path-when-deferred-nested/middle.jinja 8 | 9 | -----Post-Second----- 10 | Parent's current path is: eager/reconstructs-block-path-when-deferred-nested/base.jinja -------------------------------------------------------------------------------- /src/test/resources/eager/modifies-variable-in-deferred-macro/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% macro my_macro(list, other) %} 2 | {% do list.append(other) %} 3 | {% endmacro %}\ 4 | {% set list = [] %}\ 5 | {% do my_macro(list, deferred) %} 6 | {{ list }} 7 | 8 | {% macro my_macro(list, other) %} 9 | {% do list.append(other) %} 10 | {% endmacro %}\ 11 | {% set var = [] %}\ 12 | {% do my_macro(var, deferred) %} 13 | {{ var }} 14 | 15 | {% macro my_macro(list, other) %} 16 | {% do list.append(other) %} 17 | {% endmacro %}\ 18 | {% set var2 = [] %}\ 19 | {% do my_macro(var2, 1) %} 20 | {{ var2 }} 21 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/OutputTooBigException.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | public class OutputTooBigException extends RuntimeException { 4 | 5 | private long maxSize; 6 | private final long size; 7 | 8 | public OutputTooBigException(long maxSize, long size) { 9 | this.maxSize = maxSize; 10 | this.size = size; 11 | } 12 | 13 | @Override 14 | public String getMessage() { 15 | return String.format( 16 | "%d byte output rendered, over limit of %d bytes", 17 | size, 18 | maxSize 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/resources/eager/fully-defers-filtered-macro/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% macro flashy(foo) %}\ 2 | {{ filter:upper.filter(foo, ____int3rpr3t3r____) }} 3 | A flashy {{ deferred }}\ 4 | .{% endmacro %}\ 5 | {% set __macro_flashy_1625622909_temp_variable_0__ %}\ 6 | BAR 7 | A flashy {{ deferred }}\ 8 | .{% endset %}\ 9 | {{ flashy(__macro_flashy_1625622909_temp_variable_0__) }} 10 | --- 11 | 12 | {% set __macro_silly_2092874071_temp_variable_0__ %}\ 13 | A silly {{ deferred }}\ 14 | .{% endset %}\ 15 | {{ filter:upper.filter(__macro_silly_2092874071_temp_variable_0__, ____int3rpr3t3r____) }} -------------------------------------------------------------------------------- /src/test/java/com/hubspot/jinjava/lib/filter/DAliasedDefaultFilterTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.lib.filter; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import com.hubspot.jinjava.BaseJinjavaTest; 6 | import java.util.HashMap; 7 | import org.junit.Test; 8 | 9 | public class DAliasedDefaultFilterTest extends BaseJinjavaTest { 10 | 11 | @Test 12 | public void itSetsDefaultStringValues() { 13 | assertThat( 14 | jinjava.render("{% set d=d |d(\"some random value\") %}{{ d }}", new HashMap<>()) 15 | ) 16 | .isEqualTo("some random value"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/el/ext/IdentifierPreservationStrategy.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.el.ext; 2 | 3 | public enum IdentifierPreservationStrategy { 4 | PRESERVING(true), 5 | RESOLVING(false); 6 | 7 | public static IdentifierPreservationStrategy preserving(boolean preserveIdentifier) { 8 | return preserveIdentifier ? PRESERVING : RESOLVING; 9 | } 10 | 11 | private final boolean preserving; 12 | 13 | IdentifierPreservationStrategy(boolean preserving) { 14 | this.preserving = preserving; 15 | } 16 | 17 | public boolean isPreserving() { 18 | return preserving; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/resources/eager/reconstructs-deferred-variable-eventually/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% set my_list = [] %}\ 2 | {% set __macro_append_stuff_153654787_temp_variable_0__ %} 3 | {% if deferred %} 4 | 5 | {% set __macro_foo_97643642_temp_variable_0__ %} 6 | {% do my_list.append('b') %} 7 | {% endset %}\ 8 | {{ __macro_foo_97643642_temp_variable_0__ }} 9 | {% set __macro_foo_97643642_temp_variable_1__ %} 10 | {% do my_list.append('c') %} 11 | {% endset %}\ 12 | {{ __macro_foo_97643642_temp_variable_1__ }} 13 | {% endif %} 14 | {% endset %}\ 15 | {{ __macro_append_stuff_153654787_temp_variable_0__ }} 16 | 17 | {{ my_list }} 18 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/doc/JinjavaDocSnippet.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.doc; 2 | 3 | public class JinjavaDocSnippet { 4 | 5 | private final String desc; 6 | private final String code; 7 | private final String output; 8 | 9 | public JinjavaDocSnippet(String desc, String code, String output) { 10 | this.desc = desc; 11 | this.code = code; 12 | this.output = output; 13 | } 14 | 15 | public String getDesc() { 16 | return desc; 17 | } 18 | 19 | public String getCode() { 20 | return code; 21 | } 22 | 23 | public String getOutput() { 24 | return output; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/doc/annotations/JinjavaParam.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.doc.annotations; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ ElementType.TYPE, ElementType.METHOD }) 10 | public @interface JinjavaParam { 11 | String value(); 12 | 13 | String type() default "String"; 14 | 15 | String desc() default ""; 16 | 17 | String defaultValue() default ""; 18 | 19 | boolean required() default false; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/el/ext/eager/EagerExtendedSyntaxBuilder.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.el.ext.eager; 2 | 3 | import com.hubspot.jinjava.el.ExtendedSyntaxBuilder; 4 | import de.odysseus.el.tree.impl.Parser; 5 | 6 | public class EagerExtendedSyntaxBuilder extends ExtendedSyntaxBuilder { 7 | 8 | public EagerExtendedSyntaxBuilder() { 9 | super(); 10 | } 11 | 12 | public EagerExtendedSyntaxBuilder(Feature... features) { 13 | super(features); 14 | } 15 | 16 | @Override 17 | protected Parser createParser(String expression) { 18 | return new EagerExtendedParser(this, expression); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/resources/tags/extendstag/base1.jinja: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block head %} 6 | 7 | {% block title %}{% endblock %} - My Webpage 8 | {% endblock %} 9 | 10 | 11 |
{% block content %}{% endblock %}
12 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/util/RenderLimitUtils.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.util; 2 | 3 | import com.hubspot.jinjava.JinjavaConfig; 4 | 5 | public class RenderLimitUtils { 6 | 7 | public static long clampProvidedRenderLimitToConfig( 8 | long providedLimit, 9 | JinjavaConfig jinjavaConfig 10 | ) { 11 | long configMaxOutput = jinjavaConfig.getMaxOutputSize(); 12 | 13 | if (configMaxOutput <= 0) { 14 | return providedLimit; 15 | } 16 | 17 | if (providedLimit <= 0) { 18 | return configMaxOutput; 19 | } 20 | 21 | return Math.min(providedLimit, configMaxOutput); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/com/hubspot/jinjava/BaseJinjavaTest.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava; 2 | 3 | import org.junit.Before; 4 | 5 | public abstract class BaseJinjavaTest { 6 | 7 | public Jinjava jinjava; 8 | 9 | @Before 10 | public void baseSetup() { 11 | jinjava = 12 | new Jinjava( 13 | JinjavaConfig 14 | .newBuilder() 15 | .withLegacyOverrides( 16 | LegacyOverrides 17 | .newBuilder() 18 | .withUsePyishObjectMapper(true) 19 | .withKeepNullableLoopValues(true) 20 | .build() 21 | ) 22 | .build() 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/el/ext/StringBuildingOperator.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.el.ext; 2 | 3 | import com.hubspot.jinjava.interpret.JinjavaInterpreter; 4 | import com.hubspot.jinjava.util.LengthLimitingStringBuilder; 5 | 6 | public interface StringBuildingOperator { 7 | default LengthLimitingStringBuilder getStringBuilder() { 8 | JinjavaInterpreter interpreter = JinjavaInterpreter.getCurrent(); 9 | 10 | long maxSize = (interpreter == null || interpreter.getConfig() == null) 11 | ? 0 12 | : interpreter.getConfig().getMaxOutputSize(); 13 | 14 | return new LengthLimitingStringBuilder(maxSize); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/features/Features.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.features; 2 | 3 | import com.hubspot.jinjava.interpret.Context; 4 | 5 | public class Features { 6 | 7 | private final FeatureConfig featureConfig; 8 | 9 | public Features(FeatureConfig featureConfig) { 10 | this.featureConfig = featureConfig; 11 | } 12 | 13 | public boolean isActive(String featureName, Context context) { 14 | return getActivationStrategy(featureName).isActive(context); 15 | } 16 | 17 | public FeatureActivationStrategy getActivationStrategy(String featureName) { 18 | return featureConfig.getFeature(featureName); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/util/CharArrayUtils.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.util; 2 | 3 | public class CharArrayUtils { 4 | 5 | public static boolean charArrayRegionMatches( 6 | char[] value, 7 | int startPos, 8 | CharSequence toMatch 9 | ) { 10 | int matchLen = toMatch.length(), endPos = startPos + matchLen; 11 | 12 | if (endPos > value.length) { 13 | return false; 14 | } 15 | 16 | for (int matchIndex = 0, i = startPos; i < endPos; i++, matchIndex++) { 17 | if (value[i] != toMatch.charAt(matchIndex)) { 18 | return false; 19 | } 20 | } 21 | 22 | return true; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/el/JinjavaObjectUnwrapper.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.el; 2 | 3 | import com.hubspot.jinjava.interpret.LazyExpression; 4 | import java.util.Optional; 5 | 6 | public class JinjavaObjectUnwrapper implements ObjectUnwrapper { 7 | 8 | @Override 9 | public Object unwrapObject(Object o) { 10 | if (o instanceof LazyExpression) { 11 | o = ((LazyExpression) o).get(); 12 | } 13 | 14 | if (o instanceof Optional) { 15 | Optional optValue = (Optional) o; 16 | if (!optValue.isPresent()) { 17 | return null; 18 | } 19 | 20 | o = optValue.get(); 21 | } 22 | 23 | return o; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/hubspot/jinjava/interpret/JinjavaInterpreterFactory.java: -------------------------------------------------------------------------------- 1 | package com.hubspot.jinjava.interpret; 2 | 3 | import com.hubspot.jinjava.Jinjava; 4 | import com.hubspot.jinjava.JinjavaConfig; 5 | 6 | public class JinjavaInterpreterFactory implements InterpreterFactory { 7 | 8 | @Override 9 | public JinjavaInterpreter newInstance(JinjavaInterpreter orig) { 10 | return new JinjavaInterpreter(orig); 11 | } 12 | 13 | @Override 14 | public JinjavaInterpreter newInstance( 15 | Jinjava application, 16 | Context context, 17 | JinjavaConfig renderConfig 18 | ) { 19 | return new JinjavaInterpreter(application, context, renderConfig); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/resources/tags/eager/extendstag/reconstructs-deferred-outside-block.expected.jinja: -------------------------------------------------------------------------------- 1 | {# Start Label: ignored_output_from_extends #}{% do %} 2 | {% if deferred %} 3 | {% set foo = 'yes' %} 4 | {% else %} 5 | {% set foo = 'no' %} 6 | {% endif %}\ 7 | {% enddo %}\ 8 | {# End Label: ignored_output_from_extends #}{% set current_path = '../eager/extendstag/base.html' %}\ 9 | 10 | 11 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/test/resources/eager/defers-large-loop/test.expected.jinja: -------------------------------------------------------------------------------- 1 | {% for __ignored__ in [0] %} 2 | Small 0 {{ deferred }} {{ deferred ~ 0 }} 3 | 4 | Small 1 {{ deferred }} {{ deferred ~ 1 }} 5 | 6 | Small 2 {{ deferred }} {{ deferred ~ 2 }} 7 | 8 | Small 3 {{ deferred }} {{ deferred ~ 3 }} 9 | 10 | Small 4 {{ deferred }} {{ deferred ~ 4 }} 11 | 12 | Small 5 {{ deferred }} {{ deferred ~ 5 }} 13 | 14 | Small 6 {{ deferred }} {{ deferred ~ 6 }} 15 | 16 | Small 7 {{ deferred }} {{ deferred ~ 7 }} 17 | 18 | Small 8 {{ deferred }} {{ deferred ~ 8 }} 19 | 20 | Small 9 {{ deferred }} {{ deferred ~ 9 }} 21 | {% endfor %} 22 | {% for i in range(600) %} 23 | Big {{ i }} {{ deferred }} {{ deferred ~ i }} 24 | {% endfor %} -------------------------------------------------------------------------------- /src/test/resources/eager/does-not-reconstruct-extra-times/test.jinja: -------------------------------------------------------------------------------- 1 | {% set foo = 'first' %} 2 | {% for i in range(1) %} 3 | {# this should do nothing because it's in a for loop #} 4 | {% set foo = deferred %} 5 | {% endfor %} 6 | 7 | {# actually defer foo #} 8 | {% set foo = deferred %} 9 | 10 | {# make sure we don't reconstruct foo = 'first' in front of the for block #} 11 | {% for i in range(1) %} 12 | {% if deferred %} 13 | {{ foo }} 14 | {% set foo = 'second' %} 15 | {% endif %} 16 | {{ foo }} 17 | {% endfor %} 18 | {{ foo }} 19 | 20 | {# make sure we don't reconstruct foo = 'first' in front of the if block #} 21 | {% if deferred %} 22 | {% set foo = 'second' %} 23 | {% endif %} 24 | {{ foo }} 25 | 26 | --------------------------------------------------------------------------------