<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.6">Jekyll</generator><link href="https://blog.nicholasnooney.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.nicholasnooney.com/" rel="alternate" type="text/html" /><updated>2021-08-03T05:50:48+00:00</updated><id>https://blog.nicholasnooney.com/feed.xml</id><title type="html">Nicholas Nooney’s Blog</title><subtitle>A Collection of Ideas and Writings
</subtitle><author><name>Nicholas Nooney</name></author><entry><title type="html">Improving Navigation</title><link href="https://blog.nicholasnooney.com/web/improving-navigation.html" rel="alternate" type="text/html" title="Improving Navigation" /><published>2019-05-21T17:23:52+00:00</published><updated>2019-05-21T17:23:52+00:00</updated><id>https://blog.nicholasnooney.com/web/improving-navigation</id><content type="html" xml:base="https://blog.nicholasnooney.com/web/improving-navigation.html">&lt;p&gt;The original menu on the front page was lacking. It only contained a list of the
categories of each post I’ve written. However, after adding support for series
of posts, I think it would be nice to show the series’ titles in the menu as
well. This required making a custom plugin &lt;code class=&quot;highlighter-rouge&quot;&gt;jekyll-groupby&lt;/code&gt; and the creation of
a new layout called &lt;code class=&quot;highlighter-rouge&quot;&gt;group&lt;/code&gt; to display groups of items. The result of the code
in this post leads to the menu on the sidebar.&lt;/p&gt;

&lt;!-- excerpt separator --&gt;

&lt;p&gt;Eariler in the development of this site, I added support for a series of posts,
which allowed me to provide controls to navigate from post to post within a
series. However, I still lacked a way to see all of the posts that belong to a
series in a readable manner. I also cannot view all the posts belonging to a
category or tag (which we’ll see later is similar to viewing all of the posts
in a series).&lt;/p&gt;

&lt;p&gt;I’ve also never worked with plugins to modify content in Jekyll static sites.
The &lt;a href=&quot;https://jekyllrb.com/docs/plugins/&quot;&gt;documentation&lt;/a&gt; contains several examples of what can be done with
plugins, including generating content (which will be used here to create landing
pages for each of the series, categories, and tags). The result of this post is
the plugin &lt;code class=&quot;highlighter-rouge&quot;&gt;jekyll-groupby&lt;/code&gt;, which allows for dynamic configuration of groups of
posts.&lt;/p&gt;

&lt;p&gt;Since I have never programmed in Ruby before, I based my plugin off of the
existing plugin &lt;a href=&quot;https://github.com/jekyll/jekyll-archives&quot;&gt;jekyll-archives&lt;/a&gt;. This plugin allows for creation of achives
by date, tag, and category. The plugin itself consists of two parts: a custom
page class to store information pertaining to the generated page, and a custom
generator used to construct a page and populate it with content from the site’s
data. My plugin will also use this structure.&lt;/p&gt;

&lt;h1 id=&quot;implementing-the-plugin&quot;&gt;Implementing the Plugin&lt;/h1&gt;

&lt;p&gt;The plugin is implemented as a single Ruby source file and placed in the
&lt;code class=&quot;highlighter-rouge&quot;&gt;_plugins&lt;/code&gt; directory in the website’s source tree. I found this to be the
easiest method (other methods supported by Jekyll require the plugin to be
installed as a Ruby gem).&lt;/p&gt;

&lt;p&gt;The Jekyll documentation describes that a Generator must define a function
&lt;code class=&quot;highlighter-rouge&quot;&gt;generate&lt;/code&gt; that is provided an instance of the site. By modifying the variable
&lt;code class=&quot;highlighter-rouge&quot;&gt;site.pages&lt;/code&gt;, it is possible to generate any new content for a site. The page
can use Jekyll’s existing layout system to create the layout; this plugin needs
to provide details about the posts that belong to a particular series or
category or tag.&lt;/p&gt;

&lt;p&gt;To begin this plugin, I want to look at the configuration used in &lt;code class=&quot;highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt;.
A look at the configuration describes the settings I’ve arrived at and need to
implement.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;jekyll-groupby&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;permalink&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;:group/:name.html&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;groups&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;series&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;group&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;category&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;group&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;tags&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;group&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The top-level key is the name of the plugin. This is a common theme when using
plugins so that a &lt;code class=&quot;highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt; file can organize all of it’s settings. Inside
this hash are two keys &lt;code class=&quot;highlighter-rouge&quot;&gt;permalink&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;groups&lt;/code&gt;. The &lt;code class=&quot;highlighter-rouge&quot;&gt;permalink&lt;/code&gt; describes how
to format the URLs for this generated page. It uses the placeholders &lt;code class=&quot;highlighter-rouge&quot;&gt;:group&lt;/code&gt;,
which is the name of the group (“series”, “category”, “tag”), and &lt;code class=&quot;highlighter-rouge&quot;&gt;:name&lt;/code&gt;, which
is the name of an item in the group (“code” or “web” for the group “category”).
The &lt;code class=&quot;highlighter-rouge&quot;&gt;groups&lt;/code&gt; key is an array of objects that provide the name of each group and
the layout used to format the group page. The site currently uses three groups,
each with the same layout &lt;code class=&quot;highlighter-rouge&quot;&gt;group&lt;/code&gt; (which is shown later).&lt;/p&gt;

&lt;p&gt;The structure of this config can provide context for implementing the generator.
What we need to do is loop over each object in &lt;code class=&quot;highlighter-rouge&quot;&gt;groups&lt;/code&gt;, and for each object,
find the posts that use that group and divide them into lists by group. This is
best shown with an example; we’ll use this set of posts (available via
&lt;code class=&quot;highlighter-rouge&quot;&gt;site.posts&lt;/code&gt; as an example for the plugin):&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;#&lt;/th&gt;
      &lt;th&gt;post&lt;/th&gt;
      &lt;th&gt;category&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;C++ overview&lt;/td&gt;
      &lt;td&gt;code&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;Chrome vs Firefox&lt;/td&gt;
      &lt;td&gt;web&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;Python 2 and 3&lt;/td&gt;
      &lt;td&gt;code&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;Javascript&lt;/td&gt;
      &lt;td&gt;code, web&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;WebSockets&lt;/td&gt;
      &lt;td&gt;web&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The groupby page will generate pages for each category, and each page will show
a list of posts with the matching category. The plugin will use a Generator and
Page in order to create the category pages. With the example site above, there
are 2 generated pages: &lt;code class=&quot;highlighter-rouge&quot;&gt;/category/code&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;/category/web&lt;/code&gt;. Each page will
contain a list of posts belonging to that category, accessible via the variable
&lt;code class=&quot;highlighter-rouge&quot;&gt;page.posts&lt;/code&gt;. This is the reason we need a custom Page class instead of using
Jekyll’s default Page class; with our custom class, we can provide any of the
data that we want to provide for rendering with liquid templates.&lt;/p&gt;

&lt;h1 id=&quot;the-page-class&quot;&gt;The Page Class&lt;/h1&gt;

&lt;p&gt;Below is the source for the Page class.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Jekyll&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Groupby&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GroupbyPage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Page&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:slug&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:config&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# Attributes for Liquid templates. Every member in this array is&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# accessible to use in the layout file for the rendered page.&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;ATTRIBUTES_FOR_LIQUID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%w(
        posts
        group
        title
        slug
        name
        path
        url
        permalink
        config
      )&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;freeze&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# Initialize a new Groupby Page. Here we setup all the member variables&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# of the page so that it can be accessed and processed by Jekyll.&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# site - The Site object.&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# title - The value of the key being grouped.&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# config - The specific configuration for this page&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# posts - The array of posts in this group.&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@site&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@posts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;posts&lt;/span&gt;

        &lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;debug&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Page:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; ... &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Generate slug for the title&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@slug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Utils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slugify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Store a reference to liquid variables.&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@layout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;layout&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Save the generated file information&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@ext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;relative_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;relative_path&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;basename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;relative_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@ext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;vi&quot;&gt;@data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;layout&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;permalink&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;permalink&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;url&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
            &lt;span class=&quot;ss&quot;&gt;:template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;jekyll-groupby&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;permalink&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;ss&quot;&gt;:placeholders&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@slug&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
            &lt;span class=&quot;ss&quot;&gt;:permalink&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ArgumentError&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ArgumentError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Template provided is invalid.&quot;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;relative_path&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unescape_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%r!^&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\/&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;#&amp;lt;Jekyll:GroupbyPage @path=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;gt;&quot;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The class itself is scoped within a special namespace to avoid collisions with
other Ruby code that runs during the generation process. The most important
function is the &lt;code class=&quot;highlighter-rouge&quot;&gt;initialize&lt;/code&gt; function. It accepts the title (item in a group,
such as “code” and “web”), config (the object with “name” and “layout”), and
a list of posts belonging to that category. All of the other functions provide
variables that can be used to access data in the page when it is time to render
it.&lt;/p&gt;

&lt;h1 id=&quot;the-generator-class&quot;&gt;The Generator Class&lt;/h1&gt;

&lt;p&gt;Below is the source for the generator class.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Jekyll&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Groupby&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Groupby&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Generator&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;safe&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;

      &lt;span class=&quot;no&quot;&gt;DEFAULTS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;permalink&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;:group/:name.html&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;groups&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;freeze&lt;/span&gt;

      &lt;span class=&quot;no&quot;&gt;GROUP_DEFAULTS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;layout&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;multiple&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;freeze&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Utils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deep_merge_hashes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DEFAULTS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;jekyll-groupby&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}))&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# The provided generate method performs 3 steps:&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;#   1. It processes each groupby archive&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;#   2. It resolves the configuration settings&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;#   3. It stores each groupby archive as a new page and in site.config.&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;generate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@site&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@posts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;posts&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@group_pages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

        &lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;info&lt;/span&gt;  &lt;span class=&quot;s2&quot;&gt;&quot;Jekyll Groupby:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Generating group pages&quot;&lt;/span&gt;
        &lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;debug&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Jekyll Groupby:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Begin Generation...&quot;&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Ensure expected config variables are present&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;jekyll-groupby&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@config&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# 1. Process all of the posts; this function will populate the&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# group_pages array and update the configuration.&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# 2. Save the updated config to the site's config.&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;jekyll-groupby&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@config&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# 3. Add all of the group_pages to the site's pages so that they get&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# rendered by later stages in the Jekyll pipeline.&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@group_pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;debug&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Jekyll Groupby:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Generation complete!&quot;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# To process each group archive, loop over each value and create a new&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# groupby page from it. Don't do it for groups of posts that do not have&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# the groupby key present.&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;groups&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
          &lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;debug&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Group:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Creating pages for &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&quot;&lt;/span&gt;

          &lt;span class=&quot;c1&quot;&gt;# Ensure the default variables are present in the config at the group&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# level.&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;GROUP_DEFAULTS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

          &lt;span class=&quot;c1&quot;&gt;# Use the groupBy method below to generate a hash where each entry in&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# the hash is a single member for the provided key and the values are&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# an array of posts containing that entry. See the groupBy function&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# below for more details.&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;group_posts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;groupBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

          &lt;span class=&quot;c1&quot;&gt;# Using our hash, convert it to an array in order to support accessing&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# the config from liquid templates and sort the array by the names of&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# each entry. The sorting allows for alphabetical iteration of each&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# group.&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;posts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group_posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;list&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

          &lt;span class=&quot;c1&quot;&gt;# For each value in the hash, create a group page.&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;group_posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;posts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
            &lt;span class=&quot;vi&quot;&gt;@group_pages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GroupbyPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# Group each post by the 'key' argument. The key is the name of a front-&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# matter variable used to define a grouping. This will create an array of&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# posts with one entry for each value of the attribute encountered. Each&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# entry looks like this:&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;#   {value: [Array of posts with that value]}&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# For example, if there were three posts, A1, A2, and S1 belonging to the&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# &quot;series&quot; A and S respectively, this function would produce the following&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# output given the key &quot;series&quot;:&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;#   { &quot;A&quot;: [A1, A2], &quot;S&quot;: [S1] }&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# If there is a post P that does not have the &quot;series&quot; front-matter, then&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# it will not be included in the output hash.&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;groupBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# What's happening here is we are accessing all posts. It turns out that&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# the Jekyll variable site.posts returns a Collection object containing&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# all posts in the site. We access the documents array of all the posts&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# because we need to access the front matter in order to determine which&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# key in the hash the post belongs to. We then filter the documents to&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# only those which contain the given key in the front-matter.&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;filtered_posts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;docs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;key?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Next we create a hash and add the post to each bucket in the hash with&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# the given value. If a post has multiple values for the key, then it&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# will end up in multiple buckets in the hash. This may be the case when&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# grouping by tags.&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@hash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;filtered_posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;pval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

          &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil?&lt;/span&gt;
            &lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;debug&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Post:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; !!! Skipping &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;next&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;pval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;addToHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;addToHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Finally, return the hash that was created.&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@hash&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# This helper method preserves the format of the hash, namely, that each&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# value is an array. When a new item is added, it is added to the array,&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# or a new array is created if the key does not yet exist in the hash.&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addToHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;has_key?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;vi&quot;&gt;@hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

        &lt;span class=&quot;vi&quot;&gt;@hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The Generator peforms the following actions (beginning with the &lt;code class=&quot;highlighter-rouge&quot;&gt;generate&lt;/code&gt;
function): Grab the configuration from &lt;code class=&quot;highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt;, organize &lt;code class=&quot;highlighter-rouge&quot;&gt;site.posts&lt;/code&gt; by
category and return a dictionary of posts for each category, then loop through
the dictionary and create a Page for each category. After all the pages are
generated, they are added to &lt;code class=&quot;highlighter-rouge&quot;&gt;site.pages&lt;/code&gt; so that they appear in the final
output.&lt;/p&gt;

