SHARE
TWEET

Untitled

a guest Jan 19th, 2020 70 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #[derive(Clone)]
  2. pub enum NodeType {
  3.     Element,
  4.     Attribute,
  5.     Text,
  6.     Comment,
  7.     DocumentType,
  8. }
  9.  
  10. pub enum TagType {
  11.     None,
  12.     Opening,
  13.     Closing,
  14.     SelfClosing,
  15. }
  16.  
  17. #[derive(Clone)]
  18. pub struct DomElement {
  19.     children: Vec<DomElement>,
  20.     parentNode: Box<Option<DomElement>>,
  21.     nodeValue: String,
  22.     nodeType: NodeType,
  23.     innerHTML: String,
  24.     outerHTML: String,
  25.     tagName: String,
  26. }
  27.  
  28. impl DomElement {
  29.     pub fn new(nodeType: NodeType) -> DomElement {
  30.         DomElement {
  31.             children: vec![],
  32.             parentNode: Box::from(None),
  33.             nodeType,
  34.             innerHTML: "".to_string(),
  35.             outerHTML: "".to_string(),
  36.             nodeValue: "".to_string(),
  37.             tagName: "".to_string(),
  38.         }
  39.     }
  40. }
  41.  
  42. const SELF_CLOSING_TAGS: &[&str] = &[
  43.     "AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK",
  44.     "MENUITEM", "META", "PARAM", "SOURCE", "TRACK", "WBR",
  45. ];
  46.  
  47. fn getTagName(source: &str) -> String {
  48.     return source
  49.         .replace("<", "")
  50.         .replace("/", "")
  51.         .replace(">", "")
  52.         .split(" ")
  53.         .collect::<Vec<&str>>()[0]
  54.         .to_uppercase()
  55.         .trim()
  56.         .to_string();
  57. }
  58.  
  59. fn getTagType(token: &str, tagName: &str) -> TagType {
  60.     let mut chars = token.chars();
  61.  
  62.     if chars.nth(0).unwrap() == '<' && chars.clone().last().unwrap() == '>' {
  63.         if chars.nth(1).unwrap() == '/' {
  64.             return TagType::Closing;
  65.         } else if SELF_CLOSING_TAGS.contains(&token) {
  66.             return TagType::SelfClosing;
  67.         } else {
  68.             return TagType::Opening;
  69.         }
  70.     }
  71.  
  72.     return TagType::None;
  73. }
  74.  
  75. fn getNodeType(token: &str, tagName: &str) -> NodeType {
  76.     let mut chars = token.chars();
  77.  
  78.     if chars.nth(0).unwrap() == '<' && chars.clone().last().unwrap() == '>' {
  79.         if token.starts_with("<!--") {
  80.             return NodeType::Comment;
  81.         } else if chars.nth(1).unwrap() == '!' {
  82.             return NodeType::DocumentType;
  83.         } else {
  84.             return NodeType::Element;
  85.         }
  86.     }
  87.  
  88.     return NodeType::Text;
  89. }
  90.  
  91. fn tokenize(html: String) -> Vec<String> {
  92.     let mut tokens: Vec<String> = vec![];
  93.  
  94.     let mut capturing = false;
  95.     let mut capturedText = String::from("");
  96.  
  97.     for i in 0..html.len() {
  98.         let c = html.chars().nth(i).unwrap();
  99.  
  100.         if c == '<' {
  101.             if capturing {
  102.                 tokens.push(capturedText.to_string());
  103.             } else {
  104.                 capturing = true;
  105.             }
  106.             capturedText = String::from("");
  107.         } else if c == '>' || i == html.len() - 1 {
  108.             capturing = false;
  109.             capturedText.push(c);
  110.         } else if !capturing {
  111.             capturedText = String::from("");
  112.         }
  113.  
  114.         if capturing {
  115.             capturedText.push(c);
  116.         }
  117.     }
  118.  
  119.     return tokens;
  120. }
  121.  
  122. fn getOpeningTag(tagName: &str, element: &Option<DomElement>) -> Option<DomElement> {
  123.     if element.clone().unwrap().tagName == tagName {
  124.         return element.clone();
  125.     } else {
  126.         return getOpeningTag(tagName, &(*(element.clone().unwrap()).parentNode));
  127.     }
  128. }
  129.  
  130. fn buildTree(tokens: Vec<String>) -> Vec<DomElement> {
  131.     let mut elements: Vec<DomElement> = vec![];
  132.     let mut openTags: Vec<String> = vec![];
  133.  
  134.     let mut parent: Option<DomElement> = None;
  135.  
  136.     for token in tokens {
  137.         let tagName = getTagName(&token);
  138.         let tagType = getTagType(&token, &tagName);
  139.         let nodeType = getNodeType(&token, &tagName);
  140.  
  141.         match tagType {
  142.             TagType::Closing => match &parent {
  143.                 Some(item) => {
  144.                     let openTagIndex = &openTags.iter().rev().position(|s| s == &tagName);
  145.                     match openTagIndex {
  146.                         Some(index) => {
  147.                             if item.tagName == tagName.to_string() {
  148.                                 parent = Some((*item.parentNode.clone()).unwrap())
  149.                             } else {
  150.                                 let openingElement = getOpeningTag(&tagName, &Some(item.clone()));
  151.                                 match openingElement {
  152.                                     Some(el) => parent = Some((*el.parentNode).unwrap()),
  153.                                     None => {}
  154.                                 }
  155.                             }
  156.  
  157.                             openTags.remove(*index);
  158.                         }
  159.                         None => {}
  160.                     }
  161.                 }
  162.                 None => {}
  163.             },
  164.             _ => {
  165.                 let mut element = DomElement::new(nodeType);
  166.  
  167.                 match &parent {
  168.                     Some(item) => {
  169.                         element.parentNode = Box::from(parent);
  170.                     }
  171.                     None => {
  172.                         elements.push(element);
  173.                     }
  174.                 }
  175.             }
  176.         }
  177.     }
  178.  
  179.     return elements;
  180. }
  181.  
  182. fn main() {
  183.     println!("Hello, world!");
  184. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top