Merge pull request 'lavender.software webring' (#2) from patch/webring into main
Reviewed-on: lavender/lavender.software#2
This commit is contained in:
		
						commit
						1e1dfbc18a
					
				
					 7 changed files with 230 additions and 24 deletions
				
			
		|  | @ -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. | ||||
|  |  | |||
|  | @ -1,21 +1,5 @@ | |||
| use std::{fs, path::Path}; | ||||
| 
 | ||||
| use crate::*; | ||||
| 
 | ||||
| fn copy_dir_recursive(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> 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"))?; | ||||
|  |  | |||
|  | @ -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<T> = std::result::Result<T, Box<dyn std::error::Error>>; | ||||
| 
 | ||||
| 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<Path>, dst: impl AsRef<Path>) -> 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() { | ||||
|  |  | |||
							
								
								
									
										11
									
								
								build_src/webring.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								build_src/webring.rs
									
									
									
									
									
										Normal file
									
								
							|  | @ -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(()) | ||||
| } | ||||
							
								
								
									
										11
									
								
								nginx-site.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								nginx-site.conf
									
									
									
									
									
										Normal file
									
								
							|  | @ -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 *; | ||||
| } | ||||
							
								
								
									
										17
									
								
								src/webring/data.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/webring/data.json
									
									
									
									
									
										Normal file
									
								
							|  | @ -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/" | ||||
|     } | ||||
| ] | ||||
							
								
								
									
										162
									
								
								src/webring/webring-0.1.0.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								src/webring/webring-0.1.0.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -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 = ` | ||||
| <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..."); | ||||
|   } | ||||
| })(); | ||||
		Loading…
	
		Reference in a new issue