From c6e47572ace31fa52a565f828e184a493573c7ff Mon Sep 17 00:00:00 2001 From: Evie Viau Date: Tue, 11 Feb 2025 02:17:04 -0800 Subject: [PATCH] Init work on IL for content Add parsing from a String and converting from Markdown --- .idea/iresine.iml | 9 +- Cargo.lock | 135 ++++++++++++++++++++++ Cargo.toml | 3 +- README.md | 2 +- iresine-ap/Cargo.toml | 6 + iresine-ap/src/main.rs | 3 + iresine-cli/Cargo.toml | 6 + iresine-cli/src/main.rs | 3 + iresine-common/Cargo.toml | 6 + iresine-common/src/lib.rs | 14 +++ iresine-il/Cargo.toml | 14 +++ iresine-il/src/convert/markdown.rs | 86 ++++++++++++++ iresine-il/src/convert/mod.rs | 1 + iresine-il/src/lib.rs | 175 +++++++++++++++++++++++++++++ iresine-il/src/nodes.rs | 43 +++++++ iresine/Cargo.toml | 6 + iresine/src/main.rs | 3 + 17 files changed, 512 insertions(+), 3 deletions(-) create mode 100644 Cargo.lock create mode 100644 iresine-ap/Cargo.toml create mode 100644 iresine-ap/src/main.rs create mode 100644 iresine-cli/Cargo.toml create mode 100644 iresine-cli/src/main.rs create mode 100644 iresine-common/Cargo.toml create mode 100644 iresine-common/src/lib.rs create mode 100644 iresine-il/Cargo.toml create mode 100644 iresine-il/src/convert/markdown.rs create mode 100644 iresine-il/src/convert/mod.rs create mode 100644 iresine-il/src/lib.rs create mode 100644 iresine-il/src/nodes.rs create mode 100644 iresine/Cargo.toml create mode 100644 iresine/src/main.rs diff --git a/.idea/iresine.iml b/.idea/iresine.iml index 6102194..99b1154 100644 --- a/.idea/iresine.iml +++ b/.idea/iresine.iml @@ -1,7 +1,14 @@ - + + + + + + + + diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..ad8722a --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,135 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "iresine" +version = "0.1.0" + +[[package]] +name = "iresine-ap" +version = "0.1.0" + +[[package]] +name = "iresine-cli" +version = "0.1.0" + +[[package]] +name = "iresine-common" +version = "0.1.0" + +[[package]] +name = "iresine-il" +version = "0.1.0" +dependencies = [ + "anyhow", + "markdown", + "serde", + "serde_json", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "markdown" +version = "1.0.0-alpha.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790c11786cb51d02938e3eb38276575e1658b1dd8555875f5788a40670a33934" +dependencies = [ + "unicode-id", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-id" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10103c57044730945224467c09f71a4db0071c123a0648cc3e818913bde6b561" + +[[package]] +name = "unicode-ident" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" diff --git a/Cargo.toml b/Cargo.toml index fe6c977..65c1dab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,3 @@ [workspace] -resolver = "2" \ No newline at end of file +resolver = "2" +members = [ "iresine", "iresine-ap", "iresine-cli","iresine-common" , "iresine-il"] diff --git a/README.md b/README.md index a34acac..9f0f267 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# Iresine \ No newline at end of file +# Iresine \ No newline at end of file diff --git a/iresine-ap/Cargo.toml b/iresine-ap/Cargo.toml new file mode 100644 index 0000000..1fafde7 --- /dev/null +++ b/iresine-ap/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "iresine-ap" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/iresine-ap/src/main.rs b/iresine-ap/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/iresine-ap/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/iresine-cli/Cargo.toml b/iresine-cli/Cargo.toml new file mode 100644 index 0000000..15997d0 --- /dev/null +++ b/iresine-cli/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "iresine-cli" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/iresine-cli/src/main.rs b/iresine-cli/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/iresine-cli/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/iresine-common/Cargo.toml b/iresine-common/Cargo.toml new file mode 100644 index 0000000..2e0363f --- /dev/null +++ b/iresine-common/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "iresine-common" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/iresine-common/src/lib.rs b/iresine-common/src/lib.rs new file mode 100644 index 0000000..b93cf3f --- /dev/null +++ b/iresine-common/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/iresine-il/Cargo.toml b/iresine-il/Cargo.toml new file mode 100644 index 0000000..80f7f7a --- /dev/null +++ b/iresine-il/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "iresine-il" +version = "0.1.0" +edition = "2021" + +[dependencies] +serde = { version = "1.0.217", features = ["derive"] } +serde_json = "1.0.138" + +anyhow = "1.0.95" + +markdown = "1.0.0-alpha.22" + +[dev-dependencies] \ No newline at end of file diff --git a/iresine-il/src/convert/markdown.rs b/iresine-il/src/convert/markdown.rs new file mode 100644 index 0000000..4cf1aa8 --- /dev/null +++ b/iresine-il/src/convert/markdown.rs @@ -0,0 +1,86 @@ +use anyhow::anyhow; +use markdown::mdast::Node; +use crate::nodes::{Document, Header, Image, Link, Nodes, Text}; +use crate::SUPPORTED_FORMAT_VERSION; + +fn do_parse(input: &Node) -> Nodes { + let mut il_node: Nodes = match input { + Node::Break(_) => { + Nodes::Divider + } + Node::Image(node) => { + let node = node.clone(); + + Nodes::Image(Image { + url: node.url, + alt: Some(node.alt), + blur_hash: None, + width: None, + height: None, + value: vec![], + }) + } + Node::Link(node) => { + Nodes::Link(Link { + url: node.clone().url, + value: vec![], + }) + } + Node::Text(node) => { + Nodes::Literal(node.clone().value) + } + Node::Heading(node) => { + Nodes::Header(Header { + level: node.depth.to_string(), + value: vec![], + }) + } + Node::Paragraph(_) => { + Nodes::Text(Text { + value: vec![], + }) + } + _ => { + Nodes::Literal(format!("{:#?}", input)) + } + }; + + if let Some(children) = input.children() { + for i in children { + match &mut il_node { + Nodes::Text(node) => { + node.value.push(do_parse(i)) + } + Nodes::Link(node) => { + node.value.push(do_parse(i)) + } + Nodes::Image(node) => { + node.value.push(do_parse(i)) + } + Nodes::Header(node) => { + node.value.push(do_parse(i)) + } + _ => { + eprintln!("Cannot have children?") + } + } + } + } + + il_node +} + +pub fn from_markdown(value: &str) -> Result { + let root = markdown::to_mdast(value, &markdown::ParseOptions::default()).expect("MDX?"); + + let mut document = Document { + version: SUPPORTED_FORMAT_VERSION, + value: vec![], + }; + + for i in root.children().ok_or(anyhow!("Empty?"))? { + document.value.push(do_parse(i)); + } + + Ok(document) +} \ No newline at end of file diff --git a/iresine-il/src/convert/mod.rs b/iresine-il/src/convert/mod.rs new file mode 100644 index 0000000..d7c69bb --- /dev/null +++ b/iresine-il/src/convert/mod.rs @@ -0,0 +1 @@ +pub mod markdown; \ No newline at end of file diff --git a/iresine-il/src/lib.rs b/iresine-il/src/lib.rs new file mode 100644 index 0000000..c19402e --- /dev/null +++ b/iresine-il/src/lib.rs @@ -0,0 +1,175 @@ +use crate::nodes::{Document, Header, Image, Nodes, Text, Link}; + +pub mod nodes; +pub mod convert; + +static SUPPORTED_FORMAT_VERSION: u64 = 0; + +pub fn parse(value: &str) -> Result { + let res: Result = serde_json::from_str(value); + + match res { + Ok(res) => { + if res.version > SUPPORTED_FORMAT_VERSION { + Err(anyhow::anyhow!("Unsupported document version: {}", res.version)) + } else { + Ok(res) + } + } + Err(res) => { + Err(anyhow::Error::from(res)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_markdown_conversion() { + let test_doc = Document { + version: 0, + value: vec![ + Nodes::Header(Header { + level: "1".to_string(), + value: vec![Nodes::Literal("Hi!".to_string())], + }), + Nodes::Text(Text { + value: vec![ + Nodes::Literal("This is a test of ".to_string()), + Nodes::Link(Link { + url: "https://en.wikipedia.org/wiki/Markdown".to_string(), + value: vec![ + Nodes::Literal("Markdown".to_string()) + ], + }), + Nodes::Literal(" to ".to_string()), + Nodes::Link(Link { + url: "https://forge.gaycatgirl.sex/evie/iresine".to_string(), + value: vec![ + Nodes::Literal("Iresine".to_string()) + ], + }), + Nodes::Literal(" IL.".to_string()) + ], + }) + ], + }; + + let test_md = r#"# Hi! + +This is a test of [Markdown](https://en.wikipedia.org/wiki/Markdown) to [Iresine](https://forge.gaycatgirl.sex/evie/iresine) IL. + "#; + + let result = convert::markdown::from_markdown(test_md); + + assert!(result.is_ok()); + assert_eq!(test_doc, result.unwrap()); + } + + #[test] + fn test_string_parse() { + let test_doc = Document { + version: 0, + value: vec![ + Nodes::Header(Header { + level: "1".to_string(), + value: vec![Nodes::Literal("Hi!".to_string())], + }), + Nodes::Image(Image { + url: "https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png".to_string(), + alt: Some("Example Image".to_string()), + blur_hash: Some("L6R{-$oI^bx@O_WB?DtSm$ozafV@".to_string()), + width: None, + height: None, + value: vec![ + Nodes::Text(Text { + value: vec![Nodes::Literal("Hello, world!".to_string())], + }) + ], + }), + Nodes::Divider, + Nodes::Text(Text { + value: vec![ + Nodes::Literal("This is a test of the ".to_string()), + Nodes::Link(Link { + url: "https://forge.gaycatgirl.sex/evie/iresine".to_string(), + value: vec![ + Nodes::Literal("Iresine".to_string()) + ], + }), + Nodes::Literal(" Markup Language.".to_string()) + ], + }) + ], + }; + + let test_str = r#" + { + "version": 0, + "value": [ + { + "Header": { + "level": "1", + "value": [ + { + "Literal": "Hi!" + } + ] + } + }, + { + "Image": { + "url": "https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png", + "alt": "Example Image", + "blur_hash": "L6R{-$oI^bx@O_WB?DtSm$ozafV@", + "width": null, + "height": null, + "value": [ + { + "Text": { + "value": [ + { + "Literal": "Hello, world!" + } + ] + } + } + ] + } + }, + "Divider", + { + "Text": { + "value": [ + { + "Literal": "This is a test of the " + }, + { + "Link": { + "url": "https://forge.gaycatgirl.sex/evie/iresine", + "value": [ + { + "Literal": "Iresine" + } + ] + } + }, + { + "Literal": " Markup Language." + } + ] + } + } + ] + } + "#; + + + let result: Result = parse(test_str); + + assert!(result.is_ok()); + assert_eq!(test_doc, result.unwrap()); + } +} diff --git a/iresine-il/src/nodes.rs b/iresine-il/src/nodes.rs new file mode 100644 index 0000000..e0828be --- /dev/null +++ b/iresine-il/src/nodes.rs @@ -0,0 +1,43 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +pub enum Nodes { + Literal(String), + Text(Text), + Link(Link), + Image(Image), + Header(Header), + Divider, +} +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone)] +pub struct Text { + pub value: Vec +} + +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone)] +pub struct Header { + pub level: String, + pub value: Vec +} + +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone)] +pub struct Image { + pub url: String, + pub alt: Option, + pub blur_hash: Option, + pub width: Option, + pub height: Option, + pub value: Vec, +} + +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone)] +pub struct Link { + pub url: String, + pub value: Vec, +} + +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone)] +pub struct Document { + pub version: u64, + pub value: Vec +} \ No newline at end of file diff --git a/iresine/Cargo.toml b/iresine/Cargo.toml new file mode 100644 index 0000000..00abb08 --- /dev/null +++ b/iresine/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "iresine" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/iresine/src/main.rs b/iresine/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/iresine/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +}