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,
}
}
}