mf_model/
node_definition.rs

1use super::attrs::Attrs;
2use super::content::ContentMatch;
3use super::id_generator::IdGenerator;
4use super::mark::Mark;
5use super::mark_definition::MarkDefinition;
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 NodeTree(pub Node, pub Vec<NodeTree>);
16
17impl NodeTree {
18    pub fn into_parts(self) -> (Node, Vec<NodeTree>) {
19        match self {
20            NodeTree(node, children) => (node, children),
21        }
22    }
23    pub fn from(
24        node: Node,
25        childs: Vec<Node>,
26    ) -> Self {
27        NodeTree(
28            node,
29            childs.into_iter().map(|n| NodeTree(n, vec![])).collect(),
30        )
31    }
32}
33/// 用于描述节点类型的行为规则和属性约束,通过[Schema](super::schema::Schema)进行统一管理
34#[derive(Clone, PartialEq, Eq)]
35pub struct NodeDefinition {
36    /// 节点类型的唯一标识符(例如:"dw", "dxgc")
37    pub name: String,
38    /// 节点类型的详细配置规范
39    pub spec: NodeSpec,
40    /// 节点类型的描述信息
41    pub desc: String,
42    /// 节点所属的逻辑分组
43    pub groups: Vec<String>,
44    /// 节点支持的属性集合(属性名 -> 属性定义)
45    pub attrs: HashMap<String, Attribute>,
46    /// 节点属性的默认值集合
47    pub default_attrs: HashMap<String, Value>,
48    /// 内容匹配规则,定义允许的子节点结构
49    pub content_match: Option<ContentMatch>,
50    /// 允许附加的Mark类型集合
51    pub mark_set: Option<Vec<MarkDefinition>>,
52}
53impl Debug for NodeDefinition {
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 NodeDefinition {
71    /// 将原始节点规范编译为可用的节点类型集合
72    ///
73    /// # 参数
74    /// - `nodes`: 节点名称到[NodeSpec]的映射
75    ///
76    /// # 返回值
77    /// 返回[HashMap]<String, [NodeType]> 类型节点集合
78    pub fn compile(
79        nodes: HashMap<String, NodeSpec>
80    ) -> HashMap<String, NodeDefinition> {
81        let mut result = HashMap::new();
82
83        // First create all node types without content_match
84        for (name, spec) in &nodes {
85            result.insert(
86                name.clone(),
87                NodeDefinition::new(name.clone(), spec.clone()),
88            );
89        }
90
91        // Then set up content_match for each node type
92        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    /// 创建新的节点类型实例
103    ///
104    /// # 参数
105    /// - `name`: 节点类型名称  
106    /// - `spec`: 节点规范定义  
107    ///
108    /// # 注意
109    /// 自动从spec中推导默认属性和内容匹配规则
110    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        NodeDefinition {
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    /// 验证节点内容是否符合类型约束
145    ///
146    /// # 参数
147    /// - `content`: 子节点切片  
148    /// - `schema`: 当前使用的文档模式  
149    ///
150    /// # 返回值
151    /// 返回`true`表示内容合法,`false`表示不合法
152    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    /// 验证节点属性是否符合规范
168    ///
169    /// # 参数
170    /// - `values`: 待验证的属性集合  
171    ///
172    /// # Panics
173    /// 当遇到以下情况会panic:  
174    /// - 包含未定义的属性  
175    /// - 缺少必须的属性
176    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    /// 检查节点是否包含必须的属性
193    pub fn has_required_attrs(&self) -> bool {
194        self.attrs.values().any(|attr: &Attribute| attr.is_required())
195    }
196
197    /// 创建节点并填充内容(保持旧 API 兼容,内部委托给 [`crate::NodeFactory`])。
198    pub fn create_and_fill(
199        &self,
200        id: Option<NodeId>,
201        attrs: Option<&HashMap<String, Value>>,
202        content: Vec<Node>,
203        marks: Option<Vec<Mark>>,
204        schema: &Schema,
205    ) -> NodeTree {
206        schema.factory()
207            .create_tree_with_type(self, id, attrs, content, marks)
208            .expect("NodeFactory::create_tree_with_type should succeed for compiled schema")
209    }
210
211    /// 创建节点(保持旧 API 兼容)。
212    pub fn create(
213        &self,
214        id: Option<NodeId>,
215        attrs: Option<&HashMap<String, Value>>,
216        content: Vec<NodeId>,
217        marks: Option<Vec<Mark>>,
218    ) -> Node {
219        let id: NodeId = id.unwrap_or_else(IdGenerator::get_id);
220
221        Node::new(
222            &id,
223            self.name.clone(),
224            self.compute_attrs(attrs),
225            content,
226            self.compute_marks(marks),
227        )
228    }
229
230    pub(crate) fn compute_marks(
231        &self,
232        marks: Option<Vec<Mark>>,
233    ) -> Vec<Mark> {
234        match (&self.mark_set, marks) {
235            (Some(def), Some(marks)) => def
236                .iter()
237                .filter_map(|mark_type| {
238                    marks.iter().find(|m| m.r#type == mark_type.name).cloned()
239                })
240                .collect(),
241            (None, Some(marks)) => marks,
242            _ => vec![],
243        }
244    }
245
246    pub(crate) fn compute_attrs(
247        &self,
248        attrs: Option<&HashMap<String, Value>>,
249    ) -> Attrs {
250        match attrs {
251            Some(attr) => compute_attrs(&self.attrs, Some(attr)),
252            None => compute_attrs(&self.attrs, Some(&self.default_attrs)),
253        }
254    }
255}
256
257/// 定义节点类型的约束规范
258///
259/// 用于配置节点类型的元数据和行为规则,通过[NodeType::compile]转换为可用类型
260#[derive(Clone, PartialEq, Debug, Eq, Default)]
261pub struct NodeSpec {
262    /// 内容约束表达式(例如:"*")
263    pub content: Option<String>,
264    // 允许附加的Mark类型表达式(例如:"color")
265    pub marks: Option<String>,
266    /// 所属的逻辑分组
267    pub group: Option<String>,
268    /// 类型描述信息
269    pub desc: Option<String>,
270    /// 属性规范定义(属性名 -> 属性规范)
271    pub attrs: Option<HashMap<String, AttributeSpec>>,
272}
273
274
275
276
277