Clearing backlog

This commit is contained in:
Jacob Guenther 2021-09-16 22:40:37 -08:00
parent 27bc498a96
commit 7c38707686
6 changed files with 405 additions and 60 deletions

View File

@ -1,6 +1,5 @@
use std::fs;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
extern crate tera;
@ -13,8 +12,16 @@ use serde::{
Deserialize,
Serialize,
};
const BLOG_BASE_TITLE: &'static str = "chmod777's blog: ";
#[derive(Clone, Debug, Serialize, Deserialize)]
struct SVGConfig {
svgs: Vec<SVGMetadata>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct SVGMetadata {
template: String,
title: String,
description: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct Post {
@ -28,10 +35,11 @@ struct Post {
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct TechDemo {
struct Project {
full_url: Option<String>,
url: String,
title: String,
image: String,
summary: String,
template_name: String,
}
@ -39,7 +47,8 @@ struct TechDemo {
#[derive(Clone, Debug, Serialize, Deserialize)]
struct Config {
posts: Vec<Post>,
tech_demos: Vec<TechDemo>,
tech_demos: Vec<Project>,
projects: Vec<Project>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
@ -57,8 +66,8 @@ struct MyContext {
twitter_card: String,
posts: Vec<Post>,
tech_demos: Vec<TechDemo>,
tech_demos: Vec<Project>,
projects: Vec<Project>,
}
impl Default for MyContext {
fn default() -> Self {
@ -74,17 +83,17 @@ impl Default for MyContext {
twitter_card: "summary".to_owned(),
posts: Vec::new(),
tech_demos: Vec::new(),
projects: Vec::new(),
}
}
}
fn write_to_file(path: &str, content: &str) {
fn get_file(path: &str) -> File {
let path = Path::new(path);
let display = path.display();
let mut file = match File::create(path) {
match File::create(path) {
Ok(file) => file,
Err(error) => panic!("Couldn't create file {}: {}", &display, &error),
};
file.write_all(content.as_bytes()).unwrap();
}
}
fn read_file(path: &str) -> String {
fs::read_to_string(path).expect(&format!("Failed to read file: {}", path))
@ -95,6 +104,32 @@ fn append_str(base: &str, extend: &str) -> String {
s
}
fn main() {
{
let svg_tera = match Tera::new("svg_templates/**/*") {
Ok(tera) => tera,
Err(error_s) => panic!("Parsing error(s): {}", error_s),
};
let svg_config_json_string = read_file("svg_config.json");
let svg_config: SVGConfig =
serde_json::from_str(&svg_config_json_string).unwrap();
for metadata in svg_config.svgs.iter() {
let temp_path = append_str("templates/svg/", &metadata.template);
let path = append_str("public/assets/svg/", &metadata.template);
svg_tera
.render_to(
&metadata.template,
&Context::from_serialize(&metadata).unwrap(),
get_file(&temp_path),
)
.unwrap();
fs::copy(temp_path, path).unwrap();
}
}
let tera = match Tera::new("templates/**/*") {
Ok(tera) => tera,
Err(error_s) => panic!("Parsing error(s): {}", error_s),
@ -104,88 +139,108 @@ fn main() {
let config: Config = serde_json::from_str(&config_json_string).unwrap();
let mut context = MyContext::default();
let base_url = "http://tilde.club/~chmod777";
for mut post in config.posts.iter().cloned() {
post.full_url = Some(append_str(base_url, &post.url));
context.posts.push(post);
}
for mut demo in config.tech_demos.iter().cloned() {
demo.full_url = Some(append_str(base_url, &demo.url));
context.tech_demos.push(demo)
}
{
let index = tera
.render("index.html", &Context::from_serialize(&context).unwrap())
.unwrap();
write_to_file("public/index.html", &index);
for mut project in config.projects.iter().cloned() {
project.full_url = Some(append_str(base_url, &project.url));
context.projects.push(project);
}
tera.render_to(
"index.html",
&Context::from_serialize(&context).unwrap(),
get_file("public/index.html"),
)
.unwrap();
{
context.title = "chmod777's blog".to_owned();
context.canonical_url = "http://tilde.club/~chmod777/blog/blog.html".to_owned();
let blog_context = Context::from_serialize(&context).unwrap();
let blog = tera
.render(
"blog/blog.html",
&blog_context,
)
.unwrap();
write_to_file("public/blog/blog.html", &blog);
tera.render_to(
"blog/blog.html",
&blog_context,
get_file("public/blog/blog.html"),
)
.unwrap();
let rss_feed = tera
.render("feed.rss", &blog_context)
tera.render_to("feed.rss", &blog_context, get_file("public/feed.rss"))
.unwrap();
write_to_file("public/feed.rss", &rss_feed);
context.og_type = "article".to_owned();
for post in context.posts.iter() {
context.title = append_str(BLOG_BASE_TITLE, &post.title);
context.canonical_url = post.full_url.clone().unwrap();
context.description = post.summary.clone();
let tera_context = &Context::from_serialize(&context).unwrap();
let rendered_post =
tera.render(&post.template_name, &tera_context).unwrap();
let path = {
let mut s = "public".to_owned();
s.push_str(&post.url);
s
};
write_to_file(&path, &rendered_post);
let path = append_str("public", &post.url);
tera.render_to(
&post.template_name,
&Context::from_serialize(&context).unwrap(),
get_file(&path),
)
.unwrap();
}
}
{
context.title = "chmod777's projects".to_owned();
context.og_type = "website".to_owned();
context.canonical_url = "http://tilde.club/~chmod777/projects/projects.html".to_owned();
context.description = "".to_owned();
tera.render_to(
"projects/projects.html",
&Context::from_serialize(&context).unwrap(),
get_file("public/projects/projects.html"),
)
.unwrap();
for project in context.projects.iter() {
context.canonical_url = project.full_url.clone().unwrap();
context.description = project.summary.clone();
let path = append_str("public", &project.url);
tera.render_to(
&project.template_name,
&Context::from_serialize(&context).unwrap(),
get_file(&path),
)
.unwrap();
}
}
{
context.title = "chmod777's tech demos".to_owned();
context.og_type = "website".to_owned();
context.canonical_url = "".to_owned();
context.canonical_url = "http://tilde.club/~chmod777/tech_demos/tech_demos.html".to_owned();
context.description = "".to_owned();
let tech_demos_context = Context::from_serialize(&context).unwrap();
let tech_demos = tera
.render(
"tech_demos/tech_demos.html",
&tech_demos_context,
)
.unwrap();
write_to_file("public/tech_demos/tech_demos.html", &tech_demos);
tera.render_to(
"tech_demos/tech_demos.html",
&Context::from_serialize(&context).unwrap(),
get_file("public/tech_demos/tech_demos.html"),
)
.unwrap();
for demo in context.tech_demos.iter() {
context.title = append_str("chmod777's ", &demo.title);
context.canonical_url = demo.full_url.clone().unwrap();
context.description = demo.summary.clone();
let demo_context = &Context::from_serialize(&context).unwrap();
let rendered_demo =
tera.render(&demo.template_name, &demo_context).unwrap();
let path = {
let mut s = "public".to_owned();
s.push_str(&demo.url);
s
};
write_to_file(&path, &rendered_demo);
}
let path = append_str("public", &demo.url);
tera.render_to(
&demo.template_name,
&Context::from_serialize(&context).unwrap(),
get_file(&path),
)
.unwrap();
}
}
}

View File

@ -0,0 +1,37 @@
{% import "macros.xml" as macros %}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 64 64"
width="64"
height="64"
preserveAspectRatio="xMinYMin meet"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink= "http://www.w3.org/1999/xlink">
<title>{{ title | safe }}</title>
<desc>{{ description | safe }}</desc>
{{ macros::metadata() }}
<defs>
<mask id="chat-mask">
<rect x="12" y="0"
width="44" height="20"
fill="white" fill-opacity="1.0" />
<rect x="48" y="0"
width="20" height="36"
fill="white" fill-opacity="1.0" />
</mask>
</defs>
<rect x="20" y="4" rx="5"
width="40" height="28"
fill="none" stroke="black" stroke-width="2"
mask="url(#chat-mask)" />
<polygon transform="translate(8 52)" points="0,0 10,0, -2, 8" fill="black" />
<rect x="4" y="24" rx="5"
width="40" height="28"
fill="none" stroke="black" stroke-width="2" />
<polygon transform="translate(48 32)" points="0,0 10,0, 12, 8" fill="black" />
</svg>

97
svg_templates/gears-icon.svg Executable file
View File

@ -0,0 +1,97 @@
{% import "macros.xml" as macros %}
<svg viewBox="0 0 65 65"
width="64"
height="64"
preserveAspectRatio="xMinYMin meet"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>{{ title | safe }}</title>
<desc>{{ description | safe }}</desc>
{{ macros::metadata() }}
<defs>
<circle id="gear_hole" r="3" cx=" 12" cy="0" />
<mask id="gear_mask" transform="" >
<rect x="-64" y="-64" width="128" height="128" fill="white" />
<use xlink:href="#gear_hole" />
<use xlink:href="#gear_hole" transform="rotate(72 0,0)" />
<use xlink:href="#gear_hole" transform="rotate(144 0,0)" />
<use xlink:href="#gear_hole" transform="rotate(216 0,0)" />
<use xlink:href="#gear_hole" transform="rotate(288 0,0)" />
<circle r="4" />
</mask>
<polygon id="large_spoke" points="-1,-3 4,-2 4,2 -1,3" transform="translate(18 0)" />
<g id="large_gear_spokes">
<use xlink:href="#large_spoke" />
<use xlink:href="#large_spoke" transform="rotate(180 0 0)" />
</g>
<polygon id="small_spoke" points="-1,-3.5 6.5,-3 6.5,3 -1,3.5" transform="translate(18 0)" />
<g id="small_gear_spokes">
<use xlink:href="#small_spoke" />
<use xlink:href="#small_spoke" transform="rotate(180 0 0)" />
</g>
<g id="large_gear" mask="url(#gear_mask)">
<circle r="18" />
<use xlink:href="#large_gear_spokes" />
<use xlink:href="#large_gear_spokes" transform="rotate(72)" />
<use xlink:href="#large_gear_spokes" transform="rotate(144)" />
<use xlink:href="#large_gear_spokes" transform="rotate(216)" />
<use xlink:href="#large_gear_spokes" transform="rotate(288)" />
</g>
<g id="small_gear" mask="url(#gear_mask)">
<circle r="18" />
<use xlink:href="#small_gear_spokes" />
<use xlink:href="#small_gear_spokes" transform="rotate(72)" />
<use xlink:href="#small_gear_spokes" transform="rotate(144)" />
<use xlink:href="#small_gear_spokes" transform="rotate(216)" />
<use xlink:href="#small_gear_spokes" transform="rotate(288)" />
</g>
</defs>
<g transform="translate(24 40) rotate(-9)">
<g>
<use xlink:href="#large_gear" class="gear forward_gear" />
</g>
</g>
<g transform="translate(49 15) rotate(9) scale(0.65 0.65)">
<g>
<use xlink:href="#small_gear" class="gear reverse_gear" />
</g>
</g>
<style>
.gear {
animation-duration: 10s;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-play-state: paused;
}
.forward_gear {
animation-name: rotate_gear_forward;
}
.reverse_gear {
animation-name: rotate_gear_reverse;
}
@keyframes rotate_gear_forward {
from {transform: none;}
to {transform: rotate(-720deg);}
}
@keyframes rotate_gear_reverse {
from {transform: none;}
to {transform: rotate(720deg);}
}
svg:hover .gear {
animation-play-state: running;
}
</style>
</svg>

32
svg_templates/macros.xml Normal file
View File

@ -0,0 +1,32 @@
{% macro metadata() %}
<metadata id="license"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#">
<rdf:RDF>
<cc:Work rdf:about="http://tilde.club/~chmod777/svg/chat-bubbles-icon.svg">
<dc:format>image/svg+xml</dc:format>
<dc:creator>chmod777</dc:creator>
<dc:title>{{ title | safe }}</dc:title>
<dc:description>{{ description | safe }}</dc:description>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<cc:license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/4.0/" />
</cc:Work>
<cc:License rdf:about="http://creativecommons.org/licenses/by-nc-sa/4.0/">
<cc:lecalcode rdf:resource="http://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt" />
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike" />
<cc:prohibits rdf:resource="http://creativecommons.org/ns#CommercialUse "/>
</cc:License>
</rdf:RDF>
</metadata>
{% endmacro metadata %}

View File

@ -0,0 +1,46 @@
{% import "macros.xml" as macros %}
<svg viewBox="0 0 64 64"
width="64"
height="64"
preserveAspectRatio="xMinYMin meet"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink= "http://www.w3.org/1999/xlink">
<title>{{ title | safe }}</title>
<desc>{{ description | safe }}</desc>
{{ macros::metadata() }}
<defs>
<g id="item">
<circle r="2" cx="14" cy="20" />
<line x1="20" y1="20" x2="40" y2="20"
stroke="black" stroke-width="1" />
</g>
<mask id="mask">
<rect width="64" height="64" fill="white" />
<rect width="52" height="57" fill="black" />
</mask>
</defs>
<rect x="7.5" y="2.5"
width="45" height="55"
fill="none"
rx="4"
stroke="black" stroke-width="2" />
<line x1="7.5" y1="14" x2="52.5" y2="14"
stroke="black" stroke-width="2" />
<use xlink:href="#item" />
<use xlink:href="#item" transform="translate(0, 6)" />
<use xlink:href="#item" transform="translate(0, 12)" />
<use xlink:href="#item" transform="translate(0, 18)" />
<use xlink:href="#item" transform="translate(0, 24)" />
<use xlink:href="#item" transform="translate(0, 30)" />
<rect x="11.5" y="6.5"
width="45" height="55"
fill="none"
rx="4"
stroke="black" stroke-width="2"
mask="url(#mask)" />
</svg>

78
svg_templates/pong.svg Normal file
View File

@ -0,0 +1,78 @@
{% import "macros.xml" as macros %}
<svg viewBox="0 0 532 276"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>{{ title | safe }}</title>
<desc>{{ description | safe }}</desc>
{{ macros::metadata() }}
<defs>
<linearGradient id="pong-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop id="pong-gradiant-begin" offset="0%" />
<stop id="pong-gradiant-end" offset="100%" />
</linearGradient>
</defs>
<rect id="pong-boarder" width="100%" height="100%" />
<svg x="10" y="10" width="512" height="256" >
<rect id="pong-board" width="100%" height="100%" />
<path id="pong-ball-path" d="M256 128" />
<path id="pong-collision-path" d="M256 128" />
<line id="pong-center-line" x1="256" y1="0" x2="256" y2="256" />
<rect id="pong-player-paddle" width="2" height="28" transform="translate(0, 114)"/>
<rect id="pong-ai-paddle" width="2" height="28" transform="translate(510, 114)"/>
<text id="pong-player-score" class="pong-score" x="85.33" y="64">0</text>
<text id="pong-ai-score" class="pong-score" x="426.66" y="64">0</text>
<circle id="pong-ball" r="3">
<animateMotion id="pong-ball-animation" dur="1.0s" repeatCount="indefinite">
<mpath xlink:href="#pong-ball-path"/>
</animateMotion>
</circle>
</svg>
<style>
#pong-gradiant-begin {
stop-color:blue;
stop-opacity:1;
}
#pong-gradiant-end {
stop-color:red;
stop-opacity:1;
}
#pong-boarder {
fill:url(#pong-gradient);
}
#pong-board {
fill:black;
}
#pong-ball-path {
stroke:blue;
}
#pong-collision-path {
stroke:red;
stroke-dasharray:1;
}
#pong-center-line {
stroke:white;
stroke-dasharray:5;
stroke-width:2;
}
#pong-ai-paddle,#pong-player-paddle,.pong-score {
fill:white;
}
.pong-score {
font-family:'Courier New',Courier,monospace;font-size:2em;
}
#pong-ball {
fill:white;
}
</style>
</svg>