use super::attrs::Attrs;
use super::mark::Mark;
use super::types::NodeId;
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Node {
#[serde(rename = "i")]
pub id: NodeId,
#[serde(rename = "t")]
pub r#type: String,
#[serde(rename = "a")]
pub attrs: Attrs,
#[serde(rename = "c")]
pub content: imbl::Vector<NodeId>, #[serde(rename = "m")]
pub marks: imbl::Vector<Mark>,
}
impl Node {
pub fn new(
id: &str, r#type: String,
attrs: Attrs,
content: Vec<NodeId>,
marks: Vec<Mark>,
) -> Self {
Node {
id: id.into(), r#type,
attrs,
content: content.into(),
marks: marks.into(),
}
}
pub fn child_count(&self) -> usize {
self.content.len()
}
pub fn update_attr(
&self,
new_values: imbl::HashMap<String, Value>,
) -> Self {
let mut new_node = self.clone();
let new_attrs = self.attrs.update(new_values);
new_node.attrs = new_attrs;
new_node
}
pub fn insert_content_at_index(
&self,
index: usize,
node_id: &str,
) -> Self {
let mut new_node = self.clone();
new_node.content.insert(index, node_id.into());
new_node
}
pub fn insert_contents(
&self,
node_ids: &Vec<NodeId>,
) -> Self {
let mut new_node = self.clone();
for node_id in node_ids {
new_node.content.push_back(node_id.clone());
}
new_node
}
pub fn insert_content(
&self,
node_id: &str,
) -> Self {
let mut new_node = self.clone();
new_node.content.push_back(node_id.into());
new_node
}
pub fn remove_mark_by_name(
&self,
mark_name: &str,
) -> Self {
let mut new_node = self.clone();
new_node.marks = new_node
.marks
.iter()
.filter(|&m| m.r#type != mark_name)
.cloned()
.collect();
new_node
}
pub fn remove_mark(
&self,
mark_types: &[String],
) -> Self {
let mut new_node = self.clone();
new_node.marks = new_node
.marks
.iter()
.filter(|&m| !mark_types.contains(&m.r#type))
.cloned()
.collect();
new_node
}
pub fn add_marks(
&self,
marks: &[Mark],
) -> Self {
let mark_types =
marks.iter().map(|m| m.r#type.clone()).collect::<Vec<String>>();
let mut new_node = self.clone();
new_node.marks = new_node
.marks
.iter()
.filter(|m| !mark_types.contains(&m.r#type))
.cloned()
.collect();
new_node.marks.extend(marks.iter().cloned());
new_node
}
}