etch 0.4.2

Not just a text formatter, don't mark it down, etch it.
Documentation
use crate::nodes::Node;
use crate::plugins::Plugin;
use crate::state::*;

const ELEMENTS: [&str; 7] = ["h1", "h2", "h3", "h4", "h5", "h6", "p"];

#[derive(Debug, PartialEq)]
pub struct WidowedWordsPlugin;

impl WidowedWordsPlugin {
    pub fn new() -> Shared<Self> {
        Shared::share(WidowedWordsPlugin)
    }
}

impl Plugin for WidowedWordsPlugin {
    fn on_node_parsed(&mut self, token: Node) -> Node {
        match token.clone() {
            Node::Element { name, .. } => {
                if ELEMENTS.contains(&name.as_str()) {
                    DeWidower::default().process(token)
                } else {
                    token
                }
            }
            _ => token,
        }
    }
}

struct DeWidower {
    break_found: bool,
}

impl Default for DeWidower {
    fn default() -> Self {
        DeWidower { break_found: false }
    }
}

impl DeWidower {
    fn process(&mut self, token: Node) -> Node {
        match token {
            Node::Element {
                name,
                tags,
                attributes,
                children,
            } => {
                let children = if let Some(children) = children {
                    let mut children: Vec<Node> = children
                        .into_iter()
                        .rev()
                        .map(|child| match child {
                            Node::Element { .. } => self.process(child),
                            Node::Whitespace { .. } => {
                                if !self.break_found {
                                    self.break_found = true;

                                    Node::NonBreakingSpace { space: " ".into() }
                                } else {
                                    child
                                }
                            }
                            _ => child,
                        })
                        .collect();

                    children.reverse();

                    Some(children)
                } else {
                    None
                };

                Node::Element {
                    name,
                    tags,
                    attributes,
                    children,
                }
            }
            _ => token,
        }
    }
}