Redo.
This commit is contained in:
parent
7918707dd9
commit
72fd3351b3
18
Cargo.toml
18
Cargo.toml
|
@ -7,25 +7,13 @@ version = "1.0.0"
|
|||
edition = "2018"
|
||||
repository = "https://git.holllo.cc/Bauke/bauke.xyz"
|
||||
license = "AGPL-3.0-or-later"
|
||||
build = "source/build.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "bauke-xyz"
|
||||
path = "source/main.rs"
|
||||
|
||||
[dependencies]
|
||||
gloo-console = "0.2.0"
|
||||
gloo-timers = "0.2.1"
|
||||
log = "0.4.14"
|
||||
rand = "0.8.4"
|
||||
userstyles = { git = "https://git.holllo.cc/Bauke/userstyles" }
|
||||
wasm-logger = "0.2.0"
|
||||
yew = "0.18.0"
|
||||
yew-router = "0.15.0"
|
||||
|
||||
[dependencies.getrandom]
|
||||
version = "0.2.3"
|
||||
features = ["js"]
|
||||
|
||||
[build-dependencies]
|
||||
askama = "0.10.5"
|
||||
color-eyre = "0.5.11"
|
||||
rsass = "0.22.2"
|
||||
userstyles = { git = "https://git.holllo.cc/Bauke/userstyles" }
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
[build]
|
||||
dist = "public"
|
||||
|
||||
[serve]
|
||||
no_autoreload = false
|
||||
port = 5500
|
||||
|
||||
[clean]
|
||||
dist = "public"
|
|
@ -0,0 +1,2 @@
|
|||
[general]
|
||||
dirs = ["source/templates"]
|
21
index.html
21
index.html
|
@ -1,21 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>bauke.xyz</title>
|
||||
<link data-trunk rel="sass" href="source/scss/modern-normalize.scss" />
|
||||
<link data-trunk rel="sass" href="source/scss/index.scss" />
|
||||
<link data-trunk rel="copy-file" href="source/netlify/_redirects" />
|
||||
<link data-trunk rel="copy-dir" href="target/userstyles" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>
|
||||
This website requires JavaScript and WebAssembly to work.
|
||||
</noscript>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -3,7 +3,7 @@
|
|||
"version": "0.0.0",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
"deploy": "trunk clean && cargo build -q && trunk build --release && yarn deploy:netlify",
|
||||
"deploy": "cargo run --release -q && yarn deploy:netlify",
|
||||
"deploy:netlify": "netlify deploy --prod --dir 'public/' -s bauke.xyz",
|
||||
"test": "stylelint 'source/**/*.scss'"
|
||||
},
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
/// Build script for the website.
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=source/**");
|
||||
let build_dir = std::path::PathBuf::from("target");
|
||||
|
||||
for target in userstyles::ALL_USERSTYLES {
|
||||
let style = userstyles::Userstyle::load(target).unwrap();
|
||||
let style_name = style.metadata.name.to_lowercase().replace(" ", "-");
|
||||
|
||||
let style_dir = build_dir.join("userstyles");
|
||||
std::fs::create_dir_all(&style_dir).unwrap();
|
||||
|
||||
let style_file = style_dir.join(format!("{}.user.css", style_name));
|
||||
let formatted = style.format();
|
||||
std::fs::write(style_file, formatted).unwrap();
|
||||
|
||||
if let Some(image) = style.image {
|
||||
let image_file = style_dir.join(format!("{}.png", style_name));
|
||||
std::fs::write(image_file, image).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
/// Contains the main page `<footer>` component.
|
||||
mod page_footer;
|
||||
/// Contains the main page `<header>` component.
|
||||
mod page_header;
|
||||
/// Contains the main page `<main>` component.
|
||||
mod page_main;
|
||||
|
||||
pub(crate) use page_footer::PageFooter;
|
||||
pub(crate) use page_header::PageHeader;
|
||||
pub(crate) use page_main::PageMain;
|
|
@ -1,29 +0,0 @@
|
|||
use yew::prelude::*;
|
||||
|
||||
/// The main page `<footer>` element.
|
||||
pub(crate) struct PageFooter;
|
||||
|
||||
impl Component for PageFooter {
|
||||
type Message = ();
|
||||
type Properties = ();
|
||||
|
||||
fn create(_props: Self::Properties, _link: ComponentLink<Self>) -> Self {
|
||||
log::trace!("Creating PageFooter");
|
||||
|
||||
Self
|
||||
}
|
||||
|
||||
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
|
||||
false
|
||||
}
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<footer class="page-footer"></footer>
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
use yew::prelude::*;
|
||||
|
||||
/// The main page `<header>` element.
|
||||
pub(crate) struct PageHeader;
|
||||
|
||||
impl Component for PageHeader {
|
||||
type Message = ();
|
||||
type Properties = ();
|
||||
|
||||
fn create(_props: Self::Properties, _link: ComponentLink<Self>) -> Self {
|
||||
log::trace!("Creating PageHeader");
|
||||
|
||||
Self
|
||||
}
|
||||
|
||||
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
|
||||
false
|
||||
}
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<header class="page-header">
|
||||
<h1>{"bauke.xyz"}</h1>
|
||||
</header>
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
use yew::prelude::*;
|
||||
|
||||
/// The main page `<main>` element.
|
||||
pub(crate) struct PageMain;
|
||||
|
||||
impl Component for PageMain {
|
||||
type Message = ();
|
||||
type Properties = ();
|
||||
|
||||
fn create(_props: Self::Properties, _link: ComponentLink<Self>) -> Self {
|
||||
log::trace!("Creating PageMain");
|
||||
|
||||
Self
|
||||
}
|
||||
|
||||
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
|
||||
false
|
||||
}
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<main class="page-main">
|
||||
<div class="contact-links">
|
||||
<a target="_blank" href="mailto:me@bauke.xyz">
|
||||
{"me@bauke.xyz"}
|
||||
</a>
|
||||
|
||||
<a target="_blank" href="https://matrix.to/#/@baukexyz:matrix.org">
|
||||
{"@baukexyz:matrix.org"}
|
||||
</a>
|
||||
|
||||
<a target="_blank" href="https://mastodon.social/@bauke">
|
||||
{"@bauke@mastodon.social"}
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
}
|
||||
}
|
||||
}
|
148
source/main.rs
148
source/main.rs
|
@ -1,72 +1,106 @@
|
|||
#![forbid(unsafe_code)]
|
||||
#![warn(missing_docs, clippy::missing_docs_in_private_items)]
|
||||
use std::{fs, path::PathBuf, process::Command};
|
||||
|
||||
//! # [bauke.xyz](https://bauke.xyz)
|
||||
use askama::Template;
|
||||
|
||||
use yew::prelude::*;
|
||||
use yew_router::router::Router;
|
||||
mod templates;
|
||||
|
||||
/// Components collection.
|
||||
pub(crate) mod components;
|
||||
/// Routes collection.
|
||||
pub(crate) mod routes;
|
||||
fn main() -> color_eyre::Result<()> {
|
||||
color_eyre::install()?;
|
||||
|
||||
/// All routes.
|
||||
#[derive(Clone, yew_router::Switch)]
|
||||
pub(crate) enum Route {
|
||||
#[to = "/userstyles"]
|
||||
Userstyles,
|
||||
#[to = "/{}"]
|
||||
NotFound(String),
|
||||
#[to = "/"]
|
||||
Home,
|
||||
}
|
||||
let build_dir = PathBuf::from("target");
|
||||
|
||||
/// The main component.
|
||||
pub(crate) struct Model;
|
||||
for target in userstyles::ALL_USERSTYLES {
|
||||
let style = userstyles::Userstyle::load(target)?;
|
||||
let style_name = style.metadata.name.to_lowercase().replace(" ", "-");
|
||||
|
||||
impl Component for Model {
|
||||
type Message = ();
|
||||
type Properties = ();
|
||||
let style_dir = build_dir.join("userstyles");
|
||||
fs::create_dir_all(&style_dir)?;
|
||||
|
||||
fn create(_props: Self::Properties, _link: ComponentLink<Self>) -> Self {
|
||||
Self
|
||||
let style_file = style_dir.join(format!("{}.user.css", style_name));
|
||||
let formatted = style.format();
|
||||
fs::write(style_file, formatted)?;
|
||||
|
||||
if let Some(image) = style.image {
|
||||
let image_file = style_dir.join(format!("{}.png", style_name));
|
||||
fs::write(image_file, image)?;
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
|
||||
unimplemented!()
|
||||
let public_dir = PathBuf::from("public");
|
||||
|
||||
let source_dir = PathBuf::from("source");
|
||||
|
||||
let styles = userstyles::ALL_USERSTYLES
|
||||
.iter()
|
||||
.map(|target| userstyles::Userstyle::load(target))
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let templates_to_render: Vec<(Box<dyn Template>, PathBuf)> = vec![
|
||||
(
|
||||
Box::new(templates::Index {
|
||||
page_title: "bauke.xyz".to_string(),
|
||||
}),
|
||||
public_dir.join("index.html"),
|
||||
),
|
||||
(
|
||||
Box::new(templates::Userstyles {
|
||||
page_title: "bauke.xyz".to_string(),
|
||||
styles,
|
||||
}),
|
||||
public_dir.join("userstyles/index.html"),
|
||||
),
|
||||
];
|
||||
|
||||
for (template, path) in templates_to_render {
|
||||
fs::create_dir_all(&path.parent().unwrap())?;
|
||||
let rendered = template.render()?;
|
||||
fs::write(path, rendered)?;
|
||||
}
|
||||
|
||||
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
|
||||
false
|
||||
}
|
||||
let css_dir = public_dir.join("css");
|
||||
fs::create_dir_all(&css_dir)?;
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<Router<Route, ()>
|
||||
render = Router::render(|route: Route| {
|
||||
match route {
|
||||
Route::NotFound(_) => html! {
|
||||
<main class="error-404">
|
||||
<p>{"🤷"}</p>
|
||||
</main>
|
||||
let scss_dir = source_dir.join("scss");
|
||||
|
||||
let scss_to_render = vec![
|
||||
(scss_dir.join("index.scss"), css_dir.join("index.css")),
|
||||
(
|
||||
scss_dir.join("modern-normalize.scss"),
|
||||
css_dir.join("modern-normalize.css"),
|
||||
),
|
||||
];
|
||||
|
||||
for (source, destination) in scss_to_render {
|
||||
let rendered = rsass::compile_scss_path(
|
||||
&source,
|
||||
rsass::output::Format {
|
||||
style: rsass::output::Style::Expanded,
|
||||
precision: 5,
|
||||
},
|
||||
Route::Home => html! {
|
||||
<routes::HomeRoute />
|
||||
},
|
||||
Route::Userstyles => html! {
|
||||
<routes::UserstylesRoute />
|
||||
}
|
||||
}
|
||||
})
|
||||
/>
|
||||
}
|
||||
}
|
||||
}
|
||||
)?;
|
||||
|
||||
/// Our main function.
|
||||
pub(crate) fn main() {
|
||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||
log::debug!("Initializing Yew");
|
||||
yew::start_app::<Model>();
|
||||
fs::write(destination, rendered)?;
|
||||
}
|
||||
|
||||
let files_to_copy = vec![(
|
||||
source_dir.join("netlify/_redirects"),
|
||||
public_dir.join("_redirects"),
|
||||
)];
|
||||
|
||||
for (source, destination) in files_to_copy {
|
||||
fs::copy(source, destination)?;
|
||||
}
|
||||
|
||||
let dirs_to_copy = vec![(build_dir.join("userstyles"), public_dir)];
|
||||
|
||||
for (source, destination) in dirs_to_copy {
|
||||
Command::new("cp")
|
||||
.arg("-r")
|
||||
.arg(source)
|
||||
.arg(destination)
|
||||
.output()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
use yew::prelude::*;
|
||||
|
||||
use crate::components::{PageFooter, PageHeader, PageMain};
|
||||
|
||||
/// The route for `/`.
|
||||
pub(crate) struct HomeRoute;
|
||||
|
||||
impl Component for HomeRoute {
|
||||
type Message = ();
|
||||
type Properties = ();
|
||||
|
||||
fn create(_props: Self::Properties, _link: ComponentLink<Self>) -> Self {
|
||||
log::trace!("Creating HomeRoute");
|
||||
|
||||
Self
|
||||
}
|
||||
|
||||
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
|
||||
false
|
||||
}
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<>
|
||||
<PageHeader />
|
||||
<PageMain />
|
||||
<PageFooter />
|
||||
</>
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
/// The route for `/`.
|
||||
mod home;
|
||||
/// The route for `/userstyles`.
|
||||
mod userstyles;
|
||||
|
||||
pub(crate) use self::userstyles::UserstylesRoute;
|
||||
pub(crate) use home::HomeRoute;
|
|
@ -1,57 +0,0 @@
|
|||
use yew::prelude::*;
|
||||
|
||||
use crate::components::PageHeader;
|
||||
|
||||
/// The route for `/userstyles`.
|
||||
pub(crate) struct UserstylesRoute;
|
||||
|
||||
impl Component for UserstylesRoute {
|
||||
type Message = ();
|
||||
type Properties = ();
|
||||
|
||||
fn create(_props: Self::Properties, _link: ComponentLink<Self>) -> Self {
|
||||
log::trace!("Creating UserstylesRoute");
|
||||
|
||||
Self
|
||||
}
|
||||
|
||||
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
|
||||
false
|
||||
}
|
||||
|
||||
fn view(&self) -> Html {
|
||||
let styles = userstyles::ALL_USERSTYLES
|
||||
.iter()
|
||||
.map(|target| userstyles::Userstyle::load(target))
|
||||
.flatten()
|
||||
.map(|style| {
|
||||
let style_name = style.metadata.name.to_lowercase().replace(" ", "-");
|
||||
|
||||
html! {
|
||||
<div class="style">
|
||||
<div class="header">
|
||||
<img src=format!("/userstyles/{}.png", style_name) />
|
||||
<h2>{style.metadata.name}</h2>
|
||||
<a target="_blank" href={style.metadata.update_url}>{"Install"}</a>
|
||||
</div>
|
||||
|
||||
<p>{style.metadata.description}</p>
|
||||
</div>
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
html! {
|
||||
<>
|
||||
<PageHeader />
|
||||
<main class="page-main userstyles">
|
||||
{styles}
|
||||
</main>
|
||||
</>
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
&:hover {
|
||||
background-color: #fff;
|
||||
border-color: #fff;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ page_title }}</title>
|
||||
<link rel="stylesheet" href="/css/modern-normalize.css">
|
||||
{% block head %}{% endblock %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{% block body %}{% endblock %}
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,27 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/css/index.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<header class="page-header">
|
||||
<h1>bauke.xyz</h1>
|
||||
</header>
|
||||
|
||||
<main class="page-main">
|
||||
<div class="contact-links">
|
||||
<a target="_blank" href="mailto:me@bauke.xyz">
|
||||
me@bauke.xyz
|
||||
</a>
|
||||
|
||||
<a target="_blank" href="https://matrix.to/#/@baukexyz:matrix.org">
|
||||
@baukexyz:matrix.org
|
||||
</a>
|
||||
|
||||
<a target="_blank" href="https://mastodon.social/@bauke">
|
||||
@bauke@mastodon.social
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
|
@ -0,0 +1,14 @@
|
|||
use askama::Template;
|
||||
|
||||
#[derive(Debug, Template)]
|
||||
#[template(path = "index.html")]
|
||||
pub struct Index {
|
||||
pub page_title: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Template)]
|
||||
#[template(path = "userstyles.html")]
|
||||
pub struct Userstyles {
|
||||
pub page_title: String,
|
||||
pub styles: Vec<userstyles::Userstyle>,
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/css/index.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<header class="page-header">
|
||||
<h1>bauke.xyz</h1>
|
||||
</header>
|
||||
|
||||
<main class="page-main userstyles">
|
||||
{% for style in styles %}
|
||||
<div class="style">
|
||||
<div class="header">
|
||||
<img src="{{ format!("/userstyles/{}.png", style.metadata.name.to_lowercase().replace(" ", "-"))|safe }}" />
|
||||
<h2>{{ style.metadata.name }}</h2>
|
||||
<a target="_blank" href="{{ style.metadata.update_url|safe }}">Install</a>
|
||||
</div>
|
||||
|
||||
<p>{{ style.metadata.description }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</main>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue