My goal here is to dynamically generate pages like /categories/code/, that would list all articles categorized in code. As far as I can tell, there’s no standard way. I found a few articles explaining how to create such pages for a given category, but none regarding how to auto-generate them for all your categories.

For this purpose, I resorted to some scripting, which through the power of CI, is completely transparent.

The process is:

  1. Create layout for category page
  2. Generate a JSON file containing the list of categories.
  3. Generate a page for each category using the layout in 1.
  4. jekyll build

Layout

The layout I used ressembles a lot the layout of the home page. In the _layouts folder of Jekyll, I created this file:

---
layout: default
---

<div class="home">

    <article class="post" itemscope itemtype="http://schema.org/BlogPosting">

  <header class="post-header">
    <h1 class="post-title" itemprop="name headline">Fixing error CS2012 on Visual Studio for mac</h1>
    <p class="post-meta">
      <time datetime="2017-05-16T00:00:00+00:00" itemprop="datePublished">2017-May-16</time>
           | <a href="/categories/Code">Code</a> | <a href="/categories/.Net">.Net</a>
    </p>
  </header>

  <div class="post-content" itemprop="articleBody">
    <p>I encountered this bug that left me a bit circumspect while trying to give a shot at Visual Studio for mac and .net standard.</p>

<p>My setup was the following:</p>

<ul>
  <li>Visual Studio for Mac community version 7</li>
  <li>Two projects with .net standard 1.4 (as far as I can tell, does the same thing for other versions), <strong>A</strong> is depending on <strong>B</strong></li>
</ul>

<p>When re-building the project, I was encountering an error when building the .net standard project.</p>

<p>The issue it gives is fairly expressive, as you can tell:</p>

<blockquote>
  <p>CSC : error CS2012: Cannot open ‘/Volumes/DIKS/git/events-client/source/EventServiceClient/obj/Debug/netstandard1.6/EventServiceClient.pdb’ for writing – ‘Sharing violation on path /Volumes/DIKS/git/events-client/source/EventServiceClient/obj/Debug/netstandard1.6/EventServiceClient.pdb’</p>
</blockquote>

<p>So basically a file conflict on trace maps.</p>

<p>This seems to be a bug<sup id="fnref:1"><a href="#fn:1" class="footnote">1</a></sup>. Despite some googling around, nothing seemed to be linked.  I finally realized that my solution is on a FAT drive, which does not handle I/O the way a HFS drive does. Moving the solution to an HFS drive does the trick!</p>

<p>Hope it can help someone.</p>

<h1 id="notes">Notes</h1>

<div class="footnotes">
  <ol>
    <li id="fn:1">
      <p>that I <a href="https://connect.microsoft.com/VisualStudio/feedback/details/3134326">logged here</a>&nbsp;<a href="#fnref:1" class="reversefootnote">&#8617;</a></p>
    </li>
  </ol>
</div>

  </div>


  <div class="post-related">
    <h1>Related</h1>
    <ul class="post-list" id="list">
    </ul>
  </div>

  <script type="text/javascript">
    var title = "Fixing error CS2012 on Visual Studio for mac".replace(/[^A-Za-z0-9=_-]/g, "");
    document.searchClient.related(title, function(err, res) { document.searchClient.display(res.slice(0, 4)); });
  </script>
</article>


    <h2>About ""</h2>

    <ul class="post-list">
        
    </ul>
</div>

This basically iterates through the posts of a category contained in property category of a given page using this layout.

Category list

In my assets folder, I created an assets.json file with the following contents:

---
---
{
  "categories": [
    
      "Psychology",
    
      "Code",
    
      "Reading notes",
    
      "Code like a monkey",
    
      "Design patterns",
    
      "Process",
    
      "Organization",
    
      "Self improvement",
    
      "Management",
    
      "Source control",
    
      "Devops",
    
      "Coffee script",
    
      "Functional programming",
    
      "Node.js",
    
      "Slack",
    
      "WIP",
    
      "Azure",
    
      "Bot",
    
      "Security",
    
      "Flow",
    
      "Small batches",
    
      "Product management",
    
      "CI",
    
      "AWS",
    
      "Physics",
    
      "KSP",
    
      "Azure functions",
    
      "Lambda",
    
      "Git",
    
      ".Net",
    
      "Jekyll",
    
      "Webapps",
    
      "Agile",
    
      "DevOps",
    
      "Smells",
    
      "Memo",
    
      "Architecture",
    
      ""
  ]
}

The --- tell Jekyll to build the file. The rest is just simple liquid. When building, the result looks like this.

Generate a page for each category

The page is plain and simple:

---
layout: category
category: Code
---

We just need to generate one for each in a categories folder, so that they can be accessed through /categories/code/.

Let’s start with a simple node script running through the categories.json:

const path = require("path");
const fs = require("fs");

const categoryFile = path.join("_site", "assets", "categories.json");
const categoryFolder = path.join("categories");

const categoryContent = fs.readFileSync(categoryFile).toString();
const deserializedCategories = JSON.parse(categoryContent);
const categories = deserializedCategories.categories;

categories.forEach(function(category) {
  if (category === "")
    return;
  const content = "---\nlayout: category\ncategory: " + category + "\n---";
  const file = path.join(categoryFolder, category + ".md");
  fs.writeFileSync(file, content);
});

I then invoke that in my build script:

#!/usr/bin/env bash

function build {
    if [ "$1" != "--refresh" ]; then
        jekyll build --incremental
    else
        jekyll build
    fi
}

function updateCategoryPages {
    if [ -d "categories" ]; then
        rm -rf categories
    fi
    mkdir categories
    node build/updateCategories.js
}

build
updateCategoryPages
build

The first build is going to generate the categories.json file. Then we iterate through it and generate files. Then we build again.

Having my build done on Codeship, all I need to do is push and this is done automagically.