fix svg attributes
This commit is contained in:
1 parent
ca13bf7358
commit
e444d3d4bc
3 files changed
+156
-131
No files matched your search
@@ -1,49 +1,62 @@
|
|||||||
use crate::elements::*;
|
use crate::elements::*;
|
||||||
|
|
||||||
// map the rsx name of the attribute to the html name of the attribute and the namespace that contains it
|
// map the rsx name of the attribute to the html name of the attribute and the namespace that contains it
|
||||||
pub fn attrbute_to_static_str(attr: &str) -> Option<(&'static str, Option<&'static str>)> {
|
pub fn attrbute_to_static_str(
|
||||||
NO_NAMESPACE_ATTRIBUTES
|
attr: &str,
|
||||||
.iter()
|
element: &'static str,
|
||||||
.find(|&a| *a == attr)
|
namespace: Option<&'static str>,
|
||||||
.map(|a| (*a, None))
|
) -> Option<(&'static str, Option<&'static str>)> {
|
||||||
.or_else(|| {
|
if namespace == Some("http://www.w3.org/2000/svg") {
|
||||||
STYLE_ATTRIBUTES
|
svg::MAPPED_ATTRIBUTES
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(a, _)| *a == attr)
|
.find(|(a, _)| *a == attr)
|
||||||
.map(|(_, b)| (*b, Some("style")))
|
.map(|(_, b)| (*b, None))
|
||||||
|
} else {
|
||||||
|
NO_NAMESPACE_ATTRIBUTES
|
||||||
|
.iter()
|
||||||
|
.find(|&a| *a == attr)
|
||||||
|
.map(|a| (*a, None))
|
||||||
|
.or_else(|| {
|
||||||
|
STYLE_ATTRIBUTES
|
||||||
|
.iter()
|
||||||
|
.find(|(a, _)| *a == attr)
|
||||||
|
.map(|(_, b)| (*b, Some("style")))
|
||||||
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
MAPPED_ATTRIBUTES
|
||||||
|
.iter()
|
||||||
|
.find(|(a, _)| *a == attr)
|
||||||
|
.map(|(_, b)| (*b, None))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
.or_else(|| {
|
||||||
|
ELEMENTS_WITH_MAPPED_ATTRIBUTES
|
||||||
|
.iter()
|
||||||
|
.find_map(|(el, attrs)| {
|
||||||
|
(element == *el)
|
||||||
|
.then(|| {
|
||||||
|
attrs
|
||||||
|
.iter()
|
||||||
|
.find(|(a, _)| *a == attr)
|
||||||
|
.map(|(_, b)| (*b, None))
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
ELEMENTS_WITH_NAMESPACE.iter().find_map(|(el, ns, attrs)| {
|
||||||
|
(element == *el && namespace == Some(*ns))
|
||||||
|
.then(|| attrs.iter().find(|a| **a == attr).map(|a| (*a, None)))
|
||||||
|
.flatten()
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
})
|
||||||
MAPPED_ATTRIBUTES
|
.or_else(|| {
|
||||||
.iter()
|
ELEMENTS_WITHOUT_NAMESPACE.iter().find_map(|(el, attrs)| {
|
||||||
.find(|(a, _)| *a == attr)
|
(element == *el)
|
||||||
.map(|(_, b)| (*b, None))
|
.then(|| attrs.iter().find(|a| **a == attr).map(|a| (*a, None)))
|
||||||
})
|
.flatten()
|
||||||
.or_else(|| {
|
|
||||||
svg::MAPPED_ATTRIBUTES
|
|
||||||
.iter()
|
|
||||||
.find(|(a, _)| *a == attr)
|
|
||||||
.map(|(_, b)| (*b, None))
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
ELEMENTS_WITH_MAPPED_ATTRIBUTES
|
|
||||||
.iter()
|
|
||||||
.find_map(|(_, attrs)| {
|
|
||||||
attrs
|
|
||||||
.iter()
|
|
||||||
.find(|(a, _)| *a == attr)
|
|
||||||
.map(|(_, b)| (*b, None))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
ELEMENTS_WITH_NAMESPACE
|
|
||||||
.iter()
|
|
||||||
.find_map(|(_, _, attrs)| attrs.iter().find(|a| **a == attr).map(|a| (*a, None)))
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
ELEMENTS_WITHOUT_NAMESPACE
|
|
||||||
.iter()
|
|
||||||
.find_map(|(_, attrs)| attrs.iter().find(|a| **a == attr).map(|a| (*a, None)))
|
|
||||||
})
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! no_namespace_trait_methods {
|
macro_rules! no_namespace_trait_methods {
|
||||||
@@ -615,6 +628,7 @@ mapped_trait_methods! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod svg {
|
pub mod svg {
|
||||||
|
|
||||||
mapped_trait_methods! {
|
mapped_trait_methods! {
|
||||||
accent_height: "accent-height",
|
accent_height: "accent-height",
|
||||||
accumulate: "accumulate",
|
accumulate: "accumulate",
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ macro_rules! builder_constructors {
|
|||||||
$(
|
$(
|
||||||
(
|
(
|
||||||
stringify!($name),
|
stringify!($name),
|
||||||
stringify!($namespace),
|
$namespace,
|
||||||
&[
|
&[
|
||||||
$(
|
$(
|
||||||
stringify!($fil),
|
stringify!($fil),
|
||||||
|
|||||||
@@ -76,63 +76,39 @@ fn build_node<'a>(
|
|||||||
Ok(factory.text(format_args!("{}", text)))
|
Ok(factory.text(format_args!("{}", text)))
|
||||||
}
|
}
|
||||||
BodyNode::Element(el) => {
|
BodyNode::Element(el) => {
|
||||||
let attributes: &mut Vec<Attribute> = bump.alloc(Vec::new());
|
let tag = bump.alloc(el.name.to_string());
|
||||||
for attr in &el.attributes {
|
if let Some((tag, ns)) = element_to_static_str(tag) {
|
||||||
match &attr.attr {
|
let attributes: &mut Vec<Attribute> = bump.alloc(Vec::new());
|
||||||
ElementAttr::AttrText { .. } | ElementAttr::CustomAttrText { .. } => {
|
for attr in &el.attributes {
|
||||||
let (name, value, span): (String, IfmtInput, Span) = match &attr.attr {
|
match &attr.attr {
|
||||||
ElementAttr::AttrText { name, value } => (
|
ElementAttr::AttrText { .. } | ElementAttr::CustomAttrText { .. } => {
|
||||||
name.to_string(),
|
let (name, value, span): (String, IfmtInput, Span) = match &attr.attr {
|
||||||
IfmtInput::from_str(&value.value()).map_err(|err| {
|
ElementAttr::AttrText { name, value } => (
|
||||||
Error::ParseError(ParseError::new(err, ctx.location.clone()))
|
name.to_string(),
|
||||||
})?,
|
IfmtInput::from_str(&value.value()).map_err(|err| {
|
||||||
name.span(),
|
Error::ParseError(ParseError::new(
|
||||||
),
|
err,
|
||||||
ElementAttr::CustomAttrText { name, value } => (
|
ctx.location.clone(),
|
||||||
name.value(),
|
))
|
||||||
IfmtInput::from_str(&value.value()).map_err(|err| {
|
})?,
|
||||||
Error::ParseError(ParseError::new(err, ctx.location.clone()))
|
name.span(),
|
||||||
})?,
|
),
|
||||||
name.span(),
|
ElementAttr::CustomAttrText { name, value } => (
|
||||||
),
|
name.value(),
|
||||||
_ => unreachable!(),
|
IfmtInput::from_str(&value.value()).map_err(|err| {
|
||||||
};
|
Error::ParseError(ParseError::new(
|
||||||
|
err,
|
||||||
|
ctx.location.clone(),
|
||||||
|
))
|
||||||
|
})?,
|
||||||
|
name.span(),
|
||||||
|
),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
if let Some((name, namespace)) = attrbute_to_static_str(&name) {
|
if let Some((name, namespace)) = attrbute_to_static_str(&name, tag, ns)
|
||||||
let value = bump.alloc(resolve_ifmt(&value, &ctx.captured)?);
|
{
|
||||||
attributes.push(Attribute {
|
let value = bump.alloc(resolve_ifmt(&value, &ctx.captured)?);
|
||||||
name,
|
|
||||||
value: AttributeValue::Text(value),
|
|
||||||
is_static: true,
|
|
||||||
is_volatile: false,
|
|
||||||
namespace,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Err(Error::ParseError(ParseError::new(
|
|
||||||
syn::Error::new(span, format!("unknown attribute: {}", name)),
|
|
||||||
ctx.location.clone(),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ElementAttr::AttrExpression { .. }
|
|
||||||
| ElementAttr::CustomAttrExpression { .. } => {
|
|
||||||
let (name, value) = match &attr.attr {
|
|
||||||
ElementAttr::AttrExpression { name, value } => {
|
|
||||||
(name.to_string(), value)
|
|
||||||
}
|
|
||||||
ElementAttr::CustomAttrExpression { name, value } => {
|
|
||||||
(name.value(), value)
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
if let Some((_, resulting_value)) = ctx
|
|
||||||
.expressions
|
|
||||||
.iter()
|
|
||||||
.find(|(n, _)| parse_str::<Expr>(*n).unwrap() == *value)
|
|
||||||
{
|
|
||||||
if let Some((name, namespace)) = attrbute_to_static_str(&name) {
|
|
||||||
let value = bump.alloc(resulting_value.clone());
|
|
||||||
attributes.push(Attribute {
|
attributes.push(Attribute {
|
||||||
name,
|
name,
|
||||||
value: AttributeValue::Text(value),
|
value: AttributeValue::Text(value),
|
||||||
@@ -140,47 +116,82 @@ fn build_node<'a>(
|
|||||||
is_volatile: false,
|
is_volatile: false,
|
||||||
namespace,
|
namespace,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
return Err(Error::ParseError(ParseError::new(
|
||||||
|
syn::Error::new(span, format!("unknown attribute: {}", name)),
|
||||||
|
ctx.location.clone(),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementAttr::AttrExpression { .. }
|
||||||
|
| ElementAttr::CustomAttrExpression { .. } => {
|
||||||
|
let (name, value) = match &attr.attr {
|
||||||
|
ElementAttr::AttrExpression { name, value } => {
|
||||||
|
(name.to_string(), value)
|
||||||
|
}
|
||||||
|
ElementAttr::CustomAttrExpression { name, value } => {
|
||||||
|
(name.value(), value)
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
if let Some((_, resulting_value)) = ctx
|
||||||
|
.expressions
|
||||||
|
.iter()
|
||||||
|
.find(|(n, _)| parse_str::<Expr>(*n).unwrap() == *value)
|
||||||
|
{
|
||||||
|
if let Some((name, namespace)) =
|
||||||
|
attrbute_to_static_str(&name, tag, ns)
|
||||||
|
{
|
||||||
|
let value = bump.alloc(resulting_value.clone());
|
||||||
|
attributes.push(Attribute {
|
||||||
|
name,
|
||||||
|
value: AttributeValue::Text(value),
|
||||||
|
is_static: true,
|
||||||
|
is_volatile: false,
|
||||||
|
namespace,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(Error::RecompileRequiredError(
|
||||||
|
RecompileReason::CapturedExpression(
|
||||||
|
value.into_token_stream().to_string(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let children = bump.alloc(Vec::new());
|
||||||
|
for child in el.children {
|
||||||
|
let node = build_node(child, ctx, factory)?;
|
||||||
|
children.push(node);
|
||||||
|
}
|
||||||
|
let listeners = bump.alloc(Vec::new());
|
||||||
|
for attr in el.attributes {
|
||||||
|
if let ElementAttr::EventTokens { .. } = attr.attr {
|
||||||
|
let expr: Expr = parse2(attr.to_token_stream()).map_err(|err| {
|
||||||
|
Error::ParseError(ParseError::new(err, ctx.location.clone()))
|
||||||
|
})?;
|
||||||
|
if let Some(idx) = ctx.listeners.iter().position(|(code, _)| {
|
||||||
|
if let Ok(parsed) = parse_str::<Expr>(*code) {
|
||||||
|
parsed == expr
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
let (_, listener) = ctx.listeners.remove(idx);
|
||||||
|
listeners.push(listener)
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::RecompileRequiredError(
|
return Err(Error::RecompileRequiredError(
|
||||||
RecompileReason::CapturedExpression(
|
RecompileReason::CapturedListener(
|
||||||
value.into_token_stream().to_string(),
|
expr.to_token_stream().to_string(),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
let children = bump.alloc(Vec::new());
|
|
||||||
for child in el.children {
|
|
||||||
let node = build_node(child, ctx, factory)?;
|
|
||||||
children.push(node);
|
|
||||||
}
|
|
||||||
let listeners = bump.alloc(Vec::new());
|
|
||||||
for attr in el.attributes {
|
|
||||||
if let ElementAttr::EventTokens { .. } = attr.attr {
|
|
||||||
let expr: Expr = parse2(attr.to_token_stream()).map_err(|err| {
|
|
||||||
Error::ParseError(ParseError::new(err, ctx.location.clone()))
|
|
||||||
})?;
|
|
||||||
if let Some(idx) = ctx.listeners.iter().position(|(code, _)| {
|
|
||||||
if let Ok(parsed) = parse_str::<Expr>(*code) {
|
|
||||||
parsed == expr
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
let (_, listener) = ctx.listeners.remove(idx);
|
|
||||||
listeners.push(listener)
|
|
||||||
} else {
|
|
||||||
return Err(Error::RecompileRequiredError(
|
|
||||||
RecompileReason::CapturedListener(expr.to_token_stream().to_string()),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let tag = bump.alloc(el.name.to_string());
|
|
||||||
if let Some((tag, ns)) = element_to_static_str(tag) {
|
|
||||||
match el.key {
|
match el.key {
|
||||||
None => Ok(factory.raw_element(
|
None => Ok(factory.raw_element(
|
||||||
tag,
|
tag,
|
||||||
|
|||||||
Reference in new issue
Block a user