# @ashnazg/mochadocs

> ### 1.1 * Scanning a path for test JS's (including the default path of "test/") now reads mjs and cjs in, not just js.

Latest version **1.1.0** (published 2024-07-03) · MIT license · 0 weekly downloads

## Install

```sh
npm install @ashnazg/mochadocs
pnpm add @ashnazg/mochadocs
yarn add @ashnazg/mochadocs
bun add @ashnazg/mochadocs
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.1.0 |
| Published | 2024-07-03 |
| First published | 2022-04-23 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 1 |
| Unpacked size | 21 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Xander |
| Maintainers | xander |

## Links

- npm: https://www.npmjs.com/package/@ashnazg/mochadocs
- npm.io page: https://npm.io/package/@ashnazg/mochadocs

## Dependencies (1)

- [@ashnazg/utils](https://npm.io/package/@ashnazg/utils.md) ^0.5.0

## Recent versions

- 1.1.0 (latest) — 2024-07-03
- 1.0.2 — 2022-08-08
- 1.0.1 — 2022-04-25
- 1.0.0 — 2022-04-23

## README

**Purpose**

I really wanted something like sphinx or doxygen but with the least possible syntax and the most DRY I could think of.

Principles:
1. Readable code is the best documentation.
2. Readable tests is the 2nd best documentation.
3. While real design docs shouldn't be crammed into this format, the unit tests file be a significant (hyperlinked) participant reduces how much pure prose has to be written.

## Releases
### 1.1
* Scanning a path for test JS's (including the default path of "test/") now reads mjs and cjs in, not just js.

## Reads Mocha test files and emits a README.md

### Default behavior
reads from `./test/` and writes `./README.md`
The file you're reading was created by running:
```js
const mochadocs = require('@ashnazg/mochadocs');
await mochadocs();
```
... and there are asserts on this page because you're reading the unit tests.
### what's emitted
1. Lines that begin with `///` are emitted as markdown.
1. `describe(...)` is parsed to make h2's
1. `it(...)` is parsed to make h3's
1. Lines of code or vanilla comments are also emitted, but wrapped in a pre-block.

### Supports Transclusion
A line that is exactly `///{{filename}}` will try to cat that filename in.

**big Nota Bene:** This is relative to the PWD of the process, NOT relative to the file the transclusion is present in.

The Release section on this page was transcluded from another file by saying:
`///{{CHANGELOG.md}}`

## Options

### Defaults
if no params given, defaults to:
```js
await mochadocs({path: 'test'});
```
if you don't need any other options, you can pass it just the path string:
```js
await mochadocs('test');
```
the full config format is:
```js
await mochadocs({
	path: 'test',
	to: 'README.md',
	libname: '@ashnazg/mochadocs',
	glossary: { // for auto-linking frequently used terms
		acronym1: 'path1',
	},
	indent: '\t\t'
});
```

### Support for space-indented files
Visible code blocks are defined as non-`/// ` lines that start with `conf.indent` and are between the opening line of the current `it(...)`
and the it-closer, which is the first line of code with less indentation thatn conf.indent.

so for a 2-space file like:
```
describe('group', function() {
  it('thing', function() {
    visible_code();
  });
  function invisibleHelper() {
    invisible_code();
  };
});
```
You'd use:
```
await mochadocs({
  indent: '    ' // four spaces
});
```

When the indent drops below the conf.indent, code blocks are not emitted til the next `it(` -- this is so the invisibleHelper's contents don't pollute the unit test's
code printout.

### Explicit output
you can write the output to a specific place:
```js
await mochadocs({to: 'different.md'});
{
	const lines = (await fs.promises.readFile('different.md', 'utf8')).split('\n');
	assert(lines[length_of_preamble] === '## Reads Mocha test files and emits a README.md');
}
```
or pass null as the destination and it'll return the markdown file as a list of lines:
```js
{
	const lines = await mochadocs({to: null});
	assert(lines[length_of_preamble] === '## Reads Mocha test files and emits a README.md');
}
```

### Explicit input, file
path can be a filename:
```js
const lines = await mochadocs({path: 'test/basics.js', to: null});
assert(lines[length_of_preamble] === '## Reads Mocha test files and emits a README.md');
```

