Added preferences and preference management.
This commit adds a few fancy flourishes, including ASCII art and 1337 themes. This is managed by a few, suitably skinned, form elements, some javascript and judicious use of the localStorage web API.
This commit is contained in:
parent
d3ca53795d
commit
a0d8ca002d
|
@ -4,7 +4,7 @@
|
|||
<meta charset="UTF-8">
|
||||
<title>Dakota's tilde.club</title>
|
||||
<link rel="stylesheet" type="text/css" href="tilde.css" media="screen" />
|
||||
<script src="tilde.js" async defer crossorigin="anonymous"></script>
|
||||
<script src="tilde.js" async defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
|
@ -15,12 +15,14 @@
|
|||
<li><a href="#bash">Fun bash one liners</a></li>
|
||||
<li>
|
||||
<a href="#readings">Readings</a>:
|
||||
<a href="#2020">2020</a>
|
||||
<a href="#2019">2019</a>
|
||||
<a href="#2018">2018</a>
|
||||
<a href="#2017">2017</a>
|
||||
<a href="#2016">2016</a>
|
||||
<a href="#2015">2015</a>
|
||||
<ul>
|
||||
<li><a href="#2020">2020</a></li>
|
||||
<li><a href="#2019">2019</a></li>
|
||||
<li><a href="#2018">2018</a></li>
|
||||
<li><a href="#2017">2017</a></li>
|
||||
<li><a href="#2016">2016</a></li>
|
||||
<li><a href="#2015">2015</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
</header>
|
||||
|
@ -28,36 +30,53 @@
|
|||
<section id="about">
|
||||
<h1>About</h1>
|
||||
This is Dakota's tilde.club page.
|
||||
<h2>Preferences</h2>
|
||||
<ul id="preferences">
|
||||
<li>
|
||||
<input type="checkbox" id="pref-force" />
|
||||
<label for="pref-force">Force mode</label>
|
||||
<input type="radio" id="pref-theme-dark" name="pref-theme" value="dark" />
|
||||
<label for="pref-theme-dark">Dark</label>
|
||||
<input type="radio" id="pref-theme-light" name="pref-theme" value="light" />
|
||||
<label for="pref-theme-light">Light</label>
|
||||
<input type="radio" id="pref-theme-h4x0r" name="pref-theme" value="h4x0r" />
|
||||
<label for="pref-theme-h4x0r">h4x0r</label>
|
||||
</li>
|
||||
<li>
|
||||
<input type="checkbox" id="pref-ascii" />
|
||||
<label for="pref-ascii">Intensified ASCII aesthetics.</label>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr />
|
||||
<section id="bash">
|
||||
<h1>Fun bash one liners</h1>
|
||||
<dl>
|
||||
<dt>Print a few random numbers</dt>
|
||||
<dd>od -d < /dev/random | awk '{ print $2 }' | head</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>A simple awk for isolating columns</dt>
|
||||
<dd>awk '{print $2}'</dd>
|
||||
<dt>Remove all tab characters</dt>
|
||||
<dd>tr -d '\t'</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Find lines containing literal tabs</dt>
|
||||
<dd>awk '/\t/'</dd>
|
||||
<dd>grep -P</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Remove all tab characters</dt>
|
||||
<dd>tr -d '\t'</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Join files using a tab separator</dt>
|
||||
<dd>join -t $'\t' file1 file2</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>A simple awk for isolating columns</dt>
|
||||
<dd>awk '{print $2}'</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Simple system benchmarks</dt>
|
||||
<dd>yes | sed '=' | sed '/y/d'</dd>
|
||||
<dd>time seq -n 1e6</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Print a few random numbers</dt>
|
||||
<dd>od -d < /dev/random | awk '{ print $2 }' | head</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>What shell am I using?</dt>
|
||||
<dd>lsof -p $$</dd>
|
||||
|
|
161
tilde.css
161
tilde.css
|
@ -1,3 +1,164 @@
|
|||
/* Default color schemes */
|
||||
:root {
|
||||
--bg: #fff;
|
||||
--fg: #000;
|
||||
--font-size: 18px;
|
||||
--link: #00f;
|
||||
--link-visited: #519;
|
||||
}
|
||||
|
||||
/* Dark mode */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #334;
|
||||
--fg: #fff;
|
||||
--font-size: 18px;
|
||||
--link: #0bf;
|
||||
--link-visited: #b4d;
|
||||
}
|
||||
}
|
||||
|
||||
/* Other themes */
|
||||
.dark {
|
||||
--bg: #334;
|
||||
--fg: #fff;
|
||||
--link: #0bf;
|
||||
--link-visited: #b4d;
|
||||
}
|
||||
|
||||
.h4x0r {
|
||||
--bg: #000;
|
||||
--fg: #0f0;
|
||||
--link: #0ff;
|
||||
--link-visited: #f0f;
|
||||
}
|
||||
|
||||
.light {
|
||||
--bg: #fff;
|
||||
--fg: #000;
|
||||
--link: #00f;
|
||||
--link-visited: #519;
|
||||
}
|
||||
|
||||
/* Apply themes */
|
||||
* {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--bg);
|
||||
color: var(--fg);
|
||||
font-size: var(--font-size);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link);
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: var(--link-visited);
|
||||
}
|
||||
|
||||
/* ASCII aesthetics */
|
||||
hr {
|
||||
border: none;
|
||||
}
|
||||
|
||||
hr:after {
|
||||
content: "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
|
||||
}
|
||||
|
||||
input[type=checkbox], input[type=radio] {
|
||||
background-color: var(--bg);
|
||||
color: var(--fg);
|
||||
font-size: var(--font-size);
|
||||
left: -1000px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
position: relative;
|
||||
top: -5px;
|
||||
width: 3ch;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
input[type=checkbox]:after, input[type=radio]:after {
|
||||
left: 1000px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
input[type=checkbox]:after {
|
||||
content: "[ ]";
|
||||
}
|
||||
|
||||
input[type=checkbox]:checked:after {
|
||||
content: "[x]";
|
||||
}
|
||||
|
||||
input[type=radio]:after {
|
||||
content: "( )";
|
||||
}
|
||||
|
||||
input[type=radio]:checked:after {
|
||||
content: "(o)";
|
||||
}
|
||||
|
||||
header, section {
|
||||
max-width: 80ch;
|
||||
}
|
||||
|
||||
ul#preferences {
|
||||
padding-inline-start: 0px;
|
||||
}
|
||||
|
||||
/* ASCII aesthetics intensifies */
|
||||
body.ascii h1 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
body.ascii h1:before {
|
||||
font-size: var(--font-size);
|
||||
position: absolute;
|
||||
right: 0ch;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
body.ascii header h1:before {
|
||||
content: "\
|
||||
___ ___ ___\A\
|
||||
/ | / | / - \\\A\
|
||||
/ /] | / /] | / __ \\\A\
|
||||
/_____/ /_____/ /_____/\A";
|
||||
top: calc(-1*var(--font-size));
|
||||
}
|
||||
|
||||
body.ascii #about h1:before {
|
||||
content: "\
|
||||
╔═╗┌┐ ┌─┐┬ ┬┌┬┐\A\
|
||||
╠═╣├┴┐│ ││ │ │\A\
|
||||
╩ ╩└─┘└─┘└─┘ ┴\A";
|
||||
line-height: 1;
|
||||
top: calc(-1*var(--font-size));
|
||||
}
|
||||
|
||||
body.ascii #bash h1:before {
|
||||
content: "\
|
||||
____ ____ ____ ____\A\
|
||||
||b |||a |||s |||h ||\A\
|
||||
||__|||__|||__|||__||\A\
|
||||
|/__\\|/__\\|/__\\|/__\\|\A";
|
||||
top: calc(-2*var(--font-size));
|
||||
}
|
||||
|
||||
body.ascii #readings h1:before {
|
||||
content: '\
|
||||
ooooooooo. .o8 o8o\A\
|
||||
`888 `Y88. "888 `"`\A\
|
||||
888 .d88` .ooooo. .oooo. .oooo888 oooo ooo. .oo. .oooooooo .oooo.o\A\
|
||||
888ooo88P` d88` `88b `P )88b d88` `888 `888 `888P"Y88b 888` `88b d88( "8\A\
|
||||
888`88b. 888ooo888 .oP"888 888 888 888 888 888 888 888 `"Y88b.\A\
|
||||
888 `88b. 888 .o d8( 888 888 888 888 888 888 `88bod8P` o. )88b\A\
|
||||
o888o o888o `Y8bod8P` `Y888""8o `Y8bod88P" o888o o888o o888o `8oooooo. 8""888P`\A\
|
||||
d" YD\A\
|
||||
"Y88888P\A';
|
||||
transform: translateX(20ch) translateY(calc(-3*var(--font-size))) scale(.5);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
(() => {
|
||||
/* DOM */
|
||||
const ascii = document.getElementById('pref-ascii');
|
||||
const force = document.getElementById('pref-force');
|
||||
const themeRadios = document.getElementsByName('pref-theme');
|
||||
const bodyClass = document.body.classList;
|
||||
|
||||
/* localStorage management */
|
||||
const lsn = "~ddb:"; // localStorage namespace
|
||||
const getPref = (pref) => localStorage.getItem(lsn + pref);
|
||||
const setPref = (pref, value) => localStorage.setItem(lsn + pref, value);
|
||||
const getPrefs = () => ({
|
||||
prefASCII: getPref('ascii') === 'true',
|
||||
prefForce: getPref('force') === 'true',
|
||||
prefTheme: getPref('theme') || 'dark',
|
||||
});
|
||||
|
||||
/* Update the state of the document based on client preferences. */
|
||||
const renderPreferences = () => {
|
||||
const { prefASCII, prefForce, prefTheme } = getPrefs();
|
||||
if(prefASCII) {
|
||||
bodyClass.add('ascii');
|
||||
ascii.checked = "checked";
|
||||
}
|
||||
if(prefForce) {
|
||||
bodyClass.add(prefTheme);
|
||||
force.checked = "checked";
|
||||
}
|
||||
themeRadios.forEach(radio => {
|
||||
if(radio.value === prefTheme) {
|
||||
radio.checked = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
renderPreferences();
|
||||
|
||||
/* ASCII aesthetic intensifies */
|
||||
ascii.onchange = (evt) => {
|
||||
const { prefASCII } = getPrefs();
|
||||
bodyClass.toggle('ascii');
|
||||
setPref('ascii', (!prefASCII).toString());
|
||||
};
|
||||
|
||||
/* Manage theme forcing behavior */
|
||||
const themes = Array.from(themeRadios).map(radio => radio.value);
|
||||
force.onchange = () => {
|
||||
const { prefForce, prefTheme } = getPrefs();
|
||||
const nextForce = !prefForce;
|
||||
themes.forEach(theme => bodyClass.remove(theme));
|
||||
if (nextForce) {
|
||||
bodyClass.add(prefTheme);
|
||||
}
|
||||
setPref('force', nextForce.toString())
|
||||
};
|
||||
|
||||
/* Manage theme selection */
|
||||
themeRadios.forEach(radio => radio.onchange = () => {
|
||||
const { prefForce } = getPrefs();
|
||||
setPref('theme', radio.value);
|
||||
if(prefForce) {
|
||||
themes.forEach(theme => bodyClass.remove(theme));
|
||||
bodyClass.add(radio.value);
|
||||
}
|
||||
});
|
||||
})()
|
Loading…
Reference in New Issue