diff --git a/README.md b/README.md index e7c7db1..3140e7f 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,5 @@ dist/ $ git pull --rebase dist/ $ git push 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. diff --git a/build_src/assets.rs b/build_src/assets.rs index 66b9715..77ecb6b 100644 --- a/build_src/assets.rs +++ b/build_src/assets.rs @@ -1,21 +1,5 @@ -use std::{fs, path::Path}; - use crate::*; -fn copy_dir_recursive(src: impl AsRef, dst: impl AsRef) -> std::io::Result<()> { - fs::create_dir_all(&dst)?; - for entry in fs::read_dir(src)? { - let entry = entry?; - let ty = entry.file_type()?; - if ty.is_dir() { - copy_dir_recursive(entry.path(), dst.as_ref().join(entry.file_name()))?; - } else { - fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?; - } - } - Ok(()) -} - pub fn copy_assets(ctx: &BuildContext) -> Result<()> { log_info("Copying assets…"); copy_dir_recursive(ctx.source_dir.join("assets"), ctx.output_dir.join("assets"))?; diff --git a/build_src/main.rs b/build_src/main.rs index d717520..8716f44 100644 --- a/build_src/main.rs +++ b/build_src/main.rs @@ -1,10 +1,11 @@ use siru::prelude::*; -use std::{convert::TryInto, path::PathBuf, sync::Arc, time::Duration}; +use std::{convert::TryInto, fs, path::Path, path::PathBuf, sync::Arc, time::Duration}; type Result = std::result::Result>; mod assets; mod main_page; +mod webring; pub struct BuildContext { source_dir: PathBuf, @@ -26,6 +27,20 @@ impl SiruFS for BuildContext { } } +pub fn copy_dir_recursive(src: impl AsRef, dst: impl AsRef) -> std::io::Result<()> { + fs::create_dir_all(&dst)?; + for entry in fs::read_dir(src)? { + let entry = entry?; + let ty = entry.file_type()?; + if ty.is_dir() { + copy_dir_recursive(entry.path(), dst.as_ref().join(entry.file_name()))?; + } else { + fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?; + } + } + Ok(()) +} + fn build() { let ctx = BuildContext { source_dir: "src".try_into().unwrap(), @@ -35,13 +50,17 @@ fn build() { let ctx = Arc::new(ctx); - [main_page::main_page, assets::copy_assets] - .iter() - .map(|f| { - let ctx = Arc::clone(&ctx); - std::thread::spawn(move || f(&ctx).unwrap()) - }) - .for_each(|t| t.join().unwrap()); + [ + main_page::main_page, + assets::copy_assets, + webring::copy_webring, + ] + .iter() + .map(|f| { + let ctx = Arc::clone(&ctx); + std::thread::spawn(move || f(&ctx).unwrap()) + }) + .for_each(|t| t.join().unwrap()); } fn main() { diff --git a/build_src/webring.rs b/build_src/webring.rs new file mode 100644 index 0000000..7088e07 --- /dev/null +++ b/build_src/webring.rs @@ -0,0 +1,11 @@ +use crate::*; + +pub fn copy_webring(ctx: &BuildContext) -> Result<()> { + log_info("Copying webring…"); + copy_dir_recursive( + ctx.source_dir.join("webring"), + ctx.output_dir.join("webring"), + )?; + + Ok(()) +} diff --git a/nginx-site.conf b/nginx-site.conf new file mode 100644 index 0000000..d416970 --- /dev/null +++ b/nginx-site.conf @@ -0,0 +1,11 @@ +# assuming the dist repo lives at /srv/http/lavender.software + +location / { + alias /srv/http/lavender.software/; +} + +error_page 404 /404.html + +location = /webring/data.json { + add_header Access-Control-Allow-Origin *; +} diff --git a/src/webring/data.json b/src/webring/data.json new file mode 100644 index 0000000..1843063 --- /dev/null +++ b/src/webring/data.json @@ -0,0 +1,17 @@ +[ + { + "id": "annie", + "name": "annieversary", + "url": "https://versary.town/" + }, + { + "id": "charlotte", + "name": "charlotte", + "url": "https://char.lt/" + }, + { + "id": "mira", + "name": "mira", + "url": "https://boxin.space/" + } +] diff --git a/src/webring/webring-0.1.0.js b/src/webring/webring-0.1.0.js new file mode 100644 index 0000000..77c80de --- /dev/null +++ b/src/webring/webring-0.1.0.js @@ -0,0 +1,162 @@ +(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 = ` +
+
+

This website is a part of the Lavender Software webring

+
+ + + +
+
+
+`; + + 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..."); + } +})();