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]
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- `MatrixElement::Div` is now a newtype variant.
|
||||
|
||||
Improvements:
|
||||
|
||||
- Add support for mathematical messages, according to MSC2191 / Matrix 1.11
|
||||
|
||||
# 0.2.0
|
||||
|
||||
Breaking Changes:
|
||||
|
@ -152,7 +152,7 @@ pub enum MatrixElement {
|
||||
/// [`<div>`], a content division element.
|
||||
///
|
||||
/// [`<div>`]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div
|
||||
Div,
|
||||
Div(DivData),
|
||||
|
||||
/// [`<table>`], a table element.
|
||||
///
|
||||
@ -268,7 +268,10 @@ impl MatrixElement {
|
||||
}
|
||||
b"hr" => (Self::Hr, 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"thead" => (Self::Thead, 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
|
||||
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 {
|
||||
/// Construct an empty `SpanData`.
|
||||
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`.
|
||||
@ -629,6 +643,9 @@ impl SpanData {
|
||||
b"data-mx-spoiler" => {
|
||||
data.spoiler = Some(attr.value.clone());
|
||||
}
|
||||
b"data-mx-maths" => {
|
||||
data.maths = Some(attr.value.clone());
|
||||
}
|
||||
_ => {
|
||||
remaining_attrs.insert(attr.clone());
|
||||
}
|
||||
@ -722,3 +739,53 @@ impl ImageData {
|
||||
(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,
|
||||
"ol" => &ALLOWED_ATTRIBUTES_OL_STRICT,
|
||||
"code" => &ALLOWED_ATTRIBUTES_CODE_STRICT,
|
||||
"div" => &ALLOWED_ATTRIBUTES_DIV_STRICT,
|
||||
};
|
||||
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_IMG_STRICT: Set<&str> =
|
||||
phf_set! { "width", "height", "alt", "title", "src" };
|
||||
static ALLOWED_ATTRIBUTES_OL_STRICT: Set<&str> = phf_set! { "start" };
|
||||
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,
|
||||
/// with their replacement.
|
||||
|
@ -26,7 +26,8 @@ fn elements() {
|
||||
// `<div>` element.
|
||||
let div_node = html_children.next().unwrap();
|
||||
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.
|
||||
assert_eq!(div_element.attrs.len(), 1);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user