Skip to content

Commit 40cc017

Browse files
committed
Initial commit
0 parents  commit 40cc017

File tree

42 files changed

+1836
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1836
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Deploy to GitHub Pages
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
workflow_dispatch: # Allows manual triggering of the workflow
9+
10+
jobs:
11+
deploy:
12+
runs-on: ubuntu-latest
13+
permissions:
14+
contents: write
15+
concurrency:
16+
group: ${{ github.workflow }}-${{ github.ref }}
17+
steps:
18+
- uses: actions/checkout@v3
19+
20+
- name: Setup Node
21+
uses: actions/setup-node@v3
22+
with:
23+
node-version: "22"
24+
25+
- name: Persist npm cache
26+
uses: actions/cache@v3
27+
with:
28+
path: ~/.npm
29+
key: ${{ runner.os }}-node-${{ hashFiles('**/package.json') }}
30+
31+
- name: Persist Eleventy .cache
32+
uses: actions/cache@v3
33+
with:
34+
path: ./.cache
35+
key: ${{ runner.os }}-eleventy-fetch-cache
36+
37+
- run: npm install
38+
- run: npm run build-ghpages
39+
40+
- name: Deploy
41+
uses: peaceiris/actions-gh-pages@v4
42+
if: github.ref == 'refs/heads/master'
43+
with:
44+
github_token: ${{ secrets.GITHUB_TOKEN }}
45+
publish_dir: ./_site

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
_site/
2+
node_modules/
3+
package-lock.json
4+
.cache

_config/filters.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { DateTime } from "luxon";
2+
import striptags from "striptags";
3+
4+
export default function(eleventyConfig) {
5+
eleventyConfig.addFilter("readableDate", (dateObj, format, zone) => {
6+
// Formatting tokens for Luxon: https://moment.github.io/luxon/#/formatting?id=table-of-tokens
7+
return DateTime.fromJSDate(dateObj, { zone: zone || "utc" }).toFormat(format || "dd LLLL yyyy");
8+
});
9+
10+
eleventyConfig.addFilter("htmlDateString", (dateObj) => {
11+
// dateObj input: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
12+
return DateTime.fromJSDate(dateObj, { zone: "utc" }).toFormat('yyyy-LL-dd');
13+
});
14+
15+
// Get the first `n` elements of a collection.
16+
eleventyConfig.addFilter("head", (array, n) => {
17+
if(!Array.isArray(array) || array.length === 0) {
18+
return [];
19+
}
20+
if( n < 0 ) {
21+
return array.slice(n);
22+
}
23+
24+
return array.slice(0, n);
25+
});
26+
27+
// Return the smallest number argument
28+
eleventyConfig.addFilter("min", (...numbers) => {
29+
return Math.min.apply(null, numbers);
30+
});
31+
32+
// Return the keys used in an object
33+
eleventyConfig.addFilter("getKeys", target => {
34+
return Object.keys(target);
35+
});
36+
37+
eleventyConfig.addFilter("filterTagList", function filterTagList(tags) {
38+
return (tags || []).filter(tag => ["all", "posts"].indexOf(tag) === -1);
39+
});
40+
41+
// Extract reading time
42+
eleventyConfig.addFilter("readingTime", (wordcount) => {
43+
let readingTime = Math.ceil(wordcount / 220);
44+
if (readingTime === 1) {
45+
return readingTime + " minute";
46+
}
47+
return readingTime + " minutes";
48+
});
49+
50+
// Extract word count
51+
eleventyConfig.addFilter("formatWords", (wordcount) => {
52+
return wordcount.toLocaleString("en");
53+
});
54+
55+
eleventyConfig.addFilter("truncate", (string, limit) => {
56+
if(string.length <= limit) return string;
57+
58+
return string.slice(0, limit - 3) + "...";
59+
});
60+
61+
eleventyConfig.addFilter("excerpt", (post) =>
62+
extractExcerpt(post)
63+
);
64+
65+
};
66+
67+
// Taken from here => https://keepinguptodate.com/pages/2019/06/creating-blog-with-eleventy/
68+
function extractExcerpt(article) {
69+
if (!Object.prototype.hasOwnProperty.call(article, "templateContent")) {
70+
console.warn(
71+
'Failed to extract excerpt: Document has no property "templateContent".'
72+
);
73+
return null;
74+
}
75+
76+
const content = article.templateContent;
77+
78+
return striptags(content.slice(0, content.indexOf("\n")));
79+
}

_config/shortcodes.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import Image from "@11ty/eleventy-img"
2+
3+
export default function(eleventyConfig) {
4+
eleventyConfig.addShortcode("currentBuildDate", () => {
5+
return (new Date()).toISOString();
6+
});
7+
};
8+

_data/eleventyDataSchema.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { z } from "zod";
2+
import { fromZodError } from 'zod-validation-error';
3+
4+
export default function(data) {
5+
// Draft content, validate `draft` front matter
6+
let result = z.object({
7+
draft: z.boolean().or(z.undefined()),
8+
}).safeParse(data);
9+
10+
if(result.error) {
11+
throw fromZodError(result.error);
12+
}
13+
}

_data/metadata.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export default {
2+
title: "ByteAether",
3+
url: "https://byteaether.github.io/",
4+
logo: "/img/icon.svg",
5+
language: "en",
6+
description: "Covering different software engineering topics.",
7+
tags: ["c#", "csharp", "dotnet", "byteaether", "blog", "tech", "programming"],
8+
author: {
9+
name: "Joonatan Uusväli",
10+
email: "joonatanu@gmail.com",
11+
url: "https://www.linkedin.com/in/joonatan-uusvali/"
12+
},
13+
googleAnalyticsKey: "G-LEY00265EM",
14+
githubComments: {
15+
repo: "CLCK0622/11ty-Serene",
16+
repoId: "R_kgDOMgVOMw",
17+
categoryId: "DIC_kwDOMgVOM84ClgHM",
18+
},
19+
}

_includes/layouts/base.njk

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<!doctype html>
2+
<html lang="{{ metadata.language }}">
3+
<head>
4+
{% include "partials/head.njk" %}
5+
6+
{%- css %}{% include "public/css/index.css" %}{% endcss %}
7+
8+
{%- css %}{% include "node_modules/@fortawesome/fontawesome-free/css/all.min.css" %}{% endcss %}
9+
{%- js %}{% include "node_modules/@fortawesome/fontawesome-free/js/all.min.js" %}{% endjs %}
10+
11+
{%- js %}{% include "node_modules/@zachleat/heading-anchors/heading-anchors.js" %}{% endjs %}
12+
13+
<style>{% getBundle "css" %}</style>
14+
<script src="/js/main.js"></script>
15+
</head>
16+
<body>
17+
<a href="#skip" class="visually-hidden">Skip to main content</a>
18+
19+
{% include "partials/header.njk" %}
20+
21+
<div class="content-wrapper">
22+
23+
<main id="skip">
24+
<heading-anchors>
25+
{{ content | safe }}
26+
</heading-anchors>
27+
</main>
28+
29+
<aside>
30+
{% include "partials/aside.njk" %}
31+
</aside>
32+
33+
</div>
34+
35+
{% include "partials/footer.njk" %}
36+
37+
<!-- This page `{{ page.url | absoluteUrl(metadata.url) }}` was built on {% currentBuildDate %} -->
38+
<script type="module" src="{% getBundleFileUrl "js" %}"></script>
39+
</body>
40+
</html>

_includes/layouts/home.njk

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
layout: layouts/base.njk
3+
---
4+
5+
{{ content | safe }}

_includes/layouts/post.njk

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
---
2+
layout: layouts/base.njk
3+
---
4+
{# Only include the syntax highlighter CSS on blog posts, included with the CSS per-page bundle #}
5+
{%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %}
6+
{%- css %}{% include "public/css/prism-diff.css" %}{%- endcss %}
7+
{%- css %}
8+
.links-nextprev {
9+
display: flex;
10+
padding: 0;
11+
margin: 0;
12+
list-style: none;
13+
}
14+
.links-nextprev li {
15+
width: 50%;
16+
}
17+
.links-nextprev-next {
18+
text-align: right;
19+
}
20+
.post-metadata {
21+
display: inline-flex;
22+
flex-wrap: wrap;
23+
gap: 2em;
24+
list-style: none;
25+
padding: 0;
26+
margin: 0;
27+
}
28+
.tag {
29+
border: 1px solid var(--border-color);
30+
border-radius: 4px;
31+
background-color: var(--bg-color-secondary);
32+
padding: 0 0.25rem;
33+
transition: background-color 0.3s, border-color 0.3s;
34+
}
35+
36+
.post-header {
37+
margin-top: 1.5rem;
38+
}
39+
40+
{%- endcss %}
41+
<h1>{{ title }}</h1>
42+
43+
<ul class="post-metadata">
44+
<div>
45+
<i class="fa-regular fa-calendar"></i>
46+
<time datetime="{{ page.date | htmlDateString }}">{{ page.date | readableDate }}</time>
47+
</div>
48+
<div data-words="{{ content | striptags | wordcount | formatWords }} words">
49+
<i class="fa-regular fa-clock"></i>
50+
{{ content | striptags | wordcount | readingTime }}
51+
</div>
52+
<div>
53+
<i class="fa-solid fa-tags"></i>
54+
{%- for tag in tags | filterTagList %}
55+
{%- set tagUrl %}/tags/{{ tag | slugify }}/{% endset %}
56+
<span class="tag"><a href="{{ tagUrl }}">{{ tag }}</a></span>
57+
{%- endfor %}
58+
</div>
59+
</ul>
60+
61+
{%- if image %}
62+
<img src="{{ image }}" alt="" class="post-header" />
63+
{% endif %}
64+
65+
{{ content | safe }}
66+
67+
{% include "partials/socials.njk" %}
68+
69+
{%- if collections.posts %}
70+
{%- set previousPost = collections.posts | getPreviousCollectionItem %}
71+
{%- set nextPost = collections.posts | getNextCollectionItem %}
72+
{%- if nextPost or previousPost %}
73+
<ul class="links-nextprev">
74+
<li class="links-nextprev-prev">{%- if previousPost %}← Previous<br> <a href="{{ previousPost.url }}">{{ previousPost.data.title }}</a>{% endif %}</li>
75+
<li class="links-nextprev-next">{%- if nextPost %}Next →<br><a href="{{ nextPost.url }}">{{ nextPost.data.title }}</a>{% endif %}</li>
76+
</ul>
77+
{%- endif %}
78+
{%- endif %}
79+
80+
{% if metadata.githubComments.repo %}
81+
<div id="giscus-comments"></div>
82+
<script>
83+
// Wait for the DOM to load or ensure themeManager is available
84+
document.addEventListener("DOMContentLoaded", () => {
85+
const giscusContainer = document.getElementById("giscus-comments");
86+
87+
const script = document.createElement("script");
88+
script.src = "https://giscus.app/client.js";
89+
script.setAttribute("data-repo", "{{ metadata.githubComments.repo }}");
90+
script.setAttribute("data-repo-id", "{{ metadata.githubComments.repoId }}");
91+
script.setAttribute("data-category-id", "{{ metadata.githubComments.categoryId }}");
92+
script.setAttribute("data-mapping", "pathname");
93+
script.setAttribute("data-strict", "0");
94+
script.setAttribute("data-reactions-enabled", "1");
95+
script.setAttribute("data-emit-metadata", "0");
96+
script.setAttribute("data-input-position", "top");
97+
script.setAttribute("data-theme", themeManager.get()); // Use themeManager.get() for theme
98+
script.setAttribute("data-lang", "en");
99+
script.setAttribute("data-loading", "lazy");
100+
script.setAttribute("crossorigin", "anonymous");
101+
script.async = true;
102+
103+
giscusContainer.appendChild(script); // Append the script to the document
104+
});
105+
</script>
106+
{% endif %}

_includes/partials/aside.njk

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{% css %}
2+
.aside-content {
3+
margin-top: 2rem;
4+
margin-left: 0.5rem;
5+
padding: 0.5rem;
6+
font-size: 0.9rem;
7+
border-left: 1px solid var(--border-color);
8+
transition: border-color 0.3s;
9+
}
10+
11+
.toc-container {
12+
position: sticky;
13+
top: 5rem;
14+
}
15+
16+
.aside-content ol {
17+
list-style-type: none;
18+
padding: 0;
19+
margin: 0;
20+
}
21+
22+
.aside-content li {
23+
margin-left: 1rem;
24+
margin-top: 1rem;
25+
}
26+
{% endcss %}
27+
28+
<div class="recents-container aside-content">
29+
<span>Recents</span>
30+
<div>
31+
<nav>
32+
<ol>
33+
{% for post in collections.posts.slice(-5).reverse() %}
34+
<li>
35+
<a href="{{ post.url }}">{{ post.data.title }}</a>
36+
</li>
37+
{% endfor %}
38+
</ol>
39+
</nav>
40+
</div>
41+
</div>
42+
43+
{% set outline = content | toc %}
44+
{% if outline %}
45+
<div class="toc-container aside-content">
46+
<span>Table of Contents</span>
47+
<div>
48+
{{ outline | safe }}
49+
</div>
50+
</div>
51+
{% endif %}

0 commit comments

Comments
 (0)