|
@@ -1,5 +1,22 @@
|
|
-use crate::core::{Attribute, AttributesData, AttributesRule, Operation};
|
|
|
|
-use std::{collections::HashMap, fmt, fmt::Formatter};
|
|
|
|
|
|
+use crate::core::{AttributesData, Operation};
|
|
|
|
+use std::{fmt, fmt::Formatter};
|
|
|
|
+
|
|
|
|
+pub trait AttributesRule {
|
|
|
|
+ // Remove the empty attribute that its value is empty. e.g. {bold: ""}.
|
|
|
|
+ fn remove_empty(self) -> Attributes;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl AttributesRule for Attributes {
|
|
|
|
+ fn remove_empty(self) -> Attributes {
|
|
|
|
+ match self {
|
|
|
|
+ Attributes::Follow => self,
|
|
|
|
+ Attributes::Custom(mut data) => {
|
|
|
|
+ data.remove_empty_value();
|
|
|
|
+ data.into()
|
|
|
|
+ },
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
|
|
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
|
|
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
|
|
#[serde(untagged)]
|
|
#[serde(untagged)]
|
|
@@ -49,18 +66,27 @@ pub fn compose_operation(left: &Option<Operation>, right: &Option<Operation>) ->
|
|
if left.is_none() && right.is_none() {
|
|
if left.is_none() && right.is_none() {
|
|
return Attributes::default();
|
|
return Attributes::default();
|
|
}
|
|
}
|
|
- let attr_l = attributes_from(left);
|
|
|
|
- let attr_r = attributes_from(right);
|
|
|
|
|
|
+ let attr_left = attributes_from(left);
|
|
|
|
+ let attr_right = attributes_from(right);
|
|
|
|
|
|
- if attr_l.is_none() {
|
|
|
|
- return attr_r.unwrap();
|
|
|
|
|
|
+ if attr_left.is_none() {
|
|
|
|
+ return attr_right.unwrap();
|
|
}
|
|
}
|
|
|
|
|
|
- if attr_r.is_none() {
|
|
|
|
- return attr_l.unwrap();
|
|
|
|
|
|
+ if attr_right.is_none() {
|
|
|
|
+ return attr_left.unwrap();
|
|
}
|
|
}
|
|
|
|
|
|
- compose_attributes(attr_l.unwrap(), attr_r.unwrap())
|
|
|
|
|
|
+ let left = attr_left.unwrap();
|
|
|
|
+ let right = attr_right.unwrap();
|
|
|
|
+ log::trace!("compose attributes: a: {:?}, b: {:?}", left, right);
|
|
|
|
+ let attr = match (&left, &right) {
|
|
|
|
+ (_, Attributes::Custom(_)) => merge_attributes(left, right),
|
|
|
|
+ (Attributes::Custom(_), _) => merge_attributes(left, right),
|
|
|
|
+ _ => Attributes::Follow,
|
|
|
|
+ };
|
|
|
|
+ log::trace!("compose attributes result: {:?}", attr);
|
|
|
|
+ attr
|
|
}
|
|
}
|
|
|
|
|
|
pub fn transform_operation(left: &Option<Operation>, right: &Option<Operation>) -> Attributes {
|
|
pub fn transform_operation(left: &Option<Operation>, right: &Option<Operation>) -> Attributes {
|
|
@@ -78,7 +104,23 @@ pub fn transform_operation(left: &Option<Operation>, right: &Option<Operation>)
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
- transform_attributes(attr_l.unwrap(), attr_r.unwrap())
|
|
|
|
|
|
+ let left = attr_l.unwrap();
|
|
|
|
+ let right = attr_r.unwrap();
|
|
|
|
+ match (left, right) {
|
|
|
|
+ (Attributes::Custom(data_l), Attributes::Custom(data_r)) => {
|
|
|
|
+ let result = data_r
|
|
|
|
+ .iter()
|
|
|
|
+ .fold(AttributesData::new(), |mut new_attr_data, (k, v)| {
|
|
|
|
+ if !data_l.contains_key(k) {
|
|
|
|
+ new_attr_data.insert(k.clone(), v.clone());
|
|
|
|
+ }
|
|
|
|
+ new_attr_data
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ Attributes::Custom(result)
|
|
|
|
+ },
|
|
|
|
+ _ => Attributes::default(),
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
pub fn invert_attributes(attr: Attributes, base: Attributes) -> Attributes {
|
|
pub fn invert_attributes(attr: Attributes, base: Attributes) -> Attributes {
|
|
@@ -115,41 +157,10 @@ pub fn merge_attributes(attributes: Attributes, other: Attributes) -> Attributes
|
|
match (&attributes, &other) {
|
|
match (&attributes, &other) {
|
|
(Attributes::Custom(data), Attributes::Custom(o_data)) => {
|
|
(Attributes::Custom(data), Attributes::Custom(o_data)) => {
|
|
let mut data = data.clone();
|
|
let mut data = data.clone();
|
|
- data.extend(Some(o_data.clone()), false);
|
|
|
|
|
|
+ data.extend(Some(o_data.clone()));
|
|
Attributes::Custom(data)
|
|
Attributes::Custom(data)
|
|
},
|
|
},
|
|
(Attributes::Custom(data), _) => Attributes::Custom(data.clone()),
|
|
(Attributes::Custom(data), _) => Attributes::Custom(data.clone()),
|
|
_ => other,
|
|
_ => other,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
-fn compose_attributes(left: Attributes, right: Attributes) -> Attributes {
|
|
|
|
- log::trace!("compose_attributes: a: {:?}, b: {:?}", left, right);
|
|
|
|
-
|
|
|
|
- let attr = match (&left, &right) {
|
|
|
|
- (_, Attributes::Custom(_)) => merge_attributes(left, right),
|
|
|
|
- (Attributes::Custom(_), _) => merge_attributes(left, right),
|
|
|
|
- _ => Attributes::Follow,
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- log::trace!("composed_attributes: a: {:?}", attr);
|
|
|
|
- attr
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-fn transform_attributes(left: Attributes, right: Attributes) -> Attributes {
|
|
|
|
- match (left, right) {
|
|
|
|
- (Attributes::Custom(data_l), Attributes::Custom(data_r)) => {
|
|
|
|
- let result = data_r
|
|
|
|
- .iter()
|
|
|
|
- .fold(AttributesData::new(), |mut new_attr_data, (k, v)| {
|
|
|
|
- if !data_l.contains_key(k) {
|
|
|
|
- new_attr_data.insert(k.clone(), v.clone());
|
|
|
|
- }
|
|
|
|
- new_attr_data
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- Attributes::Custom(result)
|
|
|
|
- },
|
|
|
|
- _ => Attributes::default(),
|
|
|
|
- }
|
|
|
|
-}
|
|
|