&lt;h1 id=&quot;the-group-layout&quot;&gt;The Group Layout&lt;/h1&gt;

&lt;p&gt;Below is the code for the &lt;code class=&quot;highlighter-rouge&quot;&gt;group&lt;/code&gt; layout.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
---
layout: default
---

{% comment %}
This template works closely with the groups used by the plugin jekyll-groupby.
{% endcomment %}

&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;title is-2 has-text-info&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    {{ page.title }}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;subtitle is-6&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    {% assign num_posts = page.posts | size %}
    {{ num_posts }}
    {% if num_posts &amp;gt; 1 %}
        posts
    {% else %}
        post
    {% endif %}
    {% if site.data[page.group].matchline %}
        {{ site.data[page.group].matchline }}
    {% else %}
        in this {{ page.group }}
    {% endif %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

{% assign group_data = site.data[page.group].items | where: &quot;name&quot;, page.slug
    | first %}
{% if group_data %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    {{ group_data.content }}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;hr&amp;gt;&lt;/span&gt;
{% endif %}

&lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;posts-group&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    {% for post in page.posts %}
        {% include components/post-snippet.html post=post %}

        {% if forloop.last == false %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;hr&amp;gt;&lt;/span&gt;
        {% endif %}
    {% endfor %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The layout uses &lt;code class=&quot;highlighter-rouge&quot;&gt;page.posts&lt;/code&gt; to display an excerpt of each post in the category
via the component &lt;code class=&quot;highlighter-rouge&quot;&gt;post-snippet&lt;/code&gt;, which was created previously for the front
page. The large amount of liquid templates provide the correct verbiage for
the page materials. Some of it is also customizable via YAML &lt;a href=&quot;https://jekyllrb.com/docs/datafiles/&quot;&gt;data files&lt;/a&gt;.
Specifically, a paragraph can be added to describe the group and the subtitle
can be customized via the variable &lt;code class=&quot;highlighter-rouge&quot;&gt;matchline&lt;/code&gt;. Here is an example of the data
used to customize a &lt;code class=&quot;highlighter-rouge&quot;&gt;series&lt;/code&gt; page on my site (in the file &lt;code class=&quot;highlighter-rouge&quot;&gt;_data/series.yml&lt;/code&gt;).&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;matchline&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;series&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;developing-a-custom-theme&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;This series of posts details the process I completed to design the theme&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;for this site. I began exploring how gem-based themes work and build a&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;working theme that contains feature-parity with Minima, Jekyll's default&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;theme. I then move on to add more advanced content, including supporting a&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;series of posts, adding Code Syntax Highlighting, and other features to&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;complement the theme of this site. As I update the theme, I will add more&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;posts to this series. You can always grab the latest copy of this theme's&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;code at GitHub.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;wrapping-it-up&quot;&gt;Wrapping It Up&lt;/h1&gt;

&lt;p&gt;With this flexible system, I can display any related group of posts on a single
page. This greatly improves discoverability and allows for viewing the bigger
picture of related content on my site.&lt;/p&gt;</content><author><name>Nicholas Nooney</name></author><category term="web" /><category term="jekyll-theme" /><category term="this-site" /><summary type="html">The original menu on the front page was lacking. It only contained a list of the categories of each post I’ve written. However, after adding support for series of posts, I think it would be nice to show the series’ titles in the menu as well. This required making a custom plugin jekyll-groupby and the creation of a new layout called group to display groups of items. The result of the code in this post leads to the menu on the sidebar.</summary></entry><entry><title type="html">Cambre: An exploration into RAII</title><link href="https://blog.nicholasnooney.com/code/cambre-an-exploration-into-raii.html" rel="alternate" type="text/html" title="Cambre: An exploration into RAII" /><published>2019-04-30T00:57:22+00:00</published><updated>2019-04-30T00:57:22+00:00</updated><id>https://blog.nicholasnooney.com/code/cambre-an-exploration-into-raii</id><content type="html" xml:base="https://blog.nicholasnooney.com/code/cambre-an-exploration-into-raii.html">&lt;p&gt;In the previous introduction to Cambre, I mentioned that I would be using
&lt;code class=&quot;highlighter-rouge&quot;&gt;GLFW&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;GLEW&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;GLM&lt;/code&gt; for handling different aspects of the program. These
libraries are great, but I would also like to use a recent C++ version to
organize the code I write. Because the three aforementioned libraries are all
C style libraries, that means that I have to do a little bit of extra wrangling
in order to make them fit my application’s organization.&lt;/p&gt;

&lt;!-- excerpt separator --&gt;

&lt;p&gt;Every program begins with a &lt;code class=&quot;highlighter-rouge&quot;&gt;main&lt;/code&gt; function, so let’s get started there:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Great! We have a program that we can run. It is even more basic than a “Hello,
World!” program, but it does work. Next we need to initialize the libraries in
order to make use of them throughout our application. Let’s expand &lt;code class=&quot;highlighter-rouge&quot;&gt;main&lt;/code&gt; to
create the libraries.&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;iostream&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;GL/glew.h&amp;gt;
#include &amp;lt;GLFW/glfw3.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glfwInit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;GLFW Initialization Failure&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;GLFWwindow&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;glfwCreateWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;800&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;800&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Cambre&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;GLFW Window Creation Failure&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;glfwMakeContextCurrent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GLEW_OK&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;glewInit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;GLEW Initialization Failure&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glfwWindowShouldClose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glfwPollEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is the basics of creating a window with &lt;code class=&quot;highlighter-rouge&quot;&gt;GLFW&lt;/code&gt; and initializing &lt;code class=&quot;highlighter-rouge&quot;&gt;GLEW&lt;/code&gt;. It
is a bit of extra work to get this to compile; another post in this series will
detail the build system that is used to compile the final executable. This post
refers just to the code required to build the program. If you are unsure about
what is happening here, the best place to find out is the
&lt;a href=&quot;https://www.glfw.org/documentation.html&quot;&gt;GLFW documentation&lt;/a&gt;. The &lt;a href=&quot;http://glew.sourceforge.net/basic.html&quot;&gt;GLEW documentation&lt;/a&gt; explains
how to get started with the GLEW library.&lt;/p&gt;

&lt;p&gt;But wait just one second. This code isn’t neatly wrapped inside the paradigm of
C++ and object oriented design. What can we do to make that work? The key is to
place this code inside of the constructor so that when we create an instance of
that object, the code is initialized for us. There is a caveat in this approach,
however. Because we are moving the code here to the constructor of an object, we
may end up in a situation where the code is executed multiple times. Depending
on the external calls, this may or may not be the desired behavior. If the code
supports being called multiple times, then it is said to be reentrant. If it is
not, then we need to introduce another pattern in order to ensure the code is
executed only once.&lt;/p&gt;

&lt;p&gt;In order to place this code into a constructor, we need to create a class that
will hold the code. Let’s call it &lt;code class=&quot;highlighter-rouge&quot;&gt;Application&lt;/code&gt;. Here is the defintion of the
class:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#ifndef _CAMBRE_APPLICATION_H_
#define _CAMBRE_APPLICATION_H_
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;GL/glew.h&amp;gt;
#include &amp;lt;GLFW/glfw3.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Application&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;Application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;private:&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;GLFWwindow&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mpWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There’s not too much to it! We provide a constructor and destructor, and a &lt;code class=&quot;highlighter-rouge&quot;&gt;run&lt;/code&gt;
function. This will be the entrypoint into the while loop of the code above. It
makes sense to split these because the step of initialization should be separate
from the step of running the program. Below are the implementations of each
method.&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;iostream&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &quot;Application.hpp&quot;
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Application&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glfwInit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;GLFW Initialization Failure&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;mpWindow&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;glfwCreateWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;800&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;800&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Cambre&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mpWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;GLFW Window Creation Failure&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;glfwMakeContextCurrent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mpWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GLEW_OK&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;glewInit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;GLEW Initialization Failure&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For the constructor, we copied the code in the main function above, replacing
the local function variable &lt;code class=&quot;highlighter-rouge&quot;&gt;window&lt;/code&gt; with the class member &lt;code class=&quot;highlighter-rouge&quot;&gt;mpWindow&lt;/code&gt;. This
allows us to keep a reference to the window as the object is used. Also notice
that we can no longer return an error code from the constructor in the event of
a failure. To do this, we need to come up with some other mechanism for
preventing the code from continuing to construct an Application if an error
occurs. That mechanism will be described in a later post.&lt;/p&gt;

&lt;p&gt;Now let’s move onto the &lt;code class=&quot;highlighter-rouge&quot;&gt;run&lt;/code&gt; method.&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Application&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glfwWindowShouldClose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mpWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glfwPollEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;run&lt;/code&gt; method for now contains the loop that will be executed over and over
while the application is still running. We will eventually expand upon this to
include all of the game’s logic and functionality.&lt;/p&gt;

&lt;p&gt;We’ve covered all of the code from the previous &lt;code class=&quot;highlighter-rouge&quot;&gt;main&lt;/code&gt; function, but we still
have the destructor to write! Actually, it is a good idea to clean up the window
once we are done with it, which we didn’t do before. That’s a good fit for the
destructor of this class; whenever an &lt;code class=&quot;highlighter-rouge&quot;&gt;Application&lt;/code&gt; object goes out of scope,
its destructor is called, automatically cleaning up the window’s memory.&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Application&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;glfwDestroyWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mpWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;glfwTerminate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With all of the logic moved outside of our &lt;code class=&quot;highlighter-rouge&quot;&gt;main&lt;/code&gt; function, it becomes very
simple to run the program! All we need to do is create an &lt;code class=&quot;highlighter-rouge&quot;&gt;Application&lt;/code&gt; object
and call its &lt;code class=&quot;highlighter-rouge&quot;&gt;run&lt;/code&gt; method. Once the &lt;code class=&quot;highlighter-rouge&quot;&gt;main&lt;/code&gt; function exits, the resources used
by the &lt;code class=&quot;highlighter-rouge&quot;&gt;Application&lt;/code&gt; object will automatically be cleaned up via the destructor.&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &quot;Application.hpp&quot;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Application&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Voila! This is the beauty of RAII, or “Resource Acquisition is Initialization”.
By constructing (think initializing) the &lt;code class=&quot;highlighter-rouge&quot;&gt;Application&lt;/code&gt; object, I’ve implicitly
acquired a window to run the program in.&lt;/p&gt;

&lt;p&gt;So what’s next? We still need to figure out how to handle errors in the
constructor of the &lt;code class=&quot;highlighter-rouge&quot;&gt;Application&lt;/code&gt; class, and it would be great to see some stuff
drawn to the window.&lt;/p&gt;</content><author><name>Nicholas Nooney</name></author><category term="code" /><category term="cpp" /><category term="opengl" /><summary type="html">In the previous introduction to Cambre, I mentioned that I would be using GLFW, GLEW, and GLM for handling different aspects of the program. These libraries are great, but I would also like to use a recent C++ version to organize the code I write. Because the three aforementioned libraries are all C style libraries, that means that I have to do a little bit of extra wrangling in order to make them fit my application’s organization.</summary></entry><entry><title type="html">Making Cambre: a voxel-based open-world game</title><link href="https://blog.nicholasnooney.com/code/making-cambre-a-voxel-based-open-world.html" rel="alternate" type="text/html" title="Making Cambre: a voxel-based open-world game" /><published>2019-02-01T18:56:26+00:00</published><updated>2019-02-01T18:56:26+00:00</updated><id>https://blog.nicholasnooney.com/code/making-cambre-a-voxel-based-open-world</id><content type="html" xml:base="https://blog.nicholasnooney.com/code/making-cambre-a-voxel-based-open-world.html">&lt;p&gt;In my day-to-day work, I don’t get to work too much with user-facing code. Such
is the world of embedded programming. So I decided to start a new project to
explore a different aspect of software. I also want to seriously consider the
architecture of this project, so not all of the posts will be directly related
to the implementation of the project. Lastly, I want to have fun making this
project, because otherwise there’s no point.&lt;/p&gt;

&lt;!-- excerpt separator --&gt;

&lt;p&gt;An important reason I write for this site is to share the knowledge that I
gained while doing this project. At the time of writing this, I’m still deciding
upon a system of feedback and updating the content.&lt;/p&gt;

&lt;h1 id=&quot;the-project&quot;&gt;The Project&lt;/h1&gt;

&lt;p&gt;I would like to make a Minecraft-inspired clone. It will be a 3D voxel game
where I can explore an expansive world. I have some ideas that I would like to
try that would distinguish this from Minecraft itself, and I’ll describe those
at the time I develop them.&lt;/p&gt;

&lt;p&gt;I did a project in college working with OpenGL. I know that the OpenGL standard
is being deprecated for the newer Vulkan standard (or if you’re Apple, the Metal
standard), but none of those have a good knowledgebase yet and I don’t want to
deal with that. So I’m going to use OpenGL for the graphics context.&lt;/p&gt;

&lt;h2 id=&quot;a-sidetrack-into-opengl&quot;&gt;A Sidetrack Into OpenGL&lt;/h2&gt;

&lt;p&gt;OpenGL is a API for communications between a Central Processing Unit (CPU) and
a Graphics Processing Unit (GPU). The OpenGL specification does not describe an
implementation; this is because the API is implemented at various levels in
hardware and software. A graphics vendor (Nvidia, Intel, AMD) will create a GPU
and provide a driver to access it. Each graphics vendor provides their own
driver specific calls that don’t necessarily represent the OpenGL API (often
they include proprietary extensions) and application developers don’t want to
provide many different builds of their application for each individual driver.
The role of translating between OpenGL calls and driver-specific calls is
performed by an OpenGL framework.&lt;/p&gt;

&lt;p&gt;OpenGL frameworks are available on different systems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Linux: Provided by the Mesa 3D Graphics Library.&lt;/li&gt;
  &lt;li&gt;MacOS: Provided by Apple’s OpenGL Framework.&lt;/li&gt;
  &lt;li&gt;Windows: Provided by Microsoft in the Windows SDK.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;libraries-and-technologies&quot;&gt;Libraries and Technologies&lt;/h1&gt;

&lt;p&gt;Using OpenGL is a large design decision, but it also represents only a single
facet of this project: Graphics Rendering. I’ll also need to handle user input,
provide audio support, and use a networking library to make it multiplayer. For
now, I’ll decide upon a user-input library (which also handles window creation),
and I’ll decide on the others later.&lt;/p&gt;

&lt;p&gt;In college, we used &lt;code class=&quot;highlighter-rouge&quot;&gt;GLUT&lt;/code&gt; to handle window creation and capturing user Input.
However, in the time since I’ve learned about &lt;code class=&quot;highlighter-rouge&quot;&gt;GLFW&lt;/code&gt;. Both provide the same
functionality: creating a window and allowing me to respond to input; however, I
prefer to use &lt;code class=&quot;highlighter-rouge&quot;&gt;GLFW&lt;/code&gt; because it provides more control over the application
structure than using &lt;code class=&quot;highlighter-rouge&quot;&gt;GLUT&lt;/code&gt;. I can write my own game loop this way.&lt;/p&gt;

&lt;p&gt;I also need an extension-management library so I can make the most out of my
GPU. For this, I’ll use &lt;code class=&quot;highlighter-rouge&quot;&gt;GLEW&lt;/code&gt;. And I want to use a math library for performing
linear algebra operations easily. For that, I’ll use &lt;code class=&quot;highlighter-rouge&quot;&gt;GLM&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This project uses the following libraries:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;GLFW (This library automatically includes Apple’s OpenGL framework).&lt;/li&gt;
  &lt;li&gt;GLEW&lt;/li&gt;
  &lt;li&gt;GLM&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;grab-a-copy&quot;&gt;Grab a Copy&lt;/h1&gt;

&lt;p&gt;If you would like to see the code as it has evolved, check it out on
&lt;a href=&quot;https://github.com/nnooney/cambre&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;</content><author><name>Nicholas Nooney</name></author><category term="code" /><category term="cpp" /><category term="opengl" /><summary type="html">In my day-to-day work, I don’t get to work too much with user-facing code. Such is the world of embedded programming. So I decided to start a new project to explore a different aspect of software. I also want to seriously consider the architecture of this project, so not all of the posts will be directly related to the implementation of the project. Lastly, I want to have fun making this project, because otherwise there’s no point.</summary></entry><entry><title type="html">Using C and C++ Together</title><link href="https://blog.nicholasnooney.com/code/using-c-cpp-together.html" rel="alternate" type="text/html" title="Using C and C++ Together" /><published>2018-09-01T00:00:00+00:00</published><updated>2018-09-01T00:00:00+00:00</updated><id>https://blog.nicholasnooney.com/code/using-c-cpp-together</id><content type="html" xml:base="https://blog.nicholasnooney.com/code/using-c-cpp-together.html">&lt;p&gt;This article describes how to write code that is available in both C and C++.
The &lt;a href=&quot;https://isocpp.org/wiki/faq/mixing-c-and-cpp&quot;&gt;C++ website&lt;/a&gt; has a great FAQ section on how to mix C and C++; this
article shows a concrete example for implementation.&lt;/p&gt;

&lt;!-- excerpt separator --&gt;

&lt;p&gt;The motivation behind this article is that at work we needed a better way to
write unit tests for our code base. Much of the logic was placed into stubbed
functions (we use Parasoft C++Test), which violated the principle of clear,
immediately understandable, test code. Therefore, we made a framework to control
the behavior of our stub functions from the test code itself. As a result, the
stubs became more similar, shorter, easier to understand, and easier to
maintain. This framework can be used to test both C and C++ code.&lt;/p&gt;

&lt;p&gt;In order to succesfully compile a component that can be included and used in
both C and C++ code, the basic structure we found to work well consists of the
following components:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A common header file that all programs include to use the component.&lt;/li&gt;
  &lt;li&gt;A C++ specific header file for the C++ implementation.&lt;/li&gt;
  &lt;li&gt;A C++ implementation of the component.&lt;/li&gt;
  &lt;li&gt;A C specific header file for the C implementation.&lt;/li&gt;
  &lt;li&gt;A C-compatible wrapper for using the component.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let me explain each of these parts in further detail.&lt;/p&gt;

&lt;h1 id=&quot;the-example-component&quot;&gt;The Example Component&lt;/h1&gt;

&lt;p&gt;For the purpose of making this article easier to understand, we’ll implement the
following component:&lt;/p&gt;

&lt;p&gt;A counter module that can be used to count things. It supports the following
interface:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;int counter(void)&lt;/code&gt;: Register a new counter with a count of 0. Returns the id
of the new counter.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;int count(int ctr, int amt)&lt;/code&gt;: Increment &lt;em&gt;ctr&lt;/em&gt; by &lt;em&gt;amt&lt;/em&gt;. Returns the new count
of &lt;em&gt;ctr&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;int reset(int ctr)&lt;/code&gt;: Reset &lt;em&gt;ctr&lt;/em&gt; to 0. Returns the new count of &lt;em&gt;ctr&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice that the specification uses only C-style functions. This is to ensure
that the component can be used in C code.&lt;/p&gt;

&lt;p&gt;The files we’ll create to implement this component will have the following
names:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;counter.h&lt;/code&gt;: The common include header.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;counter_cpp.h&lt;/code&gt;: The C++ header.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;counter_cpp.cpp&lt;/code&gt;: The C++ implementation.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;counter_c.h&lt;/code&gt;: The C header.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;counter_c.cpp&lt;/code&gt;: The C wrapper.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Notice that the C wrapper is compiled with the C++ compiler. This is important
for allowing the wrapper to call the implemented functions.&lt;/p&gt;

&lt;h2 id=&quot;the-common-header&quot;&gt;The Common Header&lt;/h2&gt;

&lt;p&gt;Although not strictly necessary, this common header file makes it easier for
all code to use the component. It makes use of the standard predefined compiler
macro &lt;code class=&quot;highlighter-rouge&quot;&gt;__cplusplus&lt;/code&gt;. This macro is only defined for C++ compilers, which makes
it possible to redirect the code to include the appropriate header.&lt;/p&gt;

&lt;p&gt;The implementation of the counter component would look like this:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// File counter.h&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#ifdef __cplusplus
#include &quot;counter_cpp.h&quot;
#else
#include &quot;counter_c.h&quot;
#endif
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-c-header&quot;&gt;The C++ Header&lt;/h2&gt;

&lt;p&gt;If the component is used as a part of C++ code, then this header will be
included. Here we create the class spec for the counter component.&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// File counter_cpp.h&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;vector&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Counter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;private:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mvCounters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For brevity, I have omitted the constructors and destructor.&lt;/p&gt;

&lt;h2 id=&quot;the-c-implementation&quot;&gt;The C++ Implementation&lt;/h2&gt;

&lt;p&gt;The C++ implementation contains the implementation for each of the functions in
the header. This is standard C++ with nothing fancy happening.&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// File counter_cpp.cpp&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &quot;counter_cpp.h&quot;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;mvCounters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;push_back&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mvCounters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;mvCounters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mvCounters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;mvCounters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mvCounters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Any C++ code can include the header and begin using the implementation of the
counter component. Things get interesting when allowing the C code to access
the members of this class.&lt;/p&gt;

&lt;h2 id=&quot;the-c-header-1&quot;&gt;The C Header&lt;/h2&gt;

&lt;p&gt;The C header defines the interface for C programs to use the component. Since
C++ code normally gets mangled, we use &lt;code class=&quot;highlighter-rouge&quot;&gt;extern &quot;C&quot;&lt;/code&gt; to ensure that the code does
not get mangled and C code can properly resolve the symbols during linking. The
C header also uses a series of wrapper functions, since the class keyword is non
existent.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/* File counter_c.h */&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counter_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counter_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counter_reset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-c-wrapper-implementation&quot;&gt;The C Wrapper Implementation&lt;/h2&gt;

&lt;p&gt;The trick to making this work is that the C wrapper implementation is actually
compiled with a C++ compiler. This allows the C code to use the C++ class
implementation.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// File counter_c.cpp&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &quot;counter_c.h&quot;
#include &quot;counter_cpp.h&quot;
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Counter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gCounterObj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counter_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gCounterObj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counter_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gCounterObj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counter_reset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gCounterObj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The C wrapper forwards each function called by the C code to the C++ object. In
this instance, a global object is used to facilitate access to the C++
implementation, but it could be also implemented by using a pointer to a
&lt;code class=&quot;highlighter-rouge&quot;&gt;Counter&lt;/code&gt; instance and declaring a struct that can be used to pass Counter
objects around in C++ code.&lt;/p&gt;

&lt;h1 id=&quot;wrapup&quot;&gt;Wrapup&lt;/h1&gt;

&lt;p&gt;The ability to commingle C and C++ code has allowed us to avoid writing a
separate implementation of a component for use with a different compiler. This
pattern can be useful to work with different components. It can be extended to
support using many other patterns as well.&lt;/p&gt;</content><author><name>Nicholas Nooney</name></author><category term="code" /><category term="c" /><category term="cpp" /><summary type="html">This article describes how to write code that is available in both C and C++. The C++ website has a great FAQ section on how to mix C and C++; this article shows a concrete example for implementation.</summary></entry><entry><title type="html">Expanding this Site with Images</title><link href="https://blog.nicholasnooney.com/web/expanding-this-site-with-images.html" rel="alternate" type="text/html" title="Expanding this Site with Images" /><published>2018-08-16T01:07:43+00:00</published><updated>2018-08-16T01:07:43+00:00</updated><id>https://blog.nicholasnooney.com/web/expanding-this-site-with-images</id><content type="html" xml:base="https://blog.nicholasnooney.com/web/expanding-this-site-with-images.html">&lt;p&gt;In order to make the site stand out, and also to support media types most
common to the internet, I’ve quickly styled up a featured image container. This
code uses the assets plugin, and results in a simple styled image at the
beginning of each post.&lt;/p&gt;

&lt;!-- excerpt separator --&gt;

&lt;p&gt;The images themselves are inserted via the &lt;a href=&quot;https://github.com/envygeeks/jekyll-assets&quot;&gt;jekyll-assets&lt;/a&gt;
plugin. The snippet of code that renders them using the assets plugin looks
like this:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;featured-image-container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;figure&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;box&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      {% if include.post.featured-image.src %}
      {% asset
          &quot;{{ include.post.featured-image.src }}&quot;
          magick:resize=400x400&amp;gt;
          alt=&quot;{{ include.post.featured-image.alt }}&quot; %}
      {% endif %}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;asset&lt;/code&gt; liquid tag comes courtesy of &lt;code class=&quot;highlighter-rouge&quot;&gt;jekyll-assets&lt;/code&gt;. It allows me to resize
the image via &lt;a href=&quot;https://imagemagick.org/index.php&quot;&gt;ImageMagick&lt;/a&gt; so that the images don’t end up too
large, and it uses the variables in the &lt;code class=&quot;highlighter-rouge&quot;&gt;featured-image&lt;/code&gt; front matter to
determine the source and alt text for the image. I’ve put this code in a
component called &lt;code class=&quot;highlighter-rouge&quot;&gt;featured-image.html&lt;/code&gt;. Any post can include it and provide the
necessary variables to use a featured image. Including the featured image from
a post looks like this:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;---
featured-image:
    src: tahoe.jpg
    alt: &quot;Lake Tahoe&quot;
---

&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    

&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;featured-image-container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;figure&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;box&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Lake Tahoe&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;integrity=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;sha256-rJYE1ALBPyU+XSD7S4P2kJpbQGKIm5HP/wiuGtHPE+s=&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;crossorigin=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;anonymous&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/assets/generated/237d7c-1f15e14edf15d5aad00a59ae64a0df892d82348d6e601f4d72889423413adb1b.jpg&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’ve added this html snippet to the &lt;code class=&quot;highlighter-rouge&quot;&gt;post&lt;/code&gt; layout as well as the &lt;code class=&quot;highlighter-rouge&quot;&gt;post-snippet&lt;/code&gt;
component so that any post can include it for free. It’s also interesting to
note that this is the first template that requires a variable to be passed into
it. By default when processing a post, Jekyll stores all information about the
post, including its front-matter, in the variable called &lt;code class=&quot;highlighter-rouge&quot;&gt;page&lt;/code&gt;. The template
passes the page variable into the component &lt;code class=&quot;highlighter-rouge&quot;&gt;featured-image.html&lt;/code&gt;. All the
variables passed via the &lt;code class=&quot;highlighter-rouge&quot;&gt;include&lt;/code&gt; liquid tag get stored in the variable called
&lt;code class=&quot;highlighter-rouge&quot;&gt;include&lt;/code&gt; (fitting, huh?). That is why the YAML front-matter is referenced as
&lt;code class=&quot;highlighter-rouge&quot;&gt;include.post.featured-image&lt;/code&gt; instead of just &lt;code class=&quot;highlighter-rouge&quot;&gt;post.featured-image&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To get the image just right, I needed to tweak a few CSS properties of Bulma.
The current method I use to organize the styling in this theme is via a main
&lt;code class=&quot;highlighter-rouge&quot;&gt;assets/nn.scss&lt;/code&gt; file. It looks like this:&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;needs&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;front&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;matter&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;order&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;Jekyll&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;process&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;Sass&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;nn-main&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is a dummy file that imports another SASS file called &lt;code class=&quot;highlighter-rouge&quot;&gt;nn-main.scss&lt;/code&gt;. That
serves as the main entrypoint for the styling of the theme. The reason I have
an additional import is so that I can separate the styles as they would be
organized in a main SASS project from the portion required to make Jekyll
process the styles.&lt;/p&gt;

&lt;p&gt;Anyways, back to the style changes that needed to be tweaked. I created another
SASS file called &lt;code class=&quot;highlighter-rouge&quot;&gt;_bulma-tweaks.scss&lt;/code&gt; that gets imported by &lt;code class=&quot;highlighter-rouge&quot;&gt;nn-main.scss&lt;/code&gt;. This
file is where I can place all the custom rules to override Bulma as much as I
need. Here’s the change I made for the &lt;code class=&quot;highlighter-rouge&quot;&gt;featured-image&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;.featured-image-container&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;justify-content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This just makes sure that the image shows up in the center of the containing
box. There was one last thing missing that I hadn’t realized up to this point:
when I looked at the front page of the site, I noticed that all the text for
posts that included this image went missing. The root cause of this is how
Jekyll determines what an excerpt should look like. Because the &lt;code class=&quot;highlighter-rouge&quot;&gt;featured-image&lt;/code&gt;
component added extra HTML, Jekyll thought that was sufficient for the excerpt
and removed the text. Thankfully, there’s a way to get it back. Jekyll considers
a config variable called &lt;code class=&quot;highlighter-rouge&quot;&gt;excerpt_separator:&lt;/code&gt; when determining how to make post
excerpts. Defining the variable in the file &lt;code class=&quot;highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt; will cause Jekyll to
consider all text before the matching string the post excerpt.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;excerpt_separator&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;!-- excerpt separator --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’ve backfilled this comment in all earlier posts and updated the Rakefile to
generate a post with an excerpt separator so that I always have control over
where to split the post. With all of these small changes in place, I am able to
include images in a more pleasing manner.&lt;/p&gt;

&lt;p&gt;In the future, I plan to add a way to view the full-size original asset as well
as include images throughout the post. This &lt;code class=&quot;highlighter-rouge&quot;&gt;featured-image&lt;/code&gt; component provides
a great starting point for all this future work.&lt;/p&gt;</content><author><name>Nicholas Nooney</name></author><category term="web" /><category term="jekyll-theme" /><category term="this-site" /><summary type="html">In order to make the site stand out, and also to support media types most common to the internet, I’ve quickly styled up a featured image container. This code uses the assets plugin, and results in a simple styled image at the beginning of each post.</summary></entry><entry><title type="html">Code Syntax Highlighting</title><link href="https://blog.nicholasnooney.com/web/code-syntax-highlighting.html" rel="alternate" type="text/html" title="Code Syntax Highlighting" /><published>2018-03-19T15:09:40+00:00</published><updated>2018-03-19T15:09:40+00:00</updated><id>https://blog.nicholasnooney.com/web/code-syntax-highlighting</id><content type="html" xml:base="https://blog.nicholasnooney.com/web/code-syntax-highlighting.html">&lt;p&gt;One aspect of this static site that was looking bland was the code snippets
first presented in &lt;a href=&quot;/web/customizing-this-site.html&quot;&gt;Customizing This Site&lt;/a&gt;. Originally, these
snippets were presented as black text on a grey background. To improve the
visual appearance of code blocks, I decided to add code syntax highlighting
with &lt;a href=&quot;https://arcticicestudio.github.io/nord/&quot;&gt;Nord&lt;/a&gt;.&lt;/p&gt;

&lt;!-- excerpt separator --&gt;

&lt;p&gt;Jekyll supports SASS to compile CSS by default. Thankfully, Nord exports its
syntax coloring as SASS variables already. Jekyll also supports syntax
highlighting via rouge. Rouge is a ruby gem that is capable of parsing many
different languages and adding syntax highlighting to them. The resulting HTML
from Rouge uses the &lt;code class=&quot;highlighter-rouge&quot;&gt;.highlight&lt;/code&gt; class to represent the formatted code.&lt;/p&gt;

&lt;p&gt;In order to apply the Nord syntax highlighting to the Rouge output, I created a
SASS file that maps the styles to the Nord colors. The mapping file can be
found &lt;a href=&quot;https://github.com/nnooney/jekyll-theme-nn/blob/master/_sass/_highlight.scss&quot;&gt;here&lt;/a&gt;. The result is the syntax highlighting you see
throughout this site!&lt;/p&gt;

&lt;p&gt;Below are some examples of the results of syntax highlighting. These snippets
(and more) can be found &lt;a href=&quot;https://helloworldcollection.de&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;c&quot;&gt;C&lt;/h4&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/* Hello World in C, Ansi-style */&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello World!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EXIT_SUCCESS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;c-1&quot;&gt;C++&lt;/h4&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Hello World in ISO C++&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;iostream&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello World!&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;go&quot;&gt;Go&lt;/h4&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;// Hello world in Go&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;fmt&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello World&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;java&quot;&gt;Java&lt;/h4&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Hello World in Java&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HelloWorld&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello World!&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;llvm&quot;&gt;LLVM&lt;/h4&gt;

&lt;div class=&quot;language-llvm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;; Hello world in LLVM Assembly&lt;/span&gt;

&lt;span class=&quot;vg&quot;&gt;@.str&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;14&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;c&quot;hello, world\0A\00&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;@printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;*,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;@main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;nounwind&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;entry:&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;%tmp1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;getelementptr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;14&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]*&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;@.str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;%tmp2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;*,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...)*&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;@printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%tmp1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;nounwind&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;python-3&quot;&gt;Python 3&lt;/h4&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Hello world in Python 3 (aka Python 3000)
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello World&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;racket&quot;&gt;Racket&lt;/h4&gt;

&lt;div class=&quot;language-racket highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;; Hello world in Racket&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;racket/base&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;Hello, World!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;ruby&quot;&gt;Ruby&lt;/h4&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Hello World in Ruby&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello World!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;shell-script&quot;&gt;Shell Script&lt;/h4&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Hello world for the Unix shells (sh, ksh, csh, zsh, bash, fish, xonsh, ...)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;Hello World
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Nicholas Nooney</name></author><category term="web" /><category term="jekyll-theme" /><category term="this-site" /><summary type="html">One aspect of this static site that was looking bland was the code snippets first presented in Customizing This Site. Originally, these snippets were presented as black text on a grey background. To improve the visual appearance of code blocks, I decided to add code syntax highlighting with Nord.</summary></entry><entry><title type="html">Adding Support for a Series of Posts</title><link href="https://blog.nicholasnooney.com/web/adding-support-for-a-series-of-posts.html" rel="alternate" type="text/html" title="Adding Support for a Series of Posts" /><published>2018-03-08T14:45:52+00:00</published><updated>2018-03-08T14:45:52+00:00</updated><id>https://blog.nicholasnooney.com/web/adding-support-for-a-series-of-posts</id><content type="html" xml:base="https://blog.nicholasnooney.com/web/adding-support-for-a-series-of-posts.html">&lt;p&gt;Sometimes, it makes sense to relate posts in a series. A continuation of a story
or an expansion of a project are all reasons to continue a post. This post is
part of the series &lt;em&gt;Developing a Custom Theme&lt;/em&gt;, which details all of the
steps that resulted in the creation of this site’s theme.&lt;/p&gt;

&lt;!-- excerpt separator --&gt;

&lt;p&gt;There are small differences between a post in a series and a post that is not
part of a series. The only difference to cause a normal post to become a part of
a series is to include the special tag &lt;code class=&quot;highlighter-rouge&quot;&gt;series:&lt;/code&gt; in the front matter of the
post. The value of this tag is a string containing the name of the series. All
posts that contain the same value become grouped into the same series.&lt;/p&gt;

&lt;p&gt;For posts belonging to a series, such as this one, you notice
a link to the series underneath the post header information. It has the nice,
italicized text &lt;em&gt;Part of the Series&lt;/em&gt;. It also includes the series name as a link
to the series page. We’ll cover the specifics of the series page in a later
post, but the markup to make the series identifier is fairly straightforward.
All of the markup is included below:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- _layouts/post.html --&amp;gt;&lt;/span&gt;

{% if page.series %}
    {% include components/series-header.html %}
{% endif %}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- _includes/components/series-header.html --&amp;gt;&lt;/span&gt;
{% assign series_page = page.series | slugify | append: &quot;.html&quot; %}

&lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;series-header level&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level-left&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level-right&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;series-header is-italic&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            Part of the series
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ series_page | prepend: &quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;series&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;relative_url&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;}}&quot;&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;link-wrapper-inline&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;has-text-info has-text-weight-semibold&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ page.series }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the post template, we add a section to include this new component if the
markup that Jekyll processes contains the &lt;code class=&quot;highlighter-rouge&quot;&gt;series:&lt;/code&gt; tag inside the front matter.
This section of code belongs just before the post content. The component
contains some Bulma markup and a link to the series page. To get the name of the
series page, I take the series tag and pass it through a filter to get a
readable url and append &lt;em&gt;html&lt;/em&gt; to the end of the name.&lt;/p&gt;

