Table of Content:
Hope lies within you, and only you.
I'm not even done setting up my blog while writing this and that's exactly why it's the perfect time to write. If you haven't read my post about HTML, I concluded that HTML5 was to be used instead of anything else. HOWEVER, when it comes to the automatic generation of a page, I can't help but choose XHTML in that regard. Well XHTML5 that is. I made the realization while coding my sitemap generator. It's a python script – I haven't coded in python in forever and made many mistakes. The good news was my terminal would tell me If and Where I had made a mistake. So in case the script was fine but not the generated page, I wanted the same type of error handling. The XML parser was then the only logical tool to use. Granted it's a bit overkill for such a small project, It's still a good habit to have.
There, I finally found a real use case for XHTML – and I wanted more.
Hugo
My blog is autogenerated by Hugo as I grew tired of reading through my tag soup in HTML. Hugo generates blog pages from Markdown files; it's much easier to code and read so it became an elegant choice. The problem with Hugo is that there are no good themes for it. I mean… Reading layouts? Having to adapt to someone else's logic? When Hugo is extremely well documented and in fact quite easy to use?
So started the creation of my own theme.
XHTML
I like to think that my machines are very very dumb. When generating HTML from a program, I want it perfectly errorless, that means XHTML. Hugo does not natively support XHTML but custom MIME types can be configured1. That was my first objective and so changed my config.toml file:
[outputFormats]
[outputFormats.xhtml]
baseName = 'index'
isHTML = true
mediaType = 'application/xhtml+xml'
[mediaTypes]
[mediaTypes.'application/xhtml+xml']
suffixes = ['xhtml']
Then I needed to change the extension of hugo's output like so:
[outputs]
home = ['xhtml', 'rss']
page = ['xhtml']
rss = ['rss']
section = ['xhtml']
taxonomy = ['xhtml']
term = ['xhtml']
Ok great, Hugo crashes now.
Markup Handler
The default markup handler is Goldmark2. It's very handy because it has an XHTML setting that if set to true will close Null End Tags and nest other tags properly. However, Goldmark's typographer isn't compatible with XHTML by default in Hugo, luckily we can configure it. XHTML cannot parse named HTML entities such as … or «, so in the configs I had to replace those entities with their decimal counterparts:
[markup]
defaultMarkdownHandler = 'goldmark'
[markup.goldmark.parser.attribute]
block = false
title = true
[markup.goldmark.renderer]
hardWraps = false
unsafe = false
xhtml = true
[markup.goldmark.extensions.typographer]
apostrophe = '''
disable = false
ellipsis = '…'
emDash = '—'
enDash = '–'
leftAngleQuote = '‹'
leftDoubleQuote = '“'
leftSingleQuote = '‘'
rightAngleQuote = '›'
rightDoubleQuote = '”'
rightSingleQuote = '’'
If ‘unsafe’ is set to true, it allows raw HTML to be written in your markdown pages. I feared it would break at some point with XHTML so I limited myself to raw Markdown.
HTML
Once I was sure my layout would parse nicely, I always planned on making an HTML version of the theme so I could minify it. In fact Hugo can do that for me3:
[minify]
minifyOutput = true
[minify.tdewolff]
[minify.tdewolff.css]
keepCSS2 = false
[minify.tdewolff.html]
keepEndTags = false
‘keepCSS2’ is set to false because most of us use CSS3 anyway and don't pay much attention to coding backwards compatible CSS. Unless you do, you can set it to true yourself.
The layout itself
Classic summary, read more etc… I mean, you can just browse the site and see for yourself. Or you can check the source code. Make sure you know all about the Hugo variables first.4
Here's a list of features:
- Shows a Recent posts list with their summary and word counts.
- Same for a specific tag page, shows the latest three posts with summary, then a full list of every posts.
- Makes one RSS feed for the entire site at
/index.xml
. nextprev.html
adds links to the Next and Previous articles to the bottom of a page.taglist.html
links all tags an article is tagged to for related content.- XHTML MIME type added.
- Goldmark support for XHTML implemented.
- If you prefer HTML, minify options are implemented as well.
Sitemap.html
generates a sitemap for users.- Toggleable Site subtitle + per page subtitles.
It's pretty basic, if you read the code you'll see a bunch of if statements YandereDev5 style but hey, it doesn't bloat the output so whatever.
More on sitemap.html
There's probably a better way to do this but at least it works with a few janky workarounds:
To generate some other type of static page, you need to create new layouts in a 'types’ folder of any name (/else/ in my theme).6
My sitemap layout is used like the default layout aka everything else; it formats Markdown files.
Therefore A sitemap.md file must be created by the user (you) and must be configured to use the sitemap layout. The top of the file should look like so:
+++
slug = 'sm'
layout = 'sitemap'
title = 'Sitemap'
type = 'else'
+++
Do NOT add content to the sitemap page, the sitemap is split in two sections: “Pages” and “Blog Entries”. To achieve this, the site checks whether a page has content or not. Since I strictly write content in my blog posts I decided to keep it simple for myself.
It is IMPERATIVE that the sitemap has the exact title “Sitemap” with a capital S. To hide the sitemap from the list of blog posts I simply added an if statement to exclude its name, and that name is “Sitemap”.
It must have a slug set to “sm” as it is the referer used in the header menu, otherwise our sitemap would be in /sitemap/ and would conflict with Hugo's sitemap generation7.
Hugo generates another type of sitemap for us, it's an XML file you give to search engines for indexation. So ideally you want both sitemaps.
Without content and with the right name, the sitemap page may rightly be listed within itself. The sitemap that is.
The <main>
has a “sitemap” id so you can edit CSS easily.
Otherwise you can disable the sitemap thing altogether in your hugo.toml file. This theme's config.toml includes variables you can copy to do so.
Here they are:
title = "Website Name" #name of your site
baseURL = 'https://example.org'
languageCode = 'en-us'
copyright = 'Made with Cleogo' #displayed in the footer
[params]
# copyright href
cphref = "https://github.com/Cleomancy/cleogo/"
favicon = "/favicon.ico"
# toggle menu and or just parts of it.
menu = true
tags = true
sitemap = false
categories = true
[markup]
defaultMarkdownHandler = 'goldmark'
[markup.goldmark.parser.attribute]
block = false
title = true
[markup.goldmark.renderer]
hardWraps = false
unsafe = false
xhtml = false
[markup.goldmark.extensions.typographer]
apostrophe = '''
disable = false
ellipsis = '…'
emDash = '—'
enDash = '–'
leftAngleQuote = '‹'
leftDoubleQuote = '“'
leftSingleQuote = '‘'
rightAngleQuote = '›'
rightDoubleQuote = '”'
rightSingleQuote = '’'
[outputFormats]
[outputFormats.xhtml]
baseName = 'index'
isHTML = true
mediaType = 'application/xhtml+xml'
[mediaTypes]
[mediaTypes.'application/xhtml+xml']
suffixes = ['xhtml']
[outputs]
home = ['html', 'rss']
page = ['html']
rss = ['rss']
section = ['html']
taxonomy = ['html']
term = ['html']
[minify]
minifyOutput = false
[minify.tdewolff]
[minify.tdewolff.css]
keepCSS2 = false
[minify.tdewolff.html]
keepEndTags = false
That's all. Thank you.
Technical