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:
- Parsing files with
nonplain.js
↗const files = new Files().load('../notes/**/*.md');
- Transforming file data with
nonplain.js
↗files.transform(({ body, metadata }) => { const newBody = markdownLinksToHTML(body); const newMetadata = { ...metadata, permalink: metadata.permalink || slug(metadata.title), }; return { body: newBody, metadata: newMetadata, }; });
- Exporting file data to JSON with
nonplain.js
↗files.export2JSON('src/_data/notes.json');
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
.