Skip to main content

htmltoadf/
adf_structure.rs

1use serde_json::Value;
2use std::collections::HashMap;
3
4use crate::types::{
5    adf_content_type::{AdfContentType, AdfMark, AdfMarkAttributes},
6    adf_permitted_children::AdfPermittedChildren,
7};
8
9lazy_static! {
10  /**
11   * Placeholder empty child type. Does not permit any child types.
12   */
13  pub static ref EMPTY_CHILD_TYPE: AdfPermittedChildren = AdfPermittedChildren::any(&[]);
14
15  /**
16   * 1. LEGAL_CHILD_TYPES: The allowed nesting of ADF Types that we permit in our output doc.
17   */
18  pub static ref LEGAL_CHILD_TYPES: HashMap<String, AdfPermittedChildren> = HashMap::from([
19    (
20      String::from("paragraph"),
21      AdfPermittedChildren::any(&["text", "emoji", "hardBreak"])
22    ),
23    (
24      String::from("heading"),
25      AdfPermittedChildren::any(&["text", "emoji", "hardBreak"])
26    ),
27    (
28      String::from("bulletList"),
29      AdfPermittedChildren::any(&["listItem"])
30    ),
31    (
32      String::from("orderedList"),
33      AdfPermittedChildren::any(&["listItem"])
34    ),
35    (
36      String::from("blockquote"),
37      AdfPermittedChildren::any(&["paragraph"])
38    ),
39    (
40      String::from("codeBlock"),
41      AdfPermittedChildren::any(&["text"])
42    ),
43    (
44      String::from("listItem"),
45      AdfPermittedChildren::any_starts_with(&["paragraph", "mediaSingle", "codeBlock"], &["paragraph", "mediaAdfPermittedChildren", "codeBlock", "orderedList", "bulletList"])
46    ),
47    (
48      String::from("table"),
49      AdfPermittedChildren::any(&["tableRow"])
50    ),
51    (
52      String::from("tableRow"),
53      AdfPermittedChildren::any(&["tableHeader","tableCell"])
54    ),
55    (
56      String::from("tableHeader"),
57      AdfPermittedChildren::any(&["codeBlock", "blockCard", "paragraph", "bulletList", "mediaSingle", "orderedList", "heading", "panel", "blockquote", "rule", "mediaGroup", "decisionList", "taskList", "extension", "embedCard", "nestedExpand"])
58    ),
59    (
60      String::from("tableCell"),
61      AdfPermittedChildren::any(&["codeBlock", "blockCard", "paragraph", "bulletList", "mediaSingle", "orderedList", "heading", "panel", "blockquote", "rule", "mediaGroup", "decisionList", "taskList", "extension", "embedCard", "nestedExpand", "hardBreak"])
62    ),
63    (
64      String::from("doc"),
65      AdfPermittedChildren::any(&["blockCard", "blockquote", "bodiedExtension", "bulletList", "codeBlock", "decisionList", "embedCard", "expand", "extension", "heading", "layoutSection", "mediaGroup", "mediaSingle", "orderedList", "panel", "paragraph", "rule", "table", "taskList"])
66    )
67  ]);
68
69  #[derive(Debug, Clone)]
70  /**
71   * NODE_MAP: The legal mappings from HTML element types to ADF types that we permit.
72   */
73  pub static ref NODE_MAP: HashMap<&'static str, AdfContentType> = HashMap::from([
74    (
75      "p",
76      AdfContentType::from_name("paragraph")
77    ),
78    (
79      "blockquote",
80      AdfContentType::from_name("blockquote")
81    ),
82    (
83      "span",
84      AdfContentType::from_name("text")
85    ),
86    (
87      "text",
88      AdfContentType::from_name("text")
89    ),
90    (
91      "ul",
92      AdfContentType::from_name("bulletList")
93    ),
94    (
95      "ol",
96      AdfContentType::from_name("orderedList")
97    ),
98    (
99      "li",
100      AdfContentType::from_name("listItem")
101    ),
102    (
103      "hr",
104      AdfContentType::from_name("rule")
105    ),
106    (
107      "br",
108      AdfContentType::from_name("hardBreak")
109    ),
110    (
111      "html",
112      AdfContentType::from_name("doc")
113    ),
114    (
115      "body",
116      AdfContentType::from_name("doc")
117    ),
118    (
119      "table",
120      AdfContentType::from_name("table")
121    ),
122    (
123      "tr",
124      AdfContentType::from_name("tableRow")
125    ),
126    (
127      "th",
128      AdfContentType::from_name("tableHeader")
129    ),
130    (
131      "td",
132      AdfContentType::from_name("tableCell")
133    ),
134    (
135      "iframe",
136      AdfContentType::from_name_and_attributes("paragraph", |node|{
137        match node.value().attr("src"){
138          Some(attribute) => vec![("src".to_string(), Value::String(attribute.to_string()))],
139          None => vec!()
140        }
141      }
142      )
143    ),
144    (
145      "b",
146      AdfContentType::from_name_and_marks("text", &[
147        AdfMark{
148          typename: "strong".to_string(),
149          attributes: AdfMarkAttributes::List(vec!())
150        }
151      ])
152    ),
153    (
154      "strong",
155      AdfContentType::from_name_and_marks("text", &[
156        AdfMark{
157          typename: "strong".to_string(),
158          attributes: AdfMarkAttributes::List(vec!())
159        }
160      ])
161    ),
162    (
163      "i",
164      AdfContentType::from_name_and_marks("text", &[
165        AdfMark{
166          typename: "em".to_string(),
167          attributes: AdfMarkAttributes::List(vec!())
168        }
169      ])
170    ),
171    (
172      "em",
173      AdfContentType::from_name_and_marks("text", &[
174        AdfMark{
175          typename: "em".to_string(),
176          attributes: AdfMarkAttributes::List(vec!())
177        }
178      ])
179    ),
180    (
181      "u",
182      AdfContentType::from_name_and_marks("text", &[
183        AdfMark{
184          typename: "underline".to_string(),
185          attributes: AdfMarkAttributes::List(vec!())
186        }
187      ])
188    ),
189    (
190      "pre",
191      AdfContentType::from_name("codeBlock")
192    ),
193    (
194      "code",
195      AdfContentType::from_name_and_marks("text", &[
196        AdfMark{
197          typename: "code".to_string(),
198          attributes: AdfMarkAttributes::List(vec!())
199        }
200      ])
201    ),
202    (
203      "a",
204      AdfContentType::from_name_and_marks("text", &[
205        AdfMark{
206          typename: "link".to_string(),
207          attributes: AdfMarkAttributes::Generator(|element| -> Vec<(String, String)>{
208            match element.value().attr("href"){
209              Some(attribute) => vec![
210                ("href".to_string(), attribute.to_string())
211              ],
212              None => vec!()
213            }
214          })
215        }
216      ])
217    ),
218    (
219      "sub",
220      AdfContentType::from_name_and_marks("text", &[
221        AdfMark{
222          typename: "subsup".to_string(),
223          attributes: AdfMarkAttributes::List(vec![("type".to_string(), "sub".to_string())])
224        }
225      ])
226    ),
227    (
228      "sup",
229      AdfContentType::from_name_and_marks("text", &[
230        AdfMark{
231          typename: "subsup".to_string(),
232          attributes: AdfMarkAttributes::List(vec![("type".to_string(), "sup".to_string())])
233        }
234      ])
235    ),
236    (
237      "h1",
238      AdfContentType::from_name_and_attributes("heading", |_|
239        {
240          vec!(
241            ("level".to_string(), Value::Number(serde_json::Number::from(1))),
242          )
243        }
244      )
245    ),
246    (
247      "h2",
248      AdfContentType::from_name_and_attributes("heading", |_|
249        {
250          vec!(
251            ("level".to_string(), Value::Number(serde_json::Number::from(2))),
252          )
253        }
254      )
255    ),
256    (
257      "h3",
258      AdfContentType::from_name_and_attributes("heading", |_|
259        {
260          vec!(
261            ("level".to_string(), Value::Number(serde_json::Number::from(3))),
262          )
263        }
264      )
265    ),
266    (
267      "h4",
268      AdfContentType::from_name_and_attributes("heading", |_|
269        {
270          vec!(
271            ("level".to_string(), Value::Number(serde_json::Number::from(4))),
272          )
273        }
274      )
275    ),
276    (
277      "h5",
278      AdfContentType::from_name_and_attributes("heading", |_|
279        {
280          vec!(
281            ("level".to_string(), Value::Number(serde_json::Number::from(5))),
282          )
283        }
284      )
285    ),
286    (
287      "h6",
288      AdfContentType::from_name_and_attributes("heading", |_|
289        {
290          vec!(
291            ("level".to_string(), Value::Number(serde_json::Number::from(6))),
292          )
293        }
294      )
295    ),
296    (
297      "img",
298      AdfContentType::from_name_and_attributes("mediaSingle", |node|
299        {
300          match node.value().attr("src"){
301            Some(attribute) => vec!(
302              ("url".to_string(), Value::String(attribute.to_string())),
303              ("type".to_string(), Value::String("external".to_string()))
304            ),
305            None => vec!()
306          }
307
308        }
309      )
310    ),
311]);
312}