Components and helpers to build user documentation websites using Dimer and Vue
npm install dimer-vue
Dimer is an open source project and CMS to help you publish your documentation online.
We believe every project/product is incomplete without documentation.
We want to help you publish user facing documentation, without worrying about tools or code to write.
| file | size | gzip size |
|------------------------|----------|-----------|
| CJS | 26 KB | 5.83 KB |
| UMD | 28.3 KB | 6.02 KB |
| UMD MIN | 9.63 KB | 2.98 KB |
The goal of the project is to make it easier to create custom designs for your documentation, without re-creating the core elements or components.
- Prerequisites
- Installation
- Nuxt usage
- Setup nuxt.config.js file
- Registering routes
- Layout component
- Doc component
- Vuex store
- Dimer plugins
- Dimer tree
- Component renderers
- Dimer tabs
- Dimer collapse
- Dimer search
- Events
1. If you are testing it on your local server, then it will be accessible as http://localhost:5000
2. If you have published it on Dimer cloud, then it will be https://api.dimerapp.com/YOUR_DOMAIN.
``sh
npm i dimer-vue
Nuxt usage
The documentation covers this module usage with Nuxt. However, any Vue project using Vue router and Vuex store can leverage the API.> Nuxt has almost zero boilerplate to create full blow SPA in Vue.js. So give it a try.
Before getting started, you have to install handful of dependencies and register them as nuxt modules inside
nuxt.config.js file.`sh
npm i nuxt-env @nuxtjs/axios @nuxtjs/router
`- The
nuxt-env is required, so that we can define environment variable for the Dimer API base url. The environment variables gives us the freedom to point to a different API endpoints in production and development respectively.
- The @nuxtjs/axios is required for making API calls.
- The @nuxtjs/router is required to register custom routes exposed by this module. The route is an optional dependency, however it makes the process of registering custom routes so simple. $3
Next step is to setup the nuxt.config.js file with following code.`js
export default {
modules: [
'@nuxtjs/router',
'@nuxtjs/axios',
['nuxt-env', {
keys: [{
key: 'DIMER_BASE_URL',
default: 'http://localhost:5000'
}]
}]
],
plugins: ['~plugins/dimer.js']
}
`We will create
~plugins/dimer.js now, with following contents.`js
import Vue from 'vue'
import { Dimer, DimerTree } from 'dimer-vue'export default async function (ctx, inject) {
Dimer.use(DimerTree)
/**
* Injects handful of utility methods and loads the vuex
* store with
dimer module.
*/
await Dimer.loadStore(ctx, inject)
Vue.use(Dimer)
}
`The dimer plugin is straight forward. We pre-load some stuff from the API to the Vuex store and also inject some helper functions.
> Feel free to add custom renderers and Dimer plugins inside this file.
$3
Now, we need to register couple of routes, which are handled by Dimer. This is done, so that Dimer can offload the task of making API calls, validating routes to have correct zone and version etc.We will leverage the
router module and define following routes inside router.js file.`js
import Vue from 'vue'
import Router from 'vue-router'
import { routes } from 'dimer-vue'import LayoutComponent from '~/components/Layout'
import DocComponent from '~/components/Doc'
Vue.use(Router)
export function createRouter() {
return new Router({
mode: 'history',
routes: routes(LayoutComponent, DocComponent)
})
}
`The
routes function exported by Dimer will register following routes-
:/zone/:version
- :/zone/:version/:permalinkAlso, if you have noticed, the
routes function accepts two Vue components. These components are rendered when Dimer will receive request on the registered routes.#### Layout component
Define the complete page layout and documentation navigation (usually a sidebar) in this file.
`vue
`#### Doc component
The
Doc component is meant to render a single doc.`vue
{{ doc.title }}
`That's all. Now you have a fully working Nuxt app consuming the Dimer API and rendering docs. From here
- You are free to design and structure the layout as per your needs.
- Use any Dimer plugins to enhance the documentation.
- Don't worry about someone entering the wrong URL, as Dimer custom routes will handle everything for you.
Vuex store
The Dimer.loadStore method registers a module named dimer and makes the API calls to the Dimer API and add following values to the store.`js
{
websiteOptions: {},
zones: []
}
`1. The
websiteOptions is loaded from /config.json endpoint.
2. The zones are loaded from /zones.json endpoint.You are free to read values from the store from any custom component. For example: Rendering the main menu from the available zones and so on.
Dimer plugins
The Dimer plugins are mainly focused on the Rendering layer of Vue. As you know that Dimer API returns the markdown content as JSON AST and available plugins can ease the process of rendering and handling certain nodes differently.$3
The DimerTree is the bare minimum you need to render the JSON AST as it is.`js
import { DimerTree, Dimer } from 'dimer'
Dimer.use(DimerTree)
`and then use the component as follows:
`vue
`The
DimerTree component also accepts one or more renderer functions. These functions will receive all the AST nodes and can handle them any way. Let's say we want to add
target="_blank" to all external links. We can define a renderer for that.`js
import { DimerTree, Dimer, utils } from 'dimer'
Dimer.use(DimerTree)Dimer.addRenderer(function (node, rerender, createElement) {
if (node.tag === 'a' && /^http(s)?/.test(node.url)) {
node.props.target = '_blank'
const attrs = utils.propsToAttrs(node.props)
const children = node.children.map(rerender)
return createElement('a', { attrs }, children)
}
})
`> The possibilities with custom renderers are endless
#### Component renderers
The renderers added via
Dimer.addRenderer are global and will always be used by dimer-tree component. However, you can use customRenderers prop to define custom renderers.`vue
`$3
The DimerTabs component is registered to ease the process showing multiple codeblocks inside a tab. They are defined using the [codeblock] macro in Markdown.This is a renderless component, that you need to wrap in order to define your own markup for tabs.
The first step is to define a Dimer renderer, that returns a custom component for the
tabs node.`js
import { Dimer, DimerTabs } from 'dimer-vue'
Dimer.use(DimerTabs)import Tabs from '~/components/Tabs'
Dimer.addRenderer(function (node, rerender, createElement) {
if (node.props.className && node.props.className.indexOf('tabs') > -1) {
return createElement(Tabs, { props: { node } })
}
})
`Next step is to create the
~components/Tabs component. This component will make use DimerTabs and defines the markup for the tabs.`vue
v-for="(pane, index) in tabs.panes"
v-show="index === activeIndex"
>
`
component is similar to the DimerTabs component, but to define the custom markup and behavior for the [collapse] macro.`js
import { Dimer, DimerCollapse } from 'dimer-vue'
Dimer.use(DimerCollapse)import Collapse from '~/components/Collapse'
Dimer.addRenderer(function (node, rerender, createElement) {
if (node.props.className && node.props.className.indexOf('collapsible') > -1) {
return createElement(Collapse, { props: { node } })
}
})
`Next step is to create the
~/components/Collapse component.`vue
{{ collapse.title }}
`$3
Dimer has inbuilt search for documentation and instead of building the entire Typeahead search from hand, we recommend using the renderless DimerSearch component.`js
import { Dimer, DimerSearch } from 'dimer-vue'
Dimer.use(DimerSearch)
``vue
type="search"
v-model="model.query"
@keyup="searchScope.triggerSearch"
/>
Results for {{ item.zone }}
`#### Events
You can define listeners for following events.
`vue
:model="model"
@onArrowUp="customHandler"
@onArrowDown="customHandler"
@onEnter="customHandler"
@onEscape="customHandler"
>
``