&lt;p&gt;In addition to the markup identifying that this post is a part of a series, I
also want the reader to be able to navigate through the series very easily. To
do this, I decided to add navigational markup to the bottom of the post. The
markup will allow the user to easily access the following items related to the
series:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Another link to the series page&lt;/li&gt;
  &lt;li&gt;The first post in the series&lt;/li&gt;
  &lt;li&gt;The previous post in the series&lt;/li&gt;
  &lt;li&gt;The next post in the series&lt;/li&gt;
  &lt;li&gt;The last post in the series&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bulma’s pagination component was perfect for displaying all of this information.
However, figuring out how to obtain all of the information via Jekyll was a bit
complicated. I’ll try my best to explain it below.&lt;/p&gt;

&lt;p&gt;Similar to how I handled the series header above, I created a new component to
handle all of the navigational information. This time, however, the excerpt is
inserted immediately after the post content.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- _layouts/post.html --&amp;gt;&lt;/span&gt;

{% if page.series %}
    {% include components/series-footer.html %}
{% endif %}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This new component contains the following skeleton code:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;hr&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;series-footer&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level-item&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ series_page | prepend: &quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;series&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;relative_url&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;}}&quot;&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;link-wrapper&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                {% include components/feather-icon.html
                    icon=&quot;archive&quot; class=&quot;has-text-info&quot; %}
                &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Use this span for spacing --&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;icon&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;has-text-info has-text-weight-semibold is-size-5&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ page.series }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;nav&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination is-centered&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;role=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;navigation&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;aria-label=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ prev_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-previous&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Previous&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

            &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ next_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-next&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Next&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

        &lt;span class=&quot;nt&quot;&gt;&amp;lt;ul&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-list&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ first_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-link&quot;&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;aria-label=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Goto page 1&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    1
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-ellipsis&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;hellip;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ prev_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-link&quot;&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;aria-label=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Goto page {{ index | minus: '1' }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ index | minus: '1' }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-link is-current&quot;&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;aria-label=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Current page {{ index }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ index }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ next_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-link&quot;&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;aria-label=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Goto page {{ index | plus: '1' }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ index | plus: '1' }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-ellipsis&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;hellip;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ last_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-link&quot;&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;aria-label=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Goto page {{ count }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ count }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level-left&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;is-hidden-tablet is-italic&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Previous: &lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                {{ prev_title }}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level-right&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;is-hidden-tablet is-italic&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Next: &lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                {{ next_title }}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This code may seem overwhelming at first, so let’s break it down. I define a
&lt;code class=&quot;highlighter-rouge&quot;&gt;section&lt;/code&gt; to contain all of the series navigation, which contains three sub
elements. The first item contains the code for the link to the series page.
The second item is Bulma’s pagination component that displays all of the buttons
for navigating throughout the series. The final component is another level that
displays the title of the previous and next post beneath the corresponding
navigational buttons.&lt;/p&gt;

