use crate::fragment::Fragment;
use crate::map::Mapping;
use crate::mark::Mark;
use crate::node::Node;
use crate::pos::ResolvedPos;
use crate::schema::Schema;
use crate::slice::Slice;
use crate::step::{AddMarkStep, AttrStep, RemoveMarkStep, ReplaceStep, Step, StepError};
#[derive(Debug, Clone)]
pub struct Transform {
doc: Node,
steps: Vec<Box<dyn Step>>,
docs: Vec<Node>,
mapping: Mapping,
}
impl Transform {
pub fn new(doc: Node) -> Self {
Transform {
doc,
steps: Vec::new(),
docs: Vec::new(),
mapping: Mapping::new(),
}
}
pub fn doc(&self) -> &Node {
&self.doc
}
pub fn steps(&self) -> &[Box<dyn Step>] {
&self.steps
}
pub fn doc_before(&self, i: usize) -> &Node {
&self.docs[i]
}
pub fn mapping(&self) -> &Mapping {
&self.mapping
}
pub fn doc_changed(&self) -> bool {
!self.steps.is_empty()
}
pub fn step(&mut self, step: Box<dyn Step>, schema: &Schema) -> Result<&mut Self, StepError> {
let next = step.apply(&self.doc, schema)?;
self.mapping.append_map(step.get_map());
self.docs.push(std::mem::replace(&mut self.doc, next));
self.steps.push(step);
Ok(self)
}
pub fn replace(
&mut self,
from: usize,
to: usize,
slice: Slice,
schema: &Schema,
) -> Result<&mut Self, StepError> {
self.step(Box::new(ReplaceStep::new(from, to, slice)), schema)
}
pub fn delete(
&mut self,
from: usize,
to: usize,
schema: &Schema,
) -> Result<&mut Self, StepError> {
self.replace(from, to, Slice::empty(), schema)
}
pub fn insert(
&mut self,
pos: usize,
slice: Slice,
schema: &Schema,
) -> Result<&mut Self, StepError> {
self.replace(pos, pos, slice, schema)
}
pub fn add_mark(
&mut self,
from: usize,
to: usize,
mark: Mark,
schema: &Schema,
) -> Result<&mut Self, StepError> {
self.step(Box::new(AddMarkStep::new(from, to, mark)), schema)
}
pub fn remove_mark(
&mut self,
from: usize,
to: usize,
mark: Mark,
schema: &Schema,
) -> Result<&mut Self, StepError> {
self.step(Box::new(RemoveMarkStep::new(from, to, mark)), schema)
}
pub fn split(&mut self, pos: usize, schema: &Schema) -> Result<&mut Self, StepError> {
self.split_at_depth(pos, 1, schema)
}
pub fn split_at_depth(
&mut self,
pos: usize,
levels: usize,
schema: &Schema,
) -> Result<&mut Self, StepError> {
if levels == 0 {
return Err(StepError("split_at_depth requires levels >= 1".into()));
}
let rp = ResolvedPos::resolve(self.doc(), pos).map_err(|e| StepError(e.to_string()))?;
if rp.depth() < levels {
return Err(StepError(format!(
"split_at_depth({levels}) needs at least {levels} ancestors at pos {pos}, found {}",
rp.depth()
)));
}
let deepest = rp.parent().clone();
let mut inner = deepest.copy_content(Fragment::empty());
for d in (rp.depth() - levels + 1..rp.depth()).rev() {
let outer = rp.node(d).clone();
inner = outer.copy_content(Fragment::from_node(inner));
}
let content = Fragment::from_node(inner.clone()).append(&Fragment::from_node(inner));
self.replace(pos, pos, Slice::new(content, levels, levels), schema)
}
pub fn set_node_attr(
&mut self,
pos: usize,
attr: &str,
value: serde_json::Value,
schema: &Schema,
) -> Result<&mut Self, StepError> {
self.step(Box::new(AttrStep::new(pos, attr, value)), schema)
}
pub fn invert_steps(&self) -> Result<Vec<Box<dyn Step>>, StepError> {
let mut inverted = Vec::with_capacity(self.steps.len());
for i in (0..self.steps.len()).rev() {
inverted.push(self.steps[i].invert(&self.docs[i])?);
}
Ok(inverted)
}
}