npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@jesterxl/hm-doc

v1.2.1

Published

Generates simple markdown documentation from Hindley Milner and optional block comments in JavaScript code.

Downloads

13

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:

  1. write your documentation in Markdown inside of comment blocks
  2. write your Hindley Milner expression in a comment line
  3. 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:

  1. Hindle-Milner goes diretly above the function as a single like comment //.
  2. Markdown goes in /* */ directly above of the Hindley-Milner single line comment.
  3. 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)