Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for {% raw %} tag #69

Merged
merged 6 commits into from
Jun 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Tests
on: [push]

jobs:
build-latest:
test-latest:
name: Test on Latest
runs-on: ubuntu-latest

Expand All @@ -18,28 +18,28 @@ jobs:
run: make test

build-old-stable:
name: Build on 1.43.0
name: Build on 1.45.0
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: 1.43.0
toolchain: 1.45.0
profile: minimal
override: true
- name: Build
run: cargo build --features=unstable_machinery,builtins,source,json,urlencode,debug,internal_debug
working-directory: ./minijinja

build-stable:
name: Test on 1.46.0
test-stable:
name: Test on 1.56.1
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: 1.46.0
toolchain: 1.56.1
profile: minimal
override: true
- name: Test
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

All notable changes to MiniJinja are documented here.

# 0.17.0

- Added support for `{% raw %}`. (#67)
- Minimum Rust version moved up to 1.45.

# 0.16.0

- Added support for unpacking in `with` blocks. (#65)
Expand Down
6 changes: 0 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ test:
@echo "CARGO TEST ALL FEATURES"
@cd minijinja; cargo test --all-features

test-142:
@$(MAKE) run-tests FEATURES=$(TEST_FEATURES)
@$(MAKE) run-tests FEATURES=$(TEST_FEATURES),key_interning
@echo "CARGO TEST ALL FEATURES"
@cd minijinja; cargo test --all-features

run-tests:
@rustup component add rustfmt 2> /dev/null
@echo "CARGO TESTS"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![Build Status](https://github.com/mitsuhiko/minijinja/workflows/Tests/badge.svg?branch=main)](https://github.com/mitsuhiko/minijinja/actions?query=workflow%3ATests)
[![License](https://img.shields.io/github/license/mitsuhiko/minijinja)](https://github.com/mitsuhiko/minijinja/blob/main/LICENSE)
[![Crates.io](https://img.shields.io/crates/d/minijinja.svg)](https://crates.io/crates/minijinja)
[![rustc 1.43.0](https://img.shields.io/badge/rust-1.43%2B-orange.svg)](https://img.shields.io/badge/rust-1.43%2B-orange.svg)
[![rustc 1.43.0](https://img.shields.io/badge/rust-1.45%2B-orange.svg)](https://img.shields.io/badge/rust-1.45%2B-orange.svg)
[![Documentation](https://docs.rs/minijinja/badge.svg)](https://docs.rs/minijinja)

</div>
Expand Down
2 changes: 1 addition & 1 deletion minijinja/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ homepage = "https://github.com/mitsuhiko/minijinja"
repository = "https://github.com/mitsuhiko/minijinja"
keywords = ["jinja", "jinja2", "templates"]
readme = "README.md"
rust-version = "1.43"
rust-version = "1.45"

[package.metadata.docs.rs]
features = ["source", "json", "urlencode"]
Expand Down
48 changes: 48 additions & 0 deletions minijinja/src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,29 @@ fn find_marker(a: &str) -> Option<usize> {
}
}

fn skip_basic_tag(block_str: &str, name: &str) -> Option<usize> {
let mut ptr = block_str;

if let Some(rest) = ptr.strip_prefix('-') {
ptr = rest;
}
while let Some(rest) = ptr.strip_prefix(|x: char| x.is_ascii_whitespace()) {
ptr = rest;
}

ptr = ptr.strip_prefix(name)?;

while let Some(rest) = ptr.strip_prefix(|x: char| x.is_ascii_whitespace()) {
ptr = rest;
}
if let Some(rest) = ptr.strip_prefix('-') {
ptr = rest;
}
ptr = ptr.strip_prefix("%}")?;

Some(block_str.len() - ptr.len())
}

/// Tokenizes without whitespace handling.
fn tokenize_raw(
input: &str,
Expand Down Expand Up @@ -182,13 +205,30 @@ fn tokenize_raw(
return Some(Ok((Token::VariableStart(ws), span!(old_loc))));
}
Some("{%") => {
// raw blocks require some special handling. If we are at the beginning of a raw
// block we want to skip everything until {% endraw %} completely ignoring iterior
// syntax and emit the entire raw block as TemplateData.
if let Some(mut ptr) = skip_basic_tag(&rest[2..], "raw") {
ptr += 2;
while let Some(block) = memstr(&rest.as_bytes()[ptr..], b"{%") {
ptr += block + 2;
if let Some(endraw) = skip_basic_tag(&rest[ptr..], "endraw") {
let result = &rest[..ptr + endraw];
advance!(ptr + endraw);
return Some(Ok((Token::TemplateData(result), span!(old_loc))));
}
}
syntax_error!("unexpected end of raw block");
}

let ws = if rest.as_bytes().get(2) == Some(&b'-') {
advance!(3);
true
} else {
advance!(2);
false
};

stack.push(LexerState::InBlock);
return Some(Ok((Token::BlockStart(ws), span!(old_loc))));
}
Expand Down Expand Up @@ -400,3 +440,11 @@ fn test_find_marker() {
assert!(find_marker("foo {").is_none());
assert_eq!(find_marker("foo {{"), Some(4));
}

#[test]
fn test_is_basic_tag() {
assert_eq!(skip_basic_tag(" raw %}", "raw"), Some(7));
assert_eq!(skip_basic_tag(" raw %}", "endraw"), None);
assert_eq!(skip_basic_tag(" raw %}", "raw"), Some(9));
assert_eq!(skip_basic_tag("- raw -%}", "raw"), Some(11));
}
19 changes: 19 additions & 0 deletions minijinja/src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
//! - [`{% with %}`](#-with-)
//! - [`{% filter %}`](#-filter-)
//! - [`{% autoescape %}`](#-autoescape-)
//! - [`{% raw %}`](#-raw-)
//!
//! </details>
//!
Expand Down Expand Up @@ -433,5 +434,23 @@
//! ```
//!
//! After an `endautoescape` the behavior is reverted to what it was before.
//!
//! ## `{% raw %}`
//!
//! A raw block is a special construct that lets you ignore the embedded template
//! syntax. This is particularly useful if a segment of template code would
//! otherwise require constant escaping with things like `{{ "{{" }}`:
//!
//! Example:
//!
//! ```jinja
//! {% raw %}
//! <ul>
//! {% for item in seq %}
//! <li>{{ item }}</li>
//! {% endfor %}
//! </ul>
//! {% endraw %}
//! ```

// this is just for docs
5 changes: 5 additions & 0 deletions minijinja/tests/lexer-inputs/raw.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
before {% raw %} this is a {{ raw }} {% block %} {% endraw %} after

before {%- raw %} this is a {{ raw }} {% block %} {% endraw -%} after

before {%- raw -%} this is a {{ raw }} {% block %} {%- endraw -%} after
14 changes: 14 additions & 0 deletions minijinja/tests/snapshots/test_lexer__lexer@raw.txt.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
source: minijinja/tests/test_lexer.rs
expression: "&tokens"
input_file: minijinja/tests/lexer-inputs/raw.txt
---
[
TEMPLATE_DATA("before "),
TEMPLATE_DATA("{% raw %} this is a {{ raw }} {% block %} {% endraw %}"),
TEMPLATE_DATA(" after\n\nbefore "),
TEMPLATE_DATA("{%- raw %} this is a {{ raw }} {% block %} {% endraw -%}"),
TEMPLATE_DATA(" after\n\nbefore "),
TEMPLATE_DATA("{%- raw -%} this is a {{ raw }} {% block %} {%- endraw -%}"),
TEMPLATE_DATA(" after"),
]