forked from lavender-legacy/lavender.software
		
	Compare commits
	
		
			26 commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 80ba6a1f02 | |||
| 2e6ca1a884 | |||
| a231108b9c | |||
| 74885b0410 | |||
| afccae891d | |||
| 027451fa6d | |||
| 59e9973a25 | |||
| 1e27c8ec39 | |||
| 4e7a5aefa7 | |||
| b6f992b46a | |||
| a777aea815 | |||
| e2f4635404 | |||
| 1e1fe5b82f | |||
| c32320fec4 | |||
| e9f60bf7e7 | |||
| 9bf90c9715 | |||
| 3e561b8474 | |||
| 4f40930dd5 | |||
| 26b30cd030 | |||
| 89f26b9a0e | |||
| 1e1dfbc18a | |||
| 0da2c0459d | |||
| 4b2d9f5d11 | |||
| 5e29b82c8d | |||
| ab9e7598be | |||
| 1e235dd0d1 | 
					 21 changed files with 746 additions and 569 deletions
				
			
		|  | @ -3,7 +3,7 @@ root = true | ||||||
| [*] | [*] | ||||||
| indent_style = space | indent_style = space | ||||||
| indent_size = 2 | indent_size = 2 | ||||||
| end_of_line = crlf | end_of_line = lf | ||||||
| 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,6 +89,15 @@ 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" | ||||||
|  | @ -416,6 +425,12 @@ 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" | ||||||
|  | @ -492,6 +507,7 @@ dependencies = [ | ||||||
|  "askama", |  "askama", | ||||||
|  "notify", |  "notify", | ||||||
|  "siru", |  "siru", | ||||||
|  |  "ssri", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
|  | @ -973,6 +989,18 @@ 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" | ||||||
|  | @ -1006,6 +1034,21 @@ 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" | ||||||
|  | @ -1080,6 +1123,26 @@ 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,3 +14,4 @@ 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,8 +2,23 @@ | ||||||
| 
 | 
 | ||||||
| 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 | ||||||
|  | @ -15,3 +30,5 @@ 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,11 +74,8 @@ 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(); | ||||||
| 
 | 
 | ||||||
|         loop { |         while rx.recv().is_ok() { | ||||||
|             match rx.recv() { |             build() | ||||||
|                 Ok(_) => build(), |  | ||||||
|                 Err(_) => break, |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,58 +1,13 @@ | ||||||
| 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…"); | ||||||
| 
 | 
 | ||||||
|     let members = [ |     ctx.write("index.html", MainPageTemplate {}.render()?)?; | ||||||
|         ("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,5 +1,7 @@ | ||||||
| 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( | ||||||
|  | @ -7,5 +9,15 @@ 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(()) | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										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 / { | ||||||
|  |   root /srv/http/lavender.software/; | ||||||
|  | 
 | ||||||
|  |   location = /webring/data.json { | ||||||
|  |     add_header Access-Control-Allow-Origin *; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | error_page 404 /404.html | ||||||
|  | @ -9,9 +9,29 @@ | ||||||
|     "name": "charlotte", |     "name": "charlotte", | ||||||
|     "url": "https://char.lt/" |     "url": "https://char.lt/" | ||||||
|   }, |   }, | ||||||
|  |   { | ||||||
|  |     "id": "milse113", | ||||||
|  |     "name": "milse113", | ||||||
|  |     "url": "https://milse113.github.io/lavender.html" | ||||||
|  |   }, | ||||||
|   { |   { | ||||||
|     "id": "mira", |     "id": "mira", | ||||||
|     "name": "mira", |     "name": "mira", | ||||||
|     "url": "https://boxin.space/" |     "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/" | ||||||
|   } |   } | ||||||
| ] | ] | ||||||
|  |  | ||||||
							
								
								
									
										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..."); | ||||||
|  |   } | ||||||
|  | })(); | ||||||
							
								
								
									
										52
									
								
								src/webring/webring-0.2.0.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/webring/webring-0.2.0.css
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,52 @@ | ||||||
|  | /* 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; | ||||||
|  | } | ||||||
							
								
								
									
										54
									
								
								src/webring/webring-0.2.0.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/webring/webring-0.2.0.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | ||||||
|  | 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); | ||||||
|  | })(); | ||||||
|  | @ -1,157 +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..."); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| })(); |  | ||||||
|  | @ -25,23 +25,13 @@ | ||||||
| 
 | 
 | ||||||
|         <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>more soon!</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>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