4

I have a very simple use case for metalsmith that doesn't seem to be covered by any readily available documentation.

In my index.html I want multiple content areas:

<!-- in my index html -- a single page landing site -->
<body>
  <section id="about">
     {{{about}}}
  </section>
  <section id="faq">
     {{{faq}}}
  </section>
...

And I want the contents for about and faq to come from markdown files. I'm happy to change how my files are organised/marked up.

I just can't figure out which plugins to use to make it work, everything seems geared towards generating one output file per source file.

The plugins that seem they would work (metalsmith-in-place and metalsmith-layouts) tell you to come to SO for more elaborate examples, so here we are!

andyhasit
  • 14,137
  • 7
  • 49
  • 51

3 Answers3

4

I created a fork for metalsmith-markdown:

https://github.com/DKhalil/metalsmith-markdown

You can add sections in your markdown files like this:

Markdown text here
---
section: SECTION_NAME
---
Markdown text here

The second markdown part would be available under the variable SECTION_NAME in the template file, the first one still under {{ contents }}

Dask
  • 61
  • 5
2

You can do multiple content areas with a language that supports template inheritance, like swig, combined with metalsmith-in-place.

Without using markdown you could do so like this:

src/index.swig

{% extends 'templates/default.swig' %}

{% block about %}
  Content for about
{% endblock %}

{% block faq %}
  Content for faq
{% endblock %}

templates/default.swig

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
</head>
<body>
  <section id="about">
    {% block about %}{% endblock %}
  </section>
  <section id="faq">
    {% block faq %}{% endblock %}
  </section>
</body>
</html>

build.js

/**
 * Dependencies
 */
var filenames = require('metalsmith-filenames');
var inPlace = require('metalsmith-in-place');
var metalsmith = require('metalsmith');

/**
 * Build
 */
metalsmith(__dirname)

  // Process templates
  .use(filenames())
  .use(inPlace('swig'))

  // Build site
  .build(function(err){
    if (err) throw err;
  });

Then run node build.js. Now if you want to use markdown as well this isn't really possible. Marked, the renderer for metalsmith-markdown, will surround your content with <p>s, escape certain characters and so forth. Which would make maintaining the templates a hassle as metalsmith-markdown might break the swig tags. It might still work, but I definitely would not recommend it.

So what I recommend is the above setup. You would lose the advantage of using markdown, but gain some extra organisation options. It's up to you to decide which you prefer.

  • 2
    I ended up using metalsmith-data-markdown an putting multiple markup areas directly in the html. Not ideal but it fitted my needs. Accepting answer as it is a good answer. – andyhasit Mar 10 '16 at 16:11
1

As other comments and answers mention, using data-markdown, in-place and a template engine with inheritance will make this possible. The only missing piece from above is putting it all together in the right sequence (which is often the case with Metalsmith, I've found).

First use in-place, then use data-markdown:

metalsmith(__dirname)
  .use(inplace({
    engine: 'swig',
    pattern: '**/*.html',
    autoescape: false,
  }))
  .use(markdown({
  }))
  .build(function(err) {
    if (err) {
        console.log(err);
    }
    else {
        console.info('✫ Built it. ✫');
    }
  });

Wrap your markdown with the data-markdown tag:

<div data-markdown>

## About

This is about me. I like lists:

* They
* Make
* Me
* So
* Happy!

</div>

Include it somewhere:

<!DOCTYPE html>
<html>
<head><title>A page</title></head>
<body>

  {% include "./markdown/about.md" %}

  {% include "./markdown/faq.md" %}

</body>

Working demo here: https://github.com/hoosteeno/metalsmith-markdown-swig/

hoosteeno
  • 644
  • 5
  • 17