0.5.4 ā€¢ Published 5 years ago

nuxt-gustave v0.5.4

Weekly downloads
3
License
ISC
Repository
github
Last release
5 years ago

GUSTAVE

Transform your markdown or yaml files into static sites or blog with Nuxt.js. Gustave is designed to work with Nuxt npm run generate.

Gustave transform your markdown or yaml files into JSON files with customizable compilers. 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 to generate the html files from our markdown files.

npm install nuxt-gustave --save-dev

Add static/api directory to .gitignore file. This is where our 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 it 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 an "compiler"

Create an 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 that 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 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/tags.js',
      'compilers/blocks.js',
      // you can passe options to an compiler with an array:
      ['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.

[
  {
    "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"
  }
]

Note that 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, that can be used 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 direclty in the markdown front-matter:

---
$slug: react-wordpress-reactpress-%f0%9f%92%9b
---

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.

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 our 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 add 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>"
  }
]

Note that the $slug and the $id

Sort by date

if you have a field with an ISO Date, you can use sortResoucesByDate function manually to sort resources before saving them as JSON.

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

5 years ago

0.5.3

5 years ago

0.5.2

5 years ago

0.5.1

5 years ago

0.5.0

5 years ago

0.4.1

5 years ago

0.4.0

5 years ago

0.3.1

5 years ago

0.3.0

5 years ago

0.2.0

5 years ago

0.1.1

5 years ago

0.1.0

5 years ago

0.0.27

5 years ago

0.0.26

5 years ago

0.0.25

5 years ago

0.0.24

5 years ago

0.0.23

5 years ago

0.0.22

5 years ago

0.0.21

5 years ago

0.0.20

5 years ago

0.0.19

5 years ago

0.0.18

5 years ago

0.0.17

5 years ago

0.0.16

5 years ago

0.0.15

5 years ago

0.0.14

5 years ago

0.0.12

5 years ago

0.0.11

5 years ago

0.0.10

5 years ago

0.0.9

5 years ago

0.0.8

5 years ago

0.0.7

5 years ago

0.0.6

5 years ago

0.0.5

5 years ago

0.0.4

5 years ago

0.0.3

5 years ago

0.0.2

5 years ago

0.0.1

5 years ago