├── askama ├── README.md ├── deny.toml ├── LICENSE-MIT ├── _typos.toml ├── clippy.toml ├── .rustfmt.toml ├── LICENSE-APACHE ├── tomlfmt.toml └── benches │ └── escape.rs ├── bench-build ├── deny.toml ├── LICENSE-MIT ├── _typos.toml ├── clippy.toml ├── .rustfmt.toml ├── LICENSE-APACHE ├── tomlfmt.toml ├── templates │ ├── hello_world.html │ └── greeting.html ├── run.sh └── Cargo.toml ├── clippy.toml ├── fuzzing ├── _typos.toml ├── clippy.toml ├── deny.toml ├── .rustfmt.toml ├── tomlfmt.toml ├── fuzz │ ├── src │ │ ├── ascii_str.rs │ │ └── html │ │ │ └── html.rs │ ├── artifacts │ │ ├── .gitattributes │ │ ├── derive │ │ │ ├── clusterfuzz-testcase-minimized-derive-4654117948817408 │ │ │ ├── clusterfuzz-testcase-minimized-derive-4793932351602688 │ │ │ ├── clusterfuzz-testcase-minimized-derive-4955521990066176 │ │ │ ├── clusterfuzz-testcase-minimized-derive-5037184261619712 │ │ │ ├── clusterfuzz-testcase-minimized-derive-5064777150038016 │ │ │ ├── clusterfuzz-testcase-minimized-derive-5107711304073216 │ │ │ ├── clusterfuzz-testcase-minimized-derive-5144827852554240 │ │ │ ├── clusterfuzz-testcase-minimized-derive-5353647120908288 │ │ │ ├── clusterfuzz-testcase-minimized-derive-5387873899839488 │ │ │ ├── clusterfuzz-testcase-minimized-derive-5611392537526272 │ │ │ ├── clusterfuzz-testcase-minimized-derive-5780292277436416 │ │ │ ├── clusterfuzz-testcase-minimized-derive-6051930453639168 │ │ │ ├── clusterfuzz-testcase-minimized-derive-6236623325167616 │ │ │ ├── clusterfuzz-testcase-minimized-derive-6380739026550784 │ │ │ ├── clusterfuzz-testcase-minimized-derive-6503980895371264 │ │ │ ├── clusterfuzz-testcase-minimized-derive-6542584430526464 │ │ │ ├── clusterfuzz-testcase-minimized-derive-6573215117017088 │ │ │ ├── clusterfuzz-testcase-minimized-derive-6617490908315648 │ │ │ ├── clusterfuzz-testcase-minimized-derive-6639137261420544 │ │ │ └── clusterfuzz-testcase-minimized-derive-6696196543676416 │ │ └── filters │ │ │ └── minimized-from-b44b4bd1da1759dee0924a8586a6001e80da76fa │ └── fuzz_targets │ │ ├── all.rs │ │ ├── html.rs │ │ ├── derive.rs │ │ ├── filters.rs │ │ └── parser.rs ├── Cargo.toml └── README.md ├── testing ├── LICENSE-MIT ├── _typos.toml ├── clippy.toml ├── deny.toml ├── templates │ ├── no-block.txt │ ├── foo.askama │ ├── foo.html │ ├── foo.jinja │ ├── latex-file.tex │ ├── included │ │ └── fragment.html │ ├── attr.html │ ├── foo.html.askama │ ├── foo.html.jinja │ ├── use-var.txt │ ├── filters.html │ ├── generics.html │ ├── hello.html │ ├── included.html │ ├── composition.html │ ├── filters_join.html │ ├── format.html │ ├── if.html │ ├── invalid_syntax.html │ ├── cycle1.html │ ├── cycle2.html │ ├── nested-attr.html │ ├── rust-macros.html │ ├── let-base.html │ ├── tuple-attr.html │ ├── char-literals │ │ ├── char-literal-1.txt │ │ ├── char-literal-2.txt │ │ ├── char-literal-5.txt │ │ ├── char-literal-3.txt │ │ ├── char-literal-4.txt │ │ ├── char-literal-6.txt │ │ └── char-literal-7.txt │ ├── nested │ │ ├── sub-nested │ │ │ └── included.html │ │ └── included.html │ ├── else.html │ ├── no-block-with-include.txt │ ├── rust-macros-full-path.html │ ├── transclude-there.html │ ├── a_file_that_is_actually_a_folder.html │ │ └── .gitignore │ ├── include_invalid_syntax.html │ ├── let.html │ ├── literals.html │ ├── raw-simple.html │ ├── if-let-shadowing.html │ ├── if-let.html │ ├── no-block-with-include-times-2.txt │ ├── size-parent.txt │ ├── base-decl.txt │ ├── no-block-with-base-template.txt │ ├── else-if.html │ ├── include.html │ ├── raw-ws.html │ ├── extend_and_import.html │ ├── include-base.html │ ├── match-no-ws.html │ ├── include-nested.html │ ├── size-child-super.txt │ ├── import.html │ ├── nested-base.html │ ├── if-let-struct.html │ ├── include-extends-included.html │ ├── leaf-templates │ │ └── includer.html │ ├── option.html │ ├── size-child.txt │ ├── base.html │ ├── child.html │ ├── deep-import-parent.html │ ├── deep-nested-macro.html │ ├── include-extends.html │ ├── raw-complex.html │ ├── block_in_include_partial.html │ ├── let-child.html │ ├── include-macro.html │ ├── macro-self-arg.html │ ├── nested-child.html │ ├── match-literal-num.html │ ├── big-table.html │ ├── let-decl.html │ ├── ranges.txt │ ├── render_in_place.html │ ├── deep-import-child.html │ ├── let-destruct-tuple.html │ ├── nested-for.html │ ├── simple.html │ ├── block_in_include_base.html │ ├── included-macro.html │ ├── literals-escape.html │ ├── macro-import-callexpr.html │ ├── macro-recursion-1.html │ ├── macro-recursion-2.html │ ├── macro-recursion-3.html │ ├── simple-no-escape.txt │ ├── match-literal-char.html │ ├── precedence.html │ ├── if-let-else.html │ ├── match-literal.html │ ├── include-extends-base.html │ ├── match-opt.html │ ├── fragment-base.html │ ├── match-opt-bool.html │ ├── precedence-for.html │ ├── fragment-mid-super.html │ ├── fragment-simple.html │ ├── blocks.txt │ ├── match-enum-or.html │ ├── nested-macro-callexpr.html │ ├── deep-kid.html │ ├── for.html │ ├── fragment-super.html │ ├── fragment-nested-super.html │ ├── fragment-unused-expr.html │ ├── nested-macro.html │ ├── block_in_include_extended.html │ ├── nested-macro-args.html │ ├── rust-macro-args.html │ ├── macro-with-caller.html │ ├── fragment-nested-block.html │ ├── match-option-result-option.html │ ├── macro-call-raw-string-many-hashes.html │ ├── macro-import-str-cmp.html │ ├── macro-no-args.html │ ├── deep-base.html │ ├── for-break-continue.html │ ├── for-range.html │ ├── named-end.html │ ├── macro-import-str-cmp-macro.html │ ├── match-custom-enum.html │ ├── html-base.html │ ├── teams.html │ ├── macro-short-circuit.html │ ├── macro.html │ ├── filter-recursion.html │ ├── let-shadow.html │ ├── deep-mid.html │ ├── operators.html │ ├── num-literals.html │ ├── compare.html │ └── if-coerce.html ├── .rustfmt.toml ├── tomlfmt.toml ├── LICENSE-APACHE ├── jinja2-assumptions │ ├── .python-version │ ├── .gitignore │ ├── README.md │ ├── test.sh │ └── pyproject.toml ├── folder-config.toml │ └── .gitignore ├── test_minimize.toml ├── test_trim.toml ├── delim-too-short.toml ├── issue-128.toml ├── issue-128-2.toml ├── operator-plus-config.toml ├── delim-clash.toml ├── operator-paren-config.toml ├── tests │ ├── ui │ │ ├── no_template_attribute.rs │ │ ├── cycle.rs │ │ ├── cycle2.rs │ │ ├── incorrect_path.rs │ │ ├── union.stderr │ │ ├── no_template_attribute.stderr │ │ ├── ref_deref.rs │ │ ├── empty-match.rs │ │ ├── macro-caller.rs │ │ ├── macro-super.rs │ │ ├── references.rs │ │ ├── duplicated_template_attribute.stderr │ │ ├── filter-recursion.rs │ │ ├── lit_on_assignment_lhs.rs │ │ ├── union.rs │ │ ├── fuzzing.stderr │ │ ├── name_mismatch_endblock.rs │ │ ├── extend.rs │ │ ├── fuzzed_recursion_depth_mul_deref.rs │ │ ├── include-a-folder.rs │ │ ├── name_mismatch_endmacro.rs │ │ ├── json-too-many-args.rs │ │ ├── multiple_extends.rs │ │ ├── break_outside_of_loop.rs │ │ ├── number.rs │ │ ├── pluralize.rs │ │ ├── fuzzing.rs │ │ ├── filter_block_ws.rs │ │ ├── ref_deref.stderr │ │ ├── cycle2.stderr │ │ ├── typo_in_keyword.rs │ │ ├── lit_on_assignment_lhs.stderr │ │ ├── duplicated_template_attribute.rs │ │ ├── loop-fields.rs │ │ ├── block_and_vars.rs │ │ ├── declare.rs │ │ ├── macro-args.stderr │ │ ├── incorrect_path.stderr │ │ ├── macro-args.rs │ │ ├── transclude-missing.rs │ │ ├── extend.stderr │ │ ├── block_and_vars.stderr │ │ ├── loop-fields.stderr │ │ ├── loop_cycle_wrong_argument_count.rs │ │ ├── json-too-many-args.stderr │ │ ├── break_outside_of_loop.stderr │ │ ├── macro-super.stderr │ │ ├── macro-caller.stderr │ │ ├── cycle.stderr │ │ ├── empty-match.stderr │ │ ├── name_mismatch_endblock.stderr │ │ ├── references.stderr │ │ ├── name_mismatch_endmacro.stderr │ │ ├── escape-filter-invalid-kind.rs │ │ ├── multiple_extends.stderr │ │ ├── ambiguous-ws-raw.rs │ │ ├── error_file_path.rs │ │ ├── filter_block_ws.stderr │ │ ├── filter-recursion.stderr │ │ ├── match_with_extra.rs │ │ ├── typo_in_keyword.stderr │ │ ├── macro-caller-with-callexpr.rs │ │ ├── loop_cycle_wrong_argument_count.stderr │ │ ├── match-unit-structs.rs │ │ ├── block_in_filter_block.rs │ │ ├── loop_cycle_empty.rs │ │ ├── macro-caller-with-callexpr.stderr │ │ ├── terminator-operator.rs │ │ ├── fuzzed_recursion_depth_mul_deref.stderr │ │ ├── include-a-folder.stderr │ │ ├── block_in_filter_block.stderr │ │ ├── num-suffix.rs │ │ ├── match_with_extra.stderr │ │ ├── declare.stderr │ │ ├── macro_default_value.rs │ │ ├── vars.rs │ │ ├── no-such-escaper.rs │ │ ├── blocks_below_top_level.rs │ │ ├── truncate.rs │ │ ├── escape-filter-invalid-kind.stderr │ │ ├── num-suffix.stderr │ │ ├── pluralize.stderr │ │ ├── terminator-operator.stderr │ │ ├── no-block.rs │ │ ├── loop_cycle_empty.stderr │ │ ├── as-primitive-type.rs │ │ ├── number.stderr │ │ ├── excessive_nesting.stderr │ │ ├── macro-args-hashtag.rs │ │ ├── iso646.rs │ │ ├── transclude-missing.stderr │ │ ├── iso646.stderr │ │ ├── wrong-end.rs │ │ ├── error_file_path.stderr │ │ ├── broken-config.rs │ │ ├── underscore.rs │ │ ├── is_defined.rs │ │ ├── garbled-closing-blocks.rs │ │ ├── macro_default_value.stderr │ │ ├── expr_fn_calls.rs │ │ ├── ambiguous-ws-raw.stderr │ │ ├── let_destructuring_has_rest.rs │ │ ├── macro-args-hashtag.stderr │ │ ├── vars.stderr │ │ ├── no-block.stderr │ │ ├── values.rs │ │ ├── end-block.rs │ │ ├── invalid_array_repeat.rs │ │ ├── macro-named-crate.rs │ │ ├── macro-recursion.rs │ │ ├── enum.stderr │ │ ├── comments-in-macro-calls.rs │ │ ├── struct-expressions.rs │ │ ├── named_filter_arguments.rs │ │ ├── unexpected-tag.rs │ │ └── comparator-chaining.rs │ ├── custom_ui │ │ ├── duplicated_block_calls.stderr │ │ └── duplicated_block_calls.rs │ ├── path.rs │ ├── coerce.rs │ ├── hello.rs │ ├── if.rs │ ├── rest_pattern.rs │ ├── no_implicit_prelude.rs │ ├── reexported-askama.rs │ ├── extend.rs │ ├── cow_str_implements_fast_writable.rs │ ├── declare.rs │ ├── size_hint.rs │ ├── render_in_place.rs │ └── blocks.rs ├── build.rs └── Cargo.toml ├── askama_derive ├── deny.toml ├── empty_test_config.toml ├── templates │ ├── a.html │ ├── b.html │ ├── include3.html │ ├── sub │ │ ├── b.html │ │ ├── c.html │ │ └── sub1 │ │ │ └── d.html │ ├── include1.html │ └── include2.html ├── .rustfmt.toml ├── LICENSE-MIT ├── _typos.toml ├── clippy.toml ├── tomlfmt.toml ├── LICENSE-APACHE ├── src │ ├── html.rs │ ├── ascii_str.rs │ └── generator │ │ └── helpers │ │ └── mod.rs └── README.md ├── askama_escape ├── deny.toml ├── .rustfmt.toml ├── LICENSE-MIT ├── _typos.toml ├── clippy.toml ├── tomlfmt.toml ├── LICENSE-APACHE ├── src │ ├── html.rs │ └── ascii_str.rs ├── benches │ ├── strings.inc │ └── all.rs └── Cargo.toml ├── askama_macros ├── deny.toml ├── .rustfmt.toml ├── LICENSE-MIT ├── _typos.toml ├── clippy.toml ├── tomlfmt.toml ├── LICENSE-APACHE ├── src │ └── lib.rs ├── README.md └── Cargo.toml ├── askama_parser ├── deny.toml ├── .rustfmt.toml ├── LICENSE-MIT ├── _typos.toml ├── clippy.toml ├── tomlfmt.toml ├── LICENSE-APACHE ├── src │ └── ascii_str.rs ├── benches │ └── librustdoc │ │ ├── item_info.html │ │ ├── type_layout_size.html │ │ ├── LICENSE.md │ │ ├── source.html │ │ ├── short_item_info.html │ │ ├── print_item.html │ │ └── item_union.html ├── README.md └── Cargo.toml ├── testing-alloc ├── deny.toml ├── .rustfmt.toml ├── LICENSE-MIT ├── _typos.toml ├── clippy.toml ├── tomlfmt.toml ├── LICENSE-APACHE ├── templates │ └── hello-world.html └── Cargo.toml ├── testing-no-std ├── deny.toml ├── LICENSE-MIT ├── _typos.toml ├── clippy.toml ├── tomlfmt.toml ├── .rustfmt.toml ├── LICENSE-APACHE ├── templates │ └── hello-world.html └── Cargo.toml ├── testing-renamed ├── deny.toml ├── LICENSE-MIT ├── _typos.toml ├── clippy.toml ├── tomlfmt.toml ├── .rustfmt.toml ├── LICENSE-APACHE ├── templates │ └── hello-world.html └── Cargo.toml ├── examples ├── axum-app │ ├── deny.toml │ ├── LICENSE-MIT │ ├── _typos.toml │ ├── clippy.toml │ ├── tomlfmt.toml │ ├── .rustfmt.toml │ ├── LICENSE-APACHE │ ├── templates │ │ └── error.html │ └── README.md ├── poem-app │ ├── deny.toml │ ├── LICENSE-MIT │ ├── _typos.toml │ ├── clippy.toml │ ├── tomlfmt.toml │ ├── .rustfmt.toml │ ├── LICENSE-APACHE │ ├── templates │ │ └── error.html │ ├── README.md │ └── Cargo.toml ├── salvo-app │ ├── deny.toml │ ├── LICENSE-MIT │ ├── _typos.toml │ ├── clippy.toml │ ├── .rustfmt.toml │ ├── LICENSE-APACHE │ ├── tomlfmt.toml │ ├── templates │ │ └── error.html │ └── README.md ├── warp-app │ ├── deny.toml │ ├── LICENSE-MIT │ ├── _typos.toml │ ├── clippy.toml │ ├── tomlfmt.toml │ ├── .rustfmt.toml │ ├── LICENSE-APACHE │ ├── templates │ │ └── error.html │ └── README.md ├── actix-web-app │ ├── deny.toml │ ├── LICENSE-MIT │ ├── _typos.toml │ ├── clippy.toml │ ├── tomlfmt.toml │ ├── .rustfmt.toml │ ├── LICENSE-APACHE │ ├── templates │ │ └── error.html │ └── README.md └── rocket-app │ ├── LICENSE-MIT │ ├── _typos.toml │ ├── clippy.toml │ ├── deny.toml │ ├── .rustfmt.toml │ ├── tomlfmt.toml │ ├── LICENSE-APACHE │ ├── templates │ └── error.html │ ├── README.md │ └── Cargo.toml ├── .gitignore ├── book ├── .gitignore ├── book.toml ├── src │ └── SUMMARY.md ├── ethicalads-theme.css ├── ethicalads-theme.sass └── 404.html ├── .gitattributes ├── .gitmodules ├── .github ├── dependabot.yml └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── deny.toml ├── Cargo.toml ├── .rustfmt.toml ├── tomlfmt.toml ├── _typos.toml └── LICENSE-MIT /askama/README.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /askama/deny.toml: -------------------------------------------------------------------------------- 1 | ../deny.toml -------------------------------------------------------------------------------- /askama/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /askama/_typos.toml: -------------------------------------------------------------------------------- 1 | ../_typos.toml -------------------------------------------------------------------------------- /askama/clippy.toml: -------------------------------------------------------------------------------- 1 | ../clippy.toml -------------------------------------------------------------------------------- /bench-build/deny.toml: -------------------------------------------------------------------------------- 1 | ../deny.toml -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | msrv = "1.88.0" 2 | -------------------------------------------------------------------------------- /fuzzing/_typos.toml: -------------------------------------------------------------------------------- 1 | ../_typos.toml -------------------------------------------------------------------------------- /fuzzing/clippy.toml: -------------------------------------------------------------------------------- 1 | ../clippy.toml -------------------------------------------------------------------------------- /fuzzing/deny.toml: -------------------------------------------------------------------------------- 1 | ../deny.toml -------------------------------------------------------------------------------- /testing/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /testing/_typos.toml: -------------------------------------------------------------------------------- 1 | ../_typos.toml -------------------------------------------------------------------------------- /testing/clippy.toml: -------------------------------------------------------------------------------- 1 | ../clippy.toml -------------------------------------------------------------------------------- /testing/deny.toml: -------------------------------------------------------------------------------- 1 | ../deny.toml -------------------------------------------------------------------------------- /testing/templates/no-block.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /askama/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../.rustfmt.toml -------------------------------------------------------------------------------- /askama/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /askama/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../tomlfmt.toml -------------------------------------------------------------------------------- /askama_derive/deny.toml: -------------------------------------------------------------------------------- 1 | ../deny.toml -------------------------------------------------------------------------------- /askama_derive/empty_test_config.toml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /askama_derive/templates/a.html: -------------------------------------------------------------------------------- 1 | foo 2 | -------------------------------------------------------------------------------- /askama_derive/templates/b.html: -------------------------------------------------------------------------------- 1 | bar 2 | -------------------------------------------------------------------------------- /askama_escape/deny.toml: -------------------------------------------------------------------------------- 1 | ../deny.toml -------------------------------------------------------------------------------- /askama_macros/deny.toml: -------------------------------------------------------------------------------- 1 | ../deny.toml -------------------------------------------------------------------------------- /askama_parser/deny.toml: -------------------------------------------------------------------------------- 1 | ../deny.toml -------------------------------------------------------------------------------- /bench-build/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /bench-build/_typos.toml: -------------------------------------------------------------------------------- 1 | ../_typos.toml -------------------------------------------------------------------------------- /bench-build/clippy.toml: -------------------------------------------------------------------------------- 1 | ../clippy.toml -------------------------------------------------------------------------------- /fuzzing/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../.rustfmt.toml -------------------------------------------------------------------------------- /fuzzing/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../tomlfmt.toml -------------------------------------------------------------------------------- /testing-alloc/deny.toml: -------------------------------------------------------------------------------- 1 | ../deny.toml -------------------------------------------------------------------------------- /testing-no-std/deny.toml: -------------------------------------------------------------------------------- 1 | ../deny.toml -------------------------------------------------------------------------------- /testing-renamed/deny.toml: -------------------------------------------------------------------------------- 1 | ../deny.toml -------------------------------------------------------------------------------- /testing/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../.rustfmt.toml -------------------------------------------------------------------------------- /testing/templates/foo.askama: -------------------------------------------------------------------------------- 1 | foo.askama -------------------------------------------------------------------------------- /testing/templates/foo.html: -------------------------------------------------------------------------------- 1 | foo.html -------------------------------------------------------------------------------- /testing/templates/foo.jinja: -------------------------------------------------------------------------------- 1 | foo.jinja -------------------------------------------------------------------------------- /testing/templates/latex-file.tex: -------------------------------------------------------------------------------- 1 | empty. -------------------------------------------------------------------------------- /testing/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../tomlfmt.toml -------------------------------------------------------------------------------- /askama_derive/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../.rustfmt.toml -------------------------------------------------------------------------------- /askama_derive/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /askama_derive/_typos.toml: -------------------------------------------------------------------------------- 1 | ../_typos.toml -------------------------------------------------------------------------------- /askama_derive/clippy.toml: -------------------------------------------------------------------------------- 1 | ../clippy.toml -------------------------------------------------------------------------------- /askama_derive/templates/include3.html: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /askama_derive/templates/sub/b.html: -------------------------------------------------------------------------------- 1 | bar 2 | -------------------------------------------------------------------------------- /askama_derive/templates/sub/c.html: -------------------------------------------------------------------------------- 1 | baz 2 | -------------------------------------------------------------------------------- /askama_derive/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../tomlfmt.toml -------------------------------------------------------------------------------- /askama_escape/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../.rustfmt.toml -------------------------------------------------------------------------------- /askama_escape/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /askama_escape/_typos.toml: -------------------------------------------------------------------------------- 1 | ../_typos.toml -------------------------------------------------------------------------------- /askama_escape/clippy.toml: -------------------------------------------------------------------------------- 1 | ../clippy.toml -------------------------------------------------------------------------------- /askama_escape/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../tomlfmt.toml -------------------------------------------------------------------------------- /askama_macros/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../.rustfmt.toml -------------------------------------------------------------------------------- /askama_macros/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /askama_macros/_typos.toml: -------------------------------------------------------------------------------- 1 | ../_typos.toml -------------------------------------------------------------------------------- /askama_macros/clippy.toml: -------------------------------------------------------------------------------- 1 | ../clippy.toml -------------------------------------------------------------------------------- /askama_macros/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../tomlfmt.toml -------------------------------------------------------------------------------- /askama_parser/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../.rustfmt.toml -------------------------------------------------------------------------------- /askama_parser/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /askama_parser/_typos.toml: -------------------------------------------------------------------------------- 1 | ../_typos.toml -------------------------------------------------------------------------------- /askama_parser/clippy.toml: -------------------------------------------------------------------------------- 1 | ../clippy.toml -------------------------------------------------------------------------------- /askama_parser/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../tomlfmt.toml -------------------------------------------------------------------------------- /bench-build/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../.rustfmt.toml -------------------------------------------------------------------------------- /bench-build/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /bench-build/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../tomlfmt.toml -------------------------------------------------------------------------------- /examples/axum-app/deny.toml: -------------------------------------------------------------------------------- 1 | ../../deny.toml -------------------------------------------------------------------------------- /examples/poem-app/deny.toml: -------------------------------------------------------------------------------- 1 | ../../deny.toml -------------------------------------------------------------------------------- /examples/salvo-app/deny.toml: -------------------------------------------------------------------------------- 1 | ../../deny.toml -------------------------------------------------------------------------------- /examples/warp-app/deny.toml: -------------------------------------------------------------------------------- 1 | ../../deny.toml -------------------------------------------------------------------------------- /testing-alloc/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../.rustfmt.toml -------------------------------------------------------------------------------- /testing-alloc/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /testing-alloc/_typos.toml: -------------------------------------------------------------------------------- 1 | ../_typos.toml -------------------------------------------------------------------------------- /testing-alloc/clippy.toml: -------------------------------------------------------------------------------- 1 | ../clippy.toml -------------------------------------------------------------------------------- /testing-alloc/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../tomlfmt.toml -------------------------------------------------------------------------------- /testing-no-std/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /testing-no-std/_typos.toml: -------------------------------------------------------------------------------- 1 | ../_typos.toml -------------------------------------------------------------------------------- /testing-no-std/clippy.toml: -------------------------------------------------------------------------------- 1 | ../clippy.toml -------------------------------------------------------------------------------- /testing-no-std/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../tomlfmt.toml -------------------------------------------------------------------------------- /testing-renamed/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /testing-renamed/_typos.toml: -------------------------------------------------------------------------------- 1 | ../_typos.toml -------------------------------------------------------------------------------- /testing-renamed/clippy.toml: -------------------------------------------------------------------------------- 1 | ../clippy.toml -------------------------------------------------------------------------------- /testing-renamed/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../tomlfmt.toml -------------------------------------------------------------------------------- /testing/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /testing/templates/included/fragment.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /askama_derive/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /askama_derive/templates/sub/sub1/d.html: -------------------------------------------------------------------------------- 1 | echo 2 | -------------------------------------------------------------------------------- /askama_escape/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /askama_macros/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /askama_parser/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /examples/actix-web-app/deny.toml: -------------------------------------------------------------------------------- 1 | ../../deny.toml -------------------------------------------------------------------------------- /examples/axum-app/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../../LICENSE-MIT -------------------------------------------------------------------------------- /examples/axum-app/_typos.toml: -------------------------------------------------------------------------------- 1 | ../../_typos.toml -------------------------------------------------------------------------------- /examples/axum-app/clippy.toml: -------------------------------------------------------------------------------- 1 | ../../clippy.toml -------------------------------------------------------------------------------- /examples/axum-app/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../../tomlfmt.toml -------------------------------------------------------------------------------- /examples/poem-app/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../../LICENSE-MIT -------------------------------------------------------------------------------- /examples/poem-app/_typos.toml: -------------------------------------------------------------------------------- 1 | ../../_typos.toml -------------------------------------------------------------------------------- /examples/poem-app/clippy.toml: -------------------------------------------------------------------------------- 1 | ../../clippy.toml -------------------------------------------------------------------------------- /examples/poem-app/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../../tomlfmt.toml -------------------------------------------------------------------------------- /examples/rocket-app/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../../LICENSE-MIT -------------------------------------------------------------------------------- /examples/rocket-app/_typos.toml: -------------------------------------------------------------------------------- 1 | ../../_typos.toml -------------------------------------------------------------------------------- /examples/rocket-app/clippy.toml: -------------------------------------------------------------------------------- 1 | ../../clippy.toml -------------------------------------------------------------------------------- /examples/rocket-app/deny.toml: -------------------------------------------------------------------------------- 1 | ../../deny.toml -------------------------------------------------------------------------------- /examples/salvo-app/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../../LICENSE-MIT -------------------------------------------------------------------------------- /examples/salvo-app/_typos.toml: -------------------------------------------------------------------------------- 1 | ../../_typos.toml -------------------------------------------------------------------------------- /examples/salvo-app/clippy.toml: -------------------------------------------------------------------------------- 1 | ../../clippy.toml -------------------------------------------------------------------------------- /examples/warp-app/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../../LICENSE-MIT -------------------------------------------------------------------------------- /examples/warp-app/_typos.toml: -------------------------------------------------------------------------------- 1 | ../../_typos.toml -------------------------------------------------------------------------------- /examples/warp-app/clippy.toml: -------------------------------------------------------------------------------- 1 | ../../clippy.toml -------------------------------------------------------------------------------- /examples/warp-app/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../../tomlfmt.toml -------------------------------------------------------------------------------- /testing-alloc/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /testing-no-std/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../.rustfmt.toml -------------------------------------------------------------------------------- /testing-no-std/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /testing-renamed/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../.rustfmt.toml -------------------------------------------------------------------------------- /testing-renamed/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /testing/templates/attr.html: -------------------------------------------------------------------------------- 1 | {{ inner.a }} 2 | -------------------------------------------------------------------------------- /testing/templates/foo.html.askama: -------------------------------------------------------------------------------- 1 | foo.html.askama -------------------------------------------------------------------------------- /testing/templates/foo.html.jinja: -------------------------------------------------------------------------------- 1 | foo.html.jinja -------------------------------------------------------------------------------- /testing/templates/use-var.txt: -------------------------------------------------------------------------------- 1 | {{ variable }} 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /askama_derive/src/html.rs: -------------------------------------------------------------------------------- 1 | ../../askama/src/html.rs -------------------------------------------------------------------------------- /askama_escape/src/html.rs: -------------------------------------------------------------------------------- 1 | ../../askama/src/html.rs -------------------------------------------------------------------------------- /examples/actix-web-app/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../../LICENSE-MIT -------------------------------------------------------------------------------- /examples/actix-web-app/_typos.toml: -------------------------------------------------------------------------------- 1 | ../../_typos.toml -------------------------------------------------------------------------------- /examples/actix-web-app/clippy.toml: -------------------------------------------------------------------------------- 1 | ../../clippy.toml -------------------------------------------------------------------------------- /examples/actix-web-app/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../../tomlfmt.toml -------------------------------------------------------------------------------- /examples/axum-app/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../../.rustfmt.toml -------------------------------------------------------------------------------- /examples/axum-app/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../../LICENSE-APACHE -------------------------------------------------------------------------------- /examples/poem-app/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../../.rustfmt.toml -------------------------------------------------------------------------------- /examples/poem-app/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../../LICENSE-APACHE -------------------------------------------------------------------------------- /examples/rocket-app/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../../.rustfmt.toml -------------------------------------------------------------------------------- /examples/rocket-app/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../../tomlfmt.toml -------------------------------------------------------------------------------- /examples/salvo-app/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../../.rustfmt.toml -------------------------------------------------------------------------------- /examples/salvo-app/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../../LICENSE-APACHE -------------------------------------------------------------------------------- /examples/salvo-app/tomlfmt.toml: -------------------------------------------------------------------------------- 1 | ../../tomlfmt.toml -------------------------------------------------------------------------------- /examples/warp-app/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../../.rustfmt.toml -------------------------------------------------------------------------------- /examples/warp-app/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../../LICENSE-APACHE -------------------------------------------------------------------------------- /testing/jinja2-assumptions/.python-version: -------------------------------------------------------------------------------- 1 | 3.13 2 | -------------------------------------------------------------------------------- /testing/templates/filters.html: -------------------------------------------------------------------------------- 1 | {{ strvar|e }} 2 | -------------------------------------------------------------------------------- /testing/templates/generics.html: -------------------------------------------------------------------------------- 1 | {{ t }}{{ u }} 2 | -------------------------------------------------------------------------------- /testing/templates/hello.html: -------------------------------------------------------------------------------- 1 | Hello, {{ name }}! 2 | -------------------------------------------------------------------------------- /testing/templates/included.html: -------------------------------------------------------------------------------- 1 | INCLUDED: {{ s }} 2 | -------------------------------------------------------------------------------- /book/.gitignore: -------------------------------------------------------------------------------- 1 | /book 2 | /.sass-cache 3 | /src/doc 4 | -------------------------------------------------------------------------------- /examples/actix-web-app/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | ../../.rustfmt.toml -------------------------------------------------------------------------------- /examples/actix-web-app/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../../LICENSE-APACHE -------------------------------------------------------------------------------- /examples/rocket-app/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../../LICENSE-APACHE -------------------------------------------------------------------------------- /testing/templates/composition.html: -------------------------------------------------------------------------------- 1 | composed: {{ foo }} 2 | -------------------------------------------------------------------------------- /testing/templates/filters_join.html: -------------------------------------------------------------------------------- 1 | {{ s|join(", ") }} 2 | -------------------------------------------------------------------------------- /testing/templates/format.html: -------------------------------------------------------------------------------- 1 | {{ "{:?}"|format(var) }} 2 | -------------------------------------------------------------------------------- /testing/templates/if.html: -------------------------------------------------------------------------------- 1 | {% if cond %}true{% endif %} 2 | -------------------------------------------------------------------------------- /testing/templates/invalid_syntax.html: -------------------------------------------------------------------------------- 1 | {% let 12 = 0 } 2 | -------------------------------------------------------------------------------- /askama_derive/src/ascii_str.rs: -------------------------------------------------------------------------------- 1 | ../../askama/src/ascii_str.rs -------------------------------------------------------------------------------- /askama_escape/src/ascii_str.rs: -------------------------------------------------------------------------------- 1 | ../../askama/src/ascii_str.rs -------------------------------------------------------------------------------- /askama_parser/src/ascii_str.rs: -------------------------------------------------------------------------------- 1 | ../../askama/src/ascii_str.rs -------------------------------------------------------------------------------- /fuzzing/fuzz/src/ascii_str.rs: -------------------------------------------------------------------------------- 1 | ../../../askama/src/ascii_str.rs -------------------------------------------------------------------------------- /fuzzing/fuzz/src/html/html.rs: -------------------------------------------------------------------------------- 1 | ../../../../askama/src/html.rs -------------------------------------------------------------------------------- /testing/folder-config.toml/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /testing/templates/cycle1.html: -------------------------------------------------------------------------------- 1 | {% extends "cycle1.html" %} 2 | -------------------------------------------------------------------------------- /testing/templates/cycle2.html: -------------------------------------------------------------------------------- 1 | {% extends "cycle1.html" %} 2 | -------------------------------------------------------------------------------- /testing/templates/nested-attr.html: -------------------------------------------------------------------------------- 1 | {{ inner.holder.a }} 2 | -------------------------------------------------------------------------------- /testing/templates/rust-macros.html: -------------------------------------------------------------------------------- 1 | Hello, {{ hello!() }}! 2 | -------------------------------------------------------------------------------- /askama_escape/benches/strings.inc: -------------------------------------------------------------------------------- 1 | ../../askama/benches/strings.inc -------------------------------------------------------------------------------- /testing/templates/let-base.html: -------------------------------------------------------------------------------- 1 | {% block body %}{% endblock %} 2 | -------------------------------------------------------------------------------- /testing/templates/tuple-attr.html: -------------------------------------------------------------------------------- 1 | {{ tuple.0 }}{{ tuple.1 }} 2 | -------------------------------------------------------------------------------- /testing/test_minimize.toml: -------------------------------------------------------------------------------- 1 | [general] 2 | whitespace = "minimize" 3 | -------------------------------------------------------------------------------- /testing/test_trim.toml: -------------------------------------------------------------------------------- 1 | [general] 2 | whitespace = "suppress" 3 | -------------------------------------------------------------------------------- /testing/templates/char-literals/char-literal-1.txt: -------------------------------------------------------------------------------- 1 | {% let s = '\a' %} 2 | -------------------------------------------------------------------------------- /testing/templates/char-literals/char-literal-2.txt: -------------------------------------------------------------------------------- 1 | {% let s = '\x' %} 2 | -------------------------------------------------------------------------------- /testing/templates/char-literals/char-literal-5.txt: -------------------------------------------------------------------------------- 1 | {% let s = '\u' %} 2 | -------------------------------------------------------------------------------- /testing/templates/nested/sub-nested/included.html: -------------------------------------------------------------------------------- 1 | INCLUDED: {{ s }} 2 | -------------------------------------------------------------------------------- /bench-build/templates/hello_world.html: -------------------------------------------------------------------------------- 1 |

