From b098b6f708caa99937125e57b250f9035a4d554a Mon Sep 17 00:00:00 2001 From: Erin Nova Date: Sun, 23 Jan 2022 13:40:13 -0500 Subject: [PATCH] Add all basic code --- .gitignore | 1 + Cargo.lock | 181 ++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 21 ++++++ index.html | 1 + src/io.rs | 19 +++++ src/main.rs | 59 +++++++++++++++ src/structures.rs | 70 ++++++++++++++++++ src/tests.rs | 20 +++++ style.css | 59 +++++++++++++++ 9 files changed, 431 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 index.html create mode 100644 src/io.rs create mode 100644 src/main.rs create mode 100644 src/structures.rs create mode 100644 src/tests.rs create mode 100644 style.css 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..68f9d67 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,181 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "build_html" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e121f1569e70b069135a0768a6b62a16c9c0eeaba92815a4baa6fdb93a97ec79" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "serde", + "time", + "winapi", +] + +[[package]] +name = "cooking" +version = "0.1.0" +dependencies = [ + "build_html", + "chrono", + "uuid", +] + +[[package]] +name = "getrandom" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.113" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eef78b64d87775463c549fbd80e19249ef436ea3bf1de2a1eb7e717ec7fab1e9" + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "serde" +version = "1.0.135" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cf9235533494ea2ddcdb794665461814781c53f19d87b76e571a1c35acbad2b" + +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "uuid" +version = "1.0.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb3ab47baa004111b323696c6eaa2752e7356f7f77cf6b6dc7a2087368ce1ca4" +dependencies = [ + "getrandom", + "rand", + "serde", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..761e453 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "cooking" +description = "simple cooking/recipe site" +authors = ["Erin Nova "] +license = "CNPLv7+" +homepage = "https://catgirl.cooking" +repository = "https://git.lavender.software/erin/tinymark" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[profile.release] +lto = true # Enable linktime optimization +codegen-units = 1 +panic = "abort" + +[dependencies] +build_html = "2.0.0" +uuid = { version = "1.0.0-alpha.1", features = ["v4", "serde", "fast-rng"] } +chrono = { version = "0.4", features = ["serde"] } diff --git a/index.html b/index.html new file mode 100644 index 0000000..359f747 --- /dev/null +++ b/index.html @@ -0,0 +1 @@ +Catgirl Cooking

🥘 Catgirl Cooking


The cutest cooking site on the net :3

Absolutely no ads, tracking, or nazis, ever.

Tags:

breakfast,apples,cheese,vegan,vegetarian,

Recipes:


homeatom

Software licensed under the CNPLv7+

Recipes under Public Domain

\ No newline at end of file diff --git a/src/io.rs b/src/io.rs new file mode 100644 index 0000000..3d7aa3f --- /dev/null +++ b/src/io.rs @@ -0,0 +1,19 @@ +use std::fs::File; +use std::io::prelude::*; +use std::path::Path; + +pub fn write_html(html: String) { + let path = Path::new("index.html"); + + // Open file in write-only mode + let mut file = match File::create(&path) { + Err(why) => panic!("couldn't create file: {}", why), + Ok(file) => file, + }; + + // Write the HTML to fil + match file.write_all(html.as_bytes()) { + Err(why) => panic!("couldn't write to file: {}", why), + Ok(_) => println!("successfully wrote to file"), + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e03c927 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,59 @@ +use build_html::{self, Html, HtmlContainer, ContainerType, Container}; + +mod structures; +mod io; +mod tests; + +fn main() { + // Specify info to go onto the base page + let base_page = build_html::HtmlPage::new() + .with_head_link("favicon.ico", "icon") // Favicon + .with_stylesheet("style.css") // Link stylesheet + .with_meta(vec![("charset", "UTF-8")]) + .with_meta(vec![("name", "viewport"), ("content", "width=device-width, initial-scale=1")]) // Display stuff + .with_meta(vec![("name", "description"), ("content", structures::DESCRIPTION)]) // Add the description + .with_title(structures::TITLE); + + // Create the footer + let footer = Container::new(ContainerType::Footer) + .with_raw(r#"
"#) // Line seperator + .with_link("/", "home") // Link to the root page + .with_link("/atom.xml", "atom") // Link the the Atom feed + // License info + .with_paragraph("Software licensed under the CNPLv7+") + .with_paragraph("Recipes under Public Domain"); + + // Create the home page + let mut home_page = base_page + .with_header(1, structures::HEADER) + .with_raw(r#"
"#) + .with_paragraph(structures::DESCRIPTION) + .with_paragraph(structures::DETAILS); + + // Create (test) lists of tags & recipes + let tags: Vec<&str> = vec!["breakfast", "apples", "cheese", "vegan", "vegetarian"]; + let recipes: Vec<&str> = vec!["Macaroni & Cheese", "Soup", "Apple Pie", "More Soup", "idk", "cum"]; + + home_page.add_raw(r#""#); // Tags in italics + home_page.add_paragraph("Tags:"); + let mut tags_html = String::new(); // Create custom html string for tags + tags_html.push_str(r#"

"#); // Begin paragraph element + for x in tags { // Go through the list of tags + tags_html.push_str(format!("{},", x, x).as_str()); // Append the tags as a link + } + tags_html.push_str(r#"

"#); // End the paragraph + home_page.add_raw(tags_html); // Add the string as html to the page + home_page.add_raw(r#"
"#); // End the italics + + // Append recipes + home_page.add_header(2, "Recipes:"); + let mut recipes_container = Container::new(ContainerType::UnorderedList); + for i in recipes { + recipes_container.add_link(i, i); + } + + home_page.add_container(recipes_container); + home_page.add_container(footer); + + io::write_html(home_page.to_html_string()); +} diff --git a/src/structures.rs b/src/structures.rs new file mode 100644 index 0000000..68c7908 --- /dev/null +++ b/src/structures.rs @@ -0,0 +1,70 @@ +use uuid::Uuid; +use chrono::prelude::*; + +// Content strings to add to html +pub const TITLE: &str = r#"Catgirl Cooking"#; +pub const HEADER: &str = r#"🥘 Catgirl Cooking"#; +pub const DESCRIPTION: &str = r#"The cutest cooking site on the net :3"#; +pub const DETAILS: &str = r#"Absolutely no ads, tracking, or nazis, ever."#; + +pub enum TimeUnits { + Hours, + Min, + Sec, +} + +pub enum MeasurementUnits { + Grams, + Kilograms, + Pounds, + Litres, + Millilitres, + Gallons, + Ounces, + Pinch, + Drop, + Tablespoon, + Teaspoon, +} + +#[derive(Debug, PartialEq, Clone)] +pub struct Tag(pub char, pub String); + +impl Tag { + pub fn new(s: String) -> Tag { + Tag('#', s) + } + + pub fn to_string(&self) -> String { + let mut tag = String::new(); + tag.push_str(&self.0.to_string()); + tag.push_str(&self.1); + return tag; + } + + pub fn from_string(s: String) -> Tag { + let hash = s.chars().nth(0).unwrap(); + let mut text = s; + text.remove(0); + text.make_ascii_lowercase(); + return Tag(hash, text); + } + + pub fn display(&self) { + println!("{}{}", self.0, self.1); + } +} + +pub struct Recipe { + id: Uuid, // Unique recipe ID + name: String, // Full recipe name + prep_time: (i32, TimeUnits), // Preparation time: (value, units) + cooking_time: (i32, TimeUnits), // Cooking time: (value, units) + servings: u8, // How many servinge the recipe makes + ingredients: Vec<(i32, MeasurementUnits, String)>, // Vector of ingredients: (value, units, name) + directions: Vec<(u16, String)>, // List of instructions: (step #, details) + attribution: String, // Author name + posted_date: DateTime, // Date the recipe was first posted + edited_date: DateTime, // Date the recipe was last edited + tags: Vec, // List of tags +} diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 0000000..00b93c4 --- /dev/null +++ b/src/tests.rs @@ -0,0 +1,20 @@ +#[cfg(test)] +mod tests { + // Note this useful idiom: importing names from outer (for mod tests) scope. + use crate::structures::*; + + #[test] + fn test_tag_new() { + assert_eq!(Tag::new("test".to_string()), Tag('#', "test".to_string())); + } + + #[test] + fn test_tag_from_string() { + assert_eq!(Tag::from_string("#test".to_string()), Tag('#', "test".to_string())); + } + + #[test] + fn test_tag_to_string() { + assert_eq!(Tag('#', "test".to_string()).to_string(), "#test".to_string()); + } +} diff --git a/style.css b/style.css new file mode 100644 index 0000000..c20a1b0 --- /dev/null +++ b/style.css @@ -0,0 +1,59 @@ +/* Light Theme */ +@media (prefers-color-scheme: light) { +:root { + --background: #fffee6; + --foreground: #0f0f0e; + --accent: #26A269; + --link: #E7044C; + --link-visited: #A43737; +} +} + +/* Dark Theme */ +@media (prefers-color-scheme: dark) { +:root { + --background: #241F31; + --foreground: #F6F5F4; + --accent: #50C878; + --link: #FD8BAF; + --link-visited: #FB0452; +} +} + +body { + background: var(--background); + color: var(--foreground); + max-width: 800px; + margin: auto; + padding: 0 16px; + margin-bottom: 500px; + font-family: 'Atkinson Hyperlegible', sans-serif; +} + +a { + color: var(--link); + padding: 5px; +} + +a:visited { + color: var(--link-visited); +} + +h1 { + text-align: center; +} + +footer { + text-align: center ; +} + +img { + max-width: 600px ; + width: 100% ; + margin: auto ; + display: block ; +} + +ul { + column-count: 3; +}