--- /dev/null
+use std::borrow::Borrow;
+
+#[derive(Debug)]
+pub enum HtmlNode<T, U> {
+ Text(T),
+ Element(U)
+}
+
+pub trait HtmlElement: Sized {
+ type Text1: AsRef<str>;
+ type Text2: AsRef<str>;
+ type ContentsIter: DoubleEndedIterator<Item=HtmlNode<Self::Text1, Self>>;
+ fn name(&self) -> &str;
+ fn contents(self) -> Self::ContentsIter;
+ fn text(&self) -> Self::Text2;
+}
--- /dev/null
+use std::cell::{Cell, RefCell};
+use std::rc::{Rc, Weak};
+use std::borrow::Cow;
+
+use html5ever::tree_builder::{TreeSink, ElementFlags};
+use html5ever::{QualName, ExpandedName, LocalNameStaticSet, Attribute};
+use html5ever::tendril::{StrTendril, TendrilSink};
+use html5ever::interface::{NodeOrText, QuirksMode};
+use html5ever::driver::ParseOpts;
+use string_cache::Atom;
+
+use crate::html::{HtmlNode, HtmlElement};
+
+type RcNode<'a> = HtmlNode<StrTendril, RcHtmlElement<'a>>;
+
+pub fn parse_html(html: &str) -> UniqHtmlElement {
+ let mut parser = html5ever::parse_fragment(RcHtmlElement(Rc::new(HtmlElementInner::root())), ParseOpts::default(), QualName::new(None, Atom::from("http://www.w3.org/1999/xhtml"), Atom::from("body")), Vec::new());
+ parser.process(StrTendril::from(html));
+ parser.finish()
+}
+
+// #[derive(Debug)]
+struct HtmlElementInner<'a> {
+ name: QualName,
+ parent: Cell<Weak<HtmlElementInner<'a>>>,
+ contents: RefCell<Vec<RcNode<'a>>>
+}
+
+impl HtmlElementInner<'_> {
+ fn root() -> Self {
+ let name = QualName::new(None, Atom::from(""), Atom::from(""));
+ let parent = Cell::new(Weak::new());
+ let contents = RefCell::new(Vec::new());
+ HtmlElementInner { name, parent, contents }
+ }
+}
+
+//#[derive(Clone, Debug)]
+#[derive(Clone)]
+struct RcHtmlElement<'a>(Rc<HtmlElementInner<'a>>);
+
+fn nodeortext_to_htmlnode<'a>(v: NodeOrText<RcHtmlElement<'a>>) -> RcNode<'a> {
+ match v {
+ NodeOrText::AppendNode(h) => HtmlNode::Element(h),
+ NodeOrText::AppendText(s) => HtmlNode::Text(s)
+ }
+}
+
+fn node_eq_elem<'a>(node: &RcNode<'a>, elem: &RcHtmlElement<'a>) -> bool {
+ match node {
+ HtmlNode::Element(elem1) if Rc::ptr_eq(&elem.0, &elem1.0) => true,
+ _ => false
+ }
+}
+
+impl<'a> TreeSink for RcHtmlElement<'a> {
+ type Handle = Self;
+ type Output = UniqHtmlElement;
+ fn finish(self) -> UniqHtmlElement {
+ // let HtmlElementInner { name, parent, contents } = Rc::try_unwrap(self.0).map_err(|_| ()).expect("no refs left around");
+ let HtmlElementInner { ref name, ref contents, .. } = *self.0;
+ let name = name.local.clone();
+ let contents = contents.borrow_mut().drain(..).map(|node| {
+ match node {
+ HtmlNode::Text(s) => HtmlNode::Text(s),
+ HtmlNode::Element(e) => HtmlNode::Element(e.finish())
+ }
+ }).collect();
+ UniqHtmlElement { name, contents }
+ }
+
+ fn parse_error(&mut self, msg: Cow<'static, str>) {
+ println!("{}", msg);
+ panic!("how do parse??");
+ }
+
+ fn get_document(&mut self) -> Self::Handle {
+ self.clone()
+ }
+
+ fn elem_name<'b>(&'b self, target: &'b Self::Handle) -> ExpandedName<'b> {
+ target.0.name.expanded()
+ }
+
+ fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>, flags: ElementFlags) -> Self::Handle {
+ assert_eq!(flags.template, false);
+ assert_eq!(flags.mathml_annotation_xml_integration_point, false);
+ let contents = RefCell::new(Vec::new());
+ let parent = Cell::new(Weak::new());
+ // handily, we never use attribute data. Toss it
+ RcHtmlElement(Rc::new(HtmlElementInner { name, parent, contents }))
+ }
+
+ fn create_comment(&mut self, text: StrTendril) -> Self::Handle {
+ panic!("HTML parser encountered a comment");
+ }
+
+ fn create_pi(&mut self, target: StrTendril, data: StrTendril) -> Self::Handle {
+ panic!("HTML parser encountered a processing instruction");
+ }
+
+ fn append(&mut self, parent: &Self::Handle, child: NodeOrText<Self::Handle>) {
+ let node = nodeortext_to_htmlnode(child);
+ if let HtmlNode::Element(ref elem) = node {
+ elem.0.parent.set(Rc::downgrade(&parent.0));
+ }
+ parent.0.contents.borrow_mut().push(node);
+ }
+
+ fn append_based_on_parent_node(&mut self, element: &Self::Handle, prev_element: &Self::Handle, child: NodeOrText<Self::Handle>) {
+ panic!("Not clear what this is for or if it needs to be implemented");
+ }
+
+ fn append_doctype_to_document(&mut self, name: StrTendril, public_id: StrTendril, system_id: StrTendril) {
+ panic!("This can likely be a no-op, just not sure if it gets called for these fragments");
+ }
+
+ fn get_template_contents(&mut self, target: &Self::Handle) -> Self::Handle {
+ panic!("HTML parser encountered a <template> element")
+ }
+
+ fn same_node(&self, x: &Self::Handle, y: &Self::Handle) -> bool {
+ Rc::ptr_eq(&x.0, &y.0)
+ }
+
+ fn set_quirks_mode(&mut self, mode: QuirksMode) {}
+
+ fn append_before_sibling(&mut self, sibling: &Self::Handle, new_node: NodeOrText<Self::Handle>) {
+ let parent_weak = sibling.0.parent.take();
+ let parent = parent_weak.upgrade().expect("parent is not dropped");
+ let mut children = parent.contents.borrow_mut();
+ sibling.0.parent.set(parent_weak);
+ let pos = children.iter().position(|node| node_eq_elem(node, sibling)).expect("sibling is child of parent");
+ children.insert(pos, nodeortext_to_htmlnode(new_node));
+ }
+
+ fn add_attrs_if_missing(&mut self, target: &Self::Handle, attrs: Vec<Attribute>) {}
+
+ fn remove_from_parent(&mut self, target: &Self::Handle) {
+ let parent = target.0.parent.replace(Weak::new()).upgrade().expect("target has parent");
+ let mut children = parent.contents.borrow_mut();
+ let pos = children.iter().position(|node| node_eq_elem(node, target)).expect("sibling is child of parent");
+ children.remove(pos);
+ }
+
+ fn reparent_children(&mut self, node: &Self::Handle, new_parent: &Self::Handle) {
+ new_parent.0.contents.borrow_mut().extend(node.0.contents.borrow_mut().drain(..));
+ }
+}
+
+
+#[derive(Debug)]
+pub struct UniqHtmlElement {
+ name: Atom<LocalNameStaticSet>,
+ contents: Vec<HtmlNode<StrTendril, UniqHtmlElement>>
+}
+
+/*fn node_text(node: &HtmlNode<StrTendril, UniqHtmlElement>) -> Cow<str> {
+ match node {
+ HtmlNode::Text(s) => Cow::Borrowed(s.as_ref()),
+ HtmlNode::Element(e) => e.text()
+ }
+}*/
+
+fn element_text_inner(buf: &mut Option<StrTendril>, elem: &UniqHtmlElement) {
+ for node in &elem.contents {
+ match node {
+ HtmlNode::Text(s) => match buf {
+ None => { *buf = Some(s.clone()); },
+ Some(tendril) => tendril.push_tendril(&s)
+ },
+ HtmlNode::Element(e) => element_text_inner(buf, &e)
+ }
+ }
+}
+
+impl HtmlElement for UniqHtmlElement {
+ type Text1 = StrTendril;
+ type Text2 = StrTendril;
+ type ContentsIter = <Vec<HtmlNode<Self::Text1, Self>> as IntoIterator>::IntoIter;
+ fn name(&self) -> &str {
+ &*self.name
+ }
+ fn contents(self) -> Self::ContentsIter {
+ self.contents.into_iter()
+ }
+ fn text(&self) -> StrTendril {
+ let mut result = None;
+ element_text_inner(&mut result, self);
+ result.unwrap_or(StrTendril::new())
+/* let mut init = self.contents.get(0).map(node_text).unwrap_or(Cow::Borrowed(""));
+ for node in &self.contents[1..] {
+ let text = node_text(node);
+ if text.len() > 0 {
+ init.to_mut().push_str(&text);
+ }
+ }
+ init*/
+ }
+}
+++ /dev/null
-use std::borrow::Borrow;
-
-#[derive(Debug)]
-pub enum HtmlNode<T, U> {
- Text(T),
- Element(U)
-}
-
-pub trait HtmlElement: Sized {
- type Text1: AsRef<str>;
- type Text2: AsRef<str>;
- type ContentsIter: DoubleEndedIterator<Item=HtmlNode<Self::Text1, Self>>;
- fn name(&self) -> &str;
- fn contents(self) -> Self::ContentsIter;
- fn text(&self) -> Self::Text2;
-}
mod live_event_buffer;
-mod html_nodes;
+mod html;
+mod html_html5ever;
pub use live_event_buffer::LiveUpdateBuffer;
-pub use html_nodes::{HtmlNode, HtmlElement};
+pub use html::{HtmlNode, HtmlElement};
+pub use html_html5ever::{parse_html};
use uuid::Uuid;
-use crate::html_nodes::HtmlElement;
+use crate::HtmlElement;
pub struct LiveUpdateMeta {
id: Uuid,
-use std::cell::{Cell, RefCell};
-use std::rc::{Rc, Weak};
-use std::borrow::Cow;
-
-use html5ever::tree_builder::{TreeSink, ElementFlags};
-use html5ever::{QualName, ExpandedName, LocalNameStaticSet, Attribute};
-use html5ever::tendril::{StrTendril, TendrilSink};
-use html5ever::interface::{NodeOrText, QuirksMode};
-use html5ever::driver::ParseOpts;
-use string_cache::Atom;
-
-use sharedmodel::{HtmlNode, HtmlElement};
+use sharedmodel::{parse_html, HtmlElement};
fn main() {
- let mut x = html5ever::parse_fragment(RcHtmlElement(Rc::new(HtmlElementInner::root())), ParseOpts::default(), QualName::new(None, Atom::from("http://www.w3.org/1999/xhtml"), Atom::from("body")), Vec::new());
//let html = "<p>This is <em>a <a href=\"#\">paragraph</a></em>. There are</p><ul><li>nested</li><li>tags, <strong>especially in <em>here</em></strong></li></ul>";
//let html = "<p>A paragraph</p>";
let html = "<section><p>Can you handle this</p><table><tr><th>a</th><th>b</th></tr><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></table></section>";
- x.process(StrTendril::from(html));
- let tr = x.finish();
+ let tr = parse_html(html);
println!("{:?}", tr);
println!("{}", tr.text())
}
-type RcNode<'a> = HtmlNode<StrTendril, RcHtmlElement<'a>>;
-
-// #[derive(Debug)]
-struct HtmlElementInner<'a> {
- name: QualName,
- parent: Cell<Weak<HtmlElementInner<'a>>>,
- contents: RefCell<Vec<RcNode<'a>>>
-}
-
-impl HtmlElementInner<'_> {
- fn root() -> Self {
- let name = QualName::new(None, Atom::from(""), Atom::from(""));
- let parent = Cell::new(Weak::new());
- let contents = RefCell::new(Vec::new());
- HtmlElementInner { name, parent, contents }
- }
-}
-
-//#[derive(Clone, Debug)]
-#[derive(Clone)]
-struct RcHtmlElement<'a>(Rc<HtmlElementInner<'a>>);
-
-fn nodeortext_to_htmlnode<'a>(v: NodeOrText<RcHtmlElement<'a>>) -> RcNode<'a> {
- match v {
- NodeOrText::AppendNode(h) => HtmlNode::Element(h),
- NodeOrText::AppendText(s) => HtmlNode::Text(s)
- }
-}
-
-fn node_eq_elem<'a>(node: &RcNode<'a>, elem: &RcHtmlElement<'a>) -> bool {
- match node {
- HtmlNode::Element(elem1) if Rc::ptr_eq(&elem.0, &elem1.0) => true,
- _ => false
- }
-}
-
-impl<'a> TreeSink for RcHtmlElement<'a> {
- type Handle = Self;
- type Output = UniqHtmlElement;
- fn finish(self) -> UniqHtmlElement {
- // let HtmlElementInner { name, parent, contents } = Rc::try_unwrap(self.0).map_err(|_| ()).expect("no refs left around");
- let HtmlElementInner { ref name, ref contents, .. } = *self.0;
- let name = name.local.clone();
- let contents = contents.borrow_mut().drain(..).map(|node| {
- match node {
- HtmlNode::Text(s) => HtmlNode::Text(s),
- HtmlNode::Element(e) => HtmlNode::Element(e.finish())
- }
- }).collect();
- UniqHtmlElement { name, contents }
- }
-
- fn parse_error(&mut self, msg: Cow<'static, str>) {
- println!("{}", msg);
- panic!("how do parse??");
- }
-
- fn get_document(&mut self) -> Self::Handle {
- self.clone()
- }
-
- fn elem_name<'b>(&'b self, target: &'b Self::Handle) -> ExpandedName<'b> {
- target.0.name.expanded()
- }
-
- fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>, flags: ElementFlags) -> Self::Handle {
- assert_eq!(flags.template, false);
- assert_eq!(flags.mathml_annotation_xml_integration_point, false);
- let contents = RefCell::new(Vec::new());
- let parent = Cell::new(Weak::new());
- // handily, we never use attribute data. Toss it
- RcHtmlElement(Rc::new(HtmlElementInner { name, parent, contents }))
- }
-
- fn create_comment(&mut self, text: StrTendril) -> Self::Handle {
- panic!("HTML parser encountered a comment");
- }
-
- fn create_pi(&mut self, target: StrTendril, data: StrTendril) -> Self::Handle {
- panic!("HTML parser encountered a processing instruction");
- }
-
- fn append(&mut self, parent: &Self::Handle, child: NodeOrText<Self::Handle>) {
- let node = nodeortext_to_htmlnode(child);
- if let HtmlNode::Element(ref elem) = node {
- elem.0.parent.set(Rc::downgrade(&parent.0));
- }
- parent.0.contents.borrow_mut().push(node);
- }
-
- fn append_based_on_parent_node(&mut self, element: &Self::Handle, prev_element: &Self::Handle, child: NodeOrText<Self::Handle>) {
- panic!("Not clear what this is for or if it needs to be implemented");
- }
-
- fn append_doctype_to_document(&mut self, name: StrTendril, public_id: StrTendril, system_id: StrTendril) {
- panic!("This can likely be a no-op, just not sure if it gets called for these fragments");
- }
-
- fn get_template_contents(&mut self, target: &Self::Handle) -> Self::Handle {
- panic!("HTML parser encountered a <template> element")
- }
-
- fn same_node(&self, x: &Self::Handle, y: &Self::Handle) -> bool {
- Rc::ptr_eq(&x.0, &y.0)
- }
-
- fn set_quirks_mode(&mut self, mode: QuirksMode) {}
-
- fn append_before_sibling(&mut self, sibling: &Self::Handle, new_node: NodeOrText<Self::Handle>) {
- let parent_weak = sibling.0.parent.take();
- let parent = parent_weak.upgrade().expect("parent is not dropped");
- let mut children = parent.contents.borrow_mut();
- sibling.0.parent.set(parent_weak);
- let pos = children.iter().position(|node| node_eq_elem(node, sibling)).expect("sibling is child of parent");
- children.insert(pos, nodeortext_to_htmlnode(new_node));
- }
-
- fn add_attrs_if_missing(&mut self, target: &Self::Handle, attrs: Vec<Attribute>) {}
-
- fn remove_from_parent(&mut self, target: &Self::Handle) {
- let parent = target.0.parent.replace(Weak::new()).upgrade().expect("target has parent");
- let mut children = parent.contents.borrow_mut();
- let pos = children.iter().position(|node| node_eq_elem(node, target)).expect("sibling is child of parent");
- children.remove(pos);
- }
-
- fn reparent_children(&mut self, node: &Self::Handle, new_parent: &Self::Handle) {
- new_parent.0.contents.borrow_mut().extend(node.0.contents.borrow_mut().drain(..));
- }
-}
-
-
-#[derive(Debug)]
-struct UniqHtmlElement {
- name: Atom<LocalNameStaticSet>,
- contents: Vec<HtmlNode<StrTendril, UniqHtmlElement>>
-}
-
-/*fn node_text(node: &HtmlNode<StrTendril, UniqHtmlElement>) -> Cow<str> {
- match node {
- HtmlNode::Text(s) => Cow::Borrowed(s.as_ref()),
- HtmlNode::Element(e) => e.text()
- }
-}*/
-
-fn element_text_inner(buf: &mut Option<StrTendril>, elem: &UniqHtmlElement) {
- for node in &elem.contents {
- match node {
- HtmlNode::Text(s) => match buf {
- None => { *buf = Some(s.clone()); },
- Some(tendril) => tendril.push_tendril(&s)
- },
- HtmlNode::Element(e) => element_text_inner(buf, &e)
- }
- }
-}
-
-impl HtmlElement for UniqHtmlElement {
- type Text1 = StrTendril;
- type Text2 = StrTendril;
- type ContentsIter = <Vec<HtmlNode<Self::Text1, Self>> as IntoIterator>::IntoIter;
- fn name(&self) -> &str {
- &*self.name
- }
- fn contents(self) -> Self::ContentsIter {
- self.contents.into_iter()
- }
- fn text(&self) -> StrTendril {
- let mut result = None;
- element_text_inner(&mut result, self);
- result.unwrap_or(StrTendril::new())
-/* let mut init = self.contents.get(0).map(node_text).unwrap_or(Cow::Borrowed(""));
- for node in &self.contents[1..] {
- let text = node_text(node);
- if text.len() > 0 {
- init.to_mut().push_str(&text);
- }
- }
- init*/
- }
-}