diff --git a/Cargo.toml b/Cargo.toml
index 7d8d83606..42cc4858c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,10 +14,8 @@ log = "0.4.13"
fern = { version = "0.6.0", features = ["colored"] }
wasm-bindgen-cli-support = "0.2.78"
anyhow = "1.0.38"
-
serde = { version = "1.0.133", features = ["derive"] }
serde_json = "1"
-
fs_extra = "1.2.0"
cargo_toml = "0.10.0"
futures = "0.3.12"
@@ -30,6 +28,7 @@ convert_case = "0.5.0"
structopt = "0.3.25"
cargo_metadata = "0.14.1"
tokio = { version = "1.15.0", features = ["full"] }
+atty = "0.2.14"
[[bin]]
path = "src/main.rs"
diff --git a/README.md b/README.md
index 079f663a3..34be58eda 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
📦✨ dioxus-Studio
+
📦✨ dioxus-cli
Tooling to supercharge dioxus projects
@@ -10,6 +10,14 @@
# About
-
dioxus-studio (inspired by wasm-pack and webpack) is a tool to help get dioxus projects off the ground. It handles all the build, development, bundling, and publishing to make web development simple.
+
+## Installation
+
+```
+$ cargo install dioxus-cli
+```
+
+Now, `dioxus` is in your path.
+
diff --git a/extension/src/extension.ts b/extension/src/extension.ts
index c8000694c..c9ab06662 100644
--- a/extension/src/extension.ts
+++ b/extension/src/extension.ts
@@ -13,7 +13,7 @@ export function activate(context: vscode.ExtensionContext) {
const selection = editor.selection;
const word = document.getText(selection);
- const child_proc = spawn("dioxus", ["translate", "-t", word]);
+ const child_proc = spawn("dioxus", ["translate", "--source", word]);
let result = '';
child_proc.stdout?.on('data', data => result += data);
@@ -37,7 +37,7 @@ export function activate(context: vscode.ExtensionContext) {
const selection = editor.selection;
const word = document.getText(selection);
- const child_proc = spawn("dioxus", ["translate", "-c", "-t", word]);
+ const child_proc = spawn("dioxus", ["translate", "--component", "--source", word]);
let result = '';
child_proc.stdout?.on('data', data => result += data);
diff --git a/out.rsx b/out.rsx
new file mode 100644
index 000000000..b30b76f9e
--- /dev/null
+++ b/out.rsx
@@ -0,0 +1,23 @@
+
+use dioxus::prelude::*;
+fn component(cx: Scope) -> Element {
+ cx.render(rsx!(
+ div {
+ h1 {
+ "hello"
+ }
+ }
+ ))
+}
+
+use dioxus::prelude::*;
+fn component(cx: Scope) -> Element {
+ cx.render(rsx!(
+ div {
+ h1 {
+ "hello"
+ }
+ }
+ ))
+}
+
diff --git a/packages/rsx-translate/Cargo.toml b/packages/rsx-translate/Cargo.toml
new file mode 100644
index 000000000..2af83c634
--- /dev/null
+++ b/packages/rsx-translate/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "rsx-translate"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/packages/rsx-translate/src/lib.rs b/packages/rsx-translate/src/lib.rs
new file mode 100644
index 000000000..1b4a90c93
--- /dev/null
+++ b/packages/rsx-translate/src/lib.rs
@@ -0,0 +1,8 @@
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn it_works() {
+ let result = 2 + 2;
+ assert_eq!(result, 4);
+ }
+}
diff --git a/src/cli/build/mod.rs b/src/cli/build/mod.rs
index adb233c33..33a81a540 100644
--- a/src/cli/build/mod.rs
+++ b/src/cli/build/mod.rs
@@ -10,3 +10,5 @@ pub struct Build {
#[structopt(flatten)]
pub build: ConfigOptsBuild,
}
+
+pub async fn perform_build() {}
diff --git a/src/cli/mod.rs b/src/cli/mod.rs
index 55e722d80..fe118cbb7 100644
--- a/src/cli/mod.rs
+++ b/src/cli/mod.rs
@@ -10,38 +10,37 @@ pub mod serve;
pub mod translate;
pub mod watch;
-/// Build, bundle & ship your Rust WASM application to the web.
+/// Build, bundle, & ship your Dioxus app.
+///
+///
#[derive(StructOpt)]
-#[structopt(name = "trunk")]
-pub struct Trunk {
+#[structopt(name = "dioxus")]
+pub struct Cli {
#[structopt(subcommand)]
- pub action: TrunkSubcommands,
-
- /// Path to the Trunk config file [default: Trunk.toml]
- #[structopt(long, parse(from_os_str), env = "TRUNK_CONFIG")]
- pub config: Option
,
+ pub action: Commands,
/// Enable verbose logging.
#[structopt(short)]
pub v: bool,
+ //
+ // // note: dioxus is still roughly compatible with trunk
+ // /// Path to the Trunk config file [default: Trunk.toml]
+ // #[structopt(long, parse(from_os_str), env = "TRUNK_CONFIG")]
+ // pub config: Option,
}
#[derive(StructOpt)]
-pub enum TrunkSubcommands {
- /// Build the Rust WASM app and all of its assets.
- Build(build::Build),
-
+pub enum Commands {
+ // /// Build the Rust WASM app and all of its assets.
+ // Build(build::Build),
/// Translate some source file into Dioxus code.
Translate(translate::Translate),
+ // /// Build, watch & serve the Rust WASM app and all of its assets.
+ // Serve(serve::Serve),
- /// Build, watch & serve the Rust WASM app and all of its assets.
- ///
- ///
- Serve(serve::Serve),
+ // /// Clean output artifacts.
+ // Clean(clean::Clean),
- /// Clean output artifacts.
- Clean(clean::Clean),
-
- /// Trunk config controls.
- Config(config::Config),
+ // /// Trunk config controls.
+ // Config(config::Config),
}
diff --git a/src/cli/translate/mod.rs b/src/cli/translate/mod.rs
index 1251f9ae6..60a3361d7 100644
--- a/src/cli/translate/mod.rs
+++ b/src/cli/translate/mod.rs
@@ -1,5 +1,7 @@
-use crate::cfg::ConfigOptsBuild;
-use anyhow::Result;
+use html_parser::Dom;
+use html_parser::Node;
+use std::fmt::Write;
+use std::io::Read;
use std::path::PathBuf;
use structopt::StructOpt;
@@ -10,4 +12,143 @@ pub mod translate;
/// Build the Rust WASM app and all of its assets.
#[derive(Clone, Debug, StructOpt)]
#[structopt(name = "translate")]
-pub struct Translate {}
+pub struct Translate {
+ /// Activate debug mode
+ // short and long flags (-d, --debug) will be deduced from the field's name
+ #[structopt(short, long)]
+ pub component: bool,
+
+ /// Input file
+ #[structopt(short, long)]
+ pub source: Option,
+
+ /// Input file
+ #[structopt(short, long, parse(from_os_str))]
+ pub input: Option,
+
+ /// Output file, stdout if not present
+ #[structopt(parse(from_os_str))]
+ pub output: Option,
+}
+
+impl Translate {
+ pub fn translate(self) -> anyhow::Result<()> {
+ let Translate {
+ component: as_component,
+ input,
+ output,
+ source,
+ } = self;
+
+ let contents = input
+ .map(|f| {
+ std::fs::read_to_string(&f)
+ .unwrap_or_else(|e| panic!("Could not read input file: {}", e))
+ })
+ .unwrap_or(source.unwrap_or_else(|| {
+ if atty::is(atty::Stream::Stdin) {
+ panic!("No input file, source, or stdin to translate from");
+ }
+
+ let mut buffer = String::new();
+ std::io::stdin().read_to_string(&mut buffer).unwrap();
+
+ buffer.trim().to_string()
+ }));
+
+ // 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, "}}")?;
+ }
+
+ if let Some(output) = output {
+ std::fs::write(&output, out_buf)?;
+ } else {
+ print!("{}", out_buf);
+ }
+
+ Ok(())
+ }
+}
+
+fn render_child(f: &mut impl Write, child: &Node, il: u32) -> std::fmt::Result {
+ write_tabs(f, il)?;
+ match child {
+ Node::Text(t) => writeln!(f, "\"{}\"", t)?,
+ Node::Comment(e) => writeln!(f, "/* {} */", e)?,
+ Node::Element(el) => {
+ // 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, "\",")?;
+ }
+ write!(f, "\n")?;
+
+ // 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)?;
+ }
+
+ // close the tag
+ write_tabs(f, il)?;
+ writeln!(f, "}}")?;
+ }
+ };
+ Ok(())
+}
+
+fn write_tabs(f: &mut impl Write, num: u32) -> std::fmt::Result {
+ for _ in 0..num {
+ write!(f, " ")?
+ }
+ Ok(())
+}
diff --git a/src/cli/translate/translate.rs b/src/cli/translate/translate.rs
index c7dad39d4..8b1378917 100644
--- a/src/cli/translate/translate.rs
+++ b/src/cli/translate/translate.rs
@@ -1,128 +1 @@
-use std::fmt::{Display, Formatter};
-use anyhow::Result;
-
-use html_parser::{Dom, Node};
-
-pub fn translate_from_html_file(target: &str) -> Result {
- use std::fs::File;
- use std::io::Read;
- let mut file = File::open(target).unwrap();
-
- let mut contents = String::new();
- file.read_to_string(&mut contents)
- .expect("Failed to read your file.");
- translate_from_html_to_rsx(&contents, true)
-}
-
-pub fn translate_from_html_to_rsx(html: &str, as_call: bool) -> Result {
- let contents = Dom::parse(html)?;
- let renderer = RsxRenderer {
- as_call,
- dom: contents,
- };
- Ok(renderer)
-}
-
-pub struct RsxRenderer {
- dom: Dom,
- as_call: bool,
-}
-
-impl Display for RsxRenderer {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- if self.as_call {
- writeln!(f, r##"use dioxus::prelude::*;"##)?;
- writeln!(
- f,
- r##"
-fn component(cx: Scope) -> Element {{
- cx.render(rsx!(
-"##
- )?;
- }
- for child in &self.dom.children {
- render_child(f, child, 1)?;
- }
- if self.as_call {
- write!(
- f,
- r##"
- )
-)
- "##
- )?;
- }
- Ok(())
- }
-}
-
-fn render_child(f: &mut Formatter<'_>, child: &Node, il: u32) -> std::fmt::Result {
- write_tabs(f, il);
- match child {
- Node::Text(t) => writeln!(f, "\"{}\"", t)?,
- Node::Comment(e) => writeln!(f, "/* {} */", e)?,
- Node::Element(el) => {
- // 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, "\",")?;
- }
- write!(f, "\n")?;
-
- // 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)?;
- }
-
- // 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(())
-}
diff --git a/src/main.rs b/src/main.rs
index 043767af6..7ecb50ac7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,49 +1,32 @@
-use dioxus_studio::*;
+use dioxus_cli::*;
use structopt::StructOpt;
#[tokio::main]
async fn main() -> Result<()> {
- let args = Trunk::from_args();
+ let args = Cli::from_args();
set_up_logging();
match args.action {
- TrunkSubcommands::Build(_) => {
- //
+ Commands::Translate(opts) => {
+ opts.translate();
}
- TrunkSubcommands::Translate(opts) => {
- // let TranslateOptions {
- // file,
- // text,
- // component,
- // } = cfg;
+ // Commands::Build(_) => {
+ // //
+ // }
- // match component {
- // true => {
- // let f = helpers::to_component::convert_html_to_component(&text.unwrap())?;
- // println!("{}", f);
- // }
- // false => {
- // let renderer = match (file, text) {
- // (None, Some(text)) => translate::translate_from_html_to_rsx(&text, false)?,
- // (Some(file), None) => translate::translate_from_html_file(&file)?,
- // _ => panic!("Must select either file or text - not both or none!"),
- // };
- // println!("{}", renderer);
- // }
- // }
- }
+ // Commands::Clean(_) => {
+ // //
+ // }
- TrunkSubcommands::Clean(_) => {
- //
- }
- TrunkSubcommands::Config(_) => {
- //
- }
- TrunkSubcommands::Serve(_) => {
- //
- }
+ // Commands::Config(_) => {
+ // //
+ // }
+
+ // Commands::Serve(_) => {
+ // //
+ // }
}
Ok(())
diff --git a/test.html b/test.html
new file mode 100644
index 000000000..33ca3dd1f
--- /dev/null
+++ b/test.html
@@ -0,0 +1,5 @@
+
+
+ hello
+
+