Initial Release

This commit is contained in:
2023-03-26 15:44:45 +02:00
commit 2b7528e89a
66 changed files with 6603 additions and 0 deletions

15
assets/css/paginator.css Normal file
View File

@ -0,0 +1,15 @@
.pagination {
@apply inline-flex border rounded px-1 dark:border-gray-600;
}
.page-item {
@apply mx-0.5 my-1 cursor-pointer rounded hover:bg-gray-800 hover:text-white dark:hover:bg-gray-500 dark:hover:text-white;
}
a.page-link {
@apply px-3 py-1 block;
}
.page-item.active {
@apply bg-gray-800 text-white dark:bg-gray-300 dark:text-gray-900;
}
.page-item.disabled {
@apply text-gray-400 hover:bg-transparent hover:text-gray-400 cursor-not-allowed;
}

View File

@ -0,0 +1,13 @@
const themeDir = __dirname + "/../../";
module.exports = {
plugins: [
require("postcss-import")({
path: [themeDir],
}),
require("tailwindcss")(themeDir + "assets/css/tailwind.config.js"),
require("autoprefixer")({
path: [themeDir],
}),
],
};

55
assets/css/site.css Normal file
View File

@ -0,0 +1,55 @@
/* Custom Styles */
body {
font-family: "Inter", sans-serif;
}
/* Fonts */
/* inter-300 - latin */
@font-face {
font-family: "Inter";
font-style: normal;
font-weight: 300;
src: url("/fonts/inter-v3-latin-300.eot"); /* IE9 Compat Modes */
src: local(""),
url("/fonts/inter-v3-latin-300.eot?#iefix") format("embedded-opentype"),
/* IE6-IE8 */ url("/fonts/inter-v3-latin-300.woff2") format("woff2"),
/* Super Modern Browsers */ url("/fonts/inter-v3-latin-300.woff")
format("woff"),
/* Modern Browsers */ url("/fonts/inter-v3-latin-300.ttf")
format("truetype"),
/* Safari, Android, iOS */ url("/fonts/inter-v3-latin-300.svg#Inter")
format("svg"); /* Legacy iOS */
}
/* inter-500 - latin */
@font-face {
font-family: "Inter";
font-style: normal;
font-weight: 500;
src: url("/fonts/inter-v3-latin-500.eot"); /* IE9 Compat Modes */
src: local(""),
url("/fonts/inter-v3-latin-500.eot?#iefix") format("embedded-opentype"),
/* IE6-IE8 */ url("/fonts/inter-v3-latin-500.woff2") format("woff2"),
/* Super Modern Browsers */ url("/fonts/inter-v3-latin-500.woff")
format("woff"),
/* Modern Browsers */ url("/fonts/inter-v3-latin-500.ttf")
format("truetype"),
/* Safari, Android, iOS */ url("/fonts/inter-v3-latin-500.svg#Inter")
format("svg"); /* Legacy iOS */
}
/* inter-700 - latin */
@font-face {
font-family: "Inter";
font-style: normal;
font-weight: 700;
src: url("/fonts/inter-v3-latin-700.eot"); /* IE9 Compat Modes */
src: local(""),
url("/fonts/inter-v3-latin-700.eot?#iefix") format("embedded-opentype"),
/* IE6-IE8 */ url("/fonts/inter-v3-latin-700.woff2") format("woff2"),
/* Super Modern Browsers */ url("/fonts/inter-v3-latin-700.woff")
format("woff"),
/* Modern Browsers */ url("/fonts/inter-v3-latin-700.ttf")
format("truetype"),
/* Safari, Android, iOS */ url("/fonts/inter-v3-latin-700.svg#Inter")
format("svg"); /* Legacy iOS */
}

55
assets/css/styles.css Normal file
View File

@ -0,0 +1,55 @@
/* Tailwind base - put variables under: tailwind.config.js */
@import "node_modules/tailwindcss/base";
/* Tailwind component classes registered by plugins*/
@import "node_modules/tailwindcss/components";
/* Site Specific */
@import "assets/css/site";
/* Paginator */
@import "assets/css/paginator";
/* Tailwind's utility classes - generated based on config file */
@import "node_modules/tailwindcss/utilities";
@layer components {
details.toc[open] summary ~ * {
animation: slideUp 0.25s ease-in-out;
}
@keyframes slideUp {
0% {
opacity: 0;
transform: translateY(10px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
details.toc[open] summary svg {
@apply transform duration-200 rotate-180 ease-in-out;
}
details.toc > ul {
@apply ml-4;
}
details.toc ul {
@apply list-none;
margin-top: 0.125rem /* 2px */ !important;
margin-bottom: 0.125rem /* 2px */ !important;
}
details.toc ul li {
margin-top: 0.125rem /* 2px */ !important;
margin-bottom: 0.125rem /* 2px */ !important;
}
details.toc ul li:before {
@apply rounded-none bg-gray-400;
}
details.toc ul li a {
@apply no-underline text-gray-700 dark:text-gray-200 text-base;
}
a:empty {
display: none;
}
}

View File

@ -0,0 +1,110 @@
const themeDir = __dirname + "/../../";
module.exports = {
purge: {
enabled: process.env.HUGO_ENVIRONMENT === "production",
content: [
themeDir + "layouts/**/*.html",
themeDir + "content/**/*.html",
"layouts/**/*.html",
"config.toml",
"content/**/*.html",
"assets/js/search.js",
"exampleSite/layouts/**/*.html",
"exampleSite/config.toml",
"exampleSite/content/**/*.html",
],
},
darkMode: "class",
theme: {
extend: {
typography: (theme) => ({
DEFAULT: {
css: [
{
'code::before': {
content: '""',
},
'code::after': {
content: '""',
},
}
]
},
dark: {
css: [
{
color: theme("colors.gray.400"),
'[class~="lead"]': {
color: theme("colors.gray.300"),
},
a: {
color: theme("colors.white"),
},
strong: {
color: theme("colors.white"),
},
"ol > li::before": {
color: theme("colors.gray.400"),
},
"ul > li::before": {
backgroundColor: theme("colors.gray.600"),
},
hr: {
borderColor: theme("colors.gray.200"),
},
blockquote: {
color: theme("colors.gray.200"),
borderLeftColor: theme("colors.gray.600"),
},
h1: {
color: theme("colors.white"),
},
h2: {
color: theme("colors.white"),
},
h3: {
color: theme("colors.white"),
},
h4: {
color: theme("colors.white"),
},
"figure figcaption": {
color: theme("colors.gray.400"),
},
code: {
color: theme("colors.white"),
},
"a code": {
color: theme("colors.white"),
},
'code::before': {
content: '""',
},
'code::after': {
content: '""',
},
pre: {
color: theme("colors.gray.200"),
backgroundColor: theme("colors.gray.800"),
},
thead: {
color: theme("colors.white"),
borderBottomColor: theme("colors.gray.400"),
},
"tbody tr": {
borderBottomColor: theme("colors.gray.600"),
},
},
],
},
}),
},
},
variants: {
extend: {
typography: ["dark"],
},
},
plugins: [require("@tailwindcss/typography")],
};

9
assets/js/fuse.min.js vendored Normal file

File diff suppressed because one or more lines are too long

174
assets/js/search.js Normal file
View File

@ -0,0 +1,174 @@
// Credits to search implementation: https://gist.github.com/cmod/5410eae147e4318164258742dd053993
var fuse; // holds our search engine
var searchVisible = false;
var firstRun = true; // allow us to delay loading json data unless search activated
var list = document.querySelector('.search-list'); // targets the <ul>
var first = list.firstChild; // first child of search list
var last = list.lastChild; // last child of search list
var maininput = document.querySelector('.search-ui input'); // input box for search
var searchResultsHeading = document.querySelector('.search-results'); // input box for search
var noResults = document.querySelector('.no-results'); // input box for search
var resultsAvailable = false; // Did we get any search results?
// ==========================================
// The main keyboard event listener running the show
//
document.querySelector('.open-search').addEventListener('click', openSearch);
document.querySelector('.close-search').addEventListener('click', closeSearch);
function closeSearch() {
document.querySelector('.search-ui').classList.add("hidden");
document.activeElement.blur(); // remove focus from search box
searchVisible = false; // search not visible
searchResultsHeading.classList.add('hidden');
}
function openSearch() {
// Load json search index if first time invoking search
// Means we don't load json unless searches are going to happen; keep user payload small unless needed
if (firstRun) {
loadSearch(); // loads our json data and builds fuse.js search index
firstRun = false; // let's never do this again
}
//Close the mobile menu when search is click.
mobileMenu.classList.toggle('hidden');
// Toggle visibility of search box
if (!searchVisible) {
document.querySelector('.search-ui').classList.remove("hidden");
document.querySelector('.search-ui input').focus(); // put focus in input box so you can just start typing
searchVisible = true; // search visible
}
}
document.addEventListener('keydown', function (event) {
if (event.metaKey && event.which === 191) {
openSearch()
}
// Allow ESC (27) to close search box
if (event.keyCode == 27) {
if (searchVisible) {
document.querySelector('.search-ui').classList.add("hidden");
document.activeElement.blur();
searchVisible = false;
searchResultsHeading.classList.add('hidden');
}
}
// DOWN (40) arrow
if (event.keyCode == 40) {
if (searchVisible && resultsAvailable) {
console.log("down");
event.preventDefault(); // stop window from scrolling
if (document.activeElement == maininput) { first.focus(); } // if the currently focused element is the main input --> focus the first <li>
else if (document.activeElement == last) { last.focus(); } // if we're at the bottom, stay there
else { document.activeElement.parentElement.nextSibling.firstElementChild.focus(); } // otherwise select the next search result
}
}
// UP (38) arrow
if (event.keyCode == 38) {
if (searchVisible && resultsAvailable) {
event.preventDefault(); // stop window from scrolling
if (document.activeElement == maininput) { maininput.focus(); } // If we're in the input box, do nothing
else if (document.activeElement == first) { maininput.focus(); } // If we're at the first item, go to input box
else { document.activeElement.parentElement.previousSibling.firstElementChild.focus(); } // Otherwise, select the search result above the current active one
}
}
})
// ==========================================
// execute search as each character is typed
//
document.querySelector('.search-ui input').onkeyup = function (e) {
executeSearch(this.value);
}
// ==========================================
// fetch some json without jquery
//
function fetchJSONFile(path, callback) {
var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
var data = JSON.parse(httpRequest.responseText);
if (callback) callback(data);
}
}
};
httpRequest.open('GET', path);
httpRequest.send();
}
// ==========================================
// load our search index, only executed once
// on first call of search box (CMD-/)
//
function loadSearch() {
const lang = document.querySelector('head > meta[name="lang"]')?.getAttribute?.('content')
fetchJSONFile(`${lang ? "/" + lang : ""}/index.json`, function (data) {
var options = { // fuse.js options; check fuse.js website for details
shouldSort: true,
location: 0,
distance: 100,
threshold: 0.4,
minMatchCharLength: 2,
keys: [
'title',
'permalink',
'contents'
]
};
fuse = new Fuse(data, options); // build the index from the json file
});
}
// ==========================================
// using the index we loaded on CMD-/, run
// a search query (for "term") every time a letter is typed
// in the search box
//
function executeSearch(term) {
let results = fuse.search(term); // the actual query being run using fuse.js
let searchitems = ''; // our results bucket
if (results.length === 0) { // no results based on what was typed into the input box
resultsAvailable = false;
searchitems = '';
if (term !== "") {
noResults.classList.remove('hidden')
} else {
noResults.classList.add('hidden')
}
} else { // build our html
noResults.classList.add('hidden')
if (term !== "") {
searchResultsHeading.classList.remove('hidden');
}
for (let item in results.slice(0, 5)) { // only show first 5 results
const title = '<div class="text-2xl mb-2 font-bold">' + results[item].item.title + '</div>';
const date = results[item].item.date ? '<div><em class="px-4">' + new Date(results[item].item.date).toUTCString().substring(0, 16) + '</em></div>' : '';
const contents = '<div class="prose px-4">' + results[item].item.contents + '</div>';
searchitems = searchitems + '<li><a class="block mb-2 px-4 py-2 rounded pb-2 border-b border-gray-200 dark:border-gray-600 focus:bg-gray-100 dark:focus:bg-gray-700 focus:outline-none" href="' + results[item].item.permalink + '" tabindex="0">' + title + '</a>' + date + contents + '</li>';
}
resultsAvailable = true;
}
list.innerHTML = searchitems;
if (results.length > 0) {
first = list.firstChild.firstElementChild; // first result container — used for checking against keyboard up/down location
last = list.lastChild.firstElementChild; // last result container — used for checking against keyboard up/down location
}
}