## File: README.md

Docsify turns one or more Markdown files into a Website, with no build process required.

## Features

- No statically built HTML files
- Simple and lightweight
- Smart full-text search plugin
- Multiple themes
- Useful plugin API
- Emoji support

## Quick Start

Get going fast by using a static web server or GitHub Pages with this ready-to-use [Docsify Template](https://github.com/docsifyjs/docsify-template), review the [quick start tutorial](https://docsify.js.org/#/quickstart) or jump right into a CodeSandbox example site with the button below.

[](https://sandbox.docsifyjs.org/)

## Showcase

A large collection of showcase projects are included in [awesome-docsify](https://github.com/docsifyjs/awesome-docsify#showcase).

## Links

- [Documentation](https://docsify.js.org)
- [Docsify CLI (Command Line Interface)](https://github.com/docsifyjs/docsify-cli)
- CDN: [UNPKG](https://unpkg.com/docsify/) | [jsDelivr](https://cdn.jsdelivr.net/npm/docsify/) | [cdnjs](https://cdnjs.com/libraries/docsify)
- [`develop` branch preview](https://docsify-preview.vercel.app/)
- [Awesome docsify](https://github.com/docsifyjs/awesome-docsify)
- [Community chat](https://discord.gg/3NwKFyR)

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md).

## Backers

Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/docsify/contribute)]

[](https://opencollective.com/docsify#backers)

## Sponsors

Thank you for supporting this project! ❤️ [[Become a sponsor](https://opencollective.com/docsify/contribute)]



## Contributors

This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].

[](https://github.com/docsifyjs/docsify/graphs/contributors)

## License

[MIT](LICENSE)

---

## File: docs/_media/example-with-yaml.md

---
author: John Smith
date: 2020-1-1
---

> This is from the `example-with-yaml.md`

---

## File: docs/_coverpage.md

# docsify <small>5.0.0</small> :id=docsify

> A magical documentation site generator

- Simple and lightweight
- No statically built HTML files
- Multiple themes

[Get Started](#docsify)
[GitHub](https://github.com/docsifyjs/docsify/)

---

## File: docs/_navbar.md

- Translations

  - [English](/)
  - [简体中文](/zh-cn/)

---

## File: docs/_sidebar.md

- Getting started

  - [Quick start](quickstart.md)
  - [Adding pages](adding-pages.md)
  - [Cover page](cover.md)
  - [Custom navbar](custom-navbar.md)

- Customization

  - [Configuration](configuration.md)
  - [Themes](themes.md)
  - [List of Plugins](plugins.md)
  - [Write a Plugin](write-a-plugin.md)
  - [Markdown configuration](markdown.md)
  - [Language highlighting](language-highlight.md)
  - [Emoji](emoji.md)

- Guide

  - [Deploy](deploy.md)
  - [Helpers](helpers.md)
  - [Vue compatibility](vue.md)
  - [CDN](cdn.md)
  - [Offline Mode (PWA)](pwa.md)
  - [Embed Files](embed-files.md)
  - [UI Kit](ui-kit.md)

- Upgrading

  - [v4 to v5](v5-upgrade.md)

* [Awesome docsify](awesome.md)
* [Changelog](changelog.md)

---

## File: docs/adding-pages.md

# Adding pages

If you need more pages, you can simply create more markdown files in your docsify directory. If you create a file named `guide.md`, then it is accessible via `/#/guide`.

For example, the directory structure is as follows:

```text
.
└── docs
    ├── README.md
    ├── guide.md
    └── zh-cn
        ├── README.md
        └── guide.md
```

Matching routes

```text
docs/README.md        => http://domain.com
docs/guide.md         => http://domain.com/#/guide
docs/zh-cn/README.md  => http://domain.com/#/zh-cn/
docs/zh-cn/guide.md   => http://domain.com/#/zh-cn/guide
```

## Sidebar

In order to have a sidebar, you can create your own `_sidebar.md` (see [this documentation's sidebar](https://github.com/docsifyjs/docsify/blob/main/docs/_sidebar.md) for an example):

First, you need to set `loadSidebar` to **true**. Details are available in the [configuration paragraph](configuration#loadsidebar).

```html


<script>
  window.$docsify = {
    loadSidebar: true,
  };
</script>
<script src="//cdn.jsdelivr.net/npm/docsify@5/dist/docsify.min.js"></script>
```

Create the `_sidebar.md`:

```markdown


- [Home](/)
- [Page 1](page-1.md)
```

To create section headers:

```markdown


- Section Header 1

  - [Home](/)
  - [Page 1](page-1.md)

- Section Header 2

  - [Page 2](page-2.md)
  - [Page 3](page-3.md)
```

You need to create a `.nojekyll` in `./docs` to prevent GitHub Pages from ignoring files that begin with an underscore.

> [!IMPORTANT] Docsify only looks for `_sidebar.md` in the current folder, and uses that, otherwise it falls back to the one configured using `window.$docsify.loadSidebar` config.

Example file structure:

```text
└── docs/
    ├── _sidebar.md
    ├── index.md
    ├── getting-started.md
    └── running-services.md
```

## Nested Sidebars

You may want the sidebar to update after navigation to reflect the current directory. This can be done by adding a `_sidebar.md` file to each folder.

`_sidebar.md` is loaded from each level directory. If the current directory doesn't have `_sidebar.md`, it will fall back to the parent directory. If, for example, the current path is `/guide/quick-start`, the `_sidebar.md` will be loaded from `/guide/_sidebar.md`.

You can specify `alias` to avoid unnecessary fallback.

```html
<script>
  window.$docsify = {
    loadSidebar: true,
    alias: {
      '/.*/_sidebar.md': '/_sidebar.md',
    },
  };
</script>
```

> [!IMPORTANT] You can create a `README.md` file in a subdirectory to use it as the landing page for the route.

## Set Page Titles from Sidebar Selection

A page's `title` tag is generated from the _selected_ sidebar item name. For better SEO, you can customize the title by specifying a string after the filename.

```markdown


- [Home](/)
- [Guide](guide.md 'The greatest guide in the world')
```

## Table of Contents

Once you've created `_sidebar.md`, the sidebar content is automatically generated based on the headers in the markdown files.

A custom sidebar can also automatically generate a table of contents by setting a `subMaxLevel`, compare [subMaxLevel configuration](configuration#submaxlevel).

```html


<script>
  window.$docsify = {
    loadSidebar: true,
    subMaxLevel: 2,
  };
</script>
<script src="//cdn.jsdelivr.net/npm/docsify@5/dist/docsify.min.js"></script>
```

## Ignoring Subheaders

When `subMaxLevel` is set, each header is automatically added to the table of contents by default. If you want to ignore a specific header, add `` to it.

```markdown
# Getting Started

## Header 

This header won't appear in the sidebar table of contents.
```

To ignore all headers on a specific page, you can use `` on the first header of the page.

```markdown
# Getting Started 

## Header

This header won't appear in the sidebar table of contents.
```

Both `` and `` will not be rendered on the page when used.

And the `{docsify-ignore}` and `{docsify-ignore-all}` can do the samething as well.

---

## File: docs/cdn.md

# CDN

The docsify [npm package](https://www.npmjs.com/package/docsify) is auto-published to CDNs with each release. The contents can be viewed on each CDN.

Docsify recommends [jsDelivr](//cdn.jsdelivr.net) as its preferred CDN:

- https://cdn.jsdelivr.net/npm/docsify/

Other CDNs are available and may be required in locations where jsDelivr is not available:

- https://cdnjs.com/libraries/docsify
- https://unpkg.com/browse/docsify/
- https://www.bootcdn.cn/docsify/

## Specifying versions

Note the `@` version lock in the CDN URLs below. This allows specifying the latest major, minor, patch, or specific [semver](https://semver.org) version number.

- MAJOR versions include breaking changes
  `1.0.0` → `2.0.0`
- MINOR versions include non-breaking new functionality
  `1.0.0` → `1.1.0`
- PATCH versions include non-breaking bug fixes
  `1.0.0` → `1.0.1`

Uncompressed resources are available by omitting the `.min` from the filename.

## Latest "major" version

Specifying the latest major version allows your site to receive all non-breaking enhancements ("minor" updates) and bug fixes ("patch" updates) as they are released. This is good option for those who prefer a zero-maintenance way of keeping their site up to date with minimal risk as new versions are published.

> [!TIP] When a new major version is released, you will need to manually update the major version number after the `@` symbol in your CDN URLs.


```html

<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@5/dist/themes/addons/vue.min.css" />


<script src="//cdn.jsdelivr.net/npm/docsify@5/dist/docsify.min.js"></script>
```

## Specific version

Specifying an exact version prevents any future updates from affecting your site. This is good option for those who prefer to manually update their resources as new versions are published.

> [!TIP] When a new version is released, you will need to manually update the version number after the `@` symbol in your CDN URLs.


```html

<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@5.0.0/dist/themes/addons/vue.min.css" />


<script src="//cdn.jsdelivr.net/npm/docsify@5.0.0/dist/docsify.min.js"></script>
```

---

## File: docs/configuration.md

# Configuration

You can configure Docsify by defining `window.$docsify` as an object:

```html
<script>
  window.$docsify = {
    repo: 'docsifyjs/docsify',
    maxLevel: 3,
    coverpage: true,
  };
</script>
```

The config can also be defined as a function, in which case the first argument is the Docsify `vm` instance. The function should return a config object. This can be useful for referencing `vm` in places like the markdown configuration:

```html
<script>
  window.$docsify = function (vm) {
    return {
      markdown: {
        renderer: {
          code(code, lang) {
            // ... use `vm` ...
          },
        },
      },
    };
  };
</script>
```

## alias

- Type: `Object`

Set the route alias. You can freely manage routing rules. Supports RegExp.
Do note that order matters! If a route can be matched by multiple aliases, the one you declared first takes precedence.

```js
window.$docsify = {
  alias: {
    '/foo/(.*)': '/bar/$1', // supports regexp
    '/zh-cn/changelog': '/changelog',
    '/changelog':
      'https://raw.githubusercontent.com/docsifyjs/docsify/main/CHANGELOG',

    // You may need this if you use routerMode:'history'.
    '/.*/_sidebar.md': '/_sidebar.md', // See #301
  },
};
```

> **Note** If you change [`routerMode`](#routermode) to `'history'`, you may
> want to configure an alias for your `_sidebar.md` and `_navbar.md` files.

## auto2top

- Type: `Boolean`
- Default: `false`

Scrolls to the top of the screen when the route is changed.

```js
window.$docsify = {
  auto2top: true,
};
```

## autoHeader

- Type: `Boolean`
- Default: `false`

If `loadSidebar` and `autoHeader` are both enabled, for each link in `_sidebar.md`, prepend a header to the page before converting it to HTML — but only if the page does not already contain an H1 heading.

For more details, see [#78](https://github.com/docsifyjs/docsify/issues/78).

```js
window.$docsify = {
  loadSidebar: true,
  autoHeader: true,
};
```

## basePath

- Type: `String`

Base path of the website. You can set it to another directory or another domain name.

```js
window.$docsify = {
  basePath: '/path/',

  // Load the files from another site
  basePath: 'https://docsify.js.org/',

  // Even can load files from other repo
  basePath:
    'https://raw.githubusercontent.com/ryanmcdermott/clean-code-javascript/master/',
};
```

## catchPluginErrors

- Type: `Boolean`
- Default: `true`

Determines if Docsify should handle uncaught _synchronous_ plugin errors automatically. This can prevent plugin errors from affecting docsify's ability to properly render live site content.

## cornerExternalLinkTarget

- Type: `String`
- Default: `'_blank'`

Target to open external link at the top right corner. Default `'_blank'` (new window/tab)

```js
window.$docsify = {
  cornerExternalLinkTarget: '_self', // default: '_blank'
};
```

## coverpage

- Type: `Boolean|String|String[]|Object`
- Default: `false`

Activate the [cover feature](cover.md). If true, it will load from `_coverpage.md`.

```js
window.$docsify = {
  coverpage: true,

  // Custom file name
  coverpage: 'cover.md',

  // multiple covers
  coverpage: ['/', '/zh-cn/'],

  // multiple covers and custom file name
  coverpage: {
    '/': 'cover.md',
    '/zh-cn/': 'cover.md',
  },
};
```

## el

- Type: `String`
- Default: `'#app'`

The DOM element to be mounted on initialization. It can be a CSS selector string or an actual [HTMLElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement).

```js
window.$docsify = {
  el: '#app',
};
```

## executeScript

- Type: `Boolean`
- Default: `null`

Execute the script on the page. Only parses the first script tag ([demo](themes)). If Vue is detected, this is `true` by default.

```js
window.$docsify = {
  executeScript: true,
};
```

```markdown
## This is test

<script>
  console.log(2333)
</script>
```

Note that if you are running an external script, e.g. an embedded jsfiddle demo, make sure to include the [external-script](plugins.md?id=external-script) plugin.

## ext

- Type: `String`
- Default: `'.md'`

Request file extension.

```js
window.$docsify = {
  ext: '.md',
};
```

## externalLinkRel

- Type: `String`
- Default: `'noopener'`

Default `'noopener'` (no opener) prevents the newly opened external page (when [externalLinkTarget](#externallinktarget) is `'_blank'`) from having the ability to control our page. No `rel` is set when it's not `'_blank'`. See [this post](https://mathiasbynens.github.io/rel-noopener/) for more information about why you may want to use this option.

```js
window.$docsify = {
  externalLinkRel: '', // default: 'noopener'
};
```

## externalLinkTarget

- Type: `String`
- Default: `'_blank'`

Target to open external links inside the markdown. Default `'_blank'` (new window/tab)

```js
window.$docsify = {
  externalLinkTarget: '_self', // default: '_blank'
};
```

## fallbackLanguages

- Type: `Array<string>`

List of languages that will fallback to the default language when a page is requested and it doesn't exist for the given locale.

Example:

- try to fetch the page of `/de/overview`. If this page exists, it'll be displayed.
- then try to fetch the default page `/overview` (depending on the default language). If this page exists, it'll be displayed.
- then display the 404 page.

```js
window.$docsify = {
  fallbackLanguages: ['fr', 'de'],
};
```

## fallbackDefaultLanguage

- Type: `String`
- Default: `''`

When a page is requested and it doesn't exist for the given locale, Docsify will fallback to the language specified by this option.

For example, in the scenario described above, if `/de/overview` does not exist and `fallbackDefaultLanguage` is configured as `zh-cn`, Docsify will fetch `/zh-cn/overview` instead of `/overview`.

```js
window.$docsify = {
  fallbackLanguages: ['fr', 'de'],
  fallbackDefaultLanguage: 'zh-cn', // default: ''
};
```

## formatUpdated

- Type: `String|Function`

We can display the file update date through **{docsify-updated}** variable. And format it by `formatUpdated`.
See https://github.com/lukeed/tinydate#patterns

```js
window.$docsify = {
  formatUpdated: '{MM}/{DD} {HH}:{mm}',

  formatUpdated(time) {
    // ...

    return time;
  },
};
```

## pageTitleFormatter

- Type: `Function`
- Default: `null`

Optional function to customize how the site `name` is used when composing the document title. If provided, Docsify will call this function with the configured `name` (which may contain HTML) and use the returned string as the title portion for the site name — Docsify will not automatically strip HTML or otherwise modify the value. If not provided, Docsify falls back to the default behavior of stripping HTML tags from `name`.

Basic example — strip HTML and trim (equivalent to Docsify's default behavior):

```js
window.$docsify = {
  name: 'My Site',
  pageTitleFormatter(name) {
    return name ? name.replace(/<[^>]+>/g, '').trim() : '';
  },
};
```

## hideSidebar

- Type : `Boolean`
- Default: `false`

This option will completely hide your sidebar and won't render any content on the side.

```js
window.$docsify = {
  hideSidebar: true,
};
```

## homepage

- Type: `String`
- Default: `'README.md'`

`README.md` in your docs folder will be treated as the homepage for your website, but sometimes you may need to serve another file as your homepage.

```js
window.$docsify = {
  // Change to /home.md
  homepage: 'home.md',

  // Or use the readme in your repo
  homepage:
    'https://raw.githubusercontent.com/docsifyjs/docsify/main/README.md',
};
```

## keyBindings

- Type: `Boolean|Object`
- Default: `Object`
  - <kbd>\\</kbd> Toggle the sidebar menu
  - <kbd>/</kbd> Focus on [search](plugins#full-text-search) field. Also supports <kbd>alt</kbd>&nbsp;/&nbsp;<kbd>ctrl</kbd>&nbsp;+&nbsp;<kbd>k</kbd>.

Binds key combination(s) to a custom callback function.

Key `bindings` are defined as case insensitive string values separated by `+`. Modifier key values include `alt`, `ctrl`, `meta`, and `shift`. Non-modifier key values should match the keyboard event's [key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) or [code](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code) value.

The `callback` function receive a [keydown event](https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event) as an argument.

> [!IMPORTANT] Let site visitors know your custom key bindings are available! If a binding is associated with a DOM element, consider inserting a `<kbd>` element as a visual cue (e.g., <kbd>alt</kbd> + <kbd>a</kbd>) or adding [title](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title) and [aria-keyshortcuts](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-keyshortcuts) attributes for hover/focus hints.

```js
window.$docsify = {
  keyBindings: {
    // Custom key binding
    myCustomBinding: {
      bindings: ['alt+a', 'shift+a'],
      callback(event) {
        alert('Hello, World!');
      },
    },
  },
};
```

Key bindings can be disabled entirely or individually by setting the binding configuration to `false`.

```js
window.$docsify = {
  // Disable all key bindings
  keyBindings: false,
};
```

```js
window.$docsify = {
  keyBindings: {
    // Disable individual key bindings
    focusSearch: false,
    toggleSidebar: false,
  },
};
```

## loadNavbar

- Type: `Boolean|String`
- Default: `false`

Loads navbar from the Markdown file `_navbar.md` if **true**, else loads it from the path specified.

```js
window.$docsify = {
  // load from _navbar.md
  loadNavbar: true,

  // load from nav.md
  loadNavbar: 'nav.md',
};
```

## loadSidebar

- Type: `Boolean|String`
- Default: `false`

Loads sidebar from the Markdown file `_sidebar.md` if **true**, else loads it from the path specified.

```js
window.$docsify = {
  // load from _sidebar.md
  loadSidebar: true,

  // load from summary.md
  loadSidebar: 'summary.md',
};
```

## logo

- Type: `String`

Website logo as it appears in the sidebar. You can resize it using CSS.

> [!IMPORTANT] Logo will only be visible if `name` prop is also set. See [name](#name) configuration.

```js
window.$docsify = {
  logo: '/_media/icon.svg',
};
```

## markdown

- Type: `Function`

See [Markdown configuration](markdown.md).

```js
window.$docsify = {
  // object
  markdown: {
    smartypants: true,
    renderer: {
      link() {
        // ...
      },
    },
  },

  // function
  markdown(marked, renderer) {
    // ...
    return marked;
  },
};
```

## maxLevel

- Type: `Number`
- Default: `6`

Maximum Table of content level.

```js
window.$docsify = {
  maxLevel: 4,
};
```

## mergeNavbar

- Type: `Boolean`
- Default: `false`

Navbar will be merged with the sidebar on smaller screens.

```js
window.$docsify = {
  mergeNavbar: true,
};
```

## name

- Type: `Boolean|String`

Website name as it appears in the sidebar.

```js
window.$docsify = {
  name: 'docsify',
};
```

The name field can also contain custom HTML for easier customization:

```js
window.$docsify = {
  name: 'docsify',
};
```

If `true`, the website name will be inferred from the document's `<title>` tag.

```js
window.$docsify = {
  name: true,
};
```

If `false` or empty, no name will be displayed.

```js
window.$docsify = {
  name: false,
};
```

## nameLink

- Type: `String`
- Default: `'window.location.pathname'`

The URL that the website `name` links to.

```js
window.$docsify = {
  nameLink: '/',

  // For each route
  nameLink: {
    '/zh-cn/': '#/zh-cn/',
    '/': '#/',
  },
};
```

## nativeEmoji

- Type: `Boolean`
- Default: `false`

Render emoji shorthand codes using GitHub-style emoji images or native emoji characters.

```js
window.$docsify = {
  nativeEmoji: true,
};
```

```markdown
:smile:
:partying_face:
:joy:
:+1:
:-1:
```

GitHub-style images when `false`:

<output data-lang="output">
  
  
  
  
  
</output>

Native characters when `true`:

<output data-lang="output">
  😄︎
  🥳︎
  😂︎
  👍︎
  👎︎
</output>

To render shorthand codes as text, replace `:` characters with the `&colon;` HTML entity.

```markdown
&colon;100&colon;
```

<output data-lang="output">

&colon;100&colon;

</output>

## noCompileLinks

- Type: `Array<string>`

Sometimes we do not want docsify to handle our links. See [#203](https://github.com/docsifyjs/docsify/issues/203). We can skip compiling of certain links by specifying an array of strings. Each string is converted into to a regular expression (`RegExp`) and the _whole_ href of a link is matched against it.

```js
window.$docsify = {
  noCompileLinks: ['/foo', '/bar/.*'],
};
```

## noEmoji

- Type: `Boolean`
- Default: `false`

Disabled emoji parsing and render all emoji shorthand as text.

```js
window.$docsify = {
  noEmoji: true,
};
```

```markdown
:100:
```

<output data-lang="output">

&colon;100&colon;

</output>

To disable emoji parsing of individual shorthand codes, replace `:` characters with the `&colon;` HTML entity.

```markdown
:100:

&colon;100&colon;
```

<output data-lang="output">

:100:

&colon;100&colon;

</output>

## notFoundPage

- Type: `Boolean|String|Object`
- Default: `false`

Display default "404 - Not Found" message:

```js
window.$docsify = {
  notFoundPage: false,
};
```

Load the `_404.md` file:

```js
window.$docsify = {
  notFoundPage: true,
};
```

Load the customized path of the 404 page:

```js
window.$docsify = {
  notFoundPage: 'my404.md',
};
```

Load the right 404 page according to the localization:

```js
window.$docsify = {
  notFoundPage: {
    '/': '_404.md',
    '/de': 'de/_404.md',
  },
};
```

> Note: The options for fallbackLanguages don't work with the `notFoundPage` options.

## onlyCover

- Type: `Boolean`
- Default: `false`

Only coverpage is loaded when visiting the home page.

```js
window.$docsify = {
  onlyCover: false,
};
```

## plugins

See [Plugins](./plugins.md).

## relativePath

- Type: `Boolean`
- Default: `false`

If **true**, links are relative to the current context.

For example, the directory structure is as follows:

```text
.
└── docs
    ├── README.md
    ├── guide.md
    └── zh-cn
        ├── README.md
        ├── guide.md
        └── config
            └── example.md
```

With relative path **enabled** and current URL `http://domain.com/zh-cn/README`, given links will resolve to:

```text
guide.md              => http://domain.com/zh-cn/guide
config/example.md     => http://domain.com/zh-cn/config/example
../README.md          => http://domain.com/README
/README.md            => http://domain.com/README
```

```js
window.$docsify = {
  // Relative path enabled
  relativePath: true,

  // Relative path disabled (default value)
  relativePath: false,
};
```

## repo

- Type: `String`

Configure the repository url, or a string of `username/repo`, to add the [GitHub Corner](http://tholman.com/github-corners/) widget in the top right corner of the site.

```js
window.$docsify = {
  repo: 'docsifyjs/docsify',
  // or
  repo: 'https://github.com/docsifyjs/docsify/',
};
```

If undefined or empty, no GitHub corner will be displayed.

## requestHeaders

- Type: `Object`

Set the request resource headers.

```js
window.$docsify = {
  requestHeaders: {
    'x-token': 'xxx',
  },
};
```

Such as setting the cache

```js
window.$docsify = {
  requestHeaders: {
    'cache-control': 'max-age=600',
  },
};
```

## routerMode

Configure the URL format that the paths of your site will use.

- Type: `String`
- Default: `'hash'`

```js
window.$docsify = {
  routerMode: 'history', // default: 'hash'
};
```

For statically-deployed sites (f.e. on GitHub Pages) hash-based routing is
simpler to set up. For websites that can re-write URLs, the history-based format
is better (especially for search-engine optimization, hash-based routing is not
so search-engine friendly)

Hash-based routing means all URL paths will be prefixed with `/#/` in the
address bar. This is a trick that allows the site to load `/index.html`, then it
uses the path that follows the `#` to determine what markdown files to load. For
example, a complete hash-based URL may look like this:
`https://example.com/#/path/to/page`. The browser will actually load
`https://example.com` (assuming your static server serves
`index.html` by default, as most do), and then the Docsify JavaScript code will
look at the `/#/...` and determine the markdown file to load and render.
Additionally, when clicking on a link, the Docsify router will change the
content after the hash dynamically. The value of `location.pathname` will still be
`/` no matter what. The parts of a hash path are _not_ sent to the server when
visiting such a URL in a browser.

On the other hand, history-based routing means the Docsify JavaScript will use
the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)
to dynamically change the URL without using a `#`. This means that all URLs will
be considered "real" by search engines, and the full path will be sent to the
server when visiting the URL in your browser. For example, a URL may look like
`https://example.com/path/to/page`. The browser will try to load that full URL
directly from the server, not just `https://example.com`. The upside of this is
that these types of URLs are much more friendly for search engines, and can be
indexed (yay!). The downside, however, is that your server, or the place where
you host your site files, has to be able to handle these URLs. Various static
website hosting services allow "rewrite rules" to be configured, such that a
server can be configured to always send back `/index.html` no matter what path
is visited. The value of `location.pathname` will show `/path/to/page`, because
it was actually sent to the server.

TLDR: start with `hash` routing (the default). If you feel adventurous, learn
how to configure a server, then switch to `history` mode for better experience
without the `#` in the URL and SEO optimization.

> **Note** If you use `routerMode: 'history'`, you may want to add an
> [`alias`](#alias) to make your `_sidebar.md` and `_navbar.md` files always be
> loaded no matter which path is being visited.
>
> ```js
> window.$docsify = {
>   routerMode: 'history',
>   alias: {
>     '/.*/_sidebar.md': '/_sidebar.md',
>     '/.*/_navbar.md': '/_navbar.md',
>   },
> };
> ```

## routes

- Type: `Object`

Define "virtual" routes that can provide content dynamically. A route is a map between the expected path, to either a string or a function. If the mapped value is a string, it is treated as markdown and parsed accordingly. If it is a function, it is expected to return markdown content.

A route function receives up to three parameters:

1. `route` - the path of the route that was requested (e.g. `/bar/baz`)
2. `matched` - the [`RegExpMatchArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match) that was matched by the route (e.g. for `/bar/(.+)`, you get `['/bar/baz', 'baz']`)
3. `next` - this is a callback that you may call when your route function is async

Do note that order matters! Routes are matched the same order you declare them in, which means that in cases where you have overlapping routes, you might want to list the more specific ones first.

```js
window.$docsify = {
  routes: {
    // Basic match w/ return string
    '/foo': '# Custom Markdown',

    // RegEx match w/ synchronous function
    '/bar/(.*)'(route, matched) {
      return '# Custom Markdown';
    },

    // RegEx match w/ asynchronous function
    '/baz/(.*)'(route, matched, next) {
      fetch('/api/users?id=12345')
        .then(response => {
          next('# Custom Markdown');
        })
        .catch(err => {
          // Handle error...
        });
    },
  },
};
```

Other than strings, route functions can return a falsy value (`null` \ `undefined`) to indicate that they ignore the current request:

```js
window.$docsify = {
  routes: {
    // accepts everything other than dogs (synchronous)
    '/pets/(.+)'(route, matched) {
      if (matched[0] === 'dogs') {
        return null;
      } else {
        return 'I like all pets but dogs';
      }
    }

    // accepts everything other than cats (asynchronous)
    '/pets/(.*)'(route, matched, next) {
      if (matched[0] === 'cats') {
        next();
      } else {
        // Async task(s)...
        next('I like all pets but cats');
      }
    }
  }
}
```

Finally, if you have a specific path that has a real markdown file (and therefore should not be matched by your route), you can opt it out by returning an explicit `false` value:

```js
window.$docsify = {
  routes: {
    // if you look up /pets/cats, docsify will skip all routes and look for "pets/cats.md"
    '/pets/cats'(route, matched) {
      return false;
    }

    // but any other pet should generate dynamic content right here
    '/pets/(.+)'(route, matched) {
      const pet = matched[0];
      return `your pet is ${pet} (but not a cat)`;
    }
  }
}
```

## skipLink

- Type: `Boolean|String|Object`
- Default: `'Skip to main content'`

Determines if/how the site's [skip navigation link](https://webaim.org/techniques/skipnav/) will be rendered.

```js
// Render skip link for all routes
window.$docsify = {
  skipLink: 'Skip to content',
};
```

```js
// Render localized skip links based on route paths
window.$docsify = {
  skipLink: {
    '/es/': 'Saltar al contenido principal',
    '/de-de/': 'Ga naar de hoofdinhoud',
    '/ru-ru/': 'Перейти к основному содержанию',
    '/zh-cn/': '跳到主要内容',
  },
};
```

```js
// Do not render skip link
window.$docsify = {
  skipLink: false,
};
```

```js
// Use default
window.$docsify = {
  skipLink: true, // "Skip to main content"
};
```

## subMaxLevel

- Type: `Number`
- Default: `0`

Add table of contents (TOC) in custom sidebar.

```js
window.$docsify = {
  subMaxLevel: 2,
};
```

If you have a link to the homepage in the sidebar and want it to be shown as active when accessing the root url, make sure to update your sidebar accordingly:

```markdown
- Sidebar
  - [Home](/)
  - [Another page](another.md)
```

For more details, see [#1131](https://github.com/docsifyjs/docsify/issues/1131).

## themeColor ⚠️ :id=themecolor

> [!IMPORTANT] Deprecated as of v5. Use the `--theme-color` [theme property](themes#theme-properties) to [customize](themes#customization) your theme color.

- Type: `String`

Customize the theme color.

```js
window.$docsify = {
  themeColor: '#3F51B5',
};
```

## topMargin ⚠️ :id=topmargin

> [!IMPORTANT] Deprecated as of v5. Use the `--scroll-padding-top` [theme property](themes#theme-properties) to specify a scroll margin when using a sticky navbar.

- Type: `Number|String`
- Default: `0`

Adds scroll padding to the top of the viewport. This is useful when you have added a sticky or "fixed" element and would like auto scrolling to align with the bottom of your element.

```js
window.$docsify = {
  topMargin: 90, // 90, '90px', '2rem', etc.
};
```

## vueComponents

- Type: `Object`

Creates and registers global [Vue](https://vuejs.org/guide/essentials/component-basics.html). Components are specified using the component name as the key with an object containing Vue options as the value. Component `data` is unique for each instance and will not persist as users navigate the site.

```js
window.$docsify = {
  vueComponents: {
    'button-counter': {
      template: `
        
          You clicked me {{ count }} times
        
      `,
      data() {
        return {
          count: 0,
        };
      },
    },
  },
};
```

```markdown

```

<output data-lang="output">
  
</output>

## vueGlobalOptions

- Type: `Object`

Specifies global Vue options for use with Vue content not explicitly mounted with [vueMounts](#mounting-dom-elements), [vueComponents](#components), or a [markdown script](#markdown-script). Changes to global `data` will persist and be reflected anywhere global references are used.

```js
window.$docsify = {
  vueGlobalOptions: {
    data() {
      return {
        count: 0,
      };
    },
  },
};
```

```markdown

  -
  {{ count }}
  +

```

<output data-lang="output">
  
    -
    {{ count }}
    +
  
</output>

## vueMounts

- Type: `Object`

Specifies DOM elements to mount as Vue instances and their associated options. Mount elements are specified using a [CSS selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors) as the key with an object containing Vue options as their value. Docsify will mount the first matching element in the main content area each time a new page is loaded. Mount element `data` is unique for each instance and will not persist as users navigate the site.

```js
window.$docsify = {
  vueMounts: {
    '#counter': {
      data() {
        return {
          count: 0,
        };
      },
    },
  },
};
```

```markdown

  -
  {{ count }}
  +

```

<output id="counter">
  -
  {{ count }}
  +
</output>

---

## File: docs/cover.md

# Cover

Activate the cover feature by setting `coverpage` to **true**. See [coverpage configuration](configuration#coverpage).

## Basic usage

Set `coverpage` to **true**, and create a `_coverpage.md`:

```js
window.$docsify = {
  coverpage: true,
};
```

```markdown




# docsify

> A magical documentation site generator

- Simple and lightweight
- No statically built HTML files
- Multiple themes

[GitHub](https://github.com/docsifyjs/docsify/)
[Get Started](#docsify)
```

## Customization

The cover page can be customized using [theme properties](themes#theme-properties):


```css
:root {
  --cover-bg         : url('path/to/image.png');
  --cover-bg-overlay : rgba(0, 0, 0, 0.5);
  --cover-color      : #fff;
  --cover-title-color: var(--theme-color);
  --cover-title-font : 600 var(--font-size-xxxl) var(--font-family);
}
```

Alternatively, a background color or image can be specified in the cover page markdown.

```markdown



```

```markdown



```

## Coverpage as homepage

Normally, the coverpage and the homepage appear at the same time. Of course, you can also separate the coverpage by [`onlyCover`](configuration#onlycover) option.

## Multiple covers

If your docs site is in more than one language, it may be useful to set multiple covers.

For example, your docs structure is like this

```text
.
└── docs
    ├── README.md
    ├── guide.md
    ├── _coverpage.md
    └── zh-cn
        ├── README.md
        └── guide.md
        └── _coverpage.md
```

Now, you can set

```js
window.$docsify = {
  coverpage: ['/', '/zh-cn/'],
};
```

Or a special file name

```js
window.$docsify = {
  coverpage: {
    '/': 'cover.md',
    '/zh-cn/': 'cover.md',
  },
};
```