use crate::{Attributes, Html, Compactability, Sum, AttributeName, AttributeValue, HtmlEnv, Empty};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Tag<'t, A: Attributes, I: Html, const SILENT: bool> { tag: &'t str,
attributes: A,
inner_html: I,
compactability: Compactability,
}
impl<'n, A: Attributes, I: Html, const SILENT: bool> Tag<'n, A, I, SILENT> {
pub fn child<C: Html>(
self,
child: C,
) -> Tag<'n, A, Sum<I, C>, SILENT> {
Tag {
tag: self.tag,
attributes: self.attributes,
inner_html: Sum(self.inner_html, child),
compactability: self.compactability,
}
}
pub fn attributes<B: Attributes>(
self,
attributes: B,
) -> Tag<'n, Sum<A, B>, I, SILENT> {
Tag {
tag: self.tag,
attributes: Sum(self.attributes, attributes),
inner_html: self.inner_html,
compactability: self.compactability,
}
}
pub fn attr<Name: AttributeName, Value: AttributeValue>(
self,
name: Name,
value: Value,
) -> Tag<'n, Sum<A, [(Name, Value); 1]>, I, SILENT> {
Tag {
tag: self.tag,
attributes: Sum(self.attributes, [(name, value)]),
inner_html: self.inner_html,
compactability: self.compactability,
}
}
}
impl<'n, A: Attributes, I: Html, const SILENT: bool> Html for Tag<'n, A, I, SILENT> {
fn write_html(self, env: &mut impl crate::HtmlEnv) -> std::fmt::Result {
if SILENT {
if !self.inner_html.is_unit() {
env.write_html(self.inner_html).map(|_| ())
} else {
Ok(())
}
} else {
if self.inner_html.is_unit() {
env
.open_tag(self.tag, self.compactability)?
.with_attributes(self.attributes)
.map(|_| ())
} else {
env
.open_tag(self.tag, self.compactability)?
.with_attributes(self.attributes)?
.inner_html()?
.write_html(self.inner_html)
.map(|_| ())
}
}
}
}
pub fn tag<'t, A: Attributes, I: Html>(
tag: &'t str,
attributes: A,
inner_html: I,
compactability: Compactability,
) -> Tag<'t, A, I, false> {
Tag {
tag,
attributes,
inner_html,
compactability,
}
}
pub fn fragment<I: Html>(
inner_html: I,
) -> Tag<'static, Empty, I, true> {
Tag {
tag: "",
attributes: Empty,
inner_html,
compactability: Compactability::No,
}
}
macro_rules! define_tag {
($(#[$attr:meta])* $tag:ident $compactability:expr) => {
$(#[$attr])*
pub fn $tag(
attributes: impl Attributes,
inner_html: impl Html,
) -> Tag<'static, impl Attributes, impl Html, false> {
tag(
stringify!($tag),
attributes,
inner_html,
$compactability,
)
}
};
}
define_tag!(
a
Compactability::No
);
define_tag!(
abbr
Compactability::No
);
define_tag!(
address
Compactability::No
);
define_tag!(
area
Compactability::Yes { final_slash: false }
);
define_tag!(
article
Compactability::No
);
define_tag!(
aside
Compactability::No
);
define_tag!(
audio
Compactability::No
);
define_tag!(
b
Compactability::No
);
define_tag!(
base
Compactability::Yes { final_slash: false }
);
define_tag!(
bdi
Compactability::No
);
define_tag!(
bdo
Compactability::No
);
define_tag!(
blockquote
Compactability::No
);
define_tag!(
body
Compactability::No
);
define_tag!(
br
Compactability::Yes { final_slash: false }
);
define_tag!(
button
Compactability::No
);
define_tag!(
canvas
Compactability::No
);
define_tag!(
caption
Compactability::No
);
define_tag!(
cite
Compactability::No
);
define_tag!(
code
Compactability::No
);
define_tag!(
col
Compactability::Yes { final_slash: false }
);
define_tag!(
colgroup
Compactability::No
);
define_tag!(
data
Compactability::No
);
define_tag!(
datalist
Compactability::No
);
define_tag!(
dd
Compactability::No
);
define_tag!(
del
Compactability::No
);
define_tag!(
details
Compactability::No
);
define_tag!(
dfn
Compactability::No
);
define_tag!(
dialog
Compactability::No
);
define_tag!(
div
Compactability::No
);
define_tag!(
dl
Compactability::No
);
define_tag!(
dt
Compactability::No
);
define_tag!(
em
Compactability::No
);
define_tag!(
embed
Compactability::Yes { final_slash: false }
);
define_tag!(
fieldset
Compactability::No
);
define_tag!(
figcaption
Compactability::No
);
define_tag!(
figure
Compactability::No
);
define_tag!(
footer
Compactability::No
);
define_tag!(
form
Compactability::No
);
define_tag!(
h1
Compactability::No
);
define_tag!(
h2
Compactability::No
);
define_tag!(
h3
Compactability::No
);
define_tag!(
h4
Compactability::No
);
define_tag!(
h5
Compactability::No
);
define_tag!(
h6
Compactability::No
);
define_tag!(
head
Compactability::No
);
define_tag!(
header
Compactability::No
);
define_tag!(
hgroup
Compactability::No
);
define_tag!(
hr
Compactability::Yes { final_slash: false }
);
define_tag!(
html
Compactability::No
);
define_tag!(
i
Compactability::No
);
define_tag!(
iframe
Compactability::No
);
define_tag!(
img
Compactability::Yes { final_slash: false }
);
define_tag!(
input
Compactability::Yes { final_slash: false }
);
define_tag!(
ins
Compactability::No
);
define_tag!(
kbd
Compactability::No
);
define_tag!(
label
Compactability::No
);
define_tag!(
legend
Compactability::No
);
define_tag!(
li
Compactability::No
);
define_tag!(
link
Compactability::Yes { final_slash: false }
);
define_tag!(
main
Compactability::No
);
define_tag!(
map
Compactability::No
);
define_tag!(
mark
Compactability::No
);
define_tag!(
meta
Compactability::Yes { final_slash: false }
);
define_tag!(
nav
Compactability::No
);
define_tag!(
noscript
Compactability::No
);
define_tag!(
object
Compactability::No
);
define_tag!(
ol
Compactability::No
);
define_tag!(
optgroup
Compactability::No
);
define_tag!(
option
Compactability::No
);
define_tag!(
output
Compactability::No
);
define_tag!(
p
Compactability::No
);
define_tag!(
param
Compactability::Yes { final_slash: false }
);
define_tag!(
pre
Compactability::No
);
define_tag!(
progress
Compactability::No
);
define_tag!(
q
Compactability::No
);
define_tag!(
rp
Compactability::No
);
define_tag!(
rt
Compactability::No
);
define_tag!(
ruby
Compactability::No
);
define_tag!(
s
Compactability::No
);
define_tag!(
samp
Compactability::No
);
define_tag!(
script
Compactability::No
);
define_tag!(
section
Compactability::No
);
define_tag!(
select
Compactability::No
);
define_tag!(
small
Compactability::No
);
define_tag!(
source
Compactability::Yes { final_slash: false }
);
define_tag!(
span
Compactability::No
);
define_tag!(
strong
Compactability::No
);
define_tag!(
style
Compactability::No
);
define_tag!(
sub
Compactability::No
);
define_tag!(
summary
Compactability::No
);
define_tag!(
sup
Compactability::No
);
define_tag!(
table
Compactability::No
);
define_tag!(
tbody
Compactability::No
);
define_tag!(
td
Compactability::No
);
define_tag!(
template
Compactability::No
);
define_tag!(
textarea
Compactability::No
);
define_tag!(
tfoot
Compactability::No
);
define_tag!(
th
Compactability::No
);
define_tag!(
thead
Compactability::No
);
define_tag!(
time
Compactability::No
);
define_tag!(
title
Compactability::No
);
define_tag!(
tr
Compactability::No
);
define_tag!(
track
Compactability::Yes { final_slash: false }
);
define_tag!(
u
Compactability::No
);
define_tag!(
ul
Compactability::No
);
define_tag!(
var
Compactability::No
);
define_tag!(
video
Compactability::No
);
define_tag!(
wbr
Compactability::Yes { final_slash: false }
);