{{greeting}}, {{user}}!

2 | -------------------------------------------------------------------------------- /testing/templates/char-literals/char-literal-3.txt: -------------------------------------------------------------------------------- 1 | {% let s = '\x1' %} 2 | -------------------------------------------------------------------------------- /testing/templates/char-literals/char-literal-4.txt: -------------------------------------------------------------------------------- 1 | {% let s = '\x80' %} 2 | -------------------------------------------------------------------------------- /testing/templates/char-literals/char-literal-6.txt: -------------------------------------------------------------------------------- 1 | {% let s = '\u{}' %} 2 | -------------------------------------------------------------------------------- /testing/templates/else.html: -------------------------------------------------------------------------------- 1 | {% if cond %}true{% else %}false{% endif %} 2 | -------------------------------------------------------------------------------- /testing/templates/no-block-with-include.txt: -------------------------------------------------------------------------------- 1 | {% include "no-block.txt" %} 2 | -------------------------------------------------------------------------------- /testing/templates/rust-macros-full-path.html: -------------------------------------------------------------------------------- 1 | Hello, {{ foo::hello2!() }}! 2 | -------------------------------------------------------------------------------- /testing/templates/char-literals/char-literal-7.txt: -------------------------------------------------------------------------------- 1 | {% let s = '\u{110000}' %} 2 | -------------------------------------------------------------------------------- /testing/templates/transclude-there.html: -------------------------------------------------------------------------------- 1 | {% include "transclude-missing.html" %} 2 | -------------------------------------------------------------------------------- /testing/templates/a_file_that_is_actually_a_folder.html/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /testing/templates/include_invalid_syntax.html: -------------------------------------------------------------------------------- 1 | {% extends "invalid_syntax.html" %} 2 | -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/.gitattributes: -------------------------------------------------------------------------------- 1 | * -text -diff binary 2 | .gitattributes text diff 3 | -------------------------------------------------------------------------------- /testing/templates/let.html: -------------------------------------------------------------------------------- 1 | {% let v = s %}{{ v }} 2 | {% let (v1,v2) = t %}{{ v1 }}{{ v2 }} -------------------------------------------------------------------------------- /testing/templates/literals.html: -------------------------------------------------------------------------------- 1 | {{ 'a' }} 2 | {{ "a" }} 3 | {{ true }} 4 | {{ false }} 5 | -------------------------------------------------------------------------------- /testing/templates/nested/included.html: -------------------------------------------------------------------------------- 1 | NESTED: {% include "sub-nested/included.html" %} 2 | -------------------------------------------------------------------------------- /testing/templates/raw-simple.html: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | {{ name }} 3 | {% endraw %} 4 | -------------------------------------------------------------------------------- /testing/delim-too-short.toml: -------------------------------------------------------------------------------- 1 | [[syntax]] 2 | name = "delim-too-short" 3 | block_start = "<" 4 | -------------------------------------------------------------------------------- /testing/issue-128.toml: -------------------------------------------------------------------------------- 1 | [[syntax]] 2 | name = "mwe" 3 | expr_start = "<<" 4 | expr_end = ">>" 5 | -------------------------------------------------------------------------------- /testing/templates/if-let-shadowing.html: -------------------------------------------------------------------------------- 1 | {% if let Some(text) = text %}{{ text }}{% endif %} 2 | -------------------------------------------------------------------------------- /testing/templates/if-let.html: -------------------------------------------------------------------------------- 1 | {% if let Some(some_text) = text %}{{ some_text }}{% endif %} 2 | -------------------------------------------------------------------------------- /testing/templates/no-block-with-include-times-2.txt: -------------------------------------------------------------------------------- 1 | {% include "no-block-with-include.txt" %} 2 | -------------------------------------------------------------------------------- /testing/templates/size-parent.txt: -------------------------------------------------------------------------------- 1 | {% block main %}{% if true %}12345{% endif %}{% endblock %} 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.html text eol=lf 2 | *.txt text eol=lf 3 | fuzzing/fuzz/corpus linguist-vendored 4 | -------------------------------------------------------------------------------- /testing/issue-128-2.toml: -------------------------------------------------------------------------------- 1 | [[syntax]] 2 | name = "mwe" 3 | expr_start = "<<<" 4 | expr_end = ">>>" 5 | -------------------------------------------------------------------------------- /testing/templates/base-decl.txt: -------------------------------------------------------------------------------- 1 | {%- let variable = 42 -%} 2 | {%- block extended %}{% endblock -%} 3 | -------------------------------------------------------------------------------- /testing/templates/no-block-with-base-template.txt: -------------------------------------------------------------------------------- 1 | {% extends "no-block-with-include-times-2.txt" %} 2 | -------------------------------------------------------------------------------- /testing/operator-plus-config.toml: -------------------------------------------------------------------------------- 1 | [[syntax]] 2 | name = "plus" 3 | expr_start = "<+" 4 | expr_end = "+>" 5 | -------------------------------------------------------------------------------- /testing/templates/else-if.html: -------------------------------------------------------------------------------- 1 | {% if cond %}true{% else if check %}checked{% else %}false{% endif %} 2 | -------------------------------------------------------------------------------- /testing/templates/include.html: -------------------------------------------------------------------------------- 1 | {% for s in strs %} 2 | {% include "included.html" %} 3 | {%- endfor %} 4 | -------------------------------------------------------------------------------- /askama_derive/templates/include1.html: -------------------------------------------------------------------------------- 1 | {%- include "include2.html" -%} 2 | {%- include "include2.html" -%} 3 | -------------------------------------------------------------------------------- /askama_derive/templates/include2.html: -------------------------------------------------------------------------------- 1 | {%- include "include3.html" -%} 2 | {%- include "include3.html" -%} 3 | -------------------------------------------------------------------------------- /testing-alloc/templates/hello-world.html: -------------------------------------------------------------------------------- 1 | Hello {%- if let Some(user) = user? -%} , {{ user }} {%- endif -%}! 2 | -------------------------------------------------------------------------------- /testing-no-std/templates/hello-world.html: -------------------------------------------------------------------------------- 1 | Hello {%- if let Some(user) = user? -%} , {{ user }} {%- endif -%}! 2 | -------------------------------------------------------------------------------- /testing/delim-clash.toml: -------------------------------------------------------------------------------- 1 | [[syntax]] 2 | name = "delim-clash" 3 | block_start = "<<<" 4 | expr_start = "<<<<" 5 | -------------------------------------------------------------------------------- /testing/operator-paren-config.toml: -------------------------------------------------------------------------------- 1 | [[syntax]] 2 | name = "paren" 3 | expr_start = "<)" 4 | expr_end = "(>" 5 | -------------------------------------------------------------------------------- /testing/templates/raw-ws.html: -------------------------------------------------------------------------------- 1 | <{% raw -%} {{hello}} {%- endraw %}> 2 | < {%- raw %}{{bye}}{% endraw -%} > 3 | -------------------------------------------------------------------------------- /testing-renamed/templates/hello-world.html: -------------------------------------------------------------------------------- 1 | Hello {%- if let Some(user) = user? -%} , {{ user }} {%- endif -%}! 2 | -------------------------------------------------------------------------------- /testing/templates/extend_and_import.html: -------------------------------------------------------------------------------- 1 | {% import "macro.html" as m1 %} 2 | 3 | {% block header %}{% endblock %} 4 | -------------------------------------------------------------------------------- /testing/templates/include-base.html: -------------------------------------------------------------------------------- 1 | {% include "included/fragment.html" %} 2 | {% block content %}{% endblock %} 3 | -------------------------------------------------------------------------------- /testing/templates/match-no-ws.html: -------------------------------------------------------------------------------- 1 | {% match foo %}{% when Some with (bar) %}{{ bar }}{% when None %}{% endmatch %} 2 | -------------------------------------------------------------------------------- /testing/templates/include-nested.html: -------------------------------------------------------------------------------- 1 | {% for s in strs %} 2 | {% include "nested/included.html" %} 3 | {%- endfor %} 4 | -------------------------------------------------------------------------------- /testing/templates/size-child-super.txt: -------------------------------------------------------------------------------- 1 | {% extends "size-parent.txt" %} 2 | {% block main %}{{ super() }}{% endblock %} 3 | -------------------------------------------------------------------------------- /testing/templates/import.html: -------------------------------------------------------------------------------- 1 | 2 | {%- import "macro.html" as scope -%} 3 | 4 | {% call scope::thrice(s) %}{% endcall %} 5 | -------------------------------------------------------------------------------- /testing/templates/nested-base.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 | loopy 3 | {% block foo %}Foo{% endblock %} 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /testing/templates/if-let-struct.html: -------------------------------------------------------------------------------- 1 | {% if let Digits { one, two, three } = digits %}{{ one }} {{ two }} {{ three }}{% endif %} 2 | -------------------------------------------------------------------------------- /testing/templates/include-extends-included.html: -------------------------------------------------------------------------------- 1 | {% extends "include-extends-base.html" %} 2 | {% block header %}foo{% endblock %} 3 | -------------------------------------------------------------------------------- /testing/templates/leaf-templates/includer.html: -------------------------------------------------------------------------------- 1 | {% extends "../include-base.html" %} 2 | 3 | {% block content %}{% endblock %} 4 | -------------------------------------------------------------------------------- /testing/templates/option.html: -------------------------------------------------------------------------------- 1 | {% if var.is_some() -%} 2 | some: {{ var.unwrap() }} 3 | {%- else -%} 4 | none 5 | {%- endif %} 6 | -------------------------------------------------------------------------------- /testing/templates/size-child.txt: -------------------------------------------------------------------------------- 1 | {% extends "size-parent.txt" %} 2 | {% block main %}{% if true %}123{% endif %}{% endblock %} 3 | -------------------------------------------------------------------------------- /testing/templates/base.html: -------------------------------------------------------------------------------- 1 | {{ title }} 2 | {% block content %}{% endblock %} 3 | {% block foo %}Foo{% endblock %} 4 | Copyright 2017 5 | -------------------------------------------------------------------------------- /testing/templates/child.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %}({{ title }}) Content goes here{% endblock content %} 3 | -------------------------------------------------------------------------------- /testing/templates/deep-import-parent.html: -------------------------------------------------------------------------------- 1 | {%- import "deep-import-child.html" as libj -%} 2 | {% call libj::parent() %}{% endcall %} 3 | -------------------------------------------------------------------------------- /testing/templates/deep-nested-macro.html: -------------------------------------------------------------------------------- 1 | {%- import "nested-macro.html" as libi -%} 2 | {%- call libi::parent() -%}{%- endcall -%} 3 | -------------------------------------------------------------------------------- /testing/templates/include-extends.html: -------------------------------------------------------------------------------- 1 |
2 |

Welcome