&lt;p&gt;The first element, which links to the series page, uses the same url scheme as
the series-header component. This time however, I center the text and include an
archive icon to indicate that this footer contains links to the series.&lt;/p&gt;

&lt;p&gt;The second element contains the markup for the Bulma Pagination component. It
features the previous and next buttons, as well as links to the first, previous,
next, and last posts in the series. The two liquid variables &lt;code class=&quot;highlighter-rouge&quot;&gt;index&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;count&lt;/code&gt;
contain numbers indicating the post’s number in the series and the total number
of posts in the series, respectively. I’ll show the logic how to calculate those
values below.&lt;/p&gt;

&lt;p&gt;The third element contains Bulma markup which has been used throughout the site
before. The variables &lt;code class=&quot;highlighter-rouge&quot;&gt;prev_title&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;next_title&lt;/code&gt; contain the titles of the
previous and next post. They are calculated in the logic below as well.&lt;/p&gt;

&lt;p&gt;Before I show the rest of the liquid logic, it is important to understand all of
the markup that we are trying to show. I will make substantial modifications to
portions of that code to introduce new logic based upon which post in the series
is currently being viewed. For instance, it doesn’t make sense to show a
previous post if the first post in the series is being viewed.&lt;/p&gt;

&lt;p&gt;In order to calculate which posts belong to a series, it is necessary to loop
over all of the posts that Jekyll knows about. Liquid can help us out here:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
{% assign count = '0' %}
{% assign index = '0' %}
{% assign capture_prev = true %}
{% assign capture_next = false %}

