Wikic
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.yml
s 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
title
page
- options that Filters use, such as
toc
,markdownIt
andtoc
There are inheritance chains of configuration:
- root config =
_config.yml
(in thewikic.cwd
) +wikic.config.js
(in thewikic.cwd
) - sub config =
_config.yml
(closest to markdown file, in the subdirectory ofwikic.cwd
) wikic.config
= defaultConfig.yml + root configcontext.site
=wikic.config
+ a sub configcontext.page
=context.page
+context.site.page
+ Front Matter in markdown
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
site
,Object
, reference tocontext.site
page
,Object
, reference tocontext.page
page.types
,Array
, markdown's dirnames
content
, string, content of HTML built from markdown
Builtin Filters
typeMap
: Get typeName set inwikic.config.typeMap
baseurl
: Get a URL prefixed with base URLrelative
: Receives a absolute path string, returns a url relative to current page.typeMaps
: Receives aArray
, Returnsarray.map(typeMap)
. Tips: get typeNames array{{ page.types | typeMaps }}
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
afterReadAllDocs
: after reading all docs, before writing all docs.beforeBuild
: before building all things.beforeBuildDocs
: before building all docs.afterBuild
: after building all things.afterBuildDocs
: after building all docs.
context
passed to following types of filter is an Object
afterRead
: invoked after reading each markdown file.beforeWrite
: invoked before writing each markdown file.beforeRender
: invoked before rendering each markdown file.beforeWriteAsset
: invoked before writing each asset.
The context may contains the following properties:
src
: string, absolute path of sourcedist
: string, absolute path of destinationdata
: string, content of document;Buffer
, for assetssite
:Object
, site configpage
:Object
, page configrenderContext
:Object
, nunjucks render context, contains variablesIS_DOC
: boolean, whether indocsPath
We can use wikic.filter.register(type, filter)
to register filters.
Suite
A suite should be a combination of filters.
It should be
- a
string
which is a module id relative towikic.cwd
- a plain
Object
- or a
Function
which receivesconfig
and returns anObject
or a falsy value.
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:
setupAndBuild
: Receives new config and then rebuildbuild
: Rebuild the whole sitebuildStaticFile
: When a static file changed which wasn't ignored byconfig.excludes
orconfig.publicExcludes
, build the static file (copy or generate html) and executeafterBuild
filter
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