1use super::attrs::Attrs;
2use super::content::ContentMatch;
3use super::id_generator::IdGenerator;
4use super::mark::Mark;
5use super::mark_type::MarkType;
6use super::node::Node;
7use super::schema::{compute_attrs, Attribute, AttributeSpec, Schema};
8use super::types::NodeId;
9use serde::{Deserialize, Serialize};
10use serde_json::Value;
11use std::collections::HashMap;
12use std::fmt::{self, Debug};
13
14#[derive(Clone, Debug, Serialize, Deserialize)]
15pub struct NodeEnum(pub Node, pub Vec<NodeEnum>);
16
17impl NodeEnum {
18 pub fn into_parts(self) -> (Node, Vec<NodeEnum>) {
19 match self {
20 NodeEnum(node, children) => (node, children),
21 }
22 }
23 pub fn from(
24 node: Node,
25 childs: Vec<Node>,
26 ) -> Self {
27 NodeEnum(
28 node,
29 childs.into_iter().map(|n| NodeEnum(n, vec![])).collect(),
30 )
31 }
32}
33#[derive(Clone, PartialEq, Eq)]
35pub struct NodeType {
36 pub name: String,
38 pub spec: NodeSpec,
40 pub desc: String,
42 pub groups: Vec<String>,
44 pub attrs: HashMap<String, Attribute>,
46 pub default_attrs: HashMap<String, Value>,
48 pub content_match: Option<ContentMatch>,
50 pub mark_set: Option<Vec<MarkType>>,
52}
53impl Debug for NodeType {
54 fn fmt(
55 &self,
56 f: &mut fmt::Formatter<'_>,
57 ) -> fmt::Result {
58 f.debug_struct("NodeType")
59 .field("name", &self.name)
60 .field("spec", &self.spec)
61 .field("desc", &self.desc)
62 .field("groups", &self.groups)
63 .field("attrs", &self.attrs)
64 .field("default_attrs", &self.default_attrs)
65 .field("mark_set", &self.mark_set)
66 .finish()
67 }
68}
69
70impl NodeType {
71 pub fn compile(
79 nodes: HashMap<String, NodeSpec>
80 ) -> HashMap<String, NodeType> {
81 let mut result = HashMap::new();
82
83 for (name, spec) in &nodes {
85 result.insert(
86 name.clone(),
87 NodeType::new(name.clone(), spec.clone()),
88 );
89 }
90
91 let result_clone = result.clone();
93 for (_, node_type) in result.iter_mut() {
94 if let Some(content) = &node_type.spec.content {
95 node_type.content_match =
96 Some(ContentMatch::parse(content.clone(), &result_clone));
97 }
98 }
99
100 result
101 }
102 pub fn new(
111 name: String,
112 spec: NodeSpec,
113 ) -> Self {
114 let attrs = spec.attrs.as_ref().map_or_else(HashMap::new, |attrs| {
115 attrs
116 .iter()
117 .map(|(name, spec)| {
118 (name.clone(), Attribute::new(spec.clone()))
119 })
120 .collect()
121 });
122
123 let default_attrs = attrs
124 .iter()
125 .filter_map(|(name, attr)| {
126 match (&attr.has_default, &attr.default) {
127 (true, Some(v)) => Some((name.clone(), v.clone())),
128 _ => None,
129 }
130 })
131 .collect();
132
133 NodeType {
134 name,
135 spec,
136 desc: "".to_string(),
137 groups: vec![],
138 attrs,
139 default_attrs,
140 content_match: None,
141 mark_set: None,
142 }
143 }
144 pub fn check_content(
153 &self,
154 content: &[Node],
155 schema: &Schema,
156 ) -> bool {
157 if let Some(content_match) = &self.content_match {
158 if let Some(result) = content_match.match_fragment(content, schema)
159 {
160 if !result.valid_end {
161 return false;
162 }
163 }
164 }
165 true
166 }
167 pub fn check_attrs(
177 &self,
178 values: &Attrs,
179 ) {
180 for (key, _value) in values.attrs.iter() {
181 if !self.attrs.contains_key(key) {
182 panic!("节点 {} 属性 {}没有定义", self.name, key);
183 }
184 }
185 for (key, value) in &self.attrs {
186 if value.is_required() && !&values.contains_key(key) {
187 panic!("节点 {} 属性 {} 没有值,这个属性必填", self.name, key);
188 }
189 }
190 }
191
192 pub fn has_required_attrs(&self) -> bool {
194 self.attrs.values().any(|attr: &Attribute| attr.is_required())
195 }
196
197 pub fn create_and_fill(
209 &self,
210 id: Option<NodeId>,
211 attrs: Option<&HashMap<String, Value>>,
212 content: Vec<Node>,
213 marks: Option<Vec<Mark>>,
214 schema: &Schema,
215 ) -> NodeEnum {
216 let id: NodeId = id.unwrap_or_else(IdGenerator::get_id);
217 let attrs = self.compute_attrs(attrs);
218
219 let mut filled_nodes = Vec::new();
221 let mut content_ids = Vec::new();
222
223 if let Some(content_match) = &self.content_match {
224 if let Some(matched) =
225 content_match.match_fragment(&content, schema)
226 {
227 if let Some(needed_type_names) =
228 matched.fill(&content, true, schema)
229 {
230 for type_name in needed_type_names {
232 let complete_node_type =
234 match schema.nodes.get(&type_name) {
235 Some(nt) => nt,
236 None => panic!(
237 "无法在 schema 中找到节点类型: {type_name}"
238 ),
239 };
240
241 let existing_node =
243 content.iter().find(|n| n.r#type == type_name);
244
245 if let Some(node) = existing_node {
246 content_ids.push(node.id.clone());
248 let child_nodes = complete_node_type
252 .create_and_fill(
253 Some(node.id.clone()),
254 Some(
255 &node
256 .attrs
257 .attrs
258 .clone()
259 .into_iter()
260 .map(|(k, v)| {
261 (k.clone(), v.clone())
262 })
263 .collect(),
264 ), vec![], Some(
267 node.marks
268 .clone()
269 .into_iter()
270 .collect(),
271 ),
272 schema,
273 );
274 filled_nodes.push(child_nodes);
275 } else {
276 let new_id = IdGenerator::get_id();
278 content_ids.push(new_id.clone());
279 let child_nodes = complete_node_type
280 .create_and_fill(
281 Some(new_id),
282 None,
283 vec![], None,
285 schema,
286 );
287 filled_nodes.push(child_nodes);
288 }
289 }
290 }
291 }
292 }
293
294 let mut final_content_ids = Vec::new();
297 for filled_node in &filled_nodes {
298 let (child_node, _) = filled_node.clone().into_parts();
299 final_content_ids.push(child_node.id);
300 }
301
302 NodeEnum(
303 Node::new(
304 &id,
305 self.name.clone(),
306 attrs,
307 final_content_ids,
308 self.compute_marks(marks),
309 ),
310 filled_nodes,
311 )
312 }
313
314 pub fn create(
316 &self,
317 id: Option<NodeId>,
318 attrs: Option<&HashMap<String, Value>>,
319 content: Vec<NodeId>,
320 marks: Option<Vec<Mark>>,
321 ) -> Node {
322 let id: NodeId = id.unwrap_or_else(IdGenerator::get_id);
324
325 Node::new(
326 &id,
327 self.name.clone(),
328 self.compute_attrs(attrs),
329 content,
330 self.compute_marks(marks),
331 )
332 }
333
334 fn compute_marks(
335 &self,
336 marks: Option<Vec<Mark>>,
337 ) -> Vec<Mark> {
338 match (&self.mark_set, marks) {
339 (Some(def), Some(marks)) => def
340 .iter()
341 .filter_map(|mark_type| {
342 marks.iter().find(|m| m.r#type == mark_type.name).cloned()
343 })
344 .collect(),
345 (None, Some(marks)) => marks,
346 _ => vec![],
347 }
348 }
349
350 fn compute_attrs(
351 &self,
352 attrs: Option<&HashMap<String, Value>>,
353 ) -> Attrs {
354 match attrs {
355 Some(attr) => compute_attrs(&self.attrs, Some(attr)),
356 None => compute_attrs(&self.attrs, Some(&self.default_attrs)),
357 }
358 }
359}
360
361#[derive(Clone, PartialEq, Debug, Eq, Default)]
365pub struct NodeSpec {
366 pub content: Option<String>,
368 pub marks: Option<String>,
370 pub group: Option<String>,
372 pub desc: Option<String>,
374 pub attrs: Option<HashMap<String, AttributeSpec>>,
376}