1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
///! Module with some extra constructors using public interfaces
///! Not strictly necessary to use, but does eliminate some repetitive tasks
use crate::{
    attributes,
    node::{Comment, Element, ElementType, Node},
    tag::Tag,
    text::Text,
};
use attributes::{Attribute, Value};
use std::collections::HashMap;

impl<'a> Node<'a> {
    /// Creates a comment as a Node from the supplied string
    pub fn comment(text: &str) -> Self {
        let comment: Comment = text.to_string().into();
        comment.into()
    }

    /// Creates a text element as a node
    pub fn text(text: &str) -> Self {
        let text: Text = Text::create(text);
        text.into()
    }


}

impl<'a> Element<'a, Vec<Node<'a>>> {
    /// Pushes a child not into the element
    /// Note: you can also do this yourself, but this is nicer
    /// as it will coerce anything that can be a node into a node
    pub fn push<N>(&mut self, node: N) -> ()
    where
        N: Into<Node<'a>>,
    {
        let node = node.into();
        self.children.push(node);
    }

    /// Helper function to create a link
    /// given the label and url
    pub fn anchor(url: Value<'a>, label: Text) -> Self {
        // Note: in future URL should be more strongly typed?
        let mut element = Element::<Vec<Node>>::create(Tag::A);
        element.set_attribute(Attribute::HREF, url);
        element.push(label);
        element.into()
    }

    /// Creates a body element. Note consumes the children vector
    pub fn body<N> (children:Vec<N>) -> Self 
        where N : Into<Node<'a>> {
        let mut el = Element::<Vec<Node>>::create(Tag::BODY);
        for child in children{
            el.push(child);
        }
        el
    }

    /// Creates the html element
    /// Helper here assumes you have a body and header.
    /// as thats's used pretty much always
    pub fn html(header:Element<'a,Vec<Node<'a>>>, body:Element<'a,Vec<Node<'a>>>) -> Self {
        let mut el = Element::<Vec<Node>>::create(Tag::HTML);
        el.push(header);
        el.push(body);
        el
    }

    /// Creates a html title, with the supplied text
    pub fn title(title:Text) -> Self {
        let mut el = Element::<Vec<Node>>::create(Tag::TITLE);
        el.push(title);
        el
    }
}

impl<'a, T> Element<'a, T>
where
    T: ElementType,
{
    /// Creates a typical element with children, from the
    /// provided tag name. This is the typical case
    pub fn create(name: Tag<'a>) -> Self {
        let attributes = HashMap::default();
        let children = T::default();
        let element = Element {
            name,
            attributes,
            children,
        };
        element
    }

    /// Sets the supplied attribute as a 'boolean' attribute
    /// This means it will just appear in the html, and will not render
    /// with a =value eg <div editable></div>
    pub fn set_bool_attribute(&mut self, key: Attribute<'a>) {
        self.attributes.insert(key, None);
    }

    /// Sets the attribute to the supplied value
    /// Note: sugar over wrapping the value with some.
    pub fn set_attribute(&mut self, key: Attribute<'a>, value: Value<'a>) {
        self.attributes.insert(key, Some(value));
    }
}