Skip to content

Latest commit

 

History

History
 
 

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

search english

Docute

Writing docs without build process.

How does it work

docute is a .js file along with its theme assets, which you can add to a static .html file hosted anywhere.

All client-side

No extra setup for docute is needed, no build process, everything is performed on the fly! We're using a fork of marked the gorgeous and blazing-fast markdown parser.

Installation

Use docute-cli to initialize the docs folder.

Using npm:

npm i -g docute-cli

Using Yarn:

yarn global add docute-cli

You don't really need docute-cli, it's just a tool for scaffolding out a doc folder and bringing you a dev-server with live reloading support. You can use any similar tool, for example, live-server + yeoman generator, or simply crafted by hand if you like, there's not much work you have to do!

Quick Start

Assume that the folder you want for docs is ./docs:

docute init ./docs

Now the ./docs folder is ready, so far we got:

  • README.md: Used as content of homepage
  • index.html: The html that contains the scripts and styles you need
  • .nojekyll: Indicates that this is not a jekyll website, ignore this if you're not deploying to github pages

Then you can preview the docs locally:

docute ./docs

Open http://localhost:8080 and you'll see it in action.

Manually

Do you hate node.js or npm? Or just being too lazy to install them? You know you don't need to install docute-cli at all!

What we really need is an index.html:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
  <title>My Awesome Doc</title>
  <!-- the docute client styles -->
  <link rel="stylesheet" href="https://unpkg.com/docute/dist/docute.css">
</head>
<body>
  <div id="app"></div>
  <!-- load the docute client library -->
  <script src="https://unpkg.com/docute/dist/docute.js"></script>
  <!-- bootstrap your docute app! -->
  <script>
    docute.init()
  </script>
</body>
</html>

And that's it!

Configuration

docute.init accepts an argument for setting configurations:

docute.init({
  // ...config goes here
})

url

docute.init({
  url: '.' // default
  // Use files from another source
  url: 'https://cdn-to-markdown-files.com/'
})

The URL to your website, eg: http://example.com/docs or /docs, the markdown files will be fetched from this url, when using the default value .:

  • When you visit / it will fetch ./README.md
  • When you visit /en/guide it will fetch ./en/guide.md
  • When you visit /es/about/ it will fetch ./es/about/README.md

Home Page

README.md in your docs folder will be treated as homepage for your website, but sometimes you may need to serve another file as your homepage. For example you're deploying ./docs as github pages but already have README.md in your repo, why do you have to populate another file at ./docs/README.md, right? Then just tell it which file we should use:

docute.init({
  // use a markdown file from url directly
  home: 'https://raw.githubusercontent.com/egoist/docute/master/README.md'
})

Landing Page

You can set the landing option to true or a custom path or a markdown string:

docute.init({
  // or custom path
  landing: '_my-landing.html',
  // or even markdown file
  landing: 'landing.md',
  // or inline markdown
  landing: '# this is landing page'
})

If you enable landing page, the route / will match landing page, and /home will be the homepage of docs.

You cannot use script tag in pages, since dynamically added scripts will not be evaluated by your browser.

Advanced usage

The landing option could also be an object:

docute.init({
  landing: {
    source: 'landing.html'
  }
})

Same as using string as the value of landing.

docute.init({
  landing: {
    markdown: '## inline markdown',
    // or:
    // html: '<h2>inline html</h2>'
  }
})

You can use inline content, html is similar to markdown here, except that it won't be parsed by marked.

You can even use it with a Vue component:

docute.init({
  landing: {
    markdown: '## counter\n {{ count }} ',
    component: {
      data() {
        return { count: 0 }
      }
    }
  }
})

Pages

You can also add more markdown files to display more pages. For example, adding chinese.md to your doc folder so that you got a new page at /#/chinese!

It supports directory too, just try adding a new file at language/chinese.md, then you'll get /#/language/chinese.

Note: file like about/README.md will be mapping to /#/about/, while the /#/about is for about.md.

Sidebar

To disable the sidebar globally, set it to false in config.js:

docute.init({
  sidebar: false
})

Or disable it for specific page:

---
sidebar: false
---
disable sidebar for this page.

There will be a toggle button for switching sidebar on and off, to hide this button:

docute.init({
  disableSidebarToggle: true
})

TOC

The TOC is coming from your markdown files, we parse markdown content and get headings (h2 to h5+) to group a nested TOC.

In sidebar we will show h2 to h4 headings by default, h5+ only will be visible when the main content scrolls there, you can update this by:

docute.init({
  // to show h2 to h3 only
  tocVisibleDepth: 3
})

It's true by default, to disable TOC entirely, set toc to false.

