charnould
charnould

Reputation: 2917

Eleventy - How to compile .yaml files (text not data) into html?

I'm new using Eleventy, but I succeed in turning .md files into .html.
So far so good, even using templates/layouts.

However, I've a problem I can't solve.

Consider a bunch of yaml files (they are not data but text).

From:

src:
 - spec-1.0.0.yaml
 - spec-1.1.0.yaml

I'd like Eleventy to compile to:

_site:
 - spec-1.0.0/index.html
 - spec-1.1.0/index.html

...where index.html are my base.njk layout and my yaml text copy/paste in a code tag.

How to do so: Eleventy doesn't see/use my yaml files?
Thanks

Upvotes: 0

Views: 1188

Answers (1)

person_v1.32
person_v1.32

Reputation: 3197

Eleventy doesn't process your yaml files because it has no idea what you want to do with them. YAML isn't a template language, and the data inside can be interpreted in many different ways.

If you want Eleventy to process yaml files by outputting html files with the contents of the yaml file inside some code, there are several methods, each with advantages and disadvantages.

Custom Template Language

You can define a custom template language which tells Eleventy how to process files that aren't part of the default template languages.

This method requires the least amount of changes but isn't very flexible if your requirements change in the future. However, it does exactly what you said you wanted to do—convert every yaml file in your src folder to an html file in a <code> tag (I also added a pre tag for keeping whitespace).

In your .eleventy.js config file:

// .eleventy.js

module.exports = function (eleventyConfig) {

  // ...

  // tell eleventy to process .yaml files
  eleventyConfig.addTemplateFormats('yaml')
  // tell eleventy what to do with them
  eleventyConfig.addExtension('yaml', {
    compile: (inputContent) => {
      let output = `<!doctype html><html><body><pre><code>${inputContent}</code></pre></body></html>`
      return () => output
    },
  })

  // ...

}

This method works, but it's not convenient if you ever want to add more things to your markup.

Data file and Pagination

You can create a JavaScript data file in your src/_data directory that finds .yaml files and returns the content. Then you can paginate the data to generate pages.

This method means that you can use any template language of your choice or layouts to add styling, scripts, or other markup. You can even parse the YAML with js-yaml or something and render different things depending on the content inside.

// src/_data/yamlFiles.js

const fs = require('fs/promises')

module.exports = async () => {
  const files = await fs.readdir('./src/')
  const yamlFiles = files.filter((file) => file.endsWith('.yaml'))

  const output = ( // read from each file
    await Promise.all(
      yamlFiles.map(async (file) => {
        const content = await fs.readFile(`./src/${file}`, 'utf8')
        return {
          file: file.split('.').slice(0, -1).join('.'),
          content,
        }
      })
    )
  )
    // convert a list of objects to an object mapping filename to content
    .reduce((acc, { file, content }) => {
      acc[file] = content
      return acc
    }, {})

  return output
}

In src/yamlFiles.njk (or template language of choice, the filename doesn't matter):

---
pagination:
    data: yamlFiles
    size: 1
    alias: filename
permalink: "{{filename}}/"
# layout: your_layout
---
{% set fileContent = yamlFiles[filename] %}

<!doctype html>
<html>
    <body>
        <pre><code>{{ fileContent | safe }}</code></pre>
    </body>
</html>

If you're using this method, you may want to create a separate directory outside your src folder to store your YAML files. Just change the paths in src/_data/yamlFiles.js.

Upvotes: 1

Related Questions