mirror of
https://github.com/jbowdre/runtimeterror.git
synced 2025-02-17 08:04:38 +00:00
Compare commits
3 commits
42dabaa2f4
...
739e21645b
Author | SHA1 | Date | |
---|---|---|---|
739e21645b | |||
a318d91ed2 | |||
797560c7a3 |
7 changed files with 160 additions and 142 deletions
20
assets/js/theme-song.js
Normal file
20
assets/js/theme-song.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
// retreives the latest link from a musicthread thread and displays it on the page
|
||||
const themeSongScript = document.currentScript
|
||||
const urlParams = new URLSearchParams(themeSongScript.src.split('.js')[1])
|
||||
const params = Object.fromEntries(urlParams.entries())
|
||||
|
||||
if (params.id)
|
||||
{
|
||||
const musicthread = `https://musicthread.app/api/v0/thread/${params.id}`
|
||||
fetch(musicthread)
|
||||
.then((response) => response.json())
|
||||
.then((thread) => {
|
||||
let themeSong = thread.links[0]
|
||||
console.log(themeSong)
|
||||
themeSongContainer = document.createElement('div')
|
||||
themeSongContainer.className = 'theme-song'
|
||||
themeSongContainer.style
|
||||
themeSongContainer.innerHTML = `<a href="${themeSong.page_url}"><img src="${themeSong.thumbnail_url}"></a><br><a href="${themeSong.page_url}">${themeSong.title}</a><br><i>${themeSong.artist}</i>`
|
||||
themeSongScript.parentNode.insertBefore(themeSongContainer, themeSongScript)
|
||||
})
|
||||
}
|
|
@ -28,168 +28,140 @@ SOFTWARE.
|
|||
*/
|
||||
|
||||
function num_between(min, max) {
|
||||
return Math.floor(Math.random() * (max- min + 1) + min);
|
||||
return Math.floor(Math.random() * (max- min + 1) + min);
|
||||
}
|
||||
|
||||
function chance(val) {
|
||||
if(num_between(0, 100) < val) return true;
|
||||
else return false;
|
||||
if(num_between(0, 100) < val) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
var typos = {
|
||||
q:['w','a'],
|
||||
w:['q','r','s'],
|
||||
e:['w','d','r'],
|
||||
r:['e','f','t'],
|
||||
t:['r','g','y'],
|
||||
y:['t','h','u'],
|
||||
u:['y','j','i'],
|
||||
i:['u','k','o'],
|
||||
o:['i','l','p'],
|
||||
p:['o',';','['],
|
||||
a:['q','s','z'],
|
||||
s:['w','a','x','d'],
|
||||
d:['e','s','c','f'],
|
||||
f:['r','d','v','g'],
|
||||
g:['t','f','b','h'],
|
||||
h:['y','g','n','j'],
|
||||
j:['u','h','m','k'],
|
||||
k:['i','j',',','l'],
|
||||
l:['o','k','.',';'],
|
||||
z:['a','x'],
|
||||
x:['z','s','c'],
|
||||
c:['x','d','v'],
|
||||
v:['c','f','b'],
|
||||
b:['v','g','n'],
|
||||
n:['b','h','m'],
|
||||
m:['n','j',','],
|
||||
q:['w','a'],
|
||||
w:['q','r','s'],
|
||||
e:['w','d','r'],
|
||||
r:['e','f','t'],
|
||||
t:['r','g','y'],
|
||||
y:['t','h','u'],
|
||||
u:['y','j','i'],
|
||||
i:['u','k','o'],
|
||||
o:['i','l','p'],
|
||||
p:['o',';','['],
|
||||
a:['q','s','z'],
|
||||
s:['w','a','x','d'],
|
||||
d:['e','s','c','f'],
|
||||
f:['r','d','v','g'],
|
||||
g:['t','f','b','h'],
|
||||
h:['y','g','n','j'],
|
||||
j:['u','h','m','k'],
|
||||
k:['i','j',',','l'],
|
||||
l:['o','k','.',';'],
|
||||
z:['a','x'],
|
||||
x:['z','s','c'],
|
||||
c:['x','d','v'],
|
||||
v:['c','f','b'],
|
||||
b:['v','g','n'],
|
||||
n:['b','h','m'],
|
||||
m:['n','j',','],
|
||||
}
|
||||
|
||||
async function typo(element, text) {
|
||||
var buffer = '';
|
||||
var typo_active = false;
|
||||
var tag_active = false;
|
||||
var typing_typos = (element.dataset.typoChance) ? element.dataset.typoChance : 10;
|
||||
var typing_speed = (element.dataset.typingDelay) ? element.dataset.typingDelay : 50;
|
||||
var typing_jitter = (element.dataset.typingJitter) ? element.dataset.typingJitter : 15;
|
||||
var buffer = '';
|
||||
var typo_active = false;
|
||||
var typing_typos = (element.dataset.typoChance) ? element.dataset.typoChance : 10;
|
||||
var typing_speed = (element.dataset.typingDelay) ? element.dataset.typingDelay : 50;
|
||||
var typing_jitter = (element.dataset.typingJitter) ? element.dataset.typingJitter : 15;
|
||||
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
// Get the letter that we're supposed to type
|
||||
letter = text.charAt(i);
|
||||
|
||||
// Get the letter that we’re supposed to type
|
||||
letter = text.charAt(i);
|
||||
// Trigger a typo
|
||||
if(chance(typing_typos) && typo_active === false && i > 1 && i < text.length - 3) {
|
||||
if(typeof typos[letter] !== 'undefined') {
|
||||
// Swap the letter with a random typo
|
||||
typo = typos[letter][Math.floor(Math.random() * typos[letter].length)];
|
||||
|
||||
// TODO: actual support for html or markup or whatever
|
||||
// Append the letter to the buffer
|
||||
buffer = buffer + typo;
|
||||
|
||||
/*
|
||||
// Handle elements/markup
|
||||
if(letter == '<' && (
|
||||
text.charAt(i+1) == 's' ||
|
||||
text.charAt(i+1) == 'p' ||
|
||||
text.charAt(i+1) == 'a' ||
|
||||
text.charAt(i+1) == '/' ||
|
||||
text.charAt(i+1) == 'i')
|
||||
) {
|
||||
tag_active = true;
|
||||
}
|
||||
// Write the buffer
|
||||
element.innerHTML = buffer;
|
||||
|
||||
if(tag_active) {
|
||||
typo_active = true;
|
||||
var seed = num_between(2,5); // Reduced max seed to ensure correction
|
||||
realization_delay = seed;
|
||||
realization_delay_counter = seed;
|
||||
}
|
||||
}
|
||||
|
||||
buffer = buffer + letter;
|
||||
element.innerHTML = buffer;
|
||||
// Append the letter to the buffer
|
||||
buffer = buffer + letter;
|
||||
|
||||
if(letter == '>' && (
|
||||
text.charAt(i-1) == 'n' ||
|
||||
text.charAt(i-1) == 'a' ||
|
||||
text.charAt(i-1) == 'p' ||
|
||||
text.charAt(i+1) == '"' ||
|
||||
text.charAt(i+1) == '/')
|
||||
) {
|
||||
tag_active = false;
|
||||
await sleep(typing_speed);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
// Write the buffer
|
||||
element.innerHTML = buffer;
|
||||
|
||||
// Trigger a typo
|
||||
if(chance(typing_typos) && typo_active === false && i > 1) {
|
||||
// Typical typing speed
|
||||
var speed_lower = parseFloat(typing_speed) - parseInt(typing_jitter);
|
||||
var speed_upper = parseFloat(typing_speed) + parseInt(typing_jitter);
|
||||
|
||||
if(typeof typos[letter] !== 'undefined') {
|
||||
delay = num_between(speed_lower,speed_upper);
|
||||
|
||||
// Swap the letter with a random typo
|
||||
typo = typos[letter][Math.floor(Math.random() * typos[letter].length)];
|
||||
// Chance of longer delay though
|
||||
if(chance(5)) delay = num_between(100, 200);
|
||||
await sleep(delay);
|
||||
|
||||
// Append the letter to the buffer
|
||||
buffer = buffer + typo;
|
||||
if(typo_active) {
|
||||
realization_delay_counter--;
|
||||
|
||||
// Write the buffer
|
||||
element.innerHTML = buffer;
|
||||
if(realization_delay_counter == 0) {
|
||||
for (var k = 0; k < seed+1; k++) {
|
||||
// Pause at realization of typo
|
||||
await sleep(typing_jitter);
|
||||
|
||||
typo_active = true;
|
||||
var seed = num_between(2,5);
|
||||
realization_delay = seed;
|
||||
realization_delay_counter = seed;
|
||||
}
|
||||
}
|
||||
// Rewind the buffer!
|
||||
buffer = buffer.substring(0, buffer.length - 1);
|
||||
|
||||
// Append the letter to the buffer
|
||||
buffer = buffer + letter;
|
||||
// Write rewound buffer
|
||||
element.innerHTML = buffer;
|
||||
|
||||
// Write the buffer
|
||||
element.innerHTML = buffer;
|
||||
// Brief pause before continuing
|
||||
await sleep(30);
|
||||
}
|
||||
|
||||
// Typical typing speed
|
||||
var speed_lower = parseFloat(typing_speed) - parseInt(typing_jitter);
|
||||
var speed_upper = parseFloat(typing_speed) + parseInt(typing_jitter);
|
||||
typo_active = false;
|
||||
|
||||
delay = num_between(speed_lower,speed_upper);
|
||||
// Add the letters back
|
||||
i = i - seed;
|
||||
await sleep(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Chance of longer delay though
|
||||
if(chance(5)) delay = num_between(100, 200);
|
||||
await sleep(delay);
|
||||
// Ensure any remaining typo is corrected
|
||||
if(typo_active) {
|
||||
await sleep(typing_jitter * 2);
|
||||
for (var k = 0; k < seed+1; k++) {
|
||||
buffer = buffer.substring(0, buffer.length - 1);
|
||||
element.innerHTML = buffer;
|
||||
await sleep(30);
|
||||
}
|
||||
for (var k = 0; k < seed; k++) {
|
||||
buffer += text.charAt(text.length - seed + k);
|
||||
element.innerHTML = buffer;
|
||||
await sleep(typing_speed);
|
||||
}
|
||||
}
|
||||
|
||||
if(typo_active) {
|
||||
|
||||
realization_delay_counter--;
|
||||
|
||||
if(realization_delay_counter == 0) {
|
||||
|
||||
for (var k = 0; k < seed+1; k++) {
|
||||
|
||||
// Pause at realization of typo
|
||||
await sleep(typing_jitter);
|
||||
|
||||
// Rewind the buffer!
|
||||
buffer = buffer.substring(0, buffer.length - 1);
|
||||
|
||||
// Write rewound buffer
|
||||
element.innerHTML = buffer;
|
||||
|
||||
// Brief pause before continuing
|
||||
await sleep(30);
|
||||
}
|
||||
|
||||
typo_active = false;
|
||||
|
||||
// Add the letters back
|
||||
i = i - seed;
|
||||
await sleep(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Whatever you do here will happen when the typing is finished
|
||||
//do_something();
|
||||
|
||||
return new Promise(resolve => setTimeout(resolve, 1));
|
||||
return new Promise(resolve => setTimeout(resolve, 1));
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var element = document.getElementById('tagline');
|
||||
var text = element.innerHTML;
|
||||
typo(element, text);
|
||||
var element = document.getElementById('tagline');
|
||||
var text = element.innerHTML;
|
||||
typo(element, text);
|
||||
});
|
|
@ -14,6 +14,9 @@ darkVisitors = [
|
|||
"AI Search Crawler"
|
||||
]
|
||||
|
||||
omgUser = "jbowdre"
|
||||
musicThreadId = "2aVjZUocjk96LELFbV5JvJjm14v"
|
||||
|
||||
# Comments
|
||||
analytics = true
|
||||
reply = true
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: "/changelog"
|
||||
date: "2024-05-26T21:19:08Z"
|
||||
lastmod: "2024-07-30T01:49:28Z"
|
||||
lastmod: "2024-08-02T21:16:14Z"
|
||||
description: "Maybe I should keep a log of all my site-related tinkering?"
|
||||
featured: false
|
||||
toc: false
|
||||
|
@ -10,6 +10,10 @@ categories: slashes
|
|||
---
|
||||
*High-level list of config/layout changes to the site. The full changelog is of course [on GitHub](https://github.com/jbowdre/runtimeterror/commits/main/).*
|
||||
|
||||
**2024-08-02:**
|
||||
- Display "pinned" recent track in sidebar using [MusicThread](https://musicthread.app) instead of latest scrobble
|
||||
- Tweak Typo behavior to avoid uncorrected mistakes near the end of the string
|
||||
|
||||
**2024-07-29:**
|
||||
- Build `robots.txt` dynamically with [Dark Visitors API](https://darkvisitors.com/) and code from [Luke Harris](https://www.lkhrs.com/blog/2024/darkvisitors-hugo/)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: "/colophon"
|
||||
date: "2024-05-26T22:30:58Z"
|
||||
lastmod: "2024-07-31T22:01:11Z"
|
||||
lastmod: "2024-08-02T21:16:41Z"
|
||||
description: "There's a lot that goes into this site. Let me tell you how it works."
|
||||
featured: false
|
||||
toc: true
|
||||
|
@ -17,6 +17,8 @@ categories: slashes
|
|||
- provides site search with [lunr](https://lunrjs.com/) based on an implementation detailed by [Victoria Drake](https://victoria.dev/blog/add-search-to-hugo-static-sites-with-lunr/).
|
||||
- uses [Dark Visitors](https://darkvisitors.com/docs/robots-txt)'s API to dynamically generate a [robots.txt](/robots.txt) discouraging AI scrapers with some Hugo code from [Luke Harris](https://github.com/lkhrs/hugo-dark-visitors).
|
||||
- leverages [Cabin](https://withcabin.com) for [privacy-friendly](https://withcabin.com/privacy/runtimeterror.dev) analytics.
|
||||
- fetches recently-played music from [MusicThread](https://musicthread.app/).
|
||||
- displays my latest status from [omg.lol](https://home.omg.lol/referred-by/jbowdre).
|
||||
- resolves via [Bunny DNS](https://bunny.net/dns/).
|
||||
- is published to / hosted on [Bunny Storage](https://bunny.net/storage/) and [Bunny CDN](https://bunny.net/cdn/) with a [GitHub Actions workflow](//further-down-the-bunny-hole/).
|
||||
- has a [Gemini](https://geminiprotocol.net) mirror at `gemini://gmi.runtimeterror.dev`. This is generated from a [Hugo gemtext post layout](https://github.com/jbowdre/runtimeterror/blob/main/layouts/_default/single.gmi), deployed to a [Vultr](https://www.vultr.com/) VPS through that same GitHub Actions workflow, and served with [Agate](https://github.com/mbrubeck/agate).
|
||||
|
|
|
@ -51,10 +51,15 @@
|
|||
{{- end }}
|
||||
</ul>
|
||||
{{- end }}
|
||||
{{ with .Site.Params.omgUser }}
|
||||
<hr>
|
||||
<h3>status.lol</h3>
|
||||
<script src="https://status.lol/jbowdre.js?time&link&fluent&pretty"></script>
|
||||
<script src="https://status.lol/{{ . }}.js?time&link&fluent&pretty"></script>
|
||||
{{ end }}
|
||||
{{ with .Site.Params.musicThreadId }}
|
||||
<hr>
|
||||
<h3>latest track</h3>
|
||||
<script src="https://recentfm.rknight.me/now.js?u=pushpianotire&e=🎶"></script>
|
||||
<h3>current theme song</h3>
|
||||
{{ $jsThemeSong := resources.Get "js/theme-song.js" | minify }}
|
||||
<script src="{{ $jsThemeSong.RelPermalink }}?id={{ . }}"></script>
|
||||
{{ end }}
|
||||
|
||||
|
|
|
@ -238,16 +238,28 @@ small[style^="opacity: .5"] {
|
|||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
/* recentfm styling */
|
||||
.recent-played {
|
||||
/* theme song styling */
|
||||
.theme-song {
|
||||
background: var(--off-bg) !important;
|
||||
flex-direction:column;
|
||||
border-radius: 0.5em;
|
||||
padding: 0.5em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.7rem;
|
||||
font-size: 0.9rem;
|
||||
line-height: 0.9rem;
|
||||
}
|
||||
|
||||
.recent-played-track {
|
||||
margin: 0.5em 0;
|
||||
.theme-song img {
|
||||
width: 14rem;
|
||||
height: auto;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
@media (min-width: 45rem) {
|
||||
.theme-song img {
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
/* code overrides */
|
||||
|
|
Loading…
Reference in a new issue