### Explicit input, dir
... or a directory, in which it'll read all `*.js`, including subfolders, and process them after sorting them by 'path/filename'.
```js
const lines = await mochadocs({path: 'test', to: null});
assert(lines[length_of_preamble] === '## Reads Mocha test files and emits a README.md');
```

### Replaces require('..')
since in a library's unit tests, `require('..')` is useful, but not helpful documentation,
This is converted to `require('LIBNAME')`.
```js
const lines = await mochadocs({path: 'test', to: null}); // reading the output of section "default"
const hits = lines.filter(line => line === "const mochadocs = require('@ashnazg/mochadocs');");
assert(hits.length === 1);
```

### Configuring require('..') replacement
By default, mochadocs assumes that `./package.json` is available and will use that to know your lib's name.
if that's not a useful guess (wrong path or wrong name) you can pass in a library name of your choosing as a third param:
```js
const lines = await mochadocs({path: 'test', to: null, libname: 'custom_lib_name'});
const hits = lines.filter(line => line === "const mochadocs = require('custom_lib_name');");
assert(hits.length === 1);
```

### Automatic Glossary
To allow good linkage to other relevant topics without repetitive writing, you can pass in a glossary map and if that key is found in the non-code blocks, it'll be
emitted as a link:
```js
lines = await mochadocs({
	to: null,
	glossary: {
		GLOSSARY: 'https://en.wikipedia.org/wiki/Glossary'
	}
});
```

## Glossary Rules

### Only links exact words
Given the above config, the word "[GLOSSARY](https://en.wikipedia.org/wiki/Glossary)" is now a link.
```js
// search term without creating a false positive:
{
	const key = `[GLOS` + `SARY](https://en.wikipedia.org/wiki/Glossary)`;
	const hits = lines.filter(line => line.includes(key));
	assert(hits.length === 1, `${hits.length} hits`);
}
```
... but GLOSSARYFOO is not, because the replacer respects word boundaries.
```js
{
	const key = `GLOS` + `SARYFOO`;
	const hits = lines.filter(line => line.includes(key));
	assert(hits.length === 1, `${hits.length} hits`);
}
```

### Longer glossary terms take precedence
```js
await mochadocs({
	glossary: {
		GLOSSARY: 'https://en.wikipedia.org/wiki/Glossary',
		SHORT_NAME: '#glossary-rules',
		SHORT_NAME_IN_LONGER_NAME: '#longer-glossary-terms-take-precedence'
	}
});
```
[SHORT_NAME_IN_LONGER_NAME](#longer-glossary-terms-take-precedence) should be a clean link, and its internals should not be affected by the [SHORT_NAME](#glossary-rules) term, as replacement is not allowed to go into recursive
expansion.
```js
const lines = (await fs.promises.readFile('README.md', 'utf8')).split('\n');
const key = `[SHORT_NAM` + `E_IN_LONGER_NAME](#longer-glossary-terms-take-precedence) should be a clean link, and its internals should not be affected by the [SHORT_NAME](#glossary-rules) term`;
const hits = lines.filter(line => line.includes(key));
assert(hits.length === 1, `${hits.length} hits`);
```

### Existing links are unaffected
this predefined link [SHORT_NAME](#existing-links-are-unaffected) is not further processed.
```js
const lines = (await fs.promises.readFile('README.md', 'utf8')).split('\n');
// here's the unwanted form:
const key = `[[SHORT` + `_NAME](test1)](#existing-links-are-unaffected)`;
const hits = lines.filter(line => line.includes(key));
assert(hits.length === 0, `${hits.length} hits`);
```

## Release 1.0.2

### fixed a bug where a really short input file leaves the code pre unclosed
```js
const lines = await mochadocs({path: 'samples/trailing-pre-missing.js', to: null});
assert(lines[lines.length-1] === '```', 'simple did not close pre');
```

## Release 1.0.1
1. Suppressed codeblocks that aren't inside an `it(...)`

## Release 1.0
1. Wrote the thing

---
_Source: https://npm.io/package/@ashnazg/mochadocs · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