Custom TOC

If you don't want to use auto-generated toc, you can specify a custom toc to display on the sidebar:

docute.init({
  toc: `
- [Install](/install)
- [Guide](/guide)
  - [How to do A](/guide/how-to-do-a)
  - [How to do B](/guide/how-to-do-b)
`
})

// or a remote file:
docute.init({
  toc: './toc.md'
})

To make it eaiser to write, you can get toc content from an HTML element:

<script id="my-toc" type="text/x-markdown">
- [Install](/install)
- [Guide](/guide)
  - [How to do A](/guide/how-to-do-a)
  - [How to do B](/guide/how-to-do-b)
</script>
<script>
  docute.init({
    toc: document.getElementById('my-toc').textContent
  })
</script>

All the value types that are supported in landing option are supported here as well.

Besides, toc could also be a function which accepts $route as the only argument.

Currently custom toc is not supported in front-matter, however you can enable custom toc globally by setting `toc` in `docute.init()`, and set `toc` to `true` in front-matter when you need auto-generated toc for specific page.

Navbar

You may need a navbar as the entrance for the pages:

docute.init({
  nav: [
    // homepage
    {title: 'Home', path: '/'},
    // chinese doc
    {title: 'Chinese', path: '/language/chinese'}
  ]
})

The `path` could also be an external URL, it will work exactly like a normal hyperlink.

Besides this, as you've learned in Pages section, something like /language/chinese will fetch `/language/chinese.md`, if you want to fetch an external file just set the source option like `source: 'https://foo.com/bar.md'`

Custom source

A path like /language/chinese will make docute fetch /language/chinese.md, you can use source option to fetch another file:

docute.init({
  nav: [{
    title: 'Chinese',
    path: '/language/chinese',
    source: '/language/chinese-foo.md'
    // or even external file
    source: 'https://raw.githubusercontent.com/user/repo/master/file.md'
  }]
})

You may wonder why there's `home` option when we already have `source` option, that's because `source` option is only available for nav item, while `home` is always available no matter if you add `/` to nav.

If you use absolute path in `source` option, it will fetch files from the root of your domain, which means if your website is `http://example.com/docs`, it will fetch `http://example.com/foo.md` with `source: '/foo.md'`

Inline content

If you don't want it to fetch external files, use markdown option:

docute.init({
  nav: [{
    path: '/',
    markdown: '# Home'
  }]
})

Use with Vue component

Use the fetched content or inline content as the template of a Vue component:

docute.init({
  nav: [{
    path: '/',
    markdown: '## counter\n {{ count }}', // this will be parsed to html first
    component: {
      data() {
        return { count: 0 }
      }
    }
  }]
})

Icons

Icon short-hand
docute.init({
  // slug for your github repo
  repo: 'tj/co',
  // twitter username
  twitter: 'realDonaldTrump',
  // the link to source file of current page
  'edit-link': 'https://github.com/egoist/docute/blob/master/docs'
})

To fully customize the label, link or use custom svg icons, see below.

Custom Icons

The built-in svg icons: github twitter edit menu link search close info, which you can use in the icon attribute in icons option:

docute.init({
  icons: [{
    icon: 'github',
    label: 'Contribute on GitHub',
    link: 'https://github.com/owner/repo'
  }]
})

This example will have the same effect as using repo: 'owner/repo' but with custom label text here.

If you want to use your own SVG, you can set custom icon by providing the id of SVG symbol, SVG symbols is just a simple way to use inline SVG.

First, add it to your HTML file, which is index.html here:

<body>
  <div id="app"></div>
  <!-- you can add it everywhere outside #app -->
  <svg xmlns="http://www.w3.org/2000/svg" style="display:none">
    <symbol id="my-icon"  viewBox="0 0 22 22">
      <!-- all shapes like `<path>` go here -->
    </symbol>
    <!-- ... other symbols -->
  </svg>
</body>

Then use it in config.js:

docute.init({
  icons: [
    {
      label: 'Hovered!', // the text for tooltip
      svgId: 'my-icon', // the id of symbol
      link: 'http://blah.blah'
    }
  ]
})

You can also add svgClass property to use CSS to control the style of your icon

docute.init({
  icons: [
    {
      label: 'Hovered!',
      svgId: 'my-icon',
      svgClass: 'my-icon-class',
      link: 'http://blah.blah'
    }
  ]
})
/*
  To make consistent with default icon hover effect
  You can:
*/
.my-icon-class {
  fill: #ccc;
}
.my-icon-class:hover {
  fill: #333;
}

Check out index.html and config.js of this doc to see how we add a custom icon for weibo.com (the last icon in the header).

