Incluye maud 0.25.0 embebido en código

This commit is contained in:
Manuel Cillero 2023-05-17 22:46:29 +02:00
parent 51f33835af
commit 81f25cf655
8 changed files with 393 additions and 9 deletions

View file

@ -14,8 +14,8 @@ constantes. No puede considerarse preparado hasta que se libere la versión **0.
# 🔖 Créditos # 🔖 Créditos
Incluye una versión adaptada del crate [maud-macros](https://crates.io/crates/maud_macros) de Incluye en código una versión adaptada del crate [maud-macros](https://crates.io/crates/maud_macros)
[Chris Wong](https://crates.io/users/lambda-fairy) (versión de [Chris Wong](https://crates.io/users/lambda-fairy) (versión
[0.25.0](https://github.com/lambda-fairy/maud/tree/v0.25.0/maud_macros)), para incorporar sus [0.25.0](https://github.com/lambda-fairy/maud/tree/v0.25.0/maud_macros)), para incorporar sus
funcionalidades en **PageTop** sin requerir una entrada adicional en el archivo Cargo.toml de cada funcionalidades en **PageTop** sin requerir una entrada adicional en el archivo Cargo.toml de cada
proyecto. proyecto.

View file

@ -36,7 +36,9 @@ async-trait = "0.1.68"
concat-string = "1.0.1" concat-string = "1.0.1"
doc-comment = "0.3.3" doc-comment = "0.3.3"
figlet-rs = "0.1.5" figlet-rs = "0.1.5"
itoa = "1.0.6"
futures = "0.3.28" futures = "0.3.28"
futures-util = "0.3.28"
nom = "7.1.3" nom = "7.1.3"
once_cell = "1.17.1" once_cell = "1.17.1"
paste = "1.0.12" paste = "1.0.12"
@ -61,8 +63,6 @@ static-files = "0.2.3"
pagetop-macros = { version = "0.0", path = "../pagetop-macros" } pagetop-macros = { version = "0.0", path = "../pagetop-macros" }
maud = { version = "0.25.0", features = ["actix-web"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
[dependencies.sea-orm] [dependencies.sea-orm]

View file

@ -9,6 +9,15 @@ configurables.
constantes. No puede considerarse preparado hasta que se libere la versión **0.1.0**. constantes. No puede considerarse preparado hasta que se libere la versión **0.1.0**.
# 🔖 Créditos
Incluye en código una versión adaptada del excelente crate [maud](https://crates.io/crates/maud) de
[Chris Wong](https://crates.io/users/lambda-fairy) (versión
[0.25.0](https://github.com/lambda-fairy/maud/tree/v0.25.0/maud)), para incorporar sus
funcionalidades en **PageTop** sin requerir una entrada adicional en el archivo Cargo.toml de cada
proyecto.
# 📜 Licencia # 📜 Licencia
Este proyecto tiene licencia, de hecho tiene dos, puedes aplicar cualquiera de las siguientes a tu Este proyecto tiene licencia, de hecho tiene dos, puedes aplicar cualquiera de las siguientes a tu

View file

@ -14,8 +14,6 @@ pagetop = { version = "0.0", features = ["mysql"], default-features = false }
# Opcional. Para usar archivos y recursos binarios contenidos en el ejecutable: # Opcional. Para usar archivos y recursos binarios contenidos en el ejecutable:
static-files = "0.2.3" static-files = "0.2.3"
# Opcional. Para usar la macro html!:
maud = "0.25.0"
# Opcional. Para serializar estructuras de datos: # Opcional. Para serializar estructuras de datos:
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }

View file

@ -13,8 +13,6 @@ pagetop = { version = "0.0", features = ["database"], default-features = false }
# Opcional. Para usar archivos y recursos binarios contenidos en la librería: # Opcional. Para usar archivos y recursos binarios contenidos en la librería:
static-files = "0.2.3" static-files = "0.2.3"
# Opcional. Para usar la macro html!:
maud = "0.25.0"
# Opcional. Para serializar estructuras de datos: # Opcional. Para serializar estructuras de datos:
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }

View file

@ -1,6 +1,7 @@
//! HTML en código. //! HTML en código.
pub use maud::{html, Markup, PreEscaped, DOCTYPE}; mod maud;
pub use maud::{html, html_private, Markup, PreEscaped, DOCTYPE};
mod assets; mod assets;
pub use assets::javascript::{JavaScript, ModeJS}; pub use assets::javascript::{JavaScript, ModeJS};

344
pagetop/src/html/maud.rs Normal file
View file

@ -0,0 +1,344 @@
//#![no_std]
//! A macro for writing HTML templates.
//!
//! This documentation only describes the runtime API. For a general
//! guide, check out the [book] instead.
//!
//! [book]: https://maud.lambda.xyz/
//#![doc(html_root_url = "https://docs.rs/maud/0.25.0")]
extern crate alloc;
use alloc::{borrow::Cow, boxed::Box, string::String};
use core::fmt::{self, Arguments, Display, Write};
pub use pagetop_macros::html;
mod escape;
/// An adapter that escapes HTML special characters.
///
/// The following characters are escaped:
///
/// * `&` is escaped as `&`
/// * `<` is escaped as `&lt;`
/// * `>` is escaped as `&gt;`
/// * `"` is escaped as `&quot;`
///
/// All other characters are passed through unchanged.
///
/// **Note:** In versions prior to 0.13, the single quote (`'`) was
/// escaped as well.
///
/// # Example
///
/// ```rust
/// use maud::Escaper;
/// use std::fmt::Write;
/// let mut s = String::new();
/// write!(Escaper::new(&mut s), "<script>launchMissiles()</script>").unwrap();
/// assert_eq!(s, "&lt;script&gt;launchMissiles()&lt;/script&gt;");
/// ```
pub struct Escaper<'a>(&'a mut String);
impl<'a> Escaper<'a> {
/// Creates an `Escaper` from a `String`.
pub fn new(buffer: &'a mut String) -> Escaper<'a> {
Escaper(buffer)
}
}
impl<'a> fmt::Write for Escaper<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
escape::escape_to_string(s, self.0);
Ok(())
}
}
/// Represents a type that can be rendered as HTML.
///
/// To implement this for your own type, override either the `.render()`
/// or `.render_to()` methods; since each is defined in terms of the
/// other, you only need to implement one of them. See the example below.
///
/// # Minimal implementation
///
/// An implementation of this trait must override at least one of
/// `.render()` or `.render_to()`. Since the default definitions of
/// these methods call each other, not doing this will result in
/// infinite recursion.
///
/// # Example
///
/// ```rust
/// use maud::{html, Markup, Render};
///
/// /// Provides a shorthand for linking to a CSS stylesheet.
/// pub struct Stylesheet(&'static str);
///
/// impl Render for Stylesheet {
/// fn render(&self) -> Markup {
/// html! {
/// link rel="stylesheet" type="text/css" href=(self.0);
/// }
/// }
/// }
/// ```
pub trait Render {
/// Renders `self` as a block of `Markup`.
fn render(&self) -> Markup {
let mut buffer = String::new();
self.render_to(&mut buffer);
PreEscaped(buffer)
}
/// Appends a representation of `self` to the given buffer.
///
/// Its default implementation just calls `.render()`, but you may
/// override it with something more efficient.
///
/// Note that no further escaping is performed on data written to
/// the buffer. If you override this method, you must make sure that
/// any data written is properly escaped, whether by hand or using
/// the [`Escaper`](struct.Escaper.html) wrapper struct.
fn render_to(&self, buffer: &mut String) {
buffer.push_str(&self.render().into_string());
}
}
impl Render for str {
fn render_to(&self, w: &mut String) {
escape::escape_to_string(self, w);
}
}
impl Render for String {
fn render_to(&self, w: &mut String) {
str::render_to(self, w);
}
}
impl<'a> Render for Cow<'a, str> {
fn render_to(&self, w: &mut String) {
str::render_to(self, w);
}
}
impl<'a> Render for Arguments<'a> {
fn render_to(&self, w: &mut String) {
let _ = Escaper::new(w).write_fmt(*self);
}
}
impl<'a, T: Render + ?Sized> Render for &'a T {
fn render_to(&self, w: &mut String) {
T::render_to(self, w);
}
}
impl<'a, T: Render + ?Sized> Render for &'a mut T {
fn render_to(&self, w: &mut String) {
T::render_to(self, w);
}
}
impl<T: Render + ?Sized> Render for Box<T> {
fn render_to(&self, w: &mut String) {
T::render_to(self, w);
}
}
macro_rules! impl_render_with_display {
($($ty:ty)*) => {
$(
impl Render for $ty {
fn render_to(&self, w: &mut String) {
// TODO: remove the explicit arg when Rust 1.58 is released
format_args!("{self}", self = self).render_to(w);
}
}
)*
};
}
impl_render_with_display! {
char f32 f64
}
macro_rules! impl_render_with_itoa {
($($ty:ty)*) => {
$(
impl Render for $ty {
fn render_to(&self, w: &mut String) {
w.push_str(itoa::Buffer::new().format(*self));
}
}
)*
};
}
impl_render_with_itoa! {
i8 i16 i32 i64 i128 isize
u8 u16 u32 u64 u128 usize
}
/// Renders a value using its [`Display`] impl.
///
/// # Example
///
/// ```rust
/// use maud::html;
/// use std::net::Ipv4Addr;
///
/// let ip_address = Ipv4Addr::new(127, 0, 0, 1);
///
/// let markup = html! {
/// "My IP address is: "
/// (maud::display(ip_address))
/// };
///
/// assert_eq!(markup.into_string(), "My IP address is: 127.0.0.1");
/// ```
pub fn display(value: impl Display) -> impl Render {
struct DisplayWrapper<T>(T);
impl<T: Display> Render for DisplayWrapper<T> {
fn render_to(&self, w: &mut String) {
format_args!("{0}", self.0).render_to(w);
}
}
DisplayWrapper(value)
}
/// A wrapper that renders the inner value without escaping.
#[derive(Debug, Clone, Copy)]
pub struct PreEscaped<T: AsRef<str>>(pub T);
impl<T: AsRef<str>> Render for PreEscaped<T> {
fn render_to(&self, w: &mut String) {
w.push_str(self.0.as_ref());
}
}
/// A block of markup is a string that does not need to be escaped.
///
/// The `html!` macro expands to an expression of this type.
pub type Markup = PreEscaped<String>;
impl<T: AsRef<str> + Into<String>> PreEscaped<T> {
/// Converts the inner value to a string.
pub fn into_string(self) -> String {
self.0.into()
}
}
impl<T: AsRef<str> + Into<String>> From<PreEscaped<T>> for String {
fn from(value: PreEscaped<T>) -> String {
value.into_string()
}
}
impl<T: AsRef<str> + Default> Default for PreEscaped<T> {
fn default() -> Self {
Self(Default::default())
}
}
/// The literal string `<!DOCTYPE html>`.
///
/// # Example
///
/// A minimal web page:
///
/// ```rust
/// use maud::{DOCTYPE, html};
///
/// let markup = html! {
/// (DOCTYPE)
/// html {
/// head {
/// meta charset="utf-8";
/// title { "Test page" }
/// }
/// body {
/// p { "Hello, world!" }
/// }
/// }
/// };
/// ```
pub const DOCTYPE: PreEscaped<&'static str> = PreEscaped("<!DOCTYPE html>");
mod actix_support {
extern crate alloc;
use crate::html::PreEscaped;
use actix_web::{http::header, HttpRequest, HttpResponse, Responder};
use alloc::string::String;
impl Responder for PreEscaped<String> {
type Body = String;
fn respond_to(self, _req: &HttpRequest) -> HttpResponse<Self::Body> {
HttpResponse::Ok()
.content_type(header::ContentType::html())
.message_body(self.0)
.unwrap()
}
}
}
#[doc(hidden)]
pub mod html_private {
extern crate alloc;
use super::{display, Render};
use alloc::string::String;
use core::fmt::Display;
#[doc(hidden)]
#[macro_export]
macro_rules! render_to {
($x:expr, $buffer:expr) => {{
use $crate::html::html_private::*;
match ChooseRenderOrDisplay($x) {
x => (&&x).implements_render_or_display().render_to(x.0, $buffer),
}
}};
}
pub use render_to;
pub struct ChooseRenderOrDisplay<T>(pub T);
pub struct ViaRenderTag;
pub struct ViaDisplayTag;
pub trait ViaRender {
fn implements_render_or_display(&self) -> ViaRenderTag {
ViaRenderTag
}
}
pub trait ViaDisplay {
fn implements_render_or_display(&self) -> ViaDisplayTag {
ViaDisplayTag
}
}
impl<T: Render> ViaRender for &ChooseRenderOrDisplay<T> {}
impl<T: Display> ViaDisplay for ChooseRenderOrDisplay<T> {}
impl ViaRenderTag {
pub fn render_to<T: Render + ?Sized>(self, value: &T, buffer: &mut String) {
value.render_to(buffer);
}
}
impl ViaDisplayTag {
pub fn render_to<T: Display + ?Sized>(self, value: &T, buffer: &mut String) {
display(value).render_to(buffer);
}
}
}

View file

@ -0,0 +1,34 @@
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!! PLEASE KEEP THIS IN SYNC WITH `maud_macros/src/escape.rs` !!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
extern crate alloc;
use alloc::string::String;
pub fn escape_to_string(input: &str, output: &mut String) {
for b in input.bytes() {
match b {
b'&' => output.push_str("&amp;"),
b'<' => output.push_str("&lt;"),
b'>' => output.push_str("&gt;"),
b'"' => output.push_str("&quot;"),
_ => unsafe { output.as_mut_vec().push(b) },
}
}
}
#[cfg(test)]
mod test {
extern crate alloc;
use super::escape_to_string;
use alloc::string::String;
#[test]
fn it_works() {
let mut s = String::new();
escape_to_string("<script>launchMissiles()</script>", &mut s);
assert_eq!(s, "&lt;script&gt;launchMissiles()&lt;/script&gt;");
}
}