Add hack font and add publish and edit dates to posts.

Also changed the publish directory to ./publish in stead of using project root
master
Hugo Thunnissen 2 years ago
parent c9d9d0f3cd
commit e8b9640742

1
.gitignore vendored

@ -0,0 +1 @@
/publish

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,34 @@
/*!
* Hack typeface https://github.com/source-foundry/Hack
* License: https://github.com/source-foundry/Hack/blob/master/LICENSE.md
*/
/* FONT PATHS
* -------------------------- */
@font-face {
font-family: 'Hack';
src: url('fonts/hack-regular.woff2?sha=3114f1256') format('woff2'), url('fonts/hack-regular.woff?sha=3114f1256') format('woff');
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'Hack';
src: url('fonts/hack-bold.woff2?sha=3114f1256') format('woff2'), url('fonts/hack-bold.woff?sha=3114f1256') format('woff');
font-weight: 700;
font-style: normal;
}
@font-face {
font-family: 'Hack';
src: url('fonts/hack-italic.woff2?sha=3114f1256') format('woff2'), url('fonts/hack-italic.woff?sha=3114f1256') format('woff');
font-weight: 400;
font-style: italic;
}
@font-face {
font-family: 'Hack';
src: url('fonts/hack-bolditalic.woff2?sha=3114f1256') format('woff2'), url('fonts/hack-bolditalic.woff?sha=3114f1256') format('woff');
font-weight: 700;
font-style: italic;
}

@ -1,47 +0,0 @@
<html>
<head>
<title>Blog</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="UTF-8">
</head>
<style type="text/css">
h2 a {
color: #5b4636;
text-decoration: none;
}
h2 a:visited {
color: #5b4636;
text-decoration: none;
}
</style>
<body>
<div style="display: flex; flex-direction: horizontal;">
<a href="index.html">Home</a>
<span style="margin-left: 1em; margin-right: 1em;">|</span>
<a href="feed.xml">RSS Feed</a>
</div>
<h1>Blog</h1>
<div><h2 style="margin-bottom: 0.1em;"><a href="posts/use-your-mail-client-for-physical-mail/index.html"> How To Use Your Email Client For Physical Mail </a></h2><i style="font-size: 0.8em;">Mon, 17 Feb 2020 11:55:42 +0100</i><p style="margin-top: 0.5em;">Whether it&#39;s to re-read a conversation, find a plane ticket I ordered or check
when a meeting was planned, I often find myself looking up old emails. It&#39;s
usually easy to do so because email clients are designed for the task: Many of
them support full-text search and some even complement that with neat tagging
and categorization systems. To be honest I have become completely dependent on ... <a href="posts/use-your-mail-client-for-physical-mail/index.html">Continue reading</a></p>
</div>
<hr><div><h2 style="margin-bottom: 0.1em;"><a href="posts/simple-static-blog/index.html"> Creating a Simple Static Blog </a></h2><i style="font-size: 0.8em;">Sat, 08 Feb 2020 12:14:16 +0100</i><p style="margin-top: 0.5em;">I love personal websites. It&#39;s amazing that people can share content with the
entire world just by writing some text and throwing it behind a web server. I
wanted to know what that is like, so I set out to create a personal website of
my own. As you can see I succeeded in doing so, but getting here wasn&#39;t as
straight forward as I initially thought it would be. I thought that, being a ... <a href="posts/simple-static-blog/index.html">Continue reading</a></p>
</div>
<hr><div><h2 style="margin-bottom: 0.1em;"><a href="posts/introduction/index.html"> Introduction </a></h2><i style="font-size: 0.8em;">Sat, 08 Feb 2020 09:30:06 +0100</i><p style="margin-top: 0.5em;">Hello, welcome to my blog! My name is Hugo. I am a 22 year old Software
Engineering student from the Netherlands. Software development is a huge part
of my life, I write a lot of (weird) programs to scratch my own itch and most
software I create is open_source by default. I also run a one-man company that
provides some IT services on the side. ... <a href="posts/introduction/index.html">Continue reading</a></p>
</div>
<hr> </body>
</html>

