Mireille Raad's blog
Goofy things, code, data, unfamiliar ideas and stuff worth sharing.
home / blog / datacode
A git post-merge hook to turn vanilla github markdown files into hugo posts

Here is how you can take a bunch of github markdown file and automatically insert meta data that a static site generators can use.

I find that:

  • The choice of a static site generator might change over time,
  • You have content, but you are not ready yet to commit to a static site generator,
  • It is just one extra step to add the frontmatter or setup a CMS,
  • It is nice not having to explain what frontmatter is and just edit generic markdown files,
  • It will be nice to build a distributed system that is able to pull content from regular repos, assumes no coordination or rules.

The setup uses:

  • A repo for the site generator,
  • Submodules as “links” to the content.

The workflow:

  • Once content is updated, a git hook fires up, gets the new content,
  • A bash script will add any bells and whistles that you want to the content,
  • New saved content goes to a new repo where site gets built.

Here is what you need to know before you get started:

  • A vague idea of what git and git hooks are,
  • Sub-modules and how they work,
  • Site generator like Hugo,
  • A vague idea of bash scripting, but knowledge of how to run one,

Steps:

  • Start a new private repo with hugo as a site generator.
  • Add a submodule in the content directory. The sub-module can point to a specific branch in the private or a public git repo where all the nice writing is.
  • pull new content of the submodule, at first manually
    • later on automate with a hook.
  • add a git hook that does all the processing.

Here is how this fancy hook turned out:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
  #/usr/bin/env bash

  changed_files="$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)"

  for file in $changed_files;do
          echo "changed files: \n" $file

          starts_with="$(head -n 1 $file)"

          if [ "$starts_with" != "---" ]; then
                  title="$(grep -m 1 '#' $file | tr -d '#')"
                  (echo $'---\ntitle:'$title'\n---\n' && cat $file ) > tmp && mv tmp $file
          fi
  done

This is a lot of ugly one-liners. Be careful when copying, bash scripting is super case sensitive.

Here is what the hook does:

  • detects changed files
  • loops through the files
  • checks if changed files have front-matter by looking for “—” at the beginning of the file.
  • If no front-matter is detected:
    • find the title of the file by looking for “#”
    • drop the # from the title
    • create front-matter
    • insert it into a temp file
    • replace the pulled file

This seemed like a lot of work. My initial solution was to just soldier on and create a weird hugo theme that doesn’t rely on front-matter. After some tinkering with hugo code, I managed to do that by reading the markdown as data. I generated a homepage and even the navigation menu.

Here is what the hugo code looked like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
  {{$path :=  "/content/data-science" }}
  {{$file := "/data-science/README.md"}}

      <div class="container-fluid ml-4 pt-5 mt-5">
        <div class="row pt-5">
          <aside class="col-lg-3">
            <div id="sticky" class="sticky bg-dark p-2 mr-5">
            {{- $dirs := readDir $path -}}
              {{ range $dirs }}
                {{ $type_arr := split .Name "." }}
                {{ $ext := index $type_arr 1 }}
                {{ if and (ne $ext "git") (ne $ext "gitignore")  }}
                    <div class="nav-item">   <a class="nav-link text-white " href="#">{{ .Name }}</a>   </div>
                {{ end }}
              {{ end }}
            </div>
          </aside>
          <article id="content" class="col-lg-6">
              {{- $file  | readFile | markdownify -}}
          </article>
        </div>
      </div>      

But things got un-usable pretty fast. I couldn’t easily do search or navigation between content. I also got lazy. I have tons of written hugo code already. Re-writing it to just ignore the markdown was an over-kill. The hook started to look like a walk in the park.

I know I am meant to loose my post-merge hook or the hugo code that could be useful for a tiny site. So I am publishing it here for future reference and for whichever poor soul is trying to do the same work.