diff --git a/src/check.rs b/src/check.rs index 4fc811f..c4f3387 100644 --- a/src/check.rs +++ b/src/check.rs @@ -14,10 +14,13 @@ pub fn is_ascii_alphanumeric(c: char) -> bool { /// doesn't give an easy answer. Because of this, we're conservative in what we /// allow. This way, the output we produce should parse correctly in a wide /// range of circumstances while following the standard. +/// +/// The `annotation-xml` MathML element requires us to allow dashes in tag +/// names. pub fn is_valid_tag_name(name: &str) -> bool { !name.is_empty() && name.chars().take(1).all(is_ascii_alpha) - && name.chars().all(is_ascii_alphanumeric) + && name.chars().all(|c| is_ascii_alphanumeric(c) || c == '-') } /// diff --git a/src/element.rs b/src/element.rs index 8da0968..e12112b 100644 --- a/src/element.rs +++ b/src/element.rs @@ -63,8 +63,13 @@ pub struct Element { impl Element { pub fn new(name: impl ToString, kind: ElementKind) -> Self { + let mut name = name.to_string(); + if kind == ElementKind::Foreign { + name = name.to_ascii_lowercase() + } + Self { - name: name.to_string().to_ascii_lowercase(), + name, kind, attributes: BTreeMap::new(), children: vec![], diff --git a/src/elements.rs b/src/html.rs similarity index 96% rename from src/elements.rs rename to src/html.rs index 2e117e7..f518fbe 100644 --- a/src/elements.rs +++ b/src/html.rs @@ -112,9 +112,7 @@ element!(portal); element!(source, ElementKind::Void); // SVG and MathML -// TODO Proper SVG and MathML support -element!(svg, ElementKind::Foreign); -element!(math, ElementKind::Foreign); +// See corresponding modules // Scripting element!(canvas); diff --git a/src/lib.rs b/src/lib.rs index 7a186fd..3b157fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,14 +5,16 @@ mod check; mod element; -pub mod elements; +pub mod html; +pub mod mathml; mod render; +pub mod svg; -pub use self::{element::*, elements::*, render::*}; +pub use self::{element::*, render::*}; #[cfg(test)] mod tests { - use crate::{elements::*, render::Render, Content, Element}; + use crate::{html::*, Content, Element, Render}; #[test] fn simple_website() { diff --git a/src/mathml.rs b/src/mathml.rs new file mode 100644 index 0000000..f9c091e --- /dev/null +++ b/src/mathml.rs @@ -0,0 +1,50 @@ +//! Definitions for all non-deprecated MathML elements. +//! +//! + +use crate::{Element, ElementKind}; + +macro_rules! element { + ( $name:ident ) => { + element!($name, stringify!($name)); + }; + ( $name:ident, $tag:expr ) => { + pub fn $name() -> Element { + Element::new($tag, ElementKind::Foreign) + } + }; +} + +// MathML elements A to Z + +// Deprecated and non-standard elements intentionally omitted. + +element!(annotation); +element!(annotation_xml, "annotation-xml"); +element!(math); +element!(merror); +element!(mfrac); +element!(mi); +element!(mmultiscripts); +element!(mn); +element!(mo); +element!(mover); +element!(mpadded); +element!(mphantom); +element!(mprescripts); +element!(mroot); +element!(mrow); +element!(ms); +element!(mspace); +element!(msqrt); +element!(mstyle); +element!(msub); +element!(msubsup); +element!(msup); +element!(mtable); +element!(mtd); +element!(mtext); +element!(mtr); +element!(munder); +element!(munderover); +element!(semantics); diff --git a/src/svg.rs b/src/svg.rs new file mode 100644 index 0000000..bf450fe --- /dev/null +++ b/src/svg.rs @@ -0,0 +1,84 @@ +//! Definitions for all non-deprecated SVG elements. +//! +//! + +use crate::{Element, ElementKind}; + +macro_rules! element { + ( $name:ident ) => { + element!($name, stringify!($name)); + }; + ( $name:ident, $tag:expr ) => { + pub fn $name() -> Element { + Element::new($tag, ElementKind::Foreign) + } + }; +} + +// SVG elements A to Z + +// Deprecated elements intentionally omitted. + +element!(a); +element!(animate); +element!(animate_motion, "animateMotion"); +element!(animate_transform, "animateTransform"); +element!(circle); +element!(clip_path, "clipPath"); +element!(defs); +element!(desc); +element!(ellipse); +element!(fe_blend, "feBlend"); +element!(fe_color_matrix, "feColorMatrix"); +element!(fe_component_transfer, "feComponentTransfer"); +element!(fe_composite, "feComposite"); +element!(fe_convolve_matrix, "feConvolveMatrix"); +element!(fe_diffuse_lighting, "feDiffuseLighting"); +element!(fe_displacement_map, "feDisplacementMap"); +element!(fe_distant_light, "feDistantLight"); +element!(fe_drop_shadow, "feDropShadow"); +element!(fe_flood, "feFlood"); +element!(fe_func_a, "feFuncA"); +element!(fe_func_b, "feFuncB"); +element!(fe_func_g, "feFuncG"); +element!(fe_func_r, "feFuncR"); +element!(fe_gaussian_blue, "feGaussianBlur"); +element!(fe_image, "feImage"); +element!(fe_merge, "feMerge"); +element!(fe_merge_node, "feMergeNode"); +element!(fe_morphology, "feMorphology"); +element!(fe_offset, "feOffset"); +element!(fe_point_light, "fePointLight"); +element!(fe_specular_lighting, "feSpecularLighting"); +element!(fe_spot_light, "feSpotLight"); +element!(fe_tile, "feTile"); +element!(fe_turbulence, "feTurbulence"); +element!(filter); +element!(foreign_object, "foreignObject"); +element!(g); +element!(image); +element!(line); +element!(linear_gradient, "linearGradient"); +element!(marker); +element!(mask); +element!(metadata); +element!(mpath); +element!(path); +element!(pattern); +element!(polygon); +element!(polyline); +element!(radial_gradient, "radialGradient"); +element!(rect); +element!(script); +element!(set); +element!(stop); +element!(style); +element!(svg); +element!(switch); +element!(symbol); +element!(text); +element!(text_path, "textPath"); +element!(title); +element!(tspan); +element!(r#use); +element!(view);