mirror of
https://github.com/askama-rs/askama.git
synced 2025-09-30 14:31:36 +00:00
Filter linebreaksbr
only needs core
This commit is contained in:
parent
b9490c4b5d
commit
94e7757078
@ -3,7 +3,6 @@ use alloc::string::String;
|
|||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
use core::fmt::{self, Write};
|
use core::fmt::{self, Write};
|
||||||
|
|
||||||
use super::escape::HtmlSafeOutput;
|
|
||||||
use crate::{FastWritable, Result};
|
use crate::{FastWritable, Result};
|
||||||
|
|
||||||
/// Return an ephemeral `&str` for `$src: impl fmt::Display`
|
/// Return an ephemeral `&str` for `$src: impl fmt::Display`
|
||||||
@ -95,60 +94,6 @@ pub fn fmt() {}
|
|||||||
/// Compare with [fmt](./fn.fmt.html).
|
/// Compare with [fmt](./fn.fmt.html).
|
||||||
pub fn format() {}
|
pub fn format() {}
|
||||||
|
|
||||||
/// Converts all newlines in a piece of plain text to HTML line breaks
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # #[cfg(feature = "code-in-doc")] {
|
|
||||||
/// # use askama::Template;
|
|
||||||
/// /// ```jinja
|
|
||||||
/// /// <div>{{ lines|linebreaksbr }}</div>
|
|
||||||
/// /// ```
|
|
||||||
/// #[derive(Template)]
|
|
||||||
/// #[template(ext = "html", in_doc = true)]
|
|
||||||
/// struct Example<'a> {
|
|
||||||
/// lines: &'a str,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// assert_eq!(
|
|
||||||
/// Example { lines: "a\nb\nc" }.to_string(),
|
|
||||||
/// "<div>a<br/>b<br/>c</div>"
|
|
||||||
/// );
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
|
||||||
pub fn linebreaksbr<S: fmt::Display>(
|
|
||||||
source: S,
|
|
||||||
) -> Result<HtmlSafeOutput<Linebreaksbr<S>>, Infallible> {
|
|
||||||
Ok(HtmlSafeOutput(Linebreaksbr(source)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Linebreaksbr<S>(S);
|
|
||||||
|
|
||||||
impl<S: fmt::Display> fmt::Display for Linebreaksbr<S> {
|
|
||||||
#[inline]
|
|
||||||
fn fmt(&self, dest: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
let mut buffer;
|
|
||||||
flush_linebreaksbr(dest, try_to_str!(self.0 => buffer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: FastWritable> FastWritable for Linebreaksbr<S> {
|
|
||||||
#[inline]
|
|
||||||
fn write_into<W: fmt::Write + ?Sized>(
|
|
||||||
&self,
|
|
||||||
dest: &mut W,
|
|
||||||
values: &dyn crate::Values,
|
|
||||||
) -> crate::Result<()> {
|
|
||||||
let mut buffer = String::new();
|
|
||||||
self.0.write_into(&mut buffer, values)?;
|
|
||||||
Ok(flush_linebreaksbr(dest, &buffer)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flush_linebreaksbr(dest: &mut (impl fmt::Write + ?Sized), s: &str) -> fmt::Result {
|
|
||||||
dest.write_str(&s.replace('\n', "<br/>"))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts to lowercase
|
/// Converts to lowercase
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -541,15 +486,6 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_linebreaksbr() {
|
|
||||||
assert_eq!(linebreaksbr("Foo\nBar").unwrap().to_string(), "Foo<br/>Bar");
|
|
||||||
assert_eq!(
|
|
||||||
linebreaksbr("Foo\nBar\n\nBaz").unwrap().to_string(),
|
|
||||||
"Foo<br/>Bar<br/><br/>Baz"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_lower() {
|
fn test_lower() {
|
||||||
assert_eq!(lower("Foo").unwrap().to_string(), "foo");
|
assert_eq!(lower("Foo").unwrap().to_string(), "foo");
|
||||||
|
@ -735,14 +735,7 @@ impl<W: fmt::Write + ?Sized> fmt::Write for NewlineCountingFormatter<'_, W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for line in s.split_inclusive('\n') {
|
for line in s.split_inclusive('\n') {
|
||||||
let (has_eol, line) = if let Some(line) = line.strip_suffix("\r\n") {
|
let (has_eol, line) = strip_newline_suffix(line);
|
||||||
(true, line)
|
|
||||||
} else if let Some(line) = line.strip_suffix('\n') {
|
|
||||||
(true, line)
|
|
||||||
} else {
|
|
||||||
(false, line)
|
|
||||||
};
|
|
||||||
|
|
||||||
if !line.is_empty() {
|
if !line.is_empty() {
|
||||||
match replace(&mut self.counter, if has_eol { 1 } else { 0 }) {
|
match replace(&mut self.counter, if has_eol { 1 } else { 0 }) {
|
||||||
..=0 => {}
|
..=0 => {}
|
||||||
@ -758,6 +751,79 @@ impl<W: fmt::Write + ?Sized> fmt::Write for NewlineCountingFormatter<'_, W> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts all newlines in a piece of plain text to HTML line breaks
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #[cfg(feature = "code-in-doc")] {
|
||||||
|
/// # use askama::Template;
|
||||||
|
/// /// ```jinja
|
||||||
|
/// /// <div>{{ lines|linebreaksbr }}</div>
|
||||||
|
/// /// ```
|
||||||
|
/// #[derive(Template)]
|
||||||
|
/// #[template(ext = "html", in_doc = true)]
|
||||||
|
/// struct Example<'a> {
|
||||||
|
/// lines: &'a str,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// Example { lines: "a\nb\nc" }.to_string(),
|
||||||
|
/// "<div>a<br/>b<br/>c</div>"
|
||||||
|
/// );
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn linebreaksbr<S: fmt::Display>(
|
||||||
|
source: S,
|
||||||
|
) -> Result<HtmlSafeOutput<Linebreaksbr<S>>, Infallible> {
|
||||||
|
Ok(HtmlSafeOutput(Linebreaksbr(source)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Linebreaksbr<S>(S);
|
||||||
|
|
||||||
|
impl<S: fmt::Display> fmt::Display for Linebreaksbr<S> {
|
||||||
|
#[inline]
|
||||||
|
fn fmt(&self, dest: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(LinebreaksbrFormatter(dest), "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LinebreaksbrFormatter<'a, W: ?Sized>(&'a mut W);
|
||||||
|
|
||||||
|
impl<S: FastWritable> FastWritable for Linebreaksbr<S> {
|
||||||
|
#[inline]
|
||||||
|
fn write_into<W: fmt::Write + ?Sized>(
|
||||||
|
&self,
|
||||||
|
dest: &mut W,
|
||||||
|
values: &dyn crate::Values,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
self.0.write_into(&mut LinebreaksbrFormatter(dest), values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: fmt::Write + ?Sized> fmt::Write for LinebreaksbrFormatter<'_, W> {
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
for line in s.split_inclusive('\n') {
|
||||||
|
let (has_eol, line) = strip_newline_suffix(line);
|
||||||
|
self.0.write_str(line)?;
|
||||||
|
if has_eol {
|
||||||
|
self.0.write_str("<br/>")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether a newline suffix was stripped and the (maybe stripped) line.
|
||||||
|
fn strip_newline_suffix(line: &str) -> (bool, &str) {
|
||||||
|
if let Some(line) = line.strip_suffix("\r\n") {
|
||||||
|
(true, line)
|
||||||
|
} else if let Some(line) = line.strip_suffix('\n') {
|
||||||
|
(true, line)
|
||||||
|
} else {
|
||||||
|
(false, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(all(test, feature = "alloc"))]
|
#[cfg(all(test, feature = "alloc"))]
|
||||||
mod tests {
|
mod tests {
|
||||||
use alloc::string::{String, ToString};
|
use alloc::string::{String, ToString};
|
||||||
@ -898,4 +964,13 @@ mod tests {
|
|||||||
"<p>Foo</p><p>Bar</p><p>Baz</p>"
|
"<p>Foo</p><p>Bar</p><p>Baz</p>"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_linebreaksbr() {
|
||||||
|
assert_eq!(linebreaksbr("Foo\nBar").unwrap().to_string(), "Foo<br/>Bar");
|
||||||
|
assert_eq!(
|
||||||
|
linebreaksbr("Foo\nBar\n\nBaz").unwrap().to_string(),
|
||||||
|
"Foo<br/>Bar<br/><br/>Baz"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,11 @@ mod urlencode;
|
|||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub use self::alloc::{
|
pub use self::alloc::{
|
||||||
capitalize, fmt, format, linebreaksbr, lower, lowercase, title, titlecase, trim, upper,
|
capitalize, fmt, format, lower, lowercase, title, titlecase, trim, upper, uppercase,
|
||||||
uppercase,
|
|
||||||
};
|
};
|
||||||
pub use self::core::{
|
pub use self::core::{
|
||||||
PluralizeCount, center, join, linebreaks, paragraphbreaks, pluralize, reject, reject_with,
|
PluralizeCount, center, join, linebreaks, linebreaksbr, paragraphbreaks, pluralize, reject,
|
||||||
truncate, wordcount,
|
reject_with, truncate, wordcount,
|
||||||
};
|
};
|
||||||
pub use self::escape::{
|
pub use self::escape::{
|
||||||
AutoEscape, AutoEscaper, Escaper, Html, HtmlSafe, HtmlSafeOutput, MaybeSafe, Safe, Text,
|
AutoEscape, AutoEscaper, Escaper, Html, HtmlSafe, HtmlSafeOutput, MaybeSafe, Safe, Text,
|
||||||
|
@ -333,9 +333,8 @@ impl<'a> Generator<'a, '_> {
|
|||||||
ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
buf: &mut Buffer,
|
buf: &mut Buffer,
|
||||||
args: &[WithSpan<'a, Expr<'a>>],
|
args: &[WithSpan<'a, Expr<'a>>],
|
||||||
node: Span<'_>,
|
_node: Span<'_>,
|
||||||
) -> Result<DisplayWrap, CompileError> {
|
) -> Result<DisplayWrap, CompileError> {
|
||||||
ensure_filter_has_feature_alloc(ctx, "linebreaksbr", node)?;
|
|
||||||
self.visit_linebreaks_filters(ctx, buf, "linebreaksbr", args)
|
self.visit_linebreaks_filters(ctx, buf, "linebreaksbr", args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,11 +320,6 @@ Output:
|
|||||||
### linebreaksbr
|
### linebreaksbr
|
||||||
[#linebreaksbr]: #linebreaksbr
|
[#linebreaksbr]: #linebreaksbr
|
||||||
|
|
||||||
<blockquote class="right" style="padding:0.5ex 1ex; margin:0 0 1ex 1ex; font-size:80%">
|
|
||||||
enabled by <code>"alloc"</code><br/>
|
|
||||||
enabled by <code>"default"</code>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
```jinja
|
```jinja
|
||||||
{{ text_to_break | linebreaksbr }}
|
{{ text_to_break | linebreaksbr }}
|
||||||
```
|
```
|
||||||
|
Loading…
x
Reference in New Issue
Block a user