Add all basic code
This commit is contained in:
commit
b098b6f708
|
@ -0,0 +1 @@
|
|||
/target
|
|
@ -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"
|
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "cooking"
|
||||
description = "simple cooking/recipe site"
|
||||
authors = ["Erin Nova <contact@the-system.eu.org>"]
|
||||
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"] }
|
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><html><head><link href="favicon.ico" rel="icon"><link href="style.css" rel="stylesheet"><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="The cutest cooking site on the net :3"><title>Catgirl Cooking</title></head><body><h1>🥘 Catgirl Cooking</h1><hr><p>The cutest cooking site on the net :3</p><p>Absolutely no ads, tracking, or nazis, ever.</p><i><p>Tags:</p><p><a href='breakfast'>breakfast</a>,<a href='apples'>apples</a>,<a href='cheese'>cheese</a>,<a href='vegan'>vegan</a>,<a href='vegetarian'>vegetarian</a>,</p></i><h2>Recipes:</h2><ul><li><a href="Macaroni & Cheese">Macaroni & Cheese</a></li><li><a href="Soup">Soup</a></li><li><a href="Apple Pie">Apple Pie</a></li><li><a href="More Soup">More Soup</a></li><li><a href="idk">idk</a></li><li><a href="cum">cum</a></li></ul><footer><hr><a href="/">home</a><a href="/atom.xml">atom</a><p>Software licensed under the CNPLv7+</p><p>Recipes under Public Domain</p></footer></body></html>
|
|
@ -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"),
|
||||
}
|
||||
}
|
|
@ -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#"<hr>"#) // 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#"<hr>"#)
|
||||
.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#"<i>"#); // 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#"<p>"#); // Begin paragraph element
|
||||
for x in tags { // Go through the list of tags
|
||||
tags_html.push_str(format!("<a href='{}'>{}</a>,", x, x).as_str()); // Append the tags as a link
|
||||
}
|
||||
tags_html.push_str(r#"</p>"#); // End the paragraph
|
||||
home_page.add_raw(tags_html); // Add the string as html to the page
|
||||
home_page.add_raw(r#"</i>"#); // 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());
|
||||
}
|
|
@ -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<Utc>, // Date the recipe was first posted
|
||||
edited_date: DateTime<Utc>, // Date the recipe was last edited
|
||||
tags: Vec<Tag>, // List of tags
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue