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 if attr.has_default {
127 Some((name.clone(), attr.default.clone().unwrap()))
128 } else {
129 None
130 }
131 })
132 .collect();
133
134 NodeType {
135 name,
136 spec,
137 desc: "".to_string(),
138 groups: vec![],
139 attrs,
140 default_attrs,
141 content_match: None,
142 mark_set: None,
143 }
144 }
145 pub fn check_content(
154 &self,
155 content: &[Node],
156 schema: &Schema,
157 ) -> bool {
158 if let Some(content_match) = &self.content_match {
159 if let Some(result) = content_match.match_fragment(content, schema)
160 {
161 if !result.valid_end {
162 return false;
163 }
164 }
165 }
166 true
167 }
168 pub fn check_attrs(
178 &self,
179 values: &Attrs,
180 ) {
181 for (key, _value) in values.attrs.iter() {
182 if !self.attrs.contains_key(key) {
183 panic!("节点 {} 属性 {}没有定义", self.name, key);
184 }
185 }
186 for (key, value) in &self.attrs {
187 if value.is_required() && !&values.contains_key(key) {
188 panic!("节点 {} 属性 {} 没有值,这个属性必填", self.name, key);
189 }
190 }
191 }
192
193 pub fn has_required_attrs(&self) -> bool {
195 self.attrs.values().any(|attr: &Attribute| attr.is_required())
196 }
197
198 pub fn create_and_fill(
210 &self,
211 id: Option<String>,
212 attrs: Option<&HashMap<String, Value>>,
213 content: Vec<Node>,
214 marks: Option<Vec<Mark>>,
215 schema: &Schema,
216 ) -> NodeEnum {
217 let id: String = id.unwrap_or_else(IdGenerator::get_id);
218 let attrs = self.compute_attrs(attrs);
219
220 let mut filled_nodes = Vec::new();
222 let mut content_ids = Vec::new();
223
224 if let Some(content_match) = &self.content_match {
225 if let Some(matched) =
226 content_match.match_fragment(&content, schema)
227 {
228 if let Some(needed_type_names) =
229 matched.fill(&content, true, schema)
230 {
231 for type_name in needed_type_names {
233 let complete_node_type =
235 schema.nodes.get(&type_name).expect(&format!(
236 "无法在 schema 中找到节点类型: {}",
237 type_name
238 ));
239
240 let existing_node =
242 content.iter().find(|n| n.r#type == type_name);
243
244 if let Some(node) = existing_node {
245 content_ids.push(node.id.clone());
247 let child_nodes = complete_node_type
251 .create_and_fill(
252 Some(node.id.clone()),
253 Some(
254 &node
255 .attrs
256 .attrs
257 .clone()
258 .into_iter()
259 .map(|(k, v)| {
260 (k.clone(), v.clone())
261 })
262 .collect(),
263 ), vec![], Some(
266 node.marks
267 .clone()
268 .into_iter()
269 .map(|m| m.clone())
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<String>,
318 attrs: Option<&HashMap<String, Value>>,
319 content: Vec<NodeId>,
320 marks: Option<Vec<Mark>>,
321 ) -> Node {
322 let id: String = 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
343 .iter()
344 .find(|m| m.r#type == mark_type.name)
345 .map(|m| m.clone())
346 })
347 .collect(),
348 (None, Some(marks)) => marks,
349 _ => vec![],
350 }
351 }
352
353 fn compute_attrs(
354 &self,
355 attrs: Option<&HashMap<String, Value>>,
356 ) -> Attrs {
357 match attrs {
358 Some(attr) => compute_attrs(&self.attrs, Some(attr)),
359 None => compute_attrs(&self.attrs, Some(&self.default_attrs)),
360 }
361 }
362}
363
364#[derive(Clone, PartialEq, Debug, Eq, Default)]
368pub struct NodeSpec {
369 pub content: Option<String>,
371 pub marks: Option<String>,
373 pub group: Option<String>,
375 pub desc: Option<String>,
377 pub attrs: Option<HashMap<String, AttributeSpec>>,
379}