Compare commits
No commits in common. "main" and "main" have entirely different histories.
21 changed files with 569 additions and 746 deletions
|
@ -3,7 +3,7 @@ root = true
|
||||||
[*]
|
[*]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
end_of_line = lf
|
end_of_line = crlf
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
63
Cargo.lock
generated
63
Cargo.lock
generated
|
@ -89,15 +89,6 @@ version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "base64"
|
|
||||||
version = "0.10.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
|
||||||
dependencies = [
|
|
||||||
"byteorder",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
|
@ -425,12 +416,6 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hex"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "html5ever"
|
name = "html5ever"
|
||||||
version = "0.25.1"
|
version = "0.25.1"
|
||||||
|
@ -507,7 +492,6 @@ dependencies = [
|
||||||
"askama",
|
"askama",
|
||||||
"notify",
|
"notify",
|
||||||
"siru",
|
"siru",
|
||||||
"ssri",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -989,18 +973,6 @@ dependencies = [
|
||||||
"opaque-debug",
|
"opaque-debug",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sha2"
|
|
||||||
version = "0.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69"
|
|
||||||
dependencies = [
|
|
||||||
"block-buffer",
|
|
||||||
"digest",
|
|
||||||
"fake-simd",
|
|
||||||
"opaque-debug",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shell-words"
|
name = "shell-words"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -1034,21 +1006,6 @@ version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527"
|
checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ssri"
|
|
||||||
version = "7.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a9cec0d388f39fbe79d7aa600e8d38053bf97b1bc8d350da7c0ba800d0f423f2"
|
|
||||||
dependencies = [
|
|
||||||
"base64",
|
|
||||||
"digest",
|
|
||||||
"hex",
|
|
||||||
"serde",
|
|
||||||
"sha-1",
|
|
||||||
"sha2",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -1123,26 +1080,6 @@ dependencies = [
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror"
|
|
||||||
version = "1.0.30"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror-impl",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror-impl"
|
|
||||||
version = "1.0.30"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.44"
|
version = "0.1.44"
|
||||||
|
|
|
@ -14,4 +14,3 @@ path = "build_src/main.rs"
|
||||||
askama = "0.10.5"
|
askama = "0.10.5"
|
||||||
notify = "4.0.17"
|
notify = "4.0.17"
|
||||||
siru = { git = "https://github.com/videogame-hacker/siru.git" }
|
siru = { git = "https://github.com/videogame-hacker/siru.git" }
|
||||||
ssri = "7.0.0"
|
|
||||||
|
|
17
README.md
17
README.md
|
@ -2,23 +2,8 @@
|
||||||
|
|
||||||
Static site generated using [siru](https://github.com/videogame-hacker/siru) and hosted at [lavender.software](https://lavender.software/).
|
Static site generated using [siru](https://github.com/videogame-hacker/siru) and hosted at [lavender.software](https://lavender.software/).
|
||||||
|
|
||||||
## Setting Up
|
|
||||||
|
|
||||||
```shell
|
|
||||||
$ git clone 'git@lavender.software:lavender/lavender.software.git'
|
|
||||||
$ cd lavender.software/
|
|
||||||
lavender.software/ $ mkdir dist # or follow instructions in 'Deploying'
|
|
||||||
lavender.software/ $ cargo run
|
|
||||||
...
|
|
||||||
lavender.software/ $ # Built files are in dist/
|
|
||||||
```
|
|
||||||
|
|
||||||
You may want to `cd dist && python -m http.server` to get a local HTTP server.
|
|
||||||
|
|
||||||
## Deploying
|
## Deploying
|
||||||
|
|
||||||
**Note:** You don't need to do this unless you're the one deploying the site to the production environment.
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ # To set up, ensure that the 'dist' folder reflects the VPS
|
$ # To set up, ensure that the 'dist' folder reflects the VPS
|
||||||
$ git clone 'root@lavender.software:/srv/http/lavender.software' dist
|
$ git clone 'root@lavender.software:/srv/http/lavender.software' dist
|
||||||
|
@ -30,5 +15,3 @@ dist/ $ git pull --rebase
|
||||||
dist/ $ git push
|
dist/ $ git push
|
||||||
dist/ $ # Your changes should now be live at lavender.software
|
dist/ $ # Your changes should now be live at lavender.software
|
||||||
```
|
```
|
||||||
|
|
||||||
If deploying this site, you may also want to examine the sample `nginx-site.conf` file.
|
|
||||||
|
|
|
@ -74,8 +74,11 @@ fn main() {
|
||||||
let mut watcher = watcher(tx, Duration::from_millis(100)).unwrap();
|
let mut watcher = watcher(tx, Duration::from_millis(100)).unwrap();
|
||||||
watcher.watch("./src", RecursiveMode::Recursive).unwrap();
|
watcher.watch("./src", RecursiveMode::Recursive).unwrap();
|
||||||
|
|
||||||
while rx.recv().is_ok() {
|
loop {
|
||||||
build()
|
match rx.recv() {
|
||||||
|
Ok(_) => build(),
|
||||||
|
Err(_) => break,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,58 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
|
struct Member {
|
||||||
|
name: String,
|
||||||
|
website: String,
|
||||||
|
title: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&(&str, &str, &str)> for Member {
|
||||||
|
fn from(tuple: &(&str, &str, &str)) -> Self {
|
||||||
|
Member {
|
||||||
|
name: tuple.0.to_string(),
|
||||||
|
website: tuple.1.to_string(),
|
||||||
|
title: tuple.2.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "main_page.html.j2")]
|
#[template(path = "main_page.html.j2")]
|
||||||
struct MainPageTemplate {}
|
struct MainPageTemplate {
|
||||||
|
members: Vec<Member>,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main_page(ctx: &BuildContext) -> Result<()> {
|
pub fn main_page(ctx: &BuildContext) -> Result<()> {
|
||||||
log_info("Rendering main page…");
|
log_info("Rendering main page…");
|
||||||
|
|
||||||
ctx.write("index.html", MainPageTemplate {}.render()?)?;
|
let members = [
|
||||||
|
("charlotte som", "https://som.codes/", "founder"),
|
||||||
|
("agatha rose", "https://agatharose.dev/", "meow"),
|
||||||
|
("maya", "https://1312.gay/", "chief director of maya"),
|
||||||
|
(
|
||||||
|
"Luna Lulu",
|
||||||
|
"https://lunaisa.dev",
|
||||||
|
"critically acclaimed website maker",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"annie versario",
|
||||||
|
"https://annie.kitty.lgbt",
|
||||||
|
"regional marquee technician",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"The System",
|
||||||
|
"https://the-system.eu.org",
|
||||||
|
"lead systems specialist",
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
ctx.write(
|
||||||
|
"index.html",
|
||||||
|
MainPageTemplate {
|
||||||
|
members: members.iter().map(|x| x.into()).collect(),
|
||||||
|
}
|
||||||
|
.render()?,
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
use ssri::{Algorithm, IntegrityOpts};
|
|
||||||
|
|
||||||
pub fn copy_webring(ctx: &BuildContext) -> Result<()> {
|
pub fn copy_webring(ctx: &BuildContext) -> Result<()> {
|
||||||
log_info("Copying webring…");
|
log_info("Copying webring…");
|
||||||
copy_dir_recursive(
|
copy_dir_recursive(
|
||||||
|
@ -9,15 +7,5 @@ pub fn copy_webring(ctx: &BuildContext) -> Result<()> {
|
||||||
ctx.output_dir.join("webring"),
|
ctx.output_dir.join("webring"),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
log_info("Calculating webring integrity…");
|
|
||||||
let webring_content = ctx.read_bin("webring/webring-0.2.0.js")?;
|
|
||||||
let integrity = IntegrityOpts::new()
|
|
||||||
.algorithm(Algorithm::Sha512)
|
|
||||||
.algorithm(Algorithm::Sha1)
|
|
||||||
.chain(&webring_content)
|
|
||||||
.result();
|
|
||||||
|
|
||||||
ctx.write("webring/webring-0.2.0.js.integ.txt", integrity.to_string())?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
# assuming the dist repo lives at /srv/http/lavender.software
|
|
||||||
|
|
||||||
location / {
|
|
||||||
root /srv/http/lavender.software/;
|
|
||||||
|
|
||||||
location = /webring/data.json {
|
|
||||||
add_header Access-Control-Allow-Origin *;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
error_page 404 /404.html
|
|
|
@ -1,37 +1,17 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": "annie",
|
"id": "annie",
|
||||||
"name": "annieversary",
|
"name": "annieversary",
|
||||||
"url": "https://versary.town/"
|
"url": "https://versary.town/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "charlotte",
|
"id": "charlotte",
|
||||||
"name": "charlotte",
|
"name": "charlotte",
|
||||||
"url": "https://char.lt/"
|
"url": "https://char.lt/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "milse113",
|
"id": "mira",
|
||||||
"name": "milse113",
|
"name": "mira",
|
||||||
"url": "https://milse113.github.io/lavender.html"
|
"url": "https://boxin.space/"
|
||||||
},
|
}
|
||||||
{
|
|
||||||
"id": "mira",
|
|
||||||
"name": "mira",
|
|
||||||
"url": "https://boxin.space/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "oatmealine",
|
|
||||||
"name": "oatmealine",
|
|
||||||
"url": "https://oat.zone/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "maia",
|
|
||||||
"name": "maia",
|
|
||||||
"url": "https://maia.crimew.gay/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "easrng",
|
|
||||||
"name": "easrng",
|
|
||||||
"url": "https://easrng.net/"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,162 +0,0 @@
|
||||||
(function () {
|
|
||||||
function getUID() {
|
|
||||||
var array = new Uint8Array(8);
|
|
||||||
window.crypto.getRandomValues(array);
|
|
||||||
return Array.from(array)
|
|
||||||
.map((b) => b.toString(16).padStart(2, "0"))
|
|
||||||
.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
const params = document.currentScript.dataset;
|
|
||||||
const UID = getUID();
|
|
||||||
|
|
||||||
const css = `
|
|
||||||
#--lavender-cssreset-${UID} {
|
|
||||||
all: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
#--lavender-webring-container-${UID} {
|
|
||||||
background-color: rgb(28, 23, 36);
|
|
||||||
background-blend-mode: multiply;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
background-color: ${params.backgroundColor || "purple"};
|
|
||||||
color: ${params.textColor || "white"};
|
|
||||||
text-shadow: 0px 1px 1px ${params.textShadowColor || "black"};
|
|
||||||
padding: 1px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-family: sans-serif;
|
|
||||||
|
|
||||||
margin: 10px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#--lavender-webring-container-${UID} a {
|
|
||||||
color: inherit !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#--lavender-webring-container-${UID}::before {
|
|
||||||
display: block;
|
|
||||||
content: ' ';
|
|
||||||
top: 0; left: 0; bottom: 0; right: 0;
|
|
||||||
position: absolute;
|
|
||||||
box-sizing: border-box;
|
|
||||||
pointer-events: none;
|
|
||||||
border: 5px outset;
|
|
||||||
opacity: 0.25;
|
|
||||||
border-color: white black black white;
|
|
||||||
}
|
|
||||||
|
|
||||||
#--lavender-webring-container-${UID} #--lavender-webring-title-${UID} {
|
|
||||||
margin: 10px 10px 0px;
|
|
||||||
text-align: center;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
#--lavender-webring-container-${UID} #--lavender-webring-item-container-${UID} {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-around;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
#--lavender-webring-container-${UID} #--lavender-webring-item-container-${UID} {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#--lavender-webring-container-${UID} .--lavender-webring-items-${UID} {
|
|
||||||
font-size: 14px;
|
|
||||||
display: block;
|
|
||||||
text-align: center;
|
|
||||||
padding: 0px;
|
|
||||||
margin: 10px 10px 8px;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#--lavender-webring-container-${UID} #--lavender-webring-item-1-${UID}::before {
|
|
||||||
display: inline;
|
|
||||||
content: '\\2190\\00a0';
|
|
||||||
}
|
|
||||||
#--lavender-webring-container-${UID} #--lavender-webring-item-3-${UID}::after {
|
|
||||||
display: inline;
|
|
||||||
content: '\\00a0\\2192';
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const webring_content = `
|
|
||||||
<div id="--lavender-cssreset-${UID}">
|
|
||||||
<div id="--lavender-webring-container-${UID}">
|
|
||||||
<p id="--lavender-webring-title-${UID}">This website is a part of the Lavender Software webring</p>
|
|
||||||
<div id="--lavender-webring-item-container-${UID}">
|
|
||||||
<a class="--lavender-webring-items-${UID}" id="--lavender-webring-item-1-${UID}"></a>
|
|
||||||
<a class="--lavender-webring-items-${UID}" id="--lavender-webring-item-2-${UID}"></a>
|
|
||||||
<a class="--lavender-webring-items-${UID}" id="--lavender-webring-item-3-${UID}"></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
function renderIdx(data, element, idx) {
|
|
||||||
idx = (idx + data.length) % data.length;
|
|
||||||
|
|
||||||
datum = data[idx];
|
|
||||||
element.textContent = datum.name;
|
|
||||||
element.href = datum.url;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getElementByPostfixedId(path) {
|
|
||||||
return document.getElementById(path + "-" + UID);
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderContent(currentScript, data) {
|
|
||||||
const params = currentScript.dataset;
|
|
||||||
|
|
||||||
var headstyle = document.createElement("style");
|
|
||||||
headstyle.innerHTML = css;
|
|
||||||
document.head.appendChild(headstyle);
|
|
||||||
|
|
||||||
currentScript.insertAdjacentHTML("afterend", webring_content);
|
|
||||||
|
|
||||||
const container = getElementByPostfixedId("--lavender-webring-container");
|
|
||||||
|
|
||||||
const item1 = getElementByPostfixedId("--lavender-webring-item-1");
|
|
||||||
const item2 = getElementByPostfixedId("--lavender-webring-item-2");
|
|
||||||
const item3 = getElementByPostfixedId("--lavender-webring-item-3");
|
|
||||||
|
|
||||||
const id = params.siteId;
|
|
||||||
var idindex = -1;
|
|
||||||
|
|
||||||
for (var i = 0; i < data.length; i++) {
|
|
||||||
if (data[i].id == id) {
|
|
||||||
idindex = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idindex == -1) {
|
|
||||||
item2.textContent =
|
|
||||||
"this site was not found in the list. please check that you don't have any typos in the id!";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("hideTitle" in params) {
|
|
||||||
getElementByPostfixedId("--lavender-webring-title").style.display =
|
|
||||||
"none";
|
|
||||||
}
|
|
||||||
|
|
||||||
renderIdx(data, item1, idindex - 1);
|
|
||||||
renderIdx(data, item2, idindex);
|
|
||||||
renderIdx(data, item3, idindex + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentScript = document.currentScript;
|
|
||||||
if (currentScript) {
|
|
||||||
fetch("https://lavender.software/webring/data.json")
|
|
||||||
.then(function (response) {
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(function (data) {
|
|
||||||
renderContent(currentScript, data);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.log("cannot locate document.currentScript element. aborting...");
|
|
||||||
}
|
|
||||||
})();
|
|
|
@ -1,52 +0,0 @@
|
||||||
/* Feel free to style the webring however you like! */
|
|
||||||
|
|
||||||
.lavender-webring-container {
|
|
||||||
all: unset;
|
|
||||||
|
|
||||||
/*
|
|
||||||
assuming Linux users will have a preferable sans-serif font set in their browser,
|
|
||||||
everyone else gets a nice default
|
|
||||||
*/
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "SF Pro", "Segoe UI",
|
|
||||||
"Helvetica Neue", sans-serif;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
background-color: rgb(28, 23, 36);
|
|
||||||
color: rgb(234, 234, 248);
|
|
||||||
|
|
||||||
padding: 1em;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
font-size: 1.125rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lavender-webring-description {
|
|
||||||
margin-block-end: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lavender-webring-container a {
|
|
||||||
color: hsl(275, 57%, 68%);
|
|
||||||
text-decoration: none;
|
|
||||||
border-bottom: 1px solid hsl(275, 57%, 68%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.lavender-webring-site-links {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
||||||
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lavender-webring-prev-site a::before {
|
|
||||||
content: "←";
|
|
||||||
margin-inline-end: 1ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lavender-webring-next-site a::after {
|
|
||||||
content: "→";
|
|
||||||
margin-inline-start: 1ch;
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
const currentScript = document.currentScript;
|
|
||||||
const ctx = currentScript.dataset;
|
|
||||||
|
|
||||||
// charlotte's ad-hoc terse javascript framework!
|
|
||||||
const CSS_PREFIX = "lavender-webring";
|
|
||||||
const e = (tag, props = {}, children = []) => {
|
|
||||||
let element = Object.assign(document.createElement(tag), props);
|
|
||||||
element.append(...children);
|
|
||||||
return element;
|
|
||||||
};
|
|
||||||
const t = (text) => document.createTextNode(text);
|
|
||||||
const c = (className) => ({ className: `${CSS_PREFIX}-${className}` });
|
|
||||||
const h = (href) => ({ href });
|
|
||||||
|
|
||||||
const createDescriptionContent = () =>
|
|
||||||
ctx.description != null
|
|
||||||
? [t(ctx.description)]
|
|
||||||
: [
|
|
||||||
t("This site is part of the "),
|
|
||||||
e("a", h("https://lavender.software"), [t("lavender.software")]),
|
|
||||||
t(" webring!"),
|
|
||||||
];
|
|
||||||
|
|
||||||
const renderWebring = (currSite, prevSite, nextSite) => {
|
|
||||||
currentScript.replaceWith(
|
|
||||||
e("aside", c("container"), [
|
|
||||||
e("section", c("description"), createDescriptionContent()),
|
|
||||||
e("ul", c("site-links"), [
|
|
||||||
e("li", c("prev-site"), [e("a", h(prevSite.url), [t(prevSite.name)])]),
|
|
||||||
e("li", c("curr-site"), [e("a", h(currSite.url), [t(currSite.name)])]),
|
|
||||||
e("li", c("next-site"), [e("a", h(nextSite.url), [t(nextSite.name)])]),
|
|
||||||
]),
|
|
||||||
])
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
const data = await fetch("https://lavender.software/webring/data.json").then(
|
|
||||||
(r) => r.json()
|
|
||||||
);
|
|
||||||
|
|
||||||
let thisSiteIdx = data.findIndex((site) => site.id == ctx.siteId);
|
|
||||||
if (thisSiteIdx === -1) {
|
|
||||||
throw new Error(
|
|
||||||
`Could not find site by id '${ctx.siteId}' in the webring!`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let currSite = data[thisSiteIdx];
|
|
||||||
let prevSite = data[(thisSiteIdx + data.length - 1) % data.length];
|
|
||||||
let nextSite = data[(thisSiteIdx + 1) % data.length];
|
|
||||||
|
|
||||||
renderWebring(currSite, prevSite, nextSite);
|
|
||||||
})();
|
|
157
src/webring/webring.js
Normal file
157
src/webring/webring.js
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
(function() {
|
||||||
|
function getUID() {
|
||||||
|
var array = new Uint8Array(8);
|
||||||
|
window.crypto.getRandomValues(array);
|
||||||
|
return Array.from(array).map(b => b.toString(16).padStart(2, "0")).join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = document.currentScript.dataset;
|
||||||
|
const UID = getUID();
|
||||||
|
|
||||||
|
const css = `
|
||||||
|
#--lavender-cssreset-${UID} {
|
||||||
|
all: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#--lavender-webring-container-${UID} {
|
||||||
|
background-color: rgb(28, 23, 36);
|
||||||
|
background-blend-mode: multiply;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
background-color: ${params.backgroundColor || "purple"};
|
||||||
|
color: ${params.textColor || "white"};
|
||||||
|
text-shadow: 0px 1px 1px ${params.textShadowColor || "black"};
|
||||||
|
padding: 1px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
|
||||||
|
margin: 10px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#--lavender-webring-container-${UID} a {
|
||||||
|
color: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#--lavender-webring-container-${UID}::before {
|
||||||
|
display: block;
|
||||||
|
content: ' ';
|
||||||
|
top: 0; left: 0; bottom: 0; right: 0;
|
||||||
|
position: absolute;
|
||||||
|
box-sizing: border-box;
|
||||||
|
pointer-events: none;
|
||||||
|
border: 5px outset;
|
||||||
|
opacity: 0.25;
|
||||||
|
border-color: white black black white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#--lavender-webring-container-${UID} #--lavender-webring-title-${UID} {
|
||||||
|
margin: 10px 10px 0px;
|
||||||
|
text-align: center;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
#--lavender-webring-container-${UID} #--lavender-webring-item-container-${UID} {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
#--lavender-webring-container-${UID} #--lavender-webring-item-container-${UID} {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#--lavender-webring-container-${UID} .--lavender-webring-items-${UID} {
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 10px 10px 8px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#--lavender-webring-container-${UID} #--lavender-webring-item-1-${UID}::before {
|
||||||
|
display: inline;
|
||||||
|
content: '\\2190\\00a0';
|
||||||
|
}
|
||||||
|
#--lavender-webring-container-${UID} #--lavender-webring-item-3-${UID}::after {
|
||||||
|
display: inline;
|
||||||
|
content: '\\00a0\\2192';
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const webring_content = `
|
||||||
|
<div id="--lavender-cssreset-${UID}">
|
||||||
|
<div id="--lavender-webring-container-${UID}">
|
||||||
|
<p id="--lavender-webring-title-${UID}">This website is a part of the Lavender Software webring</p>
|
||||||
|
<div id="--lavender-webring-item-container-${UID}">
|
||||||
|
<a class="--lavender-webring-items-${UID}" id="--lavender-webring-item-1-${UID}"></a>
|
||||||
|
<a class="--lavender-webring-items-${UID}" id="--lavender-webring-item-2-${UID}"></a>
|
||||||
|
<a class="--lavender-webring-items-${UID}" id="--lavender-webring-item-3-${UID}"></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
function renderIdx(data, element, idx) {
|
||||||
|
idx = (idx + data.length) % data.length;
|
||||||
|
|
||||||
|
datum = data[idx];
|
||||||
|
element.textContent = datum.name;
|
||||||
|
element.href = datum.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getElementByPostfixedId(path) {
|
||||||
|
return document.getElementById(path + "-" + UID);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderContent(currentScript, data) {
|
||||||
|
const params = currentScript.dataset;
|
||||||
|
|
||||||
|
var headstyle = document.createElement('style');
|
||||||
|
headstyle.innerHTML = css;
|
||||||
|
document.head.appendChild(headstyle);
|
||||||
|
|
||||||
|
currentScript.insertAdjacentHTML("afterend", webring_content);
|
||||||
|
|
||||||
|
const container = getElementByPostfixedId('--lavender-webring-container');
|
||||||
|
|
||||||
|
const item1 = getElementByPostfixedId('--lavender-webring-item-1');
|
||||||
|
const item2 = getElementByPostfixedId('--lavender-webring-item-2');
|
||||||
|
const item3 = getElementByPostfixedId('--lavender-webring-item-3');
|
||||||
|
|
||||||
|
const id = params.siteId;
|
||||||
|
var idindex = -1;
|
||||||
|
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
if (data[i].id == id) {
|
||||||
|
idindex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idindex == -1) {
|
||||||
|
item2.textContent = "this site was not found in the list. please check that you don't have any typos in the id!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("hideTitle" in params) {
|
||||||
|
getElementByPostfixedId('--lavender-webring-title').style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
renderIdx(data, item1, idindex - 1);
|
||||||
|
renderIdx(data, item2, idindex);
|
||||||
|
renderIdx(data, item3, idindex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentScript = document.currentScript;
|
||||||
|
if (currentScript) {
|
||||||
|
fetch("https://lavender.software/webring/data.json").then(function(response) {
|
||||||
|
return response.json();
|
||||||
|
}).then(function(data) {
|
||||||
|
renderContent(currentScript, data);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log("cannot locate document.currentScript element. aborting...");
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
|
@ -25,13 +25,23 @@
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://git.lain.faith/videogame-hacker/discord-css-injector">lavender cord</a> - a theming platform for Discord</li>
|
<li><a href="https://git.lain.faith/videogame-hacker/discord-css-injector">lavender cord</a> - a theming platform for Discord</li>
|
||||||
<li><a href="https://git.lavender.software/lavender/watch-party">watch-party</a> - a webapp to allow for synced video playback among friends</li>
|
<li>more soon!</li>
|
||||||
<li>catsette <em>(upcoming)</em> - an independent music marketplace platform for artists</li>
|
|
||||||
<li>Hermes <em>(upcoming)</em> - a native <a href="https://scuttlebutt.nz/">Secure Scuttlebutt</a> client for Linux</li>
|
|
||||||
<li>… and more soon!</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<section>
|
||||||
|
<h2>who are we?</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{% for member in members %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ member.website }}">{{ member.name }}</a> - {{ member.title }}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</section> -->
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h2>services</h2>
|
<h2>services</h2>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue