Wikic

Build Status Coveralls MIT License version Node

a simple static site generator

Table of Contents

Example

Usage

CLI

wikic init

Use wikic init to create a new wikic folder

wikic init <dir>

wikic build

Use wikic build to build pages.

wikic build [options]
#  Options:
#
#    -h, --help           output usage information
#    -c, --clean          clean public dir before building
#    -w, --watch          watch src dir change
#    -s, --serve          serve public dir
#    -d, --dir <dir>      change working dir
#    -o, --output <dir>   change public dir
#    -p, --port <number>  change server port

Node module

const htmlclean = require('htmlclean')
const Wikic = require('wikic')
const docslist = require('wikic-suite-docslist')

const wikic = new Wikic()

// add filter to minify html before write
wikic.filter.register('beforeWrite', function minify(context) {
  if (!context.data) return context
  context.data = htmlclean(context.data)
  return context
})

// add suite to provide `list` variable
wikic.registerSuite(docslist)

// build the site and start watcher and server to debug or preview
wikic
  .build()
  .then(() => wikic.watch())
  .then(() => wikic.serve())

Getting started

Installation

# install as a cli tool
npm install -g wikic

# install as a node dependency
npm install --save wikic

Configuration and Front Matter

There is a default config lib/defaultConfig.yml. We can create _config.ymls or a wikic.config.js to override it.

There are two kinds of configuration, root config and sub config. A root config must be a wikic.config.js or a _config.yml in the working directory of a build (aka wikic.cwd). A sub config must be a _config.yml in the subdirectory of wikic.cwd.

Not all options work in sub configs and we can use some of the options such as

There are inheritance chains of configuration:

See Filter for details of context.

wikic.config.js Example:

module.exports = {
  title: 'Wikic',
  toc: {
    selectors: 'h2, h3, h4',
  },
}

Front Matter example:

---
title: Hello World # title of the page
toc: false # disable toc for this page
layout: docs # set layout for this page
---

Dev Server

We should use a server extension to run wikic build -s.

Server extension Example:

Layouts

We can create Nunjucks templates (extname is .njk) in layoutPath.

In order to specify default layout for markdowns in a specific path, create a _config.yml in the path and add lines to it:

page:
  layout: customLayout

Also, we can set layout in Front Matter for a specific markdown.

Variables in Layouts

Builtin Filters

Nunjucks in Markdown

Variable site and page is available.

{{, }}, {#, #}, {%, %} in raw blocks and <code> blocks will be escaped.

<!-- markdown -->
{% raw %}
{{ page.title }}
{% endraw %}

<!-- output -->
{{ page.title }}
<!-- markdown -->
`{{ page.title }}`

<!-- output -->
<code>{{ page.title }}</code>

Filter

const filter = function(context, wikic) {
  const newContext = Object.assign({}, context)
  // do something with newContext
  return newContext
}

A 'filter' is a Function, which receives a context and the wikic and returns a context.

The context returned by the filter will be passed to next filter.

context

A context is corresponding to a build of a markdown file.

context of the following types of filter is null

context passed to following types of filter is an Object

The context may contains the following properties:

We can use wikic.filter.register(type, filter) to register filters.

Suite

A suite should be a combination of filters.

It should be

Suite objects' property name should be a filter's type name.

Example

Register suites in wikic.config.js

Use Object

module.exports = {
  suites: [
    {
      beforeBuild: function() {
        console.time('build')
      },
      afterBuild: function() {
        console.timeEnd('build')
      },
    },
  ],
}

Use Function

const showBuildTime = function(config) {
  // if option `time` is falsy, do not add suite
  if (!config.time) return null

  return {
    beforeBuild: function() {
      console.time('build')
    },
    afterBuild: function() {
      console.timeEnd('build')
    },
  }
}

module.exports = {
  suites: [showBuildTime],
}

Use module ID

module.exports = {
  suites: ['wikic-suite-docslist'],
}

We can also use wikic.registerSuite(suite) to add suites.

Watch handlers

Built-in handlers

Three built-in handlers:

We can set their values to matchers in anymatch.

The default value is like following wikic.config.js

module.exports = {
  watchHandlers: {
    setupAndBuild: ['**/wikic.config.js', '**/_config.yml'],
    build: [`${config.layoutPath}/**`, `${config.docsPath}/**`],
    buildStaticFile: '**/*',
  },
}

Custom handlers

We can add handlers for files that won't be handled by built-in handlers like the example:

module.exports = {
  publicExcludes: ['sw-template.js'],

  watchHandlers: {
    custom: {
      sw: {
        matcher: ['sw-template.js'],
        handler: (filePath, wikic) => {
          try {
            genSW(wikic.publicPath)
          } catch (err) {
            console.log('oops, something wrong when generating sw.js')
            return false
            // Return false to find a next matched handler
          }
        },
      },
    },
  },
}

Priority

The order of finding handler: setupAndBuild > build > buildStaticFile > custom

Thanks

API

See JSDoc in lib/wikic/index.js

LICENSE

MIT