node.jsmetalsmith

Metalsmith static site pages are missing metadata


I've been attempting a tutorial to set up Metalsmith, and I've gotten to the end of part 1.

I've install node.js and modules. The IDE is Visual Studio 2013 with Node.js tools installed. I've put a basic structure in and I'm trying to get a single page to render with a template.

The instructions tell to put into a file the following:

---
title: Home
template: home.hbt
---

This is your first page

With a template like:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>{{ title }} | Metalsmith Page</title>
</head>
<body>
    <div class="main-wrapper">
        {{{ contents }}}
    </div>
</body>
</html>

The tutorial says that it should render out into a html page but the result I am getting is something like:

--- title: Home template: home.hbt --- This is your first page

When I use the markdown renderer it gives

<p>---
title: Home</p>
<h2 id="template-home-hbt">template: home.hbt</h2>
<p>This is your first page</p>

Debugging the code shows that when it gets to the renderer the YAML front-matter metadata is missing. This seems to be important as the plugins use the metadata to render the page.


Solution

  • The key to the solution lay in the three strange charatcers at the begining of the markdown rendered page

    
    

    and the YAML front-matter warning:

    UTF-8 Character Encoding Warning

    If you use UTF-8 encoding, make sure that no BOM header characters exist in your files or very, very bad things will happen to Jekyll. This is especially relevant if you’re running Jekyll on Windows.

    Looking at the buffer loaded in Node.js showed the utf8 BOM characters.

    One solution would be to make the IDE stop saving it as utf8 with BOM but for me that wasn't a viable option.

    I created a workaround as a few small lines that has to be run before any other metalsmith plugin.

    var stripBom = require('strip-bom');
    var front = require('front-matter');
    var extend = require('extend');
    
    // **snip**
    
    .use(function __utf8BOM_workaround(files, metalsmith, done)
    {
        setImmediate(done);
        Object.keys(files).forEach(function (file)
        {
            var data = files[file];
            var parsed = front(stripBom(data.contents.toString()));
            data = extend({}, data, parsed.attributes);
            data.contents = new Buffer(parsed.body);
    
            files[file] = data;
        });
    })