{% for post in site.posts reversed %}
    {% if post.series == page.series %}
        {% capture count %}{{ count | plus: '1' }}{% endcapture %}
        {% assign last_url = post.url %}

        {% if capture_next %}
            {% assign next_title = post.title %}
            {% assign next_url = post.url %}
            {% assign capture_next = false %}
        {% endif %}

        {% if post.url == page.url %}
            {% capture index %}{{ count }}{% endcapture %}
            {% assign capture_prev = false %}
            {% assign capture_next = true %}
        {% endif %}

        {% if capture_prev %}
            {% assign prev_title = post.title %}
            {% assign prev_url = post.url %}
        {% endif %}

        {% if count == '1' %}
            {% assign first_url = post.url %}
        {% endif %}
    {% endif %}
{% endfor %}
{% assign after = count | minus: index %}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’ve presented all of the code up front. You can see at the beginning I assign
the variables &lt;code class=&quot;highlighter-rouge&quot;&gt;count&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;index&lt;/code&gt;, as well as two helper variables,
&lt;code class=&quot;highlighter-rouge&quot;&gt;capture_prev&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;capture_next&lt;/code&gt;. I use these two variables to help record
information about the previous and next post in the series. Then I loop over
each post. By default, Jekyll loops over posts starting with the most recent;
however, for numbering the posts in the series, I want to keep track of them in
chronological order. Therefore, I loop over them with the &lt;code class=&quot;highlighter-rouge&quot;&gt;reversed&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;If the post belongs to the same series as the page (in this instance, page is
the current page being rendered while post is the collection of all posts on
this site), then I increment the count of pages. Every step after that in this
loop records information based upon which post is encountered. Interestingly,
for the correct behavior to emerge, I collect information in the opposite order
as the posts are presented.&lt;/p&gt;

&lt;p&gt;To get the last post url, I always overwrite the variable &lt;code class=&quot;highlighter-rouge&quot;&gt;last_url&lt;/code&gt;. This way,
by the end of the for loop, &lt;code class=&quot;highlighter-rouge&quot;&gt;last_url&lt;/code&gt; is guaranteed to contain the url of the
last post in the series.&lt;/p&gt;

&lt;p&gt;To get the next post url, I wait until I reach the current post and set the
&lt;code class=&quot;highlighter-rouge&quot;&gt;capture_next&lt;/code&gt; variable to true. Then on the next iteration of the for loop, I
store the post title and url and reset the &lt;code class=&quot;highlighter-rouge&quot;&gt;capture_next&lt;/code&gt; variable to false.
This helper variable, which goes from off to on and back to off again allows me
to capture the post immediately after the current post.&lt;/p&gt;

&lt;p&gt;When I encounter the current post, I record the current count as the &lt;code class=&quot;highlighter-rouge&quot;&gt;index&lt;/code&gt;.
I also set &lt;code class=&quot;highlighter-rouge&quot;&gt;capture_next&lt;/code&gt; to true and &lt;code class=&quot;highlighter-rouge&quot;&gt;capture_prev&lt;/code&gt; to false. This affects the
capture of the next and previous post information.&lt;/p&gt;

&lt;p&gt;To get the previous post url, I capture every post while &lt;code class=&quot;highlighter-rouge&quot;&gt;capture_prev&lt;/code&gt; is true.
Once I reach the current post, I set &lt;code class=&quot;highlighter-rouge&quot;&gt;capture_prev&lt;/code&gt; to false in order to stop
recording the previous information.&lt;/p&gt;

