The Cracked Bassoon


Displaying external files in Jekyll

Filed under jekyll, liquid.

The website is written in Jekyll. I like to display code in my posts, but copy-pasting working code directly from my scripts into Markdown files never felt like an elegant method. For one thing, if I changed my script for whatever reason, I also needed to go back and edit the Markdown file, which was annoying.

So I came up with the following method. First off, when I write a new script for a blog post, I always store it within a directory called /assets/scripts inside the GitHub repository for this website. After the script and the related post are both finished, but before I commit and push the changes to the repo, I run a file called code2yaml.py (also within /assets/scripts). This script looks like:

"""code2yaml.py

Convert contents of `scripts` directory to YAML.

"""
import os
import black


def code2yaml():
    """Convert contents of `scripts` directory to YAML.

    """

    for i, f in enumerate(os.listdir(os.getcwd())):

        src = os.path.join(os.getcwd(), f)
        try:
            contents = open(src).read()
            kwargs = {"fast": True, "mode": black.FileMode()}
            _, ext = os.path.splitext(f)
            if ext == ".py":
                try:
                    # for some reason I can't get "in-place" formatter to work
                    contents = black.format_file_contents(contents, **kwargs)
                except black.NothingChanged:
                    pass
            open(src, "w").write(contents)
            contents = "  " + contents.replace("\n", "\n  ").rstrip() + "\n"
            contents = f"{f.replace('.', '__')}: |\n" + contents
            open("../../_data/code.yaml", "w" if i == 0 else "a").write(contents)
        except IsADirectoryError:
            pass


if __name__ == "__main__":
    code2yaml()

As the name suggests, code2yaml.py converts the contents of all files within /assets/scripts to a YAML data file called _data/code.yaml. As an added bonus, it also formats any Python scripts using black. When Jekyll builds the website, all YAML data within _data/ become accessible via Liquid tags, which can be wrapped inside a Markdown code block with the appropriate language selected for syntax highlighting, like so:

```python
{{ site.data.code.code2yaml__py }}
```

Now I can make changes to my scripts at any time, and those changes will appear on the related posts (so long as I don’t forget to run code2yaml.py!).

Version history

Related posts