Przeglądaj źródła

fix: translation service

Jonathan Kelley 3 lat temu
rodzic
commit
025efc9120

+ 0 - 1
src/cli/translate/extract_svgs.rs

@@ -1 +0,0 @@
-

+ 192 - 48
src/cli/translate/mod.rs

@@ -1,15 +1,14 @@
+use anyhow::Result;
 use html_parser::Dom;
+use html_parser::Element;
 use html_parser::Node;
-use std::fmt::Write;
+#[allow(unused_imports)]
+use std::fmt::{Display, Formatter};
 use std::io::Read;
 use std::path::PathBuf;
 use std::process::exit;
 use structopt::StructOpt;
 
-pub mod extract_svgs;
-pub mod to_component;
-pub mod translate;
-
 /// Build the Rust WASM app and all of its assets.
 #[derive(Clone, Debug, StructOpt)]
 #[structopt(name = "translate")]
@@ -21,11 +20,7 @@ pub struct Translate {
 
     /// Input file
     #[structopt(short, long)]
-    pub source: Option<String>,
-
-    /// Input file
-    #[structopt(short, long, parse(from_os_str))]
-    pub input: Option<PathBuf>,
+    pub file: Option<String>,
 
     /// Output file, stdout if not present
     #[structopt(parse(from_os_str))]
@@ -35,23 +30,17 @@ pub struct Translate {
 impl Translate {
     pub fn translate(self) -> anyhow::Result<()> {
         let Translate {
-            component: as_component,
-            input,
+            component,
             output,
-            source,
+            file,
         } = self;
 
-        let contents;
-        let temp = input.map(|f| {
-            std::fs::read_to_string(&f).unwrap_or_else(|e| {
+        let contents = match file {
+            Some(input) => std::fs::read_to_string(&input).unwrap_or_else(|e| {
                 log::error!("Cloud not read input file: {}.", e);
                 exit(0);
-            })
-        });
-        if let Some(..) = temp {
-            if let Some(s) = source {
-                contents = s;
-            } else {
+            }),
+            None => {
                 if atty::is(atty::Stream::Stdin) {
                     log::error!("No input file, source, or stdin to translate from.");
                     exit(0);
@@ -60,28 +49,21 @@ impl Translate {
                 let mut buffer = String::new();
                 std::io::stdin().read_to_string(&mut buffer).unwrap();
 
-                contents = buffer.trim().to_string();
+                buffer.trim().to_string()
             }
-        } else {
-            contents = temp.unwrap();
-        }
+        };
 
-        // parse the input as html and prepare the output
-        let dom = Dom::parse(&contents)?;
-        let mut out_buf = String::new();
-
-        if as_component {
-            writeln!(out_buf, "use dioxus::prelude::*;")?;
-            writeln!(out_buf, "fn component(cx: Scope) -> Element {{")?;
-            writeln!(out_buf, "    cx.render(rsx!(")?;
-        }
-        for child in &dom.children {
-            render_child(&mut out_buf, child, if as_component { 2 } else { 0 })?;
-        }
-        if as_component {
-            writeln!(out_buf, "    ))")?;
-            writeln!(out_buf, "}}")?;
-        }
+        let out_buf = match component {
+            true => format!("{}", convert_html_to_component(&contents).unwrap()),
+            false => {
+                let mut buf = String::new();
+                let dom = Dom::parse(&contents).unwrap();
+                for child in &dom.children {
+                    simple_render_child(&mut buf, child, 0)?;
+                }
+                buf
+            }
+        };
 
         if let Some(output) = output {
             std::fs::write(&output, out_buf)?;
@@ -93,7 +75,8 @@ impl Translate {
     }
 }
 
-fn render_child(f: &mut impl Write, child: &Node, il: u32) -> std::fmt::Result {
+/// render without handling svgs or anything
+fn simple_render_child(f: &mut impl std::fmt::Write, child: &Node, il: u32) -> std::fmt::Result {
     write_tabs(f, il)?;
     match child {
         Node::Text(t) => writeln!(f, "\"{}\"", t)?,
@@ -131,9 +114,8 @@ fn render_child(f: &mut impl Write, child: &Node, il: u32) -> std::fmt::Result {
                         None => writeln!(f, "{}: \"\",", new_name)?,
                     }
                 } else {
-                    match name.as_str() {
-                        "for" | "async" | "type" | "as" => write!(f, "r#")?,
-                        _ => {}
+                    if matches!(name.as_str(), "for" | "async" | "type" | "as") {
+                        write!(f, "r#")?
                     }
 
                     match value {
@@ -145,7 +127,7 @@ fn render_child(f: &mut impl Write, child: &Node, il: u32) -> std::fmt::Result {
 
             // now the children
             for child in &el.children {
-                render_child(f, child, il + 1)?;
+                simple_render_child(f, child, il + 1)?;
             }
 
             // close the tag
@@ -156,9 +138,171 @@ fn render_child(f: &mut impl Write, child: &Node, il: u32) -> std::fmt::Result {
     Ok(())
 }
 
-fn write_tabs(f: &mut impl Write, num: u32) -> std::fmt::Result {
+pub fn convert_html_to_component(html: &str) -> Result<ComponentRenderer> {
+    Ok(ComponentRenderer {
+        dom: Dom::parse(html)?,
+        icon_index: 0,
+    })
+}
+
+#[allow(dead_code)]
+pub struct ComponentRenderer {
+    dom: Dom,
+    icon_index: usize,
+}
+
+impl Display for ComponentRenderer {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        writeln!(
+            f,
+            r##"
+fn component(cx: Scope) -> Element {{
+    cx.render(rsx!("##
+        )?;
+        let mut svg_nodes = vec![];
+
+        let mut svg_idx = 0;
+        for child in &self.dom.children {
+            render_child(f, child, 2, &mut svg_nodes, true, &mut svg_idx)?;
+        }
+        write!(
+            f,
+            r##"    ))
+}}"##
+        )?;
+
+        if svg_idx == 0 {
+            return Ok(());
+        }
+
+        writeln!(f, "\n\nmod icons {{")?;
+
+        let mut id = 0;
+        while let Some(svg) = svg_nodes.pop() {
+            writeln!(
+                f,
+                r##"    pub(super) fn icon_{}(cx: Scope) -> Element {{
+        cx.render(rsx!("##,
+                id
+            )?;
+            write_tabs(f, 3)?;
+
+            render_element(f, svg, 3, &mut svg_nodes, false, &mut 0)?;
+            writeln!(f, "\t\t))\n\t}}\n")?;
+            id += 1;
+        }
+
+        writeln!(f, "}}")?;
+
+        Ok(())
+    }
+}
+
+fn render_child<'a>(
+    f: &mut Formatter<'_>,
+    child: &'a Node,
+    il: u32,
+    svg_buffer: &mut Vec<&'a Element>,
+    skip_svg: bool,
+    svg_idx: &mut usize,
+) -> std::fmt::Result {
+    write_tabs(f, il)?;
+    match child {
+        Node::Text(t) => writeln!(f, "\"{}\"", t)?,
+        Node::Comment(e) => writeln!(f, "/* {} */", e)?,
+        Node::Element(el) => render_element(f, el, il, svg_buffer, skip_svg, svg_idx)?,
+    };
+    Ok(())
+}
+
+fn render_element<'a>(
+    f: &mut Formatter<'_>,
+    el: &'a Element,
+    il: u32,
+    svg_buffer: &mut Vec<&'a Element>,
+    skip_svg: bool,
+    svg_idx: &mut usize,
+) -> std::fmt::Result {
+    if el.name == "svg" && skip_svg {
+        svg_buffer.push(el);
+        // todo: attach the right icon ID
+        writeln!(f, "icons::icon_{} {{}}", svg_idx)?;
+        *svg_idx += 1;
+        return Ok(());
+    }
+
+    // open the tag
+    write!(f, "{} {{ ", &el.name)?;
+
+    // todo: dioxus will eventually support classnames
+    // for now, just write them with a space between each
+    let class_iter = &mut el.classes.iter();
+    if let Some(first_class) = class_iter.next() {
+        write!(f, "class: \"{}", first_class)?;
+        for next_class in class_iter {
+            write!(f, " {}", next_class)?;
+        }
+        write!(f, "\",")?;
+    }
+    writeln!(f)?;
+
+    // write the attributes
+    if let Some(id) = &el.id {
+        write_tabs(f, il + 1)?;
+        writeln!(f, "id: \"{}\",", id)?;
+    }
+
+    for (name, value) in &el.attributes {
+        write_tabs(f, il + 1)?;
+
+        use convert_case::{Case, Casing};
+        if name.chars().any(|ch| ch.is_ascii_uppercase() || ch == '-') {
+            let new_name = name.to_case(Case::Snake);
+            match value {
+                Some(val) => writeln!(f, "{}: \"{}\",", new_name, val)?,
+                None => writeln!(f, "{}: \"\",", new_name)?,
+            }
+        } else {
+            if matches!(name.as_str(), "for" | "async" | "type" | "as") {
+                write!(f, "r#")?
+            }
+
+            match value {
+                Some(val) => writeln!(f, "{}: \"{}\",", name, val)?,
+                None => writeln!(f, "{}: \"\",", name)?,
+            }
+        }
+    }
+
+    // now the children
+    for child in &el.children {
+        render_child(f, child, il + 1, svg_buffer, skip_svg, svg_idx)?;
+    }
+
+    // close the tag
+    write_tabs(f, il)?;
+    writeln!(f, "}}")?;
+    Ok(())
+}
+
+fn write_tabs(f: &mut impl std::fmt::Write, num: u32) -> std::fmt::Result {
     for _ in 0..num {
         write!(f, "    ")?
     }
     Ok(())
 }
+
+#[test]
+fn generates_svgs() {
+    use std::io::Write;
+
+    let st = include_str!("../../../tests/svg.html");
+
+    let out = format!("{:}", convert_html_to_component(st).unwrap());
+    dbg!(&out);
+
+    std::fs::File::create("svg_rsx.rs")
+        .unwrap()
+        .write_all(out.as_bytes())
+        .unwrap();
+}

+ 0 - 183
src/cli/translate/to_component.rs

@@ -1,183 +0,0 @@
-//! Intelligently converts html to rsx with appropraite transformations and extractions.
-//!
-//! - [*] Creates a component
-//! - [ ] Extracts svgs
-//! - [ ] Attempts to extract lists
-
-#[allow(unused_imports)]
-use std::{
-    fmt::{Display, Formatter},
-    io::Write,
-};
-
-use anyhow::Result;
-
-use html_parser::{Dom, Element, Node};
-
-pub fn convert_html_to_component(html: &str) -> Result<ComponentRenderer> {
-    Ok(ComponentRenderer {
-        dom: Dom::parse(html)?,
-        icon_index: 0,
-    })
-}
-
-#[allow(dead_code)]
-pub struct ComponentRenderer {
-    dom: Dom,
-    icon_index: usize,
-}
-
-impl Display for ComponentRenderer {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        writeln!(
-            f,
-            r##"
-fn component(cx: Scope) -> Element {{
-    cx.render(rsx!("##
-        )?;
-        let mut svg_nodes = vec![];
-
-        let mut svg_idx = 0;
-        for child in &self.dom.children {
-            render_child(f, child, 2, &mut svg_nodes, true, &mut svg_idx)?;
-        }
-        write!(
-            f,
-            r##"    ))
-}}"##
-        )?;
-
-        if svg_idx == 0 {
-            return Ok(());
-        }
-
-        writeln!(f, "\n\nmod icons {{")?;
-
-        let mut id = 0;
-        while let Some(svg) = svg_nodes.pop() {
-            writeln!(
-                f,
-                r##"    pub(super) fn icon_{}(cx: Scope) -> Element {{
-        cx.render(rsx!("##,
-                id
-            )?;
-            write_tabs(f, 3)?;
-
-            render_element(f, svg, 3, &mut svg_nodes, false, &mut 0)?;
-            writeln!(f, "\t\t))\n\t}}\n")?;
-            id += 1;
-        }
-
-        writeln!(f, "}}")?;
-
-        Ok(())
-    }
-}
-
-fn render_child<'a>(
-    f: &mut Formatter<'_>,
-    child: &'a Node,
-    il: u32,
-    svg_buffer: &mut Vec<&'a Element>,
-    skip_svg: bool,
-    svg_idx: &mut usize,
-) -> std::fmt::Result {
-    write_tabs(f, il)?;
-    match child {
-        Node::Text(t) => writeln!(f, "\"{}\"", t)?,
-        Node::Comment(e) => writeln!(f, "/* {} */", e)?,
-        Node::Element(el) => render_element(f, el, il, svg_buffer, skip_svg, svg_idx)?,
-    };
-    Ok(())
-}
-
-fn render_element<'a>(
-    f: &mut Formatter<'_>,
-    el: &'a Element,
-    il: u32,
-    svg_buffer: &mut Vec<&'a Element>,
-    skip_svg: bool,
-    svg_idx: &mut usize,
-) -> std::fmt::Result {
-    if el.name == "svg" && skip_svg {
-        svg_buffer.push(el);
-        // todo: attach the right icon ID
-        writeln!(f, "icons::icon_{} {{}}", svg_idx)?;
-        *svg_idx += 1;
-        return Ok(());
-    }
-
-    // open the tag
-    write!(f, "{} {{ ", &el.name)?;
-
-    // todo: dioxus will eventually support classnames
-    // for now, just write them with a space between each
-    let class_iter = &mut el.classes.iter();
-    if let Some(first_class) = class_iter.next() {
-        write!(f, "class: \"{}", first_class)?;
-        for next_class in class_iter {
-            write!(f, " {}", next_class)?;
-        }
-        write!(f, "\",")?;
-    }
-    writeln!(f)?;
-
-    // write the attributes
-    if let Some(id) = &el.id {
-        write_tabs(f, il + 1)?;
-        writeln!(f, "id: \"{}\",", id)?;
-    }
-
-    for (name, value) in &el.attributes {
-        write_tabs(f, il + 1)?;
-
-        use convert_case::{Case, Casing};
-        if name.chars().any(|ch| ch.is_ascii_uppercase() || ch == '-') {
-            let new_name = name.to_case(Case::Snake);
-            match value {
-                Some(val) => writeln!(f, "{}: \"{}\",", new_name, val)?,
-                None => writeln!(f, "{}: \"\",", new_name)?,
-            }
-        } else {
-            match name.as_str() {
-                "for" | "async" | "type" | "as" => write!(f, "r#")?,
-                _ => {}
-            }
-
-            match value {
-                Some(val) => writeln!(f, "{}: \"{}\",", name, val)?,
-                None => writeln!(f, "{}: \"\",", name)?,
-            }
-        }
-    }
-
-    // now the children
-    for child in &el.children {
-        render_child(f, child, il + 1, svg_buffer, skip_svg, svg_idx)?;
-    }
-
-    // close the tag
-    write_tabs(f, il)?;
-    writeln!(f, "}}")?;
-    Ok(())
-}
-
-fn write_tabs(f: &mut Formatter, num: u32) -> std::fmt::Result {
-    for _ in 0..num {
-        write!(f, "    ")?
-    }
-    Ok(())
-}
-
-#[test]
-fn generates_svgs() {
-    let st = include_str!("../../../tests/svg.html");
-
-    let out = format!("{:}", convert_html_to_component(st).unwrap());
-    dbg!(&out);
-
-    std::fs::File::create("svg_rsx.rs")
-        .unwrap()
-        .write_all(out.as_bytes())
-        .unwrap();
-}

+ 0 - 1
src/cli/translate/translate.rs

@@ -1 +0,0 @@
-