summary refs log tree commit diff
diff options
context:
space:
mode:
authorAshelyn Rose <git@ashen.earth>2024-10-18 18:08:40 -0600
committerAshelyn Rose <git@ashen.earth>2024-10-18 18:08:40 -0600
commita35d336dc9a61fda931f4a9158205d590af87bd5 (patch)
treecde9b67c0a5d938d7caec596664bc9d0610b5d90
Basic sync rendering
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock18
-rw-r--r--Cargo.toml7
-rw-r--r--modules/proc/Cargo.toml3
-rw-r--r--modules/proc/src/lib.rs0
-rw-r--r--modules/site_test/Cargo.toml6
-rw-r--r--modules/site_test/src/main.rs59
-rw-r--r--src/lib.rs7
-rw-r--r--src/render.rs49
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(),
+        }
+    }
+}