diff options
author | Ashelyn Rose <git@ashen.earth> | 2024-10-18 18:08:40 -0600 |
---|---|---|
committer | Ashelyn Rose <git@ashen.earth> | 2024-10-18 18:08:40 -0600 |
commit | a35d336dc9a61fda931f4a9158205d590af87bd5 (patch) | |
tree | cde9b67c0a5d938d7caec596664bc9d0610b5d90 |
Basic sync rendering
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Cargo.lock | 18 | ||||
-rw-r--r-- | Cargo.toml | 7 | ||||
-rw-r--r-- | modules/proc/Cargo.toml | 3 | ||||
-rw-r--r-- | modules/proc/src/lib.rs | 0 | ||||
-rw-r--r-- | modules/site_test/Cargo.toml | 6 | ||||
-rw-r--r-- | modules/site_test/src/main.rs | 59 | ||||
-rw-r--r-- | src/lib.rs | 7 | ||||
-rw-r--r-- | src/render.rs | 49 |
9 files changed, 150 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..4809d49 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,18 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "morgana" +version = "0.1.0" + +[[package]] +name = "morgana_proc" +version = "0.0.0" + +[[package]] +name = "morgana_site_test" +version = "0.0.0" +dependencies = [ + "morgana", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..fa0dafb --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[workspace] +members = ["modules/proc", "modules/site_test"] + +[package] +name = "morgana" +version = "0.1.0" +edition = "2021" diff --git a/modules/proc/Cargo.toml b/modules/proc/Cargo.toml new file mode 100644 index 0000000..16bcbb8 --- /dev/null +++ b/modules/proc/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "morgana_proc" +edition = "2021" diff --git a/modules/proc/src/lib.rs b/modules/proc/src/lib.rs new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/modules/proc/src/lib.rs diff --git a/modules/site_test/Cargo.toml b/modules/site_test/Cargo.toml new file mode 100644 index 0000000..118c9bd --- /dev/null +++ b/modules/site_test/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "morgana_site_test" +edition = "2021" + +[dependencies] +morgana = { path = "../../" } diff --git a/modules/site_test/src/main.rs b/modules/site_test/src/main.rs new file mode 100644 index 0000000..3062c11 --- /dev/null +++ b/modules/site_test/src/main.rs @@ -0,0 +1,59 @@ +use std::collections::HashMap; + +use morgana::{Component, RenderNode}; + +pub fn main() { + let parent = ParentLayout { + children: vec![ + RenderNode::Component( + Box::new(Child { + children: vec![ + RenderNode::TextNode { content: "Hello world!".to_string() } + ] + }) + ) + ] + }; + + let text = morgana::render_tree(RenderNode::Component(Box::new(parent))); + println!("{text}") +} + +struct ParentLayout { + children: Vec<RenderNode> +} + +impl Component for ParentLayout { + fn render(self: Box<Self>) -> Vec<RenderNode> { + vec![ + RenderNode::Element { name: "html".to_string(), attributes: HashMap::from([("lang".to_string(), "en-US".to_string())]), children: vec![ + RenderNode::Element { name: "head".to_string(), attributes: HashMap::new(), children: vec![ + RenderNode::Element { name: "title".to_string(), attributes: HashMap::new(), children: vec![ + RenderNode::TextNode { content: "test thing".to_string() } + ] } + ] }, + RenderNode::Element { + name: "body".to_string(), + attributes: HashMap::new(), + children: self.children, + }, + ] } + ] + } +} + +struct Child { + children: Vec<RenderNode> +} + +impl Component for Child { + fn render(self: Box<Self>) -> Vec<RenderNode> { + vec![ + RenderNode::Element { + name: "p".to_string(), + attributes: HashMap::new(), + children: self.children + } + ] + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..717d715 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,7 @@ +mod render; + +pub use render::{Component, RenderNode}; + +pub fn render_tree(parent_node: RenderNode) -> String { + parent_node.render_to_string() +} diff --git a/src/render.rs b/src/render.rs new file mode 100644 index 0000000..33469e0 --- /dev/null +++ b/src/render.rs @@ -0,0 +1,49 @@ +use std::collections::HashMap; + +pub trait Component { + fn render(self: Box<Self>) -> Vec<RenderNode>; +} + +pub enum RenderNode { + Component(Box<dyn Component>), + Element { + name: String, + attributes: HashMap<String, String>, + children: Vec<RenderNode> + }, + TextNode { + content: String, + }, + Portal, + Null, +} + +impl RenderNode { + pub(crate) fn render_to_string(self) -> String { + match self { + RenderNode::Component(component) => { + let elements = component.render(); + elements.into_iter() + .map(|child| child.render_to_string()) + .collect::<Vec<_>>().join("") + + }, + + RenderNode::Element { name, attributes, children } => { + let text_attributes = attributes.into_iter() + .map(|(key, value)| format!(" {key}=\"{value}\"")) + .collect::<Vec<_>>().join(""); + + let rendered_children = children.into_iter() + .map(|child| child.render_to_string()) + .collect::<Vec<_>>().join(""); + + format!("<{name}{text_attributes}>{rendered_children}</{name}>") + }, + + RenderNode::TextNode { content } => content, + RenderNode::Portal => todo!(), + RenderNode::Null => "".to_string(), + } + } +} |