Docup is a single JavaScript file that fetches Markdown file and renders it as a beautiful one-page documentation.
Docup is built with Preact, the entire bundle (with CSS) is just 30kB minified and gzipped.
Quick Start
Create an HTML file: index.html
which will be be homepage of your documentation website:
<!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>
<!-- Stylesheet -->
<link
rel="stylesheet"
href="https://unpkg.com/@egoist/docup@2/dist/docup.min.css"
/>
</head>
<body>
<!-- Start app -->
<script type="module">
import * as docup from 'https://unpkg.com/@egoist/docup@2/dist/docup.min.js'
docup.init({
// ..options
})
</script>
</body>
</html>
Then populate a README.md
file to the same directory where index.html
is located.
## Introduction
How about this.
## Advanced
How about that.
Finally serve this directory as a static website:
- node.js:
npm i -g static-server && static-server .
- deno:
deno install --allow-net --allow-read https://deno.land/std/http/file_server.ts && file_server .
- python:
python -m SimpleHTTPServer
- ...etc, you can use any static file server, for real.
How Files Are Resolved
If current location.pathname
is /
, i.e. the homepage, it fetches /README.md
.
If current location.pathname
is /docs/
, it fetches /docs/README.md
.
If current location.pathname
is /docs/en
, it fetches /docs/en.md
.
Basically if the pathname ends with a slash, we treat it as a directory and try to load the README.md
file under that path, you can also use indexFile option to change README.md
to other file if you want. If the pathname does not end with slash, we would fetch pathname + '.md'
.
You can also use root option to set the origin of the files, for example if you want to load files from other domain, you can set root: 'https://sub.domain.com/data'
.
Guide
Site Title
We use the value of document.title
if it's not undefined
, you can also set a title via options:
docup.init({
title: 'My Website',
})
Markdown Features
We use the blazing fast marked to parse Markdown, all GitHub Flavored Markdown features are supported.
Message Blocks
To highlight some messages in your documentation, use the following format to write a blockquote
:
> [TYPE]: This is a very dangerous action!
Where [TYPE]
can be:
Alert
Warning
Info
Success
Note
And they look like:
Embedding
Embedding and running code snippets is easy if your provider supports iframe, like codesandbox.io:
<iframe
src="https://codesandbox.io/embed/vue"
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"
>
</iframe>
Highlight
Docup uses Prism.js to highlight code blocks, by default only a few languages are supported, namely: html
css
js
markdown
bash
json
, you can manually load Prism language components to support more languages, e.g. for Go programming language:
docup.init({
highlightLanguages: ['go'],
})
Available languages:
Inline Component
You can inline Preact, React and Vue 3 components inside Markdown file like this:
```js preact
import { useState, html } from 'docup'
export default () => {
const [count, setCount] = useState(0)
return html`<button
style="width:100px;border:1px solid;padding:5px"
onClick=${() => setCount(count + 1)}
>
${count}
</button>`
}
```
Write preact
next to the language name and we will render the code as a Preact component in place:
See another example with React:
import React from 'react'
import Trend from 'react-trend'
import htm from 'htm'
const html = htm.bind(React.createElement)
export default () => html`<${Trend}
smooth
autoDraw
autoDrawDuration="{3000}"
autoDrawEasing="ease-out"
data=${[0, 2, 5, 9, 5, 10, 3, 5, 0, 0, 1, 8, 2, 9, 0]}
gradient=${['#00c6ff', '#F0F', '#FF0']}
radius=${10}
strokeWidth=${2}
strokeLinecap=${'butt'}
/>`
When the code block is recognized as a component, the code itself will be removed from the markdown, if you want to show the code block below the rendered component, you can use the keep
keyword:
```js react,keep
export default () => {}
```
If you want to show the code block above the component, use keepAbove
instead.
CSS Variables
Multiple Pages
If your doc is too long to display in a single page, you can split it into multiple Markdown files, that works because Docup fetches Markdown file based on the current pathname
.
Then all you need is to route all requests to the index.html
. (Also known as SPA fallback)
If you host your docs on Netlify, use following rule in _redirects
file:
/* /index.html 301
Or if you're using Vercel, use following config in vercel.json
:
{
"rewrites": [
{
"source": "/(.*)",
"destination": "/index.html"
}
]
}
Or Nginx config:
location / {
try_files /index.html =404;
}
Deploy
GitHub Pages
Simply put all your files in docs
folder on master
branch, or root directory on the gh-pages
branch.
Then enable it on repo's settings
page:
Don't forget to add .nojekyll
file to tell GitHub to treat it as a normal static website.
Netlify
Set the public directory to where your index.html
is located at.
Vercel
Set the public directory to where your index.html
is located at.
API
docup.init(options)
options
title
- Type:
string
The title that is shown in the navbar. It defaults to document.title
navLinks
- Type:
NavLink[]
Links in the navbar.
interface NavLink {
text: string
link: string
}
indexFile
- Type:
string
- Default:
README.md
Used for path ending with a slash.
base
- Type:
string
- Default:
/
The base path your website is located at. If you are serving your docs under a sub path like https://user.github.io/awesome-project
, you need to set this option to /awesome-project
.
root
- Type:
string
- Default:
''
The root path we use to resolve files from.
highlightLanguages
- Type:
string[]
Extra languages to highlight.
font
- Type:
string
- Default:
Lato
Use a custom font from Google Fonts. We use Lato by default.
props
- Type:
any
Inject props to inlined components.
For example:
docup.init({
props: {
count: 0,
},
})
Then you can inline component and use props in Markdown:
```js preact
import { html } from 'docup'
export default ({ count }) => {
return html`<button>${count}</button>`
}
```
useSystemTheme
- Type:
boolean
- Default:
true
Follow system theme, i.e. use dark theme when system theme is dark.
beforeSidebar
- Type:
string
HTML string to display before sidebar.
Browser support
Last 2 versions of modern browsers.
Resources
Discord Chat
Join my Discord Community.
GitHub Sponsors
Support this project via GitHub Sponsors.
License
MIT © EGOIST