@ -1,161 +0,0 @@
<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>Hugot Blog</title>
<link>https://hugot.nl/blog.html</link>
<description>Hugo's personal blog</description>
<language>en-us</language>
<pubDate>Thu, 16 Apr 2020 08:36:12 +0200</pubDate>
<lastBuildDate>Thu, 16 Apr 2020 08:36:12 +0200</lastBuildDate>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<generator>Hugo's Custom Bash Script</generator>
<managingEditor>social@hugot.nl (Hugot)</managingEditor>
<webMaster>infra@hugot.nl (Hugot Infra)</webMaster>
<item><title> How To Use Your Email Client For Physical Mail </title><link>https://hugot.nl/posts/use-your-mail-client-for-physical-mail/index.html</link><description> &lt;h1&gt;
How To Use Your Email Client For Physical Mail
&lt;/h1&gt;
&lt;p&gt;
Whether it&amp;#39;s to re-read a conversation, find a plane ticket I ordered or
check when a meeting was planned, I often find myself looking up old
emails. It&amp;#39;s usually easy to do so because email clients are designed for
the task: Many of them support full-text search and some even complement
that with neat tagging and categorization systems. To be honest I have
become completely dependent on those features for my day to day
life. Having full-text search and some sort of categorization for email
can be a huge time saver. When it comes to physical mail however, I still
have to browse through stacks of paper to (hopefully) find what I&amp;#39;m
looking for. I figured that it&amp;#39;d be nice to use my fancy email client to
deal with physical mail as well, so I found a way to do just that. Turns
out it&amp;#39;s pretty simple!
&lt;/p&gt;
&lt;p&gt;
The main objective here is to transform our physical mail into an email
that can be received, indexed and read by our email client of choice. Now,
one way to do that would be to type the contents of our mail into an email
by hand, but
&lt;i&gt;
ain&amp;#39;t nobody got time for that!
&lt;/i&gt;
. The (more appealing)
alternative is to use a document scanner. I have a single purpose scanner
unit from Canon that I hook up to my laptop for just this purpose.
&lt;/p&gt;
&lt;p&gt;
It isn&amp;#39;t as simple as just emailing a scanned document to ourselves
though: email clients are smart, but they can&amp;#39;t understand a word of text
in our PDF or JPEG of a physical document. They need content to be in
plain text form in order to provide us with some of their best features
like full-text search. We&amp;#39;ll have to somehow transform our scanned
documents into plain text that we can include in our email. To do this, we
can use tesseract. Tesseract is an optical character recognition (OCR)
engine, meaning that it can recognize text in images and extract it for
us. Installing it should be easy on Debian derivative distros like
Ubuntu. My laptop is running Debian unstable so I just ran
&lt;code&gt;
apt
install tesseract
&lt;/code&gt;
and started using it. Using it is as easy as
upening up a terminal and typing
&lt;code&gt;
tesseract FILE.jpg
OUTPUT
&lt;/code&gt;
. That command will save all the text that tesseract is able
to recognize in the image FILE.jpg to a file called OUTPUT.txt.
&lt;/p&gt;
&lt;aside&gt;
&lt;i&gt;
Side note: I am Dutch, so most of my physical mail is in Dutch. To
make tesseract better understand my mail I installed the
tesseract-ocr-nld package using
&lt;code&gt;
apt install
tesseract-ocr-nld
&lt;/code&gt;
. You can check what other language packs are
available by using
&lt;code&gt;
apt search tesseract-ocr
&lt;/code&gt;
.
&lt;/i&gt;
&lt;/aside&gt;
&lt;p&gt;
All we have to do from there is copy-paste the contents of that file into
an email and send it to ourselves! Depending on the formatting of the
input document, the output may not always be pleasant to read. We can
account for this by including the original document as an attachment to
the email. That way we get the best of both worlds: we can use the search
functionality of our email client to find the document, and then read it
in its original form by opening the attachment.
&lt;/p&gt;
&lt;p&gt;
This is all easy enough, but I&amp;#39;m lazy. I didn&amp;#39;t feel like opening up my
email client and doing manual copy-pasting, so I decided to automate the
process a little further. I have postfix setup on my system to relay to my
mail server, so I can simply use the
&lt;code&gt;
mail
&lt;/code&gt;
command to send
emails without a GUI mail client. I combined that with tesseract in a
little bash script. The script iterates through all of its arguments and
interprets them as filenames of scanned documents. It calls tesseract to
extract text from them, concatenates the results, attaches the files to an
email and sends it to my personal email address. Now all I have to do is
run the script with filenames of some documents and my job is done. If
anyone is interested in an actual program that does the same thing and
doesn&amp;#39;t require you to setup postfix, let me know! I might consider
authoring one if it&amp;#39;s useful to more people than just myself. The script
I&amp;#39;m currently using can be found
&lt;a href=&quot;scan-to-mailpile.bash.html&quot;&gt;
here
(pretty)
&lt;/a&gt;
and
&lt;a href=&quot;scan-to-mailpile.bash&quot;&gt;
here (raw)
&lt;/a&gt;
, but I
don&amp;#39;t recommend using it if you don&amp;#39;t fully understand its contents, it&amp;#39;s
not a polished user experience 🤓.
&lt;/p&gt;</description><pubDate>Mon, 17 Feb 2020 11:55:42 +0100</pubDate><guid isPermaLink="false"> How To Use Your Email Client For Physical Mail NDc2MDg1MjYxIDQxODUK</guid>
</item>
<item><title> Creating a Simple Static Blog </title><link>https://hugot.nl/posts/simple-static-blog/index.html</link><description></description><pubDate>Sat, 08 Feb 2020 12:14:16 +0100</pubDate><guid isPermaLink="false"> Creating a Simple Static Blog MjU5OTIyNDIwMyA2MTI5Cg==</guid>
</item>
<item><title> Introduction </title><link>https://hugot.nl/posts/introduction/index.html</link><description> &lt;h1&gt;
Introduction
&lt;/h1&gt;
&lt;p&gt;
Hello, welcome to my blog! My name is Hugo. I am a 22 year old Software Engineering
student from the Netherlands. Software development is a huge part of my life, I write a
lot of (weird) programs to scratch my own itch and most software I create
is
&lt;a href=&quot;https://github.com/hugot&quot;&gt;
open source
&lt;/a&gt;
by default. I also run a one-man
company that provides some IT services on the side.
&lt;/p&gt;
&lt;p&gt;
Between working on projects and studying I like to watch movies &amp;amp; series, listen to music
&amp;amp; podcasts, ride my road bike and take hikes.
&lt;/p&gt;
&lt;h2&gt;
What kind of blog is this?
&lt;/h2&gt;
&lt;p&gt;
Because I&amp;#39;m quite new to this and I want to keep myself interested, I won&amp;#39;t be
limiting myself to a single topic. You can expect me to post about a variety of topics
that may interest/annoy/excite me at any given moment.
&lt;/p&gt;
&lt;p&gt;
May my posts be interesting and my posting schedule be consistent 🤓🖖
&lt;/p&gt;
&lt;p&gt;
I hope to see you around! - Hugo
&lt;/p&gt;</description><pubDate>Sat, 08 Feb 2020 09:30:06 +0100</pubDate><guid isPermaLink="false"> Introduction MzYzMzkyNDgwOCA5MDcK</guid>
</item>
</channel>
</rss>

@ -17,7 +17,7 @@ here="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
printf 'Changing directory: ' printf 'Changing directory: '
pushd "$here" || exit $? pushd "$here" || exit $?
posts_file="$here/posts.txt" posts_file="$here/publish.txt"
if ! [[ -f "$posts_file" ]]; then if ! [[ -f "$posts_file" ]]; then
printf 'Posts file "%s" not found. Generation cancelled.\n' "$posts_file" >&2 printf 'Posts file "%s" not found. Generation cancelled.\n' "$posts_file" >&2
@ -54,9 +54,9 @@ print-blog-html-top() {
<body> <body>
<div style="display: flex; flex-direction: horizontal;"> <div style="display: flex; flex-direction: horizontal;">
<a href="index.html">Home</a> <a href="index.html">Home</a>
<span style="margin-left: 1em; margin-right: 1em;">|</span> <span style="margin-left: 1em; margin-right: 1em;">|</span>
<a href="feed.xml">RSS Feed</a> <a href="feed.xml">RSS Feed</a>
</div> </div>
<h1>Blog</h1> <h1>Blog</h1>
' '
@ -71,6 +71,41 @@ rfc-822-date-time() {
LC_ALL=C date "$@" --rfc-email LC_ALL=C date "$@" --rfc-email
} }
print-post-html-top() {
declare title="$1"
cat <<EOF
<!DOCTYPE HTML>
<html>
<head>
<title>${title}</title>
<link rel="stylesheet" type="text/css" href="../../style.css">
<meta charset="UTF-8">
</head>
<body>
<div style="display: flex; flex-direction: horizontal;">
<a href="../../blog.html">Blog</a>
<span style="margin-left: 1em; margin-right: 1em;">|</span>
<a href="feed.xml">RSS Feed</a>
</div>
<article>
EOF
}
print-post-html-bottom() {
declare publish_date="$1" last_edit_date="$2"
cat <<EOF
<span class="publish-date">
<i>First published: ${publish_date}</i><br>
<i>Last edited: ${last_edit_date}</i>
</span>
</article>
</body>
</html>
EOF
}
# Note: pubDate and lastBuildDate are both set to the current time. # Note: pubDate and lastBuildDate are both set to the current time.
print-blog-rss-top() { print-blog-rss-top() {
cat <<EOF cat <<EOF
@ -115,14 +150,18 @@ el-enclose() {
printf '%s' "</$element_name>" printf '%s' "</$element_name>"
} }
publish_dir="$here/publish"
site_url="https://hugot.nl" site_url="https://hugot.nl"
blog_html="$here/blog.html" blog_html="$publish_dir/blog.html"
new_html="$blog_html.new" new_html="$blog_html.new"
blog_rss="$here/feed.xml" blog_rss="$publish_dir/feed.xml"
new_rss="$blog_rss.new" new_rss="$blog_rss.new"
mkdir -p "$publish_dir" || exit $?
print-blog-html-top > "$new_html" print-blog-html-top > "$new_html"
print-blog-rss-top > "$new_rss" print-blog-rss-top > "$new_rss"
@ -132,20 +171,26 @@ while read -r post_html; do
# The title should be on the 2nd line of text, right after the link to the # The title should be on the 2nd line of text, right after the link to the
# homepage. This is a bit inflexible but it will do for now. # homepage. This is a bit inflexible but it will do for now.
title="$(tail -n +3 <<<"$text" | head -n 1 | tr -d '*')" || exit $? title="$(head -n 1 <<<"$text" | tr -d '*')" || exit $?
# Use the first 5 lines after the title as post excerpt. # Use the first 5 lines after the title as post excerpt.
excerpt="$(tail -n +4 <<<"$text" | head -n 5)" || exit $? excerpt="$(tail -n +2 <<<"$text" | head -n 5)" || exit $?
# Escape just the article element for use in the RSS feed article description. # Escape just the article element for use in the RSS feed article description.
# This way the entire article can be read from an RSS reader. # This way the entire article can be read from an RSS reader.
article_html="$(pup article < "$post_html" | head -n -1 | tail -n +2 | escape-html)" article_html="$({ head -n -1 | tail -n +2 | escape-html; } < "$post_html")"
# Escape the post html file name to safely use it in the generated html. # Escape the post html file name to safely use it in the generated html.
href="$(escape-html <<<"$post_html")" || exit $? href="$(escape-html <<<"$post_html")" || exit $?
post_dir="$(dirname "$post_html")" || exit $? post_dir="$(dirname "$post_html")" || exit $?
post_publish_dir="$publish_dir/posts/$(basename "$post_dir")" || exit $?
pubdate_file="$post_dir/publish_date.txt" pubdate_file="$post_dir/publish_date.txt"
checksum_file="$post_dir/last_checksum.txt"
last_edit_file="$post_dir/last_edit_date.txt"
current_checksum="$(cksum < "$post_html")"
declare checksum=''
# Determine a publishing date for the post # Determine a publishing date for the post
if [[ -f "$pubdate_file" ]]; then if [[ -f "$pubdate_file" ]]; then
@ -155,8 +200,37 @@ while read -r post_html; do
echo "$pubdate" > "$pubdate_file" echo "$pubdate" > "$pubdate_file"
fi fi
if [[ -f "$checksum_file" ]]; then
read -r checksum < "$checksum_file"
else
echo "$current_checksum" > "$checksum_file"
checksum="$current_checksum"
fi
if [[ -f "$last_edit_file" ]]; then
read -r last_edit_date < "$last_edit_file"
fi
if [[ "$checksum" != "$current_checksum" ]]; then
last_edit_date="$(date)"
echo "$last_edit_date" > "$last_edit_file"
echo "$current_checksum" > "$checksum_file"
fi
# Convert publishing date to be conform RFC 822 # Convert publishing date to be conform RFC 822
pubdate="$(rfc-822-date-time --date="$pubdate")" pubdate="$(rfc-822-date-time --date="$pubdate")"
last_edit_date="$(rfc-822-date-time --date="$last_edit_date")"
declare post_index_file="$post_publish_dir/index.html"
if [[ "$checksum" != "$current_checksum" ]] || ! [[ -f "$post_index_file" ]]; then
printf 'Publishing %s\n' "$post_html" >&2
mkdir -p "$post_publish_dir"
print-post-html-top "$title" > "$post_index_file"
cat "$post_html" >> "$post_index_file"
print-post-html-bottom "$pubdate" "$last_edit_date" >> "$post_index_file"
fi
{ {
el div el div
@ -181,7 +255,7 @@ while read -r post_html; do
el-enclose description "$article_html" el-enclose description "$article_html"
el-enclose pubDate "$pubdate" el-enclose pubDate "$pubdate"
echo "<guid isPermaLink=\"false\">$title$(base64 <(cksum <<<"$text"))</guid>" echo "<guid isPermaLink=\"false\">$title$(base64 <<<"$checksum")</guid>"
el-close item el-close item
} >> "$new_rss" } >> "$new_rss"
@ -193,4 +267,9 @@ print-blog-rss-bottom >> "$new_rss"
mv -v "$new_html" "$blog_html" || exit $? mv -v "$new_html" "$blog_html" || exit $?
mv -v "$new_rss" "$blog_rss" || exit $? mv -v "$new_rss" "$blog_rss" || exit $?
cp -v "$here/style.css" "$publish_dir/style.css"
cp -v "$here/index.html" "$publish_dir/index.html"
cp -rv "$here/assets" "$publish_dir/assets"
echo 'SUCCESS!' echo 'SUCCESS!'

@ -10,8 +10,9 @@
<a href="blog.html">Blog</a> <a href="blog.html">Blog</a>
<h1>Hugo's homepage</h1> <h1>Hugo's homepage</h1>
<p> <p>
Hello and welcome to my personal homepage! I'll add some info about myself to Hello and welcome to my personal homepage! I'll add some info about my
this page soon. In the mean time, maybe take a look at my <a href="blog.html">blog</a> projects to this page soon. In the mean time, maybe take a look at
my <a href="blog.html">blog</a>
</p> </p>
<p> <p>

@ -1,42 +1,28 @@
<!DOCTYPE HTML> <h1>Introduction</h1>
<html>
<head>
<title>Introduction</title>
<link rel="stylesheet" type="text/css" href="../../style.css">
<meta charset="UTF-8">
</head>
<body> <p>
<a href="../../blog.html">Home</a> Hello, welcome to my blog! My name is Hugo. I am a 22 year old Software Engineering
<article> student from the Netherlands. Software development is a huge part of my life, I write a
<h1>Introduction</h1> lot of (weird) programs to scratch my own itch and most software I create
is <a href="https://github.com/hugot">open source</a> by default. I also run a one-man
company that provides some IT services on the side.
</p>
<p> <p>
Hello, welcome to my blog! My name is Hugo. I am a 22 year old Software Engineering Between working on projects and studying I like to watch movies &amp; series, listen to music
student from the Netherlands. Software development is a huge part of my life, I write a &amp; podcasts, ride my road bike and take hikes.
lot of (weird) programs to scratch my own itch and most software I create </p>
is <a href="https://github.com/hugot">open source</a> by default. I also run a one-man
company that provides some IT services on the side.
</p>
<p> <h2>What kind of blog is this?</h2>
Between working on projects and studying I like to watch movies &amp; series, listen to music <p>
&amp; podcasts, ride my road bike and take hikes. Because I'm quite new to this and I want to keep myself interested, I won't be
</p> limiting myself to a single topic. You can expect me to post about a variety of topics
that may interest/annoy/excite me at any given moment.
</p>
<h2>What kind of blog is this?</h2> <p>May my posts be interesting and my posting schedule be consistent 🤓🖖</p>
<p>
Because I'm quite new to this and I want to keep myself interested, I won't be
limiting myself to a single topic. You can expect me to post about a variety of topics
that may interest/annoy/excite me at any given moment.
</p>
<p>May my posts be interesting and my posting schedule be consistent 🤓🖖</p> <p>I hope to see you around! - Hugo</p>
<p>I hope to see you around! - Hugo</p>
</article>
</body>
</html>
<!-- Local Variables: --> <!-- Local Variables: -->
<!-- sgml-basic-offset: 1 --> <!-- sgml-basic-offset: 1 -->

@ -0,0 +1 @@
Fri May 20 11:15:16 PM CEST 2022

@ -1,183 +1,171 @@
<!DOCTYPE html> <h1>Creating a Simple Static Blog</h1>
<html>
<head> <p>
<title>Creating a Simple Static Blog</title> I love personal websites. It's amazing that people can share content with the
<link rel="stylesheet" type="text/css" href="../../style.css"> entire world just by writing some text and throwing it behind a web server. I
<meta charset="UTF-8"> wanted to know what that is like, so I set out to create a personal website of
</head> my own. As you can see I succeeded in doing so, but getting here wasn't as
straight forward as I initially thought it would be. I thought that, being a
<body> programmer and knowing a thing or two about web servers, setting up my own
<a href="../../blog.html">Home</a> website was going to be easy: How complicated can it be to throw some text
<h1>Creating a Simple Static Blog</h1> behind a web server, right?! I was wrong. Throwing text behind a web server
can be very complicated (and wasteful). But it doesn't have to be!
<p> </p>
I love personal websites. It's amazing that people can share content with the
entire world just by writing some text and throwing it behind a web server. I <h2>The search for a CMS</h2>
wanted to know what that is like, so I set out to create a personal website of <p>
my own. As you can see I succeeded in doing so, but getting here wasn't as The first thought that popped into my head when I got started was: <em>I need to
straight forward as I initially thought it would be. I thought that, being a find myself a CMS</em>. I had a few requirements: my site should be
programmer and knowing a thing or two about web servers, setting up my own self-hosted, be lightweight, have no JavaScript in it and it should look
website was going to be easy: How complicated can it be to throw some text pretty. I also wanted to be able to write blog posts in markdown using my
behind a web server, right?! I was wrong. Throwing text behind a web server trusty text editor. The first CMSes that came to mind were WordPress, Ghost,
can be very complicated (and wasteful). But it doesn't have to be! Jekyll and Hugo. I don't want to get into too much detail, so I'll summarize
</p> my judgments here without any nuance: Wordpress is the devil, Ghost is great
but too bulky and both Jekyll and Hugo required me to learn about theming and
<h2>The search for a CMS</h2> project structure which I deemed too much effort. I just wanted to write some
<p> text and throw it behind a web server, but all solutions I saw were sophisticated
The first thought that popped into my head when I got started was: <em>I need to programs that were designed to &quot;scale&quot;, support &quot;modern
find myself a CMS</em>. I had a few requirements: my site should be workflows&quot; or be &quot;easy to use with integrated WYSIWYG
self-hosted, be lightweight, have no JavaScript in it and it should look editors&quot;. I didn't feel like exploring the idea further and gave up on
pretty. I also wanted to be able to write blog posts in markdown using my having a website for a while.
trusty text editor. The first CMSes that came to mind were WordPress, Ghost, </p>
Jekyll and Hugo. I don't want to get into too much detail, so I'll summarize
my judgments here without any nuance: Wordpress is the devil, Ghost is great <p>
but too bulky and both Jekyll and Hugo required me to learn about theming and Then, a few months back, I learned about writefreely. Writefreely is an open
project structure which I deemed too much effort. I just wanted to write some source web application from write.as that lets users create blogs that
text and throw it behind a web server, but all solutions I saw were sophisticated federate through the fediverse. I had just started to become acquainted with
programs that were designed to &quot;scale&quot;, support &quot;modern the fediverse and it seemed like a cool idea to me at the time, so me and a
workflows&quot; or be &quot;easy to use with integrated WYSIWYG friend decided to set up our own instance. It wasn't too hard to set up and
editors&quot;. I didn't feel like exploring the idea further and gave up on once it was running I only needed a couple of hours to add some custom
having a website for a while. style sheets. I finally had a fully functioning blog that satisfied all of my
</p> needs!
</p>
<p>
Then, a few months back, I learned about writefreely. Writefreely is an open <p>
source web application from write.as that lets users create blogs that After that the holiday season came along and I turned my back on blogging for
federate through the fediverse. I had just started to become acquainted with a while. When I checked on our instance three or four weeks later I was
the fediverse and it seemed like a cool idea to me at the time, so me and a displeased to discover that spammers had created accounts on the instance and
friend decided to set up our own instance. It wasn't too hard to set up and were posting spammy garbage. Sure, we could just close registrations. But this
once it was running I only needed a couple of hours to add some custom event reminded me that hosting any dynamic web application on the public
style sheets. I finally had a fully functioning blog that satisfied all of my internet is a big responsibility that involves keeping software up to date,
needs! monitoring and doing other configuration/maintenance work. Not to mention
</p> having to do regular database backups. I didn't feel like having to do any of
that, I already have by hands full with self-hosting a bunch of other
<p> services. Once again I had found a complicated solution for a simple problem:
After that the holiday season came along and I turned my back on blogging for I just wanted to throw some text behind a web server, remember? Why did I need to use a CMS
a while. When I checked on our instance three or four weeks later I was again?
displeased to discover that spammers had created accounts on the instance and </p>
were posting spammy garbage. Sure, we could just close registrations. But this
event reminded me that hosting any dynamic web application on the public <p>
internet is a big responsibility that involves keeping software up to date, CMSes seem to offer solutions to a problem that I don't have: I don't mind
monitoring and doing other configuration/maintenance work. Not to mention writing plain html and I most certainly don't need a WISYWIG editor. I also
having to do regular database backups. I didn't feel like having to do any of don't need plugins, dynamic code for analytics, pretty yaml or toml
that, I already have by hands full with self-hosting a bunch of other configuration files, templates, extensive theming, admin panels, markdown,
services. Once again I had found a complicated solution for a simple problem: mailing lists, comment threads or any other common CMS features. I just want
I just wanted to throw some text behind a web server, remember? Why did I need to use a CMS to throw some text behind a web server, so why not just write some HTML and do
again? exactly that?
</p> </p>
<p> <h2>A CMS in ~200 lines</h2>
CMSes seem to offer solutions to a problem that I don't have: I don't mind <p>
writing plain html and I most certainly don't need a WISYWIG editor. I also It was decided: I was going to blog in plain HTML. Having figured out what I
don't need plugins, dynamic code for analytics, pretty yaml or toml actually wanted, I went to work. The first order of business was creating a
configuration files, templates, extensive theming, admin panels, markdown, style sheet to make things look good. I made it my goal to use as little CSS
mailing lists, comment threads or any other common CMS features. I just want as possible and I managed to limit myself to just these 23 lines:
to throw some text behind a web server, so why not just write some HTML and do </p>
exactly that?
</p> <style type="text/css">
.code {
<h2>A CMS in ~200 lines</h2> color: #f6f3e8;
<p> background-color: #242424;
It was decided: I was going to blog in plain HTML. Having figured out what I }
actually wanted, I went to work. The first order of business was creating a .builtin {
style sheet to make things look good. I made it my goal to use as little CSS color: #e5786d;
as possible and I managed to limit myself to just these 23 lines: }
</p> .css-property {
color: #8ac6f2;
<style type="text/css"> font-weight: bold;
.code { }
color: #f6f3e8; .css-selector {
background-color: #242424; color: #cae682;
} }
.builtin { .custom {
color: #e5786d; color: #000000;
} background-color: #f4ecd8;
.css-property { }
color: #8ac6f2; .custom-1 {
font-weight: bold; color: #ffffff;
} background-color: #5b4636;
.css-selector { }
color: #cae682; </style>
}
.custom { <div class="code">
color: #000000; <pre>
background-color: #f4ecd8; <span class="css-selector">html </span>{
}
.custom-1 {
color: #ffffff;
background-color: #5b4636;
}
</style>
<div class="code">
<pre>
<span class="css-selector">html </span>{
<span class="css-property">font-family</span>: Helvetica, Arial, sans-serif; <span class="css-property">font-family</span>: Helvetica, Arial, sans-serif;
<span class="css-property">color</span>: <span class="custom-1">#5b4636</span>; <span class="css-property">color</span>: <span class="custom-1">#5b4636</span>;
<span class="css-property">background-color</span>: <span class="custom">#f4ecd8</span>; <span class="css-property">background-color</span>: <span class="custom">#f4ecd8</span>;
} }
<span class="css-selector">body </span>{ <span class="css-selector">body </span>{
<span class="css-property">padding</span>: 1em; <span class="css-property">padding</span>: 1em;
<span class="css-property">margin</span>: auto; <span class="css-property">margin</span>: auto;
} }
<span class="builtin">@media</span> only all and (pointer: coarse), (pointer: none) { <span class="builtin">@media</span> only all and (pointer: coarse), (pointer: none) {
<span class="css-selector">body </span>{ <span class="css-selector">body </span>{
<span class="css-property">font-size</span>: 5.5vmin; <span class="css-property">font-size</span>: 5.5vmin;
}
} }
}
<span class="builtin">@media</span> only all and (pointer: fine) { <span class="builtin">@media</span> only all and (pointer: fine) {
<span class="css-selector">body </span>{ <span class="css-selector">body </span>{
<span class="css-property">font-size</span>: calc(16px + 0.6vmin); <span class="css-property">font-size</span>: calc(16px + 0.6vmin);
<span class="css-property">min-width</span>: 500px; <span class="css-property">min-width</span>: 500px;
<span class="css-property">max-width</span>: 50em; <span class="css-property">max-width</span>: 50em;
}
} }
</pre> }
</div> </pre>
</div>
<p>
This is all the CSS I need to have a responsive website that looks pretty (I <p>
stole the colors from firefox's reader mode btw). It's such a small amount This is all the CSS I need to have a responsive website that looks pretty (I
that I don't mind copy-pasting it at the top of all new HTML pages that I add stole the colors from firefox's reader mode btw). It's such a small amount
to my website. This might make it harder to change the styling later, but it that I don't mind copy-pasting it at the top of all new HTML pages that I add
has the added benefit that each page is a standalone document. So for to my website. This might make it harder to change the styling later, but it
example <code>wget PAGE_URL</code> will download a HTML page that looks has the added benefit that each page is a standalone document. So for
exactly the same locally as it does on the web without having to download any example <code>wget PAGE_URL</code> will download a HTML page that looks
extra assets. exactly the same locally as it does on the web without having to download any
</p> extra assets.
</p>
<p>
The next challenge was creating and maintaining the article listing page and <p>
the RSS feed for the blog. I don't mind typing HTML pages, but typing out a The next challenge was creating and maintaining the article listing page and
page and an RSS feed containing excerpts/titles from other files gets old soon the RSS feed for the blog. I don't mind typing HTML pages, but typing out a
and I'd be bound to forget updating its content every once in a while. This page and an RSS feed containing excerpts/titles from other files gets old soon
seemed like a perfect occasion to write a little bash script, so I did. You and I'd be bound to forget updating its content every once in a while. This
can find the script <a href="../../generate-blog.bash">here (raw)</a> and seemed like a perfect occasion to write a little bash script, so I did. You
<a href="../../generate-blog.bash.html">here (pretty)</a>. What it basically can find the script <a href="../../generate-blog.bash">here (raw)</a> and
does is read in a file called posts.txt that has html filenames in it, <a href="../../generate-blog.bash.html">here (pretty)</a>. What it basically
separated by newlines. Using those filenames and the contents of the files it does is read in a file called posts.txt that has html filenames in it,
then generates a HTML page (called <a href="../../blog.html">blog.html</a>) separated by newlines. Using those filenames and the contents of the files it
and an RSS feed (called <a href="../../feed.xml">feed.xml</a>). then generates a HTML page (called <a href="../../blog.html">blog.html</a>)
</p> and an RSS feed (called <a href="../../feed.xml">feed.xml</a>).
</p>
<p>
I keep all of this neatly stored under version control <p>
<a href="https://snorba.art/hugo/website">here</a>, so deploying a new version I keep all of this neatly stored under version control
is as easy as running <code>git pull</code> on my web server. I can honestly say that <a href="https://snorba.art/hugo/website">here</a>, so deploying a new version
this is the simplest, most user-friendly CMS that I have ever used, and it is as easy as running <code>git pull</code> on my web server. I can honestly say that
only took me several months to figure out that this is exactly what I needed 🤓. this is the simplest, most user-friendly CMS that I have ever used, and it
</p> only took me several months to figure out that this is exactly what I needed 🤓.
</p>
<p>
So, to conclude this story: websites are just HTML. You don't need fancy <p>
programs or WYSIWYG editors to create a website. Just a text editor, a web So, to conclude this story: websites are just HTML. You don't need fancy
server and some spare time. programs or WYSIWYG editors to create a website. Just a text editor, a web
</p> server and some spare time.
</body> </p>
</html>
<!-- Local Variables: --> <!-- Local Variables: -->
<!-- sgml-basic-offset: 1 --> <!-- sgml-basic-offset: 1 -->

@ -0,0 +1 @@
Fri May 20 11:25:14 PM CEST 2022

@ -1,98 +1,84 @@
<!DOCTYPE HTML> <h1>How To Use Your Email Client For Physical Mail</h1>
<html> <p>
<head> Whether it's to re-read a conversation, find a plane ticket I ordered or
<title>Use Your Email Client For Physical Mail</title> check when a meeting was planned, I often find myself looking up old
<link rel="stylesheet" type="text/css" href="../../style.css"> emails. It's usually easy to do so because email clients are designed for
<meta charset="UTF-8"> the task: Many of them support full-text search and some even complement
</head> that with neat tagging and categorization systems. To be honest I have
become completely dependent on those features for my day to day
life. Having full-text search and some sort of categorization for email
can be a huge time saver. When it comes to physical mail however, I still
have to browse through stacks of paper to (hopefully) find what I'm
looking for. I figured that it'd be nice to use my fancy email client to
deal with physical mail as well, so I found a way to do just that. Turns
out it's pretty simple!
</p>
<body> <p>
<a href="../../blog.html">Home</a> The main objective here is to transform our physical mail into an email
<article> that can be received, indexed and read by our email client of choice. Now,
<h1>How To Use Your Email Client For Physical Mail</h1> one way to do that would be to type the contents of our mail into an email
<p> by hand, but <i>ain't nobody got time for that!</i>. The (more appealing)
Whether it's to re-read a conversation, find a plane ticket I ordered or alternative is to use a document scanner. I have a single purpose scanner
check when a meeting was planned, I often find myself looking up old unit from Canon that I hook up to my laptop for just this purpose.
emails. It's usually easy to do so because email clients are designed for </p>
the task: Many of them support full-text search and some even complement
that with neat tagging and categorization systems. To be honest I have
become completely dependent on those features for my day to day
life. Having full-text search and some sort of categorization for email
can be a huge time saver. When it comes to physical mail however, I still
have to browse through stacks of paper to (hopefully) find what I'm
looking for. I figured that it'd be nice to use my fancy email client to
deal with physical mail as well, so I found a way to do just that. Turns
out it's pretty simple!
</p>
<p> <p>
The main objective here is to transform our physical mail into an email It isn't as simple as just emailing a scanned document to ourselves
that can be received, indexed and read by our email client of choice. Now, though: email clients are smart, but they can't understand a word of text
one way to do that would be to type the contents of our mail into an email in our PDF or JPEG of a physical document. They need content to be in
by hand, but <i>ain't nobody got time for that!</i>. The (more appealing) plain text form in order to provide us with some of their best features
alternative is to use a document scanner. I have a single purpose scanner like full-text search. We'll have to somehow transform our scanned
unit from Canon that I hook up to my laptop for just this purpose. documents into plain text that we can include in our email. To do this, we
</p> can use tesseract. Tesseract is an optical character recognition (OCR)
engine, meaning that it can recognize text in images and extract it for
us. Installing it should be easy on Debian derivative distros like
Ubuntu. My laptop is running Debian unstable so I just ran <code class="nowrap">apt
install tesseract</code> and started using it. Using it is as easy as
upening up a terminal and typing <code class="nowrap">tesseract FILE.jpg
OUTPUT</code>. That command will save all the text that tesseract is able
to recognize in the image FILE.jpg to a file called OUTPUT.txt.
</p>
<p> <aside>
It isn't as simple as just emailing a scanned document to ourselves <i>
though: email clients are smart, but they can't understand a word of text Side note: I am Dutch, so most of my physical mail is in Dutch. To
in our PDF or JPEG of a physical document. They need content to be in make tesseract better understand my mail I installed the
plain text form in order to provide us with some of their best features tesseract-ocr-nld package using <code>apt install
like full-text search. We'll have to somehow transform our scanned tesseract-ocr-nld</code>. You can check what other language packs are
documents into plain text that we can include in our email. To do this, we available by using <code>apt search tesseract-ocr</code>.
can use tesseract. Tesseract is an optical character recognition (OCR) </i>
engine, meaning that it can recognize text in images and extract it for </aside>
us. Installing it should be easy on Debian derivative distros like
Ubuntu. My laptop is running Debian unstable so I just ran <code>apt
install tesseract</code> and started using it. Using it is as easy as
upening up a terminal and typing <code>tesseract FILE.jpg
OUTPUT</code>. That command will save all the text that tesseract is able
to recognize in the image FILE.jpg to a file called OUTPUT.txt.
</p>
<aside> <p>
<i> All we have to do from there is copy-paste the contents of that file into
Side note: I am Dutch, so most of my physical mail is in Dutch. To an email and send it to ourselves! Depending on the formatting of the
make tesseract better understand my mail I installed the input document, the output may not always be pleasant to read. We can
tesseract-ocr-nld package using <code>apt install account for this by including the original document as an attachment to
tesseract-ocr-nld</code>. You can check what other language packs are the email. That way we get the best of both worlds: we can use the search
available by using <code>apt search tesseract-ocr</code>. functionality of our email client to find the document, and then read it
</i> in its original form by opening the attachment.
</aside> </p>
<p> <p>
All we have to do from there is copy-paste the contents of that file into This is all easy enough, but I'm lazy. I didn't feel like opening up my
an email and send it to ourselves! Depending on the formatting of the email client and doing manual copy-pasting, so I decided to automate the
input document, the output may not always be pleasant to read. We can process a little further. I have postfix setup on my system to relay to my
account for this by including the original document as an attachment to mail server, so I can simply use the <code>mail</code> command to send
the email. That way we get the best of both worlds: we can use the search emails without a GUI mail client. I combined that with tesseract in a
functionality of our email client to find the document, and then read it little bash script. The script iterates through all of its arguments and
in its original form by opening the attachment. interprets them as filenames of scanned documents. It calls tesseract to
</p> extract text from them, concatenates the results, attaches the files to an
email and sends it to my personal email address. Now all I have to do is
<p> run the script with filenames of some documents and my job is done. If
This is all easy enough, but I'm lazy. I didn't feel like opening up my anyone is interested in an actual program that does the same thing and
email client and doing manual copy-pasting, so I decided to automate the doesn't require you to setup postfix, let me know! I might consider
process a little further. I have postfix setup on my system to relay to my authoring one if it's useful to more people than just myself. The script
mail server, so I can simply use the <code>mail</code> command to send I'm currently using can be found <a href="scan-to-mailpile.bash.html">here
emails without a GUI mail client. I combined that with tesseract in a (pretty)</a> and <a href="scan-to-mailpile.bash">here (raw)</a>, but I
little bash script. The script iterates through all of its arguments and don't recommend using it if you don't fully understand its contents, it's
interprets them as filenames of scanned documents. It calls tesseract to not a polished user experience 🤓.
extract text from them, concatenates the results, attaches the files to an </p>
email and sends it to my personal email address. Now all I have to do is
run the script with filenames of some documents and my job is done. If
anyone is interested in an actual program that does the same thing and
doesn't require you to setup postfix, let me know! I might consider
authoring one if it's useful to more people than just myself. The script
I'm currently using can be found <a href="scan-to-mailpile.bash.html">here
(pretty)</a> and <a href="scan-to-mailpile.bash">here (raw)</a>, but I
don't recommend using it if you don't fully understand its contents, it's
not a polished user experience 🤓.
</p>
</article>
</body>
</html>
<!-- Local Variables: --> <!-- Local Variables: -->
<!-- sgml-basic-offset: 1 --> <!-- sgml-basic-offset: 1 -->

@ -1,3 +1,5 @@
@import "assets/hack.css";
a:visited { a:visited {
color: #c2e; color: #c2e;
} }
@ -17,36 +19,70 @@ body {
margin: auto; margin: auto;
} }
pre {
white-space: pre-wrap;
}
body {
font-size: 18px;
}
aside { aside {
width: 30%; width: inherit;
min-width: 10em;
background-color: rgba(0,0,0, 0.1);
float: right;
padding: 1em;
margin: 1em;
} }
pre { .publish-date {
white-space: pre-wrap; font-size: 14px;
} }
@media only all and (pointer: coarse), (pointer: none) { code {
font-family: Hack, monospace;
background-color: rgba(0,0,0, 0.05);
}
.nowrap {
white-space: nowrap;
}
@media only all and (min-width: 640px) {
body { body {
font-size: 5.5vmin; line-height: 1.4;
font-size: 16px;
max-width: 80ch;
} }
aside { .publish-date {
width: inherit; font-size: 12px;
} }
}
body { aside {
line-height: 1.4; width: 30%;
min-width: 10em;
background-color: rgba(0,0,0, 0.1);
float: right;
padding: 1em;
margin: 1em;
}
} }
@media only all and (pointer: fine) { @media only all and (min-width: 1920px) {
body { body {
font-size: calc(14px + 0.6vmin); line-height: 1.4;
font-size: calc(14px + 0.2vmax);
max-width: 80ch; max-width: 80ch;
} }
.publish-date {
font-size: calc(10px + 0.2vmax);
}
aside {
width: 30%;
min-width: 10em;
background-color: rgba(0,0,0, 0.1);
float: right;
padding: 1em;
margin: 1em;
}
} }

Loading…
Cancel
Save