3 | {% include "include-extends-included.html" %} 4 |
5 | -------------------------------------------------------------------------------- /testing/templates/raw-complex.html: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | {% block name %} 3 | {{ name }} 4 | {% endblock %} 5 | {% endraw %} 6 | -------------------------------------------------------------------------------- /testing/templates/block_in_include_partial.html: -------------------------------------------------------------------------------- 1 | {%- block block_in_partial -%} 2 | block_in_partial: from partial! 3 | {% endblock -%} 4 | -------------------------------------------------------------------------------- /testing/templates/let-child.html: -------------------------------------------------------------------------------- 1 | {% extends "let-base.html" %} 2 | {% block body -%} 3 | {% let x = 1 %} 4 | {{- x -}} 5 | {%- endblock %} 6 | -------------------------------------------------------------------------------- /testing/tests/ui/no_template_attribute.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | struct NoTemplate; 5 | 6 | fn main() { 7 | } 8 | -------------------------------------------------------------------------------- /testing/templates/include-macro.html: -------------------------------------------------------------------------------- 1 | {% macro m(name) -%} 2 | Hello, {{ name }}! 3 | {%- endmacro -%} 4 | {% include "included-macro.html" %} 5 | -------------------------------------------------------------------------------- /testing/templates/macro-self-arg.html: -------------------------------------------------------------------------------- 1 | {%- macro my_s(slf) -%} 2 | {{ slf.s }} 3 | {%- endmacro -%} 4 | 5 | {%- call my_s(self) -%}{%- endcall -%} 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "fuzzing/fuzz/corpus"] 2 | path = fuzzing/fuzz/corpus 3 | url = https://github.com/askama-rs/fuzzing-corpus.git 4 | branch = main 5 | -------------------------------------------------------------------------------- /testing/templates/nested-child.html: -------------------------------------------------------------------------------- 1 | {% extends "nested-base.html" %} 2 | {% block content %} 3 | {% block foo %}durpy{% endblock %} 4 | {% endblock content %} 5 | -------------------------------------------------------------------------------- /testing/tests/ui/cycle.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(path = "cycle2.html")] 5 | struct Cycle; 6 | 7 | fn main() { 8 | } 9 | -------------------------------------------------------------------------------- /testing/templates/match-literal-num.html: -------------------------------------------------------------------------------- 1 | {% match item %} 2 | {% when 42 %} 3 | Found answer to everything 4 | {% else %} 5 | Else found {{item}} 6 | {% endmatch %} 7 | -------------------------------------------------------------------------------- /testing/tests/ui/cycle2.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(path = "cycle1.html")] 5 | struct Cycle; 6 | 7 | fn main() { 8 | } 9 | -------------------------------------------------------------------------------- /testing/templates/big-table.html: -------------------------------------------------------------------------------- 1 | 2 | {% for row in table %} 3 | {% for col in row %}{% endfor %} 4 | {% endfor %} 5 |
{{ col|escape }}
6 | -------------------------------------------------------------------------------- /testing/templates/let-decl.html: -------------------------------------------------------------------------------- 1 | {% let val -%} 2 | {% if cond -%} 3 | {% let val = "foo" -%} 4 | {% else -%} 5 | {% let val = s -%} 6 | {% endif -%} 7 | {{ val }} 8 | -------------------------------------------------------------------------------- /testing/templates/ranges.txt: -------------------------------------------------------------------------------- 1 | {{ foo[..]|join("") }} 2 | {{ foo[0 + 1..]|join("") }} 3 | {% let bar = 1 %} 4 | {{ foo[..bar]|join("") }} 5 | {{ foo[..=bar]|join("") }} 6 | -------------------------------------------------------------------------------- /fuzzing/fuzz/fuzz_targets/all.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | libfuzzer_sys::fuzz_target!(|data: &[u8]| { 4 | let _ = ::fuzz(data); 5 | }); 6 | -------------------------------------------------------------------------------- /testing/templates/render_in_place.html: -------------------------------------------------------------------------------- 1 | Section 1: {{ s1 }} 2 | Section 2: {{ s2|safe }} 3 | Section 3 for: 4 | {% for s in s3.as_slice() -%} 5 | * {{ s }} 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /fuzzing/fuzz/fuzz_targets/html.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | libfuzzer_sys::fuzz_target!(|data: &[u8]| { 4 | let _ = ::fuzz(data); 5 | }); 6 | -------------------------------------------------------------------------------- /testing/templates/deep-import-child.html: -------------------------------------------------------------------------------- 1 | {%- import "nested-macro.html" as libi -%} 2 | {%- macro parent() -%} 3 | {% call libi::parent() %}{% endcall %} 4 | {%- endmacro -%} 5 | -------------------------------------------------------------------------------- /testing/templates/let-destruct-tuple.html: -------------------------------------------------------------------------------- 1 | {% let (a, ((b, c), (d))) = abcd %}{{a}}{{b}}{{c}}{{d}} 2 | {% let (a, (_, d)) = abcd %}{{a}}{{d}} 3 | {% let (((a))) = abcd.0 %}{{a}} 4 | -------------------------------------------------------------------------------- /testing/templates/nested-for.html: -------------------------------------------------------------------------------- 1 | {% for seq in seqs -%} 2 | {{ loop.index }} 3 | {% for v in seq -%} 4 | {{ loop.index0 }}{{ v }} 5 | {%- endfor -%} 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /testing/templates/simple.html: -------------------------------------------------------------------------------- 1 | {# our very first test! #} 2 | hello world, {{ strvar }} 3 | with number: {{ num }} 4 | Iñtërnâtiônàlizætiøn is important 5 | in vars too: {{ i18n }} 6 | -------------------------------------------------------------------------------- /fuzzing/fuzz/fuzz_targets/derive.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | libfuzzer_sys::fuzz_target!(|data: &[u8]| { 4 | let _ = ::fuzz(data); 5 | }); 6 | -------------------------------------------------------------------------------- /fuzzing/fuzz/fuzz_targets/filters.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | libfuzzer_sys::fuzz_target!(|data: &[u8]| { 4 | let _ = ::fuzz(data); 5 | }); 6 | -------------------------------------------------------------------------------- /fuzzing/fuzz/fuzz_targets/parser.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | libfuzzer_sys::fuzz_target!(|data: &[u8]| { 4 | let _ = ::fuzz(data); 5 | }); 6 | -------------------------------------------------------------------------------- /testing/templates/block_in_include_base.html: -------------------------------------------------------------------------------- 1 | {%- block block_in_base -%} 2 | block_in_base: from base! 3 | {% endblock -%} 4 | 5 | {%- include "block_in_include_partial.html" -%} 6 | -------------------------------------------------------------------------------- /testing/tests/ui/incorrect_path.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(path = "thisdoesnotexist.html")] 5 | struct MyTemplate; 6 | 7 | fn main() { 8 | } 9 | -------------------------------------------------------------------------------- /testing/templates/included-macro.html: -------------------------------------------------------------------------------- 1 | {% macro m2(name) -%} 2 | Howdy, {{ name }}! 3 | {%- endmacro -%} 4 | 5 | {% call m(name) %}{% endcall %} 6 | {% call m2(name2) %}{% endcall %} 7 | -------------------------------------------------------------------------------- /testing/templates/literals-escape.html: -------------------------------------------------------------------------------- 1 | {{ '\x41' }}{{ '\n' }}{{ '\r' }}{{ '\t' }}{{ '\\' }}{{ '\0' }}{{ '\u{2665}' }}{{ '\'' }}{{ '\"' }}{{ '"' }} 2 | {{ "\x41\n\r\t\\\0\u{2665}\'\"'" }} 3 | -------------------------------------------------------------------------------- /testing/templates/macro-import-callexpr.html: -------------------------------------------------------------------------------- 1 | {% import "nested-macro-callexpr.html" as otherscope %} 2 | 3 | {% macro intermediate() %} 4 | {{- otherscope::parent() -}} 5 | {% endmacro %} -------------------------------------------------------------------------------- /testing/templates/macro-recursion-1.html: -------------------------------------------------------------------------------- 1 | {% import "macro-recursion-2.html" as next %} 2 | 3 | {% macro some_macro %} 4 | {% call next::some_macro %}{% endcall %} 5 | {% endmacro %} 6 | -------------------------------------------------------------------------------- /testing/templates/macro-recursion-2.html: -------------------------------------------------------------------------------- 1 | {% import "macro-recursion-3.html" as next %} 2 | 3 | {% macro some_macro %} 4 | {% call next::some_macro %}{% endcall %} 5 | {% endmacro %} 6 | -------------------------------------------------------------------------------- /testing/templates/macro-recursion-3.html: -------------------------------------------------------------------------------- 1 | {% import "macro-recursion-1.html" as next %} 2 | 3 | {% macro some_macro %} 4 | {% call next::some_macro %}{% endcall %} 5 | {% endmacro %} 6 | -------------------------------------------------------------------------------- /testing/templates/simple-no-escape.txt: -------------------------------------------------------------------------------- 1 | {# our very first test! #} 2 | hello world, {{ strvar }} 3 | with number: {{ num }} 4 | Iñtërnâtiônàlizætiøn is important 5 | in vars too: {{ i18n }} 6 | -------------------------------------------------------------------------------- /testing/tests/ui/union.stderr: -------------------------------------------------------------------------------- 1 | error: askama templates are not supported for `union` types, only `struct` and `enum` 2 | --> tests/ui/union.rs:5:1 3 | | 4 | 5 | union Tmpl { 5 | | ^^^^^ 6 | -------------------------------------------------------------------------------- /testing/templates/match-literal-char.html: -------------------------------------------------------------------------------- 1 | {% match item %} 2 | {% when 'a' %} 3 | Found literal a 4 | {% when 'b' %} 5 | Found literal b 6 | {% else %} 7 | Else found {{item}} 8 | {% endmatch %} 9 | -------------------------------------------------------------------------------- /testing/templates/precedence.html: -------------------------------------------------------------------------------- 1 | {{ 3 * 4 / 2 -}} 2 | {{ 26 / 2 % 7 -}} 3 | {{ 3 % 2 * 6 -}} 4 | {{ 1 * 2 + 4 -}} 5 | {{ 11 - 15 / 3 -}} 6 | {{ 4 + 5 % 3 -}} 7 | {{ 4 bitor 2 + 5 bitand 2 -}} 8 | -------------------------------------------------------------------------------- /testing/tests/ui/no_template_attribute.stderr: -------------------------------------------------------------------------------- 1 | error: no attribute `template` found 2 | --> tests/ui/no_template_attribute.rs:4:8 3 | | 4 | 4 | struct NoTemplate; 5 | | ^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /testing/tests/ui/ref_deref.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "{% let *x = 2 %}", ext = "html")] 5 | struct WrongRefDeref; 6 | 7 | fn main() { 8 | } 9 | -------------------------------------------------------------------------------- /askama_derive/src/generator/helpers/mod.rs: -------------------------------------------------------------------------------- 1 | mod macro_invocation; 2 | mod paths; 3 | 4 | pub(crate) use macro_invocation::MacroInvocation; 5 | pub(crate) use paths::{clean as clean_path, diff_paths}; 6 | -------------------------------------------------------------------------------- /testing/templates/if-let-else.html: -------------------------------------------------------------------------------- 1 | {%- if !cond -%} 2 | !cond 3 | {%- else if let Ok(ok) = value -%} 4 | {{ ok }} 5 | {%- else if let Err(err) = value -%} 6 | {{ err }} 7 | {%- endif -%} 8 | -------------------------------------------------------------------------------- /testing/templates/match-literal.html: -------------------------------------------------------------------------------- 1 | {% match item %} 2 | {% when "foo" %} 3 | Found literal foo 4 | {% when "bar" %} 5 | Found literal bar 6 | {% else %} 7 | Else found {{item}} 8 | {% endmatch %} 9 | -------------------------------------------------------------------------------- /testing/templates/include-extends-base.html: -------------------------------------------------------------------------------- 1 |
2 |

Below me is the header

3 | {% block header %}{% endblock %} 4 |

Above me is the header

5 |
6 | Hello, {{ name }}! 7 | -------------------------------------------------------------------------------- /testing/tests/ui/empty-match.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "{% match true %}{% endmatch %}", ext = "html")] 5 | struct EmptyMatch; 6 | 7 | fn main() {} 8 | -------------------------------------------------------------------------------- /testing/templates/match-opt.html: -------------------------------------------------------------------------------- 1 | {% match item %} 2 | {% when Some with ("foo") %} 3 | Found literal foo 4 | {% when Some with (val) %} 5 | Found {{val}} 6 | {% when None %} 7 | Not Found 8 | {% endmatch %} 9 | -------------------------------------------------------------------------------- /testing/tests/ui/macro-caller.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "{%- macro caller() -%}{%- endmacro -%}", ext = "html")] 5 | struct MacroSuper; 6 | 7 | fn main() { 8 | } 9 | -------------------------------------------------------------------------------- /testing/tests/ui/macro-super.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "{%- macro super() -%}{%- endmacro -%}", ext = "html")] 5 | struct MacroSuper; 6 | 7 | fn main() { 8 | } 9 | -------------------------------------------------------------------------------- /testing/tests/ui/references.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "{{J::<&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&e>()}}", ext = "html")] 5 | struct X; 6 | 7 | fn main() {} 8 | -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-4654117948817408: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-4654117948817408 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-4793932351602688: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-4793932351602688 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-4955521990066176: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-4955521990066176 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5037184261619712: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5037184261619712 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5064777150038016: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5064777150038016 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5107711304073216: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5107711304073216 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5144827852554240: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5144827852554240 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5353647120908288: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5353647120908288 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5387873899839488: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5387873899839488 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5611392537526272: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5611392537526272 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5780292277436416: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-5780292277436416 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6051930453639168: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6051930453639168 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6236623325167616: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6236623325167616 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6380739026550784: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6380739026550784 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6503980895371264: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6503980895371264 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6542584430526464: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6542584430526464 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6573215117017088: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6573215117017088 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6617490908315648: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6617490908315648 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6639137261420544: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6639137261420544 -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6696196543676416: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/derive/clusterfuzz-testcase-minimized-derive-6696196543676416 -------------------------------------------------------------------------------- /testing/templates/fragment-base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% block body %} 5 |

Parent body content

6 | {% endblock %} 7 | {% block other_body %}{% endblock %} 8 | 9 | 10 | -------------------------------------------------------------------------------- /testing/templates/match-opt-bool.html: -------------------------------------------------------------------------------- 1 | {% match item %} 2 | {% when Some with (true) %} 3 | Found Some(true) 4 | {% when Some with (false) %} 5 | Found Some(false) 6 | {% when None %} 7 | Not Found 8 | {% endmatch %} 9 | -------------------------------------------------------------------------------- /testing/templates/precedence-for.html: -------------------------------------------------------------------------------- 1 | {% for s in strings %} 2 | {{- loop.index0 }}. {{ s }}{{ 2 * loop.index }}{% if !loop.first %}{% else %} (first){% endif %}{% if loop.last %} (last){% endif %} 3 | {% endfor %} 4 | -------------------------------------------------------------------------------- /bench-build/templates/greeting.html: -------------------------------------------------------------------------------- 1 | {%- block hello -%} 2 | Hello 3 | {%- endblock -%} 4 | 5 | {%- block hey -%} 6 | Hey 7 | {%- endblock -%} 8 | 9 | {%- block hi -%} 10 | Hi 11 | {%- endblock -%} 12 | -------------------------------------------------------------------------------- /fuzzing/fuzz/artifacts/filters/minimized-from-b44b4bd1da1759dee0924a8586a6001e80da76fa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askama-rs/askama/HEAD/fuzzing/fuzz/artifacts/filters/minimized-from-b44b4bd1da1759dee0924a8586a6001e80da76fa -------------------------------------------------------------------------------- /testing/templates/fragment-mid-super.html: -------------------------------------------------------------------------------- 1 | {% extends "fragment-base.html" %} 2 | 3 | {% block body %} 4 | [{{ super() }}] 5 | {% endblock %} 6 | 7 | {% block other_body %} 8 | ({{ super() }}) 9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /testing/tests/ui/duplicated_template_attribute.stderr: -------------------------------------------------------------------------------- 1 | error: must specify `source`, `path` or `is_doc` exactly once 2 | --> tests/ui/duplicated_template_attribute.rs:9:5 3 | | 4 | 9 | source = "🙃", 5 | | ^^^^^^ 6 | -------------------------------------------------------------------------------- /testing/tests/ui/filter-recursion.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(path = "filter-recursion.html")] 5 | struct Filtered { 6 | s: &'static str, 7 | } 8 | 9 | fn main() {} 10 | -------------------------------------------------------------------------------- /testing/tests/ui/lit_on_assignment_lhs.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | source = "{%let 7=x%}", 6 | ext = "txt" 7 | )] 8 | struct MyTemplate; 9 | 10 | fn main() { 11 | } 12 | -------------------------------------------------------------------------------- /testing/tests/ui/union.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "a={{ a }} b={{ b }}", ext = "html")] 5 | union Tmpl { 6 | a: i32, 7 | b: u32, 8 | } 9 | 10 | fn main() {} 11 | -------------------------------------------------------------------------------- /testing/jinja2-assumptions/.gitignore: -------------------------------------------------------------------------------- 1 | # Python-generated files 2 | __pycache__/ 3 | *.py[oc] 4 | build/ 5 | dist/ 6 | wheels/ 7 | *.egg-info 8 | 9 | # Virtual environments 10 | .venv 11 | 12 | .pytest_cache 13 | uv.lock 14 | -------------------------------------------------------------------------------- /testing/tests/ui/fuzzing.stderr: -------------------------------------------------------------------------------- 1 | error: failed to parse template source 2 | --> :1:4 3 | "{Ւ{" 4 | --> tests/ui/fuzzing.rs:7:14 5 | | 6 | 7 | source = r#"{{..{Ւ{"#, 7 | | ^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/tests/ui/name_mismatch_endblock.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "{% block foo %}{% endblock not_foo %}", ext = "html")] 5 | struct NameMismatchEndBlock; 6 | 7 | fn main() { 8 | } 9 | -------------------------------------------------------------------------------- /askama_parser/benches/librustdoc/item_info.html: -------------------------------------------------------------------------------- 1 | {% if !items.is_empty() %} 2 | 3 | {% for item in items %} 4 | {{item|safe}} {# #} 5 | {% endfor %} 6 | 7 | {% endif %} 8 | -------------------------------------------------------------------------------- /testing/templates/fragment-simple.html: -------------------------------------------------------------------------------- 1 | {% extends "fragment-base.html" %} 2 | 3 | {% block body %} 4 |

Hello {{ name }}!

5 | {% endblock %} 6 | 7 | {% block other_body %} 8 |

Don't render me.

9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /testing/tests/ui/extend.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | source = r##"bla 6 | {% extends "base.html" %} 7 | "##, 8 | ext = "txt", 9 | )] 10 | pub struct X; 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /testing/templates/blocks.txt: -------------------------------------------------------------------------------- 1 | {% block index %} 2 | Section: {{ s1 }} 3 | {% endblock %} 4 | 5 | {% block section -%} 6 | [ 7 | {%- for value in values -%} 8 | {{ value }} 9 | {%- endfor -%} 10 | ] 11 | {%- endblock %} 12 | -------------------------------------------------------------------------------- /testing/templates/match-enum-or.html: -------------------------------------------------------------------------------- 1 | The card is 2 | {%- match suit %} 3 | {%- when Suit::Clubs or Suit::Spades -%} 4 | {{ " black" }} 5 | {%- when Suit::Diamonds or Suit::Hearts -%} 6 | {{ " red" }} 7 | {%- endmatch %} 8 | 9 | -------------------------------------------------------------------------------- /testing/tests/ui/fuzzed_recursion_depth_mul_deref.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(path = "fuzzed-recursion-mul-deref.txt")] 5 | struct Filtered { 6 | s: &'static str, 7 | } 8 | 9 | fn main() {} 10 | -------------------------------------------------------------------------------- /testing/tests/ui/include-a-folder.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(ext = "txt", source = r#"{% include "a_file_that_is_actually_a_folder.html" %}"#)] 5 | struct YouCannotIncludeFolders; 6 | 7 | fn main() { 8 | } 9 | -------------------------------------------------------------------------------- /testing/tests/ui/name_mismatch_endmacro.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "{% macro foo(arg) %} {{arg}} {% endmacro not_foo %}", ext = "html")] 5 | struct NameMismatchEndMacro; 6 | 7 | fn main() { 8 | } 9 | -------------------------------------------------------------------------------- /testing/tests/ui/json-too-many-args.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "serde_json")] 2 | 3 | use askama::Template; 4 | 5 | #[derive(Template)] 6 | #[template(ext = "txt", source = "{{ 1|json(2, 3) }}")] 7 | struct OneTwoThree; 8 | 9 | fn main() { 10 | } 11 | -------------------------------------------------------------------------------- /testing/tests/ui/multiple_extends.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = r#" 5 | {% extends "let.html" %} 6 | {% extends "foo.html" %} 7 | "#, ext = "txt")] 8 | struct MyTemplate4; 9 | 10 | fn main() {} 11 | -------------------------------------------------------------------------------- /testing/tests/ui/break_outside_of_loop.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | source = "Have a {%break%}, have a parsing error!", 6 | ext = "txt" 7 | )] 8 | struct MyTemplate; 9 | 10 | fn main() { 11 | } 12 | -------------------------------------------------------------------------------- /testing/templates/nested-macro-callexpr.html: -------------------------------------------------------------------------------- 1 | {%- macro child0() -%} 2 | foo 3 | {%- endmacro -%} 4 | 5 | {%- macro child1() -%} 6 | {{ child0() }} 7 | {%- endmacro -%} 8 | 9 | {%- macro parent() -%} 10 | {{ child1() }} 11 | {%- endmacro -%} 12 | -------------------------------------------------------------------------------- /testing/tests/ui/number.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = r#"{{ e!(0o08) }}"#, ext = "html")] 5 | struct A; 6 | 7 | #[derive(Template)] 8 | #[template(source = r#"{{ e!(0b3) }}"#, ext = "html")] 9 | struct B; 10 | -------------------------------------------------------------------------------- /testing/tests/ui/pluralize.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | ext = "html", 6 | source = "{{ input|pluralize }}", 7 | )] 8 | struct Pluralize { 9 | input: &'static str, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /testing/templates/deep-kid.html: -------------------------------------------------------------------------------- 1 | {% extends "deep-mid.html" %} 2 | {% import "macro.html" as libk %} 3 | 4 | {% block head %} 5 | 6 | {% endblock %} 7 | 8 | {% block content %} 9 | {% call libk::thrice(item) %}{% endcall %} 10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /testing/templates/for.html: -------------------------------------------------------------------------------- 1 | {% for s in strings %} 2 | {{- loop.index0 }}. {{ s }}{% if loop.first %} (first){% endif %} 3 | {% endfor %} 4 | {% for (s1, s2, ) in tuple_strings %} 5 | {{- loop.index0 }}. {{ s1 }},{{ s2 }}{% if loop.first %} (first){% endif %} 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /testing/templates/fragment-super.html: -------------------------------------------------------------------------------- 1 | {% extends "fragment-base.html" %} 2 | 3 | {% block body %} 4 |

Hello {{ name }}!

5 | {{ super() }} 6 | {% endblock %} 7 | 8 | {% block other_body %} 9 |

Don't render me.

10 | {{ super() }} 11 | {% endblock %} 12 | 13 | -------------------------------------------------------------------------------- /testing/tests/ui/fuzzing.rs: -------------------------------------------------------------------------------- 1 | // Test file specifically for parser bugs uncovered with fuzzing. 2 | 3 | use askama::Template; 4 | 5 | #[derive(Template)] 6 | #[template( 7 | source = r#"{{..{Ւ{"#, 8 | ext = "html", 9 | )] 10 | struct T; 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "cargo" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /testing/tests/custom_ui/duplicated_block_calls.stderr: -------------------------------------------------------------------------------- 1 | ⚠️ X.txt:4:3: block `content` was already called at `X.txt:3:3` so the previous one will be ignored 2 | ⚠️ X2.txt:3:3: block `content` was already called at `testing/templates/child.html:2:3` so the previous one will be ignored 3 | -------------------------------------------------------------------------------- /testing/tests/ui/filter_block_ws.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "{% filter lower|indent(2) - %} 5 | HELLO 6 | {{v}} 7 | {%- endfilter %}", ext = "html")] 8 | struct A; 9 | 10 | fn main() { 11 | A.render().unwrap(); 12 | } 13 | -------------------------------------------------------------------------------- /testing/tests/ui/ref_deref.stderr: -------------------------------------------------------------------------------- 1 | error: failed to parse template source 2 | --> :1:7 3 | "*x = 2 %}" 4 | --> tests/ui/ref_deref.rs:4:21 5 | | 6 | 4 | #[template(source = "{% let *x = 2 %}", ext = "html")] 7 | | ^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /deny.toml: -------------------------------------------------------------------------------- 1 | [licenses] 2 | version = 2 3 | allow = ["Apache-2.0", "MIT", "MIT-0", "Unicode-3.0"] 4 | private = { ignore = true } 5 | 6 | [[licenses.clarify]] 7 | name = "ring" 8 | expression = "ISC AND MIT AND OpenSSL" 9 | license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }] 10 | -------------------------------------------------------------------------------- /testing/tests/ui/cycle2.stderr: -------------------------------------------------------------------------------- 1 | error: cyclic dependency in graph [ 2 | "\"$DIR/templates/cycle1.html/" --> \"$DIR/templates/cycle1.html/"", 3 | ] 4 | --> tests/ui/cycle2.rs:4:19 5 | | 6 | 4 | #[template(path = "cycle1.html")] 7 | | ^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/tests/ui/typo_in_keyword.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | source = "{%for i in 1..=10%}{{i}}{%endfo%}\n1234567890123456789012345678901234567890", 6 | ext = "txt" 7 | )] 8 | struct MyTemplate; 9 | 10 | fn main() { 11 | } 12 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "askama", 4 | "askama_derive", 5 | "askama_escape", 6 | "askama_macros", 7 | "askama_parser", 8 | "testing", 9 | "testing-alloc", 10 | "testing-no-std", 11 | "testing-renamed", 12 | ] 13 | resolver = "2" 14 | -------------------------------------------------------------------------------- /testing/templates/fragment-nested-super.html: -------------------------------------------------------------------------------- 1 | {% extends "fragment-mid-super.html" %} 2 | 3 | {% block body %} 4 |

Hello {{ name }}!

5 | {{ super() }} 6 | {% endblock %} 7 | 8 | {% block other_body %} 9 |

Don't render me.

10 | {{ super() }} 11 | {% endblock %} 12 | 13 | -------------------------------------------------------------------------------- /testing/templates/fragment-unused-expr.html: -------------------------------------------------------------------------------- 1 | {% extends "fragment-base.html" %} 2 | 3 | {{ not_required }} 4 | 5 | {% block body %} 6 |

{{ required }}

7 | {% endblock %} 8 | 9 | {% block other_body %} 10 | {{ not_required_2 }} 11 |

Don't render me.

12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /testing/templates/nested-macro.html: -------------------------------------------------------------------------------- 1 | {%- macro child0() -%} 2 | foo 3 | {%- endmacro -%} 4 | 5 | {%- macro child1() -%} 6 | {% call child0() %}{% endcall %} 7 | {%- endmacro -%} 8 | 9 | {%- macro parent() -%} 10 | {% call child1() %}{% endcall %} 11 | {%- endmacro -%} 12 | -------------------------------------------------------------------------------- /testing/tests/ui/lit_on_assignment_lhs.stderr: -------------------------------------------------------------------------------- 1 | error: literals are not allowed on the left-hand side of an assignment 2 | --> MyTemplate.txt:1:2 3 | "let 7=x%}" 4 | --> tests/ui/lit_on_assignment_lhs.rs:5:14 5 | | 6 | 5 | source = "{%let 7=x%}", 7 | | ^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/templates/block_in_include_extended.html: -------------------------------------------------------------------------------- 1 | {%- extends "block_in_include_base.html" -%} 2 | 3 | {%- block block_in_base -%} 4 | block_in_base: from extended! 5 | {% endblock -%} 6 | 7 | {%- block block_in_partial -%} 8 | block_in_partial: from extended! 9 | {% endblock -%} 10 | -------------------------------------------------------------------------------- /testing/templates/nested-macro-args.html: -------------------------------------------------------------------------------- 1 | {%- macro outer(first) -%} 2 | {%- call inner(first, "second") -%}{%- endcall -%} 3 | {%- endmacro -%} 4 | 5 | {%- macro inner(first, second) -%} 6 | {{ first }} {{ second }} 7 | {%- endmacro -%} 8 | 9 | {%- call outer("first") -%}{%- endcall -%} 10 | -------------------------------------------------------------------------------- /testing/tests/ui/duplicated_template_attribute.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | source = "🙂", 6 | ext = "txt" 7 | )] 8 | #[template( 9 | source = "🙃", 10 | ext = "txt" 11 | )] 12 | struct TwoEmojis; 13 | 14 | fn main() { 15 | } 16 | -------------------------------------------------------------------------------- /testing/templates/rust-macro-args.html: -------------------------------------------------------------------------------- 1 | {{ call_a_or_b_on_tail!((a: year, b: month, c: day), call a: 2021, "July", (0+2)) }} 2 | {{ call_a_or_b_on_tail!((a: year, b: month, c: day), call b: 2021, "July", (0+2)) }} 3 | {{ call_a_or_b_on_tail!((a: year, b: day, c: month), call b: 2021, "July", (0+2)) }} 4 | -------------------------------------------------------------------------------- /testing/tests/ui/loop-fields.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | // Fail on unknown `loop` fields 4 | 5 | #[derive(Template)] 6 | #[template( 7 | source = "{% for _ in 0..10 %} {{ loop.index1 }} {% endfor %}", 8 | ext = "txt" 9 | )] 10 | struct UnknownLoopField; 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /testing/tests/ui/block_and_vars.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = r#"{% extends "extend_and_import.html" %} 5 | 6 | {% let x = 12 %} 7 | {% block header -%} 8 | {{ x }} 9 | {% endblock %}"#, ext = "html")] 10 | struct A; 11 | 12 | fn main() { 13 | } 14 | -------------------------------------------------------------------------------- /testing/tests/ui/declare.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "{% decl x = 'a' %}", ext = "html")] 5 | struct Declare1; 6 | 7 | #[derive(Template)] 8 | #[template(source = "{% declare x = 'a' %}", ext = "html")] 9 | struct Declare2; 10 | 11 | fn main() {} 12 | -------------------------------------------------------------------------------- /testing/tests/ui/macro-args.stderr: -------------------------------------------------------------------------------- 1 | error: you are missing a space to separate two string literals 2 | --> :1:11 3 | "r\" \\ \"}}}" 4 | --> tests/ui/macro-args.rs:7:14 5 | | 6 | 7 | source = r###"{{e!{ r#""#r" \ "}}}"###, 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/templates/macro-with-caller.html: -------------------------------------------------------------------------------- 1 | {%- macro outer() -%} 2 |
{{caller()}}
3 | {%- endmacro -%} 4 | 5 | {%- macro inner() -%} 6 | content 7 | {%- endmacro -%} 8 | 9 | {%- macro intermediate() -%} 10 | intermediate 11 | {%- call inner() -%}{%- endcall -%} 12 | {%- endmacro -%} -------------------------------------------------------------------------------- /testing/tests/ui/incorrect_path.stderr: -------------------------------------------------------------------------------- 1 | error: template "thisdoesnotexist.html" not found in directories ["$WORKSPACE/target/tests/trybuild/askama_testing/templates"] 2 | --> tests/ui/incorrect_path.rs:4:19 3 | | 4 | 4 | #[template(path = "thisdoesnotexist.html")] 5 | | ^^^^^^^^^^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /testing/jinja2-assumptions/README.md: -------------------------------------------------------------------------------- 1 | This folder contains tests to ensure that askama works the same as Jinja2. 2 | 3 | Ensure that `uv` is installed: , then execute: 4 | 5 | ```bash 6 | ./test.sh 7 | 8 | # OR 9 | 10 | uv sync && uv run pytest --verbose 11 | ``` 12 | -------------------------------------------------------------------------------- /testing/templates/fragment-nested-block.html: -------------------------------------------------------------------------------- 1 | {% extends "fragment-base.html" %} 2 | 3 | {% block body %} 4 |

Don't render me!

5 | {% block nested %} 6 |

I should be here.

7 | {% endblock %} 8 | {% endblock %} 9 | 10 | {% block other_body %} 11 |

Don't render me!

