Skip to content
This repository has been archived by the owner on Jun 23, 2020. It is now read-only.
/ nuxt-gustave Public archive

Gustave is a minimalistic Nuxt.js module to help you generate easily a static site from markdown files with "npm run generate" command

Notifications You must be signed in to change notification settings

yann-yinn/nuxt-gustave

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GUSTAVE

Gustave helps you to generate static sites from markdown or yaml files with Nuxt npm run generate command, by transforming Markdown or yaml files into JSON files. Those JSON files can then be easily consumed by your Vue.js components.

Features

  • Frontmatter support for markdown files
  • Handle dates in filenames for blogging, like Jekyll (e.g: 2018-08-21-apples.md)
  • Hot-reloading when markdown files are changed

Requirements

  • Node v10.12.0 (uses { recursive: true } option from fs.mkdir)

Installation

Install Gustave as a dev dependency only, as it is needed only at compile time to generate the JSON files from our markdown files.

npm install nuxt-gustave --save-dev

Add static/api directory to .gitignore file. This is where JSON files will be generated by default.

# nuxt-gustave
static/api

Getting started

The core concept of Gustave are compilers : a compiler is just a function exporting a compile method. This compile method fetches data from somewhere (for example, local mardown files), save them as JSON and return to Nuxt an array of dynamic routes if needed ( for example : ['user/1', 'user/4', 'user/18']).

💡Thoses routes array are required for dynamic routes by npm run generate command, see https://nuxtjs.org/api/configuration-generate#routes . This is not required for static routes like /contact or /about. If you return them directly from your compiler, you don't need to add them manually to nuxt.generate.routes property from nuxt.config.js.

Create a "compiler"

Create a compilers/posts.js file that will turn mardown files from a content/posts directory into a static/api/posts.json file

const { parseMarkdownDirectory } = require('nuxt-gustave/lib/markdown')
const { saveToJsonDirectory } = require('nuxt-gustave/lib/gustave')

exports.compile = () => {
  const resources = parseMarkdownDirectory('content/posts')
  saveToJsonDirectory('posts.json', resources)
  return resources.map(resource => `/posts/${resource.$slug}`)
}

NOTA BENE : we declared here an array of routes with /posts/${resource.$slug} : this mean than, later, we MUST create a corresponding pages/posts/_slug.vue component to handle thoses routes, to actually generate our html.

You can also convert a single file to markdown :

const { parseMarkdownFile } = require('nuxt-gustave/lib/markdown')
const { saveToJsonDirectory } = require('nuxt-gustave/lib/gustave')

exports.compile = () => {
  const resource = parseMarkdownFile('content/settings.md')
  saveToJsonDirectory('settings.json', resource)
  return []
}

Register Gustave compilers

Now we have to configure nuxt.config.js file to use Gustave module and register our new compilers/posts.js compiler.

module.exports = {
  // ...
  // add nuxt-gustave module
  modules: ['nuxt-gustave'],
  // register compilers to use:
  gustave: {
    compilers: [
      'compilers/posts.js',
      // you can pass options to your compiler with array notation, if needed:
      // ['compilers/posts.js', { hello: 'world' }]
    ]
  }
}

Create some posts in yaml

In content/posts directory, add two posts:

📝 content/posts/first-post.md

---
title: this is my firt blog post :D
date: 2019-01-02
---

Hello there, this is my first blog post with Gustave.

📝 content/posts/second-post.md

---
title: second post
date: 2019-01-03
---

Another post in mardown.

Generate our JSON files

Now , if we run npm run dev, npm run generate or npx nuxt-gustave command, a static/api/posts.json file will be automatically created. Simply editing those markdown files will also automatically regenerate the JSON file.

[
  {
    "title": "second post",
    "date": "2019-01-03T00:00:00.000Z",
    "$html": "<p>Another post in mardown. This is the future.</p>\n",
    "$id": "second-post.md",
    "$slug": "another-post"
  },
  {
    "title": "this is my firt blog post :D",
    "date": "2019-01-02T00:00:00.000Z",
    "$html": "<p>Hello there, this is my first blog post with Gustave.</p>\n",
    "$id": "first-post.md",
    "$slug": "hello"
  }
]

Gustave added some useful variables here :

  • $html : the mardkown rendered as html.
  • $id : a uniq id to identify this resource. Filename is used by default.
  • $slug : a slug generated from the filename to build pretty urls like "/posts/my-second-post"

All thoses variables can be overriden inside the compiler, before the resources are saved as a JSON file or even directly in the markdown front-matter:

---
$slug: react-wordpress-reactpress
---

Displaying our posts

We now have a posts.json file that can be used from our components. Below are a simple example of how it could be done, but from this point; it's really up to you : Gustave's Job is only to generate the JSON files declaring the routes.

Display all posts : 📝 pages/posts/index.vue

<template>
  <div>
    <div v-for="post in posts" :key="post.$slug">
      <h2>
        <nuxt-link :to="`/posts/${post.$slug}`">{{post.title}}</nuxt-link>
      </h2>
      <div v-html="post.$html" />
    </div>
  </div>
</template>

<script>
  import posts from 'static/api/posts.json'
  export default {
    computed: {
      posts() {
        return posts
      }
    }
  }
</script>

Display a single post : pages/posts/_slug.vue

<template>
  <div>
    <h1>{{post.title}}</h1>
    <div v-html="post.$html"></div>
  </div>
</template>

<script>
  import posts from 'static/api/posts.json'
  export default {
    computed: {
      post() {
        return posts.find(post => post.$slug === this.$route.params.slug)
      }
    }
  }
</script>

Customize markdown interpreter options

Custom mardown instance

Gustave is using Markdown-it to render markdown, with a default instance. We can pass your own markdownIt instance to get the full control about markdownIt configuration :

module.exports = {
  // ...
  gustave: {
    markdownIt() {
      const markdownIt = require('markdown-it')({
        html: false,
        linkify: true
      })
      // we can add plugins here too
      return markdownIt
    }
    // ...
  }
}

Syntaxic coloration

Code syntaxic coloration with markdownIt can be enable automatically with the highlight options (behind the hood, this will simply inject automatically CSS and JS from highlight.js npm package) :

module.exports = {
  // ...
  gustave: {
    highlight: true
    // ...
  }
}

Blogging with "jekyllMode"

If you have a lot of posts, it is easier to retrieve quickly a post if your filename starts with the date. This what the "jekyllMode" is for :

For the following directory structure:

📁 content
  📁 posts
    📝 2018-07-02-my-first-post.md
    📝 2018-08-03-my-last-post.md

You can create the following compiler :

exports.compile = () => {
  const resources = parseMarkdownDirectory('content/posts', {
    jekyllMode: true
  })
  saveToJsonDirectory('posts.json', resources)
  return resources.map(resource => `/blog/${resource.$slug}`)
}

It will create the following JSON in static/api, already sorted by date and with a $date field:

[
  {
    "$date": "2018-07-02",
    "$slug": "my-last-post",
    "$id": "my-last-post.md",
    "$html": "<div>html content of my last post</div>"
  },
  {
    "$date": "2018-07-02",
    "$slug": "my-first-post",
    "$id": "my-first-post.md",
    "$html": "<div>html content of my first post</div>"
  }
]

Sort by date

if you have a field with an ISO Date (in the yaml frontmatter for example), you can use sortResoucesByDate function manually to sort resources before saving them as JSON. For example:

resources = sortResourcesByDate(resources, '$date', 'asc')

About

Gustave is a minimalistic Nuxt.js module to help you generate easily a static site from markdown files with "npm run generate" command

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published