attributes.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. #![allow(non_snake_case)]
  2. use crate::{
  3. block_attribute,
  4. core::{Attributes, OperationTransformable, RichTextOperation},
  5. errors::OTError,
  6. ignore_attribute,
  7. inline_attribute,
  8. list_attribute,
  9. };
  10. use lazy_static::lazy_static;
  11. use std::{
  12. collections::{HashMap, HashSet},
  13. fmt,
  14. fmt::Formatter,
  15. iter::FromIterator,
  16. };
  17. use strum_macros::Display;
  18. #[derive(Debug, Clone, Eq, PartialEq)]
  19. pub struct RichTextAttributes {
  20. pub(crate) inner: HashMap<RichTextAttributeKey, RichTextAttributeValue>,
  21. }
  22. impl std::default::Default for RichTextAttributes {
  23. fn default() -> Self {
  24. Self {
  25. inner: HashMap::with_capacity(0),
  26. }
  27. }
  28. }
  29. impl fmt::Display for RichTextAttributes {
  30. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_fmt(format_args!("{:?}", self.inner)) }
  31. }
  32. pub fn plain_attributes() -> RichTextAttributes { RichTextAttributes::default() }
  33. impl RichTextAttributes {
  34. pub fn new() -> Self { RichTextAttributes { inner: HashMap::new() } }
  35. pub fn is_empty(&self) -> bool { self.inner.is_empty() }
  36. pub fn add(&mut self, attribute: RichTextAttribute) {
  37. let RichTextAttribute { key, value, scope: _ } = attribute;
  38. self.inner.insert(key, value);
  39. }
  40. pub fn add_kv(&mut self, key: RichTextAttributeKey, value: RichTextAttributeValue) {
  41. self.inner.insert(key, value);
  42. }
  43. pub fn delete(&mut self, key: &RichTextAttributeKey) {
  44. self.inner.insert(key.clone(), RichTextAttributeValue(None));
  45. }
  46. pub fn mark_all_as_removed_except(&mut self, attribute: Option<RichTextAttributeKey>) {
  47. match attribute {
  48. None => {
  49. self.inner.iter_mut().for_each(|(_k, v)| v.0 = None);
  50. },
  51. Some(attribute) => {
  52. self.inner.iter_mut().for_each(|(k, v)| {
  53. if k != &attribute {
  54. v.0 = None;
  55. }
  56. });
  57. },
  58. }
  59. }
  60. pub fn remove(&mut self, key: RichTextAttributeKey) { self.inner.retain(|k, _| k != &key); }
  61. // pub fn block_attributes_except_header(attributes: &Attributes) -> Attributes
  62. // { let mut new_attributes = Attributes::new();
  63. // attributes.iter().for_each(|(k, v)| {
  64. // if k != &AttributeKey::Header {
  65. // new_attributes.insert(k.clone(), v.clone());
  66. // }
  67. // });
  68. //
  69. // new_attributes
  70. // }
  71. // Update inner by constructing new attributes from the other if it's
  72. // not None and replace the key/value with self key/value.
  73. pub fn merge(&mut self, other: Option<RichTextAttributes>) {
  74. if other.is_none() {
  75. return;
  76. }
  77. let mut new_attributes = other.unwrap().inner;
  78. self.inner.iter().for_each(|(k, v)| {
  79. new_attributes.insert(k.clone(), v.clone());
  80. });
  81. self.inner = new_attributes;
  82. }
  83. }
  84. impl Attributes for RichTextAttributes {
  85. fn is_empty(&self) -> bool { self.inner.is_empty() }
  86. fn remove_empty(&mut self) { self.inner.retain(|_, v| v.0.is_some()); }
  87. fn extend_other(&mut self, other: Self) { self.inner.extend(other.inner); }
  88. }
  89. impl OperationTransformable for RichTextAttributes {
  90. fn compose(&self, other: &Self) -> Result<Self, OTError>
  91. where
  92. Self: Sized,
  93. {
  94. let mut attributes = self.clone();
  95. attributes.extend_other(other.clone());
  96. Ok(attributes)
  97. }
  98. fn transform(&self, other: &Self) -> Result<(Self, Self), OTError>
  99. where
  100. Self: Sized,
  101. {
  102. let a = self
  103. .iter()
  104. .fold(RichTextAttributes::new(), |mut new_attributes, (k, v)| {
  105. if !other.contains_key(k) {
  106. new_attributes.insert(k.clone(), v.clone());
  107. }
  108. new_attributes
  109. });
  110. let b = other
  111. .iter()
  112. .fold(RichTextAttributes::new(), |mut new_attributes, (k, v)| {
  113. if !self.contains_key(k) {
  114. new_attributes.insert(k.clone(), v.clone());
  115. }
  116. new_attributes
  117. });
  118. Ok((a, b))
  119. }
  120. fn invert(&self, other: &Self) -> Self {
  121. let base_inverted = other.iter().fold(RichTextAttributes::new(), |mut attributes, (k, v)| {
  122. if other.get(k) != self.get(k) && self.contains_key(k) {
  123. attributes.insert(k.clone(), v.clone());
  124. }
  125. attributes
  126. });
  127. let inverted = self.iter().fold(base_inverted, |mut attributes, (k, _)| {
  128. if other.get(k) != self.get(k) && !other.contains_key(k) {
  129. attributes.delete(k);
  130. }
  131. attributes
  132. });
  133. inverted
  134. }
  135. }
  136. impl std::ops::Deref for RichTextAttributes {
  137. type Target = HashMap<RichTextAttributeKey, RichTextAttributeValue>;
  138. fn deref(&self) -> &Self::Target { &self.inner }
  139. }
  140. impl std::ops::DerefMut for RichTextAttributes {
  141. fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner }
  142. }
  143. pub fn attributes_except_header(op: &RichTextOperation) -> RichTextAttributes {
  144. let mut attributes = op.get_attributes();
  145. attributes.remove(RichTextAttributeKey::Header);
  146. attributes
  147. }
  148. #[derive(Debug, Clone)]
  149. pub struct RichTextAttribute {
  150. pub key: RichTextAttributeKey,
  151. pub value: RichTextAttributeValue,
  152. pub scope: AttributeScope,
  153. }
  154. impl RichTextAttribute {
  155. // inline
  156. inline_attribute!(Bold, bool);
  157. inline_attribute!(Italic, bool);
  158. inline_attribute!(Underline, bool);
  159. inline_attribute!(StrikeThrough, bool);
  160. inline_attribute!(Link, &str);
  161. inline_attribute!(Color, String);
  162. inline_attribute!(Font, usize);
  163. inline_attribute!(Size, usize);
  164. inline_attribute!(Background, String);
  165. inline_attribute!(InlineCode, bool);
  166. // block
  167. block_attribute!(Header, usize);
  168. block_attribute!(Indent, usize);
  169. block_attribute!(Align, String);
  170. block_attribute!(List, &str);
  171. block_attribute!(CodeBlock, bool);
  172. block_attribute!(BlockQuote, bool);
  173. // ignore
  174. ignore_attribute!(Width, usize);
  175. ignore_attribute!(Height, usize);
  176. // List extension
  177. list_attribute!(Bullet, "bullet");
  178. list_attribute!(Ordered, "ordered");
  179. list_attribute!(Checked, "checked");
  180. list_attribute!(UnChecked, "unchecked");
  181. pub fn to_json(&self) -> String {
  182. match serde_json::to_string(self) {
  183. Ok(json) => json,
  184. Err(e) => {
  185. log::error!("Attribute serialize to str failed: {}", e);
  186. "".to_owned()
  187. },
  188. }
  189. }
  190. }
  191. impl fmt::Display for RichTextAttribute {
  192. fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
  193. let s = format!("{:?}:{:?} {:?}", self.key, self.value.0, self.scope);
  194. f.write_str(&s)
  195. }
  196. }
  197. impl std::convert::From<RichTextAttribute> for RichTextAttributes {
  198. fn from(attr: RichTextAttribute) -> Self {
  199. let mut attributes = RichTextAttributes::new();
  200. attributes.add(attr);
  201. attributes
  202. }
  203. }
  204. #[derive(Clone, Debug, Display, Hash, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
  205. // serde.rs/variant-attrs.html
  206. // #[serde(rename_all = "snake_case")]
  207. pub enum RichTextAttributeKey {
  208. #[serde(rename = "bold")]
  209. Bold,
  210. #[serde(rename = "italic")]
  211. Italic,
  212. #[serde(rename = "underline")]
  213. Underline,
  214. #[serde(rename = "strike")]
  215. StrikeThrough,
  216. #[serde(rename = "font")]
  217. Font,
  218. #[serde(rename = "size")]
  219. Size,
  220. #[serde(rename = "link")]
  221. Link,
  222. #[serde(rename = "color")]
  223. Color,
  224. #[serde(rename = "background")]
  225. Background,
  226. #[serde(rename = "indent")]
  227. Indent,
  228. #[serde(rename = "align")]
  229. Align,
  230. #[serde(rename = "code_block")]
  231. CodeBlock,
  232. #[serde(rename = "code")]
  233. InlineCode,
  234. #[serde(rename = "list")]
  235. List,
  236. #[serde(rename = "blockquote")]
  237. BlockQuote,
  238. #[serde(rename = "width")]
  239. Width,
  240. #[serde(rename = "height")]
  241. Height,
  242. #[serde(rename = "header")]
  243. Header,
  244. }
  245. // pub trait AttributeValueData<'a>: Serialize + Deserialize<'a> {}
  246. #[derive(Debug, Clone, PartialEq, Eq, Hash)]
  247. pub struct RichTextAttributeValue(pub Option<String>);
  248. impl std::convert::From<&usize> for RichTextAttributeValue {
  249. fn from(val: &usize) -> Self { RichTextAttributeValue::from(*val) }
  250. }
  251. impl std::convert::From<usize> for RichTextAttributeValue {
  252. fn from(val: usize) -> Self {
  253. if val > 0_usize {
  254. RichTextAttributeValue(Some(format!("{}", val)))
  255. } else {
  256. RichTextAttributeValue(None)
  257. }
  258. }
  259. }
  260. impl std::convert::From<&str> for RichTextAttributeValue {
  261. fn from(val: &str) -> Self { val.to_owned().into() }
  262. }
  263. impl std::convert::From<String> for RichTextAttributeValue {
  264. fn from(val: String) -> Self {
  265. if val.is_empty() {
  266. RichTextAttributeValue(None)
  267. } else {
  268. RichTextAttributeValue(Some(val))
  269. }
  270. }
  271. }
  272. impl std::convert::From<&bool> for RichTextAttributeValue {
  273. fn from(val: &bool) -> Self { RichTextAttributeValue::from(*val) }
  274. }
  275. impl std::convert::From<bool> for RichTextAttributeValue {
  276. fn from(val: bool) -> Self {
  277. let val = match val {
  278. true => Some("true".to_owned()),
  279. false => None,
  280. };
  281. RichTextAttributeValue(val)
  282. }
  283. }
  284. pub fn is_block_except_header(k: &RichTextAttributeKey) -> bool {
  285. if k == &RichTextAttributeKey::Header {
  286. return false;
  287. }
  288. BLOCK_KEYS.contains(k)
  289. }
  290. lazy_static! {
  291. static ref BLOCK_KEYS: HashSet<RichTextAttributeKey> = HashSet::from_iter(vec![
  292. RichTextAttributeKey::Header,
  293. RichTextAttributeKey::Indent,
  294. RichTextAttributeKey::Align,
  295. RichTextAttributeKey::CodeBlock,
  296. RichTextAttributeKey::List,
  297. RichTextAttributeKey::BlockQuote,
  298. ]);
  299. static ref INLINE_KEYS: HashSet<RichTextAttributeKey> = HashSet::from_iter(vec![
  300. RichTextAttributeKey::Bold,
  301. RichTextAttributeKey::Italic,
  302. RichTextAttributeKey::Underline,
  303. RichTextAttributeKey::StrikeThrough,
  304. RichTextAttributeKey::Link,
  305. RichTextAttributeKey::Color,
  306. RichTextAttributeKey::Font,
  307. RichTextAttributeKey::Size,
  308. RichTextAttributeKey::Background,
  309. RichTextAttributeKey::InlineCode,
  310. ]);
  311. static ref INGORE_KEYS: HashSet<RichTextAttributeKey> =
  312. HashSet::from_iter(vec![RichTextAttributeKey::Width, RichTextAttributeKey::Height,]);
  313. }
  314. #[derive(Debug, PartialEq, Eq, Clone)]
  315. pub enum AttributeScope {
  316. Inline,
  317. Block,
  318. Embeds,
  319. Ignore,
  320. }