12 | {% endblock %} 13 | 14 | -------------------------------------------------------------------------------- /testing/tests/ui/macro-args.rs: -------------------------------------------------------------------------------- 1 | // This test ensures that the proc-macro fails if two arguments are not separated. 2 | 3 | use askama::Template; 4 | 5 | #[derive(Template)] 6 | #[template( 7 | source = r###"{{e!{ r#""#r" \ "}}}"###, 8 | ext = "html" 9 | )] 10 | struct Example; 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /testing/tests/ui/transclude-missing.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(path = "transclude-there.html")] 5 | struct Indirect; 6 | 7 | #[derive(Template)] 8 | #[template(source = r#"{% include "transclude-there.html" %}"#, ext = "html")] 9 | struct Direct; 10 | 11 | fn main() {} 12 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | edition = "2021" 2 | group_imports = "StdExternalCrate" 3 | imports_granularity = "Module" 4 | newline_style = "Unix" 5 | normalize_comments = true 6 | style_edition = "2024" 7 | unstable_features = true 8 | use_field_init_shorthand = true 9 | 10 | ignore = [ 11 | "testing/tests/hello.rs", 12 | ] 13 | -------------------------------------------------------------------------------- /testing/jinja2-assumptions/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | if ! which uv > /dev/null; then 6 | echo 'Please install `uv` first: ' 7 | exit 1 8 | fi > /dev/stderr 9 | 10 | cd "$(dirname "$0")" 11 | uv sync 12 | exec uv run pytest --verbose 13 | -------------------------------------------------------------------------------- /testing/templates/match-option-result-option.html: -------------------------------------------------------------------------------- 1 | {%- match foo -%} 2 | {%- when None -%} 3 | nothing 4 | {%- when Some(Err(err)) -%} 5 | err={{err}} 6 | {%- when Some(Ok(None)) -%} 7 | num=absent 8 | {%- when Some(Ok(Some(num))) -%} 9 | num={{num}} 10 | {%- endmatch -%} 11 | -------------------------------------------------------------------------------- /testing/tests/ui/extend.stderr: -------------------------------------------------------------------------------- 1 | error: `extends` block must come first in a template 2 | --> :2:2 3 | " extends \"base.html\" %}\n" 4 | --> tests/ui/extend.rs:5:14 5 | | 6 | 5 | source = r##"bla 7 | | ______________^ 8 | 6 | | {% extends "base.html" %} 9 | 7 | | "##, 10 | | |___^ 11 | -------------------------------------------------------------------------------- /testing/templates/macro-call-raw-string-many-hashes.html: -------------------------------------------------------------------------------- 1 | {{ z!(hello################################################################################################################################################################################################################################################################world) }} 2 | -------------------------------------------------------------------------------- /testing/tests/ui/block_and_vars.stderr: -------------------------------------------------------------------------------- 1 | error[E0609]: no field `x` on type `&A` 2 | --> tests/ui/block_and_vars.rs:3:10 3 | | 4 | 3 | #[derive(Template)] 5 | | ^^^^^^^^ unknown field 6 | | 7 | = note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /testing/templates/macro-import-str-cmp.html: -------------------------------------------------------------------------------- 1 | {%- import "macro-import-str-cmp-macro.html" as macros -%} 2 | 3 | A 4 | 5 | {%- call macros::strcmp("foo") -%}{%- endcall -%} 6 | 7 | B 8 | 9 | {%- call macros::strcmp("bar") -%}{%- endcall -%} 10 | 11 | C 12 | 13 | {%- call macros::strcmp("cat") -%}{%- endcall -%} 14 | 15 | D 16 | -------------------------------------------------------------------------------- /testing/templates/macro-no-args.html: -------------------------------------------------------------------------------- 1 | 1 2 | 3 | {%- macro empty -%} 4 | the best thing 5 | {%- endmacro -%} 6 | 7 | 1 8 | 9 | {%- call empty() -%}{%- endcall -%} 10 | 11 | 1 12 | 13 | {%- macro whole() -%} 14 | we've ever done 15 | {%- endmacro -%} 16 | 17 | 11 18 | 19 | {%- call whole -%}{%- endcall -%} 20 | 21 | 11 22 | -------------------------------------------------------------------------------- /testing/tests/ui/loop-fields.stderr: -------------------------------------------------------------------------------- 1 | error: unknown loop variable `index1` 2 | --> UnknownLoopField.txt:1:29 3 | "index1 }} {% endfor %}" 4 | --> tests/ui/loop-fields.rs:7:14 5 | | 6 | 7 | source = "{% for _ in 0..10 %} {{ loop.index1 }} {% endfor %}", 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/tests/ui/loop_cycle_wrong_argument_count.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | source = r#"{% for v in values %}{{ loop.cycle("r", "g", "b") }}{{ v }},{% endfor %}"#, 6 | ext = "txt" 7 | )] 8 | struct ForCycle<'a> { 9 | values: &'a [u8], 10 | } 11 | 12 | fn main() { 13 | } 14 | -------------------------------------------------------------------------------- /testing/tests/ui/json-too-many-args.stderr: -------------------------------------------------------------------------------- 1 | error: `json` filter accepts at most 1 argument; its arguments are: ([indent]) 2 | --> OneTwoThree.txt:1:13 3 | "3) }}" 4 | --> tests/ui/json-too-many-args.rs:6:34 5 | | 6 | 6 | #[template(ext = "txt", source = "{{ 1|json(2, 3) }}")] 7 | | ^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest a feature you'd like askama to have 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | Please describe what you'd like to be added. For example: 11 | * Missing jinja feature 12 | * New syntax 13 | * New API 14 | * ... 15 | -------------------------------------------------------------------------------- /testing/templates/deep-base.html: -------------------------------------------------------------------------------- 1 | {% import "macro.html" as libb %} 2 | 3 | 4 | {% block head %} 5 | 6 | {% endblock %} 7 | 8 | 9 | {% block body %} 10 | {% call libb::thrice("nav") %}{% endcall %} 11 | Copyright {{ year }} 12 | {% endblock %} 13 | 14 | 15 | -------------------------------------------------------------------------------- /testing/tests/ui/break_outside_of_loop.stderr: -------------------------------------------------------------------------------- 1 | error: you can only `break` inside a `for` loop 2 | --> :1:9 3 | "break%}, have a parsing error!" 4 | --> tests/ui/break_outside_of_loop.rs:5:14 5 | | 6 | 5 | source = "Have a {%break%}, have a parsing error!", 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/tests/ui/macro-super.stderr: -------------------------------------------------------------------------------- 1 | error: `super` is not a valid name for a macro 2 | --> :1:10 3 | "super() -%}{%- endmacro -%}" 4 | --> tests/ui/macro-super.rs:4:21 5 | | 6 | 4 | #[template(source = "{%- macro super() -%}{%- endmacro -%}", ext = "html")] 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/templates/for-break-continue.html: -------------------------------------------------------------------------------- 1 | {%- for v in values -%} 2 | x {{- v -}} 3 | {%- if matches!(v, x if *x > 9) -%} 4 | {%- if matches!(v, x if *x % 2 == 0) -%} 5 | {%- break -%} 6 | {%- else -%} 7 | {%- continue -%} 8 | {%- endif -%} 9 | {%- endif -%} 10 | y 11 | {%- endfor -%} 12 | -------------------------------------------------------------------------------- /testing/templates/for-range.html: -------------------------------------------------------------------------------- 1 | {% for s in 0..2 -%} 2 | foo{% if loop.first %} (first){% endif %}{% if loop.last %} (last){% endif %} 3 | {% endfor -%} 4 | 5 | {% for s in init..1 -%} 6 | bar 7 | {% endfor -%} 8 | 9 | {% for s in 0..end -%} 10 | foo 11 | {% endfor -%} 12 | 13 | {% for s in init..end -%} 14 | bar 15 | {% endfor -%} 16 | -------------------------------------------------------------------------------- /testing/templates/named-end.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {# Testing named "endmacro" #} 3 | {% macro foo(b) -%} 4 | {% if b %}t{% else %}f{% endif -%} 5 | {% endmacro foo -%} 6 | {# Testing named endblock declaration #} 7 | {% block what %}{% endblock what %} 8 | {# Testing named endblock call #} 9 | {% block foo %}tadam{% endblock foo %} 10 | -------------------------------------------------------------------------------- /testing/tests/ui/macro-caller.stderr: -------------------------------------------------------------------------------- 1 | error: `caller` is not a valid name for a macro 2 | --> :1:10 3 | "caller() -%}{%- endmacro -%}" 4 | --> tests/ui/macro-caller.rs:4:21 5 | | 6 | 4 | #[template(source = "{%- macro caller() -%}{%- endmacro -%}", ext = "html")] 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/tests/ui/cycle.stderr: -------------------------------------------------------------------------------- 1 | error: cyclic dependency in graph [ 2 | "\"$DIR/templates/cycle2.html/" --> \"$DIR/templates/cycle1.html/"", 3 | "\"$DIR/templates/cycle1.html/" --> \"$DIR/templates/cycle1.html/"", 4 | ] 5 | --> tests/ui/cycle.rs:4:19 6 | | 7 | 4 | #[template(path = "cycle2.html")] 8 | | ^^^^^^^^^^^^^ 9 | -------------------------------------------------------------------------------- /testing/tests/path.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | // Ensure that paths starting with `::` are supported correctly. 4 | #[test] 5 | fn test_path_starting_with_colon() { 6 | #[derive(Template)] 7 | #[template(source = r#"���{{::std::format!("")}}� �t�"#, ext = "txt")] 8 | struct X; 9 | 10 | assert_eq!(X.render().unwrap(), "���� �t�"); 11 | } 12 | -------------------------------------------------------------------------------- /testing/tests/ui/empty-match.stderr: -------------------------------------------------------------------------------- 1 | error: `match` nodes must contain at least one `when` node and/or an `else` case 2 | --> :1:3 3 | "match true %}{% endmatch %}" 4 | --> tests/ui/empty-match.rs:4:21 5 | | 6 | 4 | #[template(source = "{% match true %}{% endmatch %}", ext = "html")] 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/tests/ui/name_mismatch_endblock.stderr: -------------------------------------------------------------------------------- 1 | error: expected name `foo` in `endblock` tag, found `not_foo` 2 | --> :1:27 3 | "not_foo %}" 4 | --> tests/ui/name_mismatch_endblock.rs:4:21 5 | | 6 | 4 | #[template(source = "{% block foo %}{% endblock not_foo %}", ext = "html")] 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/templates/macro-import-str-cmp-macro.html: -------------------------------------------------------------------------------- 1 | {% macro strcmp0(s, other) -%} 2 | {%- if s == "foo" -%} 3 | foo 4 | {%- else if s == other -%} 5 | other 6 | {%- else -%} 7 | neither 8 | {%- endif -%} 9 | {% endmacro %} 10 | 11 | {% macro strcmp(s) %} 12 | {%- call strcmp0(s, "bar") -%}{%- endcall -%} 13 | {% endmacro %} 14 | -------------------------------------------------------------------------------- /book/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["askama-rs developers"] 3 | language = "en" 4 | src = "src" 5 | title = "Askama" 6 | 7 | [rust] 8 | edition = "2021" 9 | 10 | [output.html] 11 | git-repository-url = "https://github.com/askama-rs/askama/tree/master/book" 12 | edit-url-template = "https://github.com/askama-rs/askama/tree/master/book/{path}" 13 | playground.runnable = false 14 | -------------------------------------------------------------------------------- /testing/templates/match-custom-enum.html: -------------------------------------------------------------------------------- 1 | {% match color %} 2 | {% when Color::Rgb with {r, g: g, b: blue} %} 3 | Colorful: #{{ "{:02X}"|format(r) }}{{ "{:02X}"|format(g) }}{{ "{:02X}"|format(blue) }} 4 | {% when Color::GrayScale with (val) %} 5 | Gray: #{{ "{:02X}"|format(val) }}{{ "{:02X}"|format(val) }}{{ "{:02X}"|format(val) }} 6 | {% else %} 7 | CMYK not supported 8 | {% endmatch %} 9 | -------------------------------------------------------------------------------- /testing/tests/ui/references.stderr: -------------------------------------------------------------------------------- 1 | error: too many references (> 20) 2 | --> :1:6 3 | "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&e>()}}" 4 | --> tests/ui/references.rs:4:21 5 | | 6 | 4 | #[template(source = "{{J::<&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&e>()}}", ext = "html")] 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/tests/coerce.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[test] 4 | fn test_coerce() { 5 | #[derive(Template)] 6 | #[template(path = "if-coerce.html")] 7 | struct IfCoerceTemplate { 8 | t: bool, 9 | f: bool, 10 | } 11 | 12 | let t = IfCoerceTemplate { t: true, f: false }; 13 | assert_eq!(t.render().unwrap(), "ftftfttftelseifelseif"); 14 | } 15 | -------------------------------------------------------------------------------- /askama_parser/benches/librustdoc/type_layout_size.html: -------------------------------------------------------------------------------- 1 | {% if is_unsized %} 2 | (unsized) 3 | {% else %} 4 | {% if size == 1 %} 5 | 1 byte 6 | {% else %} 7 | {{ size +}} bytes 8 | {% endif %} 9 | {% if is_uninhabited %} 10 | {# +#} (uninhabited) 11 | {% endif %} 12 | {% endif %} 13 | -------------------------------------------------------------------------------- /testing/templates/html-base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {%- block title -%} Default title {%- endblock title -%} 7 | 8 | 9 | 10 | {%- block body -%}{%- endblock body -%} 11 | 12 | 13 | -------------------------------------------------------------------------------- /testing/templates/teams.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ year }} 4 | 5 | 6 |

CSL {{ year }}

7 |
    8 | {% for team in teams %} 9 |
  • 10 | {{ team.name }}: {{ team.score }} 11 |
  • 12 | {% endfor %} 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /fuzzing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "askama_fuzzing" 3 | version = "0.1.0" 4 | edition = "2021" 5 | license = "MIT OR Apache-2.0" 6 | publish = false 7 | 8 | [dependencies] 9 | fuzz = { path = "fuzz" } 10 | 11 | arbitrary = "1.4.1" 12 | pretty-error-debug = "0.3.0" 13 | thiserror = "2.0.3" 14 | 15 | [profile.release] 16 | debug = 1 17 | 18 | [workspace] 19 | members = [".", "fuzz"] 20 | -------------------------------------------------------------------------------- /testing/templates/macro-short-circuit.html: -------------------------------------------------------------------------------- 1 | {% macro foo(b) -%} 2 | {{ b }} 3 | {%- endmacro -%} 4 | {% call foo(true) -%}{% endcall -%} 5 | {% call foo(true && true) -%}{% endcall -%} 6 | {% call foo(true && true && true) -%}{% endcall -%} 7 | {% call foo(false) -%}{% endcall -%} 8 | {% call foo(false || true) -%}{% endcall -%} 9 | {% call foo(false || false || true) -%}{% endcall -%} 10 | -------------------------------------------------------------------------------- /testing/templates/macro.html: -------------------------------------------------------------------------------- 1 | 1 2 | 3 | {%- macro thrice(param) -%} 4 | 5 | {{ param }} {{ param }} {{ param }} 6 | 7 | {%- endmacro -%} 8 | 9 | 2 10 | 11 | {%- call thrice(s) -%}{%- endcall -%} 12 | 13 | 3 14 | 15 | {%- macro twice(param) -%} 16 | 17 | {{ param }} {{ param }} 18 | 19 | {%- endmacro twice -%} 20 | 21 | 4 22 | 23 | {%- call twice(s) -%}{%- endcall -%} 24 | 25 | 5 26 | -------------------------------------------------------------------------------- /testing/tests/ui/name_mismatch_endmacro.stderr: -------------------------------------------------------------------------------- 1 | error: expected name `foo` in `endmacro` tag, found `not_foo` 2 | --> :1:41 3 | "not_foo %}" 4 | --> tests/ui/name_mismatch_endmacro.rs:4:21 5 | | 6 | 4 | #[template(source = "{% macro foo(arg) %} {{arg}} {% endmacro not_foo %}", ext = "html")] 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/tests/ui/escape-filter-invalid-kind.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | source = r#"{{ "a"|escape(b"none") }}"#, 6 | ext = "txt", 7 | )] 8 | struct BadEscapeKind; 9 | 10 | #[derive(Template)] 11 | #[template( 12 | source = r#"{{ "a"|escape(c"none") }}"#, 13 | ext = "txt", 14 | )] 15 | struct BadEscapeKind2; 16 | 17 | fn main() {} 18 | -------------------------------------------------------------------------------- /testing/tests/ui/multiple_extends.stderr: -------------------------------------------------------------------------------- 1 | error: `extends` block must come first in a template 2 | --> :3:2 3 | " extends \"foo.html\" %}\n" 4 | --> tests/ui/multiple_extends.rs:4:21 5 | | 6 | 4 | #[template(source = r#" 7 | | _____________________^ 8 | 5 | | {% extends "let.html" %} 9 | 6 | | {% extends "foo.html" %} 10 | 7 | | "#, ext = "txt")] 11 | | |__^ 12 | -------------------------------------------------------------------------------- /testing/templates/filter-recursion.html: -------------------------------------------------------------------------------- 1 | {{s|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|AA|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A||A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A -------------------------------------------------------------------------------- /testing/tests/ui/ambiguous-ws-raw.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = r#"X{#-#}Y"#, ext = "html")] 5 | struct Suppress; 6 | 7 | #[derive(Template)] 8 | #[template(source = r#"X{#+#}Y"#, ext = "html")] 9 | struct Preserve; 10 | 11 | #[derive(Template)] 12 | #[template(source = r#"X{#~#}Y"#, ext = "html")] 13 | struct Minimize; 14 | 15 | fn main() { 16 | } 17 | -------------------------------------------------------------------------------- /testing/tests/ui/error_file_path.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(path = "invalid_syntax.html")] 5 | struct A; 6 | 7 | #[derive(Template)] 8 | #[template(path = "include_invalid_syntax.html")] 9 | struct B; 10 | 11 | #[derive(Template)] 12 | #[template(source = r#"{% extends "include_invalid_syntax.html" %}"#, ext = "txt")] 13 | struct C; 14 | 15 | fn main() { 16 | } 17 | -------------------------------------------------------------------------------- /testing/tests/ui/filter_block_ws.stderr: -------------------------------------------------------------------------------- 1 | error: failed to parse template source 2 | --> :1:27 3 | " %}\nHELLO\n{{v}}\n{%- endfilter %}" 4 | --> tests/ui/filter_block_ws.rs:4:21 5 | | 6 | 4 | #[template(source = "{% filter lower|indent(2) - %} 7 | | _____________________^ 8 | 5 | | HELLO 9 | 6 | | {{v}} 10 | 7 | | {%- endfilter %}", ext = "html")] 11 | | |_________________^ 12 | -------------------------------------------------------------------------------- /testing/tests/ui/filter-recursion.stderr: -------------------------------------------------------------------------------- 1 | error: your template code is too deeply nested, or the last expression is too complex 2 | --> testing/templates/filter-recursion.html:1:277 3 | "|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A||A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A"... 4 | --> tests/ui/filter-recursion.rs:4:19 5 | | 6 | 4 | #[template(path = "filter-recursion.html")] 7 | | ^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/tests/ui/match_with_extra.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | ext = "txt", 6 | source = r#" 7 | {%- match good -%} 8 | // Help, I forgot how to write comments! 9 | {%- when true %} 10 | good 11 | {%- when _ -%} 12 | bad 13 | {%- endmatch -%}"# 14 | )] 15 | struct MatchWithExtra { 16 | good: bool, 17 | } 18 | 19 | fn main() { 20 | } 21 | -------------------------------------------------------------------------------- /testing-no-std/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "askama_testing-no-std" 3 | version = "0.15.0" 4 | authors = ["askama-rs developers"] 5 | edition = "2024" 6 | rust-version = "1.88" 7 | publish = false 8 | 9 | [dev-dependencies] 10 | askama = { path = "../askama", version = "0.15.0", default-features = false, features = ["derive"] } 11 | 12 | assert_matches = "1.5.0" 13 | 14 | [features] 15 | nightly-spans = ["askama/nightly-spans"] 16 | -------------------------------------------------------------------------------- /testing/tests/ui/typo_in_keyword.stderr: -------------------------------------------------------------------------------- 1 | error: expected `endfor` to terminate `for` node, found `endfo` 2 | --> :1:26 3 | "endfo%}\n1234567890123456789012345678901234567890" 4 | --> tests/ui/typo_in_keyword.rs:5:14 5 | | 6 | 5 | source = "{%for i in 1..=10%}{{i}}{%endfo%}\n1234567890123456789012345678901234567890", 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing-alloc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "askama_testing-alloc" 3 | version = "0.15.0" 4 | authors = ["askama-rs developers"] 5 | edition = "2024" 6 | rust-version = "1.88" 7 | publish = false 8 | 9 | [dev-dependencies] 10 | askama = { path = "../askama", version = "0.15.0", default-features = false, features = ["alloc", "derive"] } 11 | 12 | assert_matches = "1.5.0" 13 | 14 | [features] 15 | nightly-spans = ["askama/nightly-spans"] 16 | -------------------------------------------------------------------------------- /testing/tests/ui/macro-caller-with-callexpr.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | // Calling into a macro that expects content (`caller`) using 4 | // the call-expr syntax should fail 5 | 6 | #[derive(Template)] 7 | #[template( 8 | source = r#" 9 | {% macro testmacro() %} 10 | {{caller()}} 11 | {% endmacro %} 12 | {{ testmacro() }} 13 | "#, 14 | ext = "txt" 15 | )] 16 | struct MacroCallerWithCallExpr; 17 | 18 | fn main() {} 19 | -------------------------------------------------------------------------------- /testing/tests/ui/loop_cycle_wrong_argument_count.stderr: -------------------------------------------------------------------------------- 1 | error: loop.cycle(…) cannot use an empty array 2 | --> ForCycle.txt:1:29 3 | "cycle(\"r\", \"g\", \"b\") }}{{ v }},{% endfor %}" 4 | --> tests/ui/loop_cycle_wrong_argument_count.rs:5:14 5 | | 6 | 5 | source = r#"{% for v in values %}{{ loop.cycle("r", "g", "b") }}{{ v }},{% endfor %}"#, 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /testing/tests/ui/match-unit-structs.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | enum Greeting { 4 | Hello, 5 | Hey, 6 | Hi, 7 | } 8 | 9 | #[derive(Template)] 10 | #[template( 11 | ext = "txt", 12 | source = r#" 13 | {%- match greeting -%} 14 | {%- when Hello -%} Hello! 15 | {%- when Hey -%} Hey! 16 | {%- when Hi -%} Hi! 17 | {%- endmatch -%}"# 18 | )] 19 | struct Greeter { 20 | greeting: Greeting, 21 | } 22 | 23 | fn main() { 24 | } 25 | -------------------------------------------------------------------------------- /testing-renamed/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "askama_testing-renamed" 3 | version = "0.15.0" 4 | authors = ["askama-rs developers"] 5 | edition = "2024" 6 | rust-version = "1.88" 7 | publish = false 8 | 9 | [dev-dependencies] 10 | some_name = { package = "askama", path = "../askama", version = "0.15.0", default-features = false, features = ["derive"] } 11 | 12 | assert_matches = "1.5.0" 13 | 14 | [features] 15 | nightly-spans = ["some_name/nightly-spans"] 16 | -------------------------------------------------------------------------------- /testing/templates/let-shadow.html: -------------------------------------------------------------------------------- 1 | {%- let a = 1 -%} 2 | {%- let b -%} 3 | 4 | {%- if cond -%} 5 | {%- let b = 22 -%} 6 | {{ b }}- 7 | 8 | {%- let b = 33 -%} 9 | {{ a }}-{{ b }}- 10 | {%- else -%} 11 | {%- let b = 222 -%} 12 | {{ b }}- 13 | 14 | {%- let b = 333 -%} 15 | {{ a }}-{{ b }}- 16 | 17 | {%- let (a, b) = Self::tuple() -%} 18 | {{ a }}-{{ b }}- 19 | {%- endif -%} 20 | 21 | {%- let a = 11 -%} 22 | {{ a }}-{{ b }} 23 | -------------------------------------------------------------------------------- /testing/tests/ui/block_in_filter_block.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | source = r#"{% extends "html-base.html" %} 6 | 7 | {%- block body -%} 8 |

Metadata

