mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-12 23:57:09 +00:00
feat: attributes on body and html
This commit is contained in:
parent
f70702c6c4
commit
8a878eaaa4
2 changed files with 76 additions and 67 deletions
|
@ -51,6 +51,7 @@ use futures::{Stream, StreamExt};
|
|||
use leptos::{
|
||||
attr::NextAttribute,
|
||||
component,
|
||||
html::attributes_to_html,
|
||||
logging::debug_warn,
|
||||
reactive_graph::owner::{provide_context, use_context},
|
||||
tachys::{
|
||||
|
@ -234,7 +235,13 @@ impl ServerMetaContextOutput {
|
|||
// collect all registered meta tags
|
||||
let meta_buf = self.elements.into_iter().collect::<String>();
|
||||
|
||||
let modified_chunk = if title_len == 0 && meta_buf.is_empty() {
|
||||
// get HTML strings for `<html>` and `<body>`
|
||||
let mut html_attrs = String::new();
|
||||
_ = attributes_to_html(self.html, &mut html_attrs);
|
||||
let mut body_attrs = String::new();
|
||||
_ = attributes_to_html(self.body, &mut body_attrs);
|
||||
|
||||
let mut modified_chunk = if title_len == 0 && meta_buf.is_empty() {
|
||||
first_chunk
|
||||
} else {
|
||||
let mut buf = String::with_capacity(
|
||||
|
@ -263,6 +270,22 @@ impl ServerMetaContextOutput {
|
|||
buf
|
||||
};
|
||||
|
||||
if !html_attrs.is_empty() {
|
||||
if let Some(index) = modified_chunk.find("<html") {
|
||||
// Calculate the position where the new string should be inserted
|
||||
let insert_pos = index + "<html".len();
|
||||
modified_chunk.insert_str(insert_pos, &html_attrs);
|
||||
}
|
||||
}
|
||||
|
||||
if !body_attrs.is_empty() {
|
||||
if let Some(index) = modified_chunk.find("<body") {
|
||||
// Calculate the position where the new string should be inserted
|
||||
let insert_pos = index + "<body".len();
|
||||
modified_chunk.insert_str(insert_pos, &body_attrs);
|
||||
}
|
||||
}
|
||||
|
||||
futures::stream::once(async move { modified_chunk }).chain(stream)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -278,37 +278,7 @@ where
|
|||
buf.push('<');
|
||||
buf.push_str(E::TAG);
|
||||
|
||||
// attributes
|
||||
|
||||
// `class` and `style` are created first, and pushed later
|
||||
// this is because they can be filled by a mixture of values that include
|
||||
// either the whole value (`class="..."` or `style="..."`) and individual
|
||||
// classes and styles (`class:foo=true` or `style:height="40px"`), so they
|
||||
// need to be filled during the whole attribute-creation process and then
|
||||
// added
|
||||
|
||||
// String doesn't allocate until the first push, so this is cheap if there
|
||||
// is no class or style on an element
|
||||
let mut class = String::new();
|
||||
let mut style = String::new();
|
||||
let mut inner_html = String::new();
|
||||
|
||||
// inject regular attributes, and fill class and style
|
||||
self.attributes
|
||||
.to_html(buf, &mut class, &mut style, &mut inner_html);
|
||||
|
||||
if !class.is_empty() {
|
||||
buf.push(' ');
|
||||
buf.push_str("class=\"");
|
||||
buf.push_str(&escape_attr(class.trim_start().trim_end()));
|
||||
buf.push('"');
|
||||
}
|
||||
if !style.is_empty() {
|
||||
buf.push(' ');
|
||||
buf.push_str("style=\"");
|
||||
buf.push_str(&escape_attr(style.trim_start().trim_end()));
|
||||
buf.push('"');
|
||||
}
|
||||
let inner_html = attribute_to_html(self.attributes, buf);
|
||||
|
||||
buf.push('>');
|
||||
|
||||
|
@ -346,41 +316,7 @@ where
|
|||
buf.push('<');
|
||||
buf.push_str(E::TAG);
|
||||
|
||||
// attributes
|
||||
|
||||
// `class` and `style` are created first, and pushed later
|
||||
// this is because they can be filled by a mixture of values that include
|
||||
// either the whole value (`class="..."` or `style="..."`) and individual
|
||||
// classes and styles (`class:foo=true` or `style:height="40px"`), so they
|
||||
// need to be filled during the whole attribute-creation process and then
|
||||
// added
|
||||
|
||||
// String doesn't allocate until the first push, so this is cheap if there
|
||||
// is no class or style on an element
|
||||
let mut class = String::new();
|
||||
let mut style = String::new();
|
||||
let mut inner_html = String::new();
|
||||
|
||||
// inject regular attributes, and fill class and style
|
||||
self.attributes.to_html(
|
||||
&mut buf,
|
||||
&mut class,
|
||||
&mut style,
|
||||
&mut inner_html,
|
||||
);
|
||||
|
||||
if !class.is_empty() {
|
||||
buf.push(' ');
|
||||
buf.push_str("class=\"");
|
||||
buf.push_str(class.trim_start().trim_end());
|
||||
buf.push('"');
|
||||
}
|
||||
if !style.is_empty() {
|
||||
buf.push(' ');
|
||||
buf.push_str("style=\"");
|
||||
buf.push_str(style.trim_start().trim_end());
|
||||
buf.push('"');
|
||||
}
|
||||
let inner_html = attribute_to_html(self.attributes, &mut buf);
|
||||
|
||||
buf.push('>');
|
||||
buffer.push_sync(&buf);
|
||||
|
@ -450,6 +386,56 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn attribute_to_html<At, R>(attribute: At, buf: &mut String) -> String
|
||||
where
|
||||
At: Attribute<R>,
|
||||
R: Renderer,
|
||||
{
|
||||
attributes_to_html(std::iter::once(attribute), buf)
|
||||
}
|
||||
|
||||
pub fn attributes_to_html<At, R>(
|
||||
attributes: impl IntoIterator<Item = At>,
|
||||
buf: &mut String,
|
||||
) -> String
|
||||
where
|
||||
At: Attribute<R>,
|
||||
R: Renderer,
|
||||
{
|
||||
// `class` and `style` are created first, and pushed later
|
||||
// this is because they can be filled by a mixture of values that include
|
||||
// either the whole value (`class="..."` or `style="..."`) and individual
|
||||
// classes and styles (`class:foo=true` or `style:height="40px"`), so they
|
||||
// need to be filled during the whole attribute-creation process and then
|
||||
// added
|
||||
|
||||
// String doesn't allocate until the first push, so this is cheap if there
|
||||
// is no class or style on an element
|
||||
let mut class = String::new();
|
||||
let mut style = String::new();
|
||||
let mut inner_html = String::new();
|
||||
|
||||
// inject regular attributes, and fill class and style
|
||||
for attr in attributes {
|
||||
attr.to_html(buf, &mut class, &mut style, &mut inner_html);
|
||||
}
|
||||
|
||||
if !class.is_empty() {
|
||||
buf.push(' ');
|
||||
buf.push_str("class=\"");
|
||||
buf.push_str(&escape_attr(class.trim_start().trim_end()));
|
||||
buf.push('"');
|
||||
}
|
||||
if !style.is_empty() {
|
||||
buf.push(' ');
|
||||
buf.push_str("style=\"");
|
||||
buf.push_str(&escape_attr(style.trim_start().trim_end()));
|
||||
buf.push('"');
|
||||
}
|
||||
|
||||
inner_html
|
||||
}
|
||||
|
||||
pub struct ElementState<At, Ch, R: Renderer> {
|
||||
pub el: R::Element,
|
||||
pub attrs: At,
|
||||
|
|
Loading…
Reference in a new issue