first commitm

This commit is contained in:
Lukas 2024-03-24 15:45:15 -04:00
commit f8dc7e71a4
69 changed files with 2125 additions and 0 deletions

25
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,25 @@
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'run zola build'
sh 'zola build'
}
}
stage('Deploy') {
steps {
echo 'Hello World'
sh 'ls public'
sshagent(credentials: ['d82f9436-4c96-44c2-9ed3-b21481e7b742']) {
sh '''
[ -d ~/.ssh ] || mkdir ~/.ssh && chmod 0700 ~/.ssh
ssh-keyscan -t rsa,dsa lvacula.com >> ~/.ssh/known_hosts
rsync -avz -e "ssh -o StrictHostKeyChecking=no" public/. greywolver@lvacula.com:lvacula.com-docker/volumes/blog
'''
}
}
}
}
}

81
config.toml Normal file
View File

@ -0,0 +1,81 @@
title = "Temporary Permanence"
description = "Lukas Vacula's personal website and blog."
# The URL the site will be built for
base_url = "https://lvacula.com"
# Whether to automatically compile all Sass files in the sass directory
compile_sass = true
# Whether to build a search index to be used later on by a JavaScript library
build_search_index = true
default_language = "en"
generate_feed = true
author = "Lukas Vacula"
feed_filename = "atom.xml"
# The taxonomies to be rendered for the site and their configuration of the default languages
# Example:
# taxonomies = [
# {name = "tags", feed = true}, # each tag will have its own feed
# {name = "tags"}, # you can have taxonomies with the same name in multiple languages
# {name = "categories", paginate_by = 5}, # 5 items per page for a term
# {name = "authors"}, # Basic definition: no feed or pagination
# ]
#
taxonomies = [{ name = "tags", lang = "en", rss = true }]
[markdown]
# Whether to do syntax highlighting
# Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola
highlight_code = true
[slugify]
paths = "on"
taxonomies = "on"
anchors = "on"
[extra]
# Place your avatar in your /static folder
avatar = "/inky.png"
# Your Google Analytics measurement id ("G-XXXXXXXXXX")
# google_analytics_tag_id = "";
#keywords = "zola, theme, ink, hugo-ink"
keywords = "tech, security"
search_enabled = false
image_resizing_disabled = false
image_format = "auto" # "auto", "jpg", "png", "webp"
# responsive image shortcode
# example: {{ image(src="foo.jpeg", alt="some image") }}
image_quality = 80
images_default_size = 1024
images_sizes = [512, 1024, 2048]
thumbnail_quality = 70
thumbnail_default_size = 256
thumbnail_sizes = [128, 256]
#link_github_username = "jimmyff/zola-inky"
# link_twitter_username = ""
# link_mastodon_url = ""
# link_medium_username = ""
# link_instagram_username = ""
menu_links = [
{ url = "$BASE_URL/", name = "About" },
{ url = "$BASE_URL/posts/", name = "Posts" },
{ url = "$BASE_URL/tags/", name = "Tags" },
# { url = "https://github.com/jimmyff/zola-inky", name = "Github" },
{ url = "$BASE_URL/contact/", name = "Contact" },
{ url = "$BASE_URL/search/", name = "Search" },
]

8
content/_index.md Normal file
View File

@ -0,0 +1,8 @@
+++
title = "Home"
images = []
template = "index.html"
in_search_index = true
+++
Hi there! I'm Lukas. This is the website where I host notes about programming, homelabbing, and other topics that interest me. Not all topics are technical.

16
content/about.md Normal file
View File

@ -0,0 +1,16 @@
+++
title = "About"
images = []
template = "page.html"
in_search_index = true
+++
## The Person
Heya, I'm a guy who likes tech. My background is mostly in computer security with a focus on the IT/networks side of things rather than the programming side. However, I do a lot of automation and hobby projects with Python.
## The Site
There's a proverb in tech: "nothing is more permanent than a temporary solution". Sometimes its your “temporary fix” cron job to clear out caches instead of adding more storage. Sometimes its the quick setup server that you put in place to hotfix one that crashed. Either way, you end up seeing it years later and go “*thats* still being used?”.
I couldnt think of a blog name and nearly named it “temp”. Then I realized that I was falling right into that trap. May as well own it.

12
content/contact.md Normal file
View File

@ -0,0 +1,12 @@
+++
title = "Contact"
images = []
template = "page.html"
in_search_index = true
+++
The best way to contact me is by email - "lukas" @ this domain. I am not explicitly writing it due to spam, but I'm sure you can figure it out. ;)
## Other Ways to Find Me
I don't have a very large or public internet presence. Here are some other sites where you can find me:
- [github.com/ldv8434](github.com/ldv8434)

View File

@ -0,0 +1,9 @@
+++
title = "Example posts"
sort_by = "date"
template = "posts.html"
page_template = "post.html"
transparent = true
+++
Posts

View File