9 | 10 | {% filter wordcount %} 11 | {% block title %}New title{% endblock %} 12 | a b 13 | {% endfilter %} 14 | {%- endblock body %} 15 | "#, 16 | ext = "html" 17 | )] 18 | struct BlockInFilter; 19 | 20 | fn main() { 21 | } 22 | -------------------------------------------------------------------------------- /testing/tests/ui/loop_cycle_empty.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | source = r#"{% for v in values %}{{ loop.cycle([]) }}{{ v }},{% endfor %}"#, 6 | ext = "txt" 7 | )] 8 | struct ForCycleEmpty; 9 | 10 | #[derive(Template)] 11 | #[template( 12 | source = r#"{% for v in values %}{{ loop.cycle::([]) }}{{ v }},{% endfor %}"#, 13 | ext = "txt" 14 | )] 15 | struct ForCycleGenerics; 16 | 17 | fn main() { 18 | } 19 | -------------------------------------------------------------------------------- /testing/tests/ui/macro-caller-with-callexpr.stderr: -------------------------------------------------------------------------------- 1 | error: block is not defined for `caller` 2 | --> MacroCallerWithCallExpr.txt:3:12 3 | "()}}\n{% endmacro %}\n{{ testmacro() }}\n " 4 | --> tests/ui/macro-caller-with-callexpr.rs:8:14 5 | | 6 | 8 | source = r#" 7 | | ______________^ 8 | 9 | | {% macro testmacro() %} 9 | 10 | | {{caller()}} 10 | 11 | | {% endmacro %} 11 | 12 | | {{ testmacro() }} 12 | 13 | | "#, 13 | | |______^ 14 | -------------------------------------------------------------------------------- /testing/tests/ui/terminator-operator.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "<> and <>", config = "issue-128.toml", syntax = "mwe", ext="")] 5 | struct HelloTemplate { 6 | a: u32, 7 | b: u32, 8 | } 9 | 10 | #[derive(Template)] 11 | #[template(source = "<> and <>", config = "issue-128-2.toml", syntax = "mwe", ext="")] 12 | struct HelloTemplate2 { 13 | a: u32, 14 | b: u32, 15 | } 16 | 17 | fn main() {} 18 | -------------------------------------------------------------------------------- /testing/tests/ui/fuzzed_recursion_depth_mul_deref.stderr: -------------------------------------------------------------------------------- 1 | error: your template code is too deeply nested, or the last expression is too complex 2 | --> testing/templates/fuzzed-recursion-mul-deref.txt:2:486 3 | "!**y**false|yz***y**false|z**yz**s**fa*galse|iz**!**y**false|yz***y**f*!**y**fal"... 4 | --> tests/ui/fuzzed_recursion_depth_mul_deref.rs:4:19 5 | | 6 | 4 | #[template(path = "fuzzed-recursion-mul-deref.txt")] 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /askama_parser/benches/librustdoc/LICENSE.md: -------------------------------------------------------------------------------- 1 | The files in this folder were copied verbatim from [librustdoc/html/templates] in version 2 | eeb59f16a5f40e14dc29b95155b7f2569329e3ec. Dual licensed under MIT OR Apache-2.0. 3 | 4 | Please find the authors in [their Git history]. 5 | 6 | [librustdoc/html/templates]: 7 | [their Git history]: 8 | -------------------------------------------------------------------------------- /bench-build/run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | mkdir -p target 6 | hyperfine \ 7 | --runs=3 \ 8 | --warmup=1 \ 9 | --prepare='rm -r target' \ 10 | 'cargo run --features=derive' \ 11 | 'cargo run' 12 | echo 13 | echo ---------- 14 | echo 15 | hyperfine \ 16 | --runs=3 \ 17 | --warmup=1 \ 18 | --prepare='rm -r target' \ 19 | 'cargo run --release --features=derive' \ 20 | 'cargo run --release' 21 | -------------------------------------------------------------------------------- /testing/templates/deep-mid.html: -------------------------------------------------------------------------------- 1 | {% extends "deep-base.html" %} 2 | {% import "macro.html" as libm %} 3 | 4 | {% block head %} 5 | {{ title }} 6 | {{ super() }} 7 | {% endblock %} 8 | 9 | {% block body %} 10 |
11 |
12 | {% block content %} 13 | No content found 14 | {% endblock %} 15 |
16 | 19 |
20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /testing/tests/ui/include-a-folder.stderr: -------------------------------------------------------------------------------- 1 | error: unable to open template file '$DIR/templates/a_file_that_is_actually_a_folder.html': Is a directory (os error 21) 2 | --> YouCannotIncludeFolders.txt:1:2 3 | " include \"a_file_that_is_actually_a_folder.html\" %}" 4 | --> tests/ui/include-a-folder.rs:4:34 5 | | 6 | 4 | #[template(ext = "txt", source = r#"{% include "a_file_that_is_actually_a_folder.html" %}"#)] 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | -------------------------------------------------------------------------------- /bench-build/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bench-build" 3 | version = "0.14.0" 4 | authors = ["askama-rs developers"] 5 | edition = "2024" 6 | rust-version = "1.88" 7 | publish = false 8 | 9 | [dependencies] 10 | askama = { path = "../askama", version = "0.15.0", default-features = false, features = ["std"] } 11 | askama_macros = { path = "../askama_macros", version = "0.15.0", features = ["std"] } 12 | 13 | [features] 14 | default = [] 15 | derive = ["askama/derive"] 16 | 17 | [workspace] 18 | members = ["."] 19 | -------------------------------------------------------------------------------- /book/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [Introduction](./introduction.md) 4 | - [Creating templates](./creating_templates.md) 5 | - [Runtime values](./runtime.md) 6 | - [Debugging](./debugging.md) 7 | - [Configuration](./configuration.md) 8 | - [Template syntax](./template_syntax.md) 9 | - [Opt-in features](./features.md) 10 | - [Filters](./filters.md) 11 | - [Web-frameworks](./frameworks.md) 12 | - [Performance](./performance.md) 13 | - [Upgrading](./upgrading.md) 14 | - [API documentation](./doc/askama/index.html) 15 | -------------------------------------------------------------------------------- /testing/tests/ui/block_in_filter_block.stderr: -------------------------------------------------------------------------------- 1 | error: cannot have a block inside a filter block 2 | --> BlockInFilter.html:7:11 3 | "block title %}New title{% endblock %}\n a b\n {% endfilter %}\n{%- endblo"... 4 | --> tests/ui/block_in_filter_block.rs:5:14 5 | | 6 | 5 | source = r#"{% extends "html-base.html" %} 7 | | ______________^ 8 | 6 | | 9 | 7 | | {%- block body -%} 10 | 8 | |

Metadata

11 | ... | 12 | 14 | | {%- endblock body %} 13 | 15 | | "#, 14 | | |__^ 15 | -------------------------------------------------------------------------------- /testing/tests/ui/num-suffix.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[allow(non_camel_case_types)] 4 | #[derive(Template)] 5 | #[template( 6 | ext = "html", 7 | source = "{{ 0x0x }}", 8 | )] 9 | struct IntSuffix; 10 | 11 | #[derive(Template)] 12 | #[template( 13 | ext = "html", 14 | source = "{{ 0.0_f127 }}", 15 | )] 16 | struct FloatSuffix; 17 | 18 | #[derive(Template)] 19 | #[template( 20 | ext = "html", 21 | source = "{{ 654u321 }}", 22 | )] 23 | struct EitherSuffix; 24 | 25 | fn main() { 26 | } 27 | -------------------------------------------------------------------------------- /tomlfmt.toml: -------------------------------------------------------------------------------- 1 | # Keep in the same order as 2 | table_order = [ 3 | "package", 4 | # targets 5 | "lib", 6 | "bin", 7 | "example", 8 | "test", 9 | "bench", 10 | # dependencies 11 | "dependencies", 12 | "dev-dependencies", 13 | "build-dependencies", 14 | "target", 15 | # misc 16 | "badges", 17 | "features", 18 | "lints", 19 | "patch", 20 | "replace", 21 | "profile", 22 | "workspace", 23 | ] 24 | -------------------------------------------------------------------------------- /askama_macros/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(docsrs, feature(doc_cfg))] 2 | #![deny(elided_lifetimes_in_paths)] 3 | #![deny(unreachable_pub)] 4 | #![doc = include_str!("../README.md")] 5 | 6 | askama_derive::make_derive_template! { 7 | #[proc_macro_derive(Template, attributes(template))] 8 | pub fn derive_template() { 9 | extern crate askama; 10 | } 11 | } 12 | 13 | askama_derive::make_filter_fn! { 14 | #[proc_macro_attribute] 15 | pub fn filter_fn() { 16 | extern crate askama; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /testing/tests/ui/match_with_extra.stderr: -------------------------------------------------------------------------------- 1 | error: failed to parse template source 2 | --> :3:4 3 | "// Help, I forgot how to write comments!\n {%- when true %}\n good\n {"... 4 | --> tests/ui/match_with_extra.rs:6:14 5 | | 6 | 6 | source = r#" 7 | | ______________^ 8 | 7 | | {%- match good -%} 9 | 8 | | // Help, I forgot how to write comments! 10 | 9 | | {%- when true %} 11 | ... | 12 | 12 | | bad 13 | 13 | | {%- endmatch -%}"# 14 | | |__________________^ 15 | -------------------------------------------------------------------------------- /testing/tests/ui/declare.stderr: -------------------------------------------------------------------------------- 1 | error: failed to parse template source 2 | --> :1:10 3 | "= 'a' %}" 4 | --> tests/ui/declare.rs:4:21 5 | | 6 | 4 | #[template(source = "{% decl x = 'a' %}", ext = "html")] 7 | | ^^^^^^^^^^^^^^^^^^^^ 8 | 9 | error: failed to parse template source 10 | --> :1:13 11 | "= 'a' %}" 12 | --> tests/ui/declare.rs:8:21 13 | | 14 | 8 | #[template(source = "{% declare x = 'a' %}", ext = "html")] 15 | | ^^^^^^^^^^^^^^^^^^^^^^^ 16 | -------------------------------------------------------------------------------- /testing/tests/ui/macro_default_value.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "{%- macro thrice(param1, param2=0) -%} 5 | {{ param1 }} {{ param2 }} 6 | {%- endmacro -%} 7 | {%- call thrice() -%}{%- endcall -%}", ext = "html")] 8 | struct InvalidDefault1; 9 | 10 | #[derive(Template)] 11 | #[template(source = "{%- macro thrice(param1, param2=0) -%} 12 | {{ param1 }} {{ param2 }} 13 | {%- endmacro -%} 14 | {%- call thrice(1, 2, 3) -%}{%- endcall -%}", ext = "html")] 15 | struct InvalidDefault2; 16 | 17 | fn main() { 18 | } 19 | -------------------------------------------------------------------------------- /testing/tests/ui/vars.rs: -------------------------------------------------------------------------------- 1 | // Check that `mut` can only be used with a variable name (not destructuring). 2 | 3 | use askama::Template; 4 | 5 | #[derive(Template)] 6 | #[template(source = r#" 7 | {% let mut (a, b) = (1, 2) %} 8 | "#, ext = "html")] 9 | struct Var1; 10 | 11 | #[derive(Template)] 12 | #[template(source = r#" 13 | {% let mut [a, b] = [1, 2] %} 14 | "#, ext = "html")] 15 | struct Var2; 16 | 17 | #[derive(Template)] 18 | #[template(source = r#" 19 | {% let mut Some(a) = Some("a") %} 20 | "#, ext = "html")] 21 | struct Var3; 22 | 23 | fn main() {} 24 | -------------------------------------------------------------------------------- /book/ethicalads-theme.css: -------------------------------------------------------------------------------- 1 | .ethical-sidebar{margin-left:auto}.ethical-sidebar .ea-content{background:var(--bg) !important;color:var(--fg) !important}.ethical-sidebar .ea-content a:is(:link, :visited){color:var(--fg) !important}.ethical-sidebar .ea-content a:is(:hover, :active, :focus){color:var(--sidebar-active) !important}.ethical-sidebar .ea-content strong{color:var(--sidebar-active) !important}.ethical-sidebar .ea-callout a:is(:link, :visited){color:var(--sidebar-non-existant) !important}.ethical-sidebar .ea-callout a:is(:hover, :active, :focus){color:var(--sidebar-fg) !important} 2 | -------------------------------------------------------------------------------- /testing/jinja2-assumptions/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "jinja2-assumptions" 3 | version = "0.1.0" 4 | description = "This folder contains tests to ensure that askama work the same a Jinja2." 5 | readme = "README.md" 6 | requires-python = ">=3.13" 7 | dependencies = [ 8 | "jinja2 >= 3.1.5, == 3.*", 9 | "pytest >= 8.3.4, == 8.*", 10 | ] 11 | license.text = "MIT OR Apache-2.0" 12 | classifiers = ["Private :: Do Not Upload"] 13 | 14 | [build-system] 15 | requires = ["setuptools"] 16 | 17 | [tool.pytest.ini_options] 18 | addopts = ["--import-mode=importlib"] 19 | pythonpath = ["."] 20 | -------------------------------------------------------------------------------- /askama/benches/escape.rs: -------------------------------------------------------------------------------- 1 | use std::hint::black_box; 2 | 3 | use askama::filters::{Html, escape}; 4 | use criterion::{Criterion, criterion_group, criterion_main}; 5 | 6 | criterion_main!(benches); 7 | criterion_group!(benches, functions); 8 | 9 | fn functions(c: &mut Criterion) { 10 | c.bench_function("Escaping", escaping); 11 | } 12 | 13 | fn escaping(b: &mut criterion::Bencher<'_>) { 14 | b.iter(|| { 15 | for &s in black_box(STRINGS) { 16 | let _ = black_box(format!("{}", escape(s, Html).unwrap())); 17 | } 18 | }); 19 | } 20 | 21 | const STRINGS: &[&str] = include!("strings.inc"); 22 | -------------------------------------------------------------------------------- /testing/tests/ui/no-such-escaper.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | ext = "html", 6 | source = r#"In LaTeX you write `{{text}}` like `{{text|escape("latex")}}`."#, 7 | )] 8 | struct LocalEscaper<'a> { 9 | text: &'a str, 10 | } 11 | 12 | #[derive(Template)] 13 | #[template( 14 | ext = "tex", 15 | source = r#"In HTML you write `{{text}}` like `{{text|escape("html")}}`."#, 16 | )] 17 | struct GlobalEscaper<'a> { 18 | text: &'a str, 19 | } 20 | 21 | #[derive(Template)] 22 | #[template(path = "latex-file.tex")] 23 | struct NoSuchEscaper; 24 | 25 | fn main() { 26 | } 27 | -------------------------------------------------------------------------------- /testing/tests/hello.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] // this will generate the code... 4 | #[template(path = "hello.html")] // using the template in this path, relative 5 | // to the templates dir in the crate root 6 | struct HelloTemplate<'a> { 7 | // the name of the struct can be anything 8 | name: &'a str, // the field name should match the variable name 9 | // in your template 10 | } 11 | 12 | #[test] 13 | fn main() { 14 | let hello = HelloTemplate { name: "world" }; // instantiate your struct 15 | assert_eq!("Hello, world!", hello.render().unwrap()); // then render it. 16 | } 17 | -------------------------------------------------------------------------------- /testing/tests/ui/blocks_below_top_level.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = r#" 5 | {% block bla %} 6 | {% extends "bla.txt" %} 7 | {% endblock %} 8 | "#, ext = "txt")] 9 | struct MyTemplate1; 10 | 11 | #[derive(Template)] 12 | #[template(source = r#" 13 | {% block bla %} 14 | {% macro bla() %} 15 | {% endmacro %} 16 | {% endblock %} 17 | "#, ext = "txt")] 18 | struct MyTemplate2; 19 | 20 | #[derive(Template)] 21 | #[template(source = r#" 22 | {% block bla %} 23 | {% import "bla.txt" as blue %} 24 | {% endblock %} 25 | "#, ext = "txt")] 26 | struct MyTemplate3; 27 | 28 | fn main() { 29 | } 30 | -------------------------------------------------------------------------------- /testing/tests/ui/truncate.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = r#"{{ text | truncate }}"#, ext = "html")] 5 | struct NoArgument<'a> { 6 | text: &'a str, 7 | } 8 | 9 | #[derive(Template)] 10 | #[template(source = r#"{{ text | truncate(length) }}"#, ext = "html")] 11 | struct WrongArgumentType<'a> { 12 | text: &'a str, 13 | length: f32, 14 | } 15 | 16 | #[derive(Template)] 17 | #[template(source = r#"{{ text | truncate(length, extra) }}"#, ext = "html")] 18 | struct TooManyArguments<'a> { 19 | text: &'a str, 20 | length: usize, 21 | extra: bool, 22 | } 23 | 24 | fn main() {} 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve askama 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | What is going wrong? 12 | 13 | **To Reproduce** 14 | Please provide the code showing the bug so it can be reproduced. If possible, a minified version on how to reproduce the bug would be preferred as we would be able to work on it much faster. 15 | 16 | **Askama version** 17 | Which `askama` version are you using? 18 | 19 | **Rust version** 20 | Which `rust` version are using? You can get this information by using `rustc --version`. 21 | -------------------------------------------------------------------------------- /testing/tests/if.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[test] 4 | fn test_if() { 5 | #[derive(Template)] 6 | #[template( 7 | source = r#"{%- if s == "" -%} 8 | empty 9 | {%- else if s == "b" -%} 10 | b 11 | {%- elif s == "c" -%} 12 | c 13 | {%- else -%} 14 | else 15 | {%- endif -%}"#, 16 | ext = "txt" 17 | )] 18 | struct If<'a> { 19 | s: &'a str, 20 | } 21 | 22 | assert_eq!(If { s: "" }.render().unwrap(), "empty"); 23 | assert_eq!(If { s: "b" }.render().unwrap(), "b"); 24 | assert_eq!(If { s: "c" }.render().unwrap(), "c"); 25 | assert_eq!(If { s: "d" }.render().unwrap(), "else"); 26 | } 27 | -------------------------------------------------------------------------------- /testing/tests/ui/escape-filter-invalid-kind.stderr: -------------------------------------------------------------------------------- 1 | error: invalid escaper `b"none"`. Expected a string, found a slice 2 | --> BadEscapeKind.txt:1:14 3 | "b\"none\") }}" 4 | --> tests/ui/escape-filter-invalid-kind.rs:5:14 5 | | 6 | 5 | source = r#"{{ "a"|escape(b"none") }}"#, 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | 9 | error: invalid escaper `b"none"`. Expected a string, found a CStr 10 | --> BadEscapeKind2.txt:1:14 11 | "c\"none\") }}" 12 | --> tests/ui/escape-filter-invalid-kind.rs:12:14 13 | | 14 | 12 | source = r#"{{ "a"|escape(c"none") }}"#, 15 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 16 | -------------------------------------------------------------------------------- /askama_escape/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "askama_escape" 3 | version = "0.14.0" 4 | description = "HTML escaping, extracted from Askama" 5 | keywords = ["html", "escaping"] 6 | categories = ["no-std", "no-std::no-alloc"] 7 | homepage = "https://askama.readthedocs.io/" 8 | repository = "https://github.com/askama-rs/askama" 9 | license = "MIT OR Apache-2.0" 10 | readme = "README.md" 11 | edition = "2024" 12 | rust-version = "1.88" 13 | 14 | [package.metadata.docs.rs] 15 | rustdoc-args = ["--generate-link-to-definition", "--cfg=docsrs"] 16 | 17 | [[bench]] 18 | name = "all" 19 | harness = false 20 | 21 | [dev-dependencies] 22 | criterion = "0.8" 23 | -------------------------------------------------------------------------------- /book/ethicalads-theme.sass: -------------------------------------------------------------------------------- 1 | // run: scss --sass --style compressed ethicalads-theme.sass > ethicalads-theme.css 2 | .ethical-sidebar 3 | margin-left: auto 4 | .ea-content 5 | background: var(--bg) !important 6 | color: var(--fg) !important 7 | a:is(:link, :visited) 8 | color: var(--fg) !important 9 | a:is(:hover, :active, :focus) 10 | color: var(--sidebar-active) !important 11 | strong 12 | color: var(--sidebar-active) !important 13 | .ea-callout 14 | a:is(:link, :visited) 15 | color: var(--sidebar-non-existant) !important 16 | a:is(:hover, :active, :focus) 17 | color: var(--sidebar-fg) !important 18 | -------------------------------------------------------------------------------- /testing/templates/operators.html: -------------------------------------------------------------------------------- 1 | {% if a * c > b -%} 2 | mul 3 | {%- endif -%} 4 | {% if c / c == a -%} 5 | div 6 | {%- endif -%} 7 | {% if a % c == b -%} 8 | mod 9 | {%- endif -%} 10 | {% if a + b == c -%} 11 | add 12 | {%- endif -%} 13 | {% if a << b == c -%} 14 | rsh 15 | {%- endif -%} 16 | {% if c >> b == a -%} 17 | lsh 18 | {%- endif -%} 19 | {% if a bitand b == b -%} 20 | band 21 | {%- endif -%} 22 | {% if b xor c == a + c -%} 23 | bxor 24 | {%- endif -%} 25 | {% if b bitor c == a + c -%} 26 | bor 27 | {%- endif -%} 28 | {% if a == b && a + b == c -%} 29 | and 30 | {%- endif -%} 31 | {% if a == c || a == 1 -%} 32 | or 33 | {%- endif -%} 34 | -------------------------------------------------------------------------------- /testing/tests/rest_pattern.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[test] 4 | fn test_rest() { 5 | #[derive(Template)] 6 | #[template( 7 | source = r#" 8 | {%- if let [1, 2, who @ .., 4] = [1, 2, 3, 4] -%} 9 | 111> {{"{:?}"|format(who)}} 10 | {%- endif -%} 11 | {%- if let [who @ .., 4] = [1, 2, 3, 4] -%} 12 | 222> {{"{:?}"|format(who)}} 13 | {%- endif -%} 14 | {%- if let [1, who @ ..] = [1, 2, 3, 4] -%} 15 | 333> {{"{:?}"|format(who)}} 16 | {%- endif -%} 17 | "#, 18 | ext = "txt" 19 | )] 20 | struct Rest; 21 | 22 | assert_eq!( 23 | Rest.render().unwrap(), 24 | "111> [3]222> [1, 2, 3]333> [2, 3, 4]" 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /testing/tests/ui/num-suffix.stderr: -------------------------------------------------------------------------------- 1 | error: unknown integer suffix `x` 2 | --> :1:6 3 | "x }}" 4 | --> tests/ui/num-suffix.rs:7:14 5 | | 6 | 7 | source = "{{ 0x0x }}", 7 | | ^^^^^^^^^^^^ 8 | 9 | error: unknown float suffix `f127` 10 | --> :1:7 11 | "f127 }}" 12 | --> tests/ui/num-suffix.rs:14:14 13 | | 14 | 14 | source = "{{ 0.0_f127 }}", 15 | | ^^^^^^^^^^^^^^^^ 16 | 17 | error: unknown number suffix `u321` 18 | --> :1:6 19 | "u321 }}" 20 | --> tests/ui/num-suffix.rs:21:14 21 | | 22 | 21 | source = "{{ 654u321 }}", 23 | | ^^^^^^^^^^^^^^^ 24 | -------------------------------------------------------------------------------- /testing/tests/ui/pluralize.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: the trait bound `str: PluralizeCount` is not satisfied 2 | --> tests/ui/pluralize.rs:3:10 3 | | 4 | 3 | #[derive(Template)] 5 | | ^^^^^^^^ the trait `PluralizeCount` is not implemented for `str` 6 | | 7 | = help: the following other types implement trait `PluralizeCount`: 8 | &T 9 | &mut T 10 | i128 11 | i16 12 | i32 13 | i64 14 | i8 15 | isize 16 | and $N others 17 | = note: required for `&str` to implement `PluralizeCount` 18 | = note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info) 19 | -------------------------------------------------------------------------------- /testing/tests/ui/terminator-operator.stderr: -------------------------------------------------------------------------------- 1 | error: closing delimiters may not start with operators. The closing expression delimiter (">>") starts with operator `>` 2 | --> tests/ui/terminator-operator.rs:4:49 3 | | 4 | 4 | #[template(source = "<
> and <>", config = "issue-128.toml", syntax = "mwe", ext="")] 5 | | ^^^^^^^^^^^^^^^^ 6 | 7 | error: closing delimiters may not start with operators. The closing expression delimiter (">>>") starts with operator `>` 8 | --> tests/ui/terminator-operator.rs:11:49 9 | | 10 | 11 | #[template(source = "<> and <>", config = "issue-128-2.toml", syntax = "mwe", ext="")] 11 | | ^^^^^^^^^^^^^^^^^^ 12 | -------------------------------------------------------------------------------- /testing/templates/num-literals.html: -------------------------------------------------------------------------------- 1 | {% let plain_int = 9__0__ -%} 2 | {% let neg_int = -9__0__isize -%} 3 | {% let suffix_int = 9__0__i32 -%} 4 | {% let bin_int = 0b__1__0__ -%} 5 | {% let oct_int = 0o__7__0__ -%} 6 | {% let hex_int = 0x__f__0__ -%} 7 | {% let plain_float = 1__0__.5__0__ -%} 8 | {% let suffix_float = 1__0__.5__0__f32 -%} 9 | {% let exp_float = 1__0__e+__1__0__f32 -%} 10 | {% let dotexp_float = 1__0__.5__0__e+__1__0__f32 -%} 11 | [{{ plain_int }}, {{ neg_int }}, {{ suffix_int }}, {{ bin_int }}, {{ oct_int }}, {{ hex_int }}, {{ plain_float }}, {{ suffix_float }}, {{ exp_float }}, {{ dotexp_float }}] 12 | {% for value in 1..2 -%} 13 | {{ value }} 14 | {%- endfor %} 15 | {% for value in 1..=2 -%} 16 | {{ value }} 17 | {%- endfor %} 18 | -------------------------------------------------------------------------------- /testing/tests/no_implicit_prelude.rs: -------------------------------------------------------------------------------- 1 | #![no_implicit_prelude] 2 | 3 | use ::askama::Template; 4 | 5 | #[test] 6 | fn test_source() { 7 | #[derive(Template)] 8 | #[template(ext = "html", source = "Hello, {{ name }}!")] 9 | struct HelloTemplate<'a> { 10 | name: &'a str, 11 | } 12 | 13 | let hello = HelloTemplate { name: "world" }; 14 | ::std::assert_eq!("Hello, world!", hello.render().unwrap()); 15 | } 16 | 17 | #[test] 18 | fn test_path() { 19 | #[derive(Template)] 20 | #[template(path = "hello.html")] 21 | struct HelloTemplate<'a> { 22 | name: &'a str, 23 | } 24 | 25 | let hello = HelloTemplate { name: "world" }; 26 | ::std::assert_eq!("Hello, world!", hello.render().unwrap()); 27 | } 28 | -------------------------------------------------------------------------------- /testing/templates/compare.html: -------------------------------------------------------------------------------- 1 | {% if a == b -%} 2 | t 3 | {%- endif -%} 4 | {% if a == c -%} 5 | t 6 | {%- else -%} 7 | f 8 | {%- endif %} 9 | {% if a != c -%} 10 | t 11 | {%- endif %} 12 | {%- if a != b -%} 13 | t 14 | {%- else -%} 15 | f 16 | {%- endif %} 17 | {% if c >= b -%} 18 | t 19 | {%- endif -%} 20 | {% if b >= c -%} 21 | t 22 | {%- else -%} 23 | f 24 | {%- endif %} 25 | {% if c > b -%} 26 | t 27 | {%- endif -%} 28 | {% if a > c -%} 29 | t 30 | {%- else -%} 31 | f 32 | {%- endif %} 33 | {% if a <= b -%} 34 | t 35 | {%- endif -%} 36 | {% if c <= b -%} 37 | t 38 | {%- else -%} 39 | f 40 | {%- endif %} 41 | {% if a < c -%} 42 | t 43 | {%- endif %} 44 | {%- if a < b -%} 45 | t 46 | {%- else -%} 47 | f 48 | {%- endif %} 49 | -------------------------------------------------------------------------------- /testing/tests/custom_ui/duplicated_block_calls.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | // Check if the block call is duplicated in the current template. 4 | #[derive(Template)] 5 | #[template( 6 | source = r##"{% extends "base.html" %} 7 | 8 | {% block content %}{% endblock %} 9 | {% block content %}{% endblock %} 10 | "##, 11 | ext = "txt", 12 | )] 13 | struct X { 14 | title: &'static str, 15 | } 16 | 17 | // Check if the block call is called in the extended template and in the current one. 18 | #[derive(Template)] 19 | #[template( 20 | source = r##"{% extends "child.html" %} 21 | 22 | {% block content %}another{% endblock %} 23 | "##, 24 | ext = "txt", 25 | )] 26 | struct X2 { 27 | title: &'static str, 28 | } 29 | 30 | fn main() {} 31 | -------------------------------------------------------------------------------- /testing/tests/ui/no-block.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | ext = "txt", 6 | source = "{% block not_a %}{% endblock %}", 7 | block = "a" 8 | )] 9 | struct SourceTemplate; 10 | 11 | #[derive(Template)] 12 | #[template(path = "no-block.txt", block = "a")] 13 | struct PathTemplate; 14 | 15 | #[derive(Template)] 16 | #[template(path = "no-block-with-include.txt", block = "a")] 17 | struct NoBlockWithInclude; 18 | 19 | #[derive(Template)] 20 | #[template(path = "no-block-with-include-times-2.txt", block = "a")] 21 | struct NoBlockWithIncludeTimes2; 22 | 23 | #[derive(Template)] 24 | #[template(path = "no-block-with-base-template.txt", block = "a")] 25 | struct NoBlockWithBaseTemplate; 26 | 27 | fn main() { 28 | } 29 | -------------------------------------------------------------------------------- /testing/tests/ui/loop_cycle_empty.stderr: -------------------------------------------------------------------------------- 1 | error: loop.cycle(…) cannot use an empty array 2 | --> ForCycleEmpty.txt:1:29 3 | "cycle([]) }}{{ v }},{% endfor %}" 4 | --> tests/ui/loop_cycle_empty.rs:5:14 5 | | 6 | 5 | source = r#"{% for v in values %}{{ loop.cycle([]) }}{{ v }},{% endfor %}"#, 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | 9 | error: loop.cycle(…) doesn't use generics 10 | --> ForCycleGenerics.txt:1:29 11 | "cycle::([]) }}{{ v }},{% endfor %}" 12 | --> tests/ui/loop_cycle_empty.rs:12:14 13 | | 14 | 12 | source = r#"{% for v in values %}{{ loop.cycle::([]) }}{{ v }},{% endfor %}"#, 15 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 16 | -------------------------------------------------------------------------------- /examples/axum-app/templates/error.html: -------------------------------------------------------------------------------- 1 | {% extends "_layout.html" %} 2 | 3 | {%- block title -%} 4 | {%- match err -%} 5 | {% when AppError::NotFound -%} 404: Not Found 6 | {% else -%} 500: Internal Server Error 7 | {%- endmatch -%} 8 | {%- endblock -%} 9 | 10 | {%- block content -%} 11 |

