First commit
This commit is contained in:
commit
75562787a2
0
.gitmodules
vendored
Normal file
0
.gitmodules
vendored
Normal file
0
.hugo_build.lock
Normal file
0
.hugo_build.lock
Normal file
6
archetypes/default.md
Normal file
6
archetypes/default.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
title: "{{ replace .Name "-" " " | title }}"
|
||||||
|
date: {{ .Date }}
|
||||||
|
draft: true
|
||||||
|
---
|
||||||
|
|
15
config.toml
Normal file
15
config.toml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
baseURL = "https://nathan.freedomland.xyz"
|
||||||
|
languageCode = "en-us"
|
||||||
|
title = "Blog"
|
||||||
|
theme = "lekh"
|
||||||
|
|
||||||
|
[params]
|
||||||
|
Name = "Nathan Moll"
|
||||||
|
About = ""
|
||||||
|
Email = ""
|
||||||
|
Resume = "" # Add the filename with file extension.
|
||||||
|
PostLimit = 4 # Sets the number of posts to display on the front page
|
||||||
|
|
||||||
|
[[params.profiles]]
|
||||||
|
name = "Gitea"
|
||||||
|
url = "https://git.freedomland.xyz/darthmoll12"
|
5
content/posts/_index.md
Normal file
5
content/posts/_index.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
+++
|
||||||
|
title = "Nathan's Blog Posts"
|
||||||
|
+++
|
||||||
|
|
||||||
|
We can add some content
|
7
content/posts/first.md
Normal file
7
content/posts/first.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: "First post ever!!!!"
|
||||||
|
tags: ["test", "test2"]
|
||||||
|
categories: ["announcements"]
|
||||||
|
---
|
||||||
|
|
||||||
|
This is my first post and it's useless!!! :D :D :D
|
0
layouts/page/contact.html
Normal file
0
layouts/page/contact.html
Normal file
0
layouts/page/single.html
Normal file
0
layouts/page/single.html
Normal file
20
public/404.html
Normal file
20
public/404.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>404 Page Not Found | My New Hugo Site</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
|
<link rel="stylesheet" href="/css/fonts.css">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p> This page does not exist or as they say, it's a 404 error</p>
|
||||||
|
<p> If you can't find what you're looking for, it's better to sometimes look inside </p>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
43
public/categories/index.html
Normal file
43
public/categories/index.html
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title>Categories | My New Hugo Site</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
|
<link rel="stylesheet" href="/css/fonts.css">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header class="site-header">
|
||||||
|
<div class="wrapper">
|
||||||
|
<a class="muted small" href="http://example.org/"></a>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>
|
||||||
|
Categories
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/dark.js" defer="" ></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
10
public/categories/index.xml
Normal file
10
public/categories/index.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
|
<channel>
|
||||||
|
<title>Categories on My New Hugo Site</title>
|
||||||
|
<link>http://example.org/categories/</link>
|
||||||
|
<description>Recent content in Categories on My New Hugo Site</description>
|
||||||
|
<generator>Hugo -- gohugo.io</generator>
|
||||||
|
<language>en-us</language><atom:link href="http://example.org/categories/index.xml" rel="self" type="application/rss+xml" />
|
||||||
|
</channel>
|
||||||
|
</rss>
|
33
public/css/fonts.css
Normal file
33
public/css/fonts.css
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/* Monospace */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Source Code Pro Light';
|
||||||
|
src: url('../assets/fonts/SourceCodePro-Light.otf');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Regular */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Calendas Plus';
|
||||||
|
src: url('../assets/fonts/calendas_plus-webfont.eot');
|
||||||
|
src: url('../assets/fonts/calendas_plus-webfont.eot?#iefix') format('embedded-opentype'),
|
||||||
|
url('../assets/fonts/calendas_plus-webfont.woff2') format('woff2'),
|
||||||
|
url('../assets/fonts/calendas_plus-webfont.woff') format('woff'),
|
||||||
|
url('../assets/fonts/calendas_plus-webfont.ttf') format('truetype'),
|
||||||
|
url('../assets/fonts/calendas_plus-webfont.svg#calendas_plusregular') format('svg');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bold */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Calendas Plus';
|
||||||
|
src: url('../assets/fonts/calendas_plus_bold-webfont.eot');
|
||||||
|
src: url('../assets/fonts/calendas_plus_bold-webfont.eot?#iefix') format('embedded-opentype'),
|
||||||
|
url('../assets/fonts/calendas_plus_bold-webfont.woff2') format('woff2'),
|
||||||
|
url('../assets/fonts/calendas_plus_bold-webfont.woff') format('woff'),
|
||||||
|
url('../assets/fonts/calendas_plus_bold-webfont.ttf') format('truetype'),
|
||||||
|
url('../assets/fonts/calendas_plus_bold-webfont.svg#calendas_plusbold') format('svg');
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
57
public/css/style.css
Normal file
57
public/css/style.css
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
|
||||||
|
line-height: 1.5em;
|
||||||
|
font-size: 1.1em;
|
||||||
|
color: #222;
|
||||||
|
max-width: 70%;
|
||||||
|
padding: 2rem;
|
||||||
|
margin: auto;
|
||||||
|
background: #fafafa;
|
||||||
|
overscroll-behavior-y: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%; }
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #0074D9; }
|
||||||
|
|
||||||
|
h1, h2, strong {
|
||||||
|
color: #111; }
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.6em; }
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2em; }
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1em; }
|
||||||
|
|
||||||
|
.muted {
|
||||||
|
color: #aaa;
|
||||||
|
text-decoration: none; }
|
||||||
|
|
||||||
|
.small {
|
||||||
|
font-size: .8em; }
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: 0px;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
highlight {
|
||||||
|
}
|
||||||
|
|
||||||
|
pre code span span{
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.taglist {
|
||||||
|
border: solid;
|
||||||
|
border-weight: 2pt;
|
||||||
|
padding: 4pt;
|
||||||
|
}
|
53
public/index.html
Normal file
53
public/index.html
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta name="generator" content="Hugo 0.92.2" />
|
||||||
|
<title>My New Hugo Site</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
|
<link rel="stylesheet" href="/css/fonts.css">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1></h1>
|
||||||
|
<h4></h4>
|
||||||
|
|
||||||
|
<div></div>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td><i class="fas fa-file-alt" aria-hidden="true"></i></td>
|
||||||
|
<td> <a href="/resume/" target="_blank">Resume</a></td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td><i class="fas fa-envelope" aria-hidden="true"></i></td>
|
||||||
|
<td> <code></code></td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>Posts</h3>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h3><a href="posts/">View all posts</a></h3>
|
||||||
|
<h3><a href="categories/"> View all categories</a></h3>
|
||||||
|
<h3><a href="tags/"> View all tags</a></h3>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script src="/js/dark.js" defer="" ></script>
|
||||||
|
</html>
|
19
public/index.xml
Normal file
19
public/index.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
|
<channel>
|
||||||
|
<title>My New Hugo Site</title>
|
||||||
|
<link>http://example.org/</link>
|
||||||
|
<description>Recent content on My New Hugo Site</description>
|
||||||
|
<generator>Hugo -- gohugo.io</generator>
|
||||||
|
<language>en-us</language><atom:link href="http://example.org/index.xml" rel="self" type="application/rss+xml" />
|
||||||
|
<item>
|
||||||
|
<title></title>
|
||||||
|
<link>http://example.org/contact/</link>
|
||||||
|
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
|
||||||
|
|
||||||
|
<guid>http://example.org/contact/</guid>
|
||||||
|
<description>layout = &lsquo;contact&rsquo; title = &lsquo;Contact&rsquo;</description>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
</channel>
|
||||||
|
</rss>
|
440
public/js/dark.js
Normal file
440
public/js/dark.js
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
// darkmode.js: Javascript library for controlling page appearance, toggling between regular white and 'dark mode'
|
||||||
|
// Author: Said Achmiz
|
||||||
|
// Date: 2020-03-20
|
||||||
|
// When: Time-stamp: "2020-03-23 09:36:20 gwern"
|
||||||
|
// license: PD
|
||||||
|
// Author: Judah Sotomayor
|
||||||
|
// Date: 2023-10-15
|
||||||
|
// When: <2023-10-15 Sun 18:37>
|
||||||
|
|
||||||
|
/* For gwern.net, the default white-black */
|
||||||
|
/* scheme is 'light', and it can be flipped to a 'dark' scheme fairly easily by inverting it; the main visual problem is */
|
||||||
|
/* that blockquotes appear to become much harder to see & image-focus.js doesn't work well without additional tweaks. */
|
||||||
|
/* Known bugs: images get inverted on zoom or hover; invert filters are slow, leading to 'janky' slow rendering on scrolling. */
|
||||||
|
|
||||||
|
/****************/
|
||||||
|
/* MISC HELPERS */
|
||||||
|
/****************/
|
||||||
|
|
||||||
|
/* Given an HTML string, creates an element from that HTML, adds it to
|
||||||
|
#ui-elements-container (creating the latter if it does not exist), and
|
||||||
|
returns the created element.
|
||||||
|
*/
|
||||||
|
function addUIElement(element_html) {
|
||||||
|
var ui_elements_container = document.getElementById('ui-elements-container');
|
||||||
|
if (!ui_elements_container) {
|
||||||
|
ui_elements_container = document.createElement("div");
|
||||||
|
ui_elements_container.id = "ui-elements-container";
|
||||||
|
document.querySelector("body").appendChild(ui_elements_container);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_elements_container.insertAdjacentHTML("beforeend", element_html);
|
||||||
|
return ui_elements_container.lastElementChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof window.GW == "undefined")
|
||||||
|
window.GW = { };
|
||||||
|
GW.temp = { };
|
||||||
|
|
||||||
|
if (GW.mediaQueries == null)
|
||||||
|
GW.mediaQueries = { };
|
||||||
|
GW.mediaQueries.mobileNarrow = matchMedia("(max-width: 520px)");
|
||||||
|
GW.mediaQueries.mobileWide = matchMedia("(max-width: 900px)");
|
||||||
|
GW.mediaQueries.mobileMax = matchMedia("(max-width: 960px)");
|
||||||
|
GW.mediaQueries.hover = matchMedia("only screen and (hover: hover) and (pointer: fine)");
|
||||||
|
GW.mediaQueries.systemDarkModeActive = matchMedia("(prefers-color-scheme: dark)");
|
||||||
|
|
||||||
|
GW.modeOptions = [
|
||||||
|
[ 'auto', 'Auto', 'Set light or dark mode automatically, according to system-wide setting' ],
|
||||||
|
[ 'light', 'Light', 'Light mode at all times' ],
|
||||||
|
[ 'dark', 'Dark', 'Dark mode at all times' ]
|
||||||
|
];
|
||||||
|
GW.modeStyles = `
|
||||||
|
:root {
|
||||||
|
--GW-blockquote-background-color: #ddd
|
||||||
|
}
|
||||||
|
body::before,
|
||||||
|
body > * {
|
||||||
|
filter: invert(90%)
|
||||||
|
}
|
||||||
|
body::before {
|
||||||
|
content: '';
|
||||||
|
width: 100vw;
|
||||||
|
height: 100%;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
z-index: -1
|
||||||
|
}
|
||||||
|
img,
|
||||||
|
video {
|
||||||
|
filter: invert(100%);
|
||||||
|
}
|
||||||
|
#markdownBody, #mode-selector button {
|
||||||
|
text-shadow: 0 0 0 #000
|
||||||
|
}
|
||||||
|
article > :not(#TOC) a:link {
|
||||||
|
text-shadow:
|
||||||
|
0 0 #777,
|
||||||
|
.03em 0 #fff,
|
||||||
|
-.03em 0 #fff,
|
||||||
|
0 .03em #fff,
|
||||||
|
0 -.03em #fff,
|
||||||
|
.06em 0 #fff,
|
||||||
|
-.06em 0 #fff,
|
||||||
|
.09em 0 #fff,
|
||||||
|
-.09em 0 #fff,
|
||||||
|
.12em 0 #fff,
|
||||||
|
-.12em 0 #fff,
|
||||||
|
.15em 0 #fff,
|
||||||
|
-.15em 0 #fff
|
||||||
|
}
|
||||||
|
article > :not(#TOC) blockquote a:link {
|
||||||
|
text-shadow:
|
||||||
|
0 0 #777,
|
||||||
|
.03em 0 var(--GW-blockquote-background-color),
|
||||||
|
-.03em 0 var(--GW-blockquote-background-color),
|
||||||
|
0 .03em var(--GW-blockquote-background-color),
|
||||||
|
0 -.03em var(--GW-blockquote-background-color),
|
||||||
|
.06em 0 var(--GW-blockquote-background-color),
|
||||||
|
-.06em 0 var(--GW-blockquote-background-color),
|
||||||
|
.09em 0 var(--GW-blockquote-background-color),
|
||||||
|
-.09em 0 var(--GW-blockquote-background-color),
|
||||||
|
.12em 0 var(--GW-blockquote-background-color),
|
||||||
|
-.12em 0 var(--GW-blockquote-background-color),
|
||||||
|
.15em 0 var(--GW-blockquote-background-color),
|
||||||
|
-.15em 0 var(--GW-blockquote-background-color)
|
||||||
|
}
|
||||||
|
#logo img {
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
#mode-selector {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
#mode-selector:hover {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/****************/
|
||||||
|
/* DEBUG OUTPUT */
|
||||||
|
/****************/
|
||||||
|
|
||||||
|
function GWLog (string) {
|
||||||
|
if (GW.loggingEnabled || localStorage.getItem("logging-enabled") == "true")
|
||||||
|
console.log(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********/
|
||||||
|
/* HELPERS */
|
||||||
|
/***********/
|
||||||
|
|
||||||
|
/* Run the given function immediately if the page is already loaded, or add
|
||||||
|
a listener to run it as soon as the page loads.
|
||||||
|
*/
|
||||||
|
function doWhenPageLoaded(f) {
|
||||||
|
if (document.readyState == "complete")
|
||||||
|
f();
|
||||||
|
else
|
||||||
|
window.addEventListener("load", f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adds an event listener to a button (or other clickable element), attaching
|
||||||
|
it to both "click" and "keyup" events (for use with keyboard navigation).
|
||||||
|
Optionally also attaches the listener to the 'mousedown' event, making the
|
||||||
|
element activate on mouse down instead of mouse up.
|
||||||
|
*/
|
||||||
|
Element.prototype.addActivateEvent = function(func, includeMouseDown) {
|
||||||
|
let ael = this.activateEventListener = (event) => { if (event.button === 0 || event.key === ' ') func(event) };
|
||||||
|
if (includeMouseDown) this.addEventListener("mousedown", ael);
|
||||||
|
this.addEventListener("click", ael);
|
||||||
|
this.addEventListener("keyup", ael);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adds a scroll event listener to the page.
|
||||||
|
*/
|
||||||
|
function addScrollListener(fn, name) {
|
||||||
|
let wrapper = (event) => {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
fn(event);
|
||||||
|
document.addEventListener("scroll", wrapper, { once: true, passive: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
document.addEventListener("scroll", wrapper, { once: true, passive: true });
|
||||||
|
|
||||||
|
// Retain a reference to the scroll listener, if a name is provided.
|
||||||
|
if (typeof name != "undefined")
|
||||||
|
GW[name] = wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************/
|
||||||
|
/* ACTIVE MEDIA QUERIES */
|
||||||
|
/************************/
|
||||||
|
|
||||||
|
/* This function provides two slightly different versions of its functionality,
|
||||||
|
depending on how many arguments it gets.
|
||||||
|
|
||||||
|
If one function is given (in addition to the media query and its name), it
|
||||||
|
is called whenever the media query changes (in either direction).
|
||||||
|
|
||||||
|
If two functions are given (in addition to the media query and its name),
|
||||||
|
then the first function is called whenever the media query starts matching,
|
||||||
|
and the second function is called whenever the media query stops matching.
|
||||||
|
|
||||||
|
If you want to call a function for a change in one direction only, pass an
|
||||||
|
empty closure (NOT null!) as one of the function arguments.
|
||||||
|
|
||||||
|
There is also an optional fifth argument. This should be a function to be
|
||||||
|
called when the active media query is canceled.
|
||||||
|
*/
|
||||||
|
function doWhenMatchMedia(mediaQuery, name, ifMatchesOrAlwaysDo, otherwiseDo = null, whenCanceledDo = null) {
|
||||||
|
if (typeof GW.mediaQueryResponders == "undefined")
|
||||||
|
GW.mediaQueryResponders = { };
|
||||||
|
|
||||||
|
let mediaQueryResponder = (event, canceling = false) => {
|
||||||
|
if (canceling) {
|
||||||
|
GWLog(`Canceling media query “${name}â€`);
|
||||||
|
|
||||||
|
if (whenCanceledDo != null)
|
||||||
|
whenCanceledDo(mediaQuery);
|
||||||
|
} else {
|
||||||
|
let matches = (typeof event == "undefined") ? mediaQuery.matches : event.matches;
|
||||||
|
|
||||||
|
GWLog(`Media query “${name}†triggered (matches: ${matches ? "YES" : "NO"})`);
|
||||||
|
|
||||||
|
if (otherwiseDo == null || matches) ifMatchesOrAlwaysDo(mediaQuery);
|
||||||
|
else otherwiseDo(mediaQuery);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mediaQueryResponder();
|
||||||
|
mediaQuery.addListener(mediaQueryResponder);
|
||||||
|
|
||||||
|
GW.mediaQueryResponders[name] = mediaQueryResponder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Deactivates and discards an active media query, after calling the function
|
||||||
|
that was passed as the whenCanceledDo parameter when the media query was
|
||||||
|
added.
|
||||||
|
*/
|
||||||
|
function cancelDoWhenMatchMedia(name) {
|
||||||
|
GW.mediaQueryResponders[name](null, true);
|
||||||
|
|
||||||
|
for ([ key, mediaQuery ] of Object.entries(GW.mediaQueries))
|
||||||
|
mediaQuery.removeListener(GW.mediaQueryResponders[name]);
|
||||||
|
|
||||||
|
GW.mediaQueryResponders[name] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************/
|
||||||
|
/* MODE SELECTION */
|
||||||
|
/******************/
|
||||||
|
|
||||||
|
function injectModeSelector() {
|
||||||
|
GWLog("injectModeSelector");
|
||||||
|
|
||||||
|
// Get saved mode setting (or default).
|
||||||
|
let currentMode = localStorage.getItem("selected-mode") || 'auto';
|
||||||
|
|
||||||
|
// Inject the mode selector widget and activate buttons.
|
||||||
|
let modeSelector = addUIElement(
|
||||||
|
"<div id='mode-selector'>" +
|
||||||
|
String.prototype.concat.apply("", GW.modeOptions.map(modeOption => {
|
||||||
|
let [ name, label, desc ] = modeOption;
|
||||||
|
let selected = (name == currentMode ? ' selected' : '');
|
||||||
|
let disabled = (name == currentMode ? ' disabled' : '');
|
||||||
|
return `<button type='button' class='select-mode-${name}${selected}'${disabled} tabindex='-1' data-name='${name}' title='${desc}'>${label}</button>`})) +
|
||||||
|
"</div>");
|
||||||
|
|
||||||
|
modeSelector.querySelectorAll("button").forEach(button => {
|
||||||
|
button.addActivateEvent(GW.modeSelectButtonClicked = (event) => {
|
||||||
|
GWLog("GW.modeSelectButtonClicked");
|
||||||
|
|
||||||
|
// Determine which setting was chosen (i.e., which button was clicked).
|
||||||
|
let selectedMode = event.target.dataset.name;
|
||||||
|
|
||||||
|
// Save the new setting.
|
||||||
|
if (selectedMode == "auto") localStorage.removeItem("selected-mode");
|
||||||
|
else localStorage.setItem("selected-mode", selectedMode);
|
||||||
|
|
||||||
|
// Actually change the mode.
|
||||||
|
setMode(selectedMode);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelector("head").insertAdjacentHTML("beforeend", `<style id='mode-selector-styles'>
|
||||||
|
#mode-selector {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
padding: 0.125em 0.25em;
|
||||||
|
border: 3px solid transparent;
|
||||||
|
opacity: 0.3;
|
||||||
|
transition:
|
||||||
|
opacity 2s ease;
|
||||||
|
}
|
||||||
|
#mode-selector.hidden {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
#mode-selector:hover {
|
||||||
|
transition: none;
|
||||||
|
opacity: 1.0;
|
||||||
|
}
|
||||||
|
#mode-selector button {
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 0.5em;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1;
|
||||||
|
font-family: Lucida Sans Unicode, Source Sans Pro, Helvetica, Trebuchet MS, sans-serif;
|
||||||
|
font-size: 0.99rem;
|
||||||
|
text-align: center;
|
||||||
|
color: #000;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
#mode-selector button:hover,
|
||||||
|
#mode-selector button.selected {
|
||||||
|
box-shadow:
|
||||||
|
0 2px 0 6px #fff inset,
|
||||||
|
0 1px 0 6px currentColor inset;
|
||||||
|
}
|
||||||
|
#mode-selector button:not(:disabled):hover {
|
||||||
|
color: #000;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#mode-selector button:not(:disabled):active {
|
||||||
|
transform: translateY(2px);
|
||||||
|
box-shadow:
|
||||||
|
0 0px 0 6px #fff inset,
|
||||||
|
0 -1px 0 6px currentColor inset;
|
||||||
|
}
|
||||||
|
#mode-selector button.active:not(:hover)::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0.25em;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
border-bottom: 1px dotted currentColor;
|
||||||
|
width: 25%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
</style>`);
|
||||||
|
|
||||||
|
document.querySelector("head").insertAdjacentHTML("beforeend", `<style id='mode-styles'></style>`);
|
||||||
|
|
||||||
|
setMode(currentMode);
|
||||||
|
|
||||||
|
// We pre-query the relevant elements, so we don’t have to run queryAll on
|
||||||
|
// every firing of the scroll listener.
|
||||||
|
GW.scrollState = {
|
||||||
|
"lastScrollTop": window.pageYOffset || document.documentElement.scrollTop,
|
||||||
|
"unbrokenDownScrollDistance": 0,
|
||||||
|
"unbrokenUpScrollDistance": 0,
|
||||||
|
"modeSelector": document.querySelectorAll("#mode-selector"),
|
||||||
|
};
|
||||||
|
addScrollListener(updateModeSelectorVisibility, "updateModeSelectorVisibilityScrollListener");
|
||||||
|
GW.scrollState.modeSelector[0].addEventListener("mouseover", () => { showModeSelector(); });
|
||||||
|
doWhenMatchMedia(GW.mediaQueries.systemDarkModeActive, "updateModeSelectorStateForSystemDarkMode", () => { updateModeSelectorState(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show/hide the mode selector in response to scrolling.
|
||||||
|
|
||||||
|
Called by the ‘updateModeSelectorVisibilityScrollListener’ scroll listener.
|
||||||
|
*/
|
||||||
|
function updateModeSelectorVisibility(event) {
|
||||||
|
GWLog("updateModeSelectorVisibility");
|
||||||
|
|
||||||
|
let newScrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
||||||
|
GW.scrollState.unbrokenDownScrollDistance = (newScrollTop > GW.scrollState.lastScrollTop) ?
|
||||||
|
(GW.scrollState.unbrokenDownScrollDistance + newScrollTop - GW.scrollState.lastScrollTop) :
|
||||||
|
0;
|
||||||
|
GW.scrollState.unbrokenUpScrollDistance = (newScrollTop < GW.scrollState.lastScrollTop) ?
|
||||||
|
(GW.scrollState.unbrokenUpScrollDistance + GW.scrollState.lastScrollTop - newScrollTop) :
|
||||||
|
0;
|
||||||
|
GW.scrollState.lastScrollTop = newScrollTop;
|
||||||
|
|
||||||
|
// Hide mode selector when scrolling a full page down.
|
||||||
|
if (GW.scrollState.unbrokenDownScrollDistance > window.innerHeight) {
|
||||||
|
hideModeSelector();
|
||||||
|
}
|
||||||
|
|
||||||
|
// On desktop, show mode selector when scrolling to top of page,
|
||||||
|
// or a full page up.
|
||||||
|
// On mobile, show mode selector on ANY scroll up.
|
||||||
|
if (GW.mediaQueries.mobileNarrow.matches) {
|
||||||
|
if (GW.scrollState.unbrokenUpScrollDistance > 0 || GW.scrollState.lastScrollTop <= 0)
|
||||||
|
showModeSelector();
|
||||||
|
} else if ( GW.scrollState.unbrokenUpScrollDistance > window.innerHeight
|
||||||
|
|| GW.scrollState.lastScrollTop == 0) {
|
||||||
|
showModeSelector();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideModeSelector() {
|
||||||
|
GWLog("hideModeSelector");
|
||||||
|
|
||||||
|
GW.scrollState.modeSelector[0].classList.add("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
function showModeSelector() {
|
||||||
|
GWLog("showModeSelector");
|
||||||
|
|
||||||
|
GW.scrollState.modeSelector[0].classList.remove("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the states of the mode selector buttons.
|
||||||
|
*/
|
||||||
|
function updateModeSelectorState() {
|
||||||
|
// Get saved mode setting (or default).
|
||||||
|
let currentMode = localStorage.getItem("selected-mode") || 'auto';
|
||||||
|
|
||||||
|
// Clear current buttons state.
|
||||||
|
let modeSelector = document.querySelector("#mode-selector");
|
||||||
|
modeSelector.childNodes.forEach(button => {
|
||||||
|
button.classList.remove("active", "selected");
|
||||||
|
button.disabled = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set the correct button to be selected.
|
||||||
|
modeSelector.querySelectorAll(`.select-mode-${currentMode}`).forEach(button => {
|
||||||
|
button.classList.add("selected");
|
||||||
|
button.disabled = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ensure the right button (light or dark) has the “currently activeâ€
|
||||||
|
// indicator, if the current mode is ‘auto’.
|
||||||
|
if (currentMode == "auto") {
|
||||||
|
if (GW.mediaQueries.systemDarkModeActive.matches)
|
||||||
|
modeSelector.querySelector(".select-mode-dark").classList.add("active");
|
||||||
|
else
|
||||||
|
modeSelector.querySelector(".select-mode-light").classList.add("active");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set specified color mode (auto, light, dark).
|
||||||
|
*/
|
||||||
|
function setMode(modeOption) {
|
||||||
|
GWLog("setMode");
|
||||||
|
|
||||||
|
// Inject the appropriate styles.
|
||||||
|
let modeStyles = document.querySelector("#mode-styles");
|
||||||
|
if (modeOption == 'auto') {
|
||||||
|
modeStyles.innerHTML = `@media (prefers-color-scheme:dark) {${GW.modeStyles}}`;
|
||||||
|
} else if (modeOption == 'dark') {
|
||||||
|
modeStyles.innerHTML = GW.modeStyles;
|
||||||
|
} else {
|
||||||
|
modeStyles.innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update selector state.
|
||||||
|
updateModeSelectorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************/
|
||||||
|
/* INITIALIZATION */
|
||||||
|
/******************/
|
||||||
|
|
||||||
|
doWhenPageLoaded(() => {
|
||||||
|
injectModeSelector();
|
||||||
|
});
|
14
public/sitemap.xml
Normal file
14
public/sitemap.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||||
|
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
||||||
|
<url>
|
||||||
|
<loc>http://example.org/contact/</loc>
|
||||||
|
<priority>0</priority>
|
||||||
|
</url><url>
|
||||||
|
<loc>http://example.org/categories/</loc>
|
||||||
|
</url><url>
|
||||||
|
<loc>http://example.org/</loc>
|
||||||
|
</url><url>
|
||||||
|
<loc>http://example.org/tags/</loc>
|
||||||
|
</url>
|
||||||
|
</urlset>
|
43
public/tags/index.html
Normal file
43
public/tags/index.html
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title>Tags | My New Hugo Site</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
|
<link rel="stylesheet" href="/css/fonts.css">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header class="site-header">
|
||||||
|
<div class="wrapper">
|
||||||
|
<a class="muted small" href="http://example.org/"></a>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>
|
||||||
|
Tags
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/dark.js" defer="" ></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
10
public/tags/index.xml
Normal file
10
public/tags/index.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
|
<channel>
|
||||||
|
<title>Tags on My New Hugo Site</title>
|
||||||
|
<link>http://example.org/tags/</link>
|
||||||
|
<description>Recent content in Tags on My New Hugo Site</description>
|
||||||
|
<generator>Hugo -- gohugo.io</generator>
|
||||||
|
<language>en-us</language><atom:link href="http://example.org/tags/index.xml" rel="self" type="application/rss+xml" />
|
||||||
|
</channel>
|
||||||
|
</rss>
|
Loading…
Reference in New Issue
Block a user