&lt;p&gt;To get the first post url, I record the information when the count is 1.&lt;/p&gt;

&lt;p&gt;By the time the for loop exits, I have the urls of the first, previous, next,
and last post in the series. I also have the total count of posts and the index
of the current post. I also create the variable after, which records the number
of posts after the current post in the series. Now I need to use this
information to control which buttons should be available for the series
navigation. We’ll revisit each of the sections in the navigational buttons and
use these variables to control what to show.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;hr&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;series-footer&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    ...

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;nav&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination is-centered&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;role=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;navigation&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;aria-label=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        {% if index &amp;gt; '1' %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ prev_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-previous&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Previous&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        {% else %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ prev_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-previous&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;disabled&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                Previous
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        {% endif %}

        {% if after &amp;gt; 0 %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ next_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-next&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Next&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        {% else %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ next_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-next&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;disabled&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                Next
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        {% endif %}

        &lt;span class=&quot;nt&quot;&gt;&amp;lt;ul&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-list&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            {% if index &amp;gt; '2' %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ first_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-link&quot;&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;aria-label=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Goto page 1&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    1
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            {% endif %}

            {% if index &amp;gt; '3' %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-ellipsis&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;hellip;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            {% endif %}

            {% if index &amp;gt; '1' %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ prev_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-link&quot;&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;aria-label=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Goto page {{ index | minus: '1' }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ index | minus: '1' }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            {% endif %}

            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-link is-current&quot;&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;aria-label=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Current page {{ index }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ index }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

            {% if after &amp;gt; 0 %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ next_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-link&quot;&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;aria-label=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Goto page {{ index | plus: '1' }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ index | plus: '1' }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            {% endif %}

            {% if after &amp;gt; 2 %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-ellipsis&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;hellip;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            {% endif %}

            {% if after &amp;gt; 1 %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ last_url }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pagination-link&quot;&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;aria-label=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Goto page {{ count }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ count }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            {% endif %}

        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level-left&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            {% if index &amp;gt; '1' %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;is-hidden-tablet is-italic&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Previous: &lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                {{ prev_title }}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
            {% endif %}
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level-right&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            {% if after &amp;gt; 0 %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;is-hidden-tablet is-italic&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Next: &lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                {{ next_title }}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
            {% endif %}
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The code above represents the same code as above, but with conditional logic for
showing the controls. The first thing to notice is the previous and next
buttons. If there is not a previous or next post, then those buttons are
disabled. I chose to make them disabled rather than hidden so that the flow of
the page is not affected by the post index. This creates a more consistent
interface, which I prefer.&lt;/p&gt;

&lt;p&gt;Each of the buttons are shown dependent on the index of the post and the total
number of posts. It turns out that each button is dependent on the following
values:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;First post: &lt;code class=&quot;highlighter-rouge&quot;&gt;index &amp;gt; 2&lt;/code&gt;. In order to show the first post, there must be more
than one previous post.&lt;/li&gt;
  &lt;li&gt;Previous ellipsis: &lt;code class=&quot;highlighter-rouge&quot;&gt;index &amp;gt; 3&lt;/code&gt;. I show ellipses to indicate the existence of
a post between the first and previous. Therefore, there must be a third post
before the current post.&lt;/li&gt;
  &lt;li&gt;Previous post: &lt;code class=&quot;highlighter-rouge&quot;&gt;index &amp;gt; 1&lt;/code&gt;. There must be a previous post to show it.&lt;/li&gt;
  &lt;li&gt;Next post: &lt;code class=&quot;highlighter-rouge&quot;&gt;after &amp;gt; 0&lt;/code&gt;. There must be a next post to show it.&lt;/li&gt;
  &lt;li&gt;Next ellipsis: &lt;code class=&quot;highlighter-rouge&quot;&gt;after &amp;gt; 2&lt;/code&gt;. As with the previous ellipsis, I need to show it
if there are three or more posts after the current post.&lt;/li&gt;
  &lt;li&gt;Last post: &lt;code class=&quot;highlighter-rouge&quot;&gt;after &amp;gt; 1&lt;/code&gt;. There must be more than one next post in order to show
the last post.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The previous and next titles follow the same logic as the previous and next
post.&lt;/p&gt;

&lt;p&gt;This logic leads to the desired behavior shown on each post. It can be a lot to
take in, so it may be more helpful to see the source of the components
discussed.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/nnooney/jekyll-theme-nn/blob/master/_includes/components/series-header.html&quot;&gt;Series Header&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/nnooney/jekyll-theme-nn/blob/master/_includes/components/series-footer.html&quot;&gt;Series Footer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Nicholas Nooney</name></author><category term="web" /><category term="jekyll-theme" /><category term="this-site" /><summary type="html">Sometimes, it makes sense to relate posts in a series. A continuation of a story or an expansion of a project are all reasons to continue a post. This post is part of the series Developing a Custom Theme, which details all of the steps that resulted in the creation of this site’s theme.</summary></entry><entry><title type="html">Managing this Site with Rake</title><link href="https://blog.nicholasnooney.com/web/managing-this-site-with-rake.html" rel="alternate" type="text/html" title="Managing this Site with Rake" /><published>2018-03-08T03:40:25+00:00</published><updated>2018-03-08T03:40:25+00:00</updated><id>https://blog.nicholasnooney.com/web/managing-this-site-with-rake</id><content type="html" xml:base="https://blog.nicholasnooney.com/web/managing-this-site-with-rake.html">&lt;p&gt;In order to remember how to correctly build this site, I decided to use &lt;code class=&quot;highlighter-rouge&quot;&gt;Rake&lt;/code&gt;.
Rake is Ruby’s version of Make: by specifying targets to build and how to build
them, I can easily perform a complex series of commands to manage this site.
Because Rake is so versatile in declaring targets, I use it to create new posts,
run continuous integration, and even generate SSL Certificates for my local
development environment.&lt;/p&gt;

&lt;!-- excerpt separator --&gt;

&lt;h1 id=&quot;beginning-with-rake&quot;&gt;Beginning with Rake&lt;/h1&gt;

&lt;p&gt;After installing Rake, all I had to do was create a &lt;code class=&quot;highlighter-rouge&quot;&gt;Rakefile&lt;/code&gt; in the root of
my site. I’ve never programmed in Ruby before, but it was pretty easy to get
started. All that is needed is the name of a task and a useful description,
and then we can run a command. Prior to using the rakefile, I had to run a long
command every time I wanted to build my site.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bundle &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;jekyll build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s hard to remember! I would much rather run &lt;code class=&quot;highlighter-rouge&quot;&gt;build&lt;/code&gt; in order to build my
site. So I can make a target to build my site and insert it in the &lt;code class=&quot;highlighter-rouge&quot;&gt;Rakefile&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Build the Site'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:build&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'bundle exec jekyll build'&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this code, &lt;code class=&quot;highlighter-rouge&quot;&gt;desc&lt;/code&gt; sets the description of the task, &lt;code class=&quot;highlighter-rouge&quot;&gt;task&lt;/code&gt; describes the
task named &lt;code class=&quot;highlighter-rouge&quot;&gt;build&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;sh&lt;/code&gt; executes code in a shell script. This is neat! Now,
instead of having to remember the entire command, I can just run &lt;code class=&quot;highlighter-rouge&quot;&gt;rake build&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In order to clean the site and rebuild it, I have to run &lt;code class=&quot;highlighter-rouge&quot;&gt;jekyll clean&lt;/code&gt; followed
by &lt;code class=&quot;highlighter-rouge&quot;&gt;rake build&lt;/code&gt;. It would be nice to have one tool run everything for me, so
that I don’t get accidentally confused. Let’s make a target to clean the site
too.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Clean the Site'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:clean&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'jekyll clean'&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is great! Now I run &lt;code class=&quot;highlighter-rouge&quot;&gt;rake clean; rake build&lt;/code&gt; in order to rebuild my entire
site. That’s a lot of typing though. I could make it even shorter by running
&lt;code class=&quot;highlighter-rouge&quot;&gt;rake rebuild&lt;/code&gt;. Let’s make that target.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Rebuild the Site'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:rebuild&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:clean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unlike the other tasks, this one declares a dependency. The &lt;code class=&quot;highlighter-rouge&quot;&gt;rebuild&lt;/code&gt; task must
complete the &lt;code class=&quot;highlighter-rouge&quot;&gt;clean&lt;/code&gt; task, then complete the &lt;code class=&quot;highlighter-rouge&quot;&gt;build&lt;/code&gt; task, in that order. Also
notice that it doesn’t have a body to execute. We don’t need one because
rebuilding the site is already fully described by the &lt;code class=&quot;highlighter-rouge&quot;&gt;clean&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;build&lt;/code&gt; tasks.&lt;/p&gt;

&lt;p&gt;I am a forgetful person sometimes, and with all of these tasks, it is hard for
me to remember what I can run. Thankfully, Rake has the option &lt;code class=&quot;highlighter-rouge&quot;&gt;-T&lt;/code&gt; to list all
tasks that it finds in the Rakefile. But sometimes I even forget that. So in
order to make my life easier, I made a task to list all of the tasks.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:list_tasks&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'rake -T'&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This task doesn’t have a description. Rake doesn’t show tasks in the output of
&lt;code class=&quot;highlighter-rouge&quot;&gt;rake -T&lt;/code&gt; if they don’t have a description. That’s good, so I won’t see this
reminder task for me. But how do I remember to run &lt;code class=&quot;highlighter-rouge&quot;&gt;rake list_tasks&lt;/code&gt;? Sometimes
I may even forget that. The solution is to set a default task. The default task
is a task that is run by Rake when no other task is specified. It uses the
special &lt;code class=&quot;highlighter-rouge&quot;&gt;:default&lt;/code&gt; task name.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:default&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:list_tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Voila! Now I can run &lt;code class=&quot;highlighter-rouge&quot;&gt;rake&lt;/code&gt; whenever I forget what I can do, and Rake will tell
me!&lt;/p&gt;

&lt;h1 id=&quot;taking-rake-to-the-next-level&quot;&gt;Taking Rake to the Next Level&lt;/h1&gt;

&lt;p&gt;Now that I’ve gotten setup with Rake, I can expand upon it to perform more
complicated tasks. Jekyll recommends using HTMLProofer to verify that all the
links in your site work. We can make a command called &lt;code class=&quot;highlighter-rouge&quot;&gt;test&lt;/code&gt; that tests all the
links in the site.&lt;/p&gt;

&lt;p&gt;To do this, we need to include &lt;code class=&quot;highlighter-rouge&quot;&gt;html-proofer&lt;/code&gt; and use it directly from Rake.
Since HTMLProofer is ruby code and Rake executes Ruby code, this makes perfect
sense to do.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'html-proofer'&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Test the Site'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:test&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:check_sri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:check_html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:check_img_http&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:enforce_https&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;HTMLProofer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;check_directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'_site/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I had no idea how to setup and run HTMLProofer, but I got sensible options from
the website. I don’t like that I had to hardcode &lt;code class=&quot;highlighter-rouge&quot;&gt;_site/&lt;/code&gt; though. What if I ever
change the directory to build to? Jekyll supports the &lt;code class=&quot;highlighter-rouge&quot;&gt;-d&lt;/code&gt; option to specify
where to run the site from; all that I really care about is that the output from
the &lt;code class=&quot;highlighter-rouge&quot;&gt;:build&lt;/code&gt; task matches the directory that gets tested. Let’s make a variable.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;vg&quot;&gt;$SITE_DIR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;_site/&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Build the Site'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:build&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'bundle exec jekyll build -d'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$SITE_DIR&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Test the Site'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:test&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:check_sri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:check_html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:check_img_http&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;:enforce_https&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;HTMLProofer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;check_directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$SITE_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we’re getting somewhere. All I have to do is edit the &lt;code class=&quot;highlighter-rouge&quot;&gt;$SITE_DIR&lt;/code&gt; variable
and then my site gets build and tested in that location!&lt;/p&gt;

&lt;p&gt;There’s a lot more that can be done with Rake, and I’m just scrating the surface
with the Rakefile for this project. You can see the current Rakefile
&lt;a href=&quot;https://github.com/nnooney/nn/blob/master/Rakefile&quot;&gt;here&lt;/a&gt;. If I do anything more advanced, I’ll write another
post about it.&lt;/p&gt;</content><author><name>Nicholas Nooney</name></author><category term="web" /><category term="this-site" /><summary type="html">In order to remember how to correctly build this site, I decided to use Rake. Rake is Ruby’s version of Make: by specifying targets to build and how to build them, I can easily perform a complex series of commands to manage this site. Because Rake is so versatile in declaring targets, I use it to create new posts, run continuous integration, and even generate SSL Certificates for my local development environment.</summary></entry><entry><title type="html">Customizing the Design of this Site</title><link href="https://blog.nicholasnooney.com/web/customizing-this-site.html" rel="alternate" type="text/html" title="Customizing the Design of this Site" /><published>2018-01-22T03:56:26+00:00</published><updated>2018-01-22T03:56:26+00:00</updated><id>https://blog.nicholasnooney.com/web/customizing-this-site</id><content type="html" xml:base="https://blog.nicholasnooney.com/web/customizing-this-site.html">&lt;p&gt;The default Jekyll Site uses the &lt;code class=&quot;highlighter-rouge&quot;&gt;minima&lt;/code&gt; theme. This theme is great for getting
started with the basic content of the site, but I prefer to know what’s going
on behind the curtain. What exactly does Jekyll use to convert my markdown files
into a complete static site? To learn about this, I made a custom theme for this
site. The theme’s source code is posted on &lt;a href=&quot;https://github.com/nnooney/jekyll-theme-nn&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;!-- excerpt separator --&gt;

&lt;h1 id=&quot;how-do-jekyll-themes-work&quot;&gt;How do Jekyll Themes Work?&lt;/h1&gt;

&lt;p&gt;Jekyll uses Ruby Gems to store themes. A theme is a collection of named HTML
files with &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt; markup to insert the site content. The behavior
of each HTML/Liquid template can be controlled using front matter in each site
file. This front matter is also the way that Jekyll knows which template file to
use - the &lt;code class=&quot;highlighter-rouge&quot;&gt;layout&lt;/code&gt; keyword indicates which HTML file to render. Overall, the
process looks like this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The site file specifies a layout in its front matter.&lt;/li&gt;
  &lt;li&gt;Jekyll parses the site file and stores the file in named &lt;a href=&quot;https://jekyllrb.com/docs/variables/&quot;&gt;variables&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Jekyll loads the appropriate HTML template from the theme. The template file
gets loaded with the variables parsed in step 2.&lt;/li&gt;
  &lt;li&gt;The fully rendered HTML file is saved in a build directory, which defaults
to &lt;code class=&quot;highlighter-rouge&quot;&gt;_site&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the main process that Jekyll runs through to generate a static website
from a series of HTML files. All of the plugins available for Jekyll will alter
how an individual step in the process is completed; however, the overall
process is the same.&lt;/p&gt;

&lt;p&gt;As an example, let’s go through step-by-step how this page is rendered. You can
view the source of this page &lt;a href=&quot;https://github.com/nnooney/nn/blob/master/_posts/2018-01-21-customizing-this-site.md&quot;&gt;here&lt;/a&gt;. Notice the layout’s front
matter specifies the &lt;code class=&quot;highlighter-rouge&quot;&gt;post&lt;/code&gt; layout; therefore, Jekyll will look for the file
&lt;code class=&quot;highlighter-rouge&quot;&gt;post.html&lt;/code&gt; to convert the source to HTML. You can view &lt;code class=&quot;highlighter-rouge&quot;&gt;post.html&lt;/code&gt; for this
site’s theme &lt;a href=&quot;https://github.com/nnooney/jekyll-theme-nn/blob/master/_layouts/post.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first thing to notice is that &lt;code class=&quot;highlighter-rouge&quot;&gt;post.html&lt;/code&gt; specifies the &lt;code class=&quot;highlighter-rouge&quot;&gt;default&lt;/code&gt; layout in
its own front matter. Just like markdown files can include front matter, theme
files can also contain front matter. The rendering engine is the same as well;
Jekyll will take the contents of &lt;code class=&quot;highlighter-rouge&quot;&gt;post.html&lt;/code&gt; and will place it in the &lt;code class=&quot;highlighter-rouge&quot;&gt;content&lt;/code&gt;
variable of &lt;code class=&quot;highlighter-rouge&quot;&gt;default.html&lt;/code&gt;. With nested templates, it is possible to break down
complex page layouts into easy-to-read layout files.&lt;/p&gt;

&lt;p&gt;The custom theme for this site uses several layout components to compose all of
the pages. Every page is based off of the &lt;code class=&quot;highlighter-rouge&quot;&gt;default&lt;/code&gt; layout, which includes a
header, body, and footer. There are also optional layouts that can be included
on a per-page basis by setting variables in a page or post’s front matter. The
hero banner on the front page and the category menu are examples of optional
layouts. These optional layouts are included with the liquid tag
&lt;code class=&quot;highlighter-rouge&quot;&gt;{% include %}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This site currently has three different layouts: &lt;code class=&quot;highlighter-rouge&quot;&gt;post&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;page&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;front&lt;/code&gt;.
This post is rendered using the &lt;code class=&quot;highlighter-rouge&quot;&gt;post&lt;/code&gt; layout, as specified previously. The
homepage uses the &lt;code class=&quot;highlighter-rouge&quot;&gt;front&lt;/code&gt; layout. The About page is an example of the &lt;code class=&quot;highlighter-rouge&quot;&gt;page&lt;/code&gt;
layout. As I discover the need for more types of layouts, I will add them to
this site and detail how they work.&lt;/p&gt;

&lt;p&gt;A final note about the site’s theme: the design of this site uses &lt;a href=&quot;https://bulma.io&quot;&gt;Bulma&lt;/a&gt;
to manage layout and styling. While its not the most flexible CSS framework
available, it does provide plenty of customization and allows me to focus on
the content. The documentation is extensive and provides detailed examples of
how to structure the site’s HTML. Take a look at Bulma’s documentation if you
would like to understand the specifics of each layout.&lt;/p&gt;

&lt;h1 id=&quot;the-layouts-of-this-theme&quot;&gt;The Layouts of this Theme&lt;/h1&gt;

&lt;p&gt;In order to fully explain how this theme was developed, I will explain how I
built the layouts included in this theme. Currently, my goal for this theme is
to obtain feature parity with the &lt;code class=&quot;highlighter-rouge&quot;&gt;minima&lt;/code&gt; theme. In future posts in this
series, I will explain how these basic themes changed to fit my needs.&lt;/p&gt;

&lt;h2 id=&quot;defaulthtml&quot;&gt;default.html&lt;/h2&gt;

&lt;p&gt;Every theme starts with a base layout. This layout will contain the core
identity that all other layouts will tweak. In this theme, the base layout is
&lt;code class=&quot;highlighter-rouge&quot;&gt;default.html&lt;/code&gt;. Like all HTML documents, it starts with the base document
layout:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
{% include head.html %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’ve separated the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;head&amp;gt;&lt;/code&gt; content into a separate template, &lt;code class=&quot;highlighter-rouge&quot;&gt;head.html&lt;/code&gt;. This
is to keep all of the information belonging to the head of the document in its
own place.&lt;/p&gt;

&lt;p&gt;It’s also good to describe the language of the document. This is done via the
&lt;code class=&quot;highlighter-rouge&quot;&gt;lang&lt;/code&gt; attribute on the &lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;&lt;/code&gt; tag.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lang=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ page.lang | default: site.lang | default: 'en' }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use the page language first, falling back to the site language if the page
doesn’t specify a language, and using English if neither are specified.&lt;/p&gt;

&lt;p&gt;Many websites have a header and a footer. This site is no exception. However,
we’ll separate the header and the footer into separate templates like with the
header above. Also, we’ll use a &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;section&amp;gt;&lt;/code&gt; tag for the main content.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    {% include header.html %}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
        {{ content }}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
    {% include footer.html %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now it’s time to format the layout. I decided with this theme to use a single
column layout to focus on the content with an optional sidebar menu. To make the
menu optional, the template must specify &lt;code class=&quot;highlighter-rouge&quot;&gt;menu: true&lt;/code&gt; in its YAML Front Matter
to include the menu. The &lt;code class=&quot;highlighter-rouge&quot;&gt;front&lt;/code&gt; layout does this below. Anyways, here is what
the main content looks like, expanded upon the section tags in the previous
excerpt.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;section&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        {% if layout.menu %}
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;columns&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;column is-narrow&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                {% include components/menu.html %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;column&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        {% endif %}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;main&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;page-content&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;aria-label=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Content&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wrapper&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                        {{ content }}
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
        {% if layout.menu %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        {% endif %}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All of the classes here except for the main tag are part of &lt;a href=&quot;https://bulma.io&quot;&gt;Bulma&lt;/a&gt;. Look
through the documentation there to see how each class contributes to the overall
layout.&lt;/p&gt;

&lt;p&gt;One more snippet makes the default layout complete: an optional hero banner.
This banner adds a splash of color and can be seen on the front page of the
website. Like the menu, it too must be specified with &lt;code class=&quot;highlighter-rouge&quot;&gt;hero: true&lt;/code&gt; in order to
be activated. Since it should appear at the top of the page, it appears between
the header and the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;section&amp;gt;&lt;/code&gt; tag. This snippet sets up the hero banner:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
{% if layout.hero %}
    {% include components/hero.html %}
{% endif %}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Altogether, this code makes for a customizable default template that suits the
needs of this site. The full code for this template is available
&lt;a href=&quot;https://github.com/nnooney/jekyll-theme-nn/blob/master/_layouts/default.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;posthtml&quot;&gt;post.html&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;post&lt;/code&gt; template defines the main content for posts (including this one). As
specified in the introduction, this template inherits the &lt;code class=&quot;highlighter-rouge&quot;&gt;default&lt;/code&gt; template
via the front matter.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
---
layout: default
---

&lt;span class=&quot;nt&quot;&gt;&amp;lt;article&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will cause all of the contents of the &lt;code class=&quot;highlighter-rouge&quot;&gt;post&lt;/code&gt; layout to be inserted into the
&lt;code class=&quot;highlighter-rouge&quot;&gt;{{ content }}&lt;/code&gt; tag of the &lt;code class=&quot;highlighter-rouge&quot;&gt;default&lt;/code&gt; layout. We can inherit
the head, header, and footer from the default template. Since the post content
is the primary focus, this template will not include the optional hero or menu
template.&lt;/p&gt;

&lt;p&gt;There are two parts to the &lt;code class=&quot;highlighter-rouge&quot;&gt;post&lt;/code&gt; layout: the header and the content. The header
is the most complex. It contains the post title, date, and tags. There’s a bit
of Bulma styling here to make it render nicely as well.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post-header&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level-left&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;header&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post-title&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;title is-3 has-text-primary&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ page.title | escape }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;subtitle is-5&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ page.date | date: &quot;%B %-d, %Y&quot; }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level-right&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tags&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                {% for tag in page.tags %}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tag is-light&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{{ tag }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                {% endfor %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;hr&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The header is a combination of Bulma layout and Jekyll specific Liquid tags, and
so is the content.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post-content&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        {{ content }}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;post&lt;/code&gt; layout is heavily focused on text. In a future iteration I hope to
add better support for images and other media types as well. You can see the
full code of the post template &lt;a href=&quot;https://github.com/nnooney/jekyll-theme-nn/blob/master/_layouts/post.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;pagehtml&quot;&gt;page.html&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;page&lt;/code&gt; template is identical to the &lt;code class=&quot;highlighter-rouge&quot;&gt;post&lt;/code&gt; layout, except it can specify a
long-title to use instead of the normal title. This is due to the fact that any
page with a title by default gets added to the navigation bar in the header of
the site. Below is the content of the &lt;code class=&quot;highlighter-rouge&quot;&gt;page&lt;/code&gt; template:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;article&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;page&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level-left&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;header&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;page-header&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;title is-3 has-text-primary&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ page.long-title | default: page.title | escape }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;subtitle is-5&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ page.date | date: &quot;%B %-d, %Y&quot; }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level-right&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tags&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                {% for tag in page.tags %}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tag is-light&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{{ tag }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                {% endfor %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;hr&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        {{ content }}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see the full code of the page template &lt;a href=&quot;https://github.com/nnooney/jekyll-theme-nn/blob/master/_layouts/page.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;fronthtml&quot;&gt;front.html&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;front&lt;/code&gt; layout is designed to be the homepage of this website. It’s intent is to
provide a helpful summary of the site’s content and serve as an entry point to explore
the rest of the site. It’s layout is quite different from the &lt;code class=&quot;highlighter-rouge&quot;&gt;page&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;post&lt;/code&gt;
templates. To start, its front matter does include the optional hero and menu
components.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;default&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;hero&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;menu&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Other than that, the &lt;code class=&quot;highlighter-rouge&quot;&gt;front&lt;/code&gt; layout is very simple. It defines a &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;section&amp;gt;&lt;/code&gt; to
contain the main content, and then kicks off to include a series of the most recent
posts.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;front&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    {{ content }}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;

{% include components/recent-posts.html %}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;recent-posts&lt;/code&gt; component lists the most recent posts in the site. In fact, its
layout is very similar to the header of the &lt;code class=&quot;highlighter-rouge&quot;&gt;post&lt;/code&gt; template. The noticeable difference
is the additional liquid logic: it performs additional checks to add a horizontal line
between posts, and it limits the tags displayed to three.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;recent-posts&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    {% for post in site.posts %}
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;article&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;media&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;media-content&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level-left&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wrapper&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;title is-4&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ post.url | relative_url }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                                        {{ post.title | escape }}
                                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
                                &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;subtitle is-6&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                                    {{ post.date | date: &quot;%b %-d, %Y&quot; }}
                                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
                            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;level-right&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tags&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                                {% for category in post.categories %}
                                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tag is-info&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                                    {{ category | escape }}
                                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                                {% endfor %}
                                {% for tag in post.tags %}
                                &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tag is-light&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                                    {{ tag | escape }}
                                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                                {% if forloop.index &amp;gt; 3 %}
                                    {% break %}
                                {% endif %}
                                {% endfor %}
                            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post-excerpt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                        {{ post.excerpt }}
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
        {% if forloop.last == false %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;hr&amp;gt;&lt;/span&gt;
        {% endif %}
    {% endfor %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see the full code of the front template &lt;a href=&quot;https://github.com/nnooney/jekyll-theme-nn/blob/master/_layouts/front.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;

&lt;p&gt;These code snippets make up a complete Jekyll theme. I did not show the &lt;code class=&quot;highlighter-rouge&quot;&gt;head&lt;/code&gt;,
&lt;code class=&quot;highlighter-rouge&quot;&gt;header&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;footer&lt;/code&gt; includes that the default template uses. It is worthwhile to
have a look at those as well to gain a complete understanding of how the site fully
works. You can view the theme’s source on &lt;a href=&quot;https://github.com/nnooney/jekyll-theme-nn&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Over the course of these series of posts, I will introduce additional features to
customize the theme further. All of the code in this theme is under the
&lt;a href=&quot;https://github.com/nnooney/jekyll-theme-nn/blob/master/LICENSE.txt&quot;&gt;MIT License&lt;/a&gt; and can be customized to suit your needs.&lt;/p&gt;</content><author><name>Nicholas Nooney</name></author><category term="web" /><category term="jekyll-theme" /><category term="this-site" /><summary type="html">The default Jekyll Site uses the minima theme. This theme is great for getting started with the basic content of the site, but I prefer to know what’s going on behind the curtain. What exactly does Jekyll use to convert my markdown files into a complete static site? To learn about this, I made a custom theme for this site. The theme’s source code is posted on GitHub.</summary></entry><entry><title type="html">The Creation of this Site</title><link href="https://blog.nicholasnooney.com/web/site-creation.html" rel="alternate" type="text/html" title="The Creation of this Site" /><published>2017-12-31T00:00:00+00:00</published><updated>2017-12-31T00:00:00+00:00</updated><id>https://blog.nicholasnooney.com/web/site-creation</id><content type="html" xml:base="https://blog.nicholasnooney.com/web/site-creation.html">&lt;p&gt;So I just setup a new blog for myself, and after looking at the numerous options
for publishing content on the web, I decided a static site would suit my needs
best. I don’t imagine this site will grow to large numbers, and I don’t plan on
hosting huge amounts of media (big pictures and large video files). Plus I’ve
dealt with WordPress enough to know that I don’t want to stray anywhere near
that beast of a CMS. But mostly, being the programmer that I am, I find managing
a simple repository with files containing all of the necessary information for
this site much easier than throwing everything into a database and tweaking the
inner workings of that. Operating Systems are better suited to handle files and
folders rather than databases.&lt;/p&gt;

&lt;!-- excerpt separator --&gt;

&lt;p&gt;So after searching around on the Internet to find the static site generator that
was simple enough that I could comprehend how everything works behind the scenes
(I like exploring how things work), I settled on Jekyll. Hugo was a close second
but I decided I wanted to get some exposure to Ruby over Go. That and GitHub has
first class support of Jekyll sites and will publish them for you.&lt;/p&gt;

&lt;p&gt;I did however, want a snazzy domain name for my site, and since most people in
tech need a web presence, I decided to purchase my own. I didn’t need any
hosting package (thanks GitHub), so I purchased a domain name from NameCheap.
About $50 for 5 years. Not too bad.&lt;/p&gt;

&lt;p&gt;With a domain name and hosting through GitHub, I was ready to go. All I had to
do was install Ruby and Jekyll, and publish my repository to GitHub. With the
help of several guides, I able to set up this site exactly how I wanted to. I
followed these guides in roughly the steps outlined:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://jekyllrb.com/docs/quickstart/&quot;&gt;Setup Jekyll&lt;/a&gt; to create a site on my local PC.&lt;/li&gt;
  &lt;li&gt;Publish the repository to GitHub (I don’t have a guide for this step, since
I’ve published several repositories to GitHub before). By default, GitHub
uses the &lt;code class=&quot;highlighter-rouge&quot;&gt;master&lt;/code&gt; branch. I also published an identical &lt;code class=&quot;highlighter-rouge&quot;&gt;gh-pages&lt;/code&gt; branch
which I chose to host from.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.github.com/articles/configuring-a-publishing-source-for-github-pages/&quot;&gt;Enable GitHub Pages&lt;/a&gt; to host the &lt;code class=&quot;highlighter-rouge&quot;&gt;gh-pages&lt;/code&gt; branch of the repo.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.namecheap.com/support/knowledgebase/article.aspx/9645/2208/how-do-i-link-my-domain-to-github-pages&quot;&gt;Create a CNAME Record&lt;/a&gt; with NameCheap to point to the static site. I
only needed to create the CNAME record; I didn’t create any other records in
this tutorial.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After I got the generic site to show up, I wanted to integrate some continuous
integration steps into my site. Travis CI has first class support for continuous
integration of GitHub repositories, so it naturally made sense to include that.
Thankfully, Jekyll includes a &lt;a href=&quot;https://jekyllrb.com/docs/continuous-integration/travis-ci/&quot;&gt;great tutorial&lt;/a&gt; to setup continuous
integration with Travis CI.&lt;/p&gt;

&lt;p&gt;Windows Note: the &lt;code class=&quot;highlighter-rouge&quot;&gt;htmlproofer&lt;/code&gt; gem needs &lt;code class=&quot;highlighter-rouge&quot;&gt;libcurl.dll&lt;/code&gt; to run successfully. It
does not come prepackaged with the gem. To solve this, I downloaded curl for
Windows and moved the file &lt;code class=&quot;highlighter-rouge&quot;&gt;libcurl.dll&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;C:/Ruby24-x64/bin&lt;/code&gt;. This will allow
the local execution of the CI script.&lt;/p&gt;

&lt;p&gt;With that, I had a properly functioning static site configured, with a custom
domain and continuous integration set up.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Website Source: GitHub&lt;/li&gt;
  &lt;li&gt;Domain Name: NameCheap&lt;/li&gt;
  &lt;li&gt;Hosting: GitHub Pages&lt;/li&gt;
  &lt;li&gt;Continuous Integrations: Travis CI&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;some-time-later&quot;&gt;Some Time Later&lt;/h1&gt;

&lt;p&gt;I discovered Netlify, which provides free hosting of static sites (similar to
GitHub) and it contains its own continuous integration system. Although I
already have a functional static site, I decided to switch over to Netlify
hosting and continuous integration. I am a fan of using fewer services when
possible so that I don’t forget about all the places that I need to visit to
maintain my site.&lt;/p&gt;

&lt;p&gt;To transition the previous site over to Netlify, I needed to first disable
hosting via GitHub Pages. This was as simple as removing the CNAME file and
deleting entries from the settings tab of the repository. Once I did that, I
signed up with Netlify (via GitHub), and created a site for my repository.
Finally, I updated the CNAME record at NameCheap to point to the Netlify URL
rather than the GitHub pages URL.&lt;/p&gt;

&lt;p&gt;I also needed to update the Continuous integration from using Travis CI to using
Netlify’s built in CI. Also, while the short tutorial to set up CI is nice, it
lacks a few resources that are important to modern build systems: separate
environments, dependency-based builds, and better automated testing. However,
since it is easier to develop locally than test via pushing to the remote, I
want to be able to run the complete set of tests both locally and when I push.
Therefore, I want to introduce Rake as a better build system.&lt;/p&gt;

&lt;p&gt;Rather than use a bash script to kick off the continuous integration, I now use
&lt;code class=&quot;highlighter-rouge&quot;&gt;rake deploy&lt;/code&gt; as my deployment. After updating the build command with Netlify, I
have a full site up and running.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Website Source: GitHub&lt;/li&gt;
  &lt;li&gt;Domain Name: NameCheap&lt;/li&gt;
  &lt;li&gt;Hosting: Netlify&lt;/li&gt;
  &lt;li&gt;Continuous Integration: Netlify&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Nicholas Nooney</name></author><category term="web" /><category term="this-site" /><summary type="html">So I just setup a new blog for myself, and after looking at the numerous options for publishing content on the web, I decided a static site would suit my needs best. I don’t imagine this site will grow to large numbers, and I don’t plan on hosting huge amounts of media (big pictures and large video files). Plus I’ve dealt with WordPress enough to know that I don’t want to stray anywhere near that beast of a CMS. But mostly, being the programmer that I am, I find managing a simple repository with files containing all of the necessary information for this site much easier than throwing everything into a database and tweaking the inner workings of that. Operating Systems are better suited to handle files and folders rather than databases.</summary></entry></feed>