diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 5bbf5e0e..84219e5e 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -7,6 +7,10 @@ on:
schedule:
- cron: "32 4 * * 5"
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
jobs:
Test:
strategy:
@@ -151,3 +155,33 @@ jobs:
cargo sort --check --check-format --grouped
cd - > /dev/null
done
+
+ Fuzz:
+ strategy:
+ matrix:
+ fuzz_target:
+ - all
+ - filters
+ - html
+ - parser
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ submodules: recursive
+ - uses: dtolnay/rust-toolchain@master
+ with:
+ toolchain: nightly
+ components: rust-src
+ - run: curl --location --silent --show-error --fail https://github.com/cargo-bins/cargo-quickinstall/releases/download/cargo-fuzz-0.12.0/cargo-fuzz-0.12.0-x86_64-unknown-linux-gnu.tar.gz | tar -xzvvf - -C $HOME/.cargo/bin
+ - uses: Swatinem/rust-cache@v2
+ - run: cargo fuzz run ${{ matrix.fuzz_target }} --jobs 4 -- -max_total_time=90
+ working-directory: fuzzing
+ env:
+ RUSTFLAGS: '-Ctarget-feature=-crt-static'
+
+ Typos:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: crate-ci/typos@master
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..14295a5f
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,4 @@
+[submodule "fuzzing/fuzz/corpus"]
+ path = fuzzing/fuzz/corpus
+ url = https://github.com/rinja-rs/fuzzing-corpus.git
+ branch = main
diff --git a/_typos.toml b/_typos.toml
new file mode 100644
index 00000000..4175b71b
--- /dev/null
+++ b/_typos.toml
@@ -0,0 +1,26 @@
+[default]
+locale = "en-us"
+
+[files]
+extend-exclude = [
+ # generated files
+ "book/ethicalads-theme.css",
+ "fuzzing/fuzz/artifacts/",
+ "fuzzing/fuzz/corpus/",
+ "target/",
+ "rinja_parser/tests/*.txt",
+ # fillter texts
+ "rinja/benches/strings.inc",
+ # too many false positives
+ "testing/tests/gen_ws_tests.py",
+]
+
+[default.extend-words]
+# French words
+exemple = "exemple"
+existant = "existant"
+# used in tests
+Ba = "Ba"
+fo = "fo"
+Fo = "Fo"
+sur = "sur"
diff --git a/book/src/configuration.md b/book/src/configuration.md
index 5c80b972..bc45e411 100644
--- a/book/src/configuration.md
+++ b/book/src/configuration.md
@@ -54,7 +54,7 @@ Hello
To be noted, if one of the trimmed characters is a newline, then the only
character remaining will be a newline.
-If you want this to be the default behaviour, you can set `whitespace` to
+If you want this to be the default behavior, you can set `whitespace` to
`"minimize"`.
To be noted: you can also configure `whitespace` directly into the `template`
diff --git a/book/src/filters.md b/book/src/filters.md
index 892cbdcc..f2b604e8 100644
--- a/book/src/filters.md
+++ b/book/src/filters.md
@@ -35,6 +35,7 @@ Enable it with Cargo features (see below for more information).
* [`linebreaksbr`][#linebreaksbr]
* [`lower|lowercase`][#lower]
* [`paragraphbreaks`][#paragraphbreaks]
+ * [`pluralize`][#pluralize]
* [`ref`][#ref]
* [`safe`][#safe]
* [`title`][#title]
@@ -311,6 +312,33 @@ Output:
hello
```
+### `pluralize`
+[#pluralize]: #pluralize
+
+Select a singular or plural version of a word, depending on the input value.
+
+If the value of `self.count` is +1 or -1, then "cat" is returned, otherwise "cats":
+
+```jinja
+cat{{ count|pluralize }}
+```
+
+You can override the default empty singular suffix, e.g. to spell "doggo" for a single dog:
+
+```jinja
+dog{{ count|pluralize("go") }}
+```
+
+If the word cannot be declined by simply adding a suffix,
+then you can also override singular and the plural, too:
+
+```jinja
+{{ count|pluralize("mouse", "mice") }}
+```
+
+More complex languages that know multiple plurals might be impossible to implement with this filter,
+though.
+
### ref
[#ref]: #ref
diff --git a/book/src/template_syntax.md b/book/src/template_syntax.md
index 689e979b..30cce324 100644
--- a/book/src/template_syntax.md
+++ b/book/src/template_syntax.md
@@ -196,7 +196,7 @@ struct MyTemplate {
However, since we'll need to define this function every time we create an
instance of `MyTemplate`, it's probably not the most ideal way to associate
-some behaviour for our template.
+some behavior for our template.
### Static functions
@@ -619,6 +619,24 @@ You can also match against multiple alternative patterns at once:
{% endmatch %}
```
+For better interoperability with linters and auto-formatters like [djLint],
+you can also use an optional `{% endwhen %}` node to close a `{% when %}` case:
+
+```jinja
+{% match number %}
+ {% when 0 | 2 | 4 | 6 | 8 %}
+ even
+ {% endwhen %}
+ {% when 1 | 3 | 5 | 7 | 9 %}
+ odd
+ {% endwhen %}
+ {% else }
+ unknown
+{% endmatch %}
+```
+
+[djLint]:
+
### Referencing and dereferencing variables
If you need to put something behind a reference or to dereference it, you
@@ -743,6 +761,11 @@ let t = RenderInPlace { s1: SectionOne { a: "a", b: "b" } };
assert_eq!(t.render().unwrap(), "Section 1: A=a\nB=b")
```
+Note that if your inner template like `SectionOne` renders HTML content, then you may want to
+disable escaping when injecting it into an outer template, e.g. `{{ s1|safe }}`.
+Otherwise it will render the HTML content literally, because
+rinja [escapes HTML variables](#html-escaping) by default.
+
See the example
[render in place](https://github.com/rinja-rs/rinja/blob/master/testing/tests/render_in_place.rs)
using a vector of templates in a for block.
diff --git a/examples/actix-web-app/Cargo.toml b/examples/actix-web-app/Cargo.toml
index 50151bac..d14de4a2 100644
--- a/examples/actix-web-app/Cargo.toml
+++ b/examples/actix-web-app/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "actix-web-app"
-version = "0.3.2"
+version = "0.3.3"
edition = "2021"
license = "MIT OR Apache-2.0"
publish = false
@@ -10,7 +10,7 @@ publish = false
# and actix-web as your web-framework.
# rinja_actix makes it easy to use rinja templates as `Responder` of an actix-web request.
# The rendered template is simply the response of your handler!
-rinja_actix = { version = "0.3.2", path = "../../rinja_actix" }
+rinja_actix = { version = "0.3.3", path = "../../rinja_actix" }
actix-web = { version = "4.8.0", default-features = false, features = ["macros"] }
tokio = { version = "1.38.0", features = ["sync", "rt-multi-thread"] }
diff --git a/examples/actix-web-app/src/main.rs b/examples/actix-web-app/src/main.rs
index e232abf6..1f9722c1 100644
--- a/examples/actix-web-app/src/main.rs
+++ b/examples/actix-web-app/src/main.rs
@@ -55,7 +55,7 @@ enum Error {
///
/// The same type is used by actix-web as part of the URL, and in rinja to select what content to
/// show, and also as an HTML attribute in ` Result {
}
}
-/// The is first page your user hits does not contain language infomation, so we redirect them
+/// The is first page your user hits does not contain language information, so we redirect them
/// to a URL that does contain the default language.
#[get("/")]
async fn start_handler(req: HttpRequest) -> Result {
@@ -139,7 +139,7 @@ async fn index_handler(
// `{% if lang !=`, the former to select the text of a specific language, e.g. in the ``;
// and the latter to display references to all other available languages except the currently
// selected one.
- // The field `name` will contain the value of the query paramater of the same name.
+ // The field `name` will contain the value of the query parameter of the same name.
// In `IndexHandlerQuery` we annotated the field with `#[serde(default)]`, so if the value is
// absent, an empty string is selected by default, which is visible to the user an empty
// `` element.
diff --git a/fuzzing/fuzz/.gitignore b/fuzzing/fuzz/.gitignore
deleted file mode 100644
index 8fa697f9..00000000
--- a/fuzzing/fuzz/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/artifacts/
-/corpus/
diff --git a/fuzzing/fuzz/artifacts/.gitattributes b/fuzzing/fuzz/artifacts/.gitattributes
new file mode 100644
index 00000000..c6e54c93
--- /dev/null
+++ b/fuzzing/fuzz/artifacts/.gitattributes
@@ -0,0 +1,2 @@
+* -text -diff binary
+.gitattributes text diff
diff --git a/fuzzing/fuzz/corpus b/fuzzing/fuzz/corpus
new file mode 160000
index 00000000..dde68840
--- /dev/null
+++ b/fuzzing/fuzz/corpus
@@ -0,0 +1 @@
+Subproject commit dde688407c37aeb0d36792561b71a39501c32be7
diff --git a/rinja/Cargo.toml b/rinja/Cargo.toml
index 8d20aad1..9f0a0bb4 100644
--- a/rinja/Cargo.toml
+++ b/rinja/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rinja"
-version = "0.3.2"
+version = "0.3.3"
description = "Type-safe, compiled Jinja-like templates for Rust"
documentation = "https://docs.rs/rinja"
keywords = ["markup", "template", "jinja2", "html"]
@@ -37,7 +37,7 @@ with-rocket = ["rinja_derive/with-rocket"]
with-warp = ["rinja_derive/with-warp"]
[dependencies]
-rinja_derive = { version = "=0.3.2", path = "../rinja_derive" }
+rinja_derive = { version = "=0.3.3", path = "../rinja_derive" }
humansize = { version = "2", optional = true }
num-traits = { version = "0.2.6", optional = true }
diff --git a/rinja/benches/escape.rs b/rinja/benches/escape.rs
index a8e55f7b..18125939 100644
--- a/rinja/benches/escape.rs
+++ b/rinja/benches/escape.rs
@@ -1,4 +1,4 @@
-use criterion::{criterion_group, criterion_main, Criterion};
+use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rinja::filters::{escape, Html};
criterion_main!(benches);
@@ -9,66 +9,11 @@ fn functions(c: &mut Criterion) {
}
fn escaping(b: &mut criterion::Bencher<'_>) {
- let string_long = r#"
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris consequat tellus sit
- amet ornare fermentum. Etiam nec erat ante. In at metus a orci mollis scelerisque.
- Sed eget ultrices turpis, at sollicitudin erat. Integer hendrerit nec magna quis
- venenatis. Vivamus non dolor hendrerit, vulputate velit sed, varius nunc. Quisque
- in pharetra mi. Sed ullamcorper nibh malesuada commodo porttitor. Ut scelerisque
- sodales felis quis dignissim. Morbi aliquam finibus justo, sit amet consectetur
- mauris efficitur sit amet. Donec posuere turpis felis, eu lacinia magna accumsan
- quis. Fusce egestas lacus vel fermentum tincidunt. Phasellus a nulla eget lectus
- placerat commodo at eget nisl. Fusce cursus dui quis purus accumsan auctor.
- Donec iaculis felis quis metus consectetur porttitor.
-
- Etiam nibh mi, accumsan quis purus sed, posuere fermentum lorem. In pulvinar porta
- maximus. Fusce tincidunt lacinia tellus sit amet tincidunt. Aliquam lacus est, pulvinar
- non metus a, facilisis ultrices quam. Nulla feugiat leo in cursus eleifend. Suspendisse
- eget nisi ac justo sagittis interdum id a ipsum. Nulla mauris justo, scelerisque ac
- rutrum vitae, consequat vel ex.
-
-
- Sed sollicitudin sem mauris, at rutrum nibh egestas vel. Ut eu nisi tellus. Praesent dignissim
- orci elementum, mattis turpis eget, maximus ante. Suspendisse luctus eu felis a tempor. Morbi
- ac risus vitae sem molestie ullamcorper. Curabitur ligula augue, sollicitudin quis maximus vel,
- facilisis sed nibh. Aenean auctor magna sem, id rutrum metus convallis quis. Nullam non arcu
- dictum, lobortis erat quis, rhoncus est. Suspendisse venenatis, mi sed venenatis vehicula,
- tortor dolor egestas lectus, et efficitur turpis odio non augue. Integer velit sapien, dictum
- non egestas vitae, hendrerit sed quam. Phasellus a nunc eu erat varius imperdiet. Etiam id
- sollicitudin turpis, vitae molestie orci. Quisque ornare magna quis metus rhoncus commodo.
- Phasellus non mauris velit.
-
-
- Etiam dictum tellus ipsum, nec varius quam ornare vel. Cras vehicula diam nec sollicitudin
- ultricies. Pellentesque rhoncus sagittis nisl id facilisis. Nunc viverra convallis risus ut
- luctus. Aliquam vestibulum efficitur massa, id tempus nisi posuere a. Aliquam scelerisque
- elit justo. Nullam a ante felis. Cras vitae lorem eu nisi feugiat hendrerit. Maecenas vitae
- suscipit leo, lacinia dignissim lacus. Sed eget volutpat mi. In eu bibendum neque. Pellentesque
- finibus velit a fermentum rhoncus. Maecenas leo purus, eleifend eu lacus a, condimentum sagittis
- justo.
-
"#;
- let string_short = "Lorem ipsum dolor sit amet,bar&foo\"bar\\foo/bar";
- let empty = "";
- let no_escape = "Lorem ipsum dolor sit amet,";
- let no_escape_long = r#"
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin scelerisque eu urna in aliquet.
-Phasellus ac nulla a urna sagittis consequat id quis est. Nullam eu ex eget erat accumsan dictum
-ac lobortis urna. Etiam fermentum ut quam at dignissim. Curabitur vestibulum luctus tellus, sit
-amet lobortis augue tempor faucibus. Nullam sed felis eget odio elementum euismod in sit amet massa.
-Vestibulum sagittis purus sit amet eros auctor, sit amet pharetra purus dapibus. Donec ornare metus
-vel dictum porta. Etiam ut nisl nisi. Nullam rutrum porttitor mi. Donec aliquam ac ipsum eget
-hendrerit. Cras faucibus, eros ut pharetra imperdiet, est tellus aliquet felis, eget convallis
-lacus ipsum eget quam. Vivamus orci lorem, maximus ac mi eget, bibendum vulputate massa. In
-vestibulum dui hendrerit, vestibulum lacus sit amet, posuere erat. Vivamus euismod massa diam,
-vulputate euismod lectus vestibulum nec. Donec sit amet massa magna. Nunc ipsum nulla, euismod
-quis lacus at, gravida maximus elit. Duis tristique, nisl nullam.
- "#;
-
b.iter(|| {
- format!("{}", escape(string_long, Html).unwrap());
- format!("{}", escape(string_short, Html).unwrap());
- format!("{}", escape(empty, Html).unwrap());
- format!("{}", escape(no_escape, Html).unwrap());
- format!("{}", escape(no_escape_long, Html).unwrap());
+ for &s in black_box(STRINGS) {
+ let _ = black_box(format!("{}", escape(s, Html).unwrap()));
+ }
});
}
+
+const STRINGS: &[&str] = include!("strings.inc");
diff --git a/rinja/benches/strings.inc b/rinja/benches/strings.inc
new file mode 100644
index 00000000..9f90ba77
--- /dev/null
+++ b/rinja/benches/strings.inc
@@ -0,0 +1,69 @@
+{
+ const STRING_LONG: &str = r#"
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris consequat tellus sit
+ amet ornare fermentum. Etiam nec erat ante. In at metus a orci mollis scelerisque.
+ Sed eget ultrices turpis, at sollicitudin erat. Integer hendrerit nec magna quis
+ venenatis. Vivamus non dolor hendrerit, vulputate velit sed, varius nunc. Quisque
+ in pharetra mi. Sed ullamcorper nibh malesuada commodo porttitor. Ut scelerisque
+ sodales felis quis dignissim. Morbi aliquam finibus justo, sit amet consectetur
+ mauris efficitur sit amet. Donec posuere turpis felis, eu lacinia magna accumsan
+ quis. Fusce egestas lacus vel fermentum tincidunt. Phasellus a nulla eget lectus
+ placerat commodo at eget nisl. Fusce cursus dui quis purus accumsan auctor.
+ Donec iaculis felis quis metus consectetur porttitor.
+
+ Etiam nibh mi, accumsan quis purus sed, posuere fermentum lorem. In pulvinar porta
+ maximus. Fusce tincidunt lacinia tellus sit amet tincidunt. Aliquam lacus est, pulvinar
+ non metus a, facilisis ultrices quam. Nulla feugiat leo in cursus eleifend. Suspendisse
+ eget nisi ac justo sagittis interdum id a ipsum. Nulla mauris justo, scelerisque ac
+ rutrum vitae, consequat vel ex.
+
+
+ Sed sollicitudin sem mauris, at rutrum nibh egestas vel. Ut eu nisi tellus. Praesent dignissim
+ orci elementum, mattis turpis eget, maximus ante. Suspendisse luctus eu felis a tempor. Morbi
+ ac risus vitae sem molestie ullamcorper. Curabitur ligula augue, sollicitudin quis maximus vel,
+ facilisis sed nibh. Aenean auctor magna sem, id rutrum metus convallis quis. Nullam non arcu
+ dictum, lobortis erat quis, rhoncus est. Suspendisse venenatis, mi sed venenatis vehicula,
+ tortor dolor egestas lectus, et efficitur turpis odio non augue. Integer velit sapien, dictum
+ non egestas vitae, hendrerit sed quam. Phasellus a nunc eu erat varius imperdiet. Etiam id
+ sollicitudin turpis, vitae molestie orci. Quisque ornare magna quis metus rhoncus commodo.
+ Phasellus non mauris velit.
+
+
+ Etiam dictum tellus ipsum, nec varius quam ornare vel. Cras vehicula diam nec sollicitudin
+ ultricies. Pellentesque rhoncus sagittis nisl id facilisis. Nunc viverra convallis risus ut
+ luctus. Aliquam vestibulum efficitur massa, id tempus nisi posuere a. Aliquam scelerisque
+ elit justo. Nullam a ante felis. Cras vitae lorem eu nisi feugiat hendrerit. Maecenas vitae
+ suscipit leo, lacinia dignissim lacus. Sed eget volutpat mi. In eu bibendum neque. Pellentesque
+ finibus velit a fermentum rhoncus. Maecenas leo purus, eleifend eu lacus a, condimentum sagittis
+ justo.
+
"#;
+
+ const STRING_SHORT: &str = "Lorem ipsum dolor sit amet,bar&foo\"bar\\foo/bar";
+
+ const EMPTY: &str = "";
+
+ const NO_ESCAPE: &str = "Lorem ipsum dolor sit amet,";
+
+ const NO_ESCAPE_LONG: &str = r#"
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin scelerisque eu urna in aliquet.
+Phasellus ac nulla a urna sagittis consequat id quis est. Nullam eu ex eget erat accumsan dictum
+ac lobortis urna. Etiam fermentum ut quam at dignissim. Curabitur vestibulum luctus tellus, sit
+amet lobortis augue tempor faucibus. Nullam sed felis eget odio elementum euismod in sit amet massa.
+Vestibulum sagittis purus sit amet eros auctor, sit amet pharetra purus dapibus. Donec ornare metus
+vel dictum porta. Etiam ut nisl nisi. Nullam rutrum porttitor mi. Donec aliquam ac ipsum eget
+hendrerit. Cras faucibus, eros ut pharetra imperdiet, est tellus aliquet felis, eget convallis
+lacus ipsum eget quam. Vivamus orci lorem, maximus ac mi eget, bibendum vulputate massa. In
+vestibulum dui hendrerit, vestibulum lacus sit amet, posuere erat. Vivamus euismod massa diam,
+vulputate euismod lectus vestibulum nec. Donec sit amet massa magna. Nunc ipsum nulla, euismod
+quis lacus at, gravida maximus elit. Duis tristique, nisl nullam.
+ "#;
+
+ const STRINGS: &[&str] = &[
+ STRING_LONG,
+ STRING_SHORT,
+ EMPTY,
+ NO_ESCAPE,
+ NO_ESCAPE_LONG,
+ ];
+ STRINGS
+}
diff --git a/rinja/benches/to-json.rs b/rinja/benches/to-json.rs
index 78f31908..8d83a149 100644
--- a/rinja/benches/to-json.rs
+++ b/rinja/benches/to-json.rs
@@ -1,4 +1,4 @@
-use criterion::{criterion_group, criterion_main, Criterion};
+use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rinja::Template;
criterion_main!(benches);
@@ -18,7 +18,7 @@ fn escape_json(b: &mut criterion::Bencher<'_>) {
b.iter(|| {
let mut len = 0;
- for &s in STRINGS {
+ for &s in black_box(STRINGS) {
len += Tmpl(s).to_string().len();
}
len
@@ -32,7 +32,7 @@ fn escape_json_pretty(b: &mut criterion::Bencher<'_>) {
b.iter(|| {
let mut len = 0;
- for &s in STRINGS {
+ for &s in black_box(STRINGS) {
len += Tmpl(s).to_string().len();
}
len
@@ -46,7 +46,7 @@ fn escape_json_for_html(b: &mut criterion::Bencher<'_>) {
b.iter(|| {
let mut len = 0;
- for &s in STRINGS {
+ for &s in black_box(STRINGS) {
len += Tmpl(s).to_string().len();
}
len
@@ -60,65 +60,11 @@ fn escape_json_for_html_pretty(b: &mut criterion::Bencher<'_>) {
b.iter(|| {
let mut len = 0;
- for &s in STRINGS {
+ for &s in black_box(STRINGS) {
len += Tmpl(s).to_string().len();
}
len
});
}
-const STRINGS: &[&str] = &[STRING_LONG, STRING_SHORT, EMPTY, NO_ESCAPE, NO_ESCAPE_LONG];
-const STRING_LONG: &str = r#"
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris consequat tellus sit
-amet ornare fermentum. Etiam nec erat ante. In at metus a orci mollis scelerisque.
-Sed eget ultrices turpis, at sollicitudin erat. Integer hendrerit nec magna quis
-venenatis. Vivamus non dolor hendrerit, vulputate velit sed, varius nunc. Quisque
-in pharetra mi. Sed ullamcorper nibh malesuada commodo porttitor. Ut scelerisque
-sodales felis quis dignissim. Morbi aliquam finibus justo, sit amet consectetur
-mauris efficitur sit amet. Donec posuere turpis felis, eu lacinia magna accumsan
-quis. Fusce egestas lacus vel fermentum tincidunt. Phasellus a nulla eget lectus
-placerat commodo at eget nisl. Fusce cursus dui quis purus accumsan auctor.
-Donec iaculis felis quis metus consectetur porttitor.
-
-Etiam nibh mi, accumsan quis purus sed, posuere fermentum lorem. In pulvinar porta
-maximus. Fusce tincidunt lacinia tellus sit amet tincidunt. Aliquam lacus est, pulvinar
-non metus a, facilisis ultrices quam. Nulla feugiat leo in cursus eleifend. Suspendisse
-eget nisi ac justo sagittis interdum id a ipsum. Nulla mauris justo, scelerisque ac
-rutrum vitae, consequat vel ex.
-
-
-Sed sollicitudin sem mauris, at rutrum nibh egestas vel. Ut eu nisi tellus. Praesent dignissim
-orci elementum, mattis turpis eget, maximus ante. Suspendisse luctus eu felis a tempor. Morbi
-ac risus vitae sem molestie ullamcorper. Curabitur ligula augue, sollicitudin quis maximus vel,
-facilisis sed nibh. Aenean auctor magna sem, id rutrum metus convallis quis. Nullam non arcu
-dictum, lobortis erat quis, rhoncus est. Suspendisse venenatis, mi sed venenatis vehicula,
-tortor dolor egestas lectus, et efficitur turpis odio non augue. Integer velit sapien, dictum
-non egestas vitae, hendrerit sed quam. Phasellus a nunc eu erat varius imperdiet. Etiam id
-sollicitudin turpis, vitae molestie orci. Quisque ornare magna quis metus rhoncus commodo.
-Phasellus non mauris velit.
-
-
-Etiam dictum tellus ipsum, nec varius quam ornare vel. Cras vehicula diam nec sollicitudin
-ultricies. Pellentesque rhoncus sagittis nisl id facilisis. Nunc viverra convallis risus ut
-luctus. Aliquam vestibulum efficitur massa, id tempus nisi posuere a. Aliquam scelerisque
-elit justo. Nullam a ante felis. Cras vitae lorem eu nisi feugiat hendrerit. Maecenas vitae
-suscipit leo, lacinia dignissim lacus. Sed eget volutpat mi. In eu bibendum neque. Pellentesque
-finibus velit a fermentum rhoncus. Maecenas leo purus, eleifend eu lacus a, condimentum sagittis
-justo.
-