edita/nodes/
bullet_list.rs

1use edita_core::{Block, Editor};
2use hirola::prelude::*;
3use js_sys::Object;
4use serde::Serialize;
5use wasm_bindgen::JsCast;
6use web_sys::{Element, Node};
7
8use crate::{nodes::EditorNode, EditorState};
9
10use super::list_item::{ListItem, ListItemBlock};
11
12pub struct BulletListBlock;
13
14impl Block for BulletListBlock {
15    type Node = EditorNode;
16    type State = EditorState;
17    type Input = web_sys::Node;
18    fn accepts(&self, node: &Node) -> bool {
19        if let Some(element) = node.dyn_ref::<Element>() {
20            element.tag_name() == "UL"
21        } else {
22            false
23        }
24    }
25
26    fn parse(
27        &self,
28        editor: &Editor<Self::Node, Self::State, web_sys::Node>,
29        node: &web_sys::Node,
30    ) -> EditorNode {
31        EditorNode::BulletList(BulletList {
32            list: Object::entries(&node.child_nodes())
33                .into_iter()
34                .map(|item| ListItemBlock::parse(&ListItemBlock, editor, item.dyn_ref().unwrap()))
35                .map(|node| match node {
36                    EditorNode::ListItem(item) => Some(item),
37                    _ => None,
38                })
39                .filter(|item| item.is_some())
40                .map(|c| c.unwrap())
41                .collect(),
42        })
43    }
44}
45
46#[derive(Clone, Serialize, Debug)]
47pub struct BulletList {
48    list: Vec<ListItem>,
49}
50
51impl crate::nodes::Node for BulletList {
52    fn render(&self) -> hirola::dom::Dom {
53        html! {
54        <ul>
55            {for item in &self.list {
56                html! { <>{item.render()}</> }
57            }}
58        </ul>
59    }
60    }
61}