There're many resources for good free SVG icons, for example: bytesize-icons and simple icons.

Named Icons

You can have multiple sets of icons and use different set for different pages, just set the icons to a plain object:

docute.init({
  icons: {
    default: [{label: 'hello'}],
    chinese: [{label: '你好'}]
  }
})

Now, every page would use default icons, to use chinese icons just add front-matter in your page:

---
icons: chinese
---
hello world!

Dropdown menu

The item in navbar could also be a dropdown menu:

docute.init({
  nav: [
    {title: 'Languages', type: 'dropdown', items: [
      {title: 'Chinese', path: '/language/chinese'},
      {title: 'Japanese', path: '/language/japanese'}
    ]}
  ]
})
matchPath

Type: RegExp

To make dropdown menu display the actual title of active page, for example, show Chinese instead of Languages as the dropdown title when user enters relevant page, use matchPath. The target of matchPath is this.$route.path,eg: in https://example.com/en/get-started the target is /en/get-started

docute.init({
  nav: [{
    title: 'Languages', type: 'dropdown', items: [{
      path: '/en',
      title: 'English',
      // show `English` instead of `Languages` as the dropdown title
      // only match `/en` and `/en/xxx` not `/enxxx`
      matchPath: /^\/en[\/$]/
    }]
  }]
})

If no macthed item was found, it uses the title of dropdown menu instead.

label and sep

To have such dropdown menu:

label

You will need the label and sep helper:

docute.init({
  nav: [
    {
      title: 'Ecosystem', type: 'dropdown', items: [
        {type: 'label', title: 'Help'},
        // ... items
        {type: 'sep'} // separator
        // ... other items
      ]
    }
  ]
})

Named navbar

You can have multipage navbar and use different navbar for different pages.

If the nav option in config file is an array, it will be the only navbar across pages, but you can also set it to a plain object to have multiple named navbar:

docute.init({
  nav: {
    default: [{title: 'Home', path: '/'}],
    chinese: [{title: '首页', path: '/chinese'}]
  }
})

For now all pages will still use the default navbar, but you can switch this by setting front-matter in your markdown file:

---
nav: chinese
---
<!-- this page use the `chinese` navbar -->
你好世界!

Display Site Announcement

To display an announcement at the top of doc content:

docute.init({
  announcement: 'Welcome to the documentation of XXX!'
})

// Or with type:
docute.init({
  announcement: {
    type: 'warning', // warning | danger | success | primary
    html: 'This doc is out-dated!'
  }
})

// Even function
docute.init({
  announcement: function (route) {
    if (/\/chinese/.test(route.path)) {
      return 'Welcome, Chinese users!'
    }
    return 'Welcome, English users!'
  }
})

You can also set announcement in front-matter.

Markdown Settings

docute uses marked to parse markdown code,you can adjust marked's settings by:

docute.init({
  marked: {
    smartypants: true
    // ...
  }
})

Please refer to the official docs for details about its options.

debug

Set debug to true to enable vue-devtools:

docute.init({
  debug: true
})

routerMode

You can use hash or history mode for router:

  • hash (default): uses the hash portion of the URL (i.e. window.location.hash) to keep your UI in sync with the URL
  • history: uses the HTML5 history API (pushState, replaceState and the popstate event) to keep your UI in sync with the URL

hash mode suits all kinds of apps and browsers, especially useful when you can only deploy your app to a static web server like github pages.

To enable history mode, you will need to set a url for your website:

docute.init({
  url: docute.isDev ? location.origin : 'http://my-project.com/docs',
  routerMode: 'history'
})

Since all resources would be fetched from a path relative the url, the default url is . which is good for hash mode but will break in history mode.

In history mode it should be either a full url (starts with http) or an absolute path like /path/to/docs

Recipes

Themes

You can use some CSS to customize the look. Beside the gorgeous default theme now you're looking at, we provide the theme-github.css to make it look more similar to the color scheme that github uses. You can load the CSS after docute.css to apply it:

<link rel="stylesheet" href="https://unpkg.com/docute/dist/theme-github.css" />

To build another theme, you can check out https://github.com/egoist/docute/blob/master/src/css/theme-github.css for reference.

Page Title

The title in browser tab is the title you defined in nav property in config file, this value will also be used in navbar item.

However, you can use front-matter in markdown to override page title:

---
title: Home
---
For example, I want this page to be shown as 'English' in navbar but 'Home' in browser tab.

Code Highlight

docute uses Prism.js to highlight your code blocks, however only a few languages are supported by default, you can highlight other languages by:

<script src="/path/to/docute.js"></script>
<!-- add your language after the main docute bundle -->
<script src="https://unpkg.com/prismjs/components/prism-python.js"></script>

Now the python code will get highlighten!

def fib(n):
 a,b = 1,1
 for i in range(n-1):
  a,b = b,a+b
 return a
print fib(5)

The built-in languages are:

[ 'markup',
  'xml',
  'html',
  'mathml',
  'svg',
  'css',
  'clike',
  'javascript',
  'js',
  'json',
  'bash',
  'yaml',
  'markdown' ]

Visit https://unpkg.com/prismjs/components/ for all available programming languages.

Doc Helpers

CSS Helpers

CSS helpers make your docs even more readable.

p.tip

Show some tips in your doc:

<p class="tip">
  This is for beginners and pros, just enjoy!
</p>

And you get:

This is for beginners and pros, just enjoy!

Note that you can still use markdown inside the HTML!

p.warning

Similar to p.tip but it looks more serious:

<p class="warning">
  Do not do like this, do it that way please. If you still can't help doing such way, we will call your mom and order some pizza to let you know, you're in trouble!
</p>

And you get:

Do not do like this, do it that way please. If you still can't help doing such way, we will call you mom and order some pizza to let you know, you're in trouble!

p.danger
<p class="danger">
  This is really dangerouse, watch out!
</p>

And you get:

This is really dangerous, watch out!


If you don't like tips with background color, remove it by adding no-bg class name:

<p class="warning no-bg">
  How is it going?
</p>

And you get:

How is it going?

Buttons
<button class="docute-button">Button</button>

Button

<button class="docute-button docute-button-mini">Mini Button</button>

Mini Button

<button class="docute-button docute-button-primary">Primary Button</button>

Primary Button

<button class="docute-button docute-button-success">Success Button</button>

Success Button

<button class="docute-button docute-button-danger">Dangerous Button</button>

Dangerous Button

<button class="docute-button docute-button-warning">Warning Button</button>

Warning Button

Navigation links

Markdown links like [Go](#heading-slug) will navigate you to ?id=heading-slug in current page.

Markdown links like [Go](/page#heaing-slug) will navigate you to /page?id=heading-slug

In hash router mode, the path will automatically be prefixed with /#/ so that you don't need to add it yourself.

Alternatively, you can use HTML attributes directly:

<!-- Navigate to another page -->
<a router-link="/zh-cn/get-started?id=optional-id">
  Get Started!
</a>

<!-- Navigate to `?id=hello-world` in current page -->
<a jump-to-id="hello-world">
  Hello World
</a>

The element tag doesn't have to be a, anything meets your need like button is available here.

Global Variables

You can access following global variables if you need:

docute
docute.version // the version of docute
docute.store // Vuex store instance
docute.router // Vue router instance
docute.init // bootstrap app, you can only call it once
docute.isDev // if you're running docute as `localhost`

Vue // Vue constructor

Analytics

Google Analytics

Since a docute website is purely SPA, it's a bit different from using Google Analytics in traditional website, just add following markup to the end of your HTML file (within <body> but after loading docute.js):

<!-- Google Analytics -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
docute.router.afterEach(function (to) {
  ga('set', 'page', to.fullPath);
  ga('send', 'pageview');
});
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
<!-- End Google Analytics -->

Note that the UA-XXXXX-Y indicates your own track id.

Deploy to GitHub

There're three places to populate your docs:

  • ./docs folder
  • master branch
  • gh-pages branch

Just select it in repo's settings page after pushed files:

deploy

Deploy to VPS

Using nginx

Try following nginx conf:

server {
  listen 80;
  server_name  your.domain.com;

  location / {
    alias /path/to/dir/of/docs;
    index index.html;
  }
}

Or if you want to serve it at sub path like /docs, try:

server {
  listen 80;
  server_name  your.domain.com;

  location /docs {
    alias /path/to/dir/of/docs;
    index index.html;
  }
}

FAQ

Is it like gitbook?

Yes and No. Yes is because they are both for writing documentation and they have the similar UI, but docute does not require you to generate static html files, and have less configurations while still keeping the most useful features for writing elegant docs.

docute is also built by what I've learned from using gitbook/hexo/jekyll in the past years.

What's wrong with build before publish?

It's not wrong, but we don't always need it that way, sometimes a simple Single Page Application is good enough for our docs while we can get rid of some verbose steps to publish docs. In fact, we're also looking forward to supporting this feature and server-side rendering at some point, I know many SEO guys and girls would like this even if Google already supports retrieving data from SPA website.

How to run code inside markdown?

Since dynamically added script tags won't be executed by browser, you can use docute-iframe plugin to run specified code blocks in an iframe.

For docs about plugins please head to plugins.