12 | {%- match err -%} 13 | {% when AppError::NotFound -%} 404: Not Found 14 | {% else -%} 500: Internal Server Error 15 | {%- endmatch -%} 16 |

17 | 18 | {%- match err -%} 19 | {% when AppError::NotFound -%} 20 | {% when AppError::Render(err) -%} 21 |
{{ err }}
22 | {%- endmatch -%} 23 | 24 |

Back to the first page.

25 | {%- endblock -%} 26 | -------------------------------------------------------------------------------- /examples/poem-app/templates/error.html: -------------------------------------------------------------------------------- 1 | {% extends "_layout.html" %} 2 | 3 | {%- block title -%} 4 | {%- match err -%} 5 | {% when AppError::NotFound -%} 404: Not Found 6 | {% else -%} 500: Internal Server Error 7 | {%- endmatch -%} 8 | {%- endblock -%} 9 | 10 | {%- block content -%} 11 |

12 | {%- match err -%} 13 | {% when AppError::NotFound -%} 404: Not Found 14 | {% else -%} 500: Internal Server Error 15 | {%- endmatch -%} 16 |

17 | 18 | {%- match err -%} 19 | {% when AppError::NotFound -%} 20 | {% when AppError::Render(err) -%} 21 |
{{ err }}
22 | {%- endmatch -%} 23 | 24 |

Back to the first page.

25 | {%- endblock -%} 26 | -------------------------------------------------------------------------------- /examples/rocket-app/templates/error.html: -------------------------------------------------------------------------------- 1 | {% extends "_layout.html" %} 2 | 3 | {%- block title -%} 4 | {%- match err -%} 5 | {% when AppError::NotFound -%} 404: Not Found 6 | {% else -%} 500: Internal Server Error 7 | {%- endmatch -%} 8 | {%- endblock -%} 9 | 10 | {%- block content -%} 11 |

12 | {%- match err -%} 13 | {% when AppError::NotFound -%} 404: Not Found 14 | {% else -%} 500: Internal Server Error 15 | {%- endmatch -%} 16 |

17 | 18 | {%- match err -%} 19 | {% when AppError::NotFound -%} 20 | {% when AppError::Render(err) -%} 21 |
{{ err }}
22 | {%- endmatch -%} 23 | 24 |

Back to the first page.

25 | {%- endblock -%} 26 | -------------------------------------------------------------------------------- /examples/warp-app/templates/error.html: -------------------------------------------------------------------------------- 1 | {% extends "_layout.html" %} 2 | 3 | {%- block title -%} 4 | {%- match err -%} 5 | {% when AppError::NotFound -%} 404: Not Found 6 | {% else -%} 500: Internal Server Error 7 | {%- endmatch -%} 8 | {%- endblock -%} 9 | 10 | {%- block content -%} 11 |

12 | {%- match err -%} 13 | {% when AppError::NotFound -%} 404: Not Found 14 | {% else -%} 500: Internal Server Error 15 | {%- endmatch -%} 16 |

17 | 18 | {%- match err -%} 19 | {% when AppError::NotFound -%} 20 | {% when AppError::Render(err) -%} 21 |
{{ err }}
22 | {%- endmatch -%} 23 | 24 |

Back to the first page.

25 | {%- endblock -%} 26 | -------------------------------------------------------------------------------- /testing/tests/ui/as-primitive-type.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = r#"{{ 1234 as 4567 }}"#, ext = "html")] 5 | struct A; 6 | 7 | #[derive(Template)] 8 | #[template(source = r#"{{ 1234 as ? }}"#, ext = "html")] 9 | struct B; 10 | 11 | #[derive(Template)] 12 | #[template(source = r#"{{ 1234 as u1234 }}"#, ext = "html")] 13 | struct C; 14 | 15 | #[derive(Template)] 16 | #[template(source = r#"{{ 1234 as core::primitive::u32 }}"#, ext = "html")] 17 | struct D; 18 | 19 | #[derive(Template)] 20 | #[template(source = r#"{{ 1234 as int32_t }}"#, ext = "html")] 21 | struct E; 22 | 23 | #[derive(Template)] 24 | #[template(source = r#"{{ (1234 + 4 * 12 / 45675445 - 13) as int32_t }}"#, ext = "html")] 25 | struct F; 26 | 27 | fn main() { 28 | } 29 | -------------------------------------------------------------------------------- /testing/tests/ui/number.stderr: -------------------------------------------------------------------------------- 1 | error: only expected `01234567` digits for `0o` integers, found `8` 2 | --> :1:6 3 | "0o08) }}" 4 | --> tests/ui/number.rs:4:21 5 | | 6 | 4 | #[template(source = r#"{{ e!(0o08) }}"#, ext = "html")] 7 | | ^^^^^^^^^^^^^^^^^^^ 8 | 9 | error: only expected `01` digits for `0b` integers, found `3` 10 | --> :1:6 11 | "0b3) }}" 12 | --> tests/ui/number.rs:8:21 13 | | 14 | 8 | #[template(source = r#"{{ e!(0b3) }}"#, ext = "html")] 15 | | ^^^^^^^^^^^^^^^^^^ 16 | 17 | error[E0601]: `main` function not found in crate `$CRATE` 18 | --> tests/ui/number.rs:9:10 19 | | 20 | 9 | struct B; 21 | | ^ consider adding a `main` function to `$DIR/tests/ui/number.rs` 22 | -------------------------------------------------------------------------------- /examples/actix-web-app/templates/error.html: -------------------------------------------------------------------------------- 1 | {% extends "_layout.html" %} 2 | 3 | {%- block title -%} 4 | {%- match err -%} 5 | {% when AppError::NotFound -%} 404: Not Found 6 | {% else -%} 500: Internal Server Error 7 | {%- endmatch -%} 8 | {%- endblock -%} 9 | 10 | {%- block content -%} 11 |

12 | {%- match err -%} 13 | {% when AppError::NotFound -%} 404: Not Found 14 | {% else -%} 500: Internal Server Error 15 | {%- endmatch -%} 16 |

17 | 18 | {%- match err -%} 19 | {% when AppError::Render(err) -%} 20 |
{{ err }}
21 | {% else -%} 22 | {%- endmatch -%} 23 | 24 |

Back to the first page.

