use super::graph_node::GraphNode;
use super::Graph;
use super::GraphContext;
use crate::model::node::Node;
use crate::model::node::NodeIter;
use crate::model::node::NodePointer;
use crate::model::node::Reference;
use crate::model::node::ReferenceType;
use crate::model::node::Table;
use crate::model::NodeId;
pub struct GraphNodePointer<'a> {
id: NodeId,
graph: &'a Graph,
}
impl<'a> GraphNodePointer<'a> {
pub fn new(graph: &'a Graph, id: NodeId) -> Self {
GraphNodePointer { id, graph }
}
}
impl<'a> NodePointer<'a> for GraphNodePointer<'a> {
fn id(&self) -> Option<NodeId> {
Some(self.id)
}
fn next_id(&self) -> Option<NodeId> {
self.graph.graph_node(self.id).next_id()
}
fn child_id(&self) -> Option<NodeId> {
self.graph.graph_node(self.id).child_id()
}
fn prev_id(&self) -> Option<NodeId> {
self.graph.graph_node(self.id).prev_id()
}
fn to_node(&self, id: NodeId) -> Self {
GraphNodePointer {
id,
graph: self.graph,
}
}
fn to_key(&self, key: crate::model::Key) -> Option<Self> {
self.graph.get_node_id(&key).map(|id| GraphNodePointer {
id,
graph: self.graph,
})
}
}
impl<'a> NodeIter<'a> for GraphNodePointer<'a> {
fn next(&self) -> Option<Self> {
self.graph
.graph_node(self.id)
.next_id()
.map(|id| GraphNodePointer {
graph: self.graph,
id,
})
}
fn child(&self) -> Option<Self> {
self.graph
.graph_node(self.id)
.child_id()
.map(|id| GraphNodePointer {
graph: self.graph,
id,
})
}
fn node(&self) -> Option<Node> {
match self.graph.graph_node(self.id) {
GraphNode::Empty => None,
GraphNode::Document(document) => Some(Node::Document(
document.key().clone(),
self.graph.frontmatter.get(document.key()).cloned(),
)),
GraphNode::Section(section) => {
let inlines = self.graph.get_line(section.line_id()).normalize(self.graph);
let parent_is_list = self
.to_parent()
.map(|p| p.is_bullet_list() || p.is_ordered_list())
.unwrap_or(false);
if parent_is_list {
let (checked, stripped) =
crate::model::inline::detect_and_strip_checkbox(&inlines);
Some(Node::Item(checked, stripped))
} else {
Some(Node::Section(inlines))
}
}
GraphNode::Quote(_) => Some(Node::Quote()),
GraphNode::BulletList(_) => Some(Node::BulletList()),
GraphNode::OrderedList(_) => Some(Node::OrderedList()),
GraphNode::Leaf(leaf) => Some(Node::Leaf(
self.graph.get_line(leaf.line_id()).normalize(self.graph),
)),
GraphNode::Raw(raw) => Some(Node::Raw(raw.lang(), raw.content().to_string())),
GraphNode::HorizontalRule(_) => Some(Node::HorizontalRule()),
GraphNode::Reference(reference) => {
let text = match reference.reference_type() {
ReferenceType::Regular => self
.graph
.get_ref_text(reference.key())
.unwrap_or(reference.text().to_string()),
ReferenceType::WikiLink => String::default(),
ReferenceType::WikiLinkPiped => reference.text().to_string(),
};
let key = reference.key().clone();
let display_url = match reference.reference_type() {
ReferenceType::WikiLink | ReferenceType::WikiLinkPiped => {
Some(self.graph.wiki_display(&key, reference.url()))
}
ReferenceType::Regular => None,
};
Some(Node::Reference(Reference {
key,
text,
reference_type: reference.reference_type(),
url: reference.url().to_string(),
display_url,
}))
}
GraphNode::Table(table) => Some(Node::Table(Table {
header: table
.header()
.iter()
.map(|id| self.graph.get_line(*id).normalize(self.graph))
.collect(),
rows: table
.rows()
.iter()
.map(|row| {
row.iter()
.map(|id| self.graph.get_line(*id).normalize(self.graph))
.collect()
})
.collect(),
alignment: table.alignment().clone(),
})),
}
}
}