Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impl builder #1

Merged
merged 42 commits into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
727af4b
feat: add basic implementation for MathML global attributes
nfejzic Nov 7, 2023
a1d7b46
feat: add basic implementation for annotation element
nfejzic Nov 7, 2023
9abf901
feat: implement basics of some elements
nfejzic Nov 9, 2023
ecfe9ec
feat: implement more elements
nfejzic Nov 12, 2023
0569f4a
feat: implement more elements
nfejzic Nov 13, 2023
3bb0605
fix: ignore html and javascript files used for testing
nfejzic Nov 13, 2023
305ad42
feat: implement the rest of elements
nfejzic Nov 13, 2023
1fcdf1e
feat: group elements as defined in MathMl spec
nfejzic Nov 13, 2023
d17ea5f
feat: implement builder pattern for `mfrac`
nfejzic Nov 19, 2023
70477d8
feat: derive useful traits for marker structs
nfejzic Nov 19, 2023
0ead087
docs: hide marker structs in documentation
nfejzic Nov 19, 2023
97a229f
feat: implement builder pattern for `annotation`
nfejzic Nov 19, 2023
c0ce1b0
feat: implement builder pattern for `semantics`
nfejzic Nov 19, 2023
e917f5d
fix: generalize `from_types` macro
nfejzic Nov 19, 2023
6da8df0
feat: improve docs and impl builder for `maction`
nfejzic Nov 21, 2023
77d93b6
feat: implement builder for `math`
nfejzic Nov 21, 2023
bcdfdca
feat: implement builder for `merror`
nfejzic Nov 21, 2023
14c0ca6
feat: implement builder for `mi` element (`ident`)
nfejzic Nov 21, 2023
5d04c0a
feat: impl builder pattern for multiscripts
nfejzic Nov 21, 2023
fc35c0d
feat: implement building patterns for mn, mo
nfejzic Nov 21, 2023
dfd02c0
feat: implement building of `padded`
nfejzic Nov 21, 2023
81d3baa
feat: implement building of `phantom`
nfejzic Nov 21, 2023
c89aa73
feat: implement builder for radicals
nfejzic Nov 21, 2023
6cb213e
feat: improve API of `mrow`
nfejzic Nov 21, 2023
b717979
feat: improve API of `ms`, `mspace` and `mstyle`
nfejzic Nov 21, 2023
53729d2
feat: impl builder for `msub`, `msup` and `msubsup`
nfejzic Nov 21, 2023
a1aaf83
feat: improve API of `Table`, `TableRow` and `TableCell`
nfejzic Nov 21, 2023
d35ad91
feat: add helper function to add attributes to table
nfejzic Nov 22, 2023
f55998e
feat: improve API of Text element
nfejzic Nov 22, 2023
df564d0
feat: implement builder for `munderover` element
nfejzic Nov 22, 2023
0b27ed4
docs: resolve documentation warnings
nfejzic Nov 24, 2023
6f215e6
feat: add `Tag` variants and helper macro for conversion
nfejzic Nov 24, 2023
5c7f2d8
feat: implement annotation and semantics to tag conversion
nfejzic Nov 24, 2023
323be61
fix: improve tag_from_type macro
nfejzic Nov 24, 2023
7f2943f
feat: implement action to tag conversion
nfejzic Nov 24, 2023
fdaa0e8
docs: add todo comment regarding math element
nfejzic Nov 24, 2023
aa77c3c
feat: impl from error for tag
nfejzic Nov 24, 2023
339563e
feat: impl from frac for tag
nfejzic Nov 24, 2023
cb3ac83
feat: impl from ident for tag
nfejzic Nov 24, 2023
fa9d153
feat: impl from multiscripts for tag
nfejzic Nov 24, 2023
d3d95e5
feat: implement rest of the conversions to `Tag`
nfejzic Nov 25, 2023
5c87016
fix: lint clippy.nursery and fix lint warnings
nfejzic Nov 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
/target
/Cargo.lock

*.html
*.js
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ license = "Apache-2.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lints.clippy]
nursery = "warn"

[dependencies]
75 changes: 75 additions & 0 deletions src/attributes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/// Direction for [`Attribute::Dir`].
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Dir {
RightToLeft,
LeftToRight,
}

/// ScriptLevel for [`Attribute::ScriptLevel`].
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum ScriptLevel {
Add(usize),
Sub(usize),
Num(usize),
}

/// Attribute of a MathML element.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Attribute {
/// Class of the element, same as in HTML.
Class(String),

/// Data attribute with custom name and value (e.g. `data-name="value"`).
Data {
/// Name of the data attribute, the part after `data-` prefix. e.g. `data-abc="2"` has the
/// name "abc".
name: String,

/// The value of the data attribute. e.g. `data-name="test"` has value "test".
value: String,
},

/// Direction of the math element. Must be either `rtl` (`RightToLeft`) or `ltr`
/// (`LeftToRight`).
Dir(Dir),

/// Display style of the element, `true` maps to `normal` and `false` to `compact`.
DisplayStyle(bool),

/// Id of the element, same as in HTML.
Id(String),

/// Presentational hint for the background color of the element. Must be a value that is
/// [color](https://www.w3.org/TR/css-color-4/#propdef-color)
MathBackground(String),

/// Presentational hint for the color of the element. Must be a value that is
/// [color](https://www.w3.org/TR/css-color-4/#propdef-color).
MathColor(String),

/// Presentational hint for the font size of the element. Must be a value that is
/// [length-percentage](https://www.w3.org/TR/css-values-4/#typedef-length-percentage).
MathSize(String),

/// The `nonce` attribute, same as in HTML.
Nonce(String),

/// Presentational hint for setting the element's math-depth property to the corresponding
/// value. Can be `+<U>` ([`ScriptLevel::Add`]), `-<U>` ([`ScriptLevel::Sub`]) or `<U>`
/// ([`ScriptLevel::Num`]) where `<U>` is a [`usize`].
ScriptLevel(ScriptLevel),

/// The `style` attribute of the element, same as in HTML.
Style(String),

/// The `tabindex` attribute, same as in HTML.
TabIndex(i16),

OnHandler {
/// Name of the event.
name: String,

/// Handler function for the event.
handler: String,
},
}
57 changes: 57 additions & 0 deletions src/elements.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//! Elements found in the MathML Core Specification. These elements are called MathML Core
//! elements.

mod maction;
mod math;
mod merror;
mod mmultiscripts;
mod mphantom;
mod mrow;
mod mstyle;

pub mod grouping {
pub use super::maction::*;
pub use super::math::*;
pub use super::merror::*;
pub use super::mmultiscripts::Prescripts;
pub use super::mphantom::*;
pub use super::mrow::*;
pub use super::mstyle::*;
}

mod mroot;

pub mod radicals {
pub use super::mroot::*;
}

mod msubsup;
mod munderover;

pub mod scripted {
pub use super::mmultiscripts::Multiscripts;
pub use super::msubsup::*;
pub use super::munderover::*;
}

mod annotation;
mod mfrac;
mod mi;
mod mn;
mod mo;
mod mpadded;
mod ms;
mod mspace;
mod mtable;
mod mtext;

pub use annotation::*;
pub use mfrac::*;
pub use mi::*;
pub use mn::*;
pub use mo::*;
pub use mpadded::*;
pub use ms::*;
pub use mspace::*;
pub use mtable::*;
pub use mtext::*;
168 changes: 168 additions & 0 deletions src/elements/annotation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
use std::marker::PhantomData;

use crate::{
attributes::Attribute,
markers::{Init, Uninit},
MathMl,
};

/// The content of `annotation` element, either text or MathML.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum AnnotationContent {
Text(String),
MathMl(MathMl),
}

impl From<String> for AnnotationContent {
fn from(value: String) -> Self {
Self::Text(value)
}
}

impl<T> From<T> for AnnotationContent
where
T: Into<MathMl>,
{
fn from(value: T) -> Self {
Self::MathMl(value.into())
}
}

/// An attribute of `annotation` element. Either one of the global [`Attribute`]s, or `encode`
/// attribute.
///
/// [`Attribute`]: crate::attributes::Attribute
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum AnnotationAttr {
Global(Attribute),
Encoding(String),
}

impl From<Attribute> for AnnotationAttr {
fn from(value: Attribute) -> Self {
Self::Global(value)
}
}

/// The `annotation` (and `annotation-xml`) element.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Annotation {
content: AnnotationContent,
attributes: Vec<AnnotationAttr>,
}

impl Annotation {
pub fn builder() -> AnnotationBuilder<Uninit> {
AnnotationBuilder::default()
}
}

impl<T> From<T> for Annotation
where
T: Into<AnnotationContent>,
{
fn from(value: T) -> Self {
Self {
content: value.into(),
attributes: Default::default(),
}
}
}

crate::tag_from_type!(Annotation => Annotation);

#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct AnnotationBuilder<T> {
content: Option<AnnotationContent>,
attr: Vec<AnnotationAttr>,

_marker: PhantomData<(T,)>,
}

impl<T> AnnotationBuilder<T> {
pub fn content(self, content: impl Into<AnnotationContent>) -> AnnotationBuilder<Init> {
AnnotationBuilder {
content: Some(content.into()),
attr: self.attr,
_marker: PhantomData,
}
}

pub fn attr<I, A>(mut self, attr: I) -> Self
where
I: IntoIterator<Item = A>,
A: Into<AnnotationAttr>,
{
self.attr.extend(attr.into_iter().map(Into::into));
self
}
}

impl AnnotationBuilder<Init> {
pub fn build(self) -> Annotation {
Annotation {
content: self
.content
.expect("Content is guaranteed to be initialized at compile time."),
attributes: self.attr,
}
}
}

/// The `semantics` element is the container element that associates annotations with a MathML
/// expression. Typically, the `semantics` element has as its first child element a MathML
/// expression to be annotated while subsequent child elements represent text annotations within an
/// `annotation` element, or more complex markup annotations within an `annotation-xml` element.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Semantics {
/// Children of the `semantics` element. Rendering is same as `mrow`.
children: MathMl,

/// The `semantics` element accepts the global [`Attribute`]s.
attr: Vec<Attribute>,
}

impl Semantics {
pub fn builder() -> SemanticsBuilder<Uninit> {
SemanticsBuilder::default()
}
}

crate::tag_from_type!(Semantics => Semantics);

#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct SemanticsBuilder<T> {
content: Option<MathMl>,
attr: Vec<Attribute>,

_marker: PhantomData<(T,)>,
}

impl<T> SemanticsBuilder<T> {
pub fn content(self, content: impl Into<MathMl>) -> SemanticsBuilder<Init> {
SemanticsBuilder {
content: Some(content.into()),
attr: self.attr,
_marker: PhantomData,
}
}

pub fn attr<A>(mut self, attr: A) -> Self
where
A: IntoIterator<Item = Attribute>,
{
self.attr.extend(attr);
self
}
}

impl SemanticsBuilder<Init> {
pub fn build(self) -> Semantics {
Semantics {
children: self
.content
.expect("Content is guaranteed to be initialized at compile time."),
attr: self.attr,
}
}
}
Loading
Loading