├── .gitignore
├── LICENSE
├── README.md
├── app.js
├── bin
└── index.js
├── collaborators.md
├── components
├── content.css
├── content.js
├── main.css
├── main.js
├── menu.css
├── menu.js
├── sidebar.css
└── sidebar.js
├── examples
├── browser
│ ├── 200.html
│ ├── bundle.js
│ ├── contents.js
│ ├── index.html
│ ├── index.js
│ ├── logo.svg
│ ├── markdown
│ │ ├── about.md
│ │ ├── pig.md
│ │ ├── puppy.md
│ │ └── sheep.md
│ └── package.json
├── cli-full-html
│ ├── contents.js
│ ├── docs
│ │ ├── about.md
│ │ └── pizza.md
│ ├── package.json
│ └── style.css
├── cli-images
│ ├── assets
│ │ ├── baby.jpg
│ │ ├── doodie.jpg
│ │ ├── storycat.jpg
│ │ ├── trouble.jpg
│ │ └── wizard.jpg
│ ├── contents.js
│ ├── docs
│ │ └── about.md
│ └── package.json
└── cli
│ ├── contents.js
│ ├── docs
│ ├── about.md
│ └── pizza.md
│ ├── package.json
│ └── style.css
├── index.js
├── lib
├── create-assets.js
├── create-css.js
├── create-html.js
├── create-js.js
├── create-output-dir.js
├── create-pushstate-file.js
├── parse-contents.js
├── parse-docs.js
├── parse-markdown.js
└── parse-options.js
├── package.json
├── parse.js
├── styles
├── base.css
├── fonts.css
├── github-markdown.css
├── highlighting
│ ├── tomorrow-night.css
│ └── tomorrow.css
└── index.css
├── tests
├── app.js
├── cli.js
├── fixtures
│ ├── .DS_Store
│ ├── browser
│ │ ├── app.js
│ │ ├── contents.js
│ │ └── docs
│ │ │ ├── a.md
│ │ │ ├── b.md
│ │ │ └── c.md
│ └── cli
│ │ ├── contents.js
│ │ └── docs
│ │ ├── a.md
│ │ ├── b.md
│ │ └── c.md
├── index.js
├── node.js
└── parse-options.js
└── transform.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
18 | .grunt
19 |
20 | # node-waf configuration
21 | .lock-wscript
22 |
23 | # Compiled binary addons (http://nodejs.org/api/addons.html)
24 | build/Release
25 |
26 | # Dependency directory
27 | node_modules
28 |
29 | # Optional npm cache directory
30 | .npm
31 |
32 | # Optional REPL history
33 | .node_repl_history
34 |
35 | example/bundle.js
36 | site
37 | tmp
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Jeremy Freeman
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # minidocs
2 |
3 | [![NPM version][npm-image]][npm-url]
4 | [![js-standard-style][standard-image]][standard-url]
5 |
6 | > build a minimalist site for your documentation
7 |
8 | This module generates a documentation site from two simple components:
9 |
10 | 1. A collection of markdown documents
11 | 2. A hierarchical object specifying your table of contents
12 |
13 | This module is intentionally simpler and more opinionated than something like [Jekyll](https://jekyllrb.com/) or [Sphinx](http://www.sphinx-doc.org/en/stable/). Depending on what you're looking for, that might be good, because it's easier to reason about, or bad, because it's less flexible! It'll probably be most useful if your documentation already consists entirely of markdown files, and it composes well with any tools that generate markdown, for example [`ecosystem-docs`](https://github.com/hughsk/ecosystem-docs), which pulls README files from a collection of GitHub repositories.
14 |
15 | Sites can be built using a command-line tool, or using the library as a module with browserify. There are options for specifying a project logo, custom css, and other basic formatting. Support for themes coming soon! PRs welcome!
16 |
17 | Here is a [**simple example site**](http://minidocs-example.surge.sh) built with `minidocs`
18 |
19 | ## install
20 |
21 | ### command-line
22 |
23 | Install as a command-line tool
24 |
25 | ```
26 | npm install -g minidocs
27 | ```
28 |
29 | ### library
30 |
31 | Add to your project with
32 |
33 | ```
34 | npm install --save minidocs
35 | ```
36 |
37 | ## examples
38 |
39 | ### using minidocs on the command-line
40 |
41 | Just specify the location of your markdown files, the table of contents, the output location, and build the site
42 |
43 | ```
44 | minidocs docs/ --contents contents.json --output site/
45 | ```
46 |
47 | The folder `site` will now contain the `html`, `js`, and `css` for your site.
48 |
49 | **Have a images or other files you'd like to include?** You can copy a directory into the build of your site with the `--assets` option:
50 |
51 | ```
52 | minidocs docs/ --contents contents.json --output site/ --assets images
53 | ```
54 |
55 | **Want to change the styles?** Use the `--css` option to include a custom stylesheet.
56 |
57 | ```
58 | minidocs docs/ --contents contents.json --output site/ --css style.css
59 | ```
60 |
61 | **[See all other cli options.](https://github.com/freeman-lab/minidocs#command-line-1)**
62 |
63 | ### using minidocs as a JS module
64 |
65 | Create a table of contents in a file named `contents.json`:
66 |
67 | ```json
68 | {
69 | "overview": {
70 | "about": "about.md"
71 | },
72 | "animals": {
73 | "furry": {
74 | "sheep": "sheep.md"
75 | },
76 | "pink": {
77 | "pig": "pig.md"
78 | }
79 | }
80 | }
81 | ```
82 |
83 | Then build the site and add it to the page with
84 |
85 | ```javascript
86 | var minidocs = require('minidocs')
87 |
88 | var app = minidocs({
89 | contents: './contents.json',
90 | markdown: './markdown',,
91 | logo: './logo.svg'
92 | })
93 |
94 | var tree = app.start()
95 | document.body.appendChild(tree)
96 | ```
97 |
98 | This assumes you have the files `about.md`, `sheep.md`, and `pig.md` inside a local folder `markdown`.
99 |
100 | To run this in the browser you'll need to use the minidocs transform with browserify or budo:
101 |
102 | **browserify example:**
103 |
104 | ```
105 | browserify index.js -t minidocs/transform > bundle.js
106 | ```
107 |
108 | **budo example:**
109 |
110 | ```
111 | budo index.js:bundle.js -P -- -t minidocs/transform
112 | ```
113 |
114 | You can also add transforms to your project by adding a `browserify` field to the `package.json` file with a `transform` array:
115 |
116 | ```js
117 | "browserify": {
118 | "transform": [
119 | "minidocs/transform"
120 | ]
121 | }
122 | ```
123 |
124 | ### about the minidocs transform
125 |
126 | Packaged with minidocs is a transform that takes care of reading the contents file, the markdown files, highlighting code in the markdown, and bundling the JS and CSS.
127 |
128 | The minidocs transform is only necessary when using minidocs as a JS module, not when using the minidocs cli tool.
129 |
130 |
131 | ## run the example
132 |
133 | To run a full example, clone this repository, go into the folder [`example`](example) then call
134 |
135 | ```
136 | npm install
137 | npm start
138 | ```
139 |
140 | ## usage
141 |
142 | ### command-line
143 |
144 | ```
145 | Usage:
146 | minidocs {sourceDir} -c {contents.json} -o {buildDir}
147 |
148 | Options:
149 | * --contents, -c JSON file that defines the table of contents
150 | * --output, -o Directory for built site [site]
151 | * --title, -t Project name [name of current directory]
152 | * --logo, -l Project logo
153 | * --css, -s Optional stylesheet
154 | * --assets, -a Directory of assets to be copied to the built site
155 | * --initial, -i Page to use for root url
156 | * --pushstate, -p Create a 200.html file for hosting services like surge.sh
157 | * --basedir, -b Base directory of the site
158 | * --full-html, -f Create HTML files for all routes. Useful for GitHub Pages. [false]
159 | * --help, -h Show this help message
160 | ```
161 |
162 | ### library
163 |
164 | #### `var minidocs = require('minidocs')`
165 |
166 | #### `var app = minidocs(opts)`
167 |
168 | Where `opts` is an object that can specify the following options
169 |
170 | - `contents` the path to a JSON file or JS module with the table of contents, required
171 | - `markdown` the path to the directory of markdown files
172 | - `styles` a stylesheet, if not required will only use base styles
173 | - `logo` relative file path to a logo file, if unspecified will not include a logo
174 | - `initial` which document to show on load, if unspecified will load the first document
175 | - `root` a DOM node to append to, if unspecified will append to `document.body`
176 | - `basedir` the base route of the minidocs app (useful if published as a project on github pages)
177 |
178 | #### `var tree = app.start(rootId?, opts)`
179 | The `start` method accepts the same options as [choo's `start` method](https://github.com/yoshuawuyts/choo#tree--appstartrootid-opts).
180 |
181 | This generates the html tree of the application that can be added to the DOM like this:
182 |
183 | ```js
184 | var tree = app.start()
185 | document.body.appendChild(tree)
186 | ```
187 |
188 | #### `var html = app.toString(route, state)`
189 | The `toString` method accepts the same options as [choo's `toString` method](https://github.com/yoshuawuyts/choo#html--apptostringroute-state)
190 |
191 | We use this in the command-line tool to generate the static files of the site.
192 |
193 | ## deploying minidocs
194 |
195 | ### surge.sh
196 |
197 | [surge.sh](https://surge.sh) supports HTML5 pushstate if you have a 200.html file in your built site. You can either create that file yourself when using minidocs as a JS module, or you can build the site with the minidocs cli tool and the `--pushstate` option:
198 |
199 | ```sh
200 | minidocs docs/ -c contents.json --pushstate -o site/
201 | ```
202 |
203 | ##### Deploy with the `surge` command
204 |
205 | You can use the [`surge`](https://www.npmjs.com/package/surge) module to push the built site to the [surge.sh service](https://surge.sh).
206 |
207 | Install `surge`:
208 |
209 | ```sh
210 | npm install --save-dev surge
211 | ```
212 |
213 | Create a `deploy` npm script:
214 |
215 | ```js
216 | "scripts": {
217 | "deploy": "surge dist"
218 | }
219 | ```
220 |
221 | Publish your site:
222 |
223 | ```sh
224 | npm run deploy
225 | ```
226 |
227 | ### github pages
228 |
229 | GitHub Pages doesn't support HTML5 pushstate, so you have two options:
230 |
231 | ##### 1. Generate the site with the minidocs cli
232 |
233 | Build a minidocs site with the cli and the `--full-html` option:
234 |
235 | ```sh
236 | minidocs path/to/docs/dir -c contents.json -o site --full-html
237 | ```
238 |
239 | This creates an HTML file for each route of the site, so that on initial page load all content is sent from the server, and once the JS is loaded the minidocs app takes over all routing.
240 |
241 | ##### 2. Use hash routing with the JS module
242 |
243 | To use hash routing, start the app with the `{ hash: true }` option in the `minidocs.start` method:
244 |
245 | ```js
246 | var tree = app.start({ hash: true })
247 | document.body.appendChild(tree)
248 | ```
249 |
250 | ##### Deploy with the `gh-pages` command
251 |
252 | You can use the [`gh-pages`](https://www.npmjs.com/package/gh-pages) module to push the built site to the gh-pages branch of your repo.
253 |
254 | > Note: if you're deploying a project at a basedir like username.github.io/project-name, you'll want to use the `--basedir /project-name` option
255 |
256 | Install `gh-pages`:
257 |
258 | ```sh
259 | npm install --save-dev gh-pages
260 | ```
261 |
262 | Create a `deploy` npm script:
263 |
264 | ```js
265 | "scripts": {
266 | "deploy": "gh-pages -d dist"
267 | }
268 | ```
269 |
270 | Publish your site:
271 |
272 | ```sh
273 | npm run deploy
274 | ```
275 |
276 | ## license
277 |
278 | [MIT](LICENSE)
279 |
280 | [npm-image]: https://img.shields.io/npm/v/minidocs.svg?style=flat-square
281 | [npm-url]: https://npmjs.org/package/minidocs
282 | [standard-image]: https://img.shields.io/badge/code%20style-standard-lightgray.svg?style=flat-square
283 | [standard-url]: https://github.com/feross/standard
284 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | var choo = require('choo')
2 |
3 | var main = require('./components/main')
4 |
5 | module.exports = function (opts) {
6 | opts.basedir = (opts.basedir || '').replace(/\/$/, '')
7 | var app = choo()
8 |
9 | app.model({
10 | state: {
11 | title: opts.title,
12 | logo: opts.logo,
13 | contents: opts.contents,
14 | html: opts.html,
15 | routes: opts.routes,
16 | current: opts.initial,
17 | basedir: opts.basedir
18 | },
19 | reducers: {},
20 | subscriptions: [
21 | function catchLinks (send, done) {
22 | window.onclick = function (e) {
23 | var node = (function traverse (node) {
24 | if (!node) return
25 | if (node.localName !== 'a') return traverse(node.parentNode)
26 | if (node.href === undefined) return traverse(node.parentNode)
27 | if (window.location.host !== node.host) return traverse(node.parentNode)
28 | return node
29 | })(e.target)
30 |
31 | if (!node) return
32 | e.preventDefault()
33 | var href = node.href
34 |
35 | if (window.location.pathname !== node.pathname) {
36 | send('location:setLocation', { location: href }, done)
37 | window.history.pushState(null, null, href)
38 | document.body.scrollTop = 0
39 | } else {
40 | window.location.hash = node.hash
41 | var el = document.querySelector(node.hash)
42 | window.scrollTo(0, el.offsetTop)
43 | }
44 | }
45 | }
46 | ]
47 | })
48 |
49 | app.model({
50 | namespace: 'menu',
51 | state: {
52 | open: false,
53 | size: 'small'
54 | },
55 | reducers: {
56 | set: function (data, state) {
57 | return data
58 | },
59 | size: function (data, state) {
60 | return data
61 | }
62 | },
63 | subscriptions: [
64 | checkSize,
65 | function (send, done) {
66 | window.onresize = function () {
67 | checkSize(send, done)
68 | }
69 | }
70 | ]
71 | })
72 |
73 | function checkSize (send, done) {
74 | var size = window.innerWidth > 600 ? 'large' : 'small'
75 | send('menu:size', { size: size }, done)
76 | }
77 |
78 | app.router(function (route) {
79 | var routes = [
80 | route('/', main),
81 | route('/:page', main)
82 | ]
83 |
84 | if (opts.basedir) {
85 | return route(opts.basedir, routes)
86 | }
87 |
88 | return routes
89 | })
90 |
91 | return app
92 | }
93 |
--------------------------------------------------------------------------------
/bin/index.js:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env node
2 |
3 | var path = require('path')
4 | var assert = require('assert')
5 | var parsePath = require('parse-filepath')
6 | var minimist = require('minimist')
7 | var apply = require('async.applyeachseries')
8 | var exit = require('exit')
9 |
10 | var minidocs = require('../app')
11 | var parseOptions = require('../lib/parse-options')
12 | var createCSS = require('../lib/create-css')
13 | var createHTML = require('../lib/create-html')
14 | var createAssets = require('../lib/create-assets')
15 | var createJS = require('../lib/create-js')
16 | var createOutputDir = require('../lib/create-output-dir')
17 | var createPushstateFile = require('../lib/create-pushstate-file')
18 |
19 | var cwd = process.cwd()
20 | var cwdParsed = parsePath(cwd)
21 | var projectdir = cwdParsed.name
22 | var argv = minimist(process.argv.slice(2), {
23 | alias: {
24 | c: 'contents',
25 | o: 'output',
26 | t: 'title',
27 | l: 'logo',
28 | s: 'css',
29 | i: 'initial',
30 | a: 'assets',
31 | p: 'pushstate',
32 | b: 'basedir',
33 | f: 'full-html',
34 | h: 'help'
35 | },
36 | default: {
37 | output: 'site',
38 | title: projectdir,
39 | basedir: '',
40 | 'full-html': false
41 | }
42 | })
43 |
44 | var outputDir = path.resolve(cwd, argv.output)
45 |
46 | if (argv.help) {
47 | usage()
48 | }
49 |
50 | if (argv._[0]) {
51 | var source = path.resolve(cwd, argv._[0])
52 | } else {
53 | error('\nError:\nsource markdown directory is required', { usage: true })
54 | }
55 |
56 | if (argv.contents) {
57 | var contentsPath = path.resolve(cwd, argv.contents)
58 | } else {
59 | error('\nError:\n--contents/-c option is required', { usage: true })
60 | }
61 |
62 | if (argv.logo) {
63 | var logoSource = path.resolve(cwd, argv.logo)
64 | var logo = path.parse(argv.logo).base
65 | }
66 |
67 | var state = {
68 | title: argv.title,
69 | logo: logo,
70 | logoSource: logoSource,
71 | contents: contentsPath,
72 | markdown: source,
73 | initial: argv.initial,
74 | basedir: argv.basedir,
75 | dir: cwd
76 | }
77 |
78 | var parsedState = parseOptions(state)
79 | var app = minidocs(parsedState)
80 |
81 | build({
82 | argv: argv,
83 | state: parsedState,
84 | outputDir: outputDir
85 | }, function (err) {
86 | if (err) return error(err)
87 | exit()
88 | })
89 |
90 | function build (options) {
91 | assert.ok(options)
92 | assert.ok(options.outputDir)
93 | assert.ok(options.argv)
94 | assert.ok(options.state)
95 |
96 | var tasks = [
97 | createOutputDir,
98 | createJS,
99 | createCSS,
100 | createHTML,
101 | createAssets
102 | ]
103 |
104 | if (options.argv.pushstate) {
105 | tasks.push(createPushstateFile)
106 | }
107 |
108 | apply(tasks, app, options, function (err) {
109 | if (err) return error(err)
110 | })
111 | }
112 |
113 | function error (err, opts) {
114 | console.log(err)
115 | if (opts && opts.usage) usage(1)
116 | }
117 |
118 | function usage (exitcode) {
119 | console.log(`
120 | Usage:
121 | minidocs {sourceDir} -c {contents.json} -o {buildDir}
122 |
123 | Options:
124 | * --contents, -c JSON file that defines the table of contents
125 | * --output, -o Directory for built site [site]
126 | * --title, -t Project name [name of current directory]
127 | * --logo, -l Project logo
128 | * --css, -s Optional stylesheet
129 | * --assets, -a Directory of assets to be copied to the built site
130 | * --initial, -i Page to use for root url
131 | * --pushstate, -p Create a 200.html file for hosting services like surge.sh
132 | * --basedir, -b Base directory of the site
133 | * --full-html, -f Create HTML files for all routes. Useful for GitHub Pages. [false]
134 | * --help, -h Show this help message
135 | `)
136 | exit(exitcode || 0)
137 | }
138 |
--------------------------------------------------------------------------------
/collaborators.md:
--------------------------------------------------------------------------------
1 | # collaborators
2 |
3 | minidocs is only possible due to the excellent work of the following collaborators:
4 |
5 |
11 |
--------------------------------------------------------------------------------
/components/content.css:
--------------------------------------------------------------------------------
1 | a.markdown-link {
2 | color: rgb(173,173,173);
3 | background: rgb(240,240,240);
4 | display: inline-block;
5 | position: absolute;
6 | margin-top: -50px;
7 | padding: 3px 5px;
8 | text-decoration: none;
9 | }
10 |
11 | a.markdown-link:hover {
12 | color: rgb(130,130,130);
13 | background: rgb(225,225,225);
14 | }
15 |
16 | img.contributor {
17 | border: none;
18 | vertical-align: top;
19 | }
20 |
21 | div.contributor-wrapper {
22 | width: 30px;
23 | height: 30px;
24 | display: inline-block;
25 | text-align: center;
26 | margin-right: 5px;
27 | opacity: 0.8;
28 | cursor: pointer;
29 | border: 3px solid rgb(225, 225, 225);
30 | }
31 |
32 | div.contributor-wrapper:hover {
33 | background: rgb(205,205,205);
34 | opacity: 0.95;
35 | }
36 |
37 | div.contributor-container {
38 | width: 60%;
39 | right: 40px;
40 | margin-top: -50px;
41 | position: relative;
42 | display: inline-block;
43 | text-align: right;
44 | float: right;
45 | }
46 |
47 | @media (min-width: 600px) {
48 | div.contributor-wrapper {
49 | width: 50px;
50 | height: 50px;
51 | }
52 | div.contributor-container {
53 | right: 0px;
54 | }
55 | }
--------------------------------------------------------------------------------
/components/content.js:
--------------------------------------------------------------------------------
1 | var html = require('choo/html')
2 | var css = require('sheetify')
3 | var avatar = require('github-avatar-url')
4 |
5 | module.exports = function (state, prev, send) {
6 | var currentPage = state.params.page || state.current
7 | var page = state.html[currentPage]
8 | var pageData = state.contents.filter(function (item) {
9 | return item.key === currentPage
10 | })[0]
11 |
12 | var prefix = css('./content.css')
13 |
14 | var contentWrapper = html``
15 | contentWrapper.innerHTML = page
16 |
17 | var link = pageData.source ? html`source` : ''
18 |
19 | function contributors (items) {
20 | return items.map(function (item) {
21 | if (!item) return
22 | var user = item.replace('@', '')
23 | var img = html`
`
24 | img.style.opacity = 0
25 | avatar(user, function (err, url) {
26 | if (err) {
27 | // TODO: handle requests in effects, send error messages to state
28 | console.log(err)
29 | }
30 | img.src = url
31 | img.onload = function () {
32 | img.style.opacity = 1
33 | }
34 | })
35 | return html``
40 | })
41 | }
42 |
43 | if (pageData.contributors) {
44 | var contributorWrapper = html`
45 | ${contributors(pageData.contributors)}
46 |
`
47 | }
48 |
49 | return html`
50 | ${link}
51 | ${contributorWrapper}
52 | ${contentWrapper}
53 |
`
54 | }
55 |
--------------------------------------------------------------------------------
/components/main.css:
--------------------------------------------------------------------------------
1 | :host {
2 | width: 100%;
3 | padding: 40px;
4 | vertical-align: top;
5 | display: inline-block;
6 | box-sizing: border-box;
7 | }
8 |
9 | @media (min-width: 600px) {
10 | :host {
11 | position: absolute;
12 | right: 0;
13 | width: 73%;
14 | padding: 125.9px 8% 70.6px 8%;
15 | vertical-align: top;
16 | display: inline-block;
17 | }
18 | }
19 |
20 | @media (min-width: 900px) {
21 | :host {
22 | width: 77%;
23 | padding: 125.9px 6% 70.6px 6%;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/components/main.js:
--------------------------------------------------------------------------------
1 | var html = require('choo/html')
2 | var css = require('sheetify')
3 | var sidebar = require('./sidebar')
4 | var content = require('./content')
5 |
6 | module.exports = function (state, prev, send) {
7 | var prefix = css('./main.css')
8 |
9 | return html`
10 | ${sidebar(state, prev, send)}
11 |
12 |
13 | ${content(state, prev, send)}
14 |
15 |
16 |
`
17 | }
18 |
--------------------------------------------------------------------------------
/components/menu.css:
--------------------------------------------------------------------------------
1 | :host {
2 |
3 | }
4 |
5 | .h2 {
6 | display: block;
7 | font-size: 1.5em;
8 | font-weight: bold;
9 | margin-top: 12px;
10 | margin-bottom: 12px;
11 | }
12 |
13 | .minidocs-menu, .minidocs-menu.menu-closed {
14 | display: none;
15 | z-index: 1000;
16 | }
17 |
18 | .minidocs-menu.menu-open.menu-small {
19 | display: block;
20 | background-color: rgb(240,240,240);
21 | position: fixed;
22 | width: 100%;
23 | top: 0;
24 | height: 100%;
25 | padding: 50px;
26 | margin-bottom: 0px;
27 | box-sizing: border-box;
28 | }
29 |
30 | .minidocs-menu.menu-open.menu-small .minidocs-menu-wrapper {
31 | height: 100%;
32 | overflow-y: auto;
33 | }
34 |
35 | a.content-link {
36 | padding: 6px 8px 6px 5px;
37 | margin-bottom: 1px;
38 | cursor: pointer;
39 | text-decoration: none;
40 | color: #505050;
41 | display: block;
42 | border-left: 3px solid #eee;
43 | }
44 |
45 | a.content-link.active {
46 | background-color: #fff;
47 | border-left: 3px solid rgb(200,200,200);
48 | }
49 |
50 | a.content-link:hover {
51 | background-color: #fff;
52 | border-left: 3px solid rgb(200,200,200);
53 | }
54 |
55 | .minidocs-menu-toggle {
56 | display: block;
57 | position: absolute;
58 | top: 10px;
59 | left: 10px;
60 | border: 0px;
61 | background: transparent;
62 | padding-left: 20px;
63 | line-height: 0.9;
64 | z-index: 2000;
65 | cursor: pointer;
66 | font-size: 16px;
67 | }
68 |
69 | .minidocs-menu-toggle:before {
70 | content: "";
71 | position: absolute;
72 | left: 0;
73 | top: 0.25em;
74 | width: 1em;
75 | height: 0.15em;
76 | background: black;
77 | box-shadow:
78 | 0 0.25em 0 0 black,
79 | 0 0.5em 0 0 black;
80 | }
81 |
82 | .minidocs-menu-toc {
83 | margin-top:-2px;
84 | background-color: #f8f8f8;
85 | border-left: 3px solid rgb(200,200,200);
86 | }
87 |
88 | .minidocs-menu-toc a.content-link {
89 | border-left:0px;
90 | padding: 4px 0px 4px 10px;
91 | }
92 |
93 | @media (min-width: 600px) {
94 | .minidocs-menu {
95 | display: block;
96 | margin-bottom: 25px;
97 | }
98 |
99 | .minidocs-menu-toggle {
100 | display: none;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/components/menu.js:
--------------------------------------------------------------------------------
1 | var url = require('url')
2 | var css = require('sheetify')
3 | var html = require('choo/html')
4 |
5 | module.exports = function (state, prev, send) {
6 | var contents = state.contents
7 | var prefix = css('./menu.css')
8 |
9 | function createMenu (contents) {
10 | return contents.map(function (item) {
11 | // TODO: figure out a better way to get current page in state based on link click
12 | var current
13 | var location
14 |
15 | if (state.location && state.location.pathname) {
16 | location = url.parse(state.location.pathname)
17 | var sliceBy = state.basedir.length + 1
18 | current = location.pathname.slice(sliceBy)
19 | }
20 |
21 | if (!current || current.length <= 1) {
22 | current = state.current
23 | }
24 |
25 | function onclick (e) {
26 | send('menu:set', { open: false })
27 | }
28 |
29 | function createTocItem (tocItem) {
30 | if (tocItem.level === 1) return '' // Don't put title
31 | var depth = item.depth + (tocItem.level - 1)
32 | return html`${tocItem.title}`
33 | }
34 |
35 | if (isActive(current, item.key) && item.toc.length > 1) {
36 | return html`
37 |
45 | `
46 | }
47 |
48 | if (item.link) {
49 | return html``
50 | }
51 |
52 | return html`${item.name}
`
53 | })
54 | }
55 |
56 | function isActive (current, item) {
57 | return current === item ? 'active' : ''
58 | }
59 |
60 | function isOpen () {
61 | if (typeof window !== 'undefined' && window.innerWidth > 600) return 'menu-open'
62 | return state.menu.open ? 'menu-open' : 'menu-closed'
63 | }
64 |
65 | function onclick (e) {
66 | send('menu:set', { open: !state.menu.open })
67 | }
68 |
69 | return html`
70 |
71 |
76 |
`
77 | }
78 |
--------------------------------------------------------------------------------
/components/sidebar.css:
--------------------------------------------------------------------------------
1 | :host {
2 | width: 100%;
3 | }
4 |
5 | .minidocs-logo {
6 | width: 100%;
7 | }
8 |
9 | .minidocs-header {
10 | width: 40%;
11 | max-width: 250px;
12 | margin: 0px auto;
13 | }
14 |
15 | .h1 {
16 | display: block;
17 | font-size: 2em;
18 | font-weight: bold;
19 | margin-top: 16px;
20 | margin-bottom: 16px;
21 | }
22 |
23 | .h1:before {
24 | content: '# '
25 | }
26 |
27 | h1 a {
28 | color: #505050;
29 | text-decoration: none;
30 | }
31 |
32 | h1 a:hover {
33 | color: #222;
34 | }
35 |
36 | @media (min-width: 600px) {
37 | :host {
38 | width: 21%;
39 | padding: 0px 20px 20px 35px;
40 | display: inline-block;
41 | padding-bottom: 3%;
42 | overflow-y: scroll;
43 | background: rgb(240,240,240);
44 | height: 100%;
45 | position: fixed;
46 | top: 0;
47 | bottom: 0;
48 | }
49 |
50 | .minidocs-header {
51 | width: 100%;
52 | max-width: 250px;
53 | margin: 0px auto;
54 | }
55 |
56 | .minidocs-logo {
57 | width: 100%;
58 | max-width: 250px;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/components/sidebar.js:
--------------------------------------------------------------------------------
1 | var css = require('sheetify')
2 | var html = require('choo/html')
3 |
4 | var menu = require('./menu')
5 |
6 | module.exports = function (state, prev, send) {
7 | var prefix = css('./sidebar.css')
8 |
9 | function createHeader () {
10 | if (state.logo) {
11 | return html`
12 |
13 | `
14 | }
15 | return state.title
16 | }
17 |
18 | return html``
24 | }
25 |
--------------------------------------------------------------------------------
/examples/browser/200.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/examples/browser/contents.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'overview': {
3 | 'about': {
4 | file: 'about.md',
5 | link: 'http://github.com/freeman-lab/minidocs',
6 | contributors: ['@sethvincent', '@yoshuawuyts', '@freeman-lab', '@fraserxu']
7 | }
8 | },
9 | 'animals': {
10 | 'furry': {
11 | 'sheep': 'sheep.md',
12 | 'puppy': 'puppy.md'
13 | },
14 | 'pink': {
15 | 'pig': 'pig.md'
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/examples/browser/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/examples/browser/index.js:
--------------------------------------------------------------------------------
1 | var minidocs = require('minidocs')
2 |
3 | var app = minidocs({
4 | contents: './contents.js',
5 | markdown: './markdown',
6 | logo: './logo.svg'
7 | })
8 |
9 | var tree = app.start()
10 | document.body.appendChild(tree)
11 |
--------------------------------------------------------------------------------
/examples/browser/markdown/about.md:
--------------------------------------------------------------------------------
1 | # about
2 |
3 | Hello! This is an introduction to an example site built with [`minidocs`](https://github.com/freeman-lab/minidocs).
4 |
5 | ## doing the how it works thing
6 |
7 | ### how it works
8 |
9 | Just make a folder of markdown files, and specify an object describing the table of contents
10 |
11 | ```javascript
12 | var contents = {
13 | 'overview': {
14 | 'about': 'about.md'
15 | },
16 | 'animals': {
17 | 'furry': {
18 | 'sheep': 'sheep.md',
19 | 'puppy': 'puppy.md'
20 | },
21 | 'pink': {
22 | 'pig': 'pig.md'
23 | }
24 | }
25 | }
26 | ```
27 |
28 | Then build the site with `require('minidocs')(contents, {logo: 'logo.svg'})`
29 |
30 | Have fun with minidocs!
31 |
--------------------------------------------------------------------------------
/examples/browser/markdown/pig.md:
--------------------------------------------------------------------------------
1 | # pig
2 |
3 | i am a pig, i say oink!
4 |
5 | test
6 |
7 | test
8 |
9 | test
10 |
11 | test
12 | test
13 |
14 | test
15 | test
16 |
17 | test
18 | test
19 |
20 | test
21 | test
22 |
23 | test
24 | test
25 |
26 | test
27 | test
28 |
29 | test
30 | test
31 |
32 | test
33 | test
34 |
35 | test
36 | test
37 |
38 | test
39 | test
40 |
41 | test
42 | test
43 |
44 | test
45 | test
46 |
47 | test
48 | test
49 |
50 | test
51 | test
52 |
53 | test
54 | test
55 |
56 | ## pigs like pizza
57 |
58 | test
59 | test
60 |
61 | test
62 | test
63 |
64 | test
65 | test
66 |
67 | test
68 | test
69 |
70 | test
71 |
72 | [about minidocs](/about)
73 |
--------------------------------------------------------------------------------
/examples/browser/markdown/puppy.md:
--------------------------------------------------------------------------------
1 | # puppy
2 |
3 | i am a puppy, i say woof!
--------------------------------------------------------------------------------
/examples/browser/markdown/sheep.md:
--------------------------------------------------------------------------------
1 | # sheep
2 |
3 | i am a sheep, i say bahhhhhh!
--------------------------------------------------------------------------------
/examples/browser/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "minidocs-example",
3 | "version": "0.0.0",
4 | "description": "example for minidocs",
5 | "main": "index.js",
6 | "scripts": {
7 | "bundle": "browserify index.js -o bundle.js",
8 | "start": "budo index.js:bundle.js --pushstate"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/freeman-lab/minidocs.git"
13 | },
14 | "keywords": [
15 | "minidocs",
16 | "example",
17 | "documentation"
18 | ],
19 | "browserify": {
20 | "transform": [
21 | "minidocs/transform"
22 | ]
23 | },
24 | "author": "freeman-lab",
25 | "license": "MIT",
26 | "bugs": {
27 | "url": "https://github.com/freeman-lab/minidocs/issues"
28 | },
29 | "homepage": "https://github.com/freeman-lab/minidocs#readme",
30 | "dependencies": {},
31 | "devDependencies": {
32 | "browserify": "^13.1.0",
33 | "budo": "^8.1.0"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/examples/cli-full-html/contents.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | overview: {
3 | about: {
4 | file: 'about.md',
5 | link: 'http://github.com/freeman-lab/minidocs'
6 | }
7 | },
8 | examples: {
9 | pizza: 'pizza.md'
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/examples/cli-full-html/docs/about.md:
--------------------------------------------------------------------------------
1 | # about
2 |
3 | this is the about page
--------------------------------------------------------------------------------
/examples/cli-full-html/docs/pizza.md:
--------------------------------------------------------------------------------
1 | # pizza
2 |
3 | this is the pizza page
4 |
--------------------------------------------------------------------------------
/examples/cli-full-html/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "minidocs-example-cli",
3 | "version": "0.0.0",
4 | "description": "example for minidocs",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "npm link minidocs && minidocs docs -c contents.js --css style.css --full-html -o site",
8 | "start": "npm run build && budo --dir site --pushstate"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/freeman-lab/minidocs.git"
13 | },
14 | "keywords": [
15 | "minidocs",
16 | "example",
17 | "documentation"
18 | ],
19 | "browserify": {},
20 | "author": "freeman-lab",
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/freeman-lab/minidocs/issues"
24 | },
25 | "homepage": "https://github.com/freeman-lab/minidocs#readme",
26 | "dependencies": {},
27 | "devDependencies": {
28 | "budo": "^8.1.0"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/examples/cli-full-html/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | color: red;
3 | }
4 |
--------------------------------------------------------------------------------
/examples/cli-images/assets/baby.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/freeman-lab/minidocs/44a9929c27595a6bea83dddec6f2ca45287bac70/examples/cli-images/assets/baby.jpg
--------------------------------------------------------------------------------
/examples/cli-images/assets/doodie.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/freeman-lab/minidocs/44a9929c27595a6bea83dddec6f2ca45287bac70/examples/cli-images/assets/doodie.jpg
--------------------------------------------------------------------------------
/examples/cli-images/assets/storycat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/freeman-lab/minidocs/44a9929c27595a6bea83dddec6f2ca45287bac70/examples/cli-images/assets/storycat.jpg
--------------------------------------------------------------------------------
/examples/cli-images/assets/trouble.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/freeman-lab/minidocs/44a9929c27595a6bea83dddec6f2ca45287bac70/examples/cli-images/assets/trouble.jpg
--------------------------------------------------------------------------------
/examples/cli-images/assets/wizard.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/freeman-lab/minidocs/44a9929c27595a6bea83dddec6f2ca45287bac70/examples/cli-images/assets/wizard.jpg
--------------------------------------------------------------------------------
/examples/cli-images/contents.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | overview: {
3 | about: {
4 | file: 'about.md',
5 | link: 'http://github.com/freeman-lab/minidocs'
6 | }
7 | },
8 | examples: {
9 | pizza: 'pizza.md'
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/examples/cli-images/docs/about.md:
--------------------------------------------------------------------------------
1 | # about
2 |
3 | here's some cats that's the about have a nice time.
4 |
5 | 
6 |
7 | 
8 |
9 | 
10 |
11 | 
12 |
13 | 
14 |
--------------------------------------------------------------------------------
/examples/cli-images/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "minidocs-example-cli",
3 | "version": "0.0.0",
4 | "description": "example for minidocs",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "npm link minidocs && minidocs docs -c contents.js --assets assets -o site",
8 | "start": "npm run build && budo --dir site --pushstate"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/freeman-lab/minidocs.git"
13 | },
14 | "keywords": [
15 | "minidocs",
16 | "example",
17 | "documentation"
18 | ],
19 | "browserify": {},
20 | "author": "freeman-lab",
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/freeman-lab/minidocs/issues"
24 | },
25 | "homepage": "https://github.com/freeman-lab/minidocs#readme",
26 | "dependencies": {},
27 | "devDependencies": {
28 | "budo": "^8.1.0"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/examples/cli/contents.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | overview: {
3 | about: {
4 | file: 'about.md',
5 | link: 'http://github.com/freeman-lab/minidocs'
6 | }
7 | },
8 | examples: {
9 | pizza: 'pizza.md'
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/examples/cli/docs/about.md:
--------------------------------------------------------------------------------
1 | # about
2 |
3 | this is the about page
--------------------------------------------------------------------------------
/examples/cli/docs/pizza.md:
--------------------------------------------------------------------------------
1 | # pizza
2 |
3 | this is the pizza page
4 |
--------------------------------------------------------------------------------
/examples/cli/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "minidocs-example-cli",
3 | "version": "0.0.0",
4 | "description": "example for minidocs",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "npm link minidocs && minidocs docs -c contents.js --css style.css -o site",
8 | "start": "npm run build && budo --dir site --pushstate"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/freeman-lab/minidocs.git"
13 | },
14 | "keywords": [
15 | "minidocs",
16 | "example",
17 | "documentation"
18 | ],
19 | "browserify": {},
20 | "author": "freeman-lab",
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/freeman-lab/minidocs/issues"
24 | },
25 | "homepage": "https://github.com/freeman-lab/minidocs#readme",
26 | "dependencies": {},
27 | "devDependencies": {
28 | "budo": "^8.1.0"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/examples/cli/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | color: red;
3 | }
4 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var css = require('sheetify')
2 | var insertCSS = require('insert-css')
3 | var minidocs = require('./app')
4 |
5 | module.exports = function (opts, callback) {
6 | var app = minidocs(opts)
7 |
8 | css('./styles/base.css', { global: true })
9 | css('./styles/fonts.css', { global: true })
10 | css('./styles/github-markdown.css', { global: true })
11 | css('./styles/highlighting/tomorrow.css', { global: true })
12 |
13 | return {
14 | app: app,
15 | start: function (id, opts) {
16 | if (typeof id === 'object') {
17 | opts = id
18 | id = null
19 | }
20 | if (!opts) opts = {}
21 | opts.href = opts.href || false
22 | return app.start(id, opts)
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/create-assets.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var path = require('path')
3 | var assert = require('assert')
4 | var tar = require('tar-fs')
5 |
6 | module.exports = function createAssets (app, options, callback) {
7 | assert.ok(options)
8 | assert.ok(options.argv)
9 | assert.ok(options.outputDir)
10 |
11 | var argv = options.argv
12 | var state = options.state
13 | var outputDir = options.outputDir
14 | var logoSource = state.logoSource
15 | var assets = argv.assets || ''
16 | var assetsPath = path.parse(assets)
17 |
18 | function copyLogo (fn) {
19 | var stream = fs.createReadStream(state.logoSource)
20 | var logopath = path.join(outputDir, state.logo)
21 | var writelogo = fs.createWriteStream(logopath)
22 | stream.pipe(writelogo)
23 | stream.on('end', fn)
24 | }
25 |
26 | function copyAssets (fn) {
27 | var pack = tar.pack(assets)
28 | var extract = tar.extract(path.join(outputDir, assetsPath.name))
29 | pack.pipe(extract).on('finish', fn)
30 | }
31 |
32 | if (logoSource && assets) {
33 | copyLogo(function () {
34 | copyAssets(callback)
35 | })
36 | } else if (logoSource) {
37 | copyLogo(callback)
38 | } else if (assets) {
39 | copyAssets(callback)
40 | } else {
41 | callback()
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/create-css.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var path = require('path')
3 | var assert = require('assert')
4 |
5 | module.exports = function createCSS (app, options, callback) {
6 | assert.ok(options)
7 | assert.ok(options.argv)
8 | assert.ok(options.outputDir)
9 |
10 | var argv = options.argv
11 | var state = options.state
12 | var outputDir = options.outputDir
13 | var customStylePath = argv.css ? path.join(state.dir, argv.css) : null
14 |
15 | if (argv.css) {
16 | var customStylePath = path.join(state.dir, argv.css)
17 | fs.createReadStream(customStylePath)
18 | .pipe(fs.createWriteStream(path.join(outputDir, 'style.css')))
19 | .on('close', callback)
20 | } else {
21 | callback()
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/create-html.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var path = require('path')
3 | var assert = require('assert')
4 | var createHTML = require('create-html')
5 | var each = require('each-async')
6 |
7 | module.exports = function (app, options, callback) {
8 | assert.ok(options)
9 | assert.ok(options.argv)
10 | assert.ok(options.state)
11 | assert.ok(options.outputDir)
12 |
13 | var argv = options.argv
14 | var state = options.state
15 | var outputDir = options.outputDir
16 |
17 | assert.ok(state.title)
18 | assert.ok(state.routes)
19 |
20 | function createFile (route, filepath, callback) {
21 | var page = app.toString(state.basedir + route, state)
22 |
23 | var opts = {
24 | title: state.title,
25 | head: '',
26 | body: page,
27 | script: argv.basedir + '/bundle.js',
28 | css: argv.basedir + '/bundle.css'
29 | }
30 |
31 | if (argv.css) opts.head += `\n`
32 | var html = createHTML(opts)
33 | fs.writeFile(filepath, html, callback)
34 | }
35 |
36 | if (argv['full-html']) {
37 | each(Object.keys(state.routes), function (key, i, next) {
38 | var route = state.routes[key]
39 | var filepath = path.join(outputDir, key + '.html')
40 | state.current = key === 'index' ? state.initial : key
41 | createFile(route, filepath, next)
42 | }, callback)
43 | } else {
44 | var filepath = path.join(outputDir, 'index.html')
45 | state.current = state.initial
46 | createFile('/', filepath, callback)
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/lib/create-js.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var path = require('path')
3 | var assert = require('assert')
4 | var browserify = require('browserify')
5 |
6 | module.exports = function buildJS (app, options, callback) {
7 | assert.ok(options)
8 | assert.ok(options.argv)
9 | assert.ok(options.state)
10 | assert.ok(options.outputDir)
11 |
12 | var argv = options.argv
13 | var state = options.state
14 | var outputDir = options.outputDir
15 | var indexpath = path.join(outputDir, 'index.js')
16 |
17 | var js = `
18 | var minidocs = require('minidocs')
19 | var app = minidocs(${JSON.stringify(state)})
20 | app.start('#choo-root')
21 | `
22 |
23 | fs.writeFile(indexpath, js, function (err) {
24 | if (err) return callback(err)
25 | browserify(indexpath, { paths: [path.join(__dirname, '..', 'node_modules')] })
26 | .plugin(require('css-extract'), { out: path.join(outputDir, 'bundle.css') })
27 | .bundle(function (err, src) {
28 | if (err) return callback(err)
29 | var bundlepath = path.join(outputDir, 'bundle.js')
30 | fs.writeFile(bundlepath, src, function (err) {
31 | if (err) return callback(err)
32 | fs.unlink(indexpath, callback)
33 | })
34 | })
35 | })
36 | }
37 |
--------------------------------------------------------------------------------
/lib/create-output-dir.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert')
2 | var mkdir = require('mkdirp')
3 | var rm = require('rimraf')
4 |
5 | module.exports = function createOutputDir (app, options, callback) {
6 | assert.ok(options)
7 | assert.ok(options.outputDir)
8 |
9 | rm(options.outputDir, function (err) {
10 | if (err) return callback(err)
11 | mkdir(options.outputDir, callback)
12 | })
13 | }
14 |
--------------------------------------------------------------------------------
/lib/create-pushstate-file.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var path = require('path')
3 | var assert = require('assert')
4 | var createHTML = require('create-html')
5 |
6 | module.exports = function createPushstateFile (app, options, callback) {
7 | assert.ok(options)
8 | assert.ok(options.state)
9 | assert.ok(options.outputDir)
10 |
11 | var state = options.state
12 | var outputDir = options.outputDir
13 |
14 | assert.ok(state.title)
15 | assert.ok(state.routes)
16 |
17 | var page = app.toString(state.basedir + '/', state)
18 | var pushstatefile = path.join(outputDir, '200.html')
19 |
20 | var html = createHTML({
21 | title: state.title,
22 | body: page,
23 | script: state.basedir + '/bundle.js',
24 | css: state.basedir + '/bundle.css'
25 | })
26 |
27 | fs.writeFile(pushstatefile, html, callback)
28 | }
29 |
--------------------------------------------------------------------------------
/lib/parse-contents.js:
--------------------------------------------------------------------------------
1 | var parsePath = require('parse-filepath')
2 | var isobject = require('lodash.isobject')
3 | var isarray = require('lodash.isarray')
4 | var map = require('lodash.map')
5 |
6 | module.exports = function parseContents (options) {
7 | var contents = options.contents
8 | options.basedir = options.basedir || ''
9 | var depth = 0
10 | var menu = []
11 |
12 | function iterate (contents, depth) {
13 | return map(contents, function (value, key, obj) {
14 | return level(contents, key, value, depth + 1)
15 | })[0]
16 | }
17 |
18 | function level (contents, key, value, depth) {
19 | var obj = { depth: depth, name: key }
20 |
21 | if (isobject(value) && value.link) {
22 | obj.source = value.link
23 | }
24 |
25 | if (isobject(value) && value.contributors) {
26 | obj.contributors = isarray(value.contributors) ? value.contributors : [value.contributors]
27 | }
28 |
29 | if (isobject(value) && !value.file) {
30 | menu.push(obj)
31 | iterate(value, depth)
32 | } else {
33 | if (isobject(value)) {
34 | obj.source = value.link
35 | if (value.contributors) {
36 | obj.contributors = value.contributors && isarray(value.contributors) ? value.contributors : [value.contributors]
37 | }
38 | value = value.file
39 | }
40 | var parsed = parsePath(value)
41 | obj.key = parsed.name
42 | obj.link = options.basedir + '/' + obj.key
43 | menu.push(obj)
44 | }
45 | return menu
46 | }
47 |
48 | return iterate(contents, depth)
49 | }
50 |
--------------------------------------------------------------------------------
/lib/parse-docs.js:
--------------------------------------------------------------------------------
1 | var parseContents = require('./parse-contents')
2 | var parseMarkdown = require('./parse-markdown')
3 |
4 | module.exports = function (options) {
5 | if (!options || !options.contents || !options.markdown) {
6 | throw new Error('options object with contents and markdown properties is required')
7 | }
8 |
9 | var initial = options.initial
10 | var markdown = options.markdown
11 | var contents = parseContents(options)
12 | var html = {}
13 |
14 | var routes = { index: '/' }
15 | contents.forEach(function (item) {
16 | if (item.key) {
17 | if (!initial) initial = item.key
18 | routes[item.key] = `/${item.key}/`
19 | var parsed = parseMarkdown(markdown[item.key])
20 | html[item.key] = parsed.html
21 | item.toc = parsed.toc
22 | }
23 | })
24 |
25 | return {
26 | initial: initial,
27 | contents: contents,
28 | routes: routes,
29 | html: html
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/lib/parse-markdown.js:
--------------------------------------------------------------------------------
1 | var marked = require('marked')
2 | var hl = require('highlight.js')
3 | var slugify = require('slug')
4 | var renderer = new marked.Renderer()
5 |
6 | var toc = []
7 |
8 | renderer.heading = function(text, level, raw) {
9 | var slug = slugify(raw, {lower: true})
10 | toc.push({
11 | level: level,
12 | slug: slug,
13 | title: raw
14 | })
15 | return "" + text + ""
16 | }
17 |
18 | marked.setOptions({
19 | renderer: renderer,
20 | highlight: function (code, lang) {
21 | try {
22 | return highlight(code, lang)
23 | } catch (e) {
24 | console.error(e)
25 | }
26 | }
27 | })
28 |
29 | function highlight (code, lang) {
30 | var out = lang ? hl.highlight(lang, code) : hl.highlightAuto(code)
31 | return out.value
32 | }
33 |
34 | module.exports = function parseMarkdown (markdown) {
35 | if (!markdown) return {html: '', toc: []}
36 | toc = []
37 | return {
38 | html: marked(markdown),
39 | toc: toc
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib/parse-options.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var xtend = require('xtend')
3 | var read = require('read-directory')
4 | var parseDocs = require('./parse-docs')
5 |
6 | module.exports = function (options) {
7 | options.dir = options.dir || process.cwd()
8 |
9 | if (typeof options.contents === 'object' && options.html && typeof options.html === 'object' && options.routes) {
10 | return options
11 | }
12 |
13 | var contentsPath = path.resolve(options.dir, options.contents)
14 | var markdownPath = path.resolve(options.dir, options.markdown)
15 | var contents = require(contentsPath)
16 | var markdown = read.sync(markdownPath, { extensions: false, filter: '**/*.md' })
17 |
18 | var docs = parseDocs(xtend(options, {
19 | markdown: markdown,
20 | contents: contents
21 | }))
22 |
23 | return xtend(options, docs)
24 | }
25 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "minidocs",
3 | "version": "4.2.3",
4 | "description": "build a simple site for your documentation",
5 | "main": "index.js",
6 | "style": "components/styles/index.css",
7 | "scripts": {
8 | "link:minidocs": "npm link && npm link minidocs",
9 | "start": "npm run link:minidocs && budo --dir examples/browser/ examples/browser/index.js:bundle.js --pushstate --live",
10 | "lint": "standard",
11 | "test": "npm run link:minidocs && tape tests/*.js | tap-spec",
12 | "build:example": "cd example && browserify index.js -p yo-yoify -o bundle.js",
13 | "deploy:example": "surge example minidocs-example.surge.sh",
14 | "build": "browserify docs/index.js -p yo-yoify -o docs/bundle.js",
15 | "deploy": "npm run build && surge site minidocs.surge.sh"
16 | },
17 | "bin": {
18 | "minidocs": "bin/index.js"
19 | },
20 | "browserify": {
21 | "transform": [
22 | "./transform.js",
23 | "sheetify/transform"
24 | ]
25 | },
26 | "repository": {
27 | "type": "git",
28 | "url": "git+https://github.com/freeman-lab/minidocs.git"
29 | },
30 | "keywords": [
31 | "docs",
32 | "documentation",
33 | "site",
34 | "build",
35 | "component"
36 | ],
37 | "author": "freeman-lab",
38 | "license": "MIT",
39 | "bugs": {
40 | "url": "https://github.com/freeman-lab/minidocs/issues"
41 | },
42 | "homepage": "https://github.com/freeman-lab/minidocs#readme",
43 | "dependencies": {
44 | "async.applyeachseries": "^0.5.2",
45 | "browserify": "^13.0.1",
46 | "choo": "^3.0.1",
47 | "create-html": "^1.0.0",
48 | "css-extract": "^1.1.0",
49 | "debug": "^2.2.0",
50 | "each-async": "^1.1.1",
51 | "execspawn": "^1.0.1",
52 | "exit": "^0.1.2",
53 | "github-avatar-url": "^1.0.0",
54 | "highlight.js": "^9.2.0",
55 | "insert-css": "^1.0.0",
56 | "is-absolute": "^0.2.5",
57 | "lodash.isarray": "^4.0.0",
58 | "lodash.isobject": "^3.0.2",
59 | "lodash.map": "^4.4.0",
60 | "marked": "^0.3.5",
61 | "minimist": "^1.2.0",
62 | "mkdirp": "^0.5.1",
63 | "parse-filepath": "^1.0.1",
64 | "read-directory": "^1.2.0",
65 | "rimraf": "^2.5.2",
66 | "sheetify": "^5.0.2",
67 | "sheetify-cssnext": "^1.0.7",
68 | "slug": "^0.9.1",
69 | "static-module": "^1.3.1",
70 | "tar": "^2.2.1",
71 | "tar-fs": "^1.13.2",
72 | "through2": "^2.0.1",
73 | "xtend": "^4.0.1",
74 | "yo-yoify": "^2.0.1"
75 | },
76 | "devDependencies": {
77 | "budo": "^8.1.0",
78 | "debug": "^2.2.0",
79 | "standard": "^6.0.8",
80 | "tap-spec": "^4.1.1",
81 | "tape": "^4.6.0",
82 | "tape-run": "^2.1.4"
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/parse.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./lib/parse-options')
2 |
--------------------------------------------------------------------------------
/styles/base.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: 'clear_sans_thinregular';
3 | color: rgb(80,80,80);
4 | margin: 0px;
5 | padding: 0px;
6 | overflow-y: scroll;
7 | }
8 |
9 | .contents-link {
10 | padding-left: 2%;
11 | cursor: pointer;
12 | padding-bottom: 2px;
13 | padding-right: 10px;
14 | }
15 |
16 | .contents-link:hover {
17 | background: rgb(255,255,255);
18 | }
19 |
20 | .contents-link-selected {
21 | background: rgb(255,255,255);
22 | }
23 |
24 | ::-webkit-scrollbar {
25 | width: 10px;
26 | }
27 |
28 | ::-webkit-scrollbar-track {
29 | background-color: white;
30 | }
31 |
32 | ::-webkit-scrollbar-thumb {
33 | background-color: rgba(0, 0, 0, 0.125);
34 | height: 20px;
35 | }
36 |
37 | ::-webkit-scrollbar-thumb:hover {
38 | background-color: rgba(0, 0, 0, 0.25);
39 | }
40 |
41 | ::-webkit-scrollbar-button {
42 | background-color: rgb(200,200,200);
43 | }
44 |
45 | ::-webkit-scrollbar-corner {
46 | background-color: black;
47 | }
48 |
--------------------------------------------------------------------------------
/styles/github-markdown.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: octicons-link;
3 | src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==) format('woff');
4 | }
5 |
6 | .markdown-body {
7 | -webkit-text-size-adjust: 100%;
8 | text-size-adjust: 100%;
9 | color: rgb(80,80,80);
10 | font-size: 16px;
11 | line-height: 1.6;
12 | word-wrap: break-word;
13 | }
14 |
15 | .markdown-body a {
16 | background-color: transparent;
17 | }
18 |
19 | .markdown-body a:active,
20 | .markdown-body a:hover {
21 | outline: 0;
22 | }
23 |
24 | .markdown-body strong {
25 | font-weight: bold;
26 | }
27 |
28 | .markdown-body h1 {
29 | font-size: 2em;
30 | margin: 0.67em 0;
31 | }
32 |
33 | .markdown-body img {
34 | border: 0;
35 | }
36 |
37 | .markdown-body hr {
38 | box-sizing: content-box;
39 | height: 0;
40 | }
41 |
42 | .markdown-body pre {
43 | overflow: auto;
44 | }
45 |
46 | .markdown-body code,
47 | .markdown-body kbd,
48 | .markdown-body pre {
49 | font-family: monospace, monospace;
50 | font-size: 1em;
51 | }
52 |
53 | .markdown-body input {
54 | color: inherit;
55 | font: inherit;
56 | margin: 0;
57 | }
58 |
59 | .markdown-body html input[disabled] {
60 | cursor: default;
61 | }
62 |
63 | .markdown-body input {
64 | line-height: normal;
65 | }
66 |
67 | .markdown-body input[type="checkbox"] {
68 | box-sizing: border-box;
69 | padding: 0;
70 | }
71 |
72 | .markdown-body table {
73 | border-collapse: collapse;
74 | border-spacing: 0;
75 | }
76 |
77 | .markdown-body td,
78 | .markdown-body th {
79 | padding: 0;
80 | }
81 |
82 | .markdown-body * {
83 | box-sizing: border-box;
84 | }
85 |
86 | .markdown-body input {
87 | font: 13px / 1.4 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
88 | }
89 |
90 | .markdown-body a {
91 | color: #4078c0;
92 | text-decoration: none;
93 | }
94 |
95 | .markdown-body a:hover,
96 | .markdown-body a:active {
97 | text-decoration: underline;
98 | }
99 |
100 | .markdown-body hr {
101 | height: 0;
102 | margin: 15px 0;
103 | overflow: hidden;
104 | background: transparent;
105 | border: 0;
106 | border-bottom: 1px solid #ddd;
107 | }
108 |
109 | .markdown-body hr:before {
110 | display: table;
111 | content: "";
112 | }
113 |
114 | .markdown-body hr:after {
115 | display: table;
116 | clear: both;
117 | content: "";
118 | }
119 |
120 | .markdown-body h1,
121 | .markdown-body h2,
122 | .markdown-body h3,
123 | .markdown-body h4,
124 | .markdown-body h5,
125 | .markdown-body h6 {
126 | margin-top: 15px;
127 | line-height: 1.1;
128 | }
129 |
130 | .markdown-body h1 {
131 | font-size: 30px;
132 | }
133 |
134 | .markdown-body h2 {
135 | font-size: 21px;
136 | }
137 |
138 | .markdown-body h3 {
139 | font-size: 16px;
140 | }
141 |
142 | .markdown-body h4 {
143 | font-size: 14px;
144 | }
145 |
146 | .markdown-body h5 {
147 | font-size: 12px;
148 | }
149 |
150 | .markdown-body h6 {
151 | font-size: 11px;
152 | }
153 |
154 | .markdown-body blockquote {
155 | margin: 0;
156 | }
157 |
158 | .markdown-body ul,
159 | .markdown-body ol {
160 | padding: 0;
161 | margin-top: 0;
162 | margin-bottom: 0;
163 | }
164 |
165 | .markdown-body ol ol,
166 | .markdown-body ul ol {
167 | list-style-type: lower-roman;
168 | }
169 |
170 | .markdown-body ul ul ol,
171 | .markdown-body ul ol ol,
172 | .markdown-body ol ul ol,
173 | .markdown-body ol ol ol {
174 | list-style-type: lower-alpha;
175 | }
176 |
177 | .markdown-body dd {
178 | margin-left: 0;
179 | }
180 |
181 | .markdown-body code {
182 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
183 | font-size: 12px;
184 | }
185 |
186 | .markdown-body pre {
187 | margin-top: 0;
188 | margin-bottom: 0;
189 | font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace;
190 | }
191 |
192 | .markdown-body .select::-ms-expand {
193 | opacity: 0;
194 | }
195 |
196 | .markdown-body .octicon {
197 | font: normal normal normal 16px/1 octicons-link;
198 | display: inline-block;
199 | text-decoration: none;
200 | text-rendering: auto;
201 | -webkit-font-smoothing: antialiased;
202 | -moz-osx-font-smoothing: grayscale;
203 | -webkit-user-select: none;
204 | -moz-user-select: none;
205 | -ms-user-select: none;
206 | user-select: none;
207 | }
208 |
209 | .markdown-body .octicon-link:before {
210 | content: '\f05c';
211 | }
212 |
213 | .markdown-body:before {
214 | display: table;
215 | content: "";
216 | }
217 |
218 | .markdown-body:after {
219 | display: table;
220 | clear: both;
221 | content: "";
222 | }
223 |
224 | .markdown-body>*:first-child {
225 | margin-top: 0 !important;
226 | }
227 |
228 | .markdown-body>*:last-child {
229 | margin-bottom: 0 !important;
230 | }
231 |
232 | .markdown-body a:not([href]) {
233 | color: inherit;
234 | text-decoration: none;
235 | }
236 |
237 | .markdown-body .anchor {
238 | display: inline-block;
239 | padding-right: 2px;
240 | margin-left: -18px;
241 | }
242 |
243 | .markdown-body .anchor:focus {
244 | outline: none;
245 | }
246 |
247 | .markdown-body h1,
248 | .markdown-body h2,
249 | .markdown-body h3,
250 | .markdown-body h4,
251 | .markdown-body h5,
252 | .markdown-body h6 {
253 | margin-top: 1em;
254 | margin-bottom: 16px;
255 | font-weight: bold;
256 | line-height: 1.4;
257 | }
258 |
259 | .markdown-body h1 .octicon-link,
260 | .markdown-body h2 .octicon-link,
261 | .markdown-body h3 .octicon-link,
262 | .markdown-body h4 .octicon-link,
263 | .markdown-body h5 .octicon-link,
264 | .markdown-body h6 .octicon-link {
265 | color: #000;
266 | vertical-align: middle;
267 | visibility: hidden;
268 | }
269 |
270 | .markdown-body h1:hover .anchor,
271 | .markdown-body h2:hover .anchor,
272 | .markdown-body h3:hover .anchor,
273 | .markdown-body h4:hover .anchor,
274 | .markdown-body h5:hover .anchor,
275 | .markdown-body h6:hover .anchor {
276 | text-decoration: none;
277 | }
278 |
279 | .markdown-body h1:hover .anchor .octicon-link,
280 | .markdown-body h2:hover .anchor .octicon-link,
281 | .markdown-body h3:hover .anchor .octicon-link,
282 | .markdown-body h4:hover .anchor .octicon-link,
283 | .markdown-body h5:hover .anchor .octicon-link,
284 | .markdown-body h6:hover .anchor .octicon-link {
285 | visibility: visible;
286 | }
287 |
288 | .markdown-body h1 {
289 | padding-bottom: 0.3em;
290 | font-size: 2.25em;
291 | line-height: 1.2;
292 | margin-top: 15px;
293 | }
294 |
295 | .markdown-body h1 .anchor {
296 | line-height: 1;
297 | }
298 |
299 | .markdown-body h2 {
300 | padding-bottom: 0.3em;
301 | font-size: 1.75em;
302 | line-height: 1.225;
303 | }
304 |
305 | .markdown-body h2 .anchor {
306 | line-height: 1;
307 | }
308 |
309 | .markdown-body h3 {
310 | font-size: 1.5em;
311 | line-height: 1.43;
312 | }
313 |
314 | .markdown-body h3 .anchor {
315 | line-height: 1.2;
316 | }
317 |
318 | .markdown-body h4 {
319 | font-size: 1.25em;
320 | }
321 |
322 | .markdown-body h4 .anchor {
323 | line-height: 1.2;
324 | }
325 |
326 | .markdown-body h5 {
327 | font-size: 1em;
328 | }
329 |
330 | .markdown-body h5 .anchor {
331 | line-height: 1.1;
332 | }
333 |
334 | .markdown-body h6 {
335 | font-size: 1em;
336 | color: #777;
337 | }
338 |
339 | .markdown-body h6 .anchor {
340 | line-height: 1.1;
341 | }
342 |
343 | .markdown-body p,
344 | .markdown-body blockquote,
345 | .markdown-body ul,
346 | .markdown-body ol,
347 | .markdown-body dl,
348 | .markdown-body table,
349 | .markdown-body pre {
350 | margin-top: 0;
351 | margin-bottom: 16px;
352 | }
353 |
354 | .markdown-body hr {
355 | height: 4px;
356 | padding: 0;
357 | margin: 16px 0;
358 | background-color: #e7e7e7;
359 | border: 0 none;
360 | }
361 |
362 | .markdown-body ul,
363 | .markdown-body ol {
364 | padding-left: 2em;
365 | }
366 |
367 | .markdown-body ul ul,
368 | .markdown-body ul ol,
369 | .markdown-body ol ol,
370 | .markdown-body ol ul {
371 | margin-top: 0;
372 | margin-bottom: 0;
373 | }
374 |
375 | .markdown-body li>p {
376 | margin-top: 16px;
377 | }
378 |
379 | .markdown-body dl {
380 | padding: 0;
381 | }
382 |
383 | .markdown-body dl dt {
384 | padding: 0;
385 | margin-top: 16px;
386 | font-size: 1em;
387 | font-style: italic;
388 | font-weight: bold;
389 | }
390 |
391 | .markdown-body dl dd {
392 | padding: 0 16px;
393 | margin-bottom: 16px;
394 | }
395 |
396 | .markdown-body blockquote {
397 | padding: 0 15px;
398 | color: #777;
399 | border-left: 4px solid #ddd;
400 | }
401 |
402 | .markdown-body blockquote>:first-child {
403 | margin-top: 0;
404 | }
405 |
406 | .markdown-body blockquote>:last-child {
407 | margin-bottom: 0;
408 | }
409 |
410 | .markdown-body table {
411 | display: block;
412 | width: 100%;
413 | overflow: auto;
414 | word-break: normal;
415 | word-break: keep-all;
416 | }
417 |
418 | .markdown-body table th {
419 | font-weight: bold;
420 | }
421 |
422 | .markdown-body table th,
423 | .markdown-body table td {
424 | padding: 6px 13px;
425 | border: 1px solid #ddd;
426 | }
427 |
428 | .markdown-body table tr {
429 | background-color: #fff;
430 | border-top: 1px solid #ccc;
431 | }
432 |
433 | .markdown-body table tr:nth-child(2n) {
434 | background-color: #f8f8f8;
435 | }
436 |
437 | .markdown-body img {
438 | max-width: 100%;
439 | box-sizing: content-box;
440 | background-color: #fff;
441 | }
442 |
443 | .markdown-body code {
444 | padding: 0;
445 | padding-top: 0.2em;
446 | padding-bottom: 0.2em;
447 | margin: 0;
448 | font-size: 85%;
449 | background-color: rgba(0,0,0,0.04);
450 | border-radius: 3px;
451 | }
452 |
453 | .markdown-body code:before,
454 | .markdown-body code:after {
455 | letter-spacing: -0.2em;
456 | content: "\00a0";
457 | }
458 |
459 | .markdown-body pre>code {
460 | padding: 0;
461 | margin: 0;
462 | font-size: 100%;
463 | word-break: normal;
464 | white-space: pre;
465 | background: transparent;
466 | border: 0;
467 | }
468 |
469 | .markdown-body .highlight {
470 | margin-bottom: 16px;
471 | }
472 |
473 | .markdown-body .highlight pre,
474 | .markdown-body pre {
475 | padding: 16px;
476 | overflow: auto;
477 | font-size: 85%;
478 | line-height: 1.45;
479 | background-color: #f7f7f7;
480 | border-radius: 3px;
481 | }
482 |
483 | .markdown-body .highlight pre {
484 | margin-bottom: 0;
485 | word-break: normal;
486 | }
487 |
488 | .markdown-body pre {
489 | word-wrap: normal;
490 | }
491 |
492 | .markdown-body pre code {
493 | display: inline;
494 | max-width: initial;
495 | padding: 0;
496 | margin: 0;
497 | overflow: initial;
498 | line-height: inherit;
499 | word-wrap: normal;
500 | background-color: transparent;
501 | border: 0;
502 | }
503 |
504 | .markdown-body pre code:before,
505 | .markdown-body pre code:after {
506 | content: normal;
507 | }
508 |
509 | .markdown-body kbd {
510 | display: inline-block;
511 | padding: 3px 5px;
512 | font-size: 11px;
513 | line-height: 10px;
514 | color: #555;
515 | vertical-align: middle;
516 | background-color: #fcfcfc;
517 | border: solid 1px #ccc;
518 | border-bottom-color: #bbb;
519 | border-radius: 3px;
520 | box-shadow: inset 0 -1px 0 #bbb;
521 | }
522 |
523 | .markdown-body .pl-c {
524 | color: #969896;
525 | }
526 |
527 | .markdown-body .pl-c1,
528 | .markdown-body .pl-s .pl-v {
529 | color: #0086b3;
530 | }
531 |
532 | .markdown-body .pl-e,
533 | .markdown-body .pl-en {
534 | color: #795da3;
535 | }
536 |
537 | .markdown-body .pl-s .pl-s1,
538 | .markdown-body .pl-smi {
539 | color: #333;
540 | }
541 |
542 | .markdown-body .pl-ent {
543 | color: #63a35c;
544 | }
545 |
546 | .markdown-body .pl-k {
547 | color: #a71d5d;
548 | }
549 |
550 | .markdown-body .pl-pds,
551 | .markdown-body .pl-s,
552 | .markdown-body .pl-s .pl-pse .pl-s1,
553 | .markdown-body .pl-sr,
554 | .markdown-body .pl-sr .pl-cce,
555 | .markdown-body .pl-sr .pl-sra,
556 | .markdown-body .pl-sr .pl-sre {
557 | color: #183691;
558 | }
559 |
560 | .markdown-body .pl-v {
561 | color: #ed6a43;
562 | }
563 |
564 | .markdown-body .pl-id {
565 | color: #b52a1d;
566 | }
567 |
568 | .markdown-body .pl-ii {
569 | background-color: #b52a1d;
570 | color: #f8f8f8;
571 | }
572 |
573 | .markdown-body .pl-sr .pl-cce {
574 | color: #63a35c;
575 | font-weight: bold;
576 | }
577 |
578 | .markdown-body .pl-ml {
579 | color: #693a17;
580 | }
581 |
582 | .markdown-body .pl-mh,
583 | .markdown-body .pl-mh .pl-en,
584 | .markdown-body .pl-ms {
585 | color: #1d3e81;
586 | font-weight: bold;
587 | }
588 |
589 | .markdown-body .pl-mq {
590 | color: #008080;
591 | }
592 |
593 | .markdown-body .pl-mi {
594 | color: #333;
595 | font-style: italic;
596 | }
597 |
598 | .markdown-body .pl-mb {
599 | color: #333;
600 | font-weight: bold;
601 | }
602 |
603 | .markdown-body .pl-md {
604 | background-color: #ffecec;
605 | color: #bd2c00;
606 | }
607 |
608 | .markdown-body .pl-mi1 {
609 | background-color: #eaffea;
610 | color: #55a532;
611 | }
612 |
613 | .markdown-body .pl-mdr {
614 | color: #795da3;
615 | font-weight: bold;
616 | }
617 |
618 | .markdown-body .pl-mo {
619 | color: #1d3e81;
620 | }
621 |
622 | .markdown-body kbd {
623 | display: inline-block;
624 | padding: 3px 5px;
625 | font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace;
626 | line-height: 10px;
627 | color: #555;
628 | vertical-align: middle;
629 | background-color: #fcfcfc;
630 | border: solid 1px #ccc;
631 | border-bottom-color: #bbb;
632 | border-radius: 3px;
633 | box-shadow: inset 0 -1px 0 #bbb;
634 | }
635 |
636 | .markdown-body .task-list-item {
637 | list-style-type: none;
638 | }
639 |
640 | .markdown-body .task-list-item+.task-list-item {
641 | margin-top: 3px;
642 | }
643 |
644 | .markdown-body .task-list-item input {
645 | margin: 0 0.35em 0.25em -1.6em;
646 | vertical-align: middle;
647 | }
648 |
649 | .markdown-body :checked+.radio-label {
650 | z-index: 1;
651 | position: relative;
652 | border-color: #4078c0;
653 | }
654 |
--------------------------------------------------------------------------------
/styles/highlighting/tomorrow-night.css:
--------------------------------------------------------------------------------
1 | /* Tomorrow Night Theme */
2 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
3 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */
4 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
5 |
6 | /* Tomorrow Comment */
7 | .hljs-comment,
8 | .hljs-quote {
9 | color: #969896;
10 | }
11 |
12 | /* Tomorrow Red */
13 | .hljs-variable,
14 | .hljs-template-variable,
15 | .hljs-tag,
16 | .hljs-name,
17 | .hljs-selector-id,
18 | .hljs-selector-class,
19 | .hljs-regexp,
20 | .hljs-deletion {
21 | color: #cc6666;
22 | }
23 |
24 | /* Tomorrow Orange */
25 | .hljs-number,
26 | .hljs-built_in,
27 | .hljs-builtin-name,
28 | .hljs-literal,
29 | .hljs-type,
30 | .hljs-params,
31 | .hljs-meta,
32 | .hljs-link {
33 | color: #de935f;
34 | }
35 |
36 | /* Tomorrow Yellow */
37 | .hljs-attribute {
38 | color: #f0c674;
39 | }
40 |
41 | /* Tomorrow Green */
42 | .hljs-string,
43 | .hljs-symbol,
44 | .hljs-bullet,
45 | .hljs-addition {
46 | color: #b5bd68;
47 | }
48 |
49 | /* Tomorrow Blue */
50 | .hljs-title,
51 | .hljs-section {
52 | color: #81a2be;
53 | }
54 |
55 | /* Tomorrow Purple */
56 | .hljs-keyword,
57 | .hljs-selector-tag {
58 | color: #b294bb;
59 | }
60 |
61 | .hljs {
62 | display: block;
63 | overflow-x: auto;
64 | background: #1d1f21;
65 | color: #c5c8c6;
66 | padding: 0.5em;
67 | }
68 |
69 | .hljs-emphasis {
70 | font-style: italic;
71 | }
72 |
73 | .hljs-strong {
74 | font-weight: bold;
75 | }
76 |
--------------------------------------------------------------------------------
/styles/highlighting/tomorrow.css:
--------------------------------------------------------------------------------
1 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
2 |
3 | /* Tomorrow Comment */
4 | .hljs-comment,
5 | .hljs-quote {
6 | color: #8e908c;
7 | }
8 |
9 | /* Tomorrow Red */
10 | .hljs-variable,
11 | .hljs-template-variable,
12 | .hljs-tag,
13 | .hljs-name,
14 | .hljs-selector-id,
15 | .hljs-selector-class,
16 | .hljs-regexp,
17 | .hljs-deletion {
18 | color: #c82829;
19 | }
20 |
21 | /* Tomorrow Orange */
22 | .hljs-number,
23 | .hljs-built_in,
24 | .hljs-builtin-name,
25 | .hljs-literal,
26 | .hljs-type,
27 | .hljs-params,
28 | .hljs-meta,
29 | .hljs-link {
30 | color: #f5871f;
31 | }
32 |
33 | /* Tomorrow Yellow */
34 | .hljs-attribute {
35 | color: #eab700;
36 | }
37 |
38 | /* Tomorrow Green */
39 | .hljs-string,
40 | .hljs-symbol,
41 | .hljs-bullet,
42 | .hljs-addition {
43 | color: #718c00;
44 | }
45 |
46 | /* Tomorrow Blue */
47 | .hljs-title,
48 | .hljs-section {
49 | color: #4271ae;
50 | }
51 |
52 | /* Tomorrow Purple */
53 | .hljs-keyword,
54 | .hljs-selector-tag {
55 | color: #8959a8;
56 | }
57 |
58 | .hljs {
59 | display: block;
60 | overflow-x: auto;
61 | background: white;
62 | color: #4d4d4c;
63 | padding: 0.5em;
64 | }
65 |
66 | .hljs-emphasis {
67 | font-style: italic;
68 | }
69 |
70 | .hljs-strong {
71 | font-weight: bold;
72 | }
73 |
--------------------------------------------------------------------------------
/styles/index.css:
--------------------------------------------------------------------------------
1 | @import "./base.css";
2 | @import "./fonts.css";
3 | @import "./github-markdown.css";
4 | @import "./highlighting/tomorrow.css";
--------------------------------------------------------------------------------
/tests/app.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var test = require('tape')
3 |
4 | var createApp = require('../app')
5 | var parseOptions = require('../lib/parse-options')
6 |
7 | test('app.js returns choo app', function (t) {
8 | var app = createApp(parseOptions({
9 | contents: path.join(__dirname, 'fixtures/browser/contents.js'),
10 | markdown: path.join(__dirname, 'fixtures/browser/docs'),
11 | dir: __dirname
12 | }))
13 | t.ok(app)
14 | t.ok(app.start)
15 | t.ok(app.toString)
16 | t.end()
17 | })
18 |
19 | test('app.toString() returns html', function (t) {
20 | var options = parseOptions({
21 | contents: path.join(__dirname, 'fixtures/browser/contents.js'),
22 | markdown: path.join(__dirname, 'fixtures/browser/docs'),
23 | dir: __dirname
24 | })
25 |
26 | var app = createApp(options)
27 | var html = app.toString('/', options)
28 | t.ok(html)
29 | t.end()
30 | })
31 |
--------------------------------------------------------------------------------
/tests/cli.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var path = require('path')
3 | var test = require('tape')
4 | var exec = require('execspawn')
5 | var each = require('each-async')
6 |
7 | test('basic cli usage', function (t) {
8 | t.plan(1)
9 |
10 | var cmd = exec('minidocs ./fixtures/cli/docs -c ./fixtures/cli/contents.js -o site/', {
11 | cwd: __dirname
12 | })
13 |
14 | cmd.on('close', function () {
15 | check(['bundle.css', 'bundle.js', 'index.html'], function (err) {
16 | t.notOk(err)
17 | t.end()
18 | })
19 | })
20 | })
21 |
22 | function check (filepaths, done) {
23 | each(filepaths, function (item, i, next) {
24 | var filepath = path.join(__dirname, 'site', item)
25 | fs.stat(filepath, function (err, stats) {
26 | if (err) return next(err)
27 | next()
28 | })
29 | }, done)
30 | }
31 |
--------------------------------------------------------------------------------
/tests/fixtures/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/freeman-lab/minidocs/44a9929c27595a6bea83dddec6f2ca45287bac70/tests/fixtures/.DS_Store
--------------------------------------------------------------------------------
/tests/fixtures/browser/app.js:
--------------------------------------------------------------------------------
1 | var minidocs = require('minidocs')
2 |
3 | var app = minidocs({
4 | contents: './contents.js',
5 | markdown: './markdown'
6 | })
7 |
8 | var tree = app.start()
9 | document.body.appendChild(tree)
10 |
--------------------------------------------------------------------------------
/tests/fixtures/browser/contents.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | a: 'markdown/a.md',
3 | b: 'markdown/b.md',
4 | c: 'markdown/c.md'
5 | }
6 |
--------------------------------------------------------------------------------
/tests/fixtures/browser/docs/a.md:
--------------------------------------------------------------------------------
1 | a
--------------------------------------------------------------------------------
/tests/fixtures/browser/docs/b.md:
--------------------------------------------------------------------------------
1 | b
--------------------------------------------------------------------------------
/tests/fixtures/browser/docs/c.md:
--------------------------------------------------------------------------------
1 | c
--------------------------------------------------------------------------------
/tests/fixtures/cli/contents.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | a: 'markdown/a.md',
3 | b: 'markdown/b.md',
4 | c: 'markdown/c.md'
5 | }
6 |
--------------------------------------------------------------------------------
/tests/fixtures/cli/docs/a.md:
--------------------------------------------------------------------------------
1 | a
--------------------------------------------------------------------------------
/tests/fixtures/cli/docs/b.md:
--------------------------------------------------------------------------------
1 | b
--------------------------------------------------------------------------------
/tests/fixtures/cli/docs/c.md:
--------------------------------------------------------------------------------
1 | c
--------------------------------------------------------------------------------
/tests/index.js:
--------------------------------------------------------------------------------
1 | require('./parse-options')
2 | require('./node')
3 | require('./app')
4 | require('./cli')
5 |
--------------------------------------------------------------------------------
/tests/node.js:
--------------------------------------------------------------------------------
1 | var test = require('tape')
2 |
3 | var createApp = require('../app')
4 | var parseOptions = require('../lib/parse-options')
5 |
6 | test('app.js returns choo app', function (t) {
7 | var options = parseOptions({
8 | contents: './fixtures/browser/contents.js',
9 | markdown: './fixtures/browser/docs',
10 | dir: __dirname
11 | })
12 |
13 | var app = createApp(options)
14 | t.ok(app)
15 | t.ok(app.start)
16 | t.ok(app.toString)
17 | t.end()
18 | })
19 |
20 | test('app.toString() returns html', function (t) {
21 | var options = parseOptions({
22 | contents: './fixtures/browser/contents.js',
23 | markdown: './fixtures/browser/docs',
24 | dir: __dirname
25 | })
26 |
27 | var app = createApp(options)
28 | var html = app.toString('/', options)
29 | t.ok(html)
30 | t.end()
31 | })
32 |
--------------------------------------------------------------------------------
/tests/parse-options.js:
--------------------------------------------------------------------------------
1 | var test = require('tape')
2 | var parseOptions = require('../lib/parse-options')
3 |
4 | test('parseOptions returns contents, routes, html', function (t) {
5 | var options = parseOptions({
6 | contents: './fixtures/browser/contents.js',
7 | markdown: './fixtures/browser/docs',
8 | dir: __dirname
9 | })
10 |
11 | t.ok(options)
12 | t.ok(options.html)
13 | t.ok(options.contents)
14 | t.ok(options.routes)
15 | t.ok(options.routes.index)
16 | t.ok(options.routes.a)
17 | t.equal(options.html.a, 'a
\n')
18 | t.end()
19 | })
20 |
--------------------------------------------------------------------------------
/transform.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var through = require('through2')
3 | var staticModule = require('static-module')
4 |
5 | var parseOptions = require('./lib/parse-options')
6 |
7 | module.exports = function minidocsTransform (filename) {
8 | if (/\.json$/.test(filename)) return through()
9 | var basedir = path.dirname(filename)
10 |
11 | var vars = {
12 | __filename: filename,
13 | __dirname: basedir
14 | }
15 |
16 | var sm = staticModule({
17 | minidocs: function (options) {
18 | options.dir = basedir
19 | var parsedOptions = parseOptions(options)
20 | var stream = through()
21 | stream.push(`require('minidocs')(${JSON.stringify(parsedOptions)})`)
22 | stream.push(null)
23 | return stream
24 | }
25 | }, { vars: vars, varModules: {} })
26 |
27 | return sm
28 | }
29 |
--------------------------------------------------------------------------------