Compare commits
9 Commits
rewrite/ru
...
510897d94b
| Author | SHA1 | Date | |
|---|---|---|---|
| 510897d94b | |||
| 078634b664 | |||
| 6a5176caab | |||
|
|
282c67b1fc | ||
| 74224bd648 | |||
| 8f217ec82b | |||
| 0e1055b1a6 | |||
| 94c56d7405 | |||
|
|
0a203fdb65 |
1
.gitignore
vendored
@@ -3,3 +3,4 @@ dist/
|
||||
pkg/
|
||||
target/
|
||||
Cargo.lock
|
||||
bulma.min.css
|
||||
|
||||
14
Cargo.toml
@@ -1,21 +1,25 @@
|
||||
[package]
|
||||
name = "web_luciel"
|
||||
name = "web_iouring"
|
||||
version = "0.0.0-develop"
|
||||
authors = ["luciel"]
|
||||
authors = ["iouring"]
|
||||
license = "Apache-2.0"
|
||||
edition = "2024"
|
||||
rust-version = "1.85"
|
||||
rust-version = "1.91"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
js-sys = "0.3"
|
||||
yew = { git = "https://github.com/yewstack/yew.git", rev = "550b2cc", features = ["csr"] }
|
||||
yew-router = { git = "https://github.com/yewstack/yew.git", rev = "550b2cc" }
|
||||
yew = { git = "https://github.com/yewstack/yew.git", rev = "21f373b", features = [
|
||||
"csr",
|
||||
] }
|
||||
yew-router = { git = "https://github.com/yewstack/yew.git", rev = "21f373b" }
|
||||
wasm-bindgen = { version = "0.2" }
|
||||
|
||||
log = { version = "0.4" }
|
||||
wasm-logger = { version = "0.2" }
|
||||
|
||||
serde = { version = "1.0" }
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3"
|
||||
features = [
|
||||
|
||||
50
index.html
@@ -1,31 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<title>celesteflare.cc ~ lunary</title>
|
||||
<html lang="en" class="theme-dark">
|
||||
|
||||
<link data-trunk rel="copy-file" href="public/misc/favicon.ico"/>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
|
||||
<title>i0ur.ing ~ welcome</title>
|
||||
|
||||
<link data-trunk rel="copy-file" href="public/misc/favicon.ico" />
|
||||
<link data-trunk rel="copy-file" href="public/misc/profile.avif" />
|
||||
<link data-trunk rel="copy-file" href="public/misc/oneko.gif" />
|
||||
<link data-trunk rel="copy-file" href="public/misc/monocraft.ttf" />
|
||||
|
||||
<link data-trunk rel="copy-file" href="public/blog/testimage.jpg" />
|
||||
|
||||
<link data-trunk rel="copy-file" href="public/shaders/post.bloom.svg" />
|
||||
|
||||
<link data-trunk rel="copy-file" href="public/buttons/luciel.png"/>
|
||||
<link data-trunk rel="copy-file" href="public/buttons/servfail.png"/>
|
||||
<link data-trunk rel="copy-file" href="public/buttons/wasm.png"/>
|
||||
<link data-trunk rel="copy-file" href="public/buttons/rust.png"/>
|
||||
<link data-trunk rel="copy-file" href="public/buttons/fedora.png"/>
|
||||
<link data-trunk rel="copy-file" href="public/buttons/iouring.png" />
|
||||
<link data-trunk rel="copy-file" href="public/buttons/wasm.png" />
|
||||
<link data-trunk rel="copy-file" href="public/buttons/dataforest.png" />
|
||||
<link data-trunk rel="copy-file" href="public/buttons/servfail.png" />
|
||||
<link data-trunk rel="copy-file" href="public/buttons/rust.png" />
|
||||
<link data-trunk rel="copy-file" href="public/buttons/csharp.png" />
|
||||
<link data-trunk rel="copy-file" href="public/buttons/kotlin.png" />
|
||||
<link data-trunk rel="copy-file" href="public/buttons/java.png" />
|
||||
<link data-trunk rel="copy-file" href="public/buttons/fedora.png" />
|
||||
<link data-trunk rel="copy-file" href="public/buttons/artix.png" />
|
||||
<link data-trunk rel="copy-file" href="public/buttons/nixos.png" />
|
||||
<link data-trunk rel="copy-file" href="public/buttons/chimera.png" />
|
||||
<link data-trunk rel="copy-file" href="public/buttons/void.png" />
|
||||
<link data-trunk rel="copy-file" href="public/buttons/aqueer.png" />
|
||||
|
||||
<link data-trunk rel="copy-file" href="public/socials/fedi.svg"/>
|
||||
<link data-trunk rel="copy-file" href="public/socials/git.svg"/>
|
||||
<link data-trunk rel="copy-file" href="public/socials/lastfm.svg"/>
|
||||
|
||||
<link data-trunk rel="sass" href="main.scss"/>
|
||||
<link data-trunk rel="rust"/>
|
||||
<base data-trunk-public-url/>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma/css/bulma.min.css"/>
|
||||
<link data-trunk rel="sass" href="main.scss" />
|
||||
<link data-trunk rel="css" href="bulma.min.css" />
|
||||
<link data-trunk rel="rust" />
|
||||
<base data-trunk-public-url />
|
||||
</head>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
26
justfile
@@ -1,25 +1,15 @@
|
||||
#!/usr/bin/env just --justfile
|
||||
|
||||
install-wasm-pack:
|
||||
cargo install wasm-pack
|
||||
setup:
|
||||
rustup target add wasm32-unknown-unknown
|
||||
|
||||
install-tauri:
|
||||
cargo install tauri-cli
|
||||
install:
|
||||
cargo install --locked wasm-pack trunk --force
|
||||
|
||||
trunk-serve:
|
||||
debug:
|
||||
rm bulma.min.css && curl --proto '=https' --tlsv1.3 -LO https://cdn.jsdelivr.net/npm/bulma/css/bulma.min.css
|
||||
trunk serve
|
||||
|
||||
build:
|
||||
trunk build
|
||||
|
||||
tauri-dev:
|
||||
cargo tauri dev
|
||||
|
||||
tauri-build:
|
||||
cargo tauri build
|
||||
|
||||
create-yew-app:
|
||||
npx create-yew-app web_luciel
|
||||
|
||||
serve-app:
|
||||
cd web_luciel && trunk serve
|
||||
rm bulma.min.css && curl --proto '=https' --tlsv1.3 -LO https://cdn.jsdelivr.net/npm/bulma/css/bulma.min.css
|
||||
trunk build --release
|
||||
|
||||
71
main.scss
@@ -1,3 +1,5 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
@font-face {
|
||||
font-family: monocraft;
|
||||
src: url("monocraft.ttf");
|
||||
@@ -5,6 +7,22 @@
|
||||
|
||||
html * {
|
||||
font-family: monocraft, monospace !important;
|
||||
scrollbar-color: hsla(232, 97%, 85%, 0.5) hsla(240, 21.05%, 14.9%, 0.7) !important;
|
||||
scrollbar-width: thin !important;
|
||||
scroll-behavior: smooth !important;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
-ms-overflow-style: none !important;
|
||||
scrollbar-width: none !important;
|
||||
}
|
||||
|
||||
.textarea::-webkit-scrollbar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.box {
|
||||
@@ -13,20 +31,33 @@ html * {
|
||||
--bulma-shadow-h: 232 !important;
|
||||
--bulma-shadow-s: 97% !important;
|
||||
--bulma-shadow-l: 85% !important;
|
||||
--bulma-shadow: 0 0.5em 1em -0.125em hsla(
|
||||
var(--bulma-shadow-h),
|
||||
var(--bulma-shadow-s),
|
||||
var(--bulma-shadow-l),
|
||||
0.3
|
||||
), 0 0px 0 1px hsla(
|
||||
var(--bulma-shadow-h),
|
||||
var(--bulma-shadow-s),
|
||||
var(--bulma-shadow-l),
|
||||
0.02
|
||||
) !important;
|
||||
--bulma-shadow: 0 0.5em 1em -0.125em hsla(var(--bulma-shadow-h),
|
||||
var(--bulma-shadow-s),
|
||||
var(--bulma-shadow-l),
|
||||
0.3), 0 0px 0 1px hsla(var(--bulma-shadow-h),
|
||||
var(--bulma-shadow-s),
|
||||
var(--bulma-shadow-l),
|
||||
0.02) !important;
|
||||
}
|
||||
|
||||
.input, .select select, .textarea {
|
||||
.card {
|
||||
backdrop-filter: blur(4px) !important;
|
||||
--bulma-card-background-color: #1E1E2E80 !important;
|
||||
--bulma-shadow-h: 232 !important;
|
||||
--bulma-shadow-s: 97% !important;
|
||||
--bulma-shadow-l: 85% !important;
|
||||
--bulma-shadow: 0 0.5em 1em -0.125em hsla(var(--bulma-shadow-h),
|
||||
var(--bulma-shadow-s),
|
||||
var(--bulma-shadow-l),
|
||||
0.3), 0 0px 0 1px hsla(var(--bulma-shadow-h),
|
||||
var(--bulma-shadow-s),
|
||||
var(--bulma-shadow-l),
|
||||
0.02) !important;
|
||||
}
|
||||
|
||||
.input,
|
||||
.select select,
|
||||
.textarea {
|
||||
backdrop-filter: blur(4px);
|
||||
--bulma-input-h: 232 !important;
|
||||
--bulma-input-s: 97% !important;
|
||||
@@ -34,12 +65,10 @@ html * {
|
||||
--bulma-input-background-h: var(--bulma-input-h) !important;
|
||||
--bulma-input-background-s: var(--bulma-input-s) !important;
|
||||
--bulma-input-background-l: var(--bulma-input-l) !important;
|
||||
background-color: hsla(
|
||||
var(--bulma-input-h),
|
||||
var(--bulma-input-s),
|
||||
var(--bulma-input-background-l),
|
||||
0.213125
|
||||
) !important;
|
||||
background-color: hsla(var(--bulma-input-h),
|
||||
var(--bulma-input-s),
|
||||
var(--bulma-input-background-l),
|
||||
0.213125) !important;
|
||||
border-color: hsl(var(--bulma-input-h), var(--bulma-input-s), var(--bulma-input-l)) !important;
|
||||
}
|
||||
|
||||
@@ -57,6 +86,6 @@ a.navbar-item:hover {
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
filter: url("post.bloom.svg#process")
|
||||
}
|
||||
text-decoration: underline !important;
|
||||
filter: url("post.bloom.svg#process") !important;
|
||||
}
|
||||
BIN
public/blog/testimage.jpg
Normal file
|
After Width: | Height: | Size: 4.8 MiB |
BIN
public/buttons/aqueer.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
public/buttons/artix.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
public/buttons/chimera.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
public/buttons/csharp.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/buttons/dataforest.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.8 KiB |
BIN
public/buttons/iouring.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
public/buttons/java.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/buttons/kotlin.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
BIN
public/buttons/nixos.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
public/buttons/void.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 139 KiB |
@@ -1,5 +1,5 @@
|
||||
#version 300 es
|
||||
precision lowp float;
|
||||
precision highp float;
|
||||
|
||||
const float CAM_FAR = 20.0;
|
||||
const vec3 BACKGROUND = vec3(0.0, 0.0, 0.0);
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="196.52mm" height="196.52mm" viewBox="0 0 196.52 196.52" version="1.1" id="svg8" inkscape:version="0.92.2 2405546, 2018-03-11" sodipodi:docname="Logo_penta_connectat-imbrincat_BiN.svg" inkscape:export-filename="/home/nestor/Pictures/Fediversal/Logo_penta_connectat-imbrincat_mono-512x.png" inkscape:export-xdpi="66.175453" inkscape:export-ydpi="66.175453">
|
||||
<defs id="defs2"/>
|
||||
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="0.35646619" inkscape:cx="-324.56885" inkscape:cy="378.80956" inkscape:document-units="mm" inkscape:current-layer="layer2" showgrid="false" inkscape:snap-smooth-nodes="true" inkscape:snap-midpoints="true" inkscape:snap-global="false" inkscape:window-width="1366" inkscape:window-height="736" inkscape:window-x="0" inkscape:window-y="32" inkscape:window-maximized="1" fit-margin-top="5" fit-margin-left="5" fit-margin-right="5" fit-margin-bottom="5"/>
|
||||
<metadata id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g inkscape:label="Hexagons" inkscape:groupmode="layer" id="layer1" style="display:none" transform="translate(6.6789703,-32.495842)">
|
||||
<circle style="fill:#00a3ff;fill-opacity:0.99596773;fill-rule:nonzero;stroke:#d79611;stroke-width:11;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path830" cx="91.581032" cy="130.75584" r="87.760002"/>
|
||||
<path sodipodi:type="star" style="display:inline;fill:#0000d4;fill-opacity:1;fill-rule:nonzero;stroke:#4b4b40;stroke-width:9.88948536;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path1669" sodipodi:sides="5" sodipodi:cx="103.97202" sodipodi:cy="134.41467" sodipodi:r1="98.801643" sodipodi:r2="79.932205" sodipodi:arg1="1.0471976" sodipodi:arg2="1.6755161" inkscape:flatsided="true" inkscape:rounded="0" inkscape:randomized="0" d="M 153.37284,219.97941 37.860816,207.8386 13.712232,94.22842 114.29961,36.154276 l 86.315,77.718384 z" inkscape:transform-center-x="-2.409305" inkscape:transform-center-y="-4.7910078" transform="matrix(0.75493711,0,0,0.75474706,13.251553,29.556024)"/>
|
||||
</g>
|
||||
<g inkscape:groupmode="layer" id="layer4" inkscape:label="Linies_originals" style="display:none">
|
||||
<path transform="translate(6.6789702,-32.495842)" sodipodi:nodetypes="cc" inkscape:connector-curvature="0" id="path1690" d="M 165.18127,119.35405 38.636939,183.48684" style="display:inline;fill:none;stroke:#5496be;stroke-width:11;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
|
||||
<path transform="translate(6.6789702,-32.495842)" style="display:inline;fill:none;stroke:#a730b8;stroke-width:11;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M 25.096981,96.875251 125.21379,197.3795" id="path1684" inkscape:connector-curvature="0" sodipodi:nodetypes="cc"/>
|
||||
<path transform="translate(6.6789702,-32.495842)" sodipodi:nodetypes="cc" inkscape:connector-curvature="0" id="path1686" d="M 38.636939,183.48684 103.30568,57.239007" style="display:inline;fill:none;stroke:#ce3d1a;stroke-width:11;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
|
||||
<path transform="translate(6.6789702,-32.495842)" style="display:inline;fill:none;stroke:#46ae3a;stroke-width:11;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M 125.21379,197.3795 103.30568,57.239007" id="path1688" inkscape:connector-curvature="0" sodipodi:nodetypes="cc"/>
|
||||
<path transform="translate(6.6789702,-32.495842)" sodipodi:nodetypes="cc" inkscape:connector-curvature="0" id="path1682" d="m 25.096981,106.16365 140.084289,22.4788" style="display:inline;fill:none;stroke:#d79611;stroke-width:11;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
|
||||
</g>
|
||||
<g inkscape:groupmode="layer" id="layer2" inkscape:label="Linies" style="display:inline" transform="translate(6.6789703,-32.495842)">
|
||||
<path style="color:#ffffff;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#ffffff;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#ffffff;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:41.5748024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="M 181.13086 275.13672 A 68.892408 68.892408 0 0 1 151.66602 304.46484 L 313.42383 466.85352 L 352.42188 447.08984 L 181.13086 275.13672 z M 394.49414 489.32422 L 355.49609 509.08789 L 437.45898 591.37109 A 68.892409 68.892409 0 0 1 466.92969 562.03906 L 394.49414 489.32422 z " transform="matrix(0.26458333,0,0,0.26458333,-6.6789703,32.495842)" id="path9722"/>
|
||||
<path style="color:#ffffff;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#ffffff;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#ffffff;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:41.5748024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="M 581.64648 339.39062 L 490.07031 385.80078 L 496.82227 428.99023 L 600.4375 376.47656 A 68.892409 68.892409 0 0 1 581.64648 339.39062 z M 436.9082 412.74219 L 220.38281 522.47656 A 68.892408 68.892408 0 0 1 239.17773 559.56641 L 443.66016 455.93359 L 436.9082 412.74219 z " transform="matrix(0.26458333,0,0,0.26458333,-6.6789703,32.495842)" id="path9729"/>
|
||||
<path style="color:#ffffff;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#ffffff;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#ffffff;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:41.5748024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="M 367.27539 142.4375 L 262.79492 346.4082 L 293.64258 377.375 L 404.26562 161.41797 A 68.892408 68.892408 0 0 1 367.27539 142.4375 z M 235.62109 399.45898 L 182.69922 502.77344 A 68.892409 68.892409 0 0 1 219.68555 521.75195 L 266.4668 430.42383 L 235.62109 399.45898 z " transform="matrix(0.26458333,0,0,0.26458333,-6.6789703,32.495842)" id="path9713"/>
|
||||
<path style="color:#ffffff;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#ffffff;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#ffffff;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:41.5748024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="M 150.76758 304.91797 A 68.892408 68.892408 0 0 1 116.35156 312.11328 A 68.892408 68.892408 0 0 1 109.70117 311.41797 L 140.60352 509.08008 A 68.892409 68.892409 0 0 1 175.01953 501.88477 A 68.892409 68.892409 0 0 1 181.66602 502.58008 L 150.76758 304.91797 z " transform="matrix(0.26458333,0,0,0.26458333,-6.6789703,32.495842)" id="path1015"/>
|
||||
<path style="color:#ffffff;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#ffffff;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#ffffff;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:41.5748024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="M 239.3418 560.54492 A 68.892408 68.892408 0 0 1 240.0625 574.42188 A 68.892408 68.892408 0 0 1 232.79492 601.60156 L 430.42383 633.31445 A 68.892409 68.892409 0 0 1 429.70117 619.43555 A 68.892409 68.892409 0 0 1 436.9707 592.25781 L 239.3418 560.54492 z " transform="matrix(0.26458333,0,0,0.26458333,-6.6789703,32.495842)" id="path1674"/>
|
||||
<path style="color:#ffffff;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#ffffff;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#ffffff;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:41.5748024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="M 601.13281 377.19922 L 509.91406 555.28125 A 68.892408 68.892408 0 0 1 546.9082 574.26367 L 638.125 396.18359 A 68.892409 68.892409 0 0 1 601.13281 377.19922 z " transform="matrix(0.26458333,0,0,0.26458333,-6.6789703,32.495842)" id="path1676"/>
|
||||
<path style="color:#ffffff;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#ffffff;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#ffffff;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:41.5748024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="M 476.72266 125.33008 A 68.892408 68.892408 0 0 1 447.25195 154.66211 L 588.51758 296.47266 A 68.892409 68.892409 0 0 1 617.98633 267.14062 L 476.72266 125.33008 z " transform="matrix(0.26458333,0,0,0.26458333,-6.6789703,32.495842)" id="path1678"/>
|
||||
<path style="color:#ffffff;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#ffffff;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#ffffff;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:41.5748024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="M 347.78711 104.63086 L 169.21094 195.12891 A 68.892409 68.892409 0 0 1 188.00391 232.21484 L 366.57812 141.71289 A 68.892408 68.892408 0 0 1 347.78711 104.63086 z " transform="matrix(0.26458333,0,0,0.26458333,-6.6789703,32.495842)" id="path1680"/>
|
||||
<path style="color:#ffffff;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#ffffff;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#ffffff;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:41.5748024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="M 446.92578 154.82617 A 68.892408 68.892408 0 0 1 411.94336 162.30859 A 68.892408 68.892408 0 0 1 405.91406 161.67578 L 421.73242 262.9668 L 464.89453 269.89258 L 446.92578 154.82617 z M 430.92578 321.85352 L 468.32617 561.33594 A 68.892409 68.892409 0 0 1 502.24023 554.39258 A 68.892409 68.892409 0 0 1 509.44727 555.18359 L 474.08984 328.77734 L 430.92578 321.85352 z " transform="matrix(0.26458333,0,0,0.26458333,-6.6789703,32.495842)" id="path9758"/>
|
||||
<path style="color:#ffffff;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#ffffff;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#ffffff;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:41.5748024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="M 188.13086 232.97461 A 68.892408 68.892408 0 0 1 188.88867 247.07031 A 68.892408 68.892408 0 0 1 181.72852 274.05273 L 283.09766 290.33398 L 303.02148 251.42578 L 188.13086 232.97461 z M 361.86719 260.875 L 341.94141 299.78711 L 581.45508 338.25391 A 68.892409 68.892409 0 0 1 580.75977 324.53516 A 68.892409 68.892409 0 0 1 588.10938 297.21094 L 361.86719 260.875 z " transform="matrix(0.26458333,0,0,0.26458333,-6.6789703,32.495842)" id="path9760"/>
|
||||
</g>
|
||||
<g inkscape:groupmode="layer" id="layer3" inkscape:label="Nodes" style="display:inline;opacity:1" transform="translate(6.6789703,-32.495842)">
|
||||
<circle style="fill:#ffffff;fill-opacity:0.99596773;stroke:none;stroke-width:0.26458332;stroke-opacity:0.96078431" id="path817" cx="106.26596" cy="51.535553" r="16.570711" transform="rotate(3.1178174)"/>
|
||||
<circle id="path819" style="fill:#ffffff;fill-opacity:0.99596773;stroke:none;stroke-width:0.26458332;stroke-opacity:0.96078431" cx="171.42836" cy="110.19328" r="16.570711" transform="rotate(3.1178174)"/>
|
||||
<circle id="path823" style="fill:#ffffff;fill-opacity:0.99596773;stroke:none;stroke-width:0.26458332;stroke-opacity:0.96078431" cx="135.76379" cy="190.27704" r="16.570711" transform="rotate(3.1178174)"/>
|
||||
<circle style="fill:#ffffff;fill-opacity:0.99596773;stroke:none;stroke-width:0.26458332;stroke-opacity:0.96078431" id="path825" cx="48.559471" cy="181.1138" r="16.570711" transform="rotate(3.1178174)"/>
|
||||
<circle id="path827" style="fill:#ffffff;fill-opacity:0.99596773;stroke:none;stroke-width:0.26458332;stroke-opacity:0.96078431" cx="30.328812" cy="95.366837" r="16.570711" transform="rotate(3.1178174)"/>
|
||||
</g>
|
||||
<script xmlns=""/></svg>
|
||||
|
Before Width: | Height: | Size: 21 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="92pt" height="92pt" viewBox="0 0 92 92"><script xmlns=""/><defs><clipPath id="a"><path d="M0 .113h91.887V92H0Zm0 0"/></clipPath></defs><g clip-path="url(#a)"><path style="stroke:none;fill-rule:nonzero;fill:#fff;fill-opacity:1" d="M90.156 41.965 50.036 1.848a5.918 5.918 0 0 0-8.372 0l-8.328 8.332 10.566 10.566a7.03 7.03 0 0 1 7.23 1.684 7.034 7.034 0 0 1 1.669 7.277l10.187 10.184a7.028 7.028 0 0 1 7.278 1.672 7.04 7.04 0 0 1 0 9.957 7.05 7.05 0 0 1-9.965 0 7.044 7.044 0 0 1-1.528-7.66l-9.5-9.497V59.36a7.04 7.04 0 0 1 1.86 11.29 7.04 7.04 0 0 1-9.957 0 7.04 7.04 0 0 1 0-9.958 7.06 7.06 0 0 1 2.304-1.539V33.926a7.049 7.049 0 0 1-3.82-9.234L29.242 14.272 1.73 41.777a5.925 5.925 0 0 0 0 8.371L41.852 90.27a5.925 5.925 0 0 0 8.37 0l39.934-39.934a5.925 5.925 0 0 0 0-8.371"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 834 B |
@@ -1,5 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="geometricPrecision" text-rendering="geometricPrecision"
|
||||
image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" viewBox="0 0 512 512" fill="white">
|
||||
<path
|
||||
d="M256 0c141.385 0 256 114.615 256 256S397.385 512 256 512 0 397.385 0 256 114.615 0 256 0zm-17.22 317.056l-10.725-29.064s-17.374 19.388-43.412 19.388c-23.092 0-39.444-20.057-39.444-52.135 0-41.08 20.728-55.778 41.081-55.778 29.392 0 38.744 19.037 46.787 43.421l10.725 33.387c10.72 32.418 30.781 58.465 88.546 58.465 41.426 0 69.53-12.711 69.53-46.105 0-27.059-15.388-41.08-44.112-47.803l-21.364-4.669c-14.705-3.354-19.039-9.35-19.039-19.388 0-11.344 9.008-18.07 23.713-18.07 16.06 0 24.724 6.035 26.033 20.406l33.391-3.99c-2.681-30.093-23.41-42.454-57.486-42.454-30.092 0-59.488 11.344-59.488 47.81 0 22.736 11.048 37.085 38.748 43.761l22.737 5.357c17.024 3.996 22.732 11.049 22.732 20.736 0 12.362-12.023 17.374-34.754 17.374-33.737 0-47.811-17.724-55.786-42.104l-11.048-33.385c-13.965-43.475-36.358-59.497-80.792-59.497-49.13 0-75.221 31.055-75.221 83.877 0 50.766 26.038 78.177 72.884 78.177 37.722 0 55.779-17.724 55.779-17.724l-.015.005v.002z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
225
src/main.rs
@@ -10,17 +10,27 @@ use yew_router::prelude::*;
|
||||
|
||||
mod pages;
|
||||
use crate::pages::about::About;
|
||||
use crate::pages::landing::Landing;
|
||||
use crate::pages::blog::entries::Entries;
|
||||
use crate::pages::blog::entry::Entry;
|
||||
use crate::pages::blog::authors::Authors;
|
||||
use crate::pages::blog::author::Author;
|
||||
use crate::pages::projects::Projects;
|
||||
use pages::not_found::PageNotFound;
|
||||
|
||||
#[derive(Routable, PartialEq, Eq, Clone, Debug)]
|
||||
pub enum Route {
|
||||
#[at("/")]
|
||||
Landing,
|
||||
|
||||
#[at("/about")]
|
||||
About,
|
||||
|
||||
#[at("/blog/entries/:id")]
|
||||
Entry { id: u8 },
|
||||
#[at("/blog/entries")]
|
||||
Entries,
|
||||
#[at("/blog/authors/:id")]
|
||||
Author { id: u8 },
|
||||
#[at("/blog/authors")]
|
||||
Authors,
|
||||
|
||||
#[at("/projects")]
|
||||
Projects,
|
||||
|
||||
@@ -42,6 +52,10 @@ impl Component for App {
|
||||
type Message = Msg;
|
||||
type Properties = ();
|
||||
|
||||
fn create(_ctx: &Context<Self>) -> Self {
|
||||
Self { node_ref: NodeRef::default(), navbar_active: false }
|
||||
}
|
||||
|
||||
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
|
||||
match msg {
|
||||
Msg::ToggleNavbar => {
|
||||
@@ -51,67 +65,58 @@ impl Component for App {
|
||||
}
|
||||
}
|
||||
|
||||
fn create(_ctx: &Context<Self>) -> Self {
|
||||
Self { node_ref: NodeRef::default(), navbar_active: false }
|
||||
}
|
||||
|
||||
fn view(&self, _ctx: &Context<Self>) -> Html {
|
||||
html! {
|
||||
<>
|
||||
<BrowserRouter>
|
||||
<header>{ self.view_header(_ctx) }</header>
|
||||
<main style="z-index: 1 !important;">
|
||||
<canvas style="
|
||||
background-color: black !important;
|
||||
position: fixed !important;
|
||||
left: 0 !important;
|
||||
top: 0 !important;
|
||||
z-index: 0 !important;
|
||||
" ref={self.node_ref.clone()}/>
|
||||
<div style="
|
||||
overflow: scroll !important;
|
||||
left: 0 !important;
|
||||
margin-top: var(--bulma-navbar-height) !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
">
|
||||
<Switch<Route> render={switch} />
|
||||
</div>
|
||||
</main>
|
||||
</BrowserRouter>
|
||||
|
||||
<div class="tile is-parent container is-centered is-multiline" style="margin-bottom: var(--bulma-navbar-height) !important;">
|
||||
<div class="columns is-size-3 ml-3 mr-3" style="margin-top: var(--bulma-block-spacing) !important;">
|
||||
<div class="box mr-1 mb-5 pl-1 pr-1 pt-1 pb-1">
|
||||
<p class="subtitle ml-2 mb-1 is-size-6" style="text-align: center !important;">{r#"cool buttons you should click on:"#}</p>
|
||||
<div class="column is-full mb-0 mt-0 ml-0 mr-1 is-flex">
|
||||
<a class="mr-1" href="https://beta.servfail.network/"><img loading="eager" alt="servfail" class="image has-text-centered" src="servfail.png" /></a>
|
||||
<a class="mr-1" href="https://webassembly.org/"><img loading="eager" alt="wasm" class="image has-text-centered" src="wasm.png" /></a>
|
||||
<a class="mr-1" href="https://www.rust-lang.org/"><img loading="eager" alt="rust" class="image has-text-centered" src="rust.png" /></a>
|
||||
<a class="" href="https://fedoraproject.org/"><img loading="eager" alt="fedora" class="image has-text-centered" src="fedora.png" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box ml-1 mb-5 pl-1 pr-1 pt-1 pb-1">
|
||||
<p class="subtitle ml-2 mb-1 is-size-6" style="text-align: center !important;">{r#"hotlink my button:"#}</p>
|
||||
<div class="column mb-0 mr-1 is-flex is-flex-direction-row is-flex-wrap-nowrap">
|
||||
<a href="https://celesteflare.cc/" class="mr-2"><img loading="eager" alt="luciel" class="image" src="luciel.png" style="width: 88px !important; height: 31px !important; max-width: 100vw !important;" /></a>
|
||||
<textarea class="textarea is-size-7" placeholder="" rows="1" readonly=true style="max-height: 31px !important; resize: none !important; min-width: 0px !important;" value="<a href=\"https://celesteflare.cc/\"><img loading=\"eager\" alt=\"luciel\" class=\"image has-text-centered\" src=\"https://celesteflare.cc/luciel.png\" /></a>"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="footer" style="
|
||||
--bulma-footer-background-color: #1E1E2E80 !important;
|
||||
z-index: 1 !important;
|
||||
<canvas style="
|
||||
background-color: black !important;
|
||||
position: fixed !important;
|
||||
left: 0px !important;
|
||||
bottom: 0px !important;
|
||||
margin-bottom: 0 !important;
|
||||
min-height: 31px !important;
|
||||
width: 100% !important;
|
||||
padding: 0 !important;
|
||||
">{ self.view_footer() }</footer>
|
||||
left: 0 !important;
|
||||
top: 0 !important;
|
||||
z-index: 0 !important;
|
||||
" ref={self.node_ref.clone()}/>
|
||||
<div style="
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
flex-wrap: wrap !important;
|
||||
height: 100vh !important;
|
||||
">
|
||||
<BrowserRouter>
|
||||
<main style="
|
||||
z-index: 1 !important;
|
||||
display: flex !important;
|
||||
flex-direction: row-reverse !important;
|
||||
flex-wrap: wrap !important;
|
||||
overflow: visible !important;
|
||||
left: 0 !important;
|
||||
margin-top: calc(var(--bulma-navbar-height)) !important;
|
||||
margin-bottom: calc(var(--bulma-navbar-height) * 2) !important;
|
||||
height: calc(100vh - (var(--bulma-navbar-height) * 2)) !important;
|
||||
width: 100% !important;
|
||||
align-items: center !important;
|
||||
"><Switch<Route> render={switch} />
|
||||
</main>
|
||||
<header style="
|
||||
z-index: 1 !important;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
">{ self.view_header(_ctx) }</header>
|
||||
</BrowserRouter>
|
||||
<footer class="footer" style="
|
||||
--bulma-footer-background-color: #1E1E2E80 !important;
|
||||
z-index: 1 !important;
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
flex-wrap: wrap !important;
|
||||
position: fixed !important;
|
||||
left: 0px !important;
|
||||
bottom: 0px !important;
|
||||
margin-bottom: 0 !important;
|
||||
width: 100% !important;
|
||||
padding: 0 !important;
|
||||
">{ self.view_footer() }</footer>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
}
|
||||
@@ -123,11 +128,14 @@ impl Component for App {
|
||||
|
||||
fn switch(routes: Route) -> Html {
|
||||
match routes {
|
||||
Route::Landing => { html! { <Landing /> } }
|
||||
|
||||
Route::About => { html! { <About /> } }
|
||||
Route::Projects => { html! { <Projects /> } }
|
||||
|
||||
Route::Entries => { html! { <Entries /> } }
|
||||
Route::Entry { id } => { html! { <Entry seed={id as u8} /> } }
|
||||
Route::Authors => { html! { <Authors /> } }
|
||||
Route::Author { id } => { html! { <Author seed={id} /> } }
|
||||
|
||||
Route::Projects => { html! { <Projects /> } }
|
||||
Route::NotFound => { html! { <PageNotFound /> } }
|
||||
}
|
||||
}
|
||||
@@ -147,28 +155,19 @@ impl App {
|
||||
backdrop-filter: blur(4px) !important;
|
||||
">
|
||||
<div class="navbar-brand">
|
||||
<img loading="eager" alt="icowon" class="image pl-2 pr-2 pt-2 pb-2" style="width: var(--bulma-navbar-height) !important; height: var(--bulma-navbar-height) !important;" src="favicon.ico" />
|
||||
<button class={classes!("navbar-burger", "burger", active_class)} aria-label="menu" aria-expanded="false" onclick={_ctx.link().callback(|_| Msg::ToggleNavbar)}>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class={classes!("navbar-menu", active_class)}>
|
||||
<div class="navbar-start">
|
||||
<Link<Route> classes={classes!("navbar-item")} to={Route::About}>{r"about"}</Link<Route>>
|
||||
<Link<Route> classes={classes!("navbar-item")} to={Route::Entries}>{r"blog"}</Link<Route>>
|
||||
<Link<Route> classes={classes!("navbar-item")} to={Route::Projects}>{r"projects"}</Link<Route>>
|
||||
</div>
|
||||
/*
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="field is-grouped">
|
||||
<p class="control">
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
*/
|
||||
</div>
|
||||
</nav>
|
||||
}
|
||||
@@ -177,23 +176,71 @@ impl App {
|
||||
fn view_footer(&self) -> Html {
|
||||
html! {
|
||||
<>
|
||||
<div class="is-flex is-flex-direction-row is-flex-wrap-wrap is-justify-content-space-between" style="backdrop-filter: blur(4px);">
|
||||
<p class="is-align-content-center is-size-7 mb-1 ml-0" style="
|
||||
width: 50% !important;
|
||||
<div class="is-flex is-flex-direction-column is-flex-wrap-wrap" style="
|
||||
backdrop-filter: blur(4px);
|
||||
width: 100vw !important;
|
||||
text-align: left !important;
|
||||
vertical-align: middle !important;
|
||||
min-height: 31px !important;
|
||||
height: 40px !important; max-height: 40px !important;
|
||||
image-rendering: pixelated !important;
|
||||
">
|
||||
{r#"✨ built with "#}
|
||||
<a href="https://yew.rs/">{r#"yew"#}</a>
|
||||
{r#" and "#}
|
||||
<a href="https://bulma.io/">{r#"bulma"#}</a>
|
||||
{r#" in rust"#}
|
||||
</p>
|
||||
<div class="is-align-content-center is-inline-block mt-1 mr-0" style="width: 50% !important; text-align: right !important; vertical-align: middle !important;">
|
||||
<a class="is-inline-block" href="https://donotsta.re/lunary"><img loading="eager" alt="fedi" class="image is-24x24 has-text-centered pl-1 pr-1 pt-1 pb-1" src="fedi.svg" /></a>
|
||||
<a class="is-inline-block" href="https://git.gay/luciel/"><img loading="eager" alt="git" class="image is-24x24 has-text-centered pl-1 pr-1 pt-1 pb-1" src="git.svg" /></a>
|
||||
<a class="is-inline-block" href="https://www.last.fm/user/lumii500pg"><img loading="eager" alt="lastfm" class="image is-24x24 has-text-centered pl-1 pr-1 pt-1 pb-1" src="lastfm.svg" /></a>
|
||||
<div class="is-align-content-flex-start is-flex is-flex-shrink-0 is-flex-direction-column is-align-content-center is-flex-wrap-wrap ml-0 mt-0 mr-0 mb-0" style="width: 100% !important; min-height: 40px !important; height: 40px !important; max-height: 40px !important; overflow-y: hidden !important; overflow-x: auto !important;">
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
" href="https://i0ur.ing/"><img loading="eager" alt="servfail" class="image" src="iouring.png" /></a>
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
" href="https://webassembly.org/"><img loading="eager" alt="wasm" class="image" src="wasm.png" /></a>
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
" href="https://beta.servfail.network/"><img loading="eager" alt="servfail" class="image" src="servfail.png" /></a>
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
" href="https://www.dataforest.net/en/"><img loading="eager" alt="dataforest" class="image" src="dataforest.png" /></a>
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
" href="https://fedoraproject.org/"><img loading="eager" alt="fedora" class="image" src="fedora.png" /></a>
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
" href="https://artixlinux.org/"><img loading="eager" alt="artix" class="image" src="artix.png" /></a>
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
" href="https://nixos.org/"><img loading="eager" alt="nixos" class="image" src="nixos.png" /></a>
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
" href="https://chimera-linux.org/"><img loading="eager" alt="void" class="image" src="chimera.png" /></a>
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
" href="https://voidlinux.org/"><img loading="eager" alt="void" class="image" src="void.png" /></a>
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
" href="https://www.rust-lang.org/"><img loading="eager" alt="rust" class="image" src="rust.png" /></a>
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
" href="https://dotnet.microsoft.com/en-us/"><img loading="eager" alt="csharp" class="image" src="csharp.png" /></a>
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
" href="https://kotlinlang.org/"><img loading="eager" alt="kotlin" class="image" src="kotlin.png" /></a>
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
" href="https://www.java.com/"><img loading="eager" alt="java" class="image" src="java.png" /></a>
|
||||
<a class="mt-1 mb-1 mr-1 ml-0" style="
|
||||
width: 88px !important;
|
||||
height: 31px !important
|
||||
"><img loading="eager" alt="aqueer" class="image" src="aqueer.png" /></a>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -12,38 +12,26 @@ impl Component for About {
|
||||
fn view(&self, _ctx: &Context<Self>) -> Html {
|
||||
html! {
|
||||
<>
|
||||
<div class="tile is-parent container">
|
||||
{ self.view_info_card() }
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
}
|
||||
}
|
||||
impl About {
|
||||
fn view_info_card(&self) -> Html {
|
||||
html! {
|
||||
<>
|
||||
<div class="box is-small is-flex-shrink-5 mb-5 mt-5">
|
||||
<div class="tile is-parent container box is-small is-flex-shrink-5 mb-5 mt-5">
|
||||
<img alt="insert pfp here" loading="eager" class="image is-128x128 is-square is-inline-block mg-small" src="profile.avif" />
|
||||
<div class="columns is-narrow ml-3 is-inline-block is-vcentered is-centered is-gapless is-multiline is-0 mt-4" style="vertical-align: top !important;">
|
||||
<p class="column is-narrow" style="filter: url(post.bloom.svg#process) !important; color: #B4BEFE !important;"><img loading="eager" alt="ket" class="image is-24x24 is-square is-inline-block mg-small" src="oneko.gif" />{r" Lucielle R. Hoerner"}</p>
|
||||
<p class="column is-narrow" style="background-clip: text !important; background-image: linear-gradient(45deg, #5BCEFAFF, #F5A9B8FF, #FFFFFFFF) !important;">
|
||||
<p>{r"she/they · transfem and poly"}</p>
|
||||
<p>{r"programmer and freelancer"}</p>
|
||||
<p>{r"they/she · transfem"}</p>
|
||||
<p>{r"certified catgirl™"}</p>
|
||||
<p>{r"software engineer"}</p>
|
||||
</p>
|
||||
</div>
|
||||
<hr style="background-color: #B4BEFE60 !important;" />
|
||||
<p class="subtitle">{r#"about me"#}</p>
|
||||
<div class="content is-size-7">{r#"
|
||||
hellow there! i'm lunary but you can also just call me luciel, luci or luni.
|
||||
personal preference is ordered.
|
||||
thing's i'm interested in are gamedev, devsecops, exploits, hacking, music and cooking.
|
||||
haj! i'm luciel, but you can also just call me lucie.
|
||||
i have lots of interests including music, cooking, development and learning new things.
|
||||
in my free-time i mostly work on my private projects or spent time with my partners or online friends.
|
||||
my knowledge is based on autodidactics and experiences with (former) friends.
|
||||
looking for a job/internship at the moment because i wasn't able to finish my previous internship due to some financial circumstances.
|
||||
you can find projects i work on by clicking on the button at the left and very top.
|
||||
i may or may not update information stated here but that's it for now.
|
||||
looking for an apprenticeship or job atm. because i wasn't able to finish my previous one due to some financial circumstances.
|
||||
you can find public projects i work on somewhere in the header.
|
||||
i may or may not update information stated here.
|
||||
"#}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
82
src/pages/blog/author.rs
Normal file
@@ -0,0 +1,82 @@
|
||||
use yew::prelude::*;
|
||||
use crate::pages::blog::content;
|
||||
use crate::pages::blog::content::BlogEntry;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Properties)]
|
||||
pub struct Props {
|
||||
pub seed: u8,
|
||||
}
|
||||
|
||||
pub struct Author {
|
||||
author: content::Author,
|
||||
}
|
||||
impl Component for Author {
|
||||
type Message = ();
|
||||
type Properties = Props;
|
||||
|
||||
fn create(ctx: &Context<Self>) -> Self {
|
||||
Self { author: content::Author::from_seed(ctx.props().seed), }
|
||||
}
|
||||
|
||||
fn changed(&mut self, ctx: &Context<Self>, _old_props: &Self::Properties) -> bool {
|
||||
self.author = content::Author::from_seed(ctx.props().seed);
|
||||
true
|
||||
}
|
||||
|
||||
fn view(&self, _ctx: &Context<Self>) -> Html {
|
||||
let Self { author } = self;
|
||||
html! {
|
||||
<div class="tile is-parent container box is-small is-flex-shrink-5 mb-5 mt-5">
|
||||
<img alt="insert pfp here" loading="eager" class="image is-128x128 is-square is-inline-block mg-small" src={author.image_url.clone()} />
|
||||
<div class="columns is-narrow ml-3 is-inline-block is-vcentered is-centered is-gapless is-multiline is-0 mt-4" style="vertical-align: top !important;">
|
||||
<p class="column is-narrow" style="filter: url(post.bloom.svg#process) !important; color: #B4BEFE !important;">{author.name.clone()}</p>
|
||||
<p class="column is-narrow" style="background-clip: text !important; background-image: linear-gradient(45deg, #5BCEFAFF, #F5A9B8FF, #FFFFFFFF) !important;">
|
||||
{ for author.keywords.iter().map(|tag| html! { <p>{ tag }</p> }) }
|
||||
</p>
|
||||
</div>
|
||||
<hr style="background-color: #B4BEFE60 !important;" />
|
||||
<p class="subtitle">{r#"about me"#}</p>
|
||||
<div class="content is-size-7">
|
||||
{ author.about.clone() }
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
<div class="section container">
|
||||
<div class="tile is-ancestor is-vertical">
|
||||
<div class="tile is-parent">
|
||||
<article class="tile is-child notification is-light">
|
||||
<p class="title">{ &author.name }</p>
|
||||
</article>
|
||||
</div>
|
||||
<div class="tile">
|
||||
<div class="tile is-parent is-3">
|
||||
<article class="tile is-child notification">
|
||||
<p class="title">{ "Interests" }</p>
|
||||
<div class="tags">
|
||||
{ for author.keywords.iter().map(|tag| html! { <span class="tag is-info">{ tag }</span> }) }
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<figure class="tile is-child image is-square">
|
||||
<img alt="The author's profile picture." src={author.image_url.clone()} />
|
||||
</figure>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<article class="tile is-child notification is-info">
|
||||
<div class="content">
|
||||
<p class="title">{ "About me" }</p>
|
||||
<div class="content">
|
||||
{ author.about.clone() }
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
*/
|
||||
61
src/pages/blog/authorcard.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
use yew::prelude::*;
|
||||
use yew_router::components::Link;
|
||||
|
||||
use crate::pages::blog::content::BlogEntry;
|
||||
use crate::pages::blog::content::Author;
|
||||
|
||||
use crate::Route;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Properties)]
|
||||
pub struct PropsAuthorCard {
|
||||
pub seed: u8,
|
||||
}
|
||||
|
||||
pub struct AuthorCard {
|
||||
author: Author,
|
||||
}
|
||||
|
||||
impl Component for AuthorCard {
|
||||
type Message = ();
|
||||
type Properties = PropsAuthorCard;
|
||||
|
||||
fn create(ctx: &Context<Self>) -> Self {
|
||||
Self { author: Author::from_seed(ctx.props().seed), }
|
||||
}
|
||||
|
||||
fn changed(&mut self, ctx: &Context<Self>, _old_props: &Self::Properties) -> bool {
|
||||
self.author = Author::from_seed(ctx.props().seed);
|
||||
true
|
||||
}
|
||||
|
||||
fn view(&self, _ctx: &Context<Self>) -> Html {
|
||||
let Self { author } = self;
|
||||
html! {
|
||||
<>
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="media">
|
||||
<div class="media-left">
|
||||
<figure class="image is-128x128">
|
||||
<img alt="this should normally show an image mew,," src={author.image_url.clone()} />
|
||||
</figure>
|
||||
</div>
|
||||
<div class="media-content">
|
||||
<p class="title is-3">{ &author.name }</p>
|
||||
<p>
|
||||
{ "I like " }
|
||||
<b>{ author.keywords.join(", ") }</b>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="card-footer">
|
||||
<Link<Route> classes={classes!("card-footer-item")} to={Route::Author { id: author.seed }}>
|
||||
{ "Profile" }
|
||||
</Link<Route>>
|
||||
</footer>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/pages/blog/authors.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use yew::prelude::*;
|
||||
|
||||
use crate::pages::blog::authorcard::AuthorCard;
|
||||
|
||||
/*pub enum Msg {
|
||||
NextAuthors,
|
||||
}*/
|
||||
|
||||
pub struct Authors {
|
||||
seeds: Vec<u8>,
|
||||
}
|
||||
impl Component for Authors {
|
||||
type Message = (); //Msg;
|
||||
type Properties = ();
|
||||
|
||||
fn create(_ctx: &Context<Self>) -> Self {
|
||||
Self { seeds: vec![0], }
|
||||
}
|
||||
|
||||
/*fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
|
||||
match msg { Msg::NextAuthors => { self.seeds = vec![0]; true } }
|
||||
}*/
|
||||
|
||||
fn view(&self, _: &Context<Self>) -> Html {
|
||||
html! {
|
||||
{ for self.seeds.iter().map(|&seed| { html! {
|
||||
<AuthorCard {seed} />
|
||||
} }) }
|
||||
}
|
||||
}
|
||||
}
|
||||
144
src/pages/blog/content.rs
Normal file
@@ -0,0 +1,144 @@
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Author {
|
||||
pub seed: u8,
|
||||
pub name: String,
|
||||
pub keywords: Vec<String>,
|
||||
pub image_url: String,
|
||||
pub about: String
|
||||
}
|
||||
impl BlogEntry for Author {
|
||||
fn from_entry(entry: &mut Entry) -> Self {
|
||||
return match entry.seed {
|
||||
0 => Self {
|
||||
seed: entry.seed,
|
||||
name: "iouring".to_string(),
|
||||
image_url: "profile.avif".to_string(),
|
||||
about: "sup".to_string(),
|
||||
keywords: vec![
|
||||
"meow".to_string(),
|
||||
"mrrp".to_string(),
|
||||
"mew".to_string()
|
||||
]
|
||||
},
|
||||
_ => Self {
|
||||
seed: u8::MAX,
|
||||
name: "not found".to_string(),
|
||||
image_url: "".to_string(),
|
||||
about: "".to_string(),
|
||||
keywords: vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct PostMeta {
|
||||
pub seed: u8,
|
||||
pub title: String,
|
||||
pub author: Author,
|
||||
pub keywords: Vec<String>,
|
||||
pub image_url: String,
|
||||
}
|
||||
impl BlogEntry for PostMeta {
|
||||
fn from_entry(entry: &mut Entry) -> Self {
|
||||
return match entry.seed {
|
||||
0 => Self {
|
||||
seed: entry.seed,
|
||||
title: "awawa title".to_string(),
|
||||
author: Author::from_entry(entry),
|
||||
keywords: vec!["meow".to_string(), "mrrp".to_string(), "mew".to_string()],
|
||||
image_url: "testimage.jpg".to_string()
|
||||
},
|
||||
_ => Self {
|
||||
seed: entry.seed,
|
||||
title: "not found".to_string(),
|
||||
author: Author::from_entry(entry),
|
||||
keywords: vec![],
|
||||
image_url: "".to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Post {
|
||||
pub meta: PostMeta,
|
||||
pub content: Vec<PostPart>,
|
||||
}
|
||||
impl BlogEntry for Post {
|
||||
fn from_entry(entry: &mut Entry) -> Self {
|
||||
return Self {
|
||||
meta: PostMeta::from_entry(entry),
|
||||
content: vec![PostPart::from_entry(entry)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum PostPart {
|
||||
Section(Section),
|
||||
Quote(Quote),
|
||||
}
|
||||
impl BlogEntry for PostPart {
|
||||
fn from_entry(entry: &mut Entry) -> Self {
|
||||
// TODO: ... | add proper logic
|
||||
|
||||
return Self::Section(Section::from_entry(entry))
|
||||
// return Self::Quote(Quote::from_entry(entry))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Section {
|
||||
pub title: String,
|
||||
pub paragraphs: Vec<String>,
|
||||
pub image_url: String,
|
||||
}
|
||||
impl BlogEntry for Section {
|
||||
fn from_entry(entry: &mut Entry) -> Self {
|
||||
return match entry.seed {
|
||||
0 => Self {
|
||||
title: "awawa title".to_string(),
|
||||
image_url: "".to_string(),
|
||||
paragraphs: vec![
|
||||
"meow 1".to_string(),
|
||||
"mrrp 2".to_string(),
|
||||
"mew 3".to_string()
|
||||
]
|
||||
},
|
||||
_ => Self {
|
||||
title: "not found".to_string(),
|
||||
image_url: "".to_string(),
|
||||
paragraphs: vec![]
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Quote {
|
||||
pub author: Author,
|
||||
pub content: String,
|
||||
}
|
||||
impl BlogEntry for Quote {
|
||||
fn from_entry(entry: &mut Entry) -> Self {
|
||||
return Self { author: Author::from_seed(entry.seed), content: "awawa content".to_string() }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Entry {
|
||||
pub seed: u8
|
||||
}
|
||||
|
||||
impl Entry {
|
||||
pub fn from_seed(seed: u8) -> Self {
|
||||
Self { seed }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BlogEntry: Sized {
|
||||
fn from_entry(entry: &mut Entry) -> Self;
|
||||
fn from_seed(seed: u8) -> Self {
|
||||
Self::from_entry(&mut Entry::from_seed(seed))
|
||||
}
|
||||
}
|
||||
91
src/pages/blog/entries.rs
Normal file
@@ -0,0 +1,91 @@
|
||||
use yew::prelude::*;
|
||||
use yew_router::prelude::*;
|
||||
|
||||
use crate::pages::blog::content::Author;
|
||||
use crate::pages::blog::content::BlogEntry;
|
||||
use crate::pages::blog::entrycard::EntryCard;
|
||||
use crate::pages::blog::navigation::{PageQuery, Pagination};
|
||||
use crate::Route;
|
||||
|
||||
const ITEMS_PER_PAGE: u8 = 10;
|
||||
const TOTAL_PAGES: u8 = 1;
|
||||
|
||||
pub enum Msg {
|
||||
PageUpdated,
|
||||
}
|
||||
|
||||
pub struct Entries {
|
||||
page: u8,
|
||||
_listener: LocationHandle,
|
||||
}
|
||||
|
||||
fn current_page(ctx: &Context<Entries>) -> u8 {
|
||||
let location = ctx.link().location().unwrap();
|
||||
|
||||
location.query::<PageQuery>().map(|it| it.page as u8).unwrap_or(1)
|
||||
}
|
||||
|
||||
impl Component for Entries {
|
||||
type Message = Msg;
|
||||
type Properties = ();
|
||||
|
||||
fn create(ctx: &Context<Self>) -> Self {
|
||||
let link = ctx.link().clone();
|
||||
let listener = ctx
|
||||
.link()
|
||||
.add_location_listener(link.callback(move |_| Msg::PageUpdated))
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
page: current_page(ctx),
|
||||
_listener: listener,
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
||||
match msg {
|
||||
Msg::PageUpdated => self.page = current_page(ctx),
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn view(&self, ctx: &Context<Self>) -> Html {
|
||||
let page = self.page;
|
||||
|
||||
html! {
|
||||
<div class="section container">
|
||||
<h1 class="title">{ "entries" }</h1>
|
||||
<h2 class="subtitle">{ "here are some things i yapped about" }</h2>
|
||||
{ self.view_posts(ctx) }
|
||||
<Pagination
|
||||
{page}
|
||||
total_pages={TOTAL_PAGES}
|
||||
route_to_page={Route::Entries}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Entries {
|
||||
fn view_posts(&self, _ctx: &Context<Self>) -> Html {
|
||||
let start_seed = (self.page - 1) * ITEMS_PER_PAGE;
|
||||
let cards: Vec<_> = (0..ITEMS_PER_PAGE)
|
||||
.filter(|&seed_offset| Author::from_seed(seed_offset).seed != u8::MAX)
|
||||
.map(|seed_offset| {
|
||||
html! {
|
||||
<li class="list-item mb-5">
|
||||
<EntryCard seed={start_seed + seed_offset} />
|
||||
</li>
|
||||
}
|
||||
}).collect();
|
||||
html! {
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<ul class="list">
|
||||
{ for cards }
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
152
src/pages/blog/entry.rs
Normal file
@@ -0,0 +1,152 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use yew::prelude::*;
|
||||
use yew_router::prelude::*;
|
||||
|
||||
use crate::Route;
|
||||
use crate::pages::blog::content;
|
||||
use crate::pages::blog::content::BlogEntry;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Properties)]
|
||||
pub struct Props {
|
||||
pub seed: u8,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub struct PostState {
|
||||
pub inner: content::Post,
|
||||
}
|
||||
|
||||
impl Reducible for PostState {
|
||||
type Action = u8;
|
||||
fn reduce(self: Rc<Self>, action: u8) -> Rc<Self> {
|
||||
Self { inner: content::Post::from_seed(action.into()), }.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn Entry(props: &Props) -> Html {
|
||||
let seed = props.seed;
|
||||
|
||||
let post = use_reducer(|| PostState {
|
||||
inner: content::Post::from_seed(seed.into()),
|
||||
});
|
||||
|
||||
{
|
||||
let post_dispatcher = post.dispatcher();
|
||||
use_effect_with(seed, move |seed| {
|
||||
post_dispatcher.dispatch(*seed);
|
||||
|
||||
|| {}
|
||||
});
|
||||
}
|
||||
|
||||
let post = &post.inner;
|
||||
|
||||
let render_quote = |quote: &content::Quote| {
|
||||
html! {
|
||||
<article class="media block box my-6">
|
||||
<figure class="media-left">
|
||||
<p class="image is-64x64">
|
||||
<img alt="The author's profile" src={quote.author.image_url.clone()} loading="lazy" />
|
||||
</p>
|
||||
</figure>
|
||||
<div class="media-content">
|
||||
<div class="content">
|
||||
<Link<Route> classes={classes!("is-size-5")} to={Route::Author { id: quote.author.seed }}>
|
||||
<strong>{ "e.author.name }</strong>
|
||||
</Link<Route>>
|
||||
<p class="is-family-secondary">
|
||||
{ "e.content }
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
}
|
||||
};
|
||||
|
||||
let render_section_hero = |section: &content::Section| {
|
||||
html! {
|
||||
<section class="hero is-dark has-background mt-6 mb-3">
|
||||
<img alt="This section's image" class="hero-background is-transparent" src={section.image_url.clone()} loading="lazy" />
|
||||
<div class="hero-body">
|
||||
<div class="container">
|
||||
<h2 class="subtitle">{ §ion.title }</h2>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
};
|
||||
|
||||
let render_section = |section, show_hero| {
|
||||
let hero = if show_hero {
|
||||
render_section_hero(section)
|
||||
} else {
|
||||
html! {}
|
||||
};
|
||||
let paragraphs = section.paragraphs.iter().map(|paragraph| {
|
||||
html! {
|
||||
<p>{ paragraph }</p>
|
||||
}
|
||||
});
|
||||
html! {
|
||||
<section>
|
||||
{ hero }
|
||||
<div>{ for paragraphs }</div>
|
||||
</section>
|
||||
}
|
||||
};
|
||||
|
||||
let view_content = {
|
||||
// don't show hero for the first section
|
||||
let mut show_hero = false;
|
||||
|
||||
let parts = post.content.iter().map(|part| match part {
|
||||
content::PostPart::Section(section) => {
|
||||
let html = render_section(section, show_hero);
|
||||
// show hero between sections
|
||||
show_hero = true;
|
||||
html
|
||||
}
|
||||
content::PostPart::Quote(quote) => {
|
||||
// don't show hero after a quote
|
||||
show_hero = false;
|
||||
render_quote("e)
|
||||
}
|
||||
});
|
||||
html! {{for parts}}
|
||||
};
|
||||
|
||||
let keywords = post
|
||||
.meta
|
||||
.keywords
|
||||
.iter()
|
||||
.map(|keyword| html! { <span class="tag is-info">{ keyword }</span> });
|
||||
|
||||
html! {
|
||||
<>
|
||||
<section class="hero is-medium is-light has-background">
|
||||
<img alt="The hero's background" class="hero-background is-transparent" src={post.meta.image_url.clone()} />
|
||||
<div class="hero-body">
|
||||
<div class="container">
|
||||
<h1 class="title">
|
||||
{ &post.meta.title }
|
||||
</h1>
|
||||
<h2 class="subtitle">
|
||||
{ "by " }
|
||||
<Link<Route> classes={classes!("has-text-weight-semibold")} to={Route::Author { id: post.meta.author.seed }}>
|
||||
{ &post.meta.author.name }
|
||||
</Link<Route>>
|
||||
</h2>
|
||||
<div class="tags">
|
||||
{ for keywords }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="section container">
|
||||
{ view_content }
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
}
|
||||
68
src/pages/blog/entrycard.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use yew::prelude::*;
|
||||
use yew_router::components::Link;
|
||||
|
||||
use crate::pages::blog::content::BlogEntry;
|
||||
use crate::pages::blog::content::PostMeta;
|
||||
|
||||
use crate::Route;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Properties)]
|
||||
pub struct PropsEntryCard {
|
||||
pub seed: u8,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub struct PostMetaState {
|
||||
inner: PostMeta,
|
||||
}
|
||||
|
||||
impl Reducible for PostMetaState {
|
||||
type Action = u8;
|
||||
|
||||
fn reduce(self: Rc<Self>, action: u8) -> Rc<Self> {
|
||||
Self { inner: PostMeta::from_seed(action.into()), }.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn EntryCard(props: &PropsEntryCard) -> Html {
|
||||
let seed = props.seed;
|
||||
|
||||
let post = use_reducer_eq(|| PostMetaState {
|
||||
inner: PostMeta::from_seed(seed.into()),
|
||||
});
|
||||
|
||||
{
|
||||
let post_dispatcher = post.dispatcher();
|
||||
use_effect_with(seed, move |seed| {
|
||||
post_dispatcher.dispatch(*seed);
|
||||
|
||||
|| {}
|
||||
});
|
||||
}
|
||||
|
||||
let post = &post.inner;
|
||||
|
||||
html! {
|
||||
<div class="card" style="height: 300px !important; max-height: 300px !important;">
|
||||
<img loading="eager" class="card-image image is-2by1" src={post.image_url.clone()} alt="blog image" style="
|
||||
object-fit: cover !important;
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
height: 200px !important;
|
||||
max-height: 200px !important;
|
||||
filter: blur(6px) !important;
|
||||
" />
|
||||
<div class="card-content" style="height: fit-content !important; width: fit-content !important;">
|
||||
<Link<Route> classes={classes!("title", "is-block")} to={Route::Entry { id: post.seed }}>
|
||||
{ &post.title }
|
||||
</Link<Route>>
|
||||
<Link<Route> classes={classes!("subtitle", "is-block")} to={Route::Author { id: post.author.seed }}>
|
||||
{ &post.author.name }
|
||||
</Link<Route>>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
8
src/pages/blog/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
pub mod content;
|
||||
pub mod entries;
|
||||
pub mod entry;
|
||||
pub mod entrycard;
|
||||
pub mod authors;
|
||||
pub mod author;
|
||||
pub mod authorcard;
|
||||
pub mod navigation;
|
||||
213
src/pages/blog/navigation.rs
Normal file
@@ -0,0 +1,213 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yew::prelude::*;
|
||||
use yew_router::components::Link;
|
||||
|
||||
use crate::Route;
|
||||
|
||||
const ELLIPSIS: &str = "\u{02026}";
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
|
||||
pub struct PageQuery {
|
||||
pub page: u8,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Properties)]
|
||||
pub struct PropsNavigation {
|
||||
pub page: u8,
|
||||
pub total_pages: u8,
|
||||
pub route_to_page: Route,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn RelNavButtons(props: &PropsNavigation) -> Html {
|
||||
let PropsNavigation {
|
||||
page,
|
||||
total_pages,
|
||||
route_to_page: to,
|
||||
} = props.clone();
|
||||
|
||||
html! {
|
||||
<>
|
||||
<Link<Route, PageQuery>
|
||||
classes={classes!("pagination-previous")}
|
||||
disabled={page==1}
|
||||
query={Some(PageQuery{page: page - 1})}
|
||||
to={to.clone()}
|
||||
>
|
||||
{ "Previous" }
|
||||
</Link<Route, PageQuery>>
|
||||
<Link<Route, PageQuery>
|
||||
classes={classes!("pagination-next")}
|
||||
disabled={page==total_pages}
|
||||
query={Some(PageQuery{page: page + 1})}
|
||||
{to}
|
||||
>
|
||||
{ "Next page" }
|
||||
</Link<Route, PageQuery>>
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Properties, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct RenderLinksProps {
|
||||
range: Range<u8>,
|
||||
len: usize,
|
||||
max_links: usize,
|
||||
props: PropsNavigation,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn RenderLinks(props: &RenderLinksProps) -> Html {
|
||||
let RenderLinksProps {
|
||||
range,
|
||||
len,
|
||||
max_links,
|
||||
props,
|
||||
} = props.clone();
|
||||
|
||||
let mut range = range;
|
||||
|
||||
if len > max_links {
|
||||
let last_link =
|
||||
html! {<RenderLink to_page={range.next_back().unwrap()} props={props.clone()} />};
|
||||
let links = range
|
||||
.take(max_links - 2)
|
||||
.map(|page| html! {<RenderLink to_page={page} props={props.clone()} />});
|
||||
html! {
|
||||
<>
|
||||
{ for links }
|
||||
<li><span class="pagination-ellipsis">{ ELLIPSIS }</span></li>
|
||||
{ last_link }
|
||||
</>
|
||||
}
|
||||
} else {
|
||||
html! {
|
||||
for page in range {
|
||||
<RenderLink to_page={page} props={props.clone()} />
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Properties, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct RenderLinkProps {
|
||||
to_page: u8,
|
||||
props: PropsNavigation,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn RenderLink(props: &RenderLinkProps) -> Html {
|
||||
let RenderLinkProps { to_page, props } = props.clone();
|
||||
|
||||
let PropsNavigation {
|
||||
page,
|
||||
route_to_page,
|
||||
..
|
||||
} = props;
|
||||
|
||||
let is_current_class = if to_page == page { "is-current" } else { "" };
|
||||
|
||||
html! {
|
||||
<li>
|
||||
<Link<Route, PageQuery>
|
||||
classes={classes!("pagination-link", is_current_class)}
|
||||
to={route_to_page}
|
||||
query={Some(PageQuery{page: to_page})}
|
||||
>
|
||||
{ to_page }
|
||||
</Link<Route, PageQuery>>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn Links(props: &PropsNavigation) -> Html {
|
||||
const LINKS_PER_SIDE: usize = 3;
|
||||
|
||||
let PropsNavigation {
|
||||
page, total_pages, ..
|
||||
} = *props;
|
||||
|
||||
let pages_prev = page.checked_sub(1).unwrap_or_default() as usize;
|
||||
let pages_next = (total_pages - page) as usize;
|
||||
|
||||
let links_left = LINKS_PER_SIDE.min(pages_prev)
|
||||
// if there are less than `LINKS_PER_SIDE` to the right, we add some more on the left.
|
||||
+ LINKS_PER_SIDE.checked_sub(pages_next).unwrap_or_default();
|
||||
let links_right = 2 * LINKS_PER_SIDE - links_left;
|
||||
|
||||
html! {
|
||||
<>
|
||||
<RenderLinks range={ 1..page } len={pages_prev} max_links={links_left} props={props.clone()} />
|
||||
<RenderLink to_page={page} props={props.clone()} />
|
||||
<RenderLinks range={ page + 1..total_pages + 1 } len={pages_next} max_links={links_right} props={props.clone()} />
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn Pagination(props: &PropsNavigation) -> Html {
|
||||
html! {
|
||||
<nav class="pagination is-right" role="navigation" aria-label="pagination">
|
||||
<RelNavButtons ..{props.clone()} />
|
||||
<ul class="pagination-list">
|
||||
<Links ..{props.clone()} />
|
||||
</ul>
|
||||
</nav>
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn Nav() -> Html {
|
||||
let navbar_active = use_state_eq(|| false);
|
||||
|
||||
let toggle_navbar = {
|
||||
let navbar_active = navbar_active.clone();
|
||||
|
||||
Callback::from(move |_| {
|
||||
navbar_active.set(!*navbar_active);
|
||||
})
|
||||
};
|
||||
|
||||
let active_class = if !*navbar_active { "is-active" } else { "" };
|
||||
|
||||
html! {
|
||||
<nav class="navbar is-primary" role="navigation" aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<h1 class="navbar-item is-size-3">{ "Yew Blog" }</h1>
|
||||
|
||||
<button class={classes!("navbar-burger", "burger", active_class)}
|
||||
aria-label="menu" aria-expanded="false"
|
||||
onclick={toggle_navbar}
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class={classes!("navbar-menu", active_class)}>
|
||||
<div class="navbar-start">
|
||||
<Link<Route> classes={classes!("navbar-item")} to={Route::Entries}> // TODO: ...
|
||||
{ "Home" }
|
||||
</Link<Route>>
|
||||
<Link<Route> classes={classes!("navbar-item")} to={Route::Entries}>
|
||||
{ "Posts" }
|
||||
</Link<Route>>
|
||||
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<div class="navbar-link">
|
||||
{ "More" }
|
||||
</div>
|
||||
<div class="navbar-dropdown">
|
||||
<Link<Route> classes={classes!("navbar-item")} to={Route::Authors}>
|
||||
{ "Meet the authors" }
|
||||
</Link<Route>>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
use crate::Route;
|
||||
use yew::prelude::*;
|
||||
use yew_router::prelude::Link;
|
||||
|
||||
pub struct Landing;
|
||||
impl Component for Landing {
|
||||
type Message = ();
|
||||
type Properties = ();
|
||||
|
||||
fn create(_ctx: &Context<Self>) -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
fn view(&self, _ctx: &Context<Self>) -> Html {
|
||||
html! {
|
||||
<>
|
||||
<div class="tile is-parent container" style="
|
||||
margin: 0 !important;
|
||||
left: 0 !important;
|
||||
top: 0 !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
max-width: 100% !important;
|
||||
z-index: 2 !important;
|
||||
">
|
||||
{ self.view_background() }
|
||||
{ self.view_text() }
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Landing {
|
||||
fn view_background(&self) -> Html {
|
||||
html! {
|
||||
<>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.2" style="
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
z-index: 0 !important;
|
||||
backdrop-filter: blur(24px) !important;
|
||||
">
|
||||
<defs>
|
||||
<@{"linearGradient"} id="trans">
|
||||
<stop offset="0%" stop-color="#5BCEFA" />
|
||||
<stop offset="50%" stop-color="#F5A9B8" />
|
||||
<stop offset="100%" stop-color="#FFFFFF" />
|
||||
</@>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" x="0" y="0" rx="0" ry="0" fill="url(#trans)" fill-opacity="0.2" />
|
||||
</svg>
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
fn view_text(&self) -> Html {
|
||||
html! {
|
||||
<>
|
||||
<Link<Route> classes={classes!("navbar-item")} to={Route::About}><p style="
|
||||
display: flex !important;
|
||||
justify-content: center !important;
|
||||
align-items: center !important;
|
||||
height: calc(100vh - 16px - (var(--bulma-navbar-height) * 2)) !important;
|
||||
width: 100% !important;
|
||||
filter: url(post.bloom.svg#process)
|
||||
">{r"click to enter"}</p></Link<Route>>
|
||||
</>
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
pub mod landing;
|
||||
|
||||
pub mod about;
|
||||
pub mod blog;
|
||||
pub mod projects;
|
||||
|
||||
pub mod not_found;
|
||||
|
||||
@@ -12,7 +12,7 @@ impl Component for Projects {
|
||||
fn view(&self, _ctx: &Context<Self>) -> Html {
|
||||
html! {
|
||||
<>
|
||||
<div class="tile is-parent container mb-5 mt-5">
|
||||
<div class="tile is-parent container mb-5 mt-5" style="height: auto !important;">
|
||||
{ self.view_projects_ongoing() }
|
||||
{ self.view_projects_finished() }
|
||||
</div>
|
||||
@@ -27,13 +27,13 @@ impl Projects {
|
||||
<p class="title ml-2 is-size-4">{r#"ongoing projects"#}</p>
|
||||
<div class="columns is-size-7 ml-3 mr-3" style="margin-top: var(--bulma-block-spacing) !important;">
|
||||
<div class="column box mb-5 mr-1">
|
||||
<p class="subtitle is-inline-block mb-0"><a href="https://git.gay/luciel/app_catnip">
|
||||
<p class="subtitle is-inline-block mb-0"><a href="https://git.celesteflare.cc/i0uring/app_catnip">
|
||||
{r#"catnip"#}
|
||||
</a></p>
|
||||
<p class="content">{r#"all-rounder ide in the making"#}</p>
|
||||
</div>
|
||||
<div class="column box mb-5 ml-1">
|
||||
<p class="subtitle is-inline-block mb-0"><a href="https://git.gay/luciel/app_nekochat">
|
||||
<p class="subtitle is-inline-block mb-0"><a href="https://git.celesteflare.cc/i0uring/app_nekochat">
|
||||
{r#"neko chat"#}
|
||||
</a></p>
|
||||
<p class="content">{r#"my planned matrix client"#}</p>
|
||||
@@ -49,19 +49,25 @@ impl Projects {
|
||||
<p class="title ml-2 is-size-4">{r#"finished projects"#}</p>
|
||||
<div class="columns is-size-7 ml-3 mr-3">
|
||||
<div class="column box mb-5 mr-1">
|
||||
<p class="subtitle is-inline-block mb-0"><a href="https://git.gay/luciel/lib_tinyevents">
|
||||
<p class="subtitle is-inline-block mb-0"><a href="https://git.celesteflare.cc/i0uring/lib_tinyevents">
|
||||
{r#"tiny events"#}
|
||||
</a></p>
|
||||
<p class="content">{r#"a java seventeen (and up) event-system that is able to be scaled in large systems."#}</p>
|
||||
<p class="content">{r#"a java seventeen (and up) event-sys that is able to be scaled in large systems."#}</p>
|
||||
</div>
|
||||
<div class="column box mb-5 ml-1 mr-2">
|
||||
<p class="subtitle is-inline-block mb-0"><a href="https://git.gay/luciel/lib_swingify">
|
||||
<p class="subtitle is-inline-block mb-0"><a href="https://git.celesteflare.cc/i0uring/dotfiles">
|
||||
{r#"dotfiles"#}
|
||||
</a></p>
|
||||
<p class="content">{r#"my personal set of configurations for different things"#}</p>
|
||||
</div>
|
||||
<div class="column box mb-5 mr-1">
|
||||
<p class="subtitle is-inline-block mb-0"><a href="https://git.celesteflare.cc/i0uring/lib_swingify">
|
||||
{r#"swingify"#}
|
||||
</a></p>
|
||||
<p class="content">{r#"my java swing wrapper to simplify window creation for bogus-brains."#}</p>
|
||||
</div>
|
||||
<div class="column box mb-5 mr-1">
|
||||
<p class="subtitle is-inline-block mb-0"><a href="https://git.gay/luciel/mc_mod_mnet">
|
||||
<div class="column box mb-5 ml-1">
|
||||
<p class="subtitle is-inline-block mb-0"><a href="https://git.celesteflare.cc/stellaris/mod_mnet">
|
||||
{r#"modern netty"#}
|
||||
</a></p>
|
||||
<p class="content">{r#"fabric mod that adds experimental iouring and kqueue support."#}</p>
|
||||
|
||||