first commit
166
.eleventy.js
Normal file
@ -0,0 +1,166 @@
|
||||
const { format, formatISO, getYear } = require("date-fns");
|
||||
const pluginRss = require("@11ty/eleventy-plugin-rss");
|
||||
const pluginToc = require("eleventy-plugin-toc");
|
||||
const { MD5 } = require("crypto-js");
|
||||
const { URL } = require("url");
|
||||
const { readFileSync } = require("fs");
|
||||
const siteconfig = require("./content/_data/siteconfig.js");
|
||||
const markdownIt = require("markdown-it");
|
||||
const markdownItAnchor = require("markdown-it-anchor");
|
||||
|
||||
module.exports = function (eleventyConfig) {
|
||||
// Set Markdown library
|
||||
eleventyConfig.setLibrary(
|
||||
"md",
|
||||
markdownIt({
|
||||
html: true,
|
||||
xhtmlOut: true,
|
||||
linkify: true,
|
||||
typographer: true
|
||||
}).use(markdownItAnchor)
|
||||
);
|
||||
|
||||
// Define passthrough for assets
|
||||
eleventyConfig.addPassthroughCopy("assets");
|
||||
|
||||
// Add watch target for JS files (needed for JS bundling in dev mode)
|
||||
eleventyConfig.addWatchTarget("./assets/js/");
|
||||
// And to make this work we've to disable the .gitignore usage of eleventy.
|
||||
eleventyConfig.setUseGitIgnore(false);
|
||||
|
||||
// Add 3rd party plugins
|
||||
eleventyConfig.addPlugin(pluginRss);
|
||||
eleventyConfig.addPlugin(pluginToc);
|
||||
|
||||
// Define 11ty template formats
|
||||
eleventyConfig.setTemplateFormats([
|
||||
"njk",
|
||||
"md",
|
||||
"svg",
|
||||
"jpg",
|
||||
"css",
|
||||
"png"
|
||||
]);
|
||||
|
||||
// Generate excerpt from first paragraph
|
||||
eleventyConfig.addShortcode("excerpt", (article) =>
|
||||
extractExcerpt(article)
|
||||
);
|
||||
|
||||
// Set absolute url
|
||||
eleventyConfig.addNunjucksFilter("absoluteUrl", (path) => {
|
||||
return new URL(path, siteconfig.url).toString();
|
||||
});
|
||||
|
||||
// Extract reading time
|
||||
eleventyConfig.addNunjucksFilter("readingTime", (wordcount) => {
|
||||
let readingTime = Math.ceil(wordcount / 220);
|
||||
if (readingTime === 1) {
|
||||
return readingTime + " minute";
|
||||
}
|
||||
return readingTime + " minutes";
|
||||
});
|
||||
|
||||
// Extract word count
|
||||
eleventyConfig.addNunjucksFilter("formatWords", (wordcount) => {
|
||||
return wordcount.toLocaleString("en");
|
||||
});
|
||||
|
||||
// Returns CSS class for home page link
|
||||
eleventyConfig.addNunjucksFilter("isHomeLink", function (url, pattern) {
|
||||
return (pattern === "/" && url === "/") ||
|
||||
(pattern === "/" && url.startsWith("/posts"))
|
||||
? "active"
|
||||
: "";
|
||||
});
|
||||
|
||||
// Returns CSS class for active page link
|
||||
eleventyConfig.addNunjucksFilter("isActiveLink", function (url, pattern) {
|
||||
return url.length > 1 && url.startsWith(pattern) ? "active" : "";
|
||||
});
|
||||
|
||||
// Format dates for sitemap
|
||||
eleventyConfig.addNunjucksFilter("sitemapdate", function (date) {
|
||||
return format(date, "yyyy-MM-dd");
|
||||
});
|
||||
|
||||
// Format dates for JSON-LD
|
||||
eleventyConfig.addNunjucksFilter("isodate", function (date) {
|
||||
return formatISO(date);
|
||||
});
|
||||
|
||||
// Extracts the year from a post
|
||||
eleventyConfig.addNunjucksFilter("year", function (post) {
|
||||
if (post && post.date) {
|
||||
return getYear(post.date);
|
||||
}
|
||||
return "n/a";
|
||||
});
|
||||
|
||||
// Extracts the day of a date
|
||||
eleventyConfig.addNunjucksFilter("day", function (date) {
|
||||
return format(date, "dd");
|
||||
});
|
||||
|
||||
// Extracts the month of a date
|
||||
eleventyConfig.addNunjucksFilter("month", function (date) {
|
||||
return format(date, "MMM");
|
||||
});
|
||||
|
||||
// Extracts readable date of a date
|
||||
eleventyConfig.addNunjucksFilter("readableDate", function (date) {
|
||||
return format(date, "MMM dd, yyyy");
|
||||
});
|
||||
|
||||
// Add custom hash for cache busting
|
||||
const hashes = new Map();
|
||||
eleventyConfig.addNunjucksFilter("addHash", function (absolutePath) {
|
||||
const cached = hashes.get(absolutePath);
|
||||
if (cached) {
|
||||
return `${absolutePath}?hash=${cached}`;
|
||||
}
|
||||
const fileContent = readFileSync(`${process.cwd()}${absolutePath}`, {
|
||||
encoding: "utf-8"
|
||||
}).toString();
|
||||
const hash = MD5(fileContent.toString());
|
||||
hashes.set(absolutePath, hash);
|
||||
return `${absolutePath}?hash=${hash}`;
|
||||
});
|
||||
|
||||
// Create custom collection for getting the newest 5 updates
|
||||
eleventyConfig.addCollection("recents", function (collectionApi) {
|
||||
return collectionApi.getAllSorted().reverse().slice(0, 5);
|
||||
});
|
||||
|
||||
// Plugin for setting _blank and rel=noopener on external links in markdown content
|
||||
eleventyConfig.addPlugin(require("./_11ty/external-links.js"));
|
||||
|
||||
// Plugin for transforming images
|
||||
eleventyConfig.addPlugin(require("./_11ty/srcset.js"));
|
||||
|
||||
// Plugin for minifying HTML
|
||||
eleventyConfig.addPlugin(require("./_11ty/html-minify.js"));
|
||||
|
||||
return {
|
||||
dir: {
|
||||
// Consolidating everything below the `content` folder
|
||||
input: "content"
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Taken from here => https://keepinguptodate.com/pages/2019/06/creating-blog-with-eleventy/
|
||||
function extractExcerpt(article) {
|
||||
if (!Object.prototype.hasOwnProperty.call(article, "templateContent")) {
|
||||
console.warn(
|
||||
'Failed to extract excerpt: Document has no property "templateContent".'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const content = article.templateContent;
|
||||
|
||||
const excerpt = content.slice(0, content.indexOf("\n"));
|
||||
|
||||
return excerpt;
|
||||
}
|
17
.eslintrc.js
Executable file
@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
extends: ["eslint:recommended", "prettier"],
|
||||
plugins: ["inclusive-language"],
|
||||
rules: {
|
||||
"inclusive-language/use-inclusive-words": "error"
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
sourceType: "module"
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true
|
||||
},
|
||||
ignorePatterns: ["!/.*.js", "_site", "/assets/js/", "node_modules"]
|
||||
};
|
44
.gitignore
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
# This file is used for Git repositories to specify intentionally untracked files that Git should ignore.
|
||||
# If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore
|
||||
# For useful gitignore templates see: https://github.com/github/gitignore
|
||||
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
|
||||
# Eslint cache
|
||||
.eslintcache
|
||||
|
||||
# MacOS system files
|
||||
.DS_Store
|
||||
|
||||
# Windows system files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
[Dd]esktop.ini
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Local .env file
|
||||
.env
|
||||
|
||||
# Static content
|
||||
_site/
|
||||
# Uncomment the following line if you want to commit all images to source control. This will def speed up build time.
|
||||
# !_site/assets/images
|
||||
|
||||
# Temporary file for changed pages
|
||||
scripts/temp-output/*
|
||||
|
||||
# Locally built assets
|
||||
assets/css/*-build.css
|
||||
assets/js/min.*
|
||||
|
||||
# Local Netlify folder
|
||||
.netlify
|
1
.husky/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
_
|
1
.husky/pre-commit
Normal file
@ -0,0 +1 @@
|
||||
npm run precommit
|
5
.markdownlint.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"line-length": false,
|
||||
"list-marker-space": false,
|
||||
"no-inline-html": false
|
||||
}
|
9
.prettierignore
Executable file
@ -0,0 +1,9 @@
|
||||
# List files or directories below to ignore them when running prettier
|
||||
# More information: https://prettier.io/docs/en/ignore.html
|
||||
#
|
||||
|
||||
_site/
|
||||
.netlify/
|
||||
.vscode/
|
||||
assets/css/*-build.css
|
||||
assets/js/*.js
|
4
.prettierrc
Executable file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 4
|
||||
}
|
45
.vscode/css_custom_data.json
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"version": 1.1,
|
||||
"atDirectives": [
|
||||
{
|
||||
"name": "@tailwind",
|
||||
"description": "Use the `@tailwind` directive to insert Tailwind's `base`, `components`, `utilities` and `screens` styles into your CSS.",
|
||||
"references": [
|
||||
{
|
||||
"name": "Tailwind Documentation",
|
||||
"url": "https://tailwindcss.com/docs/functions-and-directives#tailwind"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "@responsive",
|
||||
"description": "You can generate responsive variants of your own classes by wrapping their definitions in the `@responsive` directive:\n```css\n@responsive {\n .alert {\n background-color: #E53E3E;\n }\n}\n```\n",
|
||||
"references": [
|
||||
{
|
||||
"name": "Tailwind Documentation",
|
||||
"url": "https://tailwindcss.com/docs/functions-and-directives#responsive"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "@screen",
|
||||
"description": "The `@screen` directive allows you to create media queries that reference your breakpoints by **name** instead of duplicating their values in your own CSS:\n```css\n@screen sm {\n /* ... */\n}\n```\n…gets transformed into this:\n```css\n@media (min-width: 640px) {\n /* ... */\n}\n```\n",
|
||||
"references": [
|
||||
{
|
||||
"name": "Tailwind Documentation",
|
||||
"url": "https://tailwindcss.com/docs/functions-and-directives#screen"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "@variants",
|
||||
"description": "Generate `hover`, `focus`, `active` and other **variants** of your own utilities by wrapping their definitions in the `@variants` directive:\n```css\n@variants hover, focus {\n .btn-brand {\n background-color: #3182CE;\n }\n}\n```\n",
|
||||
"references": [
|
||||
{
|
||||
"name": "Tailwind Documentation",
|
||||
"url": "https://tailwindcss.com/docs/functions-and-directives#variants"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
7
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"DavidAnson.vscode-markdownlint",
|
||||
"esbenp.prettier-vscode",
|
||||
"bradlc.vscode-tailwindcss"
|
||||
]
|
||||
}
|
4
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"css.customData": [".vscode/css_custom_data.json"],
|
||||
"css.validate": false,
|
||||
}
|
20
LICENSE.md
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2021 René Winkelmeyer and others
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
74
README.md
Normal file
@ -0,0 +1,74 @@
|
||||
# eleventy-chirpy-blog-template
|
||||
|
||||
[/badge.svg?branch=main>)](https://github.com/muenzpraeger/eleventy-chirpy-blog-template/actions?query=workflow%3A%22Blog+build+%28main%29%22) [](https://app.netlify.com/sites/eleventy-chirpy-blog-template/deploys)
|
||||
|
||||
[11ty](https://www.11ty.dev/) version of the popular [Chirpy Jekyll](https://github.com/cotes2020/jekyll-theme-chirpy) blog theme. Also powers [my personal blog](https://blog.winkelmeyer.com). I liked the UX a lot, but not the tech stack, hence I re-built it for myself. Sharing here with everybody, in case you like the same.
|
||||
|
||||
You can check out the live version on <https://eleventy-chirpy-blog-template.netlify.app>.
|
||||
|
||||
If you want to deploy, there's a button for it: [](https://app.netlify.com/start/deploy?repository=https://github.com/muenzpraeger/eleventy-chirpy-blog-template)
|
||||
|
||||
## Features
|
||||
|
||||
- 💯 on Lighthouse
|
||||
- 🔆 and 🌛 mode
|
||||
- 🎯 SEO and OpenGraph optimized
|
||||
- 🌄 Responsive images optimization
|
||||
- 👀 Accessible
|
||||
- 🛠 JavaScript and CSS build optimization
|
||||
- 👨💻 Prism-based syntax highlighting
|
||||
- 📚 RSS (yup, still a thing), sitemap.xml, and JSON-LD
|
||||
- 🔍 [Algolia Search](https://github.com/algolia/algoliasearch-netlify) enabled
|
||||
- and more
|
||||
|
||||
Opinionated setup with [Prettier](https://prettier.io/), [ESlint](https://eslint.org/), [markdownlint](https://github.com/DavidAnson/markdownlint) and others. UX build with [Nunjucks](https://mozilla.github.io/nunjucks/templating.html) and [TailwindCSS](https://tailwindcss.com/docs). JavaScript bundled with [Rollup](https://rollupjs.org/).
|
||||
|
||||
## Configuration
|
||||
|
||||
All blog configuration is handled via [`siteconfig.js`](./content/_data/siteconfig.js). Everything is inline documented.
|
||||
|
||||
## Deployment
|
||||
|
||||
All build processes rely on how `NODE_ENV` is set. For production builds, which then also means minified CSS and JS you've to set the value to `production`. I mention this explicitly as this is for some vendors not the default.
|
||||
|
||||
If you want to speed up your build times a bit you can add the generated images to your git repo. The `.gitignore` already contains a commented section for that.
|
||||
|
||||
## Local Development
|
||||
|
||||
### Before you install dependencies
|
||||
|
||||
This repo uses [Volta](https://volta.sh/). Get it, and it'll make your node life so much easier.
|
||||
|
||||
### Instructions
|
||||
|
||||
Clone this repository.
|
||||
|
||||
```zsh
|
||||
git clone https://github.com/muenzpraeger/eleventy-chirpy-blog-template
|
||||
```
|
||||
|
||||
Change into the cloned directory.
|
||||
|
||||
```zsh
|
||||
cd eleventy-chirpy-blog-template
|
||||
```
|
||||
|
||||
Install dependencies. Note, if you prefer `npm` over `yarn` make sure to first remove the `yarn.lock` file, and then run `npm install`.
|
||||
|
||||
```zsh
|
||||
yarn install
|
||||
```
|
||||
|
||||
Start the local development process.
|
||||
|
||||
```zsh
|
||||
yarn dev
|
||||
```
|
||||
|
||||
Open the page, usually on <http://localhost:8080>, and dig around!
|
||||
|
||||
## Credits
|
||||
|
||||
The UX of this template is based on the popular Chirpy template, just with a different tech stack. If you prefer to run Jekyll and Bootstrap, checkout [Chirpy](https://github.com/cotes2020/jekyll-theme-chirpy) here. It's great.
|
||||
|
||||
Also big thanks to the the authors of the [11ty High Performance Blog](https://github.com/google/eleventy-high-performance-blog).
|
39
_11ty/external-links.js
Normal file
@ -0,0 +1,39 @@
|
||||
// Transformer to ensure that non-relative links open in a new window
|
||||
// and have for SEO reasons `rel="noopener"` set.
|
||||
|
||||
const { JSDOM } = require("jsdom");
|
||||
const siteconfig = require("../content/_data/siteconfig");
|
||||
|
||||
const processHrefs = async (el) => {
|
||||
if (
|
||||
!el.href.startsWith("/") &&
|
||||
!el.href.startsWith(siteconfig.url) &&
|
||||
!el.href.startsWith("about:blank#")
|
||||
) {
|
||||
el.target = "_blank";
|
||||
el.rel = "noopener";
|
||||
}
|
||||
};
|
||||
|
||||
const convert = async (rawContent, outputPath) => {
|
||||
let content = rawContent;
|
||||
|
||||
if (outputPath && outputPath.endsWith(".html")) {
|
||||
const dom = new JSDOM(content);
|
||||
const hrefs = [...dom.window.document.querySelectorAll("a")];
|
||||
|
||||
if (hrefs.length > 0) {
|
||||
await Promise.all(hrefs.map((i) => processHrefs(i)));
|
||||
content = dom.serialize();
|
||||
}
|
||||
}
|
||||
|
||||
return content;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
initArguments: {},
|
||||
configFunction: async (eleventyConfig = {}) => {
|
||||
eleventyConfig.addTransform("externalContentLinks", convert);
|
||||
}
|
||||
};
|
25
_11ty/html-minify.js
Normal file
@ -0,0 +1,25 @@
|
||||
// Transformer to minify HTML output.
|
||||
|
||||
const htmlmin = require("html-minifier");
|
||||
|
||||
const convert = async (rawContent, outputPath) => {
|
||||
const content = rawContent;
|
||||
|
||||
if (outputPath && outputPath.endsWith(".html")) {
|
||||
const minified = htmlmin.minify(content, {
|
||||
useShortDoctype: true,
|
||||
removeComments: true,
|
||||
collapseWhitespace: true
|
||||
});
|
||||
return minified;
|
||||
}
|
||||
|
||||
return content;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
initArguments: {},
|
||||
configFunction: async (eleventyConfig = {}) => {
|
||||
eleventyConfig.addTransform("minifyHTML", convert);
|
||||
}
|
||||
};
|
162
_11ty/srcset.js
Normal file
@ -0,0 +1,162 @@
|
||||
/**
|
||||
* Copyright (c) 2020 Google Inc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Transformer to set `srcset` for all images, and to create respective
|
||||
// image versions in different formats and resolutions.
|
||||
// Modification of original script from https://github.com/google/eleventy-high-performance-blog
|
||||
|
||||
const { JSDOM } = require("jsdom");
|
||||
const sharp = require("sharp");
|
||||
const { copyFileSync, existsSync, mkdirSync, readFileSync } = require("fs");
|
||||
const { MD5 } = require("crypto-js");
|
||||
const { extname, join } = require("path");
|
||||
|
||||
const widths = [1024, 820, 640, 320];
|
||||
|
||||
const extension = {
|
||||
jpeg: "jpg",
|
||||
webp: "webp"
|
||||
};
|
||||
|
||||
// Map filenames to types and width, and then resize
|
||||
async function srcset(filename, hash, format, metadataWidth) {
|
||||
// Create a map of all file names
|
||||
const names = await Promise.all(
|
||||
widths.map((width) =>
|
||||
resize(filename, width, hash, format, metadataWidth)
|
||||
)
|
||||
);
|
||||
return names.map((n, i) => `${n} ${widths[i]}w`).join(", ");
|
||||
}
|
||||
|
||||
async function resize(filename, width, hash, format, metadataWidth) {
|
||||
const out = sizedName(filename, width, hash, format);
|
||||
if (existsSync("_site/" + out)) {
|
||||
return out;
|
||||
}
|
||||
|
||||
const file = join(process.cwd(), filename);
|
||||
|
||||
const resizeWidth = metadataWidth < width ? metadataWidth : width;
|
||||
|
||||
await sharp(file)
|
||||
.resize({ width: resizeWidth })
|
||||
[format]({
|
||||
quality: 80,
|
||||
reductionEffort: 6
|
||||
})
|
||||
.toFile("_site/" + out);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function sizedName(filename, width, hash, format) {
|
||||
const ext = extension[format];
|
||||
if (!ext) {
|
||||
throw new Error(`Unknown format ${format}`);
|
||||
}
|
||||
return filename.replace(
|
||||
/\.\w+$/,
|
||||
() => "-" + hash + "-" + width + "w." + ext
|
||||
);
|
||||
}
|
||||
|
||||
function hashedName(filename, hash) {
|
||||
return filename.replace(extname(filename), "-" + hash + extname(filename));
|
||||
}
|
||||
|
||||
async function setSrcset(img, src, hash, format, metadataWidth) {
|
||||
img.setAttribute("srcset", await srcset(src, hash, format, metadataWidth));
|
||||
}
|
||||
|
||||
const processImage = async (el) => {
|
||||
const filename = el.getAttribute("src");
|
||||
|
||||
if (/^(https?:\/\/|\/\/)/i.test(filename)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (extname(filename.toLowerCase()) === ".svg") {
|
||||
return;
|
||||
}
|
||||
|
||||
const file = join(process.cwd(), filename);
|
||||
|
||||
// Generate file hash
|
||||
const hash = MD5(readFileSync(file).toString());
|
||||
|
||||
// Get image metadata
|
||||
const metadata = await sharp(file).metadata();
|
||||
|
||||
el.setAttribute("decoding", "async");
|
||||
el.setAttribute("loading", "lazy");
|
||||
el.setAttribute("height", metadata.height);
|
||||
el.setAttribute("width", metadata.width);
|
||||
|
||||
const doc = el.ownerDocument;
|
||||
const picture = doc.createElement("picture");
|
||||
const webp = doc.createElement("source");
|
||||
const jpeg = doc.createElement("source");
|
||||
|
||||
await setSrcset(webp, filename, hash, "webp", metadata.width);
|
||||
webp.setAttribute("type", "image/webp");
|
||||
await setSrcset(jpeg, filename, hash, "jpeg", metadata.width);
|
||||
jpeg.setAttribute("type", "image/jpeg");
|
||||
|
||||
picture.appendChild(webp);
|
||||
picture.appendChild(jpeg);
|
||||
el.parentElement.replaceChild(picture, el);
|
||||
picture.appendChild(el);
|
||||
|
||||
copyFileSync(
|
||||
join(process.cwd(), filename),
|
||||
join("_site", hashedName(filename, hash))
|
||||
);
|
||||
};
|
||||
|
||||
const convert = async (rawContent, outputPath) => {
|
||||
let content = rawContent;
|
||||
|
||||
const targetDirectory = "./_site/assets/images";
|
||||
|
||||
if (!existsSync(targetDirectory)) {
|
||||
mkdirSync(targetDirectory, { recursive: true });
|
||||
}
|
||||
|
||||
if (outputPath && outputPath.endsWith(".html")) {
|
||||
const dom = new JSDOM(content);
|
||||
const images = [...dom.window.document.querySelectorAll("img")];
|
||||
|
||||
if (images.length > 0) {
|
||||
await Promise.all(images.map((i) => processImage(i, outputPath)));
|
||||
content = dom.serialize();
|
||||
}
|
||||
}
|
||||
|
||||
return content;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
initArguments: {},
|
||||
configFunction: async (eleventyConfig = {}) => {
|
||||
eleventyConfig.addTransform("imageConversion", convert);
|
||||
}
|
||||
};
|
494
assets/css/prism.css
Normal file
@ -0,0 +1,494 @@
|
||||
/* PrismJS 1.22.0
|
||||
https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+apex+sql+typoscript&plugins=line-highlight+line-numbers+show-language+toolbar */
|
||||
/**
|
||||
* prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML
|
||||
* Based on https://github.com/chriskempson/tomorrow-theme
|
||||
* @author Rose Pritchard
|
||||
*/
|
||||
|
||||
html[class="dark"] code[class*="language-"],
|
||||
html[class="dark"] pre[class*="language-"] {
|
||||
color: #ccc;
|
||||
background: none;
|
||||
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
|
||||
font-size: 1em;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
html[class="dark"] pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: 0.5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
html[class="dark"] :not(pre) > code[class*="language-"],
|
||||
html[class="dark"] pre[class*="language-"] {
|
||||
background: #2d2d2d;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
html[class="dark"] :not(pre) > code {
|
||||
padding: 0.3em;
|
||||
border-radius: 0.3em;
|
||||
white-space: normal;
|
||||
background: #2d2d2d;
|
||||
}
|
||||
|
||||
html[class="dark"] .token.comment,
|
||||
html[class="dark"] .token.block-comment,
|
||||
html[class="dark"] .token.prolog,
|
||||
html[class="dark"] .token.doctype,
|
||||
html[class="dark"] .token.cdata {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
html[class="dark"] .token.punctuation {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
html[class="dark"] .token.tag,
|
||||
html[class="dark"] .token.attr-name,
|
||||
html[class="dark"] .token.namespace,
|
||||
html[class="dark"] .token.deleted {
|
||||
color: #e2777a;
|
||||
}
|
||||
|
||||
html[class="dark"] .token.function-name {
|
||||
color: #6196cc;
|
||||
}
|
||||
|
||||
html[class="dark"] .token.boolean,
|
||||
html[class="dark"] .token.number,
|
||||
html[class="dark"] .token.function {
|
||||
color: #f08d49;
|
||||
}
|
||||
|
||||
html[class="dark"] .token.property,
|
||||
html[class="dark"] .token.class-name,
|
||||
html[class="dark"] .token.constant,
|
||||
html[class="dark"] .token.symbol {
|
||||
color: #f8c555;
|
||||
}
|
||||
|
||||
html[class="dark"] .token.selector,
|
||||
html[class="dark"] .token.important,
|
||||
html[class="dark"] .token.atrule,
|
||||
html[class="dark"] .token.keyword,
|
||||
html[class="dark"] .token.builtin {
|
||||
color: #cc99cd;
|
||||
}
|
||||
|
||||
html[class="dark"] .token.string,
|
||||
html[class="dark"] .token.char,
|
||||
html[class="dark"] .token.attr-value,
|
||||
html[class="dark"] .token.regex,
|
||||
html[class="dark"] .token.variable {
|
||||
color: #7ec699;
|
||||
}
|
||||
|
||||
html[class="dark"] .token.operator,
|
||||
html[class="dark"] .token.entity,
|
||||
html[class="dark"] .token.url {
|
||||
color: #67cdcc;
|
||||
}
|
||||
|
||||
html[class="dark"] .token.important,
|
||||
html[class="dark"] .token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
html[class="dark"] .token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
html[class="dark"] .token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
html[class="dark"] .token.inserted {
|
||||
color: green;
|
||||
}
|
||||
|
||||
html:not(.dark) code[class*="language-"],
|
||||
html:not(.dark) pre[class*="language-"] {
|
||||
color: black;
|
||||
background: none;
|
||||
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
|
||||
font-size: 1em;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
html:not(.dark) pre[class*="language-"] {
|
||||
position: relative;
|
||||
margin: 0.5em 0;
|
||||
overflow: scroll;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
html:not(.dark) pre[class*="language-"] {
|
||||
position: relative;
|
||||
border: 1px solid transparent;
|
||||
border-left: 4px solid;
|
||||
border-color: rgba(49, 46, 129);
|
||||
background-color: #fdfdfd;
|
||||
background-image: linear-gradient(
|
||||
transparent 50%,
|
||||
rgba(69, 142, 209, 0.04) 50%
|
||||
);
|
||||
background-size: 3em 3em;
|
||||
background-origin: content-box;
|
||||
background-attachment: local;
|
||||
}
|
||||
|
||||
html:not(.dark) code[class*="language-"] {
|
||||
max-height: inherit;
|
||||
height: inherit;
|
||||
display: block;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
html:not(.dark) :not(pre) > code[class*="language-"] {
|
||||
position: relative;
|
||||
padding: 0.2em;
|
||||
border-radius: 0.3em;
|
||||
color: #c92c2c;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
display: inline;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
html:not(.dark) :not(pre) > code {
|
||||
position: relative;
|
||||
padding: 0.2em;
|
||||
border-radius: 0.3em;
|
||||
color: #c92c2c;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
display: inline;
|
||||
white-space: normal;
|
||||
background-color: #fefafafa;
|
||||
}
|
||||
|
||||
html:not(.dark) .token.comment,
|
||||
html:not(.dark) .token.block-comment,
|
||||
html:not(.dark) .token.prolog,
|
||||
html:not(.dark) .token.doctype,
|
||||
html:not(.dark) .token.cdata {
|
||||
color: #7d8b99;
|
||||
}
|
||||
|
||||
html:not(.dark) .token.punctuation {
|
||||
color: #5f6364;
|
||||
}
|
||||
|
||||
html:not(.dark) .token.property,
|
||||
html:not(.dark) .token.tag,
|
||||
html:not(.dark) .token.boolean,
|
||||
html:not(.dark) .token.number,
|
||||
html:not(.dark) .token.function-name,
|
||||
html:not(.dark) .token.constant,
|
||||
html:not(.dark) .token.symbol,
|
||||
html:not(.dark) .token.deleted {
|
||||
color: #c92c2c;
|
||||
}
|
||||
|
||||
html:not(.dark) .token.selector,
|
||||
html:not(.dark) .token.attr-name,
|
||||
html:not(.dark) .token.string,
|
||||
html:not(.dark) .token.char,
|
||||
html:not(.dark) .token.function,
|
||||
html:not(.dark) .token.builtin,
|
||||
html:not(.dark) .token.inserted {
|
||||
color: #2f9c0a;
|
||||
}
|
||||
|
||||
html:not(.dark) .token.operator,
|
||||
html:not(.dark) .token.entity,
|
||||
html:not(.dark) .token.url,
|
||||
html:not(.dark) .token.variable {
|
||||
color: #a67f59;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
html:not(.dark) .token.atrule,
|
||||
html:not(.dark) .token.attr-value,
|
||||
html:not(.dark) .token.keyword,
|
||||
html:not(.dark) .token.class-name {
|
||||
color: #1990b8;
|
||||
}
|
||||
|
||||
html:not(.dark) .token.regex,
|
||||
html:not(.dark) .token.important {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
html:not(.dark) .language-css .token.string,
|
||||
html:not(.dark) .style .token.string {
|
||||
color: #a67f59;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
html:not(.dark) .token.important {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
html:not(.dark) .token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
html:not(.dark) .token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
html:not(.dark) .token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
html:not(.dark) .token.namespace {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
html:not(.dark) pre[class*="language-"]:before,
|
||||
html:not(.dark) pre[class*="language-"]:after {
|
||||
bottom: 14px;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Plugin styles: Line Numbers */
|
||||
html:not(.dark) pre[class*="language-"].line-numbers.line-numbers {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
html:not(.dark) pre[class*="language-"].line-numbers.line-numbers code {
|
||||
padding-left: 3.8em;
|
||||
}
|
||||
|
||||
html:not(.dark)
|
||||
pre[class*="language-"].line-numbers.line-numbers
|
||||
.line-numbers-rows {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* Plugin styles: Line Highlight */
|
||||
html:not(.dark) pre[class*="language-"][data-line] {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
html:not(.dark) pre[data-line] code {
|
||||
position: relative;
|
||||
padding-left: 4em;
|
||||
}
|
||||
|
||||
html:not(.dark) pre .line-highlight {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
pre[data-line] {
|
||||
position: relative;
|
||||
padding: 1em 0 1em 3em;
|
||||
}
|
||||
|
||||
.line-highlight {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: inherit 0;
|
||||
margin-top: 1em; /* Same as .prism’s padding-top */
|
||||
|
||||
background: hsla(24, 20%, 50%, 0.08);
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
hsla(24, 20%, 50%, 0.1) 70%,
|
||||
hsla(24, 20%, 50%, 0)
|
||||
);
|
||||
|
||||
pointer-events: none;
|
||||
|
||||
line-height: inherit;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.line-highlight {
|
||||
/*
|
||||
* This will prevent browsers from replacing the background color with white.
|
||||
* It's necessary because the element is layered on top of the displayed code.
|
||||
*/
|
||||
-webkit-print-color-adjust: exact;
|
||||
color-adjust: exact;
|
||||
}
|
||||
}
|
||||
|
||||
.line-highlight:before,
|
||||
.line-highlight[data-end]:after {
|
||||
content: attr(data-start);
|
||||
position: absolute;
|
||||
top: 0.4em;
|
||||
left: 0.6em;
|
||||
min-width: 1em;
|
||||
padding: 0 0.5em;
|
||||
background-color: hsla(24, 20%, 50%, 0.4);
|
||||
color: hsl(24, 20%, 95%);
|
||||
font: bold 65%/1.5 sans-serif;
|
||||
text-align: center;
|
||||
vertical-align: 0.3em;
|
||||
border-radius: 999px;
|
||||
text-shadow: none;
|
||||
box-shadow: 0 1px white;
|
||||
}
|
||||
|
||||
.line-highlight[data-end]:after {
|
||||
content: attr(data-end);
|
||||
top: auto;
|
||||
bottom: 0.4em;
|
||||
}
|
||||
|
||||
.line-numbers .line-highlight:before,
|
||||
.line-numbers .line-highlight:after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
pre[id].linkable-line-numbers span.line-numbers-rows {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
pre[id].linkable-line-numbers span.line-numbers-rows > span:before {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
pre[id].linkable-line-numbers span.line-numbers-rows > span:hover:before {
|
||||
background-color: rgba(128, 128, 128, 0.2);
|
||||
}
|
||||
|
||||
pre[class*="language-"].line-numbers {
|
||||
position: relative;
|
||||
padding-left: 3.8em;
|
||||
counter-reset: linenumber;
|
||||
}
|
||||
|
||||
pre[class*="language-"].line-numbers > code {
|
||||
position: relative;
|
||||
white-space: inherit;
|
||||
}
|
||||
|
||||
.line-numbers .line-numbers-rows {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
top: 0;
|
||||
font-size: 100%;
|
||||
left: -3.8em;
|
||||
width: 3em; /* works for line-numbers below 1000 lines */
|
||||
letter-spacing: -1px;
|
||||
border-right: 1px solid #999;
|
||||
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.line-numbers-rows > span {
|
||||
display: block;
|
||||
counter-increment: linenumber;
|
||||
}
|
||||
|
||||
.line-numbers-rows > span:before {
|
||||
content: counter(linenumber);
|
||||
color: #999;
|
||||
display: block;
|
||||
padding-right: 0.8em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.code-toolbar {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar {
|
||||
position: absolute;
|
||||
top: 0.3em;
|
||||
right: 0.2em;
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar .toolbar-item {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
html div.code-toolbar > .toolbar button {
|
||||
background: none;
|
||||
border: 0;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
line-height: normal;
|
||||
overflow: visible;
|
||||
padding: 0;
|
||||
-webkit-user-select: none; /* for button */
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
html[class="dark"] div.code-toolbar > .toolbar a,
|
||||
html[class="dark"] div.code-toolbar > .toolbar button,
|
||||
html[class="dark"] div.code-toolbar > .toolbar span {
|
||||
color: #bbb;
|
||||
font-size: 0.8em;
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
|
||||
html:not(.dark) div.code-toolbar > .toolbar a,
|
||||
html:not(.dark) div.code-toolbar > .toolbar button,
|
||||
html:not(.dark) div.code-toolbar > .toolbar span {
|
||||
color: rgb(40, 40, 40);
|
||||
font-size: 0.8em;
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar a:hover,
|
||||
div.code-toolbar > .toolbar a:focus,
|
||||
div.code-toolbar > .toolbar button:hover,
|
||||
div.code-toolbar > .toolbar button:focus,
|
||||
div.code-toolbar > .toolbar span:hover,
|
||||
div.code-toolbar > .toolbar span:focus {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
510
assets/css/site.css
Normal file
@ -0,0 +1,510 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
img {
|
||||
@apply rounded-lg shadow-lg block mx-auto h-auto;
|
||||
}
|
||||
|
||||
/* Left sidebar */
|
||||
|
||||
.sidebar .navitem {
|
||||
@apply text-gray-400 hover:text-white px-1;
|
||||
}
|
||||
|
||||
.sidebar .navitem.active {
|
||||
@apply text-white;
|
||||
}
|
||||
|
||||
div.menu li {
|
||||
@apply leading-12;
|
||||
}
|
||||
|
||||
div.menu ul > li:last-child > a {
|
||||
margin-right: -3px;
|
||||
max-width: calc(100% - 3px);
|
||||
}
|
||||
|
||||
div.menu ul > li:last-child::after {
|
||||
visibility: hidden;
|
||||
content: "";
|
||||
position: relative;
|
||||
right: -8.8rem;
|
||||
width: 3px;
|
||||
background-color: white;
|
||||
pointer-events: none;
|
||||
border-right: solid 2px white;
|
||||
transition: top 0.5s ease;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1280px) {
|
||||
div.menu ul > li:last-child::after {
|
||||
right: -6.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
div.menu ul > li.active:nth-child(1) ~ li:last-child::after,
|
||||
div.menu ul > li.navitem:nth-child(1):hover ~ li:last-child::after {
|
||||
top: -12rem;
|
||||
visibility: visible;
|
||||
}
|
||||
div.menu ul > li.active:nth-child(2) ~ li:last-child::after,
|
||||
div.menu ul > li.navitem:nth-child(2):hover ~ li:last-child::after {
|
||||
top: -9rem;
|
||||
visibility: visible;
|
||||
}
|
||||
div.menu ul > li.active:nth-child(3) ~ li:last-child::after,
|
||||
div.menu ul > li.navitem:nth-child(3):hover ~ li:last-child::after {
|
||||
top: -6rem;
|
||||
visibility: visible;
|
||||
}
|
||||
div.menu ul > li.active:nth-child(4):last-child::after,
|
||||
div.menu ul > li.navitem:nth-child(4):last-child:hover::after {
|
||||
top: -3rem;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
div.menu > * {
|
||||
transition: transform 0.4s ease;
|
||||
}
|
||||
|
||||
/* SVGs */
|
||||
|
||||
html[class="dark"] svg {
|
||||
fill: #9ca3af;
|
||||
stroke: #9ca3af;
|
||||
}
|
||||
|
||||
html[class="dark"] .social svg:hover {
|
||||
fill: white;
|
||||
stroke: white;
|
||||
}
|
||||
|
||||
html:not(.dark) svg.twitter {
|
||||
fill: #1da1f2;
|
||||
stroke: #1da1f2;
|
||||
}
|
||||
|
||||
html:not(.dark) svg.twitter:hover {
|
||||
fill: #1b90d8;
|
||||
stroke: #1b90d8;
|
||||
}
|
||||
|
||||
html:not(.dark) svg.facebook {
|
||||
fill: #4267b2;
|
||||
stroke: #4267b2;
|
||||
}
|
||||
|
||||
html:not(.dark) svg.facebook:hover {
|
||||
fill: #375593;
|
||||
stroke: #375593;
|
||||
}
|
||||
|
||||
html:not(.dark) svg.linkedin {
|
||||
fill: #0072b1;
|
||||
stroke: #0072b1;
|
||||
}
|
||||
|
||||
html:not(.dark) svg.linkedin:hover {
|
||||
fill: #006398;
|
||||
stroke: #006398;
|
||||
}
|
||||
|
||||
html[class="dark"] svg.darktoggle {
|
||||
@apply hidden;
|
||||
}
|
||||
|
||||
html:not(.dark) svg.lighttoggle {
|
||||
@apply hidden;
|
||||
}
|
||||
|
||||
.sidebar svg {
|
||||
fill: #9ca3af;
|
||||
stroke: #9ca3af;
|
||||
@apply transition duration-200 ease-in;
|
||||
}
|
||||
|
||||
.sidebar svg:hover {
|
||||
fill: #fff;
|
||||
stroke: #fff;
|
||||
}
|
||||
|
||||
/* Content area */
|
||||
|
||||
.content,
|
||||
.postlist {
|
||||
@apply mt-8 mx-8 lg:mr-32 lg:ml-32 leading-relaxed tracking-wider;
|
||||
}
|
||||
|
||||
.content a {
|
||||
@apply text-indigo-900 dark:text-indigo-300 underline;
|
||||
}
|
||||
|
||||
.content p {
|
||||
@apply pb-4 pt-2 font-light dark:font-extralight;
|
||||
}
|
||||
|
||||
.content blockquote {
|
||||
@apply border-l-2 border-gray-300 dark:border-gray-600 my-4;
|
||||
}
|
||||
|
||||
.content blockquote > p {
|
||||
@apply ml-4 py-2;
|
||||
}
|
||||
|
||||
.content h1 {
|
||||
@apply text-2xl dark:font-light py-6 mt-4;
|
||||
}
|
||||
|
||||
.content h2 {
|
||||
@apply text-xl mt-6;
|
||||
}
|
||||
|
||||
.content h3 {
|
||||
@apply text-lg mt-6;
|
||||
}
|
||||
|
||||
.content ol {
|
||||
@apply list-decimal pl-10 leading-8;
|
||||
}
|
||||
|
||||
.content ul {
|
||||
@apply list-disc pl-10 leading-8;
|
||||
}
|
||||
|
||||
.content table {
|
||||
@apply table-auto w-full;
|
||||
}
|
||||
|
||||
.content table thead tr {
|
||||
@apply leading-12;
|
||||
}
|
||||
|
||||
.content table tbody tr:nth-child(even) {
|
||||
@apply dark:bg-dark-heading;
|
||||
}
|
||||
|
||||
.content table tbody tr:nth-child(odd) {
|
||||
@apply bg-gray-100 dark:bg-sidebar-dark;
|
||||
}
|
||||
|
||||
.content img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.social svg {
|
||||
@apply h-5 ml-2 mr-3;
|
||||
}
|
||||
|
||||
.social a {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.social a::before {
|
||||
content: attr(aria-label);
|
||||
position: absolute;
|
||||
transform: translateY(-50%);
|
||||
top: -42px;
|
||||
left: -45px;
|
||||
width: 150px;
|
||||
padding: 10px;
|
||||
background: #000;
|
||||
border-radius: 0.3rem;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
opacity: 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.social a.link:active::before {
|
||||
content: "Copied";
|
||||
top: -33px;
|
||||
}
|
||||
|
||||
.social a:hover::before {
|
||||
opacity: 1;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.social a:hover > span::after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: -14px;
|
||||
left: 7px;
|
||||
margin-bottom: -5px;
|
||||
border-width: 8px;
|
||||
border-style: solid;
|
||||
border-color: black transparent transparent transparent;
|
||||
}
|
||||
|
||||
/* Utils */
|
||||
|
||||
.readingtime {
|
||||
@apply cursor-default;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.readingtime::before {
|
||||
content: attr(data-words);
|
||||
position: absolute;
|
||||
transform: translateY(-50%);
|
||||
bottom: -49px;
|
||||
right: 1px;
|
||||
width: 100px;
|
||||
padding: 4px;
|
||||
background: #000;
|
||||
border-radius: 0.3rem;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
opacity: 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
div.readingtime:hover::before {
|
||||
opacity: 1;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.readingtime:hover > span::after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 11px;
|
||||
right: 41px;
|
||||
margin-bottom: -5px;
|
||||
border-width: 8px;
|
||||
border-style: solid;
|
||||
border-color: transparent transparent black transparent;
|
||||
}
|
||||
|
||||
.content.post > p > a:hover,
|
||||
.content.page a:hover,
|
||||
a.postlistheading:hover,
|
||||
.postlist a:hover,
|
||||
#recents a:hover,
|
||||
#top-bar a:hover {
|
||||
@apply text-red-500 underline;
|
||||
}
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Right sidebar */
|
||||
|
||||
#toc {
|
||||
transition: top 0.2s ease-in-out;
|
||||
animation: fadeup-content 0.8s;
|
||||
}
|
||||
|
||||
nav.toc {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
nav.toc ol {
|
||||
@apply list-none;
|
||||
transition: top 0.4s ease;
|
||||
}
|
||||
|
||||
nav.toc li {
|
||||
@apply leading-8;
|
||||
}
|
||||
|
||||
nav.toc a {
|
||||
@apply no-underline block;
|
||||
padding-left: 18px;
|
||||
margin-left: -9px;
|
||||
}
|
||||
|
||||
nav.toc a:active,
|
||||
nav.toc a:hover {
|
||||
@apply text-indigo-900 dark:text-indigo-300;
|
||||
border-left: 1px solid;
|
||||
padding-left: 17px;
|
||||
}
|
||||
|
||||
nav.toc a.active {
|
||||
@apply text-indigo-900 dark:text-indigo-300 font-bold;
|
||||
border-left: 2px solid;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
nav.toc ol ol a,
|
||||
nav.toc ol ol a:hover,
|
||||
nav.toc ol ol a:active,
|
||||
nav.toc ol ol a.active {
|
||||
padding-left: 26px;
|
||||
}
|
||||
|
||||
nav.toc ol ol a:active,
|
||||
nav.toc ol ol a:hover {
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
nav.toc ol ol a.active {
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
/* Collection pagination */
|
||||
|
||||
ul.pagination div {
|
||||
@apply h-8 w-8 border-1 dark:text-gray-400 bg-white dark:bg-gray-700 hover:bg-indigo-800 dark:hover:bg-gray-600 border-gray-600 hover:text-white rounded-full text-center;
|
||||
}
|
||||
|
||||
html:not(.dark) ul.pagination div.active {
|
||||
@apply text-white bg-indigo-800;
|
||||
box-shadow: 0 0 8px 0 rgba(55, 48, 163);
|
||||
}
|
||||
|
||||
html[class="dark"] ul.pagination div.active {
|
||||
@apply bg-indigo-900;
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
@apply text-gray-800;
|
||||
}
|
||||
|
||||
:-ms-input-placeholder {
|
||||
@apply text-gray-800;
|
||||
}
|
||||
|
||||
#top-bar.hide {
|
||||
@apply transform -translate-y-12;
|
||||
}
|
||||
|
||||
.additions a {
|
||||
@apply no-underline;
|
||||
}
|
||||
|
||||
.additions div {
|
||||
@apply text-gray-700 dark:text-gray-400 bg-white dark:bg-dark-body border-gray-600 no-underline;
|
||||
}
|
||||
|
||||
.additions div:hover {
|
||||
@apply no-underline;
|
||||
}
|
||||
|
||||
.scroll {
|
||||
@apply bg-white dark:bg-gray-700 w-12 h-12 border-indigo-900 border-solid border-1;
|
||||
position: fixed;
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
bottom: 80px;
|
||||
right: 60px;
|
||||
opacity: 0.8;
|
||||
border-radius: 50%;
|
||||
z-index: 9;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
animation: fadeup-scrolltop 0.7s;
|
||||
}
|
||||
|
||||
@media all and (max-width: 400px) {
|
||||
.scroll {
|
||||
bottom: 40px;
|
||||
right: 40px;
|
||||
animation: fadeup-scrolltop-mobile 0.7s;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll svg {
|
||||
@apply stroke-current fill-current;
|
||||
}
|
||||
|
||||
@keyframes fadeup-content {
|
||||
0% {
|
||||
opacity: 0;
|
||||
position: relative;
|
||||
top: 2rem;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
position: relative;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeup-scrolltop {
|
||||
0% {
|
||||
opacity: 0;
|
||||
bottom: 20px;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.8;
|
||||
bottom: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeup-scrolltop-mobile {
|
||||
0% {
|
||||
opacity: 0;
|
||||
bottom: 20px;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.8;
|
||||
bottom: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Syntax highlighting */
|
||||
|
||||
pre {
|
||||
@apply rounded-md;
|
||||
}
|
||||
|
||||
div.code-toolbar {
|
||||
@apply w-full;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar {
|
||||
margin-top: -5px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar a,
|
||||
div.code-toolbar > .toolbar button,
|
||||
div.code-toolbar > .toolbar span {
|
||||
background: unset;
|
||||
box-shadow: unset;
|
||||
border-radius: unset;
|
||||
}
|
||||
|
||||
@media print {
|
||||
#sidebar #sidebar-contents {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#right-area #top-bar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#scroll {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
aside {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#search-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
main .content .social {
|
||||
display: none;
|
||||
}
|
||||
|
||||
main .content.border-b-1,
|
||||
main .block.border-b-1 {
|
||||
border-bottom-width: 0px;
|
||||
}
|
||||
|
||||
main .content .additions {
|
||||
display: none;
|
||||
}
|
||||
}
|
BIN
assets/favicons/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
assets/favicons/android-chrome-256x256.png
Normal file
After Width: | Height: | Size: 115 KiB |
BIN
assets/favicons/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 61 KiB |
9
assets/favicons/browserconfig.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/assets/favicons/mstile-150x150.png"/>
|
||||
<TileColor>#ffc40d</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
BIN
assets/favicons/favicon-16x16.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/favicons/favicon-32x32.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
assets/favicons/favicon.ico
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
assets/favicons/mstile-150x150.png
Normal file
After Width: | Height: | Size: 34 KiB |
254
assets/favicons/safari-pinned-tab.svg
Normal file
@ -0,0 +1,254 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="340.000000pt" height="340.000000pt" viewBox="0 0 340.000000 340.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,340.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M366 3349 c-27 -27 -46 -53 -42 -56 3 -3 7 -4 9 -2 1 2 24 28 52 57
|
||||
27 28 45 52 40 52 -6 0 -32 -23 -59 -51z"/>
|
||||
<path d="M586 3335 c31 -35 60 -66 63 -67 19 -8 62 -79 55 -90 -6 -10 -3 -9 9
|
||||
1 9 7 17 25 16 40 0 14 -3 20 -6 13 -3 -8 -38 21 -92 78 -101 104 -129 120
|
||||
-45 25z"/>
|
||||
<path d="M857 3357 c-39 -44 -36 -65 5 -24 51 53 62 67 47 66 -8 0 -31 -19
|
||||
-52 -42z"/>
|
||||
<path d="M1019 3383 c5 -10 19 -28 30 -40 12 -12 21 -26 21 -30 0 -5 9 -17 21
|
||||
-26 14 -12 17 -22 11 -30 -5 -7 -5 -23 -1 -37 4 -16 7 -19 8 -7 1 9 5 17 11
|
||||
17 5 0 7 -7 3 -16 -3 -8 4 -25 17 -39 19 -20 21 -27 11 -39 -11 -13 -9 -13 13
|
||||
-3 13 6 21 14 18 17 -4 3 -8 13 -10 22 -2 14 2 13 24 -7 23 -21 28 -23 41 -10
|
||||
15 15 33 12 33 -6 0 -6 -4 -8 -9 -5 -13 9 -30 -17 -26 -39 2 -11 4 -23 4 -27
|
||||
1 -11 41 -10 41 0 0 4 -5 13 -12 20 -15 15 -4 15 25 1 21 -10 21 -9 -2 10 -13
|
||||
12 -18 21 -13 21 6 0 14 -4 17 -10 9 -14 45 -13 45 2 0 6 3 9 6 5 8 -8 64 13
|
||||
64 24 0 5 4 9 9 9 4 0 7 -11 6 -25 -2 -14 1 -25 6 -25 5 0 9 4 9 8 0 12 40 9
|
||||
41 -3 3 -23 6 -51 7 -68 1 -10 6 -16 11 -12 5 3 16 -2 24 -10 19 -18 56 -20
|
||||
61 -2 2 6 7 21 12 32 6 18 8 18 11 3 3 -12 14 -18 31 -18 15 0 41 -7 57 -16
|
||||
17 -9 42 -23 58 -31 15 -8 27 -20 28 -26 0 -7 2 -22 3 -35 2 -15 -2 -21 -10
|
||||
-18 -11 4 -11 2 -1 -14 6 -11 15 -20 20 -20 4 0 5 -4 2 -10 -3 -5 1 -10 11
|
||||
-10 12 0 14 -3 6 -13 -8 -10 -5 -20 13 -41 13 -15 29 -25 35 -21 6 3 10 3 9
|
||||
-2 -5 -22 14 -43 35 -38 11 2 15 2 9 -1 -21 -10 -14 -33 11 -40 14 -3 32 -14
|
||||
41 -24 16 -18 16 -19 -9 -26 -19 -5 -26 -13 -26 -31 0 -19 3 -23 13 -16 6 6
|
||||
22 12 33 15 17 4 20 2 17 -13 -3 -11 -1 -19 5 -19 7 0 4 -13 -6 -31 -13 -24
|
||||
-14 -33 -4 -36 6 -3 10 -9 7 -14 -4 -5 2 -6 11 -2 15 5 16 1 10 -30 -5 -29 -2
|
||||
-40 17 -61 l24 -26 21 23 c12 13 22 34 22 48 1 41 27 134 45 163 10 15 37 38
|
||||
61 52 23 14 48 31 54 39 14 17 95 21 105 5 10 -16 25 -12 25 6 0 9 16 50 35
|
||||
90 29 59 46 80 94 117 33 25 58 46 56 48 -2 2 6 5 18 6 12 1 60 8 106 15 72
|
||||
10 87 10 110 -3 22 -13 31 -13 56 -3 17 7 41 14 55 14 23 1 23 2 5 10 -22 10
|
||||
-14 12 48 14 23 1 36 -3 33 -9 -2 -7 19 -15 50 -21 59 -11 62 -5 6 12 -32 10
|
||||
-34 12 -11 13 14 1 40 -6 57 -15 35 -17 53 -37 25 -28 -15 6 -15 4 2 -9 23
|
||||
-18 39 -22 30 -7 -9 15 21 12 32 -2 6 -7 13 -27 16 -44 5 -26 2 -34 -16 -43
|
||||
-19 -10 -20 -11 -2 -7 45 10 175 17 185 11 8 -5 2 -17 -15 -35 -15 -16 -26
|
||||
-30 -25 -32 7 -9 -13 -48 -21 -42 -6 3 -5 12 3 22 11 15 11 15 -3 5 -14 -11
|
||||
-12 -20 18 -80 18 -38 39 -93 47 -123 8 -30 15 -45 15 -34 1 12 -6 41 -14 64
|
||||
-19 53 -19 62 0 30 13 -22 15 3 14 227 0 207 -3 251 -14 247 -8 -3 -16 4 -20
|
||||
16 -15 47 -12 72 12 101 27 32 25 62 -4 53 -11 -4 -14 -3 -7 3 6 4 13 19 16
|
||||
33 3 14 9 33 13 43 4 11 3 17 -5 17 -6 0 -14 -9 -17 -20 -4 -16 -8 -18 -19 -9
|
||||
-11 9 -14 7 -15 -7 -1 -14 -3 -13 -8 5 -4 14 -12 26 -19 29 -13 4 -12 -24 3
|
||||
-94 6 -25 2 -36 -20 -60 -17 -18 -25 -22 -21 -11 3 9 2 17 -2 17 -4 0 -8 9 -9
|
||||
20 -2 22 13 28 19 8 3 -8 6 -9 11 -1 9 14 -13 40 -43 48 -21 7 -23 6 -13 -7
|
||||
10 -11 8 -18 -8 -32 -20 -17 -21 -17 -14 3 3 10 2 22 -3 25 -5 3 -8 24 -7 46
|
||||
2 39 1 40 -30 40 -23 0 -39 -9 -59 -30 -15 -17 -31 -28 -37 -25 -5 4 -8 2 -7
|
||||
-3 2 -6 -14 -31 -36 -57 -35 -43 -40 -45 -55 -31 -12 13 -13 20 -4 34 9 15 7
|
||||
21 -8 30 -20 13 -24 4 -20 -38 1 -11 -1 -11 -9 3 -6 9 -20 17 -30 17 -11 0
|
||||
-20 7 -20 15 0 8 5 15 10 15 15 0 49 37 42 45 -4 3 0 10 8 15 9 6 -317 10
|
||||
-867 10 l-883 -1 0 -21 c0 -16 -5 -19 -23 -16 -13 2 -29 -1 -35 -9 -15 -15
|
||||
-42 -17 -42 -3 0 6 -5 10 -11 10 -5 0 -7 -6 -4 -12 4 -7 -7 2 -24 20 -34 35
|
||||
-58 44 -42 15z m2148 -75 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z
|
||||
m-1727 -98 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4
|
||||
11 -10z m-190 -29 c0 -5 -7 -11 -15 -15 -9 -3 -15 0 -15 9 0 8 7 15 15 15 8 0
|
||||
15 -4 15 -9z m2077 -13 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z
|
||||
m3 -22 c0 -2 -7 -7 -16 -10 -8 -3 -12 -2 -9 4 6 10 25 14 25 6z m-1720 -52 c0
|
||||
-8 -4 -14 -10 -14 -5 0 -10 9 -10 21 0 11 5 17 10 14 6 -3 10 -13 10 -21z
|
||||
m1627 -36 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m140 0 c-3 -8
|
||||
-6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m-642 -39 c-38 -4 -83 -10 -100
|
||||
-13 -22 -4 -25 -3 -10 4 33 14 118 25 150 20 21 -3 9 -6 -40 -11z m155 -3 c0
|
||||
-2 -11 -6 -25 -8 -13 -3 -22 -1 -19 3 5 9 44 13 44 5z m460 -106 c0 -5 -5 -10
|
||||
-11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m18 -196 c-3 -16 -7
|
||||
-13 -21 13 -23 43 -21 52 4 26 12 -11 19 -29 17 -39z"/>
|
||||
<path d="M80 3291 c47 -45 99 -91 115 -102 28 -20 -30 39 -120 120 -81 73 -78
|
||||
61 5 -18z"/>
|
||||
<path d="M890 3271 c0 -6 4 -13 10 -16 6 -3 7 1 4 9 -7 18 -14 21 -14 7z"/>
|
||||
<path d="M1070 3199 c0 -11 4 -18 10 -14 5 3 7 12 3 20 -7 21 -13 19 -13 -6z"/>
|
||||
<path d="M1113 3178 c4 -11 0 -18 -11 -21 -9 -3 -5 -4 11 -4 31 2 34 9 10 28
|
||||
-15 12 -16 12 -10 -3z"/>
|
||||
<path d="M660 3150 c-8 -14 -8 -26 -2 -32 6 -6 12 0 16 17 9 35 1 43 -14 15z"/>
|
||||
<path d="M1460 3050 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
|
||||
-10 -4 -10 -10z"/>
|
||||
<path d="M3296 2555 c-9 -26 -7 -32 5 -12 6 10 9 21 6 23 -2 3 -7 -2 -11 -11z"/>
|
||||
<path d="M3266 2465 c-9 -26 -7 -32 5 -12 6 10 9 21 6 23 -2 3 -7 -2 -11 -11z"/>
|
||||
<path d="M3165 2360 c-3 -5 -1 -10 4 -10 6 0 11 5 11 10 0 6 -2 10 -4 10 -3 0
|
||||
-8 -4 -11 -10z"/>
|
||||
<path d="M824 2288 c3 -15 26 -23 26 -8 0 6 -4 9 -9 6 -5 -4 -12 -1 -14 4 -3
|
||||
6 -4 5 -3 -2z"/>
|
||||
<path d="M1091 2266 c7 -15 17 -22 26 -19 11 5 11 9 -3 24 -24 26 -36 24 -23
|
||||
-5z"/>
|
||||
<path d="M2710 2255 c-7 -8 -16 -13 -20 -10 -11 7 -86 -62 -77 -71 4 -4 19 3
|
||||
33 17 14 13 28 22 31 20 7 -5 53 37 53 49 0 14 -5 13 -20 -5z"/>
|
||||
<path d="M1075 2230 c21 -24 26 -25 19 -6 -3 8 -13 17 -22 21 -13 5 -13 2 3
|
||||
-15z"/>
|
||||
<path d="M1373 2216 c0 -14 3 -26 8 -26 11 0 11 21 0 39 -6 9 -8 5 -8 -13z"/>
|
||||
<path d="M590 2191 c0 -5 5 -13 10 -16 6 -3 10 -2 10 4 0 5 -4 13 -10 16 -5 3
|
||||
-10 2 -10 -4z"/>
|
||||
<path d="M2668 2179 c-38 -22 -11 -89 36 -89 47 0 63 57 24 84 -26 18 -36 19
|
||||
-60 5z"/>
|
||||
<path d="M1395 2160 c-3 -5 -1 -10 4 -10 6 0 11 5 11 10 0 6 -2 10 -4 10 -3 0
|
||||
-8 -4 -11 -10z"/>
|
||||
<path d="M3320 2145 c-32 -8 -62 -22 -72 -36 -16 -18 -22 -20 -41 -11 -24 11
|
||||
-57 13 -57 2 0 -4 -25 -13 -56 -20 -50 -12 -58 -12 -85 4 -16 9 -34 14 -39 11
|
||||
-6 -3 -10 2 -11 12 0 12 -2 13 -6 5 -3 -8 4 -22 16 -33 12 -11 21 -23 21 -26
|
||||
0 -4 -5 -2 -12 5 -7 7 -15 12 -20 12 -4 0 4 -11 17 -25 32 -31 32 -55 0 -55
|
||||
-13 0 -35 -5 -49 -11 -21 -10 -23 -14 -13 -30 17 -28 -6 -48 -34 -31 -19 12
|
||||
-20 11 -14 -10 4 -13 14 -27 21 -31 24 -14 15 -27 -17 -27 -28 0 -30 -2 -18
|
||||
-16 11 -14 11 -18 -4 -29 -17 -12 -17 -13 0 -19 17 -7 17 -8 0 -17 -14 -8 -15
|
||||
-14 -7 -24 17 -21 -29 -48 -61 -37 -18 7 -28 4 -43 -11 -16 -17 -17 -19 -3
|
||||
-14 9 3 17 3 17 -1 0 -4 14 -13 31 -19 21 -8 28 -16 23 -25 -6 -10 -5 -10 7
|
||||
-2 8 6 39 12 69 13 65 1 110 10 127 23 7 5 18 8 25 6 7 -3 1 -12 -17 -23 -17
|
||||
-11 -48 -34 -69 -52 -22 -18 -55 -36 -75 -39 -20 -4 -45 -13 -56 -20 -11 -8
|
||||
-28 -14 -39 -14 -11 0 -28 -7 -38 -17 -14 -13 -18 -13 -18 -2 -1 9 -4 8 -11
|
||||
-5 -10 -16 -19 -17 -68 -11 -69 9 -85 16 -138 68 -35 33 -50 41 -82 42 -21 0
|
||||
-37 4 -34 9 3 5 2 7 -3 5 -5 -2 -60 -24 -121 -48 -80 -31 -110 -47 -106 -57 3
|
||||
-8 0 -14 -7 -14 -6 0 -8 5 -5 10 7 11 -6 13 -29 4 -9 -3 -16 -11 -16 -18 0
|
||||
-14 -51 -15 -67 0 -6 6 -43 14 -82 18 -77 8 -83 13 -95 79 -4 20 -11 37 -15
|
||||
37 -4 0 -21 30 -36 68 -31 75 -80 168 -103 194 -8 10 -12 25 -8 35 7 16 6 16
|
||||
-12 0 -18 -17 -20 -16 -36 8 -22 34 -41 32 -41 -4 -1 -21 3 -27 10 -21 7 6 11
|
||||
2 12 -11 1 -10 -5 -19 -13 -19 -8 0 -14 -5 -14 -11 0 -5 -4 -8 -9 -5 -5 4 -11
|
||||
1 -13 -5 -3 -10 -16 -5 -90 41 -15 9 -17 7 -12 -7 5 -16 4 -16 -10 1 -9 11
|
||||
-16 23 -16 28 0 4 -11 8 -25 8 -14 0 -37 12 -51 26 -24 23 -25 26 -10 43 9 10
|
||||
16 27 16 39 0 11 7 25 16 30 10 6 12 12 6 16 -5 3 -17 -6 -26 -19 -9 -14 -21
|
||||
-23 -26 -20 -6 4 -10 0 -10 -7 0 -7 -7 0 -15 15 -10 20 -12 34 -5 46 7 13 5
|
||||
18 -6 18 -8 0 -13 -6 -10 -14 3 -8 -2 -13 -14 -13 -11 0 -20 7 -20 16 0 24
|
||||
-104 16 -108 -9 -4 -22 26 -59 41 -50 6 3 7 1 3 -6 -6 -9 -11 -9 -22 0 -11 9
|
||||
-17 9 -28 0 -8 -7 -16 -8 -18 -4 -3 4 -4 3 -2 -3 1 -5 -7 -21 -17 -35 -18 -22
|
||||
-20 -22 -18 -4 2 35 -1 46 -11 40 -5 -3 -7 0 -4 8 5 15 -21 31 -36 22 -5 -3
|
||||
-11 -1 -15 5 -3 5 -13 10 -22 10 -9 0 -30 11 -47 24 -29 21 -121 42 -110 24 3
|
||||
-5 11 -8 19 -8 7 0 15 -12 17 -27 2 -18 10 -29 23 -31 11 -3 28 -13 38 -23 17
|
||||
-18 17 -19 -8 -19 -16 0 -25 6 -25 15 0 8 -4 15 -9 15 -5 0 -22 5 -38 11 -25
|
||||
9 -26 11 -10 21 18 9 18 10 0 24 -10 7 -21 14 -25 14 -15 0 -8 -59 8 -74 11
|
||||
-12 14 -25 9 -47 -5 -22 -3 -34 6 -40 10 -6 11 -9 2 -9 -8 0 -13 -15 -13 -40
|
||||
0 -52 -23 -53 -76 -4 -23 22 -40 32 -42 25 -3 -8 -9 -5 -18 7 -7 11 -34 29
|
||||
-59 41 -29 13 -49 31 -56 47 -7 19 -15 25 -29 21 -11 -3 -29 3 -41 14 -22 19
|
||||
-39 17 -39 -4 0 -7 -8 -24 -17 -37 -10 -14 -16 -33 -15 -42 2 -10 -2 -27 -8
|
||||
-38 -9 -17 -8 -25 4 -39 18 -20 21 -57 5 -66 -7 -5 -4 -14 7 -26 16 -17 16
|
||||
-24 5 -55 -12 -33 -11 -37 8 -56 23 -21 21 -49 -4 -75 -11 -10 -15 -10 -24 1
|
||||
-6 7 -7 17 -3 22 4 4 0 3 -9 -4 -14 -11 -18 -9 -23 13 -8 31 -19 32 -35 2 -14
|
||||
-25 0 -109 18 -115 6 -2 11 -13 11 -25 0 -20 0 -20 15 -1 12 16 14 17 15 2 0
|
||||
-9 22 -49 49 -90 27 -40 51 -82 53 -93 3 -22 122 -149 159 -170 13 -8 36 -19
|
||||
51 -25 15 -7 34 -23 43 -37 12 -18 23 -23 38 -19 26 6 40 -4 90 -66 22 -28 50
|
||||
-51 65 -54 15 -4 47 -19 72 -34 25 -15 76 -40 113 -56 86 -37 152 -99 196
|
||||
-186 35 -70 53 -158 32 -158 -6 0 -16 -10 -22 -22 -9 -22 -9 -22 -4 2 15 63
|
||||
16 99 5 120 -11 20 -14 21 -27 7 -13 -13 -19 -13 -41 -1 -25 13 -28 12 -40
|
||||
-11 -7 -14 -17 -25 -23 -25 -6 0 -8 -9 -4 -22 6 -20 3 -19 -19 7 -14 17 -25
|
||||
38 -26 48 0 9 -3 17 -8 17 -4 0 -15 18 -25 40 -12 28 -23 40 -37 40 -11 0 -20
|
||||
4 -20 10 0 5 -6 7 -14 4 -9 -3 -12 -12 -9 -21 4 -11 2 -14 -5 -9 -7 4 -12 13
|
||||
-12 19 0 18 -34 44 -49 39 -8 -3 -11 0 -8 5 3 5 -4 10 -15 10 -19 2 -19 1 -3
|
||||
-17 10 -11 17 -31 17 -45 0 -15 7 -29 17 -33 19 -7 36 -31 36 -52 0 -8 11 -20
|
||||
24 -26 13 -7 28 -22 35 -35 8 -16 23 -26 46 -29 49 -7 49 -32 1 -79 -23 -22
|
||||
-41 -43 -41 -46 0 -10 40 -85 76 -140 l34 -55 -49 -102 c-27 -56 -47 -107 -44
|
||||
-115 4 -11 203 -13 1129 -13 l1124 0 0 1080 c0 858 -3 1080 -12 1079 -7 0 -38
|
||||
-7 -68 -14z m-154 -232 c-11 -11 -19 6 -11 24 8 17 8 17 12 0 3 -10 2 -21 -1
|
||||
-24z m-2092 -5 c27 -11 68 -19 90 -20 44 0 86 -15 99 -36 5 -7 14 -9 20 -6 7
|
||||
4 9 4 5 0 -4 -5 -3 -18 2 -31 7 -18 5 -24 -8 -27 -10 -3 -23 1 -30 9 -21 22
|
||||
-41 15 -59 -22 -18 -39 -12 -55 13 -34 14 12 16 11 13 -6 -7 -32 -43 -26 -47
|
||||
8 -2 15 -9 27 -16 27 -22 0 -84 63 -91 91 -5 20 -12 25 -25 22 -13 -3 -20 2
|
||||
-25 19 -4 12 -13 27 -19 31 -12 10 1 5 78 -25z m2136 -48 c10 -18 8 -20 -20
|
||||
-20 -28 0 -30 2 -20 20 6 11 15 20 20 20 5 0 14 -9 20 -20z m-67 -151 c4 -14
|
||||
0 -16 -26 -8 -33 9 -60 29 -40 29 7 0 15 10 19 22 l6 21 19 -24 c10 -13 20
|
||||
-31 22 -40z m-1603 -102 c0 -10 11 -28 25 -41 16 -15 20 -23 10 -23 -8 0 -15
|
||||
4 -15 9 0 4 -5 8 -11 8 -6 0 -8 -12 -6 -29 4 -24 2 -28 -15 -23 -11 3 -24 -3
|
||||
-33 -14 -8 -11 -14 -14 -15 -6 0 6 -5 12 -11 12 -5 0 -8 -4 -5 -8 3 -5 -1 -9
|
||||
-9 -9 -8 0 -15 5 -15 11 0 7 -9 19 -20 29 -22 18 -26 37 -9 37 6 0 20 12 31
|
||||
26 12 14 31 30 44 34 13 5 24 17 24 27 0 15 2 15 15 -3 8 -10 15 -27 15 -37z
|
||||
m-124 29 c19 -20 18 -26 -8 -26 -20 0 -20 -1 -5 -12 15 -12 14 -15 -8 -41 -13
|
||||
-15 -34 -28 -47 -30 -20 -2 -23 3 -26 35 -3 30 0 37 11 32 10 -3 17 4 21 21 5
|
||||
18 12 25 21 21 8 -3 15 -1 15 4 0 14 9 12 26 -4z m967 -71 c-3 -9 -8 -14 -10
|
||||
-11 -3 3 -2 9 2 15 9 16 15 13 8 -4z m27 -15 c0 -5 -2 -10 -4 -10 -3 0 -8 5
|
||||
-11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m-1120 -30 c0 -5 -2 -10 -4 -10 -3
|
||||
0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m960 -48 c0 -10 -81 -44 -88
|
||||
-37 -4 3 63 38 86 44 1 1 2 -3 2 -7z m-290 -17 c7 -8 18 -15 25 -15 22 0 60
|
||||
-39 48 -51 -7 -7 -24 -4 -56 10 -25 12 -49 21 -53 21 -8 0 -33 32 -34 43 0 13
|
||||
57 7 70 -8z m-130 -35 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10
|
||||
6 0 11 -4 11 -10z m185 -154 c18 -19 61 -49 93 -65 l60 -30 -8 -36 c-11 -51
|
||||
-52 -109 -129 -185 -66 -65 -141 -118 -141 -100 0 6 -6 10 -13 10 -8 0 -19 11
|
||||
-27 24 -7 14 -18 22 -26 19 -14 -5 -15 -1 -18 61 0 19 -4 32 -8 29 -15 -8 -8
|
||||
58 8 82 9 13 13 28 10 33 -3 5 6 19 19 32 13 13 22 27 19 31 -3 5 -1 9 4 9 6
|
||||
0 12 15 15 33 8 48 18 90 25 107 7 17 9 28 11 49 1 8 16 -3 36 -27 20 -22 51
|
||||
-57 70 -76z m1151 -251 c-10 -8 -24 -16 -30 -18 -6 -2 -8 -7 -5 -11 4 -4 25 0
|
||||
47 9 53 22 107 17 107 -9 0 -24 -71 -64 -86 -49 -7 7 0 14 20 23 17 7 31 16
|
||||
31 21 0 13 -32 10 -60 -6 -35 -20 -89 -19 -97 2 -8 21 31 53 66 53 25 -1 25
|
||||
-1 7 -15z m-128 -59 c15 -7 53 -19 85 -27 58 -12 75 -23 58 -33 -22 -14 -220
|
||||
52 -204 68 10 10 32 7 61 -8z m27 -83 c30 -10 54 -22 52 -28 -2 -5 -11 -9 -21
|
||||
-7 -9 2 -16 -4 -16 -12 0 -19 -61 -66 -87 -66 -10 0 -28 6 -38 14 -18 13 -18
|
||||
14 4 45 12 17 27 31 32 31 5 0 9 5 9 10 0 19 -30 10 -65 -21 -36 -32 -54 -34
|
||||
-38 -4 14 24 64 55 90 55 12 0 47 -8 78 -17z m-143 -130 c22 -20 23 -52 0 -78
|
||||
-49 -58 -112 -71 -157 -32 -24 20 -25 25 -14 55 6 19 25 42 43 53 38 23 103
|
||||
25 128 2z m-336 -155 c-25 -22 -44 -51 -56 -88 -16 -46 -19 -50 -20 -25 0 46
|
||||
70 144 104 145 5 0 -8 -15 -28 -32z m194 -58 c0 -4 -13 -25 -29 -46 -59 -81
|
||||
-112 -113 -146 -87 -19 14 -18 14 13 8 23 -5 40 -2 58 9 27 18 84 93 84 110 0
|
||||
6 -14 17 -32 25 -29 13 -33 13 -49 -7 -9 -12 -21 -22 -25 -22 -4 0 5 13 20 29
|
||||
l27 28 39 -20 c22 -10 40 -22 40 -27z m-213 -126 c-7 -7 -37 7 -37 17 0 6 9 5
|
||||
21 -1 11 -7 19 -14 16 -16z m-67 -51 c0 -5 -13 -8 -29 -8 -16 0 -27 3 -24 8 2
|
||||
4 15 7 29 7 13 0 24 -3 24 -7z m30 -23 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10
|
||||
10 0 6 5 10 10 10 6 0 10 -4 10 -10z m-128 -54 c-2 -18 1 -37 7 -40 6 -4 11
|
||||
-12 11 -17 0 -5 -9 -1 -20 9 -18 17 -21 47 -5 72 10 16 11 12 7 -24z m163 -13
|
||||
c-22 -35 -56 -73 -65 -73 -4 0 8 16 26 36 19 19 34 42 34 50 0 8 5 14 11 14 7
|
||||
0 4 -11 -6 -27z m-85 13 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21
|
||||
21 21 13z m0 -82 c0 -2 -11 -3 -24 -2 -14 1 -23 5 -20 9 4 7 44 0 44 -7z
|
||||
m-119 -177 c-10 -9 -11 -8 -5 6 3 10 9 15 12 12 3 -3 0 -11 -7 -18z"/>
|
||||
<path d="M3002 830 c-26 -24 -28 -40 -6 -40 27 0 54 20 54 40 0 26 -20 25 -48
|
||||
0z"/>
|
||||
<path d="M2815 731 c-36 -15 -61 -50 -49 -69 18 -28 91 -28 120 -1 29 27 31
|
||||
55 5 69 -23 12 -48 12 -76 1z"/>
|
||||
<path d="M2867 2127 c3 -4 11 -6 19 -3 8 3 14 -1 14 -9 0 -8 9 -15 20 -15 25
|
||||
0 26 15 3 26 -25 11 -63 12 -56 1z"/>
|
||||
<path d="M2409 2073 c-13 -16 -12 -17 4 -4 9 7 17 15 17 17 0 8 -8 3 -21 -13z"/>
|
||||
<path d="M2883 2083 c9 -2 23 -2 30 0 6 3 -1 5 -18 5 -16 0 -22 -2 -12 -5z"/>
|
||||
<path d="M1481 2064 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M2086 2057 c3 -10 9 -15 12 -12 3 3 0 11 -7 18 -10 9 -11 8 -5 -6z"/>
|
||||
<path d="M760 1979 c-14 -13 -18 -20 -9 -16 11 4 20 -3 28 -19 7 -16 16 -22
|
||||
24 -18 6 4 9 4 5 -1 -8 -9 9 -35 22 -35 13 0 -1 43 -20 65 -10 11 -19 26 -21
|
||||
33 -3 10 -11 7 -29 -9z"/>
|
||||
<path d="M2045 1990 c3 -5 13 -10 21 -10 8 0 14 5 14 10 0 6 -9 10 -21 10 -11
|
||||
0 -17 -4 -14 -10z"/>
|
||||
<path d="M2772 1978 c-1 -11 -8 -15 -17 -12 -9 4 -16 -2 -19 -18 -20 -99 -12
|
||||
-121 24 -62 14 25 20 49 17 73 -2 20 -4 28 -5 19z"/>
|
||||
<path d="M2511 1919 c-1 -24 6 -45 20 -60 19 -23 20 -23 10 -2 -6 12 -15 39
|
||||
-20 60 l-9 38 -1 -36z"/>
|
||||
<path d="M2563 1903 c-7 -2 -13 -10 -13 -17 0 -20 47 -58 67 -54 23 5 19 37
|
||||
-9 61 -21 18 -25 19 -45 10z"/>
|
||||
<path d="M2094 1870 c-10 -4 -18 -14 -20 -23 -1 -10 2 -15 7 -12 5 4 17 1 26
|
||||
-4 16 -9 15 -11 -7 -12 l-25 -1 25 -8 c14 -4 21 -9 15 -9 -13 -2 36 -30 53
|
||||
-31 15 0 61 -50 62 -67 0 -6 -9 -14 -20 -18 -11 -3 -28 -17 -38 -30 -14 -18
|
||||
-22 -21 -31 -12 -7 7 -11 8 -11 0 0 -15 25 -24 36 -13 5 5 15 6 22 1 9 -5 5
|
||||
-11 -13 -19 -31 -15 -65 -28 -88 -36 -16 -5 -16 -7 4 -30 17 -19 26 -23 43
|
||||
-16 11 5 66 28 122 52 l101 43 -33 17 c-30 16 -37 16 -70 2 -20 -8 -39 -13
|
||||
-42 -10 -3 3 11 13 32 21 l36 15 -47 60 c-32 40 -54 58 -66 56 -9 -2 -14 0
|
||||
-11 5 3 5 3 27 -1 47 -6 39 -20 46 -61 32z m16 -310 c0 -5 -2 -10 -4 -10 -3 0
|
||||
-8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z"/>
|
||||
<path d="M377 1783 c-9 -8 22 -43 37 -43 6 0 17 9 24 20 7 12 8 20 2 20 -5 0
|
||||
-10 -4 -10 -9 0 -5 -7 -12 -16 -15 -14 -5 -15 -4 -5 8 9 11 8 15 -5 20 -19 7
|
||||
-19 7 -27 -1z"/>
|
||||
<path d="M380 1726 c0 -2 8 -10 18 -17 15 -13 16 -12 3 4 -13 16 -21 21 -21
|
||||
13z"/>
|
||||
<path d="M2513 1713 c9 -2 23 -2 30 0 6 3 -1 5 -18 5 -16 0 -22 -2 -12 -5z"/>
|
||||
<path d="M2458 1663 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
|
||||
<path d="M2533 1663 c9 -2 25 -2 35 0 9 3 1 5 -18 5 -19 0 -27 -2 -17 -5z"/>
|
||||
<path d="M2785 1609 c-4 -6 -5 -12 -2 -15 2 -3 7 2 10 11 7 17 1 20 -8 4z"/>
|
||||
<path d="M2030 1590 c0 -5 7 -10 15 -10 8 0 15 5 15 10 0 6 -7 10 -15 10 -8 0
|
||||
-15 -4 -15 -10z"/>
|
||||
<path d="M211 811 c-12 -8 -12 -14 -3 -33 10 -20 12 -20 9 -3 -1 11 4 25 13
|
||||
32 17 14 2 17 -19 4z"/>
|
||||
<path d="M255 790 c-3 -5 -1 -10 4 -10 6 0 11 5 11 10 0 6 -2 10 -4 10 -3 0
|
||||
-8 -4 -11 -10z"/>
|
||||
<path d="M900 766 c0 -9 -8 -20 -17 -23 -15 -6 -15 -7 3 -14 18 -7 18 -8 0 -8
|
||||
-15 -1 -17 -8 -14 -46 2 -33 0 -44 -9 -40 -7 2 -13 -2 -13 -11 0 -14 14 -23
|
||||
42 -28 7 -1 18 -5 25 -9 6 -4 25 -6 42 -5 37 3 48 39 20 64 -11 10 -19 31 -19
|
||||
48 0 22 -9 40 -30 59 -23 22 -30 25 -30 13z"/>
|
||||
<path d="M685 650 c3 -5 11 -10 16 -10 6 0 7 5 4 10 -3 6 -11 10 -16 10 -6 0
|
||||
-7 -4 -4 -10z"/>
|
||||
<path d="M810 646 c0 -9 5 -16 10 -16 6 0 10 4 10 9 0 6 -4 13 -10 16 -5 3
|
||||
-10 -1 -10 -9z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 16 KiB |
19
assets/favicons/site.webmanifest
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "{ rene.winkelmeyer }",
|
||||
"short_name": "muenzpraeger",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/assets/favicons/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/assets/favicons/android-chrome-256x256.png",
|
||||
"sizes": "256x256",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
BIN
assets/images/2021/coolimage.jpg
Normal file
After Width: | Height: | Size: 189 KiB |
BIN
assets/images/404.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
assets/images/algolia.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
assets/images/opengraph.jpg
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
assets/images/sidebar_profile.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
18
assets/js/prism.js
Normal file
51
content/_data/siteconfig.js
Normal file
@ -0,0 +1,51 @@
|
||||
require("dotenv").config();
|
||||
|
||||
module.exports = {
|
||||
// Website title, shown in left sidebar and in page title
|
||||
title: "{ rené.winkelmeyer }",
|
||||
// Site URL to generate absolute URLs. Used across the board.
|
||||
url: process.env.URL || "http://localhost:8080",
|
||||
// Profile image for left sidebar
|
||||
image: "/assets/images/sidebar_profile.jpg",
|
||||
// Image alt text for left sidebar
|
||||
imageAlt: "René and Einstein",
|
||||
// Author name, shown in left sidebar, and used in JSON-LD
|
||||
author: "René Winkelmeyer",
|
||||
// Site description, shown below site image (optional)
|
||||
description: "My kitchen sink about stuff",
|
||||
// OpenGraph default image, in case you don't have an `image`
|
||||
// set in your Markdown frontmatter; relevant for social
|
||||
// sharing.
|
||||
openGraphDefaultImage: "/assets/images/opengraph.jpg",
|
||||
// GitHub ID (optional, remove it not needed), used for link in the left sidebar
|
||||
socialGitHub: "muenzpraeger",
|
||||
// LinkedIn ID (optional, remove it not needed), used for link in the left sidebar
|
||||
socialLinkedIn: "muenzpraeger",
|
||||
// Twitter ID (optional, remove it not needed), used for link in the left sidebar, and for OpenGraph sharing information
|
||||
socialTwitter: "muenzpraeger",
|
||||
// YouTube ID/Channel (optional, remove it not needed), used for link in the left sidebar
|
||||
socialYouTube: "UCH60RRaY2GI9m62z1loLjcA",
|
||||
// Google Analytics ID (optional, remove it not needed), used for... well, Google Analytics
|
||||
googleAnalytics: "YOUR_GA-ID",
|
||||
// Algolia-powered search (optional, remove it not needed),
|
||||
// See: https://github.com/algolia/algoliasearch-netlify
|
||||
algoliaSearch: {
|
||||
// When enabled shows the search bar in the UI
|
||||
enabled: true,
|
||||
// You'll have to set this manually in your build settings.
|
||||
// The value comes from Algolia, and is either visible in the
|
||||
// UI for the Crawler Plugin or the Algolia Dashboard.
|
||||
appId: process.env.ALGOLIA_APP_ID,
|
||||
// You'll have to set this manually in your build settings.
|
||||
// The value comes from Algolia, and is either visible in the
|
||||
// UI for the Crawler Plugin or the Algolia Dashboard.
|
||||
searchApiKey: process.env.ALGOLIA_SEARCH_API_KEY,
|
||||
// You'll have to set this manually in your build settings.
|
||||
// The value comes from Algolia, and is either visible in the
|
||||
// UI for the Crawler Plugin or the Algolia Dashboard.
|
||||
siteId: process.env.ALGOLIA_SITE_ID,
|
||||
// Assuming that you deploy your "main" branch. Otherwise you
|
||||
// can either override or configure this (using process.env.HEAD)
|
||||
branch: "main"
|
||||
}
|
||||
};
|
80
content/_includes/base.njk
Normal file
@ -0,0 +1,80 @@
|
||||
<!doctype html>
|
||||
<html lang="en" class="dark">
|
||||
<head>
|
||||
{% include "head.njk" %}
|
||||
{% include "json-ld.njk" %}
|
||||
</head>
|
||||
<body class="dark:text-gray-300 dark:bg-dark-body bg-white text-gray-900 tracking-wider font-light overflow-x-hidden sm:overflow-auto">
|
||||
<div class="grid grid-flow-col grid-cols-small sm:grid-cols-regular h-screen">
|
||||
<div id="sidebar" class="sidebar transition-transform transform -translate-x-56 sm:translate-x-0 sm:transition-none">
|
||||
{% include "sidebar.njk" %}
|
||||
</div>
|
||||
<div id="right-area" class="overflow-x-hidden sm:overflow-auto transition-transform transform sm:translate-x-0 sm:transition-none">
|
||||
<div id="top-bar" class="h-12 z-10 bg-white dark:bg-dark-heading transition-transform duration-200 ease-in sm:sticky top-0 border-gray-600 border-b-1 dark:border-transparent border-opacity-30 shadow-lg">
|
||||
<div class="grid grid-flow-col grid-cols-auto md:grid-cols-topbar max-w-content">
|
||||
<div id="mobile-top-bar" class="flex leading-12 sm:hidden col-span-2">
|
||||
<svg viewBox="0 0 100 80" class="block align-middle h-12 leading-12 ml-3 py-3 pt-4" onclick="slideLeftSidebar()">
|
||||
<rect width="60" height="7"></rect>
|
||||
<rect y="30" width="60" height="7"></rect>
|
||||
<rect y="60" width="60" height="7"></rect>
|
||||
</svg>
|
||||
<p class="flex-grow inline align-middle leading-12 text-xl text-center font-medium">{{ siteconfig.title }}</p>
|
||||
{% if siteconfig.algoliaSearch and siteconfig.algoliaSearch.enabled %}
|
||||
<svg viewBox="0 0 32 32" class="block align-middle h-12 leading-12 mr-3 py-3 pt-3" onclick="toggleSearch()">
|
||||
<path d="M27.414,24.586l-5.077-5.077C23.386,17.928,24,16.035,24,14c0-5.514-4.486-10-10-10S4,8.486,4,14 s4.486,10,10,10c2.035,0,3.928-0.614,5.509-1.663l5.077,5.077c0.78,0.781,2.048,0.781,2.828,0 C28.195,26.633,28.195,25.367,27.414,24.586z M7,14c0-3.86,3.14-7,7-7s7,3.14,7,7s-3.14,7-7,7S7,17.86,7,14z" id="XMLID_223_" />
|
||||
</svg>
|
||||
{% else %}
|
||||
<div class="w-12"></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div id="topbar-desktop-title" class="hidden sm:inline-block leading-12 align-middle ml-8 lg:ml-32 text-base text-gray-500 dark:text-gray-400 pr-8 truncate">
|
||||
{% if date %}<a href="/" class="text-indigo-900 dark:text-indigo-300 font-normal dark:font-light">Posts</a> › {% endif %}{{ title }}</div>
|
||||
<div id="search-desktop-title" class="hidden sm:hidden leading-12 align-middle ml-8 lg:ml-32 text-base text-gray-500 dark:text-gray-400">
|
||||
</div>
|
||||
{% if siteconfig.algoliaSearch and siteconfig.algoliaSearch.enabled %}
|
||||
<div id="search-box-bar" class="hidden sm:inline-block mr-6 ml-6 sm:mx-0 pt-3 col-span-2 sm:col-auto">
|
||||
<input id="search-box" type="search" autocomplete="off" spellcheck="false" autocorrect="off" onkeyup="searchContent(event)" class="bg-white dark:bg-dark-nav text-gray-800 dark:text-gray-400 font-light shadow rounded-full border-0 ring-1 ring-gray-300 focus:ring-indigo-400 dark:ring-gray-700 dark:focus:ring-gray-600 pl-2 h-6 w-2/3 sm:float-right sm:mr-6 md:float-none md:w-56 focus:outline-none" placeholder="Search..." aria-label="Search box">
|
||||
<span id="mobile-search-cancel" class="hidden sm:hidden ml-4" onclick="toggleSearch()">Cancel</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="dark:bg-dark-body grid grid-flow-col grid-cols-auto xl:grid-cols-topbar max-w-content mb-12">
|
||||
<main class="min-w-0">
|
||||
{{ content | safe }}
|
||||
</main>
|
||||
<div id="search-container" class="hidden truncate">
|
||||
<div class="postlist pb-8 mt-8 font-light dark:font-extralight pt-4 min-w-0">
|
||||
<div id="search-mobile-title" class="hidden leading-12 align-middle text-gray-500 dark:text-gray-400">
|
||||
</div>
|
||||
<ul id="search-results" class="mt-3">
|
||||
</ul>
|
||||
<span id="search-no-results" class="mt-3 hidden">
|
||||
No data found for the given query.
|
||||
</span>
|
||||
<img src="/assets/images/algolia.png" alt="Search powered by Algolia" />
|
||||
</div>
|
||||
</div>
|
||||
<aside class="hidden xl:block w-72 float-right">
|
||||
{% include "recents.njk" %}
|
||||
{% include "toc.njk" %}
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="scroll" class="scroll" onclick="scrollToTop()">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 1000 1000"
|
||||
class="h-6 w-6"
|
||||
>
|
||||
<g>
|
||||
<path
|
||||
d="M990,699.9c0,8.1,0,16.3-8.1,24.4c-16.3,16.3-40.7,16.3-56.9,0L502,350.2L79.1,732.4c-16.3,16.3-40.7,16.3-56.9,0c-16.3-16.3-16.3-40.7,0-56.9l447.3-406.6c24.4-16.3,40.7-16.3,56.9-8.1l447.3,406.6C981.9,675.5,990,691.8,990,699.9z"
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
77
content/_includes/head.njk
Normal file
@ -0,0 +1,77 @@
|
||||
<meta charset="utf-8">
|
||||
<title>{% if title %}{{ title }} | {% endif %}{{ siteconfig.title }}</title>
|
||||
{% if siteconfig.googleAnalytics %}
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id={{ siteconfig.googleAnalytics }}"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', '{{ siteconfig.googleAnalytics }}');
|
||||
</script>
|
||||
{% endif %}
|
||||
<script>
|
||||
// Toggle dark/light mode, inline JS to avoid any theme flicker
|
||||
function toggleDarkLightMode (isInit) {
|
||||
// First time visitors
|
||||
if (!("theme" in localStorage)) {
|
||||
if (window.matchMedia("(prefers-color-scheme: light)").matches) {
|
||||
document.querySelector("html").classList.remove("dark");
|
||||
document.querySelector("html").classList.add("light");
|
||||
localStorage.theme = "light";
|
||||
} else {
|
||||
localStorage.theme = "dark";
|
||||
}
|
||||
} else {
|
||||
if (!isInit) {
|
||||
if (localStorage.theme === "light") {
|
||||
document.querySelector("html").classList.add("dark");
|
||||
document.querySelector("html").classList.remove("light");
|
||||
localStorage.theme = "dark";
|
||||
} else if (localStorage.theme === "dark") {
|
||||
document.querySelector("html").classList.add("light");
|
||||
document.querySelector("html").classList.remove("dark");
|
||||
localStorage.theme = "light";
|
||||
}
|
||||
} else {
|
||||
if (localStorage.theme === "light") {
|
||||
document.querySelector("html").classList.remove("dark");
|
||||
document.querySelector("html").classList.add("light");
|
||||
} else if (localStorage.theme === "dark") {
|
||||
document.querySelector("html").classList.remove("light");
|
||||
document.querySelector("html").classList.add("dark");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
toggleDarkLightMode(true);
|
||||
</script>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ '/assets/favicons/apple-touch-icon.png' | addHash }}">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="{{ '/assets/favicons/favicon-32x32.png' | addHash }}">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="{{ '/assets/favicons/favicon-16x16.png' | addHash }}">
|
||||
<link rel="manifest" href="{{ '/assets/favicons/site.webmanifest' | addHash }}" crossorigin="use-credentials">
|
||||
<link rel="mask-icon" href="{{ '/assets/favicons/safari-pinned-tab.svg' | addHash }}" color="#5bbad5">
|
||||
<link rel="shortcut icon" href="{{ '/assets/favicons/favicon.ico' | addHash }}">
|
||||
<link rel="canonical" href="{{ page.url | absoluteUrl }}" />
|
||||
{% for name, item in meta %}
|
||||
<meta name="{{ name }}" content="{{ item.value }}">
|
||||
{% endfor %}
|
||||
<meta name="msapplication-TileColor" content="#da532c">
|
||||
<meta name="msapplication-config" content="{{ '/assets/favicons/browserconfig.xml' | addHash }}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
{% set description = description | truncate(55) %}
|
||||
<meta name="description" content="{% if description %}{{ description }}{% else %}{{ siteconfig.description }}{% endif %}">
|
||||
<meta property="og:url" content="{{ page.url | absoluteUrl }}">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="{% if title %}{{ title }} | {% endif %}{{ siteconfig.title }}">
|
||||
<meta property="og:description" content="{% if description %}{{ description }}{% else %}{{ siteconfig.description }}{% endif %}">
|
||||
<meta property="og:image" content="{% if image %}{{ image | addHash | absoluteUrl }}{% else %}{{ siteconfig.openGraphDefaultImage | addHash | absoluteUrl }}{% endif %}">
|
||||
<meta property="og:image:url" content="{% if image %}{{ image | addHash | absoluteUrl }}{% else %}{{ siteconfig.openGraphDefaultImage | addHash | absoluteUrl }}{% endif %}">
|
||||
<meta name="twitter:image" content="{% if image %}{{ image | addHash | absoluteUrl }}{% else %}{{ siteconfig.openGraphDefaultImage | addHash | absoluteUrl }} {% endif %}">
|
||||
<meta property="twitter:card" content="summary_large_image">
|
||||
<meta property="twitter:site" content="{{ siteconfig.socialTwitter }}">
|
||||
<script src="{{ '/assets/js/min.js' | addHash }}" type="module"></script>
|
||||
<link rel="stylesheet" href="{{ '/assets/css/site-build.css' | addHash }}">
|
||||
<script src="{{ '/assets/js/prism.js' | addHash }}"></script>
|
||||
<link rel="stylesheet" href="{{ '/assets/css/prism-build.css' | addHash }}">
|
15
content/_includes/json-ld.njk
Normal file
@ -0,0 +1,15 @@
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Article",
|
||||
"headline": "{{ title }}",
|
||||
"image": ["{% if image %}{{ image | absoluteUrl }}{% else %}{{ siteconfig.openGraphDefaultImage | absoluteUrl }}{% endif %}"],
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": "{{ siteconfig.author }}"
|
||||
},
|
||||
"mainEntityOfPage": "{{ page.url | absoluteUrl }}",
|
||||
"datePublished": "{{ page.date | isodate }}",
|
||||
"description": "{{ content | striptags | truncate(140) }}"
|
||||
}
|
||||
</script>
|
7
content/_includes/page.njk
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
layout: base.njk
|
||||
---
|
||||
|
||||
<div class="content page pt-4">
|
||||
{{ content | safe }}
|
||||
</div>
|
87
content/_includes/post.njk
Normal file
@ -0,0 +1,87 @@
|
||||
---
|
||||
layout: base.njk
|
||||
---
|
||||
|
||||
<div class="content post border-solid border-b-1 border-gray-700 pb-6">
|
||||
<h1>{{ title }}</h1>
|
||||
<div class="mb-12 flex text-sm font-light dark:font-extralight">
|
||||
<div class="flex">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600.112 600.111" class="h-5 w-4 mr-2">
|
||||
<path d="M537.423,52.563h-59.836V21.92c0-11.83-9.591-21.42-21.42-21.42c-11.83,0-21.42,9.59-21.42,21.42v30.642H165.364V21.92
|
||||
c0-11.83-9.59-21.42-21.42-21.42c-11.83,0-21.42,9.59-21.42,21.42v30.642H62.687c-32.058,0-58.14,26.082-58.14,58.14v430.77
|
||||
c0,32.059,26.082,58.139,58.14,58.139h474.736c32.059,0,58.141-26.08,58.141-58.139v-430.77
|
||||
C595.564,78.645,569.482,52.563,537.423,52.563z M47.387,110.703c0-8.451,6.85-15.3,15.3-15.3h59.837v24.443
|
||||
c0,11.83,9.59,21.42,21.42,21.42s21.42-9.59,21.42-21.42V95.403h269.383v24.443c0,11.83,9.59,21.42,21.42,21.42
|
||||
c11.829,0,21.42-9.59,21.42-21.42V95.403h59.836c8.45,0,15.3,6.85,15.3,15.3v53.856H47.387V110.703z M552.723,541.473
|
||||
c0,8.449-6.85,15.301-15.3,15.301H62.687c-8.45,0-15.3-6.852-15.3-15.301V207.399h505.336V541.473z" />
|
||||
<path d="M537.423,600.111H62.687c-32.334,0-58.64-26.306-58.64-58.639v-430.77c0-32.334,26.306-58.64,58.64-58.64h59.336V21.92
|
||||
c0-12.087,9.833-21.92,21.92-21.92c12.086,0,21.92,9.833,21.92,21.92v30.142h268.384V21.92c0-12.087,9.833-21.92,21.92-21.92
|
||||
s21.92,9.833,21.92,21.92v30.143h59.336c32.335,0,58.641,26.306,58.641,58.64v430.77
|
||||
C596.064,573.806,569.758,600.111,537.423,600.111z M62.687,53.062c-31.783,0-57.64,25.857-57.64,57.64v430.77
|
||||
c0,31.782,25.857,57.639,57.64,57.639h474.736c31.783,0,57.641-25.856,57.641-57.639v-430.77c0-31.783-25.857-57.64-57.641-57.64
|
||||
h-60.336V21.92c0-11.536-9.385-20.92-20.92-20.92s-20.92,9.385-20.92,20.92v31.142H164.864V21.92
|
||||
c0-11.536-9.385-20.92-20.92-20.92c-11.536,0-20.92,9.385-20.92,20.92v31.142H62.687z M537.423,557.273H62.687
|
||||
c-8.712,0-15.8-7.088-15.8-15.801V206.899h506.336v334.574C553.223,550.186,546.135,557.273,537.423,557.273z M47.887,207.899
|
||||
v333.574c0,8.161,6.639,14.801,14.8,14.801h474.736c8.16,0,14.8-6.64,14.8-14.801V207.899H47.887z M553.223,165.059H46.887
|
||||
v-54.356c0-8.712,7.088-15.8,15.8-15.8h60.337v24.943c0,11.535,9.385,20.92,20.92,20.92s20.92-9.385,20.92-20.92V94.903h270.383
|
||||
v24.943c0,11.535,9.385,20.92,20.92,20.92s20.92-9.385,20.92-20.92V94.903h60.336c8.712,0,15.8,7.088,15.8,15.8V165.059z
|
||||
M47.887,164.059h504.336v-53.356c0-8.161-6.64-14.8-14.8-14.8h-59.336v23.943c0,12.087-9.833,21.92-21.92,21.92
|
||||
s-21.92-9.833-21.92-21.92V95.903H165.864v23.943c0,12.087-9.833,21.92-21.92,21.92s-21.92-9.833-21.92-21.92V95.903H62.687
|
||||
c-8.161,0-14.8,6.639-14.8,14.8V164.059z" />
|
||||
</svg>
|
||||
{{ date | readableDate }}
|
||||
</div>
|
||||
<div class="flex readingtime" data-words="{{ content | striptags | wordcount | formatWords }} words">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 472.615 472.615" class="h-5 w-8 mr-2 ml-12">
|
||||
<path d="M472.615,205.774h-25.344c-12.797-37.99-48.686-65.462-90.935-65.462c-43.224,0-79.837,28.73-91.823,68.087
|
||||
c-7.582-5.011-17.305-8.115-28.211-8.115c-10.903,0-20.624,3.103-28.207,8.114c-11.989-39.357-48.608-68.085-91.831-68.085
|
||||
c-42.249,0-78.135,27.472-90.93,65.462H0v19.692h20.925c-0.403,3.565-0.656,7.175-0.656,10.846
|
||||
c0,52.933,43.063,95.99,95.995,95.99s96-43.058,96-95.99c0-0.552-0.073-1.085-0.083-1.635h0.069
|
||||
c0-6.952,9.88-14.702,24.053-14.702c14.178,0,24.053,7.75,24.053,14.702h0.073c-0.01,0.549-0.083,1.083-0.083,1.635
|
||||
c0,52.933,43.058,95.99,95.99,95.99s96-43.058,96-95.99c0-3.671-0.253-7.281-0.656-10.846h20.935V205.774z M116.264,312.611
|
||||
c-42.072,0-76.303-34.231-76.303-76.298c0-42.077,34.231-76.308,76.303-76.308c42.077,0,76.308,34.231,76.308,76.308
|
||||
C192.572,278.38,158.341,312.611,116.264,312.611z M356.337,312.611c-42.067,0-76.298-34.231-76.298-76.298
|
||||
c0-42.077,34.231-76.308,76.298-76.308c42.077,0,76.308,34.231,76.308,76.308C432.644,278.38,398.413,312.611,356.337,312.611z" />
|
||||
</svg>
|
||||
{{ content | striptags | wordcount | readingTime }}
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
{% if image %}
|
||||
<img src="{{ image }}" alt="{{ imageAlt }}" />
|
||||
{% endif %}
|
||||
{{ content | safe }}
|
||||
{% include "social.njk" %}
|
||||
<div class="block w-full h-1 border-solid border-b-1 border-gray-700"></div>
|
||||
<div class="additions flex flex-col sm:flex-row gap-3 mt-6 px-4 w-full">
|
||||
{% set previousPost = collections.posts | getPreviousCollectionItem(page) %}
|
||||
{% set nextPost = collections.posts | getNextCollectionItem(page) %}
|
||||
<a href="{{ previousPost.url }}" class="flex-1">
|
||||
<div class="h-24 border-1 border-gray-700 leading-pagination text-center{% if previousPost.url %} hover:bg-indigo-900 dark:hover:bg-indigo-900 hover:text-gray-200 dark:hover:text-gray-200 cursor-pointer{% else %} cursor-not-allowed{% endif %}">
|
||||
<span class="text-xs block mt-1 mb-3">Older</span>
|
||||
<span class="text-xl">{% if not previousPost.url %} - {% else %}{{ previousPost.data.title | truncate(40) }}{% endif %}</span>
|
||||
</div>
|
||||
</a>
|
||||
<a href="{{ nextPost.url }}" class="flex-1">
|
||||
<div class="h-24 border-1 border-gray-700 leading-pagination text-center{% if nextPost.url %} hover:bg-indigo-900 dark:hover:bg-indigo-900 hover:text-gray-200 dark:hover:text-gray-200 cursor-pointer{% else %} cursor-not-allowed{% endif %} overflow-auto">
|
||||
<span class="text-xs block mt-1 mb-3">Newer</span>
|
||||
<span class="text-xl">{% if not nextPost.url %} - {% else %}{{ nextPost.data.title | truncate(40) }}{% endif %}</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
{% set relatedPosts = related %}
|
||||
{% if relatedPosts %}
|
||||
<div class="block w-full h-1 border-solid border-b-1 border-gray-700"></div>
|
||||
<span class="content text-gray-800 dark:text-gray-400">Related</span>
|
||||
<div class="content additions flex mt-6 border-solid border-b-1 border-gray-700 mr-8 lg:mr-24">
|
||||
{% for post in relatedPosts %}
|
||||
<a href="{{ post.url }}" class="flex-1">
|
||||
<div class="h-24 m-1 border-1 border-gray-700 leading-pagination text-center hover:bg-indigo-900 hover:text-gray-200 rounded">
|
||||
<span class="text-xs block mt-1 mb-3">Recommended</span>
|
||||
<span class="text-xl">{{ post.title }}</span>
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
12
content/_includes/recents.njk
Normal file
@ -0,0 +1,12 @@
|
||||
{% if collections.recents %}
|
||||
<div id="recents" class="ml-1 mt-12 p-2 border-solid border-l-1 border-gray-300 dark:border-gray-700 mb-16 text-gray-800 dark:text-gray-400">
|
||||
<span class="ml-1">Recent updates</span>
|
||||
<ul class="list-none mt-2 pt-2 pl-2 pr-4 text-xs">
|
||||
{% for recent in collections.recents %}
|
||||
<li class="truncate{% if not loop.last %} pb-4{% endif %}">
|
||||
<a href="{{ recent.url }}">{{ recent.data.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
115
content/_includes/sidebar.njk
Normal file
@ -0,0 +1,115 @@
|
||||
<div id="sidebar-contents" class="dark:bg-sidebar-dark bg-sidebar-light grid-cols-1 gap-4 pt-8 h-screen grid w-56 xl:w-72">
|
||||
<div>
|
||||
<a href="/">
|
||||
<img alt="{{ siteconfig.imageAlt }}" src="{{ siteconfig.image }}" class="rounded-full h-36 border dark:border-gray-100 border-indigo-600" height="144px" width="144px" />
|
||||
</a>
|
||||
<div class="text-center font-semibold pt-6 text-gray-400">
|
||||
<a href="/" class="mx-auto">{{ siteconfig.title }}</a>
|
||||
</div>
|
||||
<div class="text-center text-sm pt-3 text-gray-400">
|
||||
{{ siteconfig.description }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu">
|
||||
<ul class="list-none pl-0">
|
||||
<li class="navitem text-center uppercase {{ page.url | isHomeLink('/') }}">
|
||||
<a href="/" class="block no-underline">Posts</a>
|
||||
</li>
|
||||
<li class="navitem text-center uppercase {{ page.url | isActiveLink('/who') }}">
|
||||
<a href="/who/" class="block no-underline">Who</a>
|
||||
</li>
|
||||
<li class="navitem text-center uppercase {{ page.url | isActiveLink('/why') }}">
|
||||
<a href="/why/" class="block no-underline">Why</a>
|
||||
</li>
|
||||
<li class="navitem text-center uppercase {{ page.url | isActiveLink('/archive') }}">
|
||||
<a href="/archive/" class="block no-underline">Archive</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="row-end-5 grid grid-cols-3 xl:grid-cols-6 gap-5 mx-auto place-content-end mb-12">
|
||||
<a onclick="toggleDarkLightMode(false)" href="#" class="w-5 h-5">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 612.001 612.001" class="lighttoggle">
|
||||
<title>Light mode icon</title>
|
||||
<g>
|
||||
<path d="M306,149.341c-86.382,0-156.661,70.278-156.661,156.661c0,86.382,70.278,156.66,156.661,156.66
|
||||
s156.66-70.278,156.66-156.66C462.66,219.618,392.382,149.341,306,149.341z" />
|
||||
<path d="M274.194,117.278h63.612c5.032,0,9.356-2.101,11.863-5.763c2.508-3.662,2.9-8.453,1.079-13.146L315.749,8.257
|
||||
c-2.789-7.184-7.305-8.256-9.749-8.256s-6.96,1.073-9.749,8.255l-35,90.114c-1.821,4.692-1.427,9.482,1.079,13.145
|
||||
C264.837,115.178,269.162,117.278,274.194,117.278z" />
|
||||
<path d="M337.806,494.723h-63.612c-5.032,0-9.357,2.102-11.863,5.764c-2.506,3.663-2.9,8.453-1.079,13.145l34.999,90.114
|
||||
c2.789,7.182,7.305,8.254,9.749,8.254c2.444,0,6.96-1.072,9.749-8.254l34.999-90.115c1.821-4.69,1.429-9.48-1.079-13.144
|
||||
C347.162,496.825,342.838,494.723,337.806,494.723z" />
|
||||
<path d="M127.54,190.824c2.412,5.477,7.028,8.746,12.348,8.746c3.644,0,7.257-1.608,10.174-4.526l44.981-44.98
|
||||
c3.558-3.558,5.13-8.102,4.312-12.466c-0.819-4.362-3.928-8.028-8.532-10.056l-88.467-38.973c-2.233-0.983-4.336-1.482-6.25-1.482
|
||||
c-3.201,0-5.959,1.415-7.568,3.882c-1.357,2.081-2.454,5.747,0.031,11.389L127.54,190.824z" />
|
||||
<path d="M484.46,421.178c-2.412-5.477-7.027-8.746-12.346-8.746c-3.645,0-7.259,1.609-10.177,4.527l-44.981,44.98
|
||||
c-3.558,3.559-5.13,8.104-4.312,12.466c0.818,4.362,3.929,8.028,8.532,10.055l88.466,38.974c2.233,0.983,4.336,1.482,6.25,1.482
|
||||
c3.201,0,5.959-1.417,7.568-3.882c1.358-2.083,2.455-5.748-0.03-11.389L484.46,421.178z" />
|
||||
<path d="M461.937,195.044c2.918,2.918,6.532,4.526,10.176,4.526c5.319,0,9.934-3.269,12.348-8.746l38.972-88.465
|
||||
c2.486-5.643,1.389-9.308,0.031-11.389c-1.609-2.467-4.367-3.882-7.568-3.882c-1.914,0-4.017,0.499-6.251,1.483l-88.466,38.97
|
||||
c-4.604,2.029-7.715,5.694-8.532,10.057c-0.818,4.363,0.754,8.908,4.312,12.466L461.937,195.044z" />
|
||||
<path d="M150.063,416.959c-2.918-2.918-6.532-4.527-10.177-4.527c-5.319,0-9.934,3.269-12.346,8.746l-38.972,88.465
|
||||
c-2.486,5.643-1.389,9.308-0.031,11.39c1.609,2.466,4.368,3.882,7.568,3.882c1.914,0,4.017-0.499,6.251-1.484l88.466-38.972
|
||||
c4.604-2.028,7.715-5.694,8.532-10.056c0.818-4.362-0.753-8.907-4.312-12.466L150.063,416.959z" />
|
||||
<path d="M603.745,296.251l-90.111-34.996c-1.942-0.755-3.896-1.137-5.806-1.137c-7.593,0-13.104,5.921-13.104,14.078l0.001,63.613
|
||||
c0,8.157,5.511,14.078,13.104,14.078c1.912,0,3.866-0.382,5.806-1.136l90.112-34.999c7.182-2.79,8.254-7.306,8.254-9.751
|
||||
C612.001,303.558,610.926,299.04,603.745,296.251z" />
|
||||
<path d="M104.173,351.886c7.594,0,13.106-5.921,13.106-14.078v-63.613c0-8.157-5.511-14.078-13.106-14.078
|
||||
c-1.912,0-3.864,0.382-5.805,1.136L8.255,296.251C1.073,299.04,0,303.556,0,306.001c0,2.444,1.072,6.96,8.255,9.752l90.111,34.996
|
||||
C100.308,351.503,102.261,351.886,104.173,351.886z" />
|
||||
</g>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 455 455" class="darktoggle">
|
||||
<title>Dark mode icon</title>
|
||||
<g>
|
||||
<polygon points="320.18,162.705 280.63,171.052 307.72,201.052 303.437,241.245 340.34,224.751 377.243,241.245 372.96,201.052
|
||||
400.05,171.052 360.5,162.705 340.34,127.67 " />
|
||||
<polygon points="440,325.677 414.091,320.208 400.883,297.253 387.675,320.208 361.766,325.677 379.513,345.33 376.708,371.661
|
||||
400.884,360.855 425.063,371.661 422.254,345.329 " />
|
||||
<path d="M218,227.5c0-89.167,51.306-166.338,126-203.64C313.443,8.6,278.978,0,242.5,0C116.855,0,15,101.855,15,227.5
|
||||
S116.855,455,242.5,455c36.478,0,70.943-8.6,101.5-23.86C269.306,393.838,218,316.667,218,227.5z" />
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
{% if siteconfig.socialLinkedIn %}
|
||||
<a href="https://linkedin.com/in/{{ siteconfig.socialLinkedIn }}" aria-label="Open LinkedIn profile" target="_blank" class="w-5 h-5" rel="noopener">
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>LinkedIn icon</title>
|
||||
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" />
|
||||
</svg>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if siteconfig.socialGitHub %}
|
||||
<a href="https://github.com/{{ siteconfig.socialGitHub }}" aria-label="Open GitHub profile" target="_blank" class="w-5 h-5" rel="noopener">
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>GitHub icon</title>
|
||||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
|
||||
</svg>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if siteconfig.socialTwitter %}
|
||||
<a href="https://twitter.com/{{ siteconfig.socialTwitter }}" aria-label="Open Twitter profile" target="_blank" class="w-5 h-5" rel="noopener">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<title>Twitter icon</title>
|
||||
<path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/>
|
||||
</svg>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if siteconfig.socialYouTube %}
|
||||
<a href="https://www.youtube.com/channel/{{ siteconfig.socialYouTube }}" aria-label="Open YouTube channel" target="_blank" class="w-5 h-5" rel="noopener">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="p-0.5">
|
||||
<title>YouTube icon</title>
|
||||
<path d="M23.498,3.186 C23.2220635,2.14660344 22.4135596,1.33276534 21.376,1.05 C19.505,0.545 12,0.545 12,0.545 C12,0.545 4.495,0.545 2.623,1.05 C1.5859324,1.33325676 0.777941373,2.14696201 0.502,3.186 C0,5.07 0,9 0,9 C0,9 0,12.93 0.502,14.814 C0.777936456,15.8533966 1.58644041,16.6672347 2.624,16.95 C4.495,17.455 12,17.455 12,17.455 C12,17.455 19.505,17.455 21.377,16.95 C22.4146666,16.6674185 23.2232481,15.8535024 23.499,14.814 C24,12.93 24,9 24,9 C24,9 24,5.07 23.498,3.186 Z M8.545,13.432 L8.545,3.432 L18.545,8.432 L8.545,13.432 Z" id="Shape"></path>
|
||||
</svg>
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="{{ '/blog.rss' | absoluteUrl }}" aria-label="Open RSS feed" target="_blank" class="w-5 h-5" rel="noopener">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 -256 1792 1792">
|
||||
<title>RSS icon</title>
|
||||
<g transform="matrix(1,0,0,-1,212.61017,1346.1695)" id="g2991">
|
||||
<path d="M 384,192 Q 384,112 328,56 272,0 192,0 112,0 56,56 0,112 0,192 q 0,80 56,136 56,56 136,56 80,0 136,-56 56,-56 56,-136 z M 896,69 Q 898,41 879,21 861,0 832,0 H 697 Q 672,0 654,16.5 636,33 634,58 612,287 449.5,449.5 287,612 58,634 33,636 16.5,654 0,672 0,697 v 135 q 0,29 21,47 17,17 43,17 h 5 Q 229,883 375,815.5 521,748 634,634 748,521 815.5,375 883,229 896,69 z m 512,-2 Q 1410,40 1390,20 1372,0 1344,0 H 1201 Q 1175,0 1156.5,17.5 1138,35 1137,60 1125,275 1036,468.5 947,662 804.5,804.5 662,947 468.5,1036 275,1125 60,1138 35,1139 17.5,1157.5 0,1176 0,1201 v 143 q 0,28 20,46 18,18 44,18 h 3 Q 329,1395 568.5,1288 808,1181 994,994 1181,808 1288,568.5 1395,329 1408,67 z" />
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
54
content/_includes/social.njk
Normal file
@ -0,0 +1,54 @@
|
||||
<div class="social flex flex-row-reverse mt-8 mb-4">
|
||||
<a
|
||||
href="#"
|
||||
aria-label="Copy page link to clipboard"
|
||||
onclick="copyUrlToClipboard()"
|
||||
class="link"
|
||||
>
|
||||
<span></span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
|
||||
<path d="M24 30.2c0 .2.1.5.1.8 0 1.4-.5 2.6-1.5 3.6l-2 2c-1 1-2.2 1.5-3.6 1.5-2.8 0-5.1-2.3-5.1-5.1 0-1.4.5-2.6 1.5-3.6l2-2c1-1 2.2-1.5 3.6-1.5.3 0 .5 0 .8.1l1.5-1.5c-.7-.3-1.5-.4-2.3-.4-1.9 0-3.6.7-4.9 2l-2 2c-1.3 1.3-2 3-2 4.9 0 3.8 3.1 6.9 6.9 6.9 1.9 0 3.6-.7 4.9-2l2-2c1.3-1.3 2-3 2-4.9 0-.8-.1-1.6-.4-2.3L24 30.2z" />
|
||||
<path d="M33 10.1c-1.9 0-3.6.7-4.9 2l-2 2c-1.3 1.3-2 3-2 4.9 0 .8.1 1.6.4 2.3l1.5-1.5c0-.2-.1-.5-.1-.8 0-1.4.5-2.6 1.5-3.6l2-2c1-1 2.2-1.5 3.6-1.5 2.8 0 5.1 2.3 5.1 5.1 0 1.4-.5 2.6-1.5 3.6l-2 2c-1 1-2.2 1.5-3.6 1.5-.3 0-.5 0-.8-.1l-1.5 1.5c.7.3 1.5.4 2.3.4 1.9 0 3.6-.7 4.9-2l2-2c1.3-1.3 2-3 2-4.9 0-3.8-3.1-6.9-6.9-6.9z" />
|
||||
<path d="M20 31c-.3 0-.5-.1-.7-.3-.4-.4-.4-1 0-1.4l10-10c.4-.4 1-.4 1.4 0s.4 1 0 1.4l-10 10c-.2.2-.4.3-.7.3z" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://www.facebook.com/sharer/sharer.php?u={{ page.url | absoluteUrl }}"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="Share on Facebook (opens new tab)"
|
||||
>
|
||||
<span></span>
|
||||
<svg
|
||||
viewBox="0 0 9 18"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="facebook"
|
||||
>
|
||||
<path
|
||||
d="M6.115 0c-2.173 0-3.66 1.5-3.66 4.23v2.363H0v3.195h2.455V18h2.926V9.788h2.45l.37-3.195H5.38V4.545c0-.922.236-1.545 1.42-1.545h1.507V.128A18.2 18.2 0 006.115 0z"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://www.linkedin.com/sharing/share-offsite/?url={{ page.url | absoluteUrl }}"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="Share on LinkedIn (opens new tab)">
|
||||
<span></span>
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="linkedin">
|
||||
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://twitter.com/intent/tweet/?text={{ title }}&url={{ page.url | absoluteUrl }}&via={{ siteconfig.twitterHandle }}"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
aria-label="Share on Twitter (opens new tab)"
|
||||
class="fill">
|
||||
<span></span>
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="twitter">
|
||||
<path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/>
|
||||
</svg>
|
||||
</a>
|
||||
<span class="text-sm mr-1">Share: </span>
|
||||
</div>
|
9
content/_includes/toc.njk
Normal file
@ -0,0 +1,9 @@
|
||||
{% set outline = content | toc %}
|
||||
{% if outline %}
|
||||
<div id="toc" class="list-none ml-1 pt-2 pr-2 border-solid border-l-1 border-gray-300 dark:border-gray-700 text-gray-800 dark:text-gray-400 sticky top-8">
|
||||
<span class="pl-2">Content</span>
|
||||
<div class="text-xs pt-2 pr-4">
|
||||
{{ outline | safe }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
31
content/archive.njk
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
eleventyExcludeFromCollections: true
|
||||
layout: base.njk
|
||||
title: Archive
|
||||
meta:
|
||||
robots:
|
||||
value: noindex
|
||||
---
|
||||
|
||||
<div class="postlist pb-8 mt-8 font-light dark:font-extralight pt-4">
|
||||
{% for post in collections.posts | reverse %}
|
||||
{% set currentYear = post | year %}
|
||||
{% set previousYear = collections.posts | getPreviousCollectionItem(post) | year %}
|
||||
{% if loop.first %}
|
||||
<span class="text-2xl">{{ currentYear }}</span>
|
||||
<ul class="mt-3">
|
||||
{% endif %}
|
||||
<li class="bg-gradient-to-r from-white via-gray-100 to-white dark:via-dark-middle dark:from-dark-outer dark:to-dark-outer mb-4 px-6 py-2 truncate">
|
||||
<span class="text-lg tabular-nums">{{ post.date | day }}</span>
|
||||
<span class="text-sm font-extralight">{{ post.date | month }}</span>
|
||||
<a href="{{ post.url }}" class="ml-6">{{ post.data.title }}</a>
|
||||
</li>
|
||||
{% if loop.last %}
|
||||
</ul>
|
||||
{% elif currentYear != previousYear %}
|
||||
</ul>
|
||||
<span class="text-2xl">{{ previousYear }}</span>
|
||||
<ul class="mt-3">
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
112
content/index.njk
Normal file
@ -0,0 +1,112 @@
|
||||
---
|
||||
eleventyExcludeFromCollections: true
|
||||
layout: base.njk
|
||||
title: Posts
|
||||
pagination:
|
||||
data: collections.posts
|
||||
size: 10
|
||||
alias: posts
|
||||
reverse: true
|
||||
meta:
|
||||
robots:
|
||||
value: noindex
|
||||
---
|
||||
|
||||
<div class="postlist pb-8 mt-8 font-light dark:font-extralight">
|
||||
{% for post in posts %}
|
||||
<div>
|
||||
<div class="pb-4 pt-4">
|
||||
<a class="text-indigo-900 dark:text-indigo-300 text-xl dark:font-light font-normal postlistheading" href="{{ post.url | url }}">{{ post.data.title }}</a>
|
||||
</div>
|
||||
<div class="pb-4 text-gray-900 dark:text-gray-400">{% excerpt post %}</div>
|
||||
<div class="pb-6 text-sm text-gray-500 dark:text-gray-400 border-b-1 border-gray-800 dark:border-gray-700 border-opacity-20 flex">
|
||||
<div class="flex">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600.112 600.111" class="h-5 w-4 mr-2">
|
||||
<path d="M537.423,52.563h-59.836V21.92c0-11.83-9.591-21.42-21.42-21.42c-11.83,0-21.42,9.59-21.42,21.42v30.642H165.364V21.92
|
||||
c0-11.83-9.59-21.42-21.42-21.42c-11.83,0-21.42,9.59-21.42,21.42v30.642H62.687c-32.058,0-58.14,26.082-58.14,58.14v430.77
|
||||
c0,32.059,26.082,58.139,58.14,58.139h474.736c32.059,0,58.141-26.08,58.141-58.139v-430.77
|
||||
C595.564,78.645,569.482,52.563,537.423,52.563z M47.387,110.703c0-8.451,6.85-15.3,15.3-15.3h59.837v24.443
|
||||
c0,11.83,9.59,21.42,21.42,21.42s21.42-9.59,21.42-21.42V95.403h269.383v24.443c0,11.83,9.59,21.42,21.42,21.42
|
||||
c11.829,0,21.42-9.59,21.42-21.42V95.403h59.836c8.45,0,15.3,6.85,15.3,15.3v53.856H47.387V110.703z M552.723,541.473
|
||||
c0,8.449-6.85,15.301-15.3,15.301H62.687c-8.45,0-15.3-6.852-15.3-15.301V207.399h505.336V541.473z" />
|
||||
<path d="M537.423,600.111H62.687c-32.334,0-58.64-26.306-58.64-58.639v-430.77c0-32.334,26.306-58.64,58.64-58.64h59.336V21.92
|
||||
c0-12.087,9.833-21.92,21.92-21.92c12.086,0,21.92,9.833,21.92,21.92v30.142h268.384V21.92c0-12.087,9.833-21.92,21.92-21.92
|
||||
s21.92,9.833,21.92,21.92v30.143h59.336c32.335,0,58.641,26.306,58.641,58.64v430.77
|
||||
C596.064,573.806,569.758,600.111,537.423,600.111z M62.687,53.062c-31.783,0-57.64,25.857-57.64,57.64v430.77
|
||||
c0,31.782,25.857,57.639,57.64,57.639h474.736c31.783,0,57.641-25.856,57.641-57.639v-430.77c0-31.783-25.857-57.64-57.641-57.64
|
||||
h-60.336V21.92c0-11.536-9.385-20.92-20.92-20.92s-20.92,9.385-20.92,20.92v31.142H164.864V21.92
|
||||
c0-11.536-9.385-20.92-20.92-20.92c-11.536,0-20.92,9.385-20.92,20.92v31.142H62.687z M537.423,557.273H62.687
|
||||
c-8.712,0-15.8-7.088-15.8-15.801V206.899h506.336v334.574C553.223,550.186,546.135,557.273,537.423,557.273z M47.887,207.899
|
||||
v333.574c0,8.161,6.639,14.801,14.8,14.801h474.736c8.16,0,14.8-6.64,14.8-14.801V207.899H47.887z M553.223,165.059H46.887
|
||||
v-54.356c0-8.712,7.088-15.8,15.8-15.8h60.337v24.943c0,11.535,9.385,20.92,20.92,20.92s20.92-9.385,20.92-20.92V94.903h270.383
|
||||
v24.943c0,11.535,9.385,20.92,20.92,20.92s20.92-9.385,20.92-20.92V94.903h60.336c8.712,0,15.8,7.088,15.8,15.8V165.059z
|
||||
M47.887,164.059h504.336v-53.356c0-8.161-6.64-14.8-14.8-14.8h-59.336v23.943c0,12.087-9.833,21.92-21.92,21.92
|
||||
s-21.92-9.833-21.92-21.92V95.903H165.864v23.943c0,12.087-9.833,21.92-21.92,21.92s-21.92-9.833-21.92-21.92V95.903H62.687
|
||||
c-8.161,0-14.8,6.639-14.8,14.8V164.059z" />
|
||||
</svg>
|
||||
{{ post.date | readableDate }}
|
||||
</div>
|
||||
<div class="readingtime flex" data-words="{{ post.templateContent | striptags | wordcount | formatWords }} words">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 472.615 472.615" class="h-5 w-8 mr-2 ml-12">
|
||||
<path d="M472.615,205.774h-25.344c-12.797-37.99-48.686-65.462-90.935-65.462c-43.224,0-79.837,28.73-91.823,68.087
|
||||
c-7.582-5.011-17.305-8.115-28.211-8.115c-10.903,0-20.624,3.103-28.207,8.114c-11.989-39.357-48.608-68.085-91.831-68.085
|
||||
c-42.249,0-78.135,27.472-90.93,65.462H0v19.692h20.925c-0.403,3.565-0.656,7.175-0.656,10.846
|
||||
c0,52.933,43.063,95.99,95.995,95.99s96-43.058,96-95.99c0-0.552-0.073-1.085-0.083-1.635h0.069
|
||||
c0-6.952,9.88-14.702,24.053-14.702c14.178,0,24.053,7.75,24.053,14.702h0.073c-0.01,0.549-0.083,1.083-0.083,1.635
|
||||
c0,52.933,43.058,95.99,95.99,95.99s96-43.058,96-95.99c0-3.671-0.253-7.281-0.656-10.846h20.935V205.774z M116.264,312.611
|
||||
c-42.072,0-76.303-34.231-76.303-76.298c0-42.077,34.231-76.308,76.303-76.308c42.077,0,76.308,34.231,76.308,76.308
|
||||
C192.572,278.38,158.341,312.611,116.264,312.611z M356.337,312.611c-42.067,0-76.298-34.231-76.298-76.298
|
||||
c0-42.077,34.231-76.308,76.298-76.308c42.077,0,76.308,34.231,76.308,76.308C432.644,278.38,398.413,312.611,356.337,312.611z" />
|
||||
</svg>
|
||||
{{ post.templateContent | striptags | wordcount | readingTime }}
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="mt-2 mx-8 lg:ml-32">
|
||||
<ul class="pagination flex list-none center pb-8 font-light dark:font-extralight">
|
||||
{% if pagination.pageNumber > 0 %}
|
||||
<li class="mr-3">
|
||||
<div class="leading-relaxed">
|
||||
{% if not pagination.href.first %}
|
||||
<span class="block cursor-not-allowed"><<</a>
|
||||
{% else %}
|
||||
<a href="{{ pagination.href.first }}" class="block hover:no-underline"><<</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
<li class="mr-3">
|
||||
<div class="leading-relaxed">
|
||||
{% if not pagination.href.previous %}
|
||||
<span class="block cursor-not-allowed"><</a>
|
||||
{% else %}
|
||||
<a href="{{ pagination.href.previous }}" class="block hover:no-underline"><</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% for pageEntry in pagination.pages %}
|
||||
{% if loop.index0 < 6 and pagination.hrefs[loop.index0 + pagination.pageNumber] %}
|
||||
<li class="mr-3">
|
||||
<div class="leading-pagination{% if pagination.hrefs[loop.index0 + pagination.pageNumber] === page.url %} active{% endif %}">
|
||||
<a href="{{ pagination.hrefs[loop.index0 + pagination.pageNumber] }}" class="block hover:no-underline">{{ loop.index + pagination.pageNumber }}</a>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if (pagination.pageNumber + 5) < pagination.pages.length %}
|
||||
<li class="mr-3">
|
||||
<div class="leading-relaxed">
|
||||
<a href="{{ pagination.href.next }}" class="block hover:no-underline">></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="mr-3">
|
||||
<div class="leading-relaxed">
|
||||
<a href="{{ pagination.href.last }}" class="block hover:no-underline">>></a>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
7
content/posts/2021/another-random-post.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Random post
|
||||
date: 2021-01-26
|
||||
image: /assets/images/2021/coolimage.jpg
|
||||
---
|
||||
|
||||
This is a super random post.
|
50
content/posts/2021/main-post.md
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
title: Your first amazing blog post
|
||||
date: 2021-01-27
|
||||
image: /assets/images/2021/coolimage.jpg
|
||||
---
|
||||
|
||||
This is your first blog post. And it can contain a lot of stuff. So let's go through a few things.
|
||||
|
||||
## Code for fun or profit
|
||||
|
||||
Having good looking (totally opiniated here, no) code snippets is mandatory. At least for myself. The included Prism config is based on [this selection](https://prismjs.com/download.html#themes=prism-coy&languages=markup+css+clike+javascript+bash+docker+java+regex+ruby+rust+scala+shell-session+typescript&plugins=show-language+toolbar). No standard theme has been chosen, there are some modifications to fit the Chirpy UX.
|
||||
|
||||
Find here an excerpt of the visuals.
|
||||
|
||||
### Bash
|
||||
|
||||
```bash
|
||||
if [ -z "$HEROKU_PWA_APP_NAME" ]; then
|
||||
echo "Please provide HEROKU_PWA_APP_NAME environment variable"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
### JavaScript
|
||||
|
||||
```javascript
|
||||
const jestLwcConfig = require("@lwc/jest-preset");
|
||||
import { resolve } from "path";
|
||||
|
||||
export const jestConfig = {
|
||||
...jestLwcConfig,
|
||||
resolver: resolve(__dirname, "../utils/resolver.js")
|
||||
};
|
||||
```
|
||||
|
||||
## Images, images, images
|
||||
|
||||
First, you'll notice this stunning picture. I got it royalty-free from Pixabay (great site). Now, that's not the point that I want to make here. The image is not added via Markdown, but instead via the `image` value of the Markdown front matter. As it's always good IMHO to start with a visual you'll get a standardized way of addding an image asset.
|
||||
|
||||
Second, the image is optimized for your browser size _and_ browser. Depending on what you currently use as browser you'll get i. e. a JPG or a WebP file. All in the right size for the screen. Obviously, all images have standard settings for lazy loading etc.
|
||||
|
||||
## Headings all over the place
|
||||
|
||||
It's all standard markdown to render the headings, and as well to display the table of contents (TOC) on the right side.
|
||||
|
||||
Note: never ever add a first level heading (aka: `h1`) to your page. This will break accessibility, as the title is already an h1, and will be represented as such in the rendered HTML.
|
||||
|
||||
## Other stuff
|
||||
|
||||
As to be expected you can do all the things that are _standard_ Markdown. So tables, blockquotes etc. And if you prefer to add custom Markdown functionality, just extend the configuration with custom [markdown-it](https://github.com/markdown-it/markdown-it) plugins.
|
7
content/posts/2021/random-post.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Your first amazing blog post
|
||||
date: 2021-01-24
|
||||
image: /assets/images/2021/coolimage.jpg
|
||||
---
|
||||
|
||||
Call me "Random Post" if you like.
|
4
content/posts/posts.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"layout": "post.njk",
|
||||
"tags": ["posts"]
|
||||
}
|
11
content/utils/404.njk
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
eleventyExcludeFromCollections: true
|
||||
layout: base.njk
|
||||
permalink: /404.html
|
||||
title: Ooooops
|
||||
---
|
||||
|
||||
<div class="content page pt-4">
|
||||
Sorry, this site doesn't exist.<br /><br />
|
||||
<img src="/assets/images/404.png" alt="Sad panda can't find this site" />
|
||||
</div>
|
6
content/utils/robots.njk
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
eleventyExcludeFromCollections: true
|
||||
permalink: /robots.txt
|
||||
---
|
||||
|
||||
Sitemap: {{ siteconfig.url }}/sitemap.xml
|
27
content/utils/rss.njk
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
eleventyExcludeFromCollections: true
|
||||
permalink: /blog.rss
|
||||
---
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>{{ siteconfig.title }}</title>
|
||||
<subtitle>{{ siteconfig.description }}</subtitle>
|
||||
<link href="{{ '/blog.rss' | absoluteUrl }}" rel="self"/>
|
||||
<link href="{{ siteconfig.url }}"/>
|
||||
<updated>{{ collections.posts | rssLastUpdatedDate }}</updated>
|
||||
<id>{{ siteconfig.url }}</id>
|
||||
<author>
|
||||
<name>{{ siteconfig.author }}</name>
|
||||
</author>
|
||||
{%- for post in collections.posts | reverse %}
|
||||
{% set absolutePostUrl %}{{ post.url | url | absoluteUrl(metadata.url) }}{% endset %}
|
||||
<entry>
|
||||
<title>{{ post.data.title }}</title>
|
||||
<link href="{{ absolutePostUrl }}"/>
|
||||
<updated>{{ post.date | rssDate }}</updated>
|
||||
<id>{{ absolutePostUrl }}</id>
|
||||
<content type="html">{{ post.templateContent | htmlToAbsoluteUrls(absolutePostUrl) | truncate(400) }}</content>
|
||||
</entry>
|
||||
{%- endfor %}
|
||||
</feed>
|
15
content/utils/sitemap.njk
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
eleventyExcludeFromCollections: true
|
||||
permalink: /sitemap.xml
|
||||
---
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
{% for item in collections.posts %}
|
||||
<url>
|
||||
<loc>{{ siteconfig.url }}{{ item.url }}</loc>
|
||||
<lastmod>{{ item.date | sitemapdate }}</lastmod>
|
||||
<changefreq>{{ item.data.sitemapChangefreq | default("daily") }}</changefreq>
|
||||
<priority>{{ item.data.sitemapPriority | default(0.8) }}</priority>
|
||||
</url>
|
||||
{% endfor %}
|
||||
</urlset>
|
7
content/who/index.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
eleventyExcludeFromCollections: true
|
||||
layout: page.njk
|
||||
title: Who
|
||||
---
|
||||
|
||||
And here you can write about yourself. Or just change in the `sidebar.njk` the label and write something different.
|
7
content/why/index.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
eleventyExcludeFromCollections: true
|
||||
layout: page.njk
|
||||
title: Why
|
||||
---
|
||||
|
||||
You can put your own page here.
|
18
netlify.toml
Normal file
@ -0,0 +1,18 @@
|
||||
[build]
|
||||
publish = "_site/"
|
||||
command = "yarn build"
|
||||
|
||||
[[headers]]
|
||||
for = "/*"
|
||||
[headers.values]
|
||||
cache-control = '''
|
||||
max-age=3600,
|
||||
public'''
|
||||
|
||||
[[headers]]
|
||||
for = "/assets/*"
|
||||
[headers.values]
|
||||
cache-control = '''
|
||||
max-age=31536000,
|
||||
public,
|
||||
immutable'''
|
61
package.json
Normal file
@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "eleventy-chirpy-blog-template",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "npm run build:css && npm run build:js && npm run build:eleventy ",
|
||||
"build:css": "postcss assets/css/site.css -o assets/css/site-build.css && postcss assets/css/prism.css -o assets/css/prism-build.css",
|
||||
"build:eleventy": "eleventy",
|
||||
"build:js": "rollup -c scripts/rollup.config.js",
|
||||
"dev": "concurrently \"npm:dev:*\"",
|
||||
"dev:css:prism": "postcss assets/css/prism.css -o assets/css/prism-build.css --watch",
|
||||
"dev:css:site": "postcss assets/css/site.css -o assets/css/site-build.css --watch",
|
||||
"dev:eleventy": "eleventy --serve",
|
||||
"dev:js": "rollup -c scripts/rollup.config.js -w",
|
||||
"lint": "npm run lint:markdown && npm run lint:js",
|
||||
"lint:markdown": "npx markdownlint-cli2 \"./content/**/*.md\"",
|
||||
"lint:js": "eslint '**/*.js'",
|
||||
"postinstall:": "husky install",
|
||||
"precommit": "npm run prettier && npm run lint",
|
||||
"prettier": "prettier --write \"**/*.{css,html,js,json,md,yaml,yml}\"",
|
||||
"prettier:verify": "prettier --list-different \"**/*.{css,html,js,json,md,yaml,yml}\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@11ty/eleventy": "^0.12.1",
|
||||
"@11ty/eleventy-plugin-rss": "^1.1.1",
|
||||
"@rollup/plugin-replace": "^2.4.2",
|
||||
"autoprefixer": "^10.2.6",
|
||||
"crypto-js": "^4.0.0",
|
||||
"cssnano": "^5.0.6",
|
||||
"date-fns": "^2.22.1",
|
||||
"dotenv": "^10.0.0",
|
||||
"eleventy-plugin-toc": "^1.1.0",
|
||||
"html-minifier": "^4.0.0",
|
||||
"jsdom": "^16.6.0",
|
||||
"markdown-it": "^12.0.6",
|
||||
"markdown-it-anchor": "^7.1.0",
|
||||
"postcss": "^8.3.2",
|
||||
"postcss-cli": "^8.3.1",
|
||||
"rollup": "^2.51.2",
|
||||
"rollup-plugin-postcss": "^4.0.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"sharp": "^0.28.3",
|
||||
"shelljs": "^0.8.4",
|
||||
"tailwindcss": "^2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^6.2.0",
|
||||
"eslint": "^7.28.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-inclusive-language": "^2.1.1",
|
||||
"husky": "^6.0.0",
|
||||
"markdownlint": "^0.23.1",
|
||||
"markdownlint-cli2": "^0.1.3",
|
||||
"prettier": "^2.3.1"
|
||||
},
|
||||
"volta": {
|
||||
"node": "14.15.4",
|
||||
"yarn": "1.22.10"
|
||||
}
|
||||
}
|
22
postcss.config.js
Normal file
@ -0,0 +1,22 @@
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
|
||||
let cssnano = undefined;
|
||||
|
||||
// We want optimization only in production
|
||||
if (isProduction) {
|
||||
cssnano = {
|
||||
cssnano: {
|
||||
preset: "default"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const plugins = {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
...(isProduction && cssnano)
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
plugins
|
||||
};
|
31
scripts/rollup.config.js
Normal file
@ -0,0 +1,31 @@
|
||||
require("dotenv").config();
|
||||
import { terser } from "rollup-plugin-terser";
|
||||
const replace = require("@rollup/plugin-replace");
|
||||
const siteconfig = require("../content/_data/siteconfig");
|
||||
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
|
||||
export default {
|
||||
input: "src/index.js",
|
||||
treeshake: false,
|
||||
output: [
|
||||
{
|
||||
file: "assets/js/min.js",
|
||||
sourcemap: !isProduction,
|
||||
format: "esm"
|
||||
}
|
||||
],
|
||||
plugins: [
|
||||
// Minify JS in production mode
|
||||
isProduction && terser(),
|
||||
// Replace env variables for Algolia, if enabled
|
||||
siteconfig.algoliaSearch &&
|
||||
siteconfig.algoliaSearch.enabled &&
|
||||
replace({
|
||||
"process.env.ALGOLIA_INDEX": `netlify_${siteconfig.algoliaSearch.siteId}_${siteconfig.algoliaSearch.branch}_all`,
|
||||
"process.env.ALGOLIA_APP_ID": siteconfig.algoliaSearch.appId,
|
||||
"process.env.ALGOLIA_SEARCH_API_KEY":
|
||||
siteconfig.algoliaSearch.searchApiKey
|
||||
})
|
||||
]
|
||||
};
|
92
src/index.js
Normal file
@ -0,0 +1,92 @@
|
||||
import { scrollToTop, slideLeftSidebar } from "./ui";
|
||||
import { searchContent, toggleSearch } from "./search";
|
||||
import { copyUrlToClipboard } from "./utils";
|
||||
|
||||
window.scrollToTop = function () {
|
||||
scrollToTop();
|
||||
};
|
||||
|
||||
window.slideLeftSidebar = function () {
|
||||
slideLeftSidebar();
|
||||
};
|
||||
|
||||
window.searchContent = function (e) {
|
||||
window.clearTimeout(window.searchDelay);
|
||||
window.searchDelay = setTimeout(() => {
|
||||
searchContent(e);
|
||||
}, 300);
|
||||
};
|
||||
|
||||
window.toggleSearch = function () {
|
||||
toggleSearch();
|
||||
};
|
||||
|
||||
window.copyUrlToClipboard = function () {
|
||||
copyUrlToClipboard();
|
||||
};
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const sections = document.querySelectorAll(".content h2,.content h3");
|
||||
const menu = document.querySelectorAll("nav.toc a");
|
||||
|
||||
const hash = window.location.hash;
|
||||
|
||||
if (hash) {
|
||||
for (const item of menu) {
|
||||
if (menu.href === hash) {
|
||||
item.classList.add("active");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const makeActive = (link) => {
|
||||
if (menu[link]) {
|
||||
menu[link].classList.add("active");
|
||||
}
|
||||
};
|
||||
const removeActive = (link) => menu[link].classList.remove("active");
|
||||
const removeAllActive = () =>
|
||||
[...Array(sections.length).keys()].forEach((link) =>
|
||||
removeActive(link)
|
||||
);
|
||||
|
||||
let currentActive = 0;
|
||||
|
||||
document
|
||||
.getElementById("right-area")
|
||||
.addEventListener("scroll", function () {
|
||||
{
|
||||
const areaEl = document.getElementById("right-area");
|
||||
const barEl = document.getElementById("top-bar");
|
||||
const scrollEl = document.getElementById("scroll");
|
||||
const scrollTop = areaEl.scrollTop;
|
||||
|
||||
const currentHeading =
|
||||
sections.length -
|
||||
[...sections].reverse().findIndex((section) => {
|
||||
return section.offsetTop - 45 <= scrollTop;
|
||||
}) -
|
||||
1;
|
||||
|
||||
if (currentHeading !== currentActive) {
|
||||
removeAllActive();
|
||||
currentActive = currentHeading;
|
||||
makeActive(currentHeading);
|
||||
}
|
||||
|
||||
if (scrollTop >= 45) {
|
||||
barEl.classList.add("hide");
|
||||
} else {
|
||||
barEl.classList.remove("hide");
|
||||
}
|
||||
|
||||
if (scrollEl) {
|
||||
if (scrollTop > window.innerHeight) {
|
||||
scrollEl.style.display = "flex";
|
||||
} else {
|
||||
scrollEl.style.display = "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
131
src/search.js
Normal file
@ -0,0 +1,131 @@
|
||||
const toggleSearch = () => {
|
||||
const elMobileTopBar = document.getElementById("mobile-top-bar");
|
||||
const elSearchBox = document.getElementById("search-box");
|
||||
const elSearchBoxBar = document.getElementById("search-box-bar");
|
||||
const elMobileSearchCancel = document.getElementById(
|
||||
"mobile-search-cancel"
|
||||
);
|
||||
elMobileTopBar.classList.toggle("hidden");
|
||||
elSearchBox.classList.toggle("w-60");
|
||||
elSearchBoxBar.classList.toggle("hidden");
|
||||
elSearchBoxBar.classList.toggle("w-full");
|
||||
elMobileSearchCancel.classList.toggle("hidden");
|
||||
|
||||
elSearchBox.value = "";
|
||||
|
||||
hideSearchContents();
|
||||
};
|
||||
|
||||
const showSearchContents = () => {
|
||||
const mainEl = document.querySelector("main");
|
||||
const tocEl = document.getElementById("toc");
|
||||
const searchContainerEl = document.getElementById("search-container");
|
||||
const searchDesktopTitleEl = document.getElementById(
|
||||
"search-desktop-title"
|
||||
);
|
||||
const searchMobileTitleEl = document.getElementById("search-mobile-title");
|
||||
const searchTopbarTitleEl = document.getElementById("topbar-desktop-title");
|
||||
|
||||
mainEl.classList.add("hidden");
|
||||
if (tocEl) {
|
||||
tocEl.classList.add("hidden");
|
||||
}
|
||||
searchContainerEl.classList.remove("hidden");
|
||||
if (window.innerWidth >= 640) {
|
||||
searchDesktopTitleEl.classList.remove("hidden");
|
||||
} else {
|
||||
searchMobileTitleEl.classList.remove("hidden");
|
||||
}
|
||||
searchDesktopTitleEl.textContent = "Search";
|
||||
searchDesktopTitleEl.classList.remove("sm:hidden");
|
||||
searchTopbarTitleEl.classList.add("sm:hidden");
|
||||
};
|
||||
|
||||
const hideSearchContents = () => {
|
||||
const mainEl = document.querySelector("main");
|
||||
const tocEl = document.getElementById("toc");
|
||||
const noResultsEl = document.getElementById("search-no-results");
|
||||
const searchContainerEl = document.getElementById("search-container");
|
||||
const searchDesktopTitleEl = document.getElementById(
|
||||
"search-desktop-title"
|
||||
);
|
||||
const searchMobileTitleEl = document.getElementById("search-mobile-title");
|
||||
const searchTopbarTitleEl = document.getElementById("topbar-desktop-title");
|
||||
|
||||
mainEl.classList.remove("hidden");
|
||||
if (tocEl) {
|
||||
tocEl.classList.remove("hidden");
|
||||
}
|
||||
searchContainerEl.classList.add("hidden");
|
||||
searchDesktopTitleEl.classList.add("hidden");
|
||||
searchDesktopTitleEl.classList.add("sm:hidden");
|
||||
searchMobileTitleEl.classList.add("hidden");
|
||||
searchTopbarTitleEl.classList.remove("sm:hidden");
|
||||
noResultsEl.classList.add("hidden");
|
||||
};
|
||||
|
||||
const searchContent = (e) => {
|
||||
const INDEX = "process.env.ALGOLIA_INDEX";
|
||||
const APP_ID = "process.env.ALGOLIA_APP_ID";
|
||||
const API_ID = "process.env.ALGOLIA_SEARCH_API_KEY";
|
||||
|
||||
const keywords = e.target.value;
|
||||
|
||||
const noResultsEl = document.getElementById("search-no-results");
|
||||
const searchDesktopTitleEl = document.getElementById(
|
||||
"search-desktop-title"
|
||||
);
|
||||
const searchMobileTitleEl = document.getElementById("search-mobile-title");
|
||||
|
||||
if (keywords !== "" && keywords !== undefined) {
|
||||
showSearchContents();
|
||||
} else {
|
||||
hideSearchContents();
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(
|
||||
`https://${APP_ID}-dsn.algolia.net/1/indexes/${INDEX}?query=${keywords}&hitsPerPage=200`,
|
||||
{
|
||||
headers: {
|
||||
"X-Algolia-Application-Id": APP_ID,
|
||||
"X-Algolia-API-Key": API_ID
|
||||
}
|
||||
}
|
||||
)
|
||||
.then((result) => {
|
||||
return result.json();
|
||||
})
|
||||
.then((json) => {
|
||||
const ulEl = document.getElementById("search-results");
|
||||
while (ulEl.lastChild) {
|
||||
ulEl.lastChild.remove();
|
||||
}
|
||||
if (json.hits.length === 0) {
|
||||
noResultsEl.classList.remove("hidden");
|
||||
} else {
|
||||
noResultsEl.classList.add("hidden");
|
||||
}
|
||||
let hits = 0;
|
||||
for (const item of json.hits) {
|
||||
const liEl = document.createElement("li");
|
||||
liEl.setAttribute(
|
||||
"class",
|
||||
"bg-gradient-to-r from-white via-gray-100 to-white dark:via-dark-middle dark:from-dark-outer dark:to-dark-outer mb-4 py-2 truncate"
|
||||
);
|
||||
const aEl = document.createElement("a");
|
||||
aEl.setAttribute("href", item.url);
|
||||
aEl.textContent = item.title.split("|")[0];
|
||||
liEl.appendChild(aEl);
|
||||
ulEl.appendChild(liEl);
|
||||
hits = hits + 1;
|
||||
}
|
||||
searchDesktopTitleEl.textContent = `Search (${hits} hit/s)`;
|
||||
searchMobileTitleEl.textContent = `${hits} hit/s`;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
|
||||
export { searchContent, toggleSearch };
|
17
src/ui.js
Normal file
@ -0,0 +1,17 @@
|
||||
const scrollToTop = () => {
|
||||
document.getElementById("right-area").scroll({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: "smooth"
|
||||
});
|
||||
};
|
||||
|
||||
const slideLeftSidebar = () => {
|
||||
const elSidebar = document.getElementById("sidebar");
|
||||
const elRightArea = document.getElementById("right-area");
|
||||
elSidebar.classList.toggle("-translate-x-56");
|
||||
elSidebar.classList.toggle("translate-x-0");
|
||||
elRightArea.classList.toggle("translate-x-56");
|
||||
};
|
||||
|
||||
export { scrollToTop, slideLeftSidebar };
|
9
src/utils.js
Normal file
@ -0,0 +1,9 @@
|
||||
const copyUrlToClipboard = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(location.href);
|
||||
} catch (err) {
|
||||
console.error("Failed to copy: ", err);
|
||||
}
|
||||
};
|
||||
|
||||
export { copyUrlToClipboard };
|
77
tailwind.config.js
Normal file
@ -0,0 +1,77 @@
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
|
||||
let purge = false;
|
||||
|
||||
// We want optimization only in production
|
||||
if (isProduction) {
|
||||
purge = ["./content/**/*.njk", "./src/*.js"];
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
purge,
|
||||
darkMode: "class",
|
||||
plugins: [
|
||||
function ({ addUtilities }) {
|
||||
const extendUnderline = {
|
||||
".underline": {
|
||||
textDecoration: "underline",
|
||||
"text-decoration-color": "text-indigo-300",
|
||||
"text-underline-position": "under"
|
||||
}
|
||||
};
|
||||
addUtilities(extendUnderline);
|
||||
}
|
||||
],
|
||||
variants: {
|
||||
extend: {
|
||||
backgroundImage: ["dark"],
|
||||
fill: ["dark"],
|
||||
fontWeight: ["dark"],
|
||||
gradientColorStops: ["dark"],
|
||||
stroke: ["dark"]
|
||||
}
|
||||
},
|
||||
theme: {
|
||||
extend: {
|
||||
backgroundColor: (theme) => ({
|
||||
...theme("colors"),
|
||||
"dark-nav": "#242424",
|
||||
"dark-body": "#1B1B1E",
|
||||
"dark-heading": "#27282B"
|
||||
}),
|
||||
backgroundImage: () => ({
|
||||
"sidebar-dark":
|
||||
"radial-gradient(circle, #242424 0%, #1d1f27 100%)",
|
||||
"sidebar-light":
|
||||
"radial-gradient(circle,rgba(42, 30, 107, 1) 0%,rgba(35, 37, 46, 1) 100%)"
|
||||
}),
|
||||
borderWidth: (theme) => ({
|
||||
...theme("width"),
|
||||
1: "1px"
|
||||
}),
|
||||
gradientColorStops: (theme) => ({
|
||||
...theme("colors"),
|
||||
"dark-outer": "#1B1B1E",
|
||||
"dark-middle": "#242424"
|
||||
}),
|
||||
gridTemplateColumns: {
|
||||
small: "0 auto",
|
||||
regular: "minmax(auto, 0fr) auto;",
|
||||
topbar: "auto 18rem"
|
||||
},
|
||||
lineHeight: {
|
||||
pagination: "1.8rem",
|
||||
12: "3rem"
|
||||
},
|
||||
margin: {
|
||||
15: "3.75rem"
|
||||
},
|
||||
maxWidth: {
|
||||
content: "95rem"
|
||||
},
|
||||
textColor: {
|
||||
"orange-hover": "#d2603a"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|