use crate::{Attributes, Container, Event, Render, RenderOutput};
pub struct Sanitize<R>(R);
impl<'s, R> Render<'s> for Sanitize<R>
where
R: Render<'s>,
{
type Error = R::Error;
fn emit(&mut self, event: Event<'s>) -> Result<(), Self::Error> {
match event {
Event::Start(Container::RawBlock { format }, _attrs)
| Event::Start(Container::RawInline { format }, _attrs)
if format == "html" =>
{
self.0.emit(Event::Start(
Container::CodeBlock { language: format },
Attributes::new(),
))
}
Event::Start(container, _attrs) => {
self.0.emit(Event::Start(container, Attributes::new()))
}
_ => self.0.emit(event),
}
}
}
impl<'s, R> RenderOutput<'s> for Sanitize<R>
where
R: RenderOutput<'s>,
{
type Output = R::Output;
fn into_output(self) -> Self::Output {
self.0.into_output()
}
}
pub trait SanitizeExt {
fn sanitize(self) -> Sanitize<Self>
where
Self: Sized,
{
Sanitize(self)
}
}
impl<'s, R> SanitizeExt for R where R: Sized + Render<'s> {}
#[cfg(feature = "async")]
pub struct AsyncSanitize<R>(R);
#[cfg(feature = "async")]
#[async_trait::async_trait]
impl<'s, R> crate::r#async::AsyncRender<'s> for AsyncSanitize<R>
where
R: crate::r#async::AsyncRender<'s> + Send,
{
type Error = R::Error;
async fn emit(&mut self, event: Event<'s>) -> Result<(), Self::Error> {
match event {
Event::Start(Container::RawBlock { format }, _attrs)
| Event::Start(Container::RawInline { format }, _attrs)
if format == "html" =>
{
self.0
.emit(Event::Start(
Container::CodeBlock { language: format },
Attributes::new(),
))
.await
}
Event::Start(container, _attrs) => {
self.0
.emit(Event::Start(container, Attributes::new()))
.await
}
_ => self.0.emit(event).await,
}
}
}
#[cfg(feature = "async")]
#[async_trait::async_trait]
impl<'s, R> crate::r#async::AsyncRenderOutput<'s> for AsyncSanitize<R>
where
R: crate::r#async::AsyncRenderOutput<'s> + Send,
{
type Output = R::Output;
fn into_output(self) -> Self::Output {
self.0.into_output()
}
}
#[cfg(feature = "async")]
pub trait AsyncSanitizeExt {
fn sanitize(self) -> AsyncSanitize<Self>
where
Self: Sized,
{
AsyncSanitize(self)
}
}
#[cfg(feature = "async")]
impl<'s, R> AsyncSanitizeExt for R where R: Sized + crate::r#async::AsyncRender<'s> + Send {}
#[test]
fn sanitize_me() {
use crate::RenderOutputExt;
let src = r#"
```=html
<p>foo</p>
```
"#;
let out = super::Renderer::minified()
.sanitize()
.render_into_document(src)
.unwrap();
assert_eq!(
out,
"<pre><code class=\"language-html\"><p>foo</p></code></pre>"
);
}