@jesterxl/hm-doc
v1.2.1
Published
Generates simple markdown documentation from Hindley Milner and optional block comments in JavaScript code.
Downloads
13
Maintainers
Readme
hm-doc
What: Generates simple markdown documentation from Hindley-Milner single line //
comments and optional /* */
block comments in JavaScript code.
Why: This is an alternative for Functional Programmers who use curried methods and don't like the pain of JSDocs yet love the functionality of jsdoc-to-markdown.
How: You have 3 options:
- Parse files and code comments, and give you an Array of those results.
- Parse files and code comments, inject into a Handlebars template, give you the String result.
- Parse files and code comments, inject into a Handlebars template, write to a file.
Contents
Installation
npm i @jesterxl/hm-doc --save
Commandline Usage
See if it installed ok:
npx hm-doc --version
Parse all code and comments in your src
directory:
npx hm-doc --files './src/**/*.js'
To exclude a directory, add an ignore (-i for short):
npx hm-doc --files './src/**/*.js' --ignore './src/**/examples'
Same as above, then put into a Handlebars template, then show in your Terminal:
npx hm-doc --files './src/**/*.js' --template README_template.hbs
Same as above, then write your documentation to a file:
npx hm-doc --files './src/**/*.js' --template README_template.hbs --output README.md
To see debug information, prefix the command (or set) the DEBUG
environment variable to hm-doc
, or *
to see every module:
DEBUG="hm-doc" npx hm-doc --files './src/**/*.js' --template README_template.hbs --output README.md
For more information, type npx hm-doc --help
.
For using the code directly, see the API docs below. We used hm-doc
to document hm-doc
.
Prior Art
I just copied how Haskell's Haddock, and more specifically Elm document their code. In those languages, the type signature is part of the code.
Here's how Elm documents the isEmpty
Array method:
{-| Determine if an array is empty.
isEmpty empty == True
-}
isEmpty : Array a -> Bool
isEmpty (Array_elm_builtin len _ _ _) =
len == 0
And here's how you'd do it in JavaScript using hm-doc
:
/* Determine if an array is empty.
isEmpty([]) === true
*/
// isEmpty :: Array a -> Bool
const isEmpty = array =>
Array.isArray(array)
&& array.length === 0
How Do I Document My Code?
Follow these 3 steps:
- write your documentation in Markdown inside of comment blocks
- write your Hindley Milner expression in a comment line
- Create a
README_template.hbs
file and put a Handlebars block ( i.e.{{#hmdoc}}{{/hmdoc}}
) where you want your API docs
Step 1 and 2: Code Comments
For example, here is an test/example.js
file that has a block comment with markdown and HTML inside a comment block. Immediately below that is the line comment with the Hindley Milner syntax. Immediately below that is the method.
NOTE: If you only do a code comment line with Hindly-Milner syntax, we'll just use that, but obviously longer markdown descriptions are encouraged. If you're in a hurry, or just don't know your public API yet, just use hm syntax with single line comments to get moving.
/*
### Description
Loads the contents of a URL via a GET request, and wraps the request.get in a Promise.
| Param | Type | Description |
| ------ | -------------------- | ----------------------------- |
| request | <code>request</code> | A Node request or request-promise module (i.e. require('request')) |
| url | <code>String</code> | The URL you wish to load. |
### Returns
<code>Promise</code> - Promise contains either the text content of the GET request or the <code>Error</code>.
### Example
<pre><code class="language-javascript">
loadURL
(require('request'))
('http://google.com')
.then(result => console.log("result:", result))
.catch(error => console.log("error:", error))
</code></pre>
*/
// loadURL :: request -> url -> Promise
const loadURL = request => url =>
new Promise((success, failure) =>
request.get(url, (err, res, body) =>
err
? failure(err)
: success(body)
)
)
That'll produce markdown that looks like the following:
// ------ EXAMPLE BELOW ------
loadURL
request -> url -> Promise
Description
Loads the contents of a URL via a GET request, and wraps the request.get in a Promise.
| Param | Type | Description | | ------ | -------------------- | ----------------------------- | | request | request | A Node request or request-promise module (i.e. require('request')) | | url | String | The URL you wish to load. |
Returns
Promise - Promise contains either the text content of the GET request or the Error.
Example
// ------ EXAMPLE ABOVE ------
Remember:
- Hindle-Milner goes diretly above the function as a single like comment
//
. - Markdown goes in
/* */
directly above of the Hindley-Milner single line comment. - 2 is optional, but encouraged.
Step 3: Handlebars Template File
The assumption is you're writing a README.md
for Github.com or your internal company's Enterprise Github. Github can read README.md files at the top of the project, and display a nice webpage when you come to the repository. The webpage is built by converting the markdown in README.md
. Handlebars, a way to dynamically build HTML documents, allows you to create your own markup tags. We use Handlebars so we can write in normal Markdown, but then dynamically inject things like API documentation where we need it with code.
If you didn't use Handlebars, you'd have to either copy paste the updated documentation each time into README.md each time you updated your code documentation.
Create a README_template.hbs
file. We use .hbs
as a filename which is standard for Handlebars, and append _template
to remove confusion. I've accidentally made changes in README.md
, forgot to check in my changes to git, re-ran the build documentation command, and it overwrote my README.md
, deleting all my chagnes. This way, if you have README_template.hbs
open and are write things, you can be safe vs. relying on the file extension which is small and easy to miss.
Here's ours:
### Our Library
Sup! This is our library documentation. Install it like `npm i something --save`, and you're ready to do things.
### API
Below are all the functions we support in the public API.
{{#hmdoc}}{{/hmdoc}}
### Support
Email us, we're here to help!
Notice the weird, double squiggly braces with #hmdoc
in the middle under the API section. That's our custom Handlebars function. When you convert Handlebars to Markdown, it'll replace those weird tags with all your API documentation. If we save this file README_template.hbs
, we'll then run our hm-doc
command like so:
hm-doc -f './src/**/*.js' -t README_template.hbs -o README.md
If we run that, then open it up, it'll render close to this:
// ------ EXAMPLE BELOW ------
Our Library
Sup! This is our library documentation. Install it like npm i something --save
, and you're ready to do things.
API
Below are all the functions we support in the public API.
loadURL
request -> url -> Promise
Description
Loads the contents of a URL via a GET request, and wraps the request.get in a Promise.
| Param | Type | Description | | ------ | -------------------- | ----------------------------- | | request | request | A Node request or request-promise module (i.e. require('request')) | | url | String | The URL you wish to load. |
Returns
Promise - Promise contains either the text content of the GET request or the Error.
Example
Support
Email us, we're here to help!
// ------ EXAMPLE ABOVE ------
Pretty rad, right?
API Documentation
Below is the hm-doc
API if you wish to use the code directly instead of the command line.
index.js
.parse
glob -> globOptions -> Promise
Description
Reads a file glob and parses all comments out and all Hindley-Milner type signatures it finds in the file(s). You'll get an Array of Objects that have the filename as the key, and the value is an Array of comment lines and comment blocks it found.
| Param | Type | Description |
| --------------------------- | ------------------- | ----------------------------- |
| glob | String | A glob String, like "example.js" or "./folder/file.js" or for all files in src
, "./src/** /*.js (remove the space after the 2 stars, heh). See glob for more information: https://www.npmjs.com/package/glob |
| globOptions | Object | Glob options Object. Feel free to use {} as default, else refer to the glob documentation on what options you can use. https://github.com/isaacs/node-glob#options
Returns
Promise - Promise contains a list of parsed comments, or an Error as to why it failed.
Example
parse
('./src/** /*.js') // ignore space after 2 stars
({ ignore: 'example' })
.then(console.log)
.catch(console.log)
.getMarkdown
glob -> globOptions -> handlebarsTemplateFile -> Promise
Description
Reads a file glob, parses all comments out and all Hindley-Milner type signatures, reads your Handlebars template, compiles it with the parsed comments, and prints out the compiled text.
| Param | Type | Description |
| --------------------------- | ------------------- | ----------------------------- |
| glob | String | A glob String, like "example.js" or "./folder/file.js" or for all files in src
, "./src/** /*.js (remove the space after the 2 stars, heh). See glob for more information: https://www.npmjs.com/package/glob |
| globOptions | Object | Glob options Object. Feel free to use {} as default, else refer to the glob documentation on what options you can use. https://github.com/isaacs/node-glob#options
| handlebarsTemplateFile | String | Filepath to the Handlebars template file you want to inject your code comments into. It should have a string {{#hmdoc}}{{/hmdoc}} somewhere in there; this is where hm-doc will render the API documentation. See http://handlebarsjs.com/ for more information. |
Returns
Promise - Promise contains either the text content of the of the rendered Markdown or an error as to why it failed.
Example
getMarkdown
('./src/** /*.js') // ignore space after 2 stars
({ ignore: './examples' })
('README_template.hbs')
.then(console.log)
.catch(console.log)
.writeMarkdownFile
glob -> handlebarsTemplateFile -> outputFilename -> Promise
Description
Reads a file glob, parses all comments out and all Hindley-Milner type signatures, reads your Handlebars template, compiles it with the parsed comments, and finally writes that compiled text to a file.
| Param | Type | Description |
| --------------------------- | ------------------- | ----------------------------- |
| glob | String | A glob String, like "example.js" or "./folder/file.js" or for all files in src
, "./src/** /*.js (remove the space after the 2 stars, heh). See glob for more information: https://www.npmjs.com/package/glob |
| globOptions | Object | Glob options Object. Feel free to use {} as default, else refer to the glob documentation on what options you can use. https://github.com/isaacs/node-glob#options
| handlebarsTemplateFile | String | Filepath to the Handlebars template file you want to inject your code comments into. It should have a string {{#hmdoc}}{{/hmdoc}} somewhere in there; this is where hm-doc will render the API documentation. See http://handlebarsjs.com/ for more information. |
| outputFilename | String | File you want to write your rendered Markdown to, probably README.md
.
Returns
Promise - Promise contains a success message of the file it wrote, an error as to why it failed.
Example
writeMarkdownFile
('./src/** /*.js') // ignore space after 2 stars
({ ignore: '' })
('README_template.hbs')
('README.md')
.then(console.log)
.catch(console.log)