25 | {%- endblock -%} 26 | -------------------------------------------------------------------------------- /testing/tests/ui/excessive_nesting.stderr: -------------------------------------------------------------------------------- 1 | error: your template code is too deeply nested, or the last expression is too complex 2 | --> :15:58 3 | "%}{%if 1%}{%if 1%}{%if 1%}\n {%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{"... 4 | --> tests/ui/excessive_nesting.rs:5:14 5 | | 6 | 5 | source = " 7 | | ______________^ 8 | 6 | | {%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%} 9 | 7 | | {%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%} 10 | 8 | | {%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%} 11 | ... | 12 | 114 | | {%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%}{%if 1%} 1000 13 | 115 | | ", 14 | | |_____^ 15 | -------------------------------------------------------------------------------- /testing/tests/ui/macro-args-hashtag.rs: -------------------------------------------------------------------------------- 1 | // This test ensures that we have the right error if a `#` character isn't prepended by 2 | // a whitespace character and also that lifetimes are correctly handled. 3 | 4 | use askama::Template; 5 | 6 | #[derive(Template)] 7 | #[template( 8 | source = r###"{{z!{'r#}}}"###, 9 | ext = "html" 10 | )] 11 | struct Example; 12 | 13 | #[derive(Template)] 14 | #[template( 15 | source = r###"{{z!{'r# y}}}"###, 16 | ext = "html" 17 | )] 18 | struct Example2; 19 | 20 | #[derive(Template)] 21 | #[template( 22 | source = r###"{{z!{'break}}}"###, 23 | ext = "html" 24 | )] 25 | struct Example3; 26 | 27 | #[derive(Template)] 28 | #[template( 29 | source = r###"{{z!{'r#self}}}"###, 30 | ext = "html" 31 | )] 32 | struct Example4; 33 | 34 | fn main() {} 35 | -------------------------------------------------------------------------------- /testing/tests/ui/iso646.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(ext = "txt", source = "{{ a & b }}")] 5 | struct BitAnd { 6 | a: u32, 7 | b: u32, 8 | } 9 | 10 | #[derive(Template)] 11 | #[template(ext = "txt", source = "{{ a bitand b }}")] 12 | struct BitAndIso646 { 13 | a: u32, 14 | b: u32, 15 | } 16 | 17 | #[derive(Template)] 18 | #[template(ext = "txt", source = "{{ a bitor b }}")] 19 | struct BitOrIso646 { 20 | a: u32, 21 | b: u32, 22 | } 23 | 24 | #[derive(Template)] 25 | #[template(ext = "txt", source = "{{ a ^ b }}")] 26 | struct Xor { 27 | a: u32, 28 | b: u32, 29 | } 30 | 31 | #[derive(Template)] 32 | #[template(ext = "txt", source = "{{ a xor b }} {{ c }}")] 33 | struct XorIso646 { 34 | a: u32, 35 | b: u32, 36 | } 37 | 38 | fn main() { 39 | } 40 | -------------------------------------------------------------------------------- /book/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Askama - Page not found 9 | 10 | 11 |
Oops!
12 |
13 |
Seems like you're lost...
14 |
Back to home?
15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /testing/tests/reexported-askama.rs: -------------------------------------------------------------------------------- 1 | #[doc(hidden)] 2 | pub use askama as __askama; 3 | 4 | #[rustfmt::skip] // FIXME: upstream bug 5 | #[macro_export] 6 | macro_rules! new_greeter { 7 | ($name:ident) => { 8 | #[derive(Debug, $crate::__askama::Template)] 9 | #[template( 10 | ext = "txt", 11 | source = "Hello, world!", 12 | askama = $crate::__askama 13 | )] 14 | struct $name; 15 | }; 16 | } 17 | 18 | #[test] 19 | fn test_reexported_askama() { 20 | // This test is the an example of `askama::Template`'s doc. 21 | // It cannot be executed in there. 22 | // We show how an re-exported `askama` can be used in a macro. 23 | 24 | new_greeter!(HelloWorld); 25 | assert_eq!(HelloWorld.to_string(), "Hello, world!"); 26 | } 27 | -------------------------------------------------------------------------------- /testing/tests/ui/transclude-missing.stderr: -------------------------------------------------------------------------------- 1 | error: template "transclude-missing.html" not found in directories ["$WORKSPACE/target/tests/trybuild/askama_testing/templates"] 2 | --> testing/templates/transclude-there.html:1:2 3 | " include \"transclude-missing.html\" %}" 4 | --> tests/ui/transclude-missing.rs:4:19 5 | | 6 | 4 | #[template(path = "transclude-there.html")] 7 | | ^^^^^^^^^^^^^^^^^^^^^^^ 8 | 9 | error: template "transclude-missing.html" not found in directories ["$WORKSPACE/target/tests/trybuild/askama_testing/templates"] 10 | --> testing/templates/transclude-there.html:1:2 11 | " include \"transclude-missing.html\" %}" 12 | --> tests/ui/transclude-missing.rs:8:21 13 | | 14 | 8 | #[template(source = r#"{% include "transclude-there.html" %}"#, ext = "html")] 15 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 16 | -------------------------------------------------------------------------------- /testing/tests/ui/iso646.stderr: -------------------------------------------------------------------------------- 1 | error: the binary AND operator is called `bitand` in askama 2 | --> :1:5 3 | "& b }}" 4 | --> tests/ui/iso646.rs:4:34 5 | | 6 | 4 | #[template(ext = "txt", source = "{{ a & b }}")] 7 | | ^^^^^^^^^^^^^ 8 | 9 | error: the binary XOR operator is called `xor` in askama 10 | --> :1:5 11 | "^ b }}" 12 | --> tests/ui/iso646.rs:25:34 13 | | 14 | 25 | #[template(ext = "txt", source = "{{ a ^ b }}")] 15 | | ^^^^^^^^^^^^^ 16 | 17 | error[E0609]: no field `c` on type `&XorIso646` 18 | --> tests/ui/iso646.rs:31:10 19 | | 20 | 31 | #[derive(Template)] 21 | | ^^^^^^^^ unknown field 22 | | 23 | = note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info) 24 | -------------------------------------------------------------------------------- /askama_parser/benches/librustdoc/source.html: -------------------------------------------------------------------------------- 1 |
{# #} 2 | {# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr 3 | Do not show "1 2 3 4 5 ..." in web search results. #} 4 |
 5 |         {% for line in lines.clone() %}
 6 |             {% if embedded %}
 7 |                 {{line|safe}}
 8 |             {%~ else %}
 9 |                 {{line|safe}}
10 |             {%~ endif %}
11 |         {% endfor %}
12 |     
{# #} 13 |
 {# #}
14 |         
15 |             {% if needs_expansion %}
16 |                 
17 |             {% endif %}
18 |             {{code_html|safe}}
19 |          {# #}
20 |     
{# #} 21 |
22 | -------------------------------------------------------------------------------- /testing/tests/ui/wrong-end.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "{% for _ in 1..=10 %}{% end %}", ext = "txt")] 5 | struct For; 6 | 7 | #[derive(Template)] 8 | #[template(source = "{% macro test() %}{% end %}", ext = "txt")] 9 | struct Macro; 10 | 11 | #[derive(Template)] 12 | #[template(source = "{% filter upper %}{% end %}", ext = "txt")] 13 | struct Filter; 14 | 15 | #[derive(Template)] 16 | #[template(source = "{% match () %}{% when () %}{% end %}", ext = "txt")] 17 | struct Match; 18 | 19 | #[derive(Template)] 20 | #[template(source = "{% block body %}{% end %}", ext = "txt")] 21 | struct Block; 22 | 23 | #[derive(Template)] 24 | #[template(source = "{% if true %}{% end %}", ext = "txt")] 25 | struct If; 26 | 27 | #[derive(Template)] 28 | #[template(source = "{% if true %}{% endfor %}", ext = "txt")] 29 | struct IfFor; 30 | 31 | fn main() {} 32 | -------------------------------------------------------------------------------- /testing/tests/ui/error_file_path.stderr: -------------------------------------------------------------------------------- 1 | error: failed to parse template source 2 | --> testing/templates/invalid_syntax.html:1:14 3 | "}" 4 | --> tests/ui/error_file_path.rs:4:19 5 | | 6 | 4 | #[template(path = "invalid_syntax.html")] 7 | | ^^^^^^^^^^^^^^^^^^^^^ 8 | 9 | error: failed to parse template source 10 | --> testing/templates/invalid_syntax.html:1:14 11 | "}" 12 | --> tests/ui/error_file_path.rs:8:19 13 | | 14 | 8 | #[template(path = "include_invalid_syntax.html")] 15 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 16 | 17 | error: failed to parse template source 18 | --> testing/templates/invalid_syntax.html:1:14 19 | "}" 20 | --> tests/ui/error_file_path.rs:12:21 21 | | 22 | 12 | #[template(source = r#"{% extends "include_invalid_syntax.html" %}"#, ext = "txt")] 23 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 24 | -------------------------------------------------------------------------------- /askama_escape/benches/all.rs: -------------------------------------------------------------------------------- 1 | use std::hint::black_box; 2 | 3 | use askama_escape::escape_html; 4 | use criterion::{Criterion, Throughput, criterion_group, criterion_main}; 5 | 6 | criterion_main!(benches); 7 | criterion_group!(benches, functions); 8 | 9 | fn functions(c: &mut Criterion) { 10 | c.bench_function("escape_html", escaping); 11 | let mut g = c.benchmark_group("all"); 12 | let bytes = STRINGS.iter().map(|s| s.len() as u64).sum(); 13 | g.throughput(Throughput::Bytes(bytes)); 14 | g.bench_function("escape_html", escaping); 15 | g.finish(); 16 | } 17 | 18 | fn escaping(b: &mut criterion::Bencher<'_>) { 19 | let mut dest = String::new(); 20 | b.iter(|| { 21 | for &s in black_box(STRINGS) { 22 | dest.clear(); 23 | black_box(escape_html(&mut dest, s)).unwrap(); 24 | } 25 | }); 26 | } 27 | 28 | const STRINGS: &[&str] = include!("strings.inc"); 29 | -------------------------------------------------------------------------------- /testing/tests/ui/broken-config.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = "", ext = "txt", config = "no-such-config.toml")] 5 | struct NoSuchConfig; 6 | 7 | #[derive(Template)] 8 | #[template(source = "", ext = "txt", config = "folder-config.toml")] 9 | struct FolderConfig; 10 | 11 | #[derive(Template)] 12 | #[template(source = "", ext = "txt", config = "delim-clash.toml")] 13 | struct DelimClash; 14 | 15 | #[derive(Template)] 16 | #[template(source = "", ext = "txt", config = "delim-too-short.toml")] 17 | struct DelimTooShort; 18 | 19 | #[derive(Template)] 20 | #[template(source = "<+a+> and <+b+>", config = "operator-plus-config.toml", syntax = "plus", ext = "txt")] 21 | struct PlusOperator; 22 | 23 | #[derive(Template)] 24 | #[template(source = "<)a(> and <)b(>", config = "operator-paren-config.toml", syntax = "paren", ext = "txt")] 25 | struct ParenOperator; 26 | 27 | fn main() {} 28 | -------------------------------------------------------------------------------- /askama_derive/README.md: -------------------------------------------------------------------------------- 1 | # askama_derive: code generator of Askama templating engine 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/askama_derive?logo=rust&style=flat-square&logoColor=white "Crates.io")](https://crates.io/crates/askama_derive) 4 | [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/askama-rs/askama/rust.yml?branch=master&logo=github&style=flat-square&logoColor=white "GitHub Workflow Status")](https://github.com/askama-rs/askama/actions/workflows/rust.yml) 5 | [![Book](https://img.shields.io/readthedocs/askama?label=book&logo=readthedocs&style=flat-square&logoColor=white "Book")](https://askama.readthedocs.io/) 6 | [![docs.rs](https://img.shields.io/docsrs/askama_derive?logo=docsdotrs&style=flat-square&logoColor=white "docs.rs")](https://docs.rs/askama_derive/) 7 | 8 | This crate contains the code generator used by the 9 | [Askama](https://github.com/askama-rs/askama) templating engine. 10 | -------------------------------------------------------------------------------- /testing/tests/ui/underscore.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = r#"{% let x = [_] %}"#, ext = "html")] 5 | struct UnderscoreErr1; 6 | 7 | #[derive(Template)] 8 | #[template(source = r#"{% if (_ + 12) != 0 %}{% endif %}"#, ext = "html")] 9 | struct UnderscoreErr2; 10 | 11 | #[derive(Template)] 12 | #[template(source = r#"{% if 12 == _ %}{% endif %}"#, ext = "html")] 13 | struct UnderscoreErr3; 14 | 15 | #[derive(Template)] 16 | #[template(source = r#"{% match _ %}{% endmatch %}"#, ext = "html")] 17 | struct UnderscoreErr4; 18 | 19 | #[derive(Template)] 20 | #[template(source = r#"{% let _ %}"#, ext = "html")] 21 | struct UnderscoreErr5; 22 | 23 | #[derive(Template)] 24 | #[template(source = r#"{% decl _ %}"#, ext = "html")] 25 | struct UnderscoreErr6; 26 | 27 | #[derive(Template)] 28 | #[template(source = r#"{% declare _ %}"#, ext = "html")] 29 | struct UnderscoreErr7; 30 | 31 | fn main() {} 32 | -------------------------------------------------------------------------------- /askama_macros/README.md: -------------------------------------------------------------------------------- 1 | # askama_macros: procedural macros for the Askama templating engine 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/askama_macros?logo=rust&style=flat-square&logoColor=white "Crates.io")](https://crates.io/crates/askama_macros) 4 | [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/askama-rs/askama/rust.yml?branch=master&logo=github&style=flat-square&logoColor=white "GitHub Workflow Status")](https://github.com/askama-rs/askama/actions/workflows/rust.yml) 5 | [![Book](https://img.shields.io/readthedocs/askama?label=book&logo=readthedocs&style=flat-square&logoColor=white "Book")](https://askama.readthedocs.io/) 6 | [![docs.rs](https://img.shields.io/docsrs/askama_macros?logo=docsdotrs&style=flat-square&logoColor=white "docs.rs")](https://docs.rs/askama_macros/) 7 | 8 | This crate contains the procedural macros used by the 9 | [Askama](https://github.com/askama-rs/askama) templating engine. 10 | -------------------------------------------------------------------------------- /askama_parser/README.md: -------------------------------------------------------------------------------- 1 | # askama_parser: template parser for the Askama templating engine 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/askama_parser?logo=rust&style=flat-square&logoColor=white "Crates.io")](https://crates.io/crates/askama_parser) 4 | [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/askama-rs/askama/rust.yml?branch=master&logo=github&style=flat-square&logoColor=white "GitHub Workflow Status")](https://github.com/askama-rs/askama/actions/workflows/rust.yml) 5 | [![Book](https://img.shields.io/readthedocs/askama?label=book&logo=readthedocs&style=flat-square&logoColor=white "Book")](https://askama.readthedocs.io/) 6 | [![docs.rs](https://img.shields.io/docsrs/askama_parser?logo=docsdotrs&style=flat-square&logoColor=white "docs.rs")](https://docs.rs/askama_parser/) 7 | 8 | This crate contains the procedural macros used by the 9 | [Askama](https://github.com/askama-rs/askama) templating engine. 10 | -------------------------------------------------------------------------------- /testing/build.rs: -------------------------------------------------------------------------------- 1 | use std::env::var_os; 2 | use std::path::PathBuf; 3 | 4 | fn main() { 5 | let Some(toolchain) = var_os("RUSTUP_TOOLCHAIN") else { 6 | println!("cargo::warning=`RUSTUP_TOOLCHAIN` unset"); 7 | return; 8 | }; 9 | 10 | let toolchain = PathBuf::from(toolchain); 11 | let toolchain = toolchain.file_name().unwrap_or(toolchain.as_os_str()); 12 | let Some(toolchain) = toolchain.to_str() else { 13 | println!("cargo::warning=env var `RUSTUP_TOOLCHAIN` is not a UTF-8 string ({toolchain:?})"); 14 | return; 15 | }; 16 | 17 | let (toolchain, _) = toolchain.split_once('-').unwrap_or((toolchain, "")); 18 | if toolchain == "stable" { 19 | println!("cargo:rustc-cfg=RUN_UI_TESTS"); 20 | } else { 21 | println!( 22 | "cargo::warning=UI tests are ignored on any channel but +stable \ 23 | (running: {toolchain:?})" 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fuzzing/README.md: -------------------------------------------------------------------------------- 1 | # Askama Fuzzing 2 | 3 | First install `cargo-fuzz` and rust-nightly (once): 4 | 5 | ```sh 6 | cargo install cargo-fuzz 7 | rustup install nightly 8 | ``` 9 | 10 | Then execute in this folder: 11 | 12 | ```sh 13 | RUST_BACKTRACE=1 nice cargo +nightly fuzz run 14 | ``` 15 | 16 | `fuzz_target` is one out of `all`, `filters`, `html` or `parser`. 17 | 18 | The execution won't stop, but continue until you kill it with ctrl+c. 19 | Or until it finds a panic. 20 | If the execution found a panic, then a file with the input scenario is written, e.g. 21 | `fuzz/artifacts/parser/crash-b91ab…`. 22 | To get more information about the failed scenario, run or debug this command with the given path: 23 | 24 | ```sh 25 | cargo run -- fuzz/artifacts/parser/crash-b91ab… 26 | ``` 27 | 28 | Find more information about fuzzing here: 29 | 30 | * `cargo fuzz help run` 31 | * 32 | -------------------------------------------------------------------------------- /testing/tests/ui/is_defined.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | ext = "html", 6 | source = r#"{% if x.y is defined %}{% endif %}"#, 7 | )] 8 | struct A; 9 | 10 | #[derive(Template)] 11 | #[template( 12 | ext = "html", 13 | source = r#"{% if true is defined %}{% endif %}"#, 14 | )] 15 | struct B; 16 | 17 | #[derive(Template)] 18 | #[template( 19 | ext = "html", 20 | source = r#"{% if true is %}{% endif %}"#, 21 | )] 22 | struct C; 23 | 24 | #[derive(Template)] 25 | #[template( 26 | ext = "html", 27 | source = r#"{% if x is %}{% endif %}"#, 28 | )] 29 | struct D; 30 | 31 | #[derive(Template)] 32 | #[template( 33 | ext = "html", 34 | source = r#"{% if x is blue %}{% endif %}"#, 35 | )] 36 | struct E; 37 | 38 | #[derive(Template)] 39 | #[template( 40 | ext = "html", 41 | source = r#"{% if x is blue.red %}{% endif %}"#, 42 | )] 43 | struct F; 44 | 45 | fn main() { 46 | } 47 | -------------------------------------------------------------------------------- /testing/tests/extend.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[test] 4 | fn test_macro_in_block_inheritance() { 5 | #[derive(Template)] 6 | #[template( 7 | source = r#"{% extends "extend_and_import.html" %} 8 | {%- import "macro.html" as m2 -%} 9 | 10 | {%- macro another(param) -%} 11 | 12 | --> {{ param }} 13 | 14 | {%- endmacro -%} 15 | 16 | {% block header -%} 17 | {% call m1::twice(1) %}{% endcall %} 18 | {% call m2::twice(2) %}{% endcall %} 19 | {% call another(3) %}{% endcall %} 20 | {%- endblock -%} 21 | "#, 22 | ext = "txt" 23 | )] 24 | struct A; 25 | 26 | assert_eq!(A.render().unwrap(), "\n\n1 1\n2 2\n--> 3"); 27 | } 28 | 29 | // This test ensures that comments are allowed before `extends` block. 30 | #[test] 31 | fn test_comment_before_extend() { 32 | #[derive(Template)] 33 | #[template(source = r##"{# comment #}{% extends "base.html" %}"##, ext = "txt")] 34 | pub struct X { 35 | title: &'static str, 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /testing/tests/ui/garbled-closing-blocks.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(ext = "txt", source = "{% if cond %-}{% endif %}")] 5 | struct BlockSuppress { 6 | cond: bool, 7 | } 8 | 9 | #[derive(Template)] 10 | #[template(ext = "txt", source = "{% if cond %+}{% endif %}")] 11 | struct BlockPreserve { 12 | cond: bool, 13 | } 14 | 15 | #[derive(Template)] 16 | #[template(ext = "txt", source = "{% if cond %~}{% endif %}")] 17 | struct BlockFold { 18 | cond: bool, 19 | } 20 | 21 | #[derive(Template)] 22 | #[template(ext = "txt", source = "{% if cond %}{% endif %-}")] 23 | struct BlockSuppress2 { 24 | cond: bool, 25 | } 26 | 27 | #[derive(Template)] 28 | #[template(ext = "txt", source = "{% if cond %}{% endif %+}")] 29 | struct BlockPreserve2 { 30 | cond: bool, 31 | } 32 | 33 | #[derive(Template)] 34 | #[template(ext = "txt", source = "{% if cond %}{% endif %~}")] 35 | struct BlockFold2 { 36 | cond: bool, 37 | } 38 | 39 | fn main() {} 40 | -------------------------------------------------------------------------------- /testing/tests/cow_str_implements_fast_writable.rs: -------------------------------------------------------------------------------- 1 | use std::borrow::Cow; 2 | use std::fmt::Display; 3 | 4 | use askama::{FastWritable, Template}; 5 | 6 | #[test] 7 | fn test_cows() { 8 | // This test ensures that Cow is FastWritable. 9 | // Every expression needs to implement fmt::Display, even if the FastWritable path 10 | // is going to be used. 11 | 12 | #[derive(Template)] 13 | #[template(source = "{{ bull }} + {{ cow }} = {{ calf }}", ext = "txt")] 14 | struct Cattle 15 | where 16 | A: FastWritable + Display, 17 | B: FastWritable + Display, 18 | C: FastWritable + Display, 19 | { 20 | bull: A, 21 | cow: B, 22 | calf: C, 23 | } 24 | 25 | let calf = "calf".to_owned(); 26 | let t = Cattle { 27 | bull: Cow::Borrowed("bull"), 28 | cow: Cow::::Owned("cow".to_owned()), 29 | calf: Cow::Borrowed(&calf), 30 | }; 31 | assert_eq!(t.render().unwrap(), "bull + cow = calf"); 32 | } 33 | -------------------------------------------------------------------------------- /testing/tests/ui/macro_default_value.stderr: -------------------------------------------------------------------------------- 1 | error: missing argument when calling macro `thrice`: `param1` 2 | --> InvalidDefault1.html:4:4 3 | "call thrice() -%}{%- endcall -%}" 4 | --> tests/ui/macro_default_value.rs:4:21 5 | | 6 | 4 | #[template(source = "{%- macro thrice(param1, param2=0) -%} 7 | | _____________________^ 8 | 5 | | {{ param1 }} {{ param2 }} 9 | 6 | | {%- endmacro -%} 10 | 7 | | {%- call thrice() -%}{%- endcall -%}", ext = "html")] 11 | | |_____________________________________^ 12 | 13 | error: macro `thrice` expected 2 arguments, found 3 14 | --> InvalidDefault2.html:4:4 15 | "call thrice(1, 2, 3) -%}{%- endcall -%}" 16 | --> tests/ui/macro_default_value.rs:11:21 17 | | 18 | 11 | #[template(source = "{%- macro thrice(param1, param2=0) -%} 19 | | _____________________^ 20 | 12 | | {{ param1 }} {{ param2 }} 21 | 13 | | {%- endmacro -%} 22 | 14 | | {%- call thrice(1, 2, 3) -%}{%- endcall -%}", ext = "html")] 23 | | |____________________________________________^ 24 | -------------------------------------------------------------------------------- /examples/salvo-app/templates/error.html: -------------------------------------------------------------------------------- 1 | {% extends "_layout.html" %} 2 | 3 | {%- block title -%} 4 | {%- match err -%} 5 | {% when AppError::NotFound -%} 404: Not Found 6 | {% when AppError::Extract(_) -%} 422: Unprocessable Entity 7 | {% when AppError::Render(_) -%} 500: Internal Server Error 8 | {%- endmatch -%} 9 | {%- endblock -%} 10 | 11 | {%- block content -%} 12 |

13 | {%- match err -%} 14 | {% when AppError::NotFound -%} 404: Not Found 15 | {% when AppError::Extract(_) -%} 422: Unprocessable Entity 16 | {% when AppError::Render(_) -%} 500: Internal Server Error 17 | {%- endmatch -%} 18 |

19 | 20 | {%- match err -%} 21 | {% when AppError::NotFound -%} 22 | {% when AppError::Extract(_) -%}
{{ err }}
23 | {% when AppError::Render(err) -%}
{{ err }}
24 | {%- endmatch -%} 25 | 26 |

Back to the first page.

27 | {%- endblock -%} 28 | -------------------------------------------------------------------------------- /testing/tests/ui/expr_fn_calls.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_variables)] 2 | 3 | use askama::Template; 4 | 5 | pub fn static_fn(arg: &str) -> &str { arg } 6 | pub fn static_fn2(arg: &str) -> Option<&str> { Some(arg) } 7 | 8 | 9 | #[derive(Template)] 10 | #[template(source = "{{ test_fn(arg = 5) }}", ext = "html")] 11 | struct NamedArgsInRustExprMemberFn; 12 | 13 | impl NamedArgsInRustExprMemberFn { 14 | pub fn test_fn(&self, arg: u64) -> &'static str { 15 | "This is a test" 16 | } 17 | } 18 | 19 | 20 | #[derive(Template)] 21 | #[template(source = r#"{{ self::static_fn(arg = "test") }}"#, ext = "html")] 22 | struct NamedArgsInRustExprStaticCall; 23 | 24 | 25 | #[derive(Template)] 26 | #[template(source = r#"{{ self::static_fn2("test").unwrap(arg = "test") }}"#, ext = "html")] 27 | struct NamedArgsInRustExprStaticCall2; 28 | 29 | 30 | #[derive(Template)] 31 | #[template(source = r#"{% let test = self::static_fn(arg = "test") %}"#, ext = "html")] 32 | struct NamedArgsInRustExprStaticCall3; 33 | 34 | 35 | fn main() {} 36 | -------------------------------------------------------------------------------- /_typos.toml: -------------------------------------------------------------------------------- 1 | [default] 2 | locale = "en-us" 3 | 4 | [files] 5 | extend-exclude = [ 6 | # generated files 7 | "book/ethicalads-theme.css", 8 | "fuzzing/fuzz/artifacts/", 9 | "fuzzing/fuzz/corpus/", 10 | "target/", 11 | "askama_parser/tests/*.txt", 12 | "testing/templates/fuzzed-*", 13 | # we copied the files verbatim including any typos :) 14 | "askama_parser/benches", 15 | "askama_derive/benches", 16 | # filler texts 17 | "*/benches/strings.inc", 18 | # too many false positives 19 | "testing/tests/gen_ws_tests.py", 20 | # truncated output 21 | "testing/tests/ui/*.stderr", 22 | # minimized file full of regular expressions that trip up the typo checker 23 | "book/theme/highlight.js", 24 | ] 25 | 26 | [default.extend-words] 27 | # It's actually called that in the ASCII standard 28 | Enquiry = "Enquiry" 29 | 30 | # French words 31 | exemple = "exemple" 32 | existant = "existant" 33 | 34 | # used in tests 35 | Ba = "Ba" 36 | fo = "fo" 37 | Fo = "Fo" 38 | sur = "sur" 39 | -------------------------------------------------------------------------------- /askama_parser/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "askama_parser" 3 | version = "0.15.0" 4 | description = "Parser for Askama templates" 5 | documentation = "https://docs.rs/askama" 6 | keywords = ["markup", "template", "jinja2", "html"] 7 | categories = ["template-engine"] 8 | homepage = "https://github.com/askama-rs/askama" 9 | repository = "https://github.com/askama-rs/askama" 10 | license = "MIT OR Apache-2.0" 11 | readme = "README.md" 12 | edition = "2024" 13 | rust-version = "1.88" 14 | 15 | [package.metadata.docs.rs] 16 | all-features = true 17 | rustdoc-args = ["--generate-link-to-definition", "--cfg=docsrs"] 18 | 19 | [[bench]] 20 | name = "from_str" 21 | harness = false 22 | 23 | [dependencies] 24 | rustc-hash = "2.0.0" 25 | serde = { version = "1.0", optional = true } 26 | serde_derive = { version = "1.0", optional = true } 27 | unicode-ident = "1.0.12" 28 | winnow = { version = "0.7.0", features = ["simd"] } 29 | 30 | [dev-dependencies] 31 | criterion = "0.8" 32 | 33 | [features] 34 | config = ["dep:serde", "dep:serde_derive"] 35 | -------------------------------------------------------------------------------- /testing/tests/ui/ambiguous-ws-raw.stderr: -------------------------------------------------------------------------------- 1 | error: ambiguous whitespace stripping 2 | use `{#- -#}` to apply the same whitespace stripping on both sides 3 | --> :1:1 4 | "{#-#}Y" 5 | --> tests/ui/ambiguous-ws-raw.rs:4:21 6 | | 7 | 4 | #[template(source = r#"X{#-#}Y"#, ext = "html")] 8 | | ^^^^^^^^^^^^ 9 | 10 | error: ambiguous whitespace stripping 11 | use `{#+ +#}` to apply the same whitespace stripping on both sides 12 | --> :1:1 13 | "{#+#}Y" 14 | --> tests/ui/ambiguous-ws-raw.rs:8:21 15 | | 16 | 8 | #[template(source = r#"X{#+#}Y"#, ext = "html")] 17 | | ^^^^^^^^^^^^ 18 | 19 | error: ambiguous whitespace stripping 20 | use `{#~ ~#}` to apply the same whitespace stripping on both sides 21 | --> :1:1 22 | "{#~#}Y" 23 | --> tests/ui/ambiguous-ws-raw.rs:12:21 24 | | 25 | 12 | #[template(source = r#"X{#~#}Y"#, ext = "html")] 26 | | ^^^^^^^^^^^^ 27 | -------------------------------------------------------------------------------- /testing/tests/ui/let_destructuring_has_rest.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | struct X { 4 | a: u32, 5 | b: u32, 6 | } 7 | 8 | #[derive(Template)] 9 | #[template(source = " 10 | {%- if let X { a, .., } = x -%}hello {{ a }}{%- endif -%} 11 | ", ext = "html")] 12 | struct T1 { 13 | x: X, 14 | } 15 | 16 | #[derive(Template)] 17 | #[template(source = " 18 | {%- if let X { a .. } = x -%}hello {{ a }}{%- endif -%} 19 | ", ext = "html")] 20 | struct T2 { 21 | x: X, 22 | } 23 | 24 | #[derive(Template)] 25 | #[template(source = " 26 | {%- if let X { a, 1 } = x -%}hello {{ a }}{%- endif -%} 27 | ", ext = "html")] 28 | struct T3 { 29 | x: X, 30 | } 31 | 32 | #[derive(Template)] 33 | #[template(source = " 34 | {%- if let X { a, .., b } = x -%}hello {{ a }}{%- endif -%} 35 | ", ext = "html")] 36 | struct T4 { 37 | x: X, 38 | } 39 | 40 | #[derive(Template)] 41 | #[template(source = " 42 | {%- if let X { .., b } = x -%}hello {{ a }}{%- endif -%} 43 | ", ext = "html")] 44 | struct T5 { 45 | x: X, 46 | } 47 | 48 | fn main() {} 49 | -------------------------------------------------------------------------------- /testing/tests/ui/macro-args-hashtag.stderr: -------------------------------------------------------------------------------- 1 | error: wrong lifetime format 2 | --> :1:5 3 | "'r#}}}" 4 | --> tests/ui/macro-args-hashtag.rs:8:14 5 | | 6 | 8 | source = r###"{{z!{'r#}}}"###, 7 | | ^^^^^^^^^^^^^^^^^^^^ 8 | 9 | error: wrong lifetime format 10 | --> :1:5 11 | "'r# y}}}" 12 | --> tests/ui/macro-args-hashtag.rs:15:14 13 | | 14 | 15 | source = r###"{{z!{'r# y}}}"###, 15 | | ^^^^^^^^^^^^^^^^^^^^^^ 16 | 17 | error: a non-raw lifetime cannot be named like an existing keyword 18 | --> :1:5 19 | "'break}}}" 20 | --> tests/ui/macro-args-hashtag.rs:22:14 21 | | 22 | 22 | source = r###"{{z!{'break}}}"###, 23 | | ^^^^^^^^^^^^^^^^^^^^^^^ 24 | 25 | error: `self` cannot be a raw lifetime 26 | --> :1:5 27 | "'r#self}}}" 28 | --> tests/ui/macro-args-hashtag.rs:29:14 29 | | 30 | 29 | source = r###"{{z!{'r#self}}}"###, 31 | | ^^^^^^^^^^^^^^^^^^^^^^^^ 32 | -------------------------------------------------------------------------------- /testing/tests/ui/vars.stderr: -------------------------------------------------------------------------------- 1 | error: you can only use the `mut` keyword with a variable name 2 | --> :2:7 3 | "mut (a, b) = (1, 2) %}\n" 4 | --> tests/ui/vars.rs:6:21 5 | | 6 | 6 | #[template(source = r#" 7 | | _____________________^ 8 | 7 | | {% let mut (a, b) = (1, 2) %} 9 | 8 | | "#, ext = "html")] 10 | | |__^ 11 | 12 | error: you can only use the `mut` keyword with a variable name 13 | --> :2:7 14 | "mut [a, b] = [1, 2] %}\n" 15 | --> tests/ui/vars.rs:12:21 16 | | 17 | 12 | #[template(source = r#" 18 | | _____________________^ 19 | 13 | | {% let mut [a, b] = [1, 2] %} 20 | 14 | | "#, ext = "html")] 21 | | |__^ 22 | 23 | error: you can only use the `mut` keyword with a variable name 24 | --> :2:7 25 | "mut Some(a) = Some(\"a\") %}\n" 26 | --> tests/ui/vars.rs:18:21 27 | | 28 | 18 | #[template(source = r#" 29 | | _____________________^ 30 | 19 | | {% let mut Some(a) = Some("a") %} 31 | 20 | | "#, ext = "html")] 32 | | |__^ 33 | -------------------------------------------------------------------------------- /examples/axum-app/README.md: -------------------------------------------------------------------------------- 1 | # askama + axum example web app 2 | 3 | This is a simple web application that uses askama as template engine, and 4 | [axum](https://crates.io/crates/axum) as web framework. 5 | It lets the user of the web page select a display language, and asks for their name. 6 | The example shows the interaction between both projects, and serves as an example to use 7 | basic askama features such as base templates to a unified layout skeleton for your page, 8 | and less boilerplate in your template code. 9 | 10 | To run the example execute `cargo run` in this folder. 11 | Once the project is running, open in your browser. 12 | To gracefully shut does the server, type ctrl+C in your terminal. 13 | 14 | The files of the project contain comments for you to read. 15 | The recommended reading order is "templates/_layout.html", "templates/index.html", 16 | "Cargo.toml", "src/main.rs". Also please have a look at our [book](https://askama.readthedocs.io/), 17 | which explains askama's features in greater detail. 18 | -------------------------------------------------------------------------------- /examples/poem-app/README.md: -------------------------------------------------------------------------------- 1 | # askama + poem example web app 2 | 3 | This is a simple web application that uses askama as template engine, and 4 | [poem](https://crates.io/crates/poem) as web framework. 5 | It lets the user of the web page select a display language, and asks for their name. 6 | The example shows the interaction between both projects, and serves as an example to use 7 | basic askama features such as base templates to a unified layout skeleton for your page, 8 | and less boilerplate in your template code. 9 | 10 | To run the example execute `cargo run` in this folder. 11 | Once the project is running, open in your browser. 12 | To gracefully shut does the server, type ctrl+C in your terminal. 13 | 14 | The files of the project contain comments for you to read. 15 | The recommended reading order is "templates/_layout.html", "templates/index.html", 16 | "Cargo.toml", "src/main.rs". Also please have a look at our [book](https://askama.readthedocs.io/), 17 | which explains askama's features in greater detail. 18 | -------------------------------------------------------------------------------- /examples/warp-app/README.md: -------------------------------------------------------------------------------- 1 | # askama + warp example web app 2 | 3 | This is a simple web application that uses askama as template engine, and 4 | [warp](https://crates.io/crates/warp) as web framework. 5 | It lets the user of the web page select a display language, and asks for their name. 6 | The example shows the interaction between both projects, and serves as an example to use 7 | basic askama features such as base templates to a unified layout skeleton for your page, 8 | and less boilerplate in your template code. 9 | 10 | To run the example execute `cargo run` in this folder. 11 | Once the project is running, open in your browser. 12 | To gracefully shut does the server, type ctrl+C in your terminal. 13 | 14 | The files of the project contain comments for you to read. 15 | The recommended reading order is "templates/_layout.html", "templates/index.html", 16 | "Cargo.toml", "src/main.rs". Also please have a look at our [book](https://askama.readthedocs.io/), 17 | which explains askama's features in greater detail. 18 | -------------------------------------------------------------------------------- /testing/tests/ui/no-block.stderr: -------------------------------------------------------------------------------- 1 | error: cannot find block `a` 2 | --> tests/ui/no-block.rs:7:13 3 | | 4 | 7 | block = "a" 5 | | ^^^ 6 | 7 | error: cannot find block `a` 8 | --> tests/ui/no-block.rs:12:43 9 | | 10 | 12 | #[template(path = "no-block.txt", block = "a")] 11 | | ^^^ 12 | 13 | error: cannot find block `a` 14 | --> tests/ui/no-block.rs:16:56 15 | | 16 | 16 | #[template(path = "no-block-with-include.txt", block = "a")] 17 | | ^^^ 18 | 19 | error: cannot find block `a` 20 | --> tests/ui/no-block.rs:20:64 21 | | 22 | 20 | #[template(path = "no-block-with-include-times-2.txt", block = "a")] 23 | | ^^^ 24 | 25 | error: cannot find block `a` 26 | --> tests/ui/no-block.rs:24:62 27 | | 28 | 24 | #[template(path = "no-block-with-base-template.txt", block = "a")] 29 | | ^^^ 30 | -------------------------------------------------------------------------------- /examples/salvo-app/README.md: -------------------------------------------------------------------------------- 1 | # askama + salvo example web app 2 | 3 | This is a simple web application that uses askama as template engine, and 4 | [salvo](https://crates.io/crates/salvo) as web framework. 5 | It lets the user of the web page select a display language, and asks for their name. 6 | The example shows the interaction between both projects, and serves as an example to use 7 | basic askama features such as base templates to a unified layout skeleton for your page, 8 | and less boilerplate in your template code. 9 | 10 | To run the example execute `cargo run` in this folder. 11 | Once the project is running, open in your browser. 12 | To gracefully shut does the server, type ctrl+C in your terminal. 13 | 14 | The files of the project contain comments for you to read. 15 | The recommended reading order is "templates/_layout.html", "templates/index.html", 16 | "Cargo.toml", "src/main.rs". Also please have a look at our [book](https://askama.readthedocs.io/), 17 | which explains askama's features in greater detail. 18 | -------------------------------------------------------------------------------- /examples/rocket-app/README.md: -------------------------------------------------------------------------------- 1 | # askama + rocket example web app 2 | 3 | This is a simple web application that uses askama as template engine, and 4 | [rocket](https://crates.io/crates/rocket) as web framework. 5 | It lets the user of the web page select a display language, and asks for their name. 6 | The example shows the interaction between both projects, and serves as an example to use 7 | basic askama features such as base templates to a unified layout skeleton for your page, 8 | and less boilerplate in your template code. 9 | 10 | To run the example execute `cargo run` in this folder. 11 | Once the project is running, open in your browser. 12 | To gracefully shut does the server, type ctrl+C in your terminal. 13 | 14 | The files of the project contain comments for you to read. 15 | The recommended reading order is "templates/_layout.html", "templates/index.html", 16 | "Cargo.toml", "src/main.rs". Also please have a look at our [book](https://askama.readthedocs.io/), 17 | which explains askama's features in greater detail. 18 | -------------------------------------------------------------------------------- /examples/actix-web-app/README.md: -------------------------------------------------------------------------------- 1 | # askama + actix-web example web app 2 | 3 | This is a simple web application that uses askama as template engine, and 4 | [actix-web](https://crates.io/crates/actix-web) as web framework. 5 | It lets the user of the web page select a display language, and asks for their name. 6 | The example shows the interaction between both projects, and serves as an example to use 7 | basic askama features such as base templates to a unified layout skeleton for your page, 8 | and less boilerplate in your template code. 9 | 10 | To run the example execute `cargo run` in this folder. 11 | Once the project is running, open in your browser. 12 | To gracefully shut does the server, type ctrl+C in your terminal. 13 | 14 | The files of the project contain comments for you to read. 15 | The recommended reading order is "templates/_layout.html", "templates/index.html", 16 | "Cargo.toml", "src/main.rs". Also please have a look at our [book](https://askama.readthedocs.io/), 17 | which explains askama's features in greater detail. 18 | -------------------------------------------------------------------------------- /askama_parser/benches/librustdoc/short_item_info.html: -------------------------------------------------------------------------------- 1 | {% match self %} 2 | {% when Self::Deprecation with { message } %} 3 |
{# #} 4 | 👎 {# #} 5 | {{message|safe}} {# #} 6 |
{# #} 7 | {% when Self::Unstable with { feature, tracking } %} 8 |
{# #} 9 | 🔬 {# #} 10 | {# #} 11 | This is a nightly-only experimental API. ({# #} 12 | {{feature}} {# #} 13 | {% match tracking %} 14 | {% when Some with ((url, num)) %} 15 |  #{{num}} {# #} 16 | {% when None %} 17 | {% endmatch %} 18 | ) {# #} 19 | {# #} 20 |
{# #} 21 | {% when Self::Portability with { message } %} 22 |
{{message|safe}}
{# #} 23 | {% endmatch %} 24 | -------------------------------------------------------------------------------- /testing/tests/ui/values.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | ext = "html", 6 | source = r#"{% if let Ok(x) = "a"|value %}{% endif %}"#, 7 | )] 8 | struct A; 9 | 10 | #[derive(Template)] 11 | #[template( 12 | ext = "html", 13 | source = r#"{% if let Ok(x) = "a"|value:: %}{% endif %}"#, 14 | )] 15 | struct B; 16 | 17 | #[derive(Template)] 18 | #[template( 19 | ext = "html", 20 | source = r#"{% if let Ok(x) = askama::get_value("a") %}{% endif %}"#, 21 | )] 22 | struct C; 23 | 24 | #[derive(Template)] 25 | #[template( 26 | ext = "html", 27 | source = r#"{% if let Ok(x) = askama::get_value::("a") %}{% endif %}"#, 28 | )] 29 | struct D; 30 | 31 | #[derive(Template)] 32 | #[template( 33 | ext = "html", 34 | source = r#"{% if let Ok(x) = askama::get_value::() %}{% endif %}"#, 35 | )] 36 | struct E; 37 | 38 | #[derive(Template)] 39 | #[template( 40 | ext = "html", 41 | source = r#"{% if let Ok(x) = askama::get_value::("a", "b") %}{% endif %}"#, 42 | )] 43 | struct F; 44 | 45 | fn main() {} 46 | -------------------------------------------------------------------------------- /examples/rocket-app/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "actix-web-app" 3 | version = "0.14.0" 4 | edition = "2021" 5 | license = "MIT OR Apache-2.0" 6 | publish = false 7 | 8 | # This is an example application that uses both askama as template engine, 9 | # and rocket as your web-framework. 10 | [dependencies] 11 | askama = { version = "0.15.0", path = "../../askama" } 12 | rocket = "0.5.1" 13 | 14 | # strum is used to parse and serialize information between web requests, 15 | # e.g. to share the selected display language. 16 | strum = { version = "0.27.1", features = ["derive"] } 17 | 18 | # These depenendies are simply used for a better user experience, having access logs in the 19 | # console, and error messages if anything goes wrong, e.g. if the port is already in use. 20 | displaydoc = "0.2.5" 21 | env_logger = "0.11.6" 22 | pretty-error-debug = "0.3.1" 23 | thiserror = "2.0.11" 24 | 25 | # In a real application you would not need this section. It is only used in here, so that this 26 | # example can have a more lenient MSRV (minimum supported rust version) than askama as a whole. 27 | [workspace] 28 | members = ["."] 29 | -------------------------------------------------------------------------------- /askama_parser/benches/librustdoc/print_item.html: -------------------------------------------------------------------------------- 1 |
{# #} 2 |

3 | {{typ}} 4 | {# The breadcrumbs of the item path, like std::string #} 5 | {% for component in path_components %} 6 | {{component.name}}:: 7 | {% endfor %} 8 | {{name}} {# #} 9 | {# #} 12 |

{# #} 13 | 14 | {% if !stability_since_raw.is_empty() %} 15 | {{ stability_since_raw|safe +}} · {#+ #} 16 | {% endif %} 17 | {% match src_href %} 18 | {% when Some with (href) %} 19 | source · {#+ #} 20 | {% else %} 21 | {% endmatch %} 22 | {# #} 25 | {# #} 26 |
{# #} 27 | -------------------------------------------------------------------------------- /testing/tests/ui/end-block.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | ext = "html", 6 | source = "{% if x %}{% if x %}{% endif %}", 7 | )] 8 | struct EndIf { 9 | x: bool, 10 | } 11 | 12 | #[derive(Template)] 13 | #[template( 14 | ext = "html", 15 | source = "{% if x %}", 16 | )] 17 | struct EndIf2 { 18 | x: bool, 19 | } 20 | 21 | #[derive(Template)] 22 | #[template( 23 | ext = "html", 24 | source = "{% match x %}", 25 | )] 26 | struct EndMatch { 27 | x: bool, 28 | } 29 | 30 | #[derive(Template)] 31 | #[template( 32 | ext = "html", 33 | source = "{% for a in x %}", 34 | )] 35 | struct EndFor { 36 | x: [u32; 2], 37 | } 38 | 39 | #[derive(Template)] 40 | #[template( 41 | ext = "html", 42 | source = "{% macro bla %}", 43 | )] 44 | struct EndMacro; 45 | 46 | #[derive(Template)] 47 | #[template( 48 | ext = "html", 49 | source = "{% filter bla %}", 50 | )] 51 | struct EndFilter; 52 | 53 | #[derive(Template)] 54 | #[template( 55 | ext = "html", 56 | source = "{% block bla %}", 57 | )] 58 | struct EndBlock; 59 | 60 | fn main() { 61 | } 62 | -------------------------------------------------------------------------------- /testing/tests/declare.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | // This test ensures that the `decl` keyword works as expected. 4 | #[test] 5 | fn decl() { 6 | #[derive(Template)] 7 | #[template( 8 | source = r#"{%- decl x -%} 9 | {%- if y -%} 10 | {%- let x = String::new() %} 11 | {%- else -%} 12 | {%- let x = format!("blob") %} 13 | {%- endif -%} 14 | {{ x }}"#, 15 | ext = "html" 16 | )] 17 | struct A { 18 | y: bool, 19 | } 20 | 21 | assert_eq!(A { y: false }.render().unwrap(), "blob"); 22 | assert_eq!(A { y: true }.render().unwrap(), ""); 23 | } 24 | 25 | // Same as `decl` except with the `declare` keyword. 26 | #[test] 27 | fn declare() { 28 | #[derive(Template)] 29 | #[template( 30 | source = r#"{%- declare x -%} 31 | {%- if y -%} 32 | {%- let x = String::new() %} 33 | {%- else -%} 34 | {%- let x = format!("blob") %} 35 | {%- endif -%} 36 | {{ x }}"#, 37 | ext = "html" 38 | )] 39 | struct A { 40 | y: bool, 41 | } 42 | 43 | assert_eq!(A { y: false }.render().unwrap(), "blob"); 44 | assert_eq!(A { y: true }.render().unwrap(), ""); 45 | } 46 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2020 Dirkjan Ochtman 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /askama_parser/benches/librustdoc/item_union.html: -------------------------------------------------------------------------------- 1 |

 2 |     {{ self.render_attributes_in_pre()|safe }}
 3 |     {{ self.render_union()|safe }}
 4 | 
5 | {{ self.document()|safe }} 6 | {% if self.fields_iter().peek().is_some() %} 7 |

{# #} 8 | Fields§ {# #} 9 |

10 | {% for (field, ty) in self.fields_iter() %} 11 | {% let name = field.name.expect("union field name") %} 12 | {# #} 14 | § {# #} 15 | {{ name }}: {{+ self.print_ty(ty)|safe }} {# #} 16 | 17 | {% if let Some(stability_class) = self.stability_field(field) %} 18 | 19 | {% endif %} 20 | {{ self.document_field(field)|safe }} 21 | {% endfor %} 22 | {% endif %} 23 | {{ self.render_assoc_items()|safe }} 24 | {{ self.document_type_layout()|safe }} 25 | -------------------------------------------------------------------------------- /testing/tests/size_hint.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | macro_rules! test_size { 4 | ($source:literal, $expected:expr) => {{ 5 | #[derive(Template)] 6 | #[allow(dead_code)] 7 | #[template(source = $source, ext = "txt")] 8 | struct T(bool); 9 | 10 | assert_eq!(T::SIZE_HINT, $expected); 11 | }}; 12 | } 13 | 14 | #[test] 15 | fn test_cond_size_hint() { 16 | test_size!("{% if self.0 %}12345{% else %}12345{% endif %}", 10); 17 | } 18 | 19 | #[test] 20 | fn test_match_size_hint() { 21 | test_size!( 22 | "{% match self.0 %}{% when true %}12345{% else %}12345{% endmatch %}", 23 | 5 24 | ); 25 | } 26 | 27 | #[test] 28 | fn test_loop_size_hint() { 29 | test_size!("{% for i in 0..1 %}12345{% endfor %}", 7); 30 | } 31 | 32 | #[test] 33 | fn test_block_size_hint() { 34 | #[derive(Template)] 35 | #[template(path = "size-child.txt")] 36 | struct T; 37 | 38 | assert_eq!(T::SIZE_HINT, 3); 39 | } 40 | 41 | #[test] 42 | fn test_super_size_hint() { 43 | #[derive(Template)] 44 | #[template(path = "size-child-super.txt")] 45 | struct T; 46 | 47 | assert_eq!(T::SIZE_HINT, 5); 48 | } 49 | -------------------------------------------------------------------------------- /testing/tests/ui/invalid_array_repeat.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(source = r#"{% let my_arr = [;] %}"#, ext = "txt")] 5 | struct Empty; 6 | 7 | #[derive(Template)] 8 | #[template(source = r#"{% let my_arr = [;0] %}"#, ext = "txt")] 9 | struct EmptyElement; 10 | 11 | #[derive(Template)] 12 | #[template(source = r#"{% let my_arr = ["";] %}"#, ext = "txt")] 13 | struct EmptyCount; 14 | 15 | #[derive(Template)] 16 | #[template(source = r#"{% let my_arr = [,;] %}"#, ext = "txt")] 17 | struct StrayElementComma; 18 | 19 | #[derive(Template)] 20 | #[template(source = r#"{% let my_arr = [; 10, 10] %}"#, ext = "txt")] 21 | struct StrayCountComma; 22 | 23 | #[derive(Template)] 24 | #[template(source = r#"{% let my_arr = [,;,] %}"#, ext = "txt")] 25 | struct StrayCommas; 26 | 27 | #[derive(Template)] 28 | #[template(source = r#"{% let my_arr = ["";10;10] %}"#, ext = "txt")] 29 | struct MultipleSemicolons; 30 | 31 | #[derive(Template)] 32 | #[template( 33 | source = r#"{{ [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ }}"#, 34 | ext = "txt" 35 | )] 36 | struct RecursionLimit; 37 | 38 | fn main() {} 39 | -------------------------------------------------------------------------------- /testing/tests/ui/macro-named-crate.rs: -------------------------------------------------------------------------------- 1 | // The names `crate`, `self`, `Self` and `super` cannot be raw identifiers, so they can never 2 | // be valid macro names. 3 | 4 | #[derive(askama::Template)] 5 | #[template(source = "{{ crate!() }}", ext = "txt")] 6 | struct MacroCrate; 7 | 8 | #[derive(askama::Template)] 9 | #[template(source = "{{ self!() }}", ext = "txt")] 10 | struct MacroSelf; 11 | 12 | #[derive(askama::Template)] 13 | #[template(source = "{{ Self!() }}", ext = "txt")] 14 | struct MacroSelfType; 15 | 16 | #[derive(askama::Template)] 17 | #[template(source = "{{ super!() }}", ext = "txt")] 18 | struct MacroSuper; 19 | 20 | #[derive(askama::Template)] 21 | #[template(source = "{{ some::path::crate!() }}", ext = "txt")] 22 | struct MacroPathCrate; 23 | 24 | #[derive(askama::Template)] 25 | #[template(source = "{{ some::path::self!() }}", ext = "txt")] 26 | struct MacroPathSelf; 27 | 28 | #[derive(askama::Template)] 29 | #[template(source = "{{ some::path::Self!() }}", ext = "txt")] 30 | struct MacroPathSelfType; 31 | 32 | #[derive(askama::Template)] 33 | #[template(source = "{{ some::path::super!() }}", ext = "txt")] 34 | struct MacroPathSuper; 35 | 36 | fn main() { 37 | } 38 | -------------------------------------------------------------------------------- /testing/tests/ui/macro-recursion.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | source = " 6 | {% macro one %}{% call one %}{% endcall %}{% endmacro %} 7 | {% call one %}{% endcall %} 8 | ", 9 | ext = "html" 10 | )] 11 | struct Direct; 12 | 13 | #[derive(Template)] 14 | #[template( 15 | source = " 16 | {% macro one %}{% call two %}{% endcall %}{% endmacro %} 17 | {% macro two %}{% call three %}{% endcall %}{% endmacro %} 18 | {% macro three %}{% call four %}{% endcall %}{% endmacro %} 19 | {% macro four %}{% call five %}{% endcall %}{% endmacro %} 20 | {% macro five %}{% call one %}{% endcall %}{% endmacro %} 21 | {% call one %}{% endcall %} 22 | ", 23 | ext = "html" 24 | )] 25 | struct Indirect; 26 | 27 | #[derive(Template)] 28 | #[template( 29 | source = r#" 30 | {% import "macro-recursion-1.html" as next %} 31 | {% macro some_macro %} 32 | {% call next::some_macro %}{% endcall %} 33 | {% endmacro %} 34 | {% call some_macro %}{% endcall %} 35 | "#, 36 | ext = "html" 37 | )] 38 | struct AcrossImports; 39 | 40 | fn main() { 41 | } 42 | -------------------------------------------------------------------------------- /testing/templates/if-coerce.html: -------------------------------------------------------------------------------- 1 | {% macro foo(b) -%} 2 | {% if b %}t{% else %}f{% endif -%} 3 | {% endmacro -%} 4 | 5 | {% macro bar(b) -%} 6 | {%- call foo(b) -%}{%- endcall -%} 7 | {% endmacro -%} 8 | 9 | {% macro baz(b) -%} 10 | {%- call bar(b) -%}{%- endcall -%} 11 | {% endmacro -%} 12 | 13 | {% macro qux(b) -%} 14 | {%- call baz(b) -%}{%- endcall -%} 15 | {% endmacro -%} 16 | 17 | {%- call foo(false) -%}{%- endcall -%} 18 | {%- call bar(true) -%}{%- endcall -%} 19 | {%- call baz(false) -%}{%- endcall -%} 20 | {%- call qux(true) -%}{%- endcall -%} 21 | 22 | {%- call qux(true && false) -%}{%- endcall -%} 23 | {%- call qux(false || true) -%}{%- endcall -%} 24 | 25 | {%- call qux(self.t) -%}{%- endcall -%} 26 | {%- call qux(self.f) -%}{%- endcall -%} 27 | {%- call qux(self.f || self.t) -%}{%- endcall -%} 28 | 29 | {%- if false -%} 30 | if 31 | {%- else if false || true -%} 32 | elseif 33 | {%- else -%} 34 | else 35 | {%- endif -%} 36 | 37 | {%- if true && false -%} 38 | if 39 | {%- else if false -%} 40 | elseif 41 | {%- else -%} 42 | else 43 | {%- endif -%} 44 | 45 | {%- if false || true -%} 46 | if 47 | {%- else if (true && false) -%} 48 | elseif 49 | {%- else -%} 50 | else 51 | {%- endif -%} 52 | -------------------------------------------------------------------------------- /testing/tests/render_in_place.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[test] 4 | fn test_render_in_place() { 5 | #[derive(Template)] 6 | #[template(path = "render_in_place.html")] 7 | struct RenderInPlace<'a> { 8 | s1: SectionOne<'a>, 9 | s2: SectionTwo<'a>, 10 | s3: &'a Vec>, 11 | } 12 | 13 | #[derive(Template)] 14 | #[template(source = "A={{ a }}\nB={{ b }}", ext = "html")] 15 | struct SectionOne<'a> { 16 | a: &'a str, 17 | b: &'a str, 18 | } 19 | 20 | #[derive(Template)] 21 | #[template(source = "C={{ c }}\nD={{ d }}", ext = "html")] 22 | struct SectionTwo<'a> { 23 | c: &'a str, 24 | d: &'a str, 25 | } 26 | 27 | let t = RenderInPlace { 28 | s1: SectionOne { a: "A", b: "B" }, 29 | s2: SectionTwo { c: "C", d: "D" }, 30 | s3: &vec![ 31 | SectionOne { a: "1", b: "2" }, 32 | SectionOne { a: "A", b: "B" }, 33 | SectionOne { a: "a", b: "b" }, 34 | ], 35 | }; 36 | assert_eq!( 37 | t.render().unwrap(), 38 | "Section 1: A=A\nB=B\nSection 2: C=C\nD=D\nSection 3 for:\n* A=1\nB=2\n* A=A\nB=B\n* A=a\nB=b\n" 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /testing/tests/ui/enum.stderr: -------------------------------------------------------------------------------- 1 | error: template attribute `askama` can only be used on the `enum`, not its variants 2 | --> tests/ui/enum.rs:5:43 3 | | 4 | 5 | #[template(ext = "txt", source = "🫨", askama = askama)] 5 | | ^^^^^^ 6 | 7 | error: template attribute `askama` can only be used on the `enum`, not its variants 8 | --> tests/ui/enum.rs:11:43 9 | | 10 | 11 | #[template(ext = "txt", source = "🫏", askama = askama)] 11 | | ^^^^^^ 12 | 13 | error: template attribute `askama` can only be used on the `enum`, not its variants 14 | --> tests/ui/enum.rs:20:43 15 | | 16 | 20 | #[template(ext = "txt", source = "🪻", askama = askama)] 17 | | ^^^^^^ 18 | 19 | error: template attribute `askama` can only be used on the `enum`, not its variants 20 | --> tests/ui/enum.rs:27:43 21 | | 22 | 27 | #[template(ext = "txt", source = "🫠", askama = askama)] 23 | | ^^^^^^ 24 | 25 | error: cannot find block `c` 26 | --> tests/ui/enum.rs:48:24 27 | | 28 | 48 | #[template(block = "c")] 29 | | ^^^ 30 | -------------------------------------------------------------------------------- /testing/tests/ui/comments-in-macro-calls.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | // Regression test for . 4 | 5 | #[derive(Template)] 6 | #[template(ext = "html", source = "{{ e!(// hello) }}")] 7 | struct LineComment; 8 | 9 | #[derive(Template)] 10 | #[template(ext = "html", source = "{{ e!(// hello)\n}}")] 11 | struct LineComment2; 12 | 13 | #[derive(Template)] 14 | #[template(ext = "html", source = "{{ e!(/* hello) }}")] 15 | struct BlockComment; 16 | 17 | #[derive(Template)] 18 | #[template(ext = "html", source = "{{ e!(/// hello) }}")] 19 | struct OuterLineDoc; 20 | 21 | #[derive(Template)] 22 | #[template(ext = "html", source = "{{ e!(/// hello)\n}}")] 23 | struct OuterLineDoc2; 24 | 25 | #[derive(Template)] 26 | #[template(ext = "html", source = "{{ e!(/** hello) }}")] 27 | struct OuterBlockDoc; 28 | 29 | #[derive(Template)] 30 | #[template(ext = "html", source = "{{ e!(//! hello) }}")] 31 | struct InnerLineDoc; 32 | 33 | #[derive(Template)] 34 | #[template(ext = "html", source = "{{ e!(//! hello)\n}}")] 35 | struct InnerLineDoc2; 36 | 37 | #[derive(Template)] 38 | #[template(ext = "html", source = "{{ e!(/*! hello) }}")] 39 | struct InnerBlockDoc; 40 | 41 | fn main() {} 42 | -------------------------------------------------------------------------------- /testing/tests/blocks.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Display; 2 | 3 | use askama::Template; 4 | 5 | #[test] 6 | fn test_blocks() { 7 | #[derive(Template)] 8 | #[template( 9 | ext = "txt", 10 | source = " 11 | {%- block first -%} first=<{{first}}> {%- endblock -%} 12 | {%- block second -%} second=<{{second}}> {%- endblock -%} 13 | {%- block third -%} third=<{{third}}> {%- endblock -%} 14 | {%- block fail -%} better luck next time {%- endblock -%} 15 | ", 16 | block = "fail", 17 | blocks = ["first", "second", "third"] 18 | )] 19 | struct WithBlocks<'a, S: Display, T> 20 | where 21 | T: Display, 22 | { 23 | first: &'a str, 24 | second: S, 25 | third: &'a T, 26 | } 27 | 28 | let tmpl = WithBlocks { 29 | first: "number one", 30 | second: 2, 31 | third: &"bronze", 32 | }; 33 | 34 | assert_eq!(tmpl.as_first().render().unwrap(), "first="); 35 | assert_eq!(tmpl.as_second().render().unwrap(), "second=<2>"); 36 | assert_eq!(tmpl.as_third().render().unwrap(), "third="); 37 | assert_eq!(tmpl.render().unwrap(), "better luck next time"); 38 | } 39 | -------------------------------------------------------------------------------- /askama_macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "askama_macros" 3 | version = "0.15.0" 4 | description = "Procedural macro package for Askama" 5 | homepage = "https://github.com/askama-rs/askama" 6 | repository = "https://github.com/askama-rs/askama" 7 | license = "MIT OR Apache-2.0" 8 | readme = "README.md" 9 | edition = "2024" 10 | rust-version = "1.88" 11 | 12 | [package.metadata.docs.rs] 13 | all-features = true 14 | rustdoc-args = ["--generate-link-to-definition", "--cfg=docsrs"] 15 | 16 | [lib] 17 | proc-macro = true 18 | 19 | [dependencies] 20 | askama_derive = { package = "askama_derive", path = "../askama_derive", version = "=0.15.0", default-features = false, features = ["external-sources", "proc-macro"] } 21 | 22 | [features] 23 | default = ["config", "derive", "std", "urlencode"] 24 | full = ["default", "code-in-doc", "serde_json"] 25 | 26 | alloc = ["askama_derive/alloc"] 27 | code-in-doc = ["askama_derive/code-in-doc"] 28 | config = ["askama_derive/config"] 29 | nightly-spans = ["askama_derive/nightly-spans"] 30 | serde_json = ["askama_derive/serde_json"] 31 | std = ["askama_derive/std"] 32 | urlencode = ["askama_derive/urlencode"] 33 | 34 | # Unused, but we want to have the same features as `askama`. 35 | derive = [] 36 | -------------------------------------------------------------------------------- /testing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "askama_testing" 3 | version = "0.15.0" 4 | authors = ["askama-rs developers"] 5 | edition = "2024" 6 | rust-version = "1.88" 7 | publish = false 8 | 9 | [[bench]] 10 | name = "all" 11 | harness = false 12 | 13 | [dependencies] 14 | askama = { path = "../askama", version = "0.15.0" } 15 | 16 | serde_json = { version = "1.0", optional = true } 17 | 18 | # intentionally shadow the name `::core` to test if the generated code still works fine 19 | core = { package = "intentionally-empty", version = "1.0.0" } 20 | 21 | [dev-dependencies] 22 | askama = { path = "../askama", version = "0.15.0", features = ["code-in-doc", "serde_json"] } 23 | askama_parser = { path = "../askama_parser", version = "0.15.0" } 24 | 25 | assert_matches = "1.5.0" 26 | criterion = "0.8" 27 | pulldown-cmark = "0.13" 28 | trybuild = "1.0.100" 29 | 30 | [features] 31 | default = ["code-in-doc", "serde_json"] 32 | code-in-doc = ["askama/code-in-doc"] 33 | nightly-spans = ["askama/nightly-spans"] 34 | serde_json = ["dep:serde_json", "askama/serde_json"] 35 | 36 | [lints.rust] 37 | # Set in `build.rs` if we are compiling in stable rust, used by `ui.rs` 38 | unexpected_cfgs = { level = "allow", check-cfg = ['cfg(RUN_UI_TESTS)'] } 39 | -------------------------------------------------------------------------------- /testing/tests/ui/struct-expressions.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_variables)] 2 | 3 | use askama::Template; 4 | 5 | #[derive(Template)] 6 | #[template( 7 | source = r#"{{ InnerCell { ..Default::default(), other: 24 } }}"#, 8 | ext = "txt" 9 | )] 10 | struct OuterTemplate1; 11 | 12 | #[derive(Template)] 13 | #[template(source = r#"some{{ InnerCell { }}"#, ext = "txt")] 14 | struct OuterTemplate2; 15 | 16 | #[derive(Template)] 17 | #[template(source = r#"some{{ InnerCell { foo: } }}"#, ext = "txt")] 18 | struct OuterTemplate3; 19 | 20 | #[derive(Template)] 21 | #[template(source = r#"some{{ InnerCell { foo: 32, .. } }}"#, ext = "txt")] 22 | struct OuterTemplate4; 23 | 24 | #[derive(Template)] 25 | #[template(source = r#"some{{ InnerCell { . } }}"#, ext = "txt")] 26 | struct OuterTemplate5; 27 | 28 | #[derive(Template)] 29 | #[template(source = r#"some{{ InnerCell { , } }}"#, ext = "txt")] 30 | struct OuterTemplate6; 31 | 32 | #[derive(Template)] 33 | #[template(source = r#"some{{ InnerCell { ..Default::default(): 32 } }}"#, ext = "txt")] 34 | struct OuterTemplate7; 35 | 36 | #[derive(Template)] 37 | #[template(source = r#"some{{ InnerCell { ..Default::default(), a: 12 } }}"#, ext = "txt")] 38 | struct OuterTemplate8; 39 | 40 | fn main() {} 41 | -------------------------------------------------------------------------------- /testing/tests/ui/named_filter_arguments.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template( 5 | source = r#"I have {{ count }} butterfl{{ count | pluralize(plural = "ies", "y") }}."#, 6 | ext = "txt" 7 | )] 8 | struct PositionalAfterNamed { 9 | count: usize, 10 | } 11 | 12 | #[derive(Template)] 13 | #[template( 14 | source = r#"I have {{ count }} butterfl{{ count | pluralize(plural = "y", plural = "ies") }}."#, 15 | ext = "txt" 16 | )] 17 | struct NamedRepeated { 18 | count: usize, 19 | } 20 | 21 | #[derive(Template)] 22 | #[template( 23 | source = r#"I have {{ count }} butterfl{{ count | pluralize("y", pl = "ies") }}."#, 24 | ext = "txt" 25 | )] 26 | struct NamedButAlreadyPositional { 27 | count: usize, 28 | } 29 | 30 | #[derive(Template)] 31 | #[template( 32 | source = r#"I have {{ count }} butterfl{{ count | pluralize("y", sg = "ies") }}."#, 33 | ext = "txt" 34 | )] 35 | struct NoSuchNamedArgument { 36 | count: usize, 37 | } 38 | 39 | #[derive(Template)] 40 | #[template( 41 | source = r#"Scream: {{ message | uppercase(case = "upper") }}"#, 42 | ext = "txt" 43 | )] 44 | struct NamedArgumentButNoArgumentExpected<'a> { 45 | message: &'a str, 46 | } 47 | 48 | fn main() {} 49 | -------------------------------------------------------------------------------- /testing/tests/ui/unexpected-tag.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | 3 | #[derive(Template)] 4 | #[template(in_doc = true, ext = "html")] 5 | /// ```askama 6 | /// {% end %} 7 | /// ``` 8 | struct UnexpectedEnd; 9 | 10 | #[derive(Template)] 11 | #[template(in_doc = true, ext = "html")] 12 | /// ```askama 13 | /// {% for i in 0..10 %} 14 | /// i = {{i}} 15 | /// {% elif %} 16 | /// what? 17 | /// {% endfor %} 18 | /// ``` 19 | struct UnexpectedElif; 20 | 21 | #[derive(Template)] 22 | #[template(in_doc = true, ext = "html")] 23 | /// ```askama 24 | /// {% block meta %} 25 | /// then 26 | /// {% else %} 27 | /// else 28 | /// {% endblock meta %} 29 | /// ``` 30 | struct UnexpectedElse; 31 | 32 | #[derive(Template)] 33 | #[template(in_doc = true, ext = "html")] 34 | /// ```askama 35 | /// {% when condition %} 36 | /// true 37 | /// {% endwhen %} 38 | /// ``` 39 | struct UnexpectedWhen; 40 | 41 | #[derive(Template)] 42 | #[template(in_doc = true, ext = "html")] 43 | /// ```askama 44 | /// {% let var %}value{% endlet %} 45 | /// ``` 46 | struct UnexpectedEndLet; 47 | 48 | #[derive(Template)] 49 | #[template(in_doc = true, ext = "html")] 50 | /// ```askama 51 | /// {% syntax error %} 52 | /// ``` 53 | struct Unexpected; 54 | 55 | fn main() {} 56 | -------------------------------------------------------------------------------- /testing/tests/ui/comparator-chaining.rs: -------------------------------------------------------------------------------- 1 | // Comparison operators cannot be chained, so our parser must reject chained comparisons. 2 | 3 | use askama::Template; 4 | 5 | #[derive(Template)] 6 | #[template(ext = "txt", source = "{{ a == b != c }}")] 7 | struct EqNe { 8 | a: usize, 9 | b: usize, 10 | c: usize, 11 | } 12 | 13 | #[derive(Template)] 14 | #[template(ext = "txt", source = "{{ a <= b < c }}")] 15 | struct Between { 16 | a: usize, 17 | b: usize, 18 | c: usize, 19 | } 20 | 21 | #[derive(Template)] 22 | #[template(ext = "txt", source = "{{ ((a == b) == c) == d == e }}")] 23 | struct ThreeTimesOk { 24 | a: usize, 25 | b: usize, 26 | c: usize, 27 | d: usize, 28 | e: usize, 29 | } 30 | 31 | #[derive(Template)] 32 | #[template(ext = "txt", source = "{{ a == (b == (c == d == e)) }}")] 33 | struct ThreeTimesOk2 { 34 | a: usize, 35 | b: usize, 36 | c: usize, 37 | d: usize, 38 | e: usize, 39 | } 40 | 41 | // Regression test for 42 | #[derive(Template)] 43 | #[template( 44 | ext = "", 45 | source = "\u{c}{{vu7218/63e3666663-666/3330e633/63e3666663666/3333