html: Add support for mathematical messages
According to MSC2191 / Matrix 1.11
This commit is contained in:
		
							parent
							
								
									ba76e0ee3a
								
							
						
					
					
						commit
						002fe2fb3d
					
				@ -1,5 +1,13 @@
 | 
				
			|||||||
# [unreleased]
 | 
					# [unreleased]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Breaking Changes:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `MatrixElement::Div` is now a newtype variant.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Improvements:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Add support for mathematical messages, according to MSC2191 / Matrix 1.11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# 0.2.0
 | 
					# 0.2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Breaking Changes:
 | 
					Breaking Changes:
 | 
				
			||||||
 | 
				
			|||||||
@ -152,7 +152,7 @@ pub enum MatrixElement {
 | 
				
			|||||||
    /// [`<div>`], a content division element.
 | 
					    /// [`<div>`], a content division element.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// [`<div>`]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div
 | 
					    /// [`<div>`]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div
 | 
				
			||||||
    Div,
 | 
					    Div(DivData),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// [`<table>`], a table element.
 | 
					    /// [`<table>`], a table element.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
@ -268,7 +268,10 @@ impl MatrixElement {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            b"hr" => (Self::Hr, attrs.clone()),
 | 
					            b"hr" => (Self::Hr, attrs.clone()),
 | 
				
			||||||
            b"br" => (Self::Br, attrs.clone()),
 | 
					            b"br" => (Self::Br, attrs.clone()),
 | 
				
			||||||
            b"div" => (Self::Div, attrs.clone()),
 | 
					            b"div" => {
 | 
				
			||||||
 | 
					                let (data, attrs) = DivData::parse(attrs);
 | 
				
			||||||
 | 
					                (Self::Div(data), attrs)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            b"table" => (Self::Table, attrs.clone()),
 | 
					            b"table" => (Self::Table, attrs.clone()),
 | 
				
			||||||
            b"thead" => (Self::Thead, attrs.clone()),
 | 
					            b"thead" => (Self::Thead, attrs.clone()),
 | 
				
			||||||
            b"tbody" => (Self::Tbody, attrs.clone()),
 | 
					            b"tbody" => (Self::Tbody, attrs.clone()),
 | 
				
			||||||
@ -599,12 +602,23 @@ pub struct SpanData {
 | 
				
			|||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// [spoiler message]: https://spec.matrix.org/latest/client-server-api/#spoiler-messages
 | 
					    /// [spoiler message]: https://spec.matrix.org/latest/client-server-api/#spoiler-messages
 | 
				
			||||||
    pub spoiler: Option<StrTendril>,
 | 
					    pub spoiler: Option<StrTendril>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// `data-mx-maths`, an inline Matrix [mathematical message].
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// The value is the mathematical notation in [LaTeX] format.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// If this attribute is present, the content of the span is the fallback representation of the
 | 
				
			||||||
 | 
					    /// mathematical notation.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// [mathematical message]: https://spec.matrix.org/latest/client-server-api/#mathematical-messages
 | 
				
			||||||
 | 
					    /// [LaTeX]: https://www.latex-project.org/
 | 
				
			||||||
 | 
					    pub maths: Option<StrTendril>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl SpanData {
 | 
					impl SpanData {
 | 
				
			||||||
    /// Construct an empty `SpanData`.
 | 
					    /// Construct an empty `SpanData`.
 | 
				
			||||||
    fn new() -> Self {
 | 
					    fn new() -> Self {
 | 
				
			||||||
        Self { bg_color: None, color: None, spoiler: None }
 | 
					        Self { bg_color: None, color: None, spoiler: None, maths: None }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Parse the given attributes to construct a new `SpanData`.
 | 
					    /// Parse the given attributes to construct a new `SpanData`.
 | 
				
			||||||
@ -629,6 +643,9 @@ impl SpanData {
 | 
				
			|||||||
                b"data-mx-spoiler" => {
 | 
					                b"data-mx-spoiler" => {
 | 
				
			||||||
                    data.spoiler = Some(attr.value.clone());
 | 
					                    data.spoiler = Some(attr.value.clone());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                b"data-mx-maths" => {
 | 
				
			||||||
 | 
					                    data.maths = Some(attr.value.clone());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                _ => {
 | 
					                _ => {
 | 
				
			||||||
                    remaining_attrs.insert(attr.clone());
 | 
					                    remaining_attrs.insert(attr.clone());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -722,3 +739,53 @@ impl ImageData {
 | 
				
			|||||||
        (data, remaining_attrs)
 | 
					        (data, remaining_attrs)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// The supported data of a `<div>` HTML element.
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					#[non_exhaustive]
 | 
				
			||||||
 | 
					pub struct DivData {
 | 
				
			||||||
 | 
					    /// `data-mx-maths`, a Matrix [mathematical message] block.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// The value is the mathematical notation in [LaTeX] format.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// If this attribute is present, the content of the div is the fallback representation of the
 | 
				
			||||||
 | 
					    /// mathematical notation.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// [mathematical message]: https://spec.matrix.org/latest/client-server-api/#mathematical-messages
 | 
				
			||||||
 | 
					    /// [LaTeX]: https://www.latex-project.org/
 | 
				
			||||||
 | 
					    pub maths: Option<StrTendril>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl DivData {
 | 
				
			||||||
 | 
					    /// Construct an empty `DivData`.
 | 
				
			||||||
 | 
					    fn new() -> Self {
 | 
				
			||||||
 | 
					        Self { maths: None }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Parse the given attributes to construct a new `SpanData`.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Returns a tuple containing the constructed data and the remaining unsupported attributes.
 | 
				
			||||||
 | 
					    #[allow(clippy::mutable_key_type)]
 | 
				
			||||||
 | 
					    fn parse(attrs: &BTreeSet<Attribute>) -> (Self, BTreeSet<Attribute>) {
 | 
				
			||||||
 | 
					        let mut data = Self::new();
 | 
				
			||||||
 | 
					        let mut remaining_attrs = BTreeSet::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for attr in attrs {
 | 
				
			||||||
 | 
					            if attr.name.ns != ns!() {
 | 
				
			||||||
 | 
					                remaining_attrs.insert(attr.clone());
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            match attr.name.local.as_bytes() {
 | 
				
			||||||
 | 
					                b"data-mx-maths" => {
 | 
				
			||||||
 | 
					                    data.maths = Some(attr.value.clone());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                _ => {
 | 
				
			||||||
 | 
					                    remaining_attrs.insert(attr.clone());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        (data, remaining_attrs)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -28,14 +28,16 @@ static ALLOWED_ATTRIBUTES_STRICT: Map<&str, &Set<&str>> = phf_map! {
 | 
				
			|||||||
    "img" => &ALLOWED_ATTRIBUTES_IMG_STRICT,
 | 
					    "img" => &ALLOWED_ATTRIBUTES_IMG_STRICT,
 | 
				
			||||||
    "ol" => &ALLOWED_ATTRIBUTES_OL_STRICT,
 | 
					    "ol" => &ALLOWED_ATTRIBUTES_OL_STRICT,
 | 
				
			||||||
    "code" => &ALLOWED_ATTRIBUTES_CODE_STRICT,
 | 
					    "code" => &ALLOWED_ATTRIBUTES_CODE_STRICT,
 | 
				
			||||||
 | 
					    "div" => &ALLOWED_ATTRIBUTES_DIV_STRICT,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
static ALLOWED_ATTRIBUTES_SPAN_STRICT: Set<&str> =
 | 
					static ALLOWED_ATTRIBUTES_SPAN_STRICT: Set<&str> =
 | 
				
			||||||
    phf_set! { "data-mx-bg-color", "data-mx-color", "data-mx-spoiler" };
 | 
					    phf_set! { "data-mx-bg-color", "data-mx-color", "data-mx-spoiler", "data-mx-maths" };
 | 
				
			||||||
static ALLOWED_ATTRIBUTES_A_STRICT: Set<&str> = phf_set! { "name", "target", "href" };
 | 
					static ALLOWED_ATTRIBUTES_A_STRICT: Set<&str> = phf_set! { "name", "target", "href" };
 | 
				
			||||||
static ALLOWED_ATTRIBUTES_IMG_STRICT: Set<&str> =
 | 
					static ALLOWED_ATTRIBUTES_IMG_STRICT: Set<&str> =
 | 
				
			||||||
    phf_set! { "width", "height", "alt", "title", "src" };
 | 
					    phf_set! { "width", "height", "alt", "title", "src" };
 | 
				
			||||||
static ALLOWED_ATTRIBUTES_OL_STRICT: Set<&str> = phf_set! { "start" };
 | 
					static ALLOWED_ATTRIBUTES_OL_STRICT: Set<&str> = phf_set! { "start" };
 | 
				
			||||||
static ALLOWED_ATTRIBUTES_CODE_STRICT: Set<&str> = phf_set! { "class" };
 | 
					static ALLOWED_ATTRIBUTES_CODE_STRICT: Set<&str> = phf_set! { "class" };
 | 
				
			||||||
 | 
					static ALLOWED_ATTRIBUTES_DIV_STRICT: Set<&str> = phf_set! { "data-mx-maths" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Attributes that were previously allowed on HTML elements according to the Matrix specification,
 | 
					/// Attributes that were previously allowed on HTML elements according to the Matrix specification,
 | 
				
			||||||
/// with their replacement.
 | 
					/// with their replacement.
 | 
				
			||||||
 | 
				
			|||||||
@ -26,7 +26,8 @@ fn elements() {
 | 
				
			|||||||
    // `<div>` element.
 | 
					    // `<div>` element.
 | 
				
			||||||
    let div_node = html_children.next().unwrap();
 | 
					    let div_node = html_children.next().unwrap();
 | 
				
			||||||
    let div_element = div_node.as_element().unwrap().to_matrix();
 | 
					    let div_element = div_node.as_element().unwrap().to_matrix();
 | 
				
			||||||
    assert_matches!(div_element.element, MatrixElement::Div);
 | 
					    assert_matches!(div_element.element, MatrixElement::Div(div));
 | 
				
			||||||
 | 
					    assert_eq!(div.maths, None);
 | 
				
			||||||
    // The `class` attribute is not supported.
 | 
					    // The `class` attribute is not supported.
 | 
				
			||||||
    assert_eq!(div_element.attrs.len(), 1);
 | 
					    assert_eq!(div_element.attrs.len(), 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user