Enhance your Docsify experience with your own plugin

Corentin Le Berre
abbeal’s tech blog
5 min readApr 4, 2023

--

Docsify is a popular and lightweight documentation generator that allows you to easily create beautiful, intuitive documentation sites based on your markdown documentation. It includes features like a search function, a table of contents, and the ability to customize the look and feel of the site using templates and custom CSS. Thanks to that it’s a popular choice for open-source documentation sites and other purposes.

If you want to extend Docsify’s features, you can use community plugins or create your own Docsify plugin.

In this post I’ll guide you to create your first Docsify plugin and deploy it to NPM.

Requirements : Node 16

To simplify the process, I’ve made a preconfigured workspace. To use it just clone the repository below and use it as a starting point for your own plugin 👇

npx degit corentinleberre/create-docsify-plugin my-plugin
cd my-plugin

Structure of the project

Here is the structure of this template. The code is stored in the src folder.

📦create-docsify-plugin
┣ 📂src
┃ ┣ 📂plugin
┃ ┃ ┣ 📜main.js
┃ ┃ ┗ 📜my-plugin.js
┃ ┣ 📂test
┃ ┃ ┗ 📜my-plugin.spec.js
┃ ┣ 📜README.md
┃ ┗ 📜index.html
┣ 📜package.json
┣ 📜playwright.config.ts
┣ 📜README.md
┗ 📜vite-config.js

We use Vite as a dev server. This allows you to take advantage of hot reloading during development and easily build and minify code with Rollup integration. Playwright is also provided, so you can write integration tests in the matching folder.

Write your plugin

👉 Run the dev server

npm run dev

Pass props to your plugin

You can pass props to your plugin this way 👇

// src/index.html

<script>
...
window.$docsify = {
name: "My plugin documentation website",
// props
myPlugin: {
hello: "world",
},
};
...
</script>

These props will be accessible through the docsify global object in your plugin 👇

// src/plugin/main.js
const docsify = window.$docsify || {};

const props = docsify.myPlugin || {};

Interact with Docsify lifecycle hooks

Docsify lifecycle hooks are provided through the hook argument passed to the plugin function. For more detail about lifecycle hooks check out the official doc.

You can attach your function to 6 differents lifecycle hooks allowing you to modify the state of the app.

Below is the example included in the template for this project.

const myPlugin = (props = { hello: "" }) => (hook) => hook.init(() => {
console.log(`hello ${props.hello}`);
});

This is a function that will be called once when the Docsify script is initialized on the first load of the application. This function will simply display the parameter provided in the browser console.

The example is deliberately very simple here, but it’s possible to modify the rendering of Docsify. For example you can add a button to copy and paste the current paragraph when hovering the content or add a custom footer on each page.

Detailed example

Here is an example coming originally from the official documentation. It interacts with two different Hooks : beforeEach and afterEach. The goal is to add an edit button and a footer to each page.

Replace my-plugin.js with this content 👇

const editOnGitPlugin = (props = { repoUrl }) => (hook, vm) => 
hook.beforeEach((html) => {
let editUrl = props.repoUrl + vm.route.file;
let editLinkMarkdown = "[📝 Edit on Github](" + editUrl + ")\n";
return editLinkMarkdown + html;
});

const customFooterPlugin = (props = { title, link }) => (hook) =>
hook.afterEach((html) => {
let footer = [
"<hr/>",
"<footer>",
`<span>${props.title}</span>`,
`<span><a href="${props.link}" target="_blank">✨</a></span>`,
"</footer>",
].join("");
return html + footer;
});

export { editOnGitPlugin, customFooterPlugin };

You may have noticed that we passed the vm property to the plugin, it’s the current Docsify instance. It gives us access to some properties as the current file rendered.

Replace main.js with this content 👇

import { editOnGitPlugin, customFooterPlugin } from "./my-plugin";

const docsify = window.$docsify || {};

const props = {
editOnGitPlugin: docsify.editOnGitPlugin,
customFooterPlugin: docsify.customFooterPlugin
} || {};

docsify.plugins = [].concat(docsify.plugins || [], editOnGitPlugin(props.editOnGitPlugin), customFooterPlugin(props.customFooterPlugin));

Replace the Docsify script section in index.html with this content 👇

<script>
window.$docsify = {
name: "Docsify-plugin-playground",
repo: "",
editOnGitPlugin: {
repoUrl: "https://github.com/docsifyjs/docsify/blob/master/docs/",
},
customFooterPlugin: {
title: "My awesome custom footer ",
link: "https://github.com/docsifyjs/awesome-docsify",
},
};
</script>

You can now see the edit button on top of the page. On click you’ll be redirected to the markdown file you want to modify on your Git repo.
The second plugin adds a footer providing some information.

Here are detailed examples of plugins that I’ve made using this template, if you need some inspiration👇

Test your plugin

You can test your plugin using Playwright. We provide a simple test file to test the two plugins we’ve made in src/my-plugin.spec.js.

👉 Run the tests

npm run test

Deploy your plugin

To deploy this package on npm, you will need to have an account on npmjs.com. Once you have an account, follow these steps :

👉 Build the project with npm run build

You have the choice to deliver it as a CommonJS, ESModule, IIFE or UMD. By default, two artifacts CJS and ESM are generated. You can modify that in vite-config.js.

📦dist
┣ 📜my-plugin.cjs
┗ 📜my-plugin.js

👉 Run npm publish

You can now access your package on npm with this url 👉 https://www.npmjs.com/package/my-docsify-plugin.

To use this package on your website we will use Jsdelivr.com. It will act as a Content Delivery Network proxying your npm package, and enabling you to use this script directly in the browser.

You can get your plugin through this url 👉https://cdn.jsdelivr.net/npm/my-docsify-plugin@version/dist/my-plugin.js

Now your users just have to add this url directly in their Docsify index.html to use your plugin 👇

<script src="//cdn.jsdelivr.net/npm/my-docsify-plugin@version/dist/my-plugin.js"></script>

If you specified “main”: “dist/my-plugin.js” in package.json, you could also access it directly with this url 👉 https://cdn.jsdelivr.net/npm/my-docsify-plugin@1.0.0

Conclusion

Thank you for reading this article. If you need more information, feel free to check out the Docsify’s plugin documentation.

--

--

Corentin Le Berre
abbeal’s tech blog

Hey, I'm Corentin 👋 I'm a fullstack developer from France