Building site data with nonplain

This site is built completely from JSON data. So, before we start generating our site, we need to get our data in order with a little help from some nonplain tools.

Notes2JSON with nonplain

nonplain and nonplain-md-link make building markdown notes into webpages simple by providing composable tools for parsing groups of "nonplain" (plaintext + frontmatter) files, transforming them as needed, and then exporting them. Loading the files, parsing them, transforming their body content and metadata, and exporting them to JSON is possible in just 60 lines of code.

The notes

First, we need a couple of files to build our site out of. You can do this yourself. For the purposes of this tutorial, make sure to create your files with a title property in the frontmatter:

---
title: The title I want my page to be
---

Optionally, specify a permalink:

---
title: This is the home page
permalink: /
---

This metadata will help us name our pages and navigate to them reliably on the web.

The code

The full code can be found on GitHub ↗, so you can go read the full build-notes.js file there. In the meantime, we'll walk through each section of that code and talk about what it does.

Dependencies

First, we need to import a few packages. We'll need the built-in Node.js path and url packages, as well as slug, an excellent package from Rich Trott ↗ that makes valid permalinks easy. Finally, we'll import nonplain to help us work with our note files and nonplain-md-link to help us make sure our wiki-style links work on the web.

const path = require('path');
const URL = require('url').URL;
const slug = require('slug');
const Files = require('nonplain').default;
const Link = require('nonplain-md-link').default;

const { regex } = require('nonplain-md-link');

Helper functions

Next, we need two helper functions. One will help us detect URLs pointing to external sites so that we can treat them accordingly, and the other will use nonplain-md-link to transform all links in our markdown to work on our site, including "wiki-style" links.

First, our external URL detector:

function isFullUrl(href) {
  try {
    new URL(href);
    return true;
  } catch (err) {
    return false;
  }
}

This function uses the built-in url package from Node.js to check whether a given string is a valid, full URL. If it is, we can assume it points to an external site. If it's not, we can assume it's a relative path ↗ and that it links to an internal page.

Now, we need to transform some links:

function markdownLinksToHTML(content) {
  return content.replace(regex.links.all, (linkStr) => {
    const link = new Link(linkStr);

    const isExternalUrl = isFullUrl(link.path);

    if (isExternalUrl) {
      const externalLinkArrow = '↗';
      link.innerText = link.innerText + ' ' + externalLinkArrow;

      return link.composeHTML('rel="noreferrer" target="_blank"');
    } else {
      link.path = '/' + slug(path.parse(link.path).name) + '/';

      return link.composeHTML();
    }
  });
}

This function uses nonplain-md-link to match ↗ and parse ↗ all links in our file body ↗. We'll call this function from within the transform() method, passing the body of our file to it. This will ensure that all markdown and wiki-style links are working properly on our site.

Building notes

This is the fun part, where we put everything together using nonplain.js.

const files = new Files().load('../notes/**/*.md');

files.transform(({ body, metadata }) => {
  const newBody = markdownLinksToHTML(body);

  const newMetadata = {
    ...metadata,
    permalink: metadata.permalink || '/' + slug(metadata.title) + '/',
  };

  return {
    body: newBody,
    metadata: newMetadata,
  };
});

files.export2JSON('src/_data/notes.json');

This is the main code that builds our notes. It runs when the file is executed by our npm run notes script. First, we load the notes into a Files instance to parse them. Then, we run a transform() on our files. Finally, we export our files to JSON.

To understand how this code works in more detail, see the links below:

Now, we can parse, transform, and export all of our note files by running this file with Node.js.

$ node build-notes.js

When we put our site together, feel free to use NPM scripts ↗ to make building as easy as npm run notes.

Next: Putting it all together with 11ty