@ -0,0 +1,20 @@
+++
title = "Resolved: Email Delivery Issues with Google Domains Email Aliases"
date = 2023-06-15
[taxonomies]
tags= ["resolved"]
+++
This post is a combination announcement and “hey, this is how you fix this” post.
Ive used Google Domains as my DNS registrar for several years now, and Ive used the email address hinted at [on my Contact page](/contact) as a personal address for just about as long. Unfortunately, it wasnt until recently that I learned that some senders *cant* or *wont* send to it because it is set up as an alias instead of a proper address.
The solution provided by Google is to use a Google Workspace email instead. I guess Ill just have to add another address to Thunderbird.
---
For anyone whos curious, heres what Google has to say about the matter [on their help page](https://support.google.com/domains/answer/3251241?hl=en#zippy=%2Cemail-forwarding-delivery-issues-from-sender):
> You may not get the email forwarded to you by senders with specific email authentication settings. Regardless of your mail settings in Google Domains, some email senders have rules that prevent their mail from being delivered with email forwarding systems.
>
> **Tip:** To avoid delivery issues, use a custom email with Google Workspace instead of email forwarding.

View File

@ -0,0 +1,9 @@
+++
title = "Example posts"
sort_by = "date"
template = "posts.html"
page_template = "post.html"
transparent = true
+++
Posts

View File

@ -0,0 +1,8 @@
+++
title = "Encryption Flashcards"
date = 2023-07-19
[taxonomies]
tags= ["shortnotes"]
+++
I think I added an extra 80 or so cards today just for encryption algorithms key lengths, block sizes, etc… I dont expect they will be used in a lot of CISSP questions, but Ill ace whatever questions involve them.

View File

@ -0,0 +1,8 @@
+++
title = "\"Prompt Engineering\""
date = 2023-07-28
[taxonomies]
tags= ["shortnotes"]
+++
A small realization just came to me: theres a certain irony to “prompt engineering” being something that people try to teach as if its a programming discipline. Wasnt the goal of the natural language models to make it so that people can speak normally and get the output they want? Shouldnt that mean that “prompt engineering” should be the same as a communications or writing class?

View File

@ -0,0 +1,8 @@
+++
title = "Security Models"
date = 2023-07-14
[taxonomies]
tags= ["shortnotes"]
+++
Im reviewing security models in preparation for taking the CISSP exam. Its something I havent had a lot of reason to think about since I took a class on it in college. Bell-LaPadula, Biba, Clark-Wilson, etc…. Im glad I know what Anki is now.

View File

@ -0,0 +1,9 @@
+++
title = "YouTube Music"
date = 2023-07-24
[taxonomies]
tags= ["shortnotes"]
+++
A funny thing Ive noticed about YouTube Music: it doesnt seem to take your recently-listened-to music into account when showing quick recommendations if you have YouTube history turned off. I can listen to as much blues or j-rock as I want, but it doesnt start showing those as quick recommends until I hit the like button on a track. Unfortunately, this also means that things I liked a while ago dont appear anymore.

View File

@ -0,0 +1,9 @@
+++
title = "Example posts"
sort_by = "date"
template = "posts.html"
page_template = "post.html"
transparent = true
+++
Posts

View File

@ -0,0 +1,59 @@
+++
title = "My Experience Studying For and Taking the CISSP Exam"
date = 2023-08-15
[taxonomies]
tags= ["security","certification"]
+++
This post is about studying for and taking the (ISC)2 CISSP exam. Ill talk about my experiences, what I thought was useful, what I thought wasnt useful, and some high-level information about the test. I will not go into specifics about the questions on the test.
## Studying
I primarily used five sources for the exam:
- Sybex CISSP Official Study Guide
- Sybex CISSP Official Practice Tests
- LearnZApp CISSP official practice test app
- Anki
- r/cissp subreddit (for meta-information)
I had access to the first two resources through OReillys online learning subscription which I had for free through my alma maters library. Both were good resources, but had multiple clear errors in the answer key (as in, mentioning something not even referenced in the question or having same answer associated with a different letter).
I took the first practice test before starting on the Official Study Guide (OSG) book. I scored a 60%. I completed the chapter questions after reading each chapter of the OSG, then did another two practice tests. By the end, I was scoring ~80%.
I cannot really recommend paying for the official practice test app if you have the practice test book. A good number of the questions in the app were identical to the ones in the book. Also, the “readiness score” isnt helpful I had a 55% when I took my exam.
## Anki
Anki, for those unfamiliar, is a [spaced-repetition software](https://en.wikipedia.org/wiki/Spaced_repetition) for flashcards. Ive used it for Japanese, trivia, grep flags, tmux keybinds, and more. It is one of the most useful pieces of software Ive ever used.
I used two Anki decks: one of my own creation, and [lfionxkshine](https://www.reddit.com/user/lfionxkshine/)s CISSP 10k deck. While lfionxkshines deck is very impressive for its size, I didnt continue using it for a few reasons:
- There are a very large number of cards that are things Id already committed to long-term memory. It makes no sense to spend such a large amount of time sorting through to find the useful cards instead of making them myself.
- Some of the cards were contained incomplete or incorrect information.
- One question was “What layer of the ring protection scheme is not normally implemented?”
This question is both in the Anki deck as an open-ended question, and in the official practice test app as a multiple-choice question with the options 0, 1, 3, and 4. Both formats list “Layer 1” as the correct answer but the practice test app goes on to tell that the full answer is layers 1 and 2.
Its better to not study the card at all than to memorize the wrong thing.
Its worth noting that Id made over 700 cards while studying but only reviewed about half of them by the time I took the exam (see below in the Taking section to see why).
## r/CISSP Subreddit
I spent a good amount of time before the exam browsing the r/cissp subreddit to see what others thoughts were on exam prep materials and the format of the exam.
## College Degree and Hands-On Experience
I have a four-year degree in computer security, and just under 2 years experience doing penetration testing. I think that had a significant impact on how much less I had to study compared to others.
---
## Taking
The days leading up to my test were, in short, a mess. The clothes dryer broke. The AC broke and it would get into the 90s some days. I was doing prep for a job offer I had just accepted. Id already bought the exam voucher and wanted to use it before things got even more hectic. I was prepared to fail the exam, but come out with better knowledge of what the questions would be like and where I would need to study more.
The sign-in process for the exam was uneventful. The only difference between it and any other certification test Ive taken (Sec+, CC, etc…) is that I had to get my palms scanned a bunch.
Again, I will not discuss details of questions. All I will say is that the questions were generally less technical than I expected, and slightly easier than some of the practice questions.
I would often see comments on the subreddit about the exam drilling you on whatever it thinks is what you struggle with the most as you get further in the exam. I dont think that I experienced that. Id have a difficult question from a random domain, followed by a really easy question from a different one. I was fairly certain that I was going to fail with how easy some of the questions near the end were. Then I hit submit on Q125 and was told my test was over. I passed.

View File

@ -0,0 +1,10 @@
+++
title = "Using Vi[m]"
date = 2023-09-19
[taxonomies]
tags= ["shortnotes"]
+++
I'm finally giving Vi[m] a try. It's hard to get used to it after using `nano` for so long. Surprisingly, it's not the `:wq` or insert mode stuff that is catching me, but the fact taht I can't go to the previous/next ling by pressing left/right at the line ends.
(Yes, I realize I can modify this in the .vimrc file but I'm attempting to keep it as close to default as possible since I work on so many different systems.)

View File

@ -0,0 +1,9 @@
+++
title = "Example posts"
sort_by = "date"
template = "posts.html"
page_template = "post.html"
transparent = true
+++
Posts

View File

@ -0,0 +1,19 @@
+++
title = "When do you change the default settings (on tools/apps?)"
description = "Musing on defaults"
date = 2023-09-28
[taxonomies]
tags= ["uncategorized"]
+++
That question is rhetorical. I already have a good system in place for myself.
I will *always* review privacy settings. Its rare that privacy settings will default to the more private options unless youre using certain open source software such as KDE. Perhaps ironically, Ill usually enable the anonymous usage statistics in those cases. The reason for that is a story for another post, though.
Things like keybinds and such are another story. Sometimes Ill change the settings to whatever gets me the most use, and sometimes Ill avoid changing the defaults as much as possible.
On one hand, if I have something like Joplin or Firefox, Ill obsess over each setting and get it configured *just so*. These are tools that Ill likely only use from devices I own, and only from a small percentage of them at that. Ill only need to do that setup once every few months.
However, take something like `Vim` or `tmux`: I use these very often (more often than Joplin for sure), but I use them on almost every system I work on. This includes systems that arent owned by me or systems that Ill only *use* once every few months. If someone else uses the system, they should be able to expect how these tools will behave.
Its for this reason that I havent configured tmux, Vim, or similar tools on my own systems. I use the system default settings for tmux. I think I have small vanity options configured for Vim (syntax highlighting, hard tabs), but nothing more.

View File

@ -0,0 +1,16 @@
+++
title = "python `or [default]`"
date = 2023-10-02
[taxonomies]
tags= ["shortnotes"]
+++
Did you know that you can use the “or” keyword in python to set a “default” for a variable?
```py
variable_name = value_or_none() or "default value!"
```
Over five years since I started using Python, and Im only learning this now. I wish I knew about it sooner.

View File

@ -0,0 +1,9 @@
+++
title = "Example posts"
sort_by = "date"
template = "posts.html"
page_template = "post.html"
transparent = true
+++
Posts

View File

@ -0,0 +1,12 @@
+++
title = "Backups and YAML"
date = 2023-10-29
[taxonomies]
tags= ["shortnotes"]
+++
Finally doing something that I should have done a long time ago adding a second (and in some places, first) backup to my systems. BorgBase won over rsync.net for price, and over Backblaze B2 for ease of use with Borg. Bonus points for also making my GUI of choice Vorta.
Additionally, Im automating as much as possible with Ansible. I still loathe YAML for configuring anything, but Ansible nearly makes that worth it. ;p

View File

@ -0,0 +1,11 @@
+++
title = "Bash history search"
date = 2023-10-05
[taxonomies]
tags= ["shortnotes"]
+++
Another useful tip for Linux users and admins: you can search your command history in bash with `Ctrl+r`. Typing something and hitting it again will search backward through commands that match that pattern. It saves a lot of time compared to pressing up repeatedly.

View File

@ -0,0 +1,20 @@
+++
title = "Resolved: Connection Issues on a libvirt Isolated Network to Router"
date = 2023-10-07
[taxonomies]
tags= ["resolved"]
+++
Quick answer: The isolated network auto-allocates the first address to a virtual interface for the hypervisor host. Check that your routers IP isnt set to the same thing.
---
I was having issues the other night with my homelab setup. Specifically, devices would randomly be unable to communicate with the router. Pinging worked, but accessing OPNsenses web interface wasnt. It wasnt firewall issues either.
After running `tcpdump` on the opnsense box, I realized that my traffic wasnt even reaching it. I double checked that they were on the same vnet (they were), then checked the ARP table on the client I was using. Sure enough, the MAC of the supposed gateway wasnt the same as the OPNsense interface.
I took down all other VMs except the router and client to isolate the issue in case it was a misconfiguration, but the issue persisted. This meant it had to be something involving libvirt.
Sure enough, a quick Google search revealed that libvirt will still allocate an address for the host on isolated subnets even if you disable services such as DHCP. It defaults to the first IP address in the subnet.
I changed the OPNsense LAN IP from .1 to .254 and the issue was resolved.

View File

@ -0,0 +1,11 @@
+++
title = "A surreal blog"
date = 2023-10-31
updated = 2023-11-13
[taxonomies]
tags= ["shortnotes"]
+++
I found a blog by someone who works at a polar research station. [Their post on nights](https://brr.fyi/posts/polar-night) there is surreal. It reminds me of Signalis.
EDIT: I realized while porting this post to Zola that I posted this on Halloween. It wasn't my intention to match that with a horror game reference, but it fits! :D

View File

@ -0,0 +1,12 @@
+++
title = "Wordpress Gripes"
date = 2023-10-30
[taxonomies]
tags= ["shortnotes"]
+++
Late night thought before work maintenance: I dont particularly enjoy WordPress writing interface. It doesnt feel suitable for quick or technical writing. Customizing the site feels like fighting against the tool.
Pelican (the static site generator) felt a lot nicer. Writing in markdown feels much nicer than using Gutenberg or the Classic Editor (plus I can do version control with Git!) and .html.j2 files for customization is easier than WordPress syntax. Im hardly a Python dev I dont wanna be a web dev too.

View File

@ -0,0 +1,9 @@
+++
title = "Example posts"
sort_by = "date"
template = "posts.html"
page_template = "post.html"
transparent = true
+++
Posts

View File

@ -0,0 +1,18 @@
+++
title = "Google finally feels worse"
date = 2023-11-06
[taxonomies]
tags= ["shortnotes"]
+++
I didnt really agree with statements about Googles search getting worse until today.
Using search would usually give me what I wanted within the first few results. All Id need to do was skip past the inevitable Amazon link that would show up.
But for the past few days, I feel like Ive had more and more “junk” in it.
- Links that look like they are for a specific post on a forum, but take me to the main page instead.
- Links for blogs that look like they were written by an AI.
- Links that go to entirely different websites than those they appear to be for.
Its admittedly tiring and makes me want to restart my habit of bookmarking more sites.

View File

@ -0,0 +1,9 @@
+++
title = "Example posts"
sort_by = "date"
template = "posts.html"
page_template = "post.html"
transparent = true
+++
Posts

9
content/posts/_index.md Normal file
View File

@ -0,0 +1,9 @@
+++
title = "Example posts"
sort_by = "date"
template = "posts.html"
page_template = "post.html"
transparent = true
+++
Posts

View File

@ -0,0 +1,9 @@
+++
title = "Zola Test"
description = "Test of Zola"
date = 2023-01-16
[taxonomies]
tags= ["Zola", "test"]
+++
This is a test of Zola as a website SSG.

6
content/search.md Normal file
View File

@ -0,0 +1,6 @@
+++
title = "Search"
images = []
template = "search.html"
in_search_index = false
+++

7
index.html Normal file
View File

@ -0,0 +1,7 @@
{% extends "base.html" %}
{% block content %}
<h1 class="title">
This is my blog made with Zola.
</h1>
{% endblock content %}

142
sass/base.scss Normal file
View File

@ -0,0 +1,142 @@
/*Resets*/
@import "normalize.css";
/*Site Wide Components*/
@import "variables.css";
@import "utilities.css";
@import "typography.css";
@import "header.css";
@import "footer.css";
@import "search.css";
/* Page Specific Components*/
@import "blog.css";
@import "gallery.css";
@import "tags.css";
@import "custom.css";
body {
font-family: var(--font-base);
word-wrap: break-word;
background-color: var(--bg-color);
color: var(--text-color);
max-width: 50em;
font-size: 1.25rem;
margin: 0 auto;
padding: 0 3rem;
line-height: 1.8rem;
display: flex;
min-height: 100vh;
flex-direction: column;
overflow-y: scroll;
}
::selection {
text-shadow: none;
color: #fff;
background: var(--text-color);
}
article {
flex: 1;
margin-bottom: 2rem;
}
.highlight-handle {
background: var(--text-color);
border-radius: 4px;
color: var(--white);
padding: 4px 8px;
}
pre {
margin-bottom: 0;
margin-top: 0;
padding: 20px;
}
hr {
border: 0;
height: 1px;
margin: 2rem 0;
background: var(--light-grey);
}
pre,
textarea {
overflow: auto;
}
img {
margin: 10px auto 10px auto;
max-width: 100%;
display: block;
}
a img {
border: none;
}
figure {
margin: 0;
text-align: center;
}
fieldset {
border: 0;
margin: 0;
padding: 0;
}
textarea {
resize: vertical;
}
.site-name {
color: var(--text-color);
}
@media (max-width: 900px) {
body {
padding: 0 2rem;
}
h1 {
font-size: 2.2rem;
}
h2 {
font-size: 1.8rem;
}
h3 {
font-size: 1.5rem;
}
h4 {
font-size: 1.3rem;
}
}
@media (max-width: 600px) {
body {
padding: 0 1rem;
}
h1 {
font-size: 1.8rem;
}
h2 {
font-size: 1.6rem;
}
h3 {
font-size: 1.2rem;
}
h4 {
font-size: 1rem;
}
}

126
sass/blog.scss Normal file
View File

@ -0,0 +1,126 @@
.posts {
margin: 0;
padding: 0;
}
.post {
display: block;
article {
img {
// max-width: 800px;
max-height: 90vh;
border-radius: var(--border-radius);
&.small {
max-height: none;
width: 100%;
max-width: 500px;
}
}
}
}
.post-header {
display: flex;
align-items: center;
}
.post-header .meta .date {
margin-right: 2rem;
width: 64px;
text-align: center;
color: var(--heading-color);
}
.post-header .meta .date .day {
font-family: "Playfair Display", serif;
font-weight: 700;
line-height: 0.75em;
font-size: 2em;
display: block;
margin: 0 0 0.5rem 0;
}
.post-header .meta .date .rest {
display: block;
font-size: 0.75em;
}
.post .title.small {
margin: 0 0 10px 0;
}
.post .post-header {
margin: 30px 0;
}
.post-header h1.title {
margin: -10px 0 0 0;
}
.archive-year {
display: flex;
width: 100%;
justify-content: center;
align-items: center;
text-align: center;
}
.archive-year:before,
.archive-year:after {
content: "";
border-top: 1px solid var(--light-grey);
margin: 0 20px 0 0;
flex: 1 0 20px;
}
.archive-year:after {
margin: 0 0 0 20px;
}
.youtube {
position: relative;
padding-bottom: 56.25%;
iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
}
.draft {
color: var(--red);
font-weight: bold;
font-size: 1rem;
margin-left: 0.5rem;
display: inline-block;
}
.tags {
list-style: none;
padding: 0;
margin: 1rem 0;
li {
display: inline-block;
a {
display: block;
margin: 0.25rem;
padding: 0.25rem 1rem;
font-size: 0.9em;
background-color: transparent;
border: 1px solid var(--primary);
border-radius: var(--border-radius);
}
}
}

1
sass/custom.scss Normal file
View File

@ -0,0 +1 @@
// Override this scss file in your own sass folder to add your own styling

9
sass/footer.scss Normal file
View File

@ -0,0 +1,9 @@
footer {
text-align: right;
font-size: 0.75em;
border-top: 1px solid var(--light-grey);
padding: 1rem 0;
display: flex;
justify-content: space-between;
align-items: center;
}

50
sass/gallery.scss Normal file
View File

@ -0,0 +1,50 @@
.gallery {
margin: 0;
padding: 0;
list-style: none;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: flex-start;
align-content: space-around;
}
.thumbnail {
display: inline-block;
width: 10rem;
// Body has 1rem horizontal padding
width: calc(100% / 6);
a {
display: inline-block;
padding: 0.5rem;
img {
margin: 0;
border-radius: var(--border-radius);
}
}
}
@media (max-width: 850px) {
.thumbnail {
width: calc(100% / 5);
}
}
@media (max-width: 700px) {
.thumbnail {
width: calc(100% / 4);
}
}
@media (max-width: 550px) {
.thumbnail {
width: calc(100% / 3);
a {
padding: 0.25rem;
}
}
}

89
sass/header.scss Normal file
View File

@ -0,0 +1,89 @@
header {
margin: 2rem 0;
}
header .avatar {
float: left;
margin: 0 2rem 0 0;
}
header .links {
line-height: 2.2rem;
}
header .avatar img {
width: 4rem;
height: 4rem;
overflow: hidden;
border-radius: 100%;
}
header .site-description {
display: flex;
justify-content: space-between;
align-items: center;
p {
margin: 0 0 1rem 0;
}
}
header h1 {
margin: 0;
// line-height: 0.2rem;
}
.social li,
.social ul {
margin: 0;
padding: 0;
}
.social li {
display: inline-block;
list-style: none;
margin: 0 30px 0 0;
}
.social a {
color: #333;
}
.social a:hover {
color: var(--primary);
}
.social nav {
margin: 0;
padding: 0;
border: none;
min-width: 50px;
margin-left: 15px;
}
.social ul svg {
max-height: 15px;
}
nav {
border-top: 1px solid var(--light-grey);
padding-top: 1rem;
}
nav a {
margin-right: 1.5rem;
}
@media (max-width: 900px) {
.social li {
margin: 0;
}
nav a {
margin-right: 0.5rem;
}
header {
margin: 1rem 0;
}
}

351
sass/normalize.scss vendored Normal file
View File

@ -0,0 +1,351 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input {
/* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select {
/* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}

58
sass/search.scss Normal file
View File

@ -0,0 +1,58 @@
.search-container input {
width: 100%;
padding: 0.5rem 1rem;
margin-bottom: 2rem;
font-weight: bold;
background-color: transparent;
border: 1px solid var(--light-grey);
border-radius: var(--border-radius);
}
.search-container input:focus {
border-color: var(--dark-grey);
}
.search-results {
display: none;
color: var(--text-color);
overflow: auto;
}
.search-results__items {
list-style: none;
}
.search-results li {
margin-top: 1rem;
border-bottom: 1px solid var(--light-grey);
}
.search-results li:last-child {
border-bottom: none;
}
.search-results li:first-of-type {
margin-top: 0;
}
.search-results__item {
margin-bottom: 1rem;
h3 {
margin: 1rem 0 0 0;
}
p {
margin: 0 0 0 0;
padding-bottom: 1rem;
}
}
.search-results__item a {
font-size: 1.2rem;
display: inline-block;
margin-bottom: 0.5rem;
}

9
sass/tags.scss Normal file
View File

@ -0,0 +1,9 @@
.tag-cloud {
margin-top: 20px;
}
.tag-cloud li {
display: inline;
list-style-type: none;
padding-right: 20px;
}

89
sass/typography.scss Normal file
View File

@ -0,0 +1,89 @@
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-headings);
line-height: 1.3em;
margin: 30px 0 20px 0;
font-weight: bold;
color: var(--heading-color);
}
h1 {
font-size: 2.7rem;
}
h2 {
font-size: 2.3rem;
}
h3 {
font-size: 1.95rem;
}
h4 {
font-size: 1.55rem;
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
blockquote {
margin-left: 1rem;
font-style: italic;
font-size: 1.4rem;
font-family: Georgia, bitstream charter, serif;
border-left: 3px solid;
border-color: var(--text-color);
padding-left: 20px;
}
blockquote cite {
font-size: 70%;
opacity: 0.8;
}
blockquote em {
font-weight: 600;
}
a {
color: var(--primary);
text-decoration: none;
}
a:hover,
a.active {
text-decoration: underline;
}
input:focus,
textarea:focus {
outline: none;
}
pre,
code {
font-family: var(--font-monospace);
text-rendering: optimizeLegibility;
}
@media (max-width: 700px) {
h1,
h2,
h3,
h4,
h5,
h6 {
letter-spacing: 1px;
}
}

19
sass/utilities.scss Normal file
View File

@ -0,0 +1,19 @@
.center {
text-align: center;
}
.ad-info {
border-left: solid 0.3rem #64dd17;
line-height: 24px;
overflow: hidden;
padding: 0.8rem;
background-color: rgba(100, 221, 23, 0.1);
}
.ad-warning {
border-left: solid 0.3rem #fa9209;
line-height: 24px;
overflow: hidden;
padding: 0.8rem;
background-color: red;
}

17
sass/variables.scss Normal file
View File

@ -0,0 +1,17 @@
:root {
--primary: #661fff;
--red: red;
--heading-color: #1a043b;
--text-color: #3e3f4d;
--bg-color: #f8f5f3;
--black: #212529;
--white: #fdfdfd;
--dark-grey: #343334;
--gray: #616060;
--light-grey: #ccc;
--lighter-gray: #f6f6f6;
--font-base: 'Andada Pro', sans-serif;
--font-monospace: menlo, monaco, lucida console, liberation mono, dejavu sans mono, bitstream vera sans mono, courier new, monospace, serif;
--font-headings: 'Andada Pro', sans-serif;
--border-radius: 0.5rem;
}

BIN
static/inky.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

180
static/js/search.js Normal file
View File

@ -0,0 +1,180 @@
function debounce(func, wait) {
var timeout;
return function () {
var context = this;
var args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function () {
timeout = null;
func.apply(context, args);
}, wait);
};
}
// Taken from mdbook
// The strategy is as follows:
// First, assign a value to each word in the document:
// Words that correspond to search terms (stemmer aware): 40
// Normal words: 2
// First word in a sentence: 8
// Then use a sliding window with a constant number of words and count the
// sum of the values of the words within the window. Then use the window that got the
// maximum sum. If there are multiple maximas, then get the last one.
// Enclose the terms in <b>.
function makeTeaser(body, terms) {
var TERM_WEIGHT = 40;
var NORMAL_WORD_WEIGHT = 2;
var FIRST_WORD_WEIGHT = 8;
var TEASER_MAX_WORDS = 30;
var stemmedTerms = terms.map(function (w) {
return elasticlunr.stemmer(w.toLowerCase());
});
var termFound = false;
var index = 0;
var weighted = []; // contains elements of ["word", weight, index_in_document]
// split in sentences, then words
var sentences = body.toLowerCase().split(". ");
for (var i in sentences) {
var words = sentences[i].split(" ");
var value = FIRST_WORD_WEIGHT;
for (var j in words) {
var word = words[j];
if (word.length > 0) {
for (var k in stemmedTerms) {
if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) {
value = TERM_WEIGHT;
termFound = true;
}
}
weighted.push([word, value, index]);
value = NORMAL_WORD_WEIGHT;
}
index += word.length;
index += 1; // ' ' or '.' if last word in sentence
}
index += 1; // because we split at a two-char boundary '. '
}
if (weighted.length === 0) {
return body;
}
var windowWeights = [];
var windowSize = Math.min(weighted.length, TEASER_MAX_WORDS);
// We add a window with all the weights first
var curSum = 0;
for (var i = 0; i < windowSize; i++) {
curSum += weighted[i][1];
}
windowWeights.push(curSum);
for (var i = 0; i < weighted.length - windowSize; i++) {
curSum -= weighted[i][1];
curSum += weighted[i + windowSize][1];
windowWeights.push(curSum);
}
// If we didn't find the term, just pick the first window
var maxSumIndex = 0;
if (termFound) {
var maxFound = 0;
// backwards
for (var i = windowWeights.length - 1; i >= 0; i--) {
if (windowWeights[i] > maxFound) {
maxFound = windowWeights[i];
maxSumIndex = i;
}
}
}
var teaser = [];
var startIndex = weighted[maxSumIndex][2];
for (var i = maxSumIndex; i < maxSumIndex + windowSize; i++) {
var word = weighted[i];
if (startIndex < word[2]) {
// missing text from index to start of `word`
teaser.push(body.substring(startIndex, word[2]));
startIndex = word[2];
}
// add <em/> around search terms
if (word[1] === TERM_WEIGHT) {
teaser.push("<b>");
}
startIndex = word[2] + word[0].length;
teaser.push(body.substring(word[2], startIndex));
if (word[1] === TERM_WEIGHT) {
teaser.push("</b>");
}
}
teaser.push("…");
return teaser.join("");
}
function formatSearchResultItem(item, terms) {
return '<div class="search-results__item">'
+ `<h3><a href="${item.ref}">${item.doc.title}</a></h3>`
+ `<p>${makeTeaser(item.doc.body, terms)}</p>`
+ '</div>';
}
function initSearch() {
var $searchInput = document.getElementById("search");
var $searchResults = document.querySelector(".search-results");
var $searchResultsItems = document.querySelector(".search-results__items");
var MAX_ITEMS = 20;
var options = {
bool: "AND",
fields: {
title: { boost: 2 },
body: { boost: 1 },
}
};
var currentTerm = "";
var index = elasticlunr.Index.load(window.searchIndex);
$searchInput.addEventListener("keyup", debounce(function () {
var term = $searchInput.value.trim();
if (term === currentTerm || !index) {
return;
}
$searchResults.style.display = term === "" ? "none" : "block";
$searchResultsItems.innerHTML = "";
currentTerm = term;
if (term === "") {
return;
}
var results = index.search(term, options);
if (results.length === 0) {
$searchResults.style.display = "none";
return;
}
for (var i = 0; i < Math.min(results.length, MAX_ITEMS); i++) {
var item = document.createElement("li");
item.innerHTML = formatSearchResultItem(results[i], term.split(" "));
$searchResultsItems.appendChild(item);
}
}, 150));
}
if (document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll)
) {
initSearch();
} else {
document.addEventListener("DOMContentLoaded", initSearch);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

143
templates/base.html Normal file
View File

@ -0,0 +1,143 @@
{% import "macros/head.html" as head -%}
{% import "macros/opengraph.html" as social -%}
{% import "macros/hooks.html" as hooks -%}
{% import "macros/images.html" as images -%}
<!DOCTYPE html>
<html lang="en" prefix="og: https://ogp.me/ns#">
<head>
{%- block general_meta -%}
{{ head::general_meta() }}
{%- endblock general_meta -%}
{%- block og_preview -%}
{{ social::og_preview() }}
{%-endblock og_preview -%}
{% block rss -%}
<link rel="alternate"
type="application/rss+xml"
title="{{config.title}}"
href="{{ get_url(path='atom.xml',trailing_slash=false)|safe}}">
{% endblock rss -%}
{% if config.extra.google_analytics_tag_id -%}
<!-- Google Analytics tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id={{ config.extra.google_analytics_tag_id }}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ config.extra.google_analytics_tag_id }}');
</script>
{% endif -%}
<link rel="preconnect"
href="https://fonts.googleapis.com">
<link rel="preconnect"
href="https://fonts.gstatic.com"
crossorigin>
<!-- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&family=Playfair+Display:wght@700&display=swap" rel="stylesheet"> -->
<link href="https://fonts.googleapis.com/css2?family=Andada+Pro&display=swap&family=Playfair+Display"
rel="stylesheet">
<link rel="stylesheet"
href="{{ get_url(path='base.css',trailing_slash=false)|safe}}">
<script src="https://cdnjs.cloudflare.com/ajax/libs/feather-icons/4.28.0/feather.min.js"
integrity="sha512-7x3zila4t2qNycrtZ31HO0NnJr8kg2VI67YLoRSyi9hGhRN66FHYWr7Axa9Y1J9tGYHVBPqIjSE1ogHrJTz51g=="
crossorigin="anonymous"></script>
</head>
<body>
<header>
{% if config.extra.avatar -%}
<div class="avatar">
<a href="/">
{{ images::responsive_image(path="", src=config.extra.avatar, default_size=128, sizes=[64,128,256], alt=config.title ) }}
</a>
</div>
{% endif -%}
<a class="site-name"
href="/">
<h1>{{ config.title }}</h1>
</a>
<div class="site-description">
<p>{{ config.description }}</p>
</div>
<nav>
<div class="links">
{% for menu_link in config.extra.menu_links -%}
{% set link_url = menu_link.url | replace(from="$BASE_URL", to=config.base_url) -%}
<a {% if current_url and current_url==link_url %}class="active" {% endif %}
href="{{ link_url | safe}} ">{{menu_link.name}}</a>
{% endfor -%}
</div>
</nav>
</header>
<article>
{% block content -%}
{% endblock -%}
</article>
<footer>
<div class="social">
<ul>
{# Github #}
{% if config.extra.link_github_username -%}
<li>
<a href="https://github.com/{{ config.extra.link_github_username }}"
title="Github" rel="me"><i data-feather="github"></i></a>
</li>
{% endif -%}
{# Mastadon #}
{% if config.extra.link_mastodon_url -%}
<li>
<a href="{{ config.extra.link_mastodon_url }}"
title="Mastodon" rel="me"><i data-feather="message-square"></i></a>
</li>
{% endif -%}
{# Twitter #}
{% if config.extra.link_twitter_username -%}
<li>
<a href="https://twitter.com/{{ config.extra.link_twitter_username }}"
title="Twitter"
rel="me"><i data-feather="twitter"></i></a>
</li>
{% endif -%}
{# Instagram #}
{% if config.extra.link_instagram_username -%}
<li>
<a href="https://www.instagram.com/jimmyff_art/{{ config.extra.link_instagram_username }}"
title="Medium"
rel="me"><i data-feather="instagram"></i></a>
</li>
{% endif -%}
{# Medium #}
{% if config.extra.link_medium_username -%}
<li>
<a href="https://medium.com/@{{ config.extra.link_medium_username }}"
title="Medium"
rel="me"><i data-feather="file-text"></i></a>
</li>
{% endif -%}
{# RSS feed #}
<li>
<a href="{{ get_url(path='atom.xml',trailing_slash=false)|safe }}"
title="{{config.title}}"><i data-feather="rss"></i></a>
</li>
</ul>
</div>
<p> © {{ config.title }} {{ now() | date(format="%Y") }}
{# If you remove the powered by information, it would be appreciated if
you could add information & links somewhere else on your site to credit
those that have created your tools. #}
{% if config.extra.disable_powered_by and config.extra.disable_powered_by == true %}{% else %}<br>Powered by <a target="_blank" href="https://getzola.org/">Zola</a>. Theme: <a target="_blank" href="https://github.com/jimmyff/zola-inky">Inky</a>.{% endif %}
</p>
</footer>
<script>
feather.replace();
</script>
{% block body_end -%}
{% endblock body_end -%}
</body>
</html>

9
templates/blog-page.html Normal file
View File

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% block content %}
<h1 class="title">
{{ page.title }}
</h1>
<p class="subtitle"><strong>{{ page.date }}</strong></p>
{{ page.content | safe }}
{% endblock content %}

13
templates/blog.html Normal file
View File

@ -0,0 +1,13 @@
{% extends "base.html" %}
{% block content %}
<h1 class="title">
{{ section.title }}
</h1>
<ul>
<!-- If you are using pagination, section.pages will be empty. You need to use the paginator object -->
{% for page in section.pages %}
<li><a href="{{ page.permalink | safe }}">{{ page.title }}</a></li>
{% endfor %}
</ul>
{% endblock content %}

24
templates/gallery.html Normal file
View File

@ -0,0 +1,24 @@
{% extends "base.html" -%}
{% block content -%}
<h1 class="title">{{ section.title }}</h1>
<article>{{ section.content | safe }}</article>
{% for year, posts in section.pages | group_by(attribute="year") -%}
<ul class="gallery flat">
<h2 class="archive-year">{{ year }}</h2>
{% for post in posts -%}
{% if post.extra.images -%}
{% for image in post.extra.images -%}
{# { set image = resize_image(path=post.path ~ image, width=256, height=256, format=config.extra.image_format, quality=config.extra.thumbnail_quality) %} #}
<li class="thumbnail">
<a href="{{ post.permalink | safe }}" title="{{ post.title }} - {{ post.date }}">
{{ images::responsive_thumbnail(path=post.colocated_path, src=image, default_size=128, sizes=[128,256], alt=post.title ~ " - " ~ post.date ) -}}
</a>
</li>
{% endfor -%}
{% endif -%}
{% endfor -%}
</ul>
{% endfor -%}
{% endblock content -%}

6
templates/index.html Normal file
View File

@ -0,0 +1,6 @@
{% extends "base.html" %}
{% block content %}
<article>{{ section.content | safe }}</article>
{% endblock content %}

8
templates/index.md Normal file
View File

@ -0,0 +1,8 @@
{% extends "base.html" %}
{% block content %}
<h1 class="title">
This is my blog made with Zola.
</h1>
<p>Click <a href="{{ get_url(path='@/blog/_index.md') }}">here</a> to see my posts.</p>
{% endblock content %}

View File

@ -0,0 +1,11 @@
{% macro general_meta() %}
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible"
content="IE=edge">
<meta name="viewport"
content="width=device-width, initial-scale=1.0" />
<meta name="description"
content="{{ config.description }}" />
<meta name="keywords"
content="{{ config.extra.keywords }}" />
{% endmacro general_meta %}

View File

@ -0,0 +1,10 @@
{% extends "base.html" %}
{# Page hooks #}
{% macro post_above_content(page) %}{% endmacro post_above_content %}
{% macro post_below_content(page) %}{% endmacro post_below_content %}
{% macro post_below_tags(page) %}{% endmacro post_below_tags %}
{% macro posts_below_title(page) %}
<span class="description"> {{page.description}} </span>
{% endmacro posts_below_title %}

View File

@ -0,0 +1,52 @@
{% extends "base.html" %}
{% macro image(path, src, alt, class="") -%}
<img alt="{{ alt }}" title="{{ alt }}" src="{{ get_url(path=path ~ src) | safe }}" class="{{ class }}" />
{% endmacro image -%}
{#
Original author: crepererum https://github.com/getzola/even/pull/48/files
Adapted to Inky template by jimmyff
#}
{% macro responsive_image(path, src, alt, default_size, sizes, class="") -%}
{% if config.extra.image_resizing_disabled and config.extra.image_resizing_disabled == true -%}
{{ image(path=path, src=src, alt=alt, class=class) -}}
{% else -%}
{% set abspath = path ~ src -%}
{% set meta = get_image_metadata(path=abspath) -%}
{% set width = meta.width -%}
{% set srcset_list = [] -%}
{% for s in sizes -%}
{% if width >= s -%}
{% set resized = resize_image(format=config.extra.image_format, path=abspath, width=s, op="fit_width", quality=config.extra.image_quality) -%}
{% set element = resized.url ~ " " ~ s ~ "w" -%}
{% set_global srcset_list = srcset_list | concat(with=[element]) -%}
{% endif -%}
{% endfor -%}
{% set default_resized = resize_image(format=config.extra.image_format, path=abspath, width=default_size, op="fit_width", quality=config.extra.image_quality) -%}
<img alt="{{ alt }}" title="{{ alt }}" src="{{ default_resized.url | safe }}" srcset="{{ srcset_list | join(sep=", ") | safe }}" class="{{ class }}" />
{% endif -%}
{% endmacro responsive_image -%}
{% macro responsive_thumbnail(path, src, alt, default_size, sizes, class="") -%}
{% if config.extra.image_resizing_disabled and config.extra.image_resizing_disabled == true -%}
{{ image(path=path, src=src, alt=alt, class=class) -}}
{% else -%}
{% set abspath = path ~ src -%}
{% set meta = get_image_metadata(path=abspath) -%}
{% set width = meta.width -%}
{% set srcset_list = [] -%}
{% for s in sizes -%}
{% if width >= s -%}
{% set resized = resize_image(format=config.extra.image_format, path=abspath, width=s, height=s, op="fill", quality=config.extra.thumbnail_quality) -%}
{% set element = resized.url ~ " " ~ s ~ "w" -%}
{% set_global srcset_list = srcset_list | concat(with=[element]) -%}
{% endif -%}
{% endfor -%}
{% set default_resized = resize_image(format=config.extra.image_format, path=abspath, width=default_size, height=default_size, op="fill", quality=config.extra.thumbnail_quality) -%}
<img alt="{{ alt }}" title="{{ alt }}" src="{{ default_resized.url | safe }}" srcset="{{ srcset_list | join(sep=", ") | safe }}" class="{{ class }}" />
{% endif -%}
{% endmacro responsive_thumbnail -%}

View File

@ -0,0 +1,53 @@
{% macro og_preview() %}
<title>{{config.title}} | {{social::og_title() }}</title>
<meta
property="og:title"
content="{{config.title}} | {{social::og_title() }}"
/>
<meta property="og:type" content="website" />
<meta property="og:url" content="{{ current_url | safe }}" />
<meta property="og:description" content="{{ social::og_description() }}" />
<meta property="og:image" content="{{social::og_image() }}" />
<meta property="og:image:url" content="{{social::og_image() }}" />
<meta property="og:image:secure_url" content="{{social::og_image() }}" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="{{social::og_title() }}" />
<meta name="twitter:description" content="{{ social::og_description() }}" />
<meta property="twitter:image" content="{{social::og_image() }}" />
{% endmacro og_preview %}
{% macro og_description() %} {%- if section -%} {%- if
section.description -%} {{ section.description }} {%- else -%} {{
config.description }} {%- endif -%} {%- elif page -%} {%- if page.summary |
string -%} {{ page.summary | striptags | truncate(length=200) }} {%- elif
page.description -%} {{ page.description }} {%- else -%} {{ config.description
}} {%- endif -%} {%- endif -%}
{% endmacro og_description %}
{% macro og_title() %}
{%- if section -%}
{%- if section.title -%}
{{ section.title | striptags }}{%- else -%}
{{ config.description }}{%- endif -%}
{%- elif page -%}
{%- if page.title -%}
{{ page.title | striptags }}
{%- else -%}
{{ config.description }}
{%- endif -%}
{%- elif term -%}
{%- if term.name -%}
{{ term.name | striptags }}
{%- else -%}
{{ config.description }}
{%- endif -%}
{%- elif taxonomy -%}
{%- if taxonomy.name -%} {{ taxonomy.name | striptags }} {%- else -%} {{ config.description }} {%- endif -%} {%- endif -%}
{% endmacro og_title %}
{% macro og_image() %}
{%- if page.extra.og_preview_img -%}
{{ get_url(path=page.extra.og_preview_img) | safe }}
{%- endif -%}
{% endmacro og_image %}

12
templates/page.html Normal file
View File

@ -0,0 +1,12 @@
{% extends "base.html" -%}
{% block title -%}
{{ config.title }} | {{page.title}}
{% endblock title -%}
{% block content -%}
<h1 class="title">
{{ page.title }}
</h1>
<article>
{{ page.content | safe }}
</article>
{% endblock content -%}

33
templates/post.html Normal file
View File

@ -0,0 +1,33 @@
{% extends "base.html" %}
{% block content %}
<section class="post">
<div class="post-header">
<div class="meta">
<div class="date">
<span class="day">{{ page.date | date(format='%d')}}</span>
<span class="rest">{{ page.date | date(format='%b %y')}}</span>
</div>
</div>
<div class="matter">
<h1 class="title">{{ page.title }} {% if page.draft %}<span class="draft">Draft</span>{% endif %}</h1>
</div>
</div>
{{ hooks::post_above_content(page=page) }}
<article>{{ page.content | safe }}</article>
{{ hooks::post_below_content(page=page) }}
{% if page.taxonomies is containing ("tags") %}
<ul class="tags">
{% for tag in page.taxonomies["tags"] %}
<li><a href='{{ config.base_url | safe }}/tags/{{ tag | slugify }}'>{{ tag }}</a></li>
{% endfor %}
</ul>
{% endif %}
{{ hooks::post_below_tags(page=page) }}
</section>
{% endblock content %}

29
templates/posts.html Normal file
View File

@ -0,0 +1,29 @@
{% extends "base.html" %} {% block content %}
<h1 class="title">{{ section.title }}</h1>
<article>{{ section.content | safe }}</article>
{% for year, posts in section.pages | group_by(attribute="year") %}
<ul class="posts flat">
<h2 class="archive-year">{{ year }}</h2>
{% for post in posts %}
<li class="post">
<div class="post-header">
<div class="meta">
<div class="date">
<span class="day">{{ post.day }}</span>
<span class="rest">{{ post.date | date(format='%b') }}</span>
</div>
</div>
<div class="matter">
<div class="title small">
<a href="{{ post.permalink | safe }}">{{ post.title }}</a>
{% if post.draft %}<span class="draft">(Draft)</span>{% endif %}
</div>
{{ hooks::posts_below_title(page=post) }}
</div>
</div>
</li>
{% endfor %}
</ul>
{% endfor %} {% endblock content %}

22
templates/search.html Normal file
View File

@ -0,0 +1,22 @@
{% extends "base.html" %}
{% block content %}
<script type="text/javascript" src="{{ get_url(path='elasticlunr.min.js')|safe }}"></script>
<script type="text/javascript" src="{{ get_url(path='search_index.en.js')|safe }}"></script>
<script type="text/javascript" src="{{ get_url(path='js/search.js')|safe }}"></script>
<div class="search-container">
<input id="search"
autofocus="true"
type="search"
placeholder="Search ↵">
<div class="search-results">
<div class="search-results__items"></div>
</div>
</div>
{% endblock content %}

View File

@ -0,0 +1,3 @@
{% import "macros/images.html" as images -%}
{{ images::responsive_image(path=page.colocated_path, src=src, default_size=config.extra.images_default_size, sizes=config.extra.images_sizes, alt=alt, class=class | default(value="") ) }}

View File

@ -0,0 +1,3 @@
{% import "macros/images.html" as images -%}
{{ images::image(path=page.path, src=src, alt=alt, class=class | default(value="") ) }}

View File

@ -0,0 +1,5 @@
<div class="center">
<iframe src="https://open.spotify.com/embed/album/{{id}}" width="300" height="380" frameborder="0"
allowtransparency="true" allow="encrypted-media">
</iframe>
</div>

View File

@ -0,0 +1,22 @@
{#
Original author: crepererum https://github.com/getzola/even/pull/48/files
Adapted to Inky template by jimmyff
#}
{% if config.extra.image_resizing_disabled and config.extra.image_resizing_disabled == true %}
<img alt="{{ alt }}" src="{{ src | safe }}" />
{% else %}
{% set abspath = "./" ~ page.path ~ src %}
{% set meta = get_image_metadata(path=abspath) %}
{% set width = meta.width %}
{% set srcset_list = [] %}
{% for s in config.extra.thumbnail_sizes %}
{% if width >= s %}
{% set resized = resize_image(format=config.extra.image_format, path=abspath, width=s, height=s, op="fill", quality=config.extra.thumbnail_quality) %}
{% set element = resized.url ~ " " ~ s ~ "w" %}
{% set_global srcset_list = srcset_list | concat(with=[element]) %}
{% endif %}
{% endfor %}
{% set default_resized = resize_image(format=config.extra.image_format, path=abspath, width=config.extra.images_default_size, height=config.extra.images_default_size, op="fill", quality=config.extra.thumbnail_quality) %}
<img alt="{{ alt }}" src="{{ default_resized.url | safe }}" srcset="{{ srcset_list | join(sep=", ") | safe }}" />
{% endif %}1

View File

@ -0,0 +1,7 @@
<div class="youtube{% if class %} {{class}}{% endif %}">
<iframe src="https://www.youtube.com/embed/{{id}}{% if autoplay %}?autoplay=1{% endif %}"
webkitallowfullscreen
mozallowfullscreen
allowfullscreen>
</iframe>
</div>

View File

@ -0,0 +1,14 @@
{% extends "base.html" %}
{% block content %}
<h1>{{ taxonomy.name | capitalize }}</h1>
{% if terms %}
<ul class="tag-cloud">
{% for term in terms %}
<li><a href="{{ term.permalink | safe }}">{{ term.name }}<sup>{{ term.pages | length }}</sup></a></li>
{% endfor %}
</ul>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,29 @@
{% extends "base.html" %}
{% block content %}
<h1>{{taxonomy.name | capitalize }} &raquo; {{ term.name | capitalize }}</h1>
{% for year, posts in term.pages | group_by(attribute="year") %}
<ul class="posts flat">
<h2 class="archive-year">{{ year }}</h2>
{% for post in posts %}
<li class="post">
<div class="post-header">
<div class="meta">
<div class="date">
<span class="day">{{ post.day }}</span>
<span class="rest">{{ post.date | date(format='%b') }}</span>
</div>
</div>
<div class="matter">
<div class="title small">
<a href="{{ post.permalink | safe }}">{{ post.title }}</a>
{% if post.draft %}<span class="draft">(Draft)</span>{% endif %}
</div>
{{ hooks::posts_below_title(page=post) }}
</div>
</div>
</li>
{% endfor %}
</ul>
{% endfor %}{% endblock content %}