# md-mini.js

A tiny, dependency-free Markdown to HTML renderer in a single ES module. It is
pure string to string (no DOM), so the same file runs unchanged in the browser
and in Node. This very README is rendered by it as the project's test fixture.

## Why

Pulling a full CommonMark library (and a build step) into a project just to
render its own docs is overkill. md-mini.js covers a small, well-defined slice
of GitHub-flavored Markdown in one file you copy in, with three properties that
matter:

- **Zero dependencies, no build step.** One self-contained ES module.
- **Escape-safe by construction.** All text is HTML-escaped before any markup is
  emitted, so rendering untrusted-ish Markdown cannot inject script.
- **Small and legible.** Around 230 lines you can read in a sitting.

It is *not* a general Markdown engine. It renders the constructs typical project
documentation uses and nothing more.

## Usage

It exports a named `renderMarkdown` and a default object:

```js
import { renderMarkdown } from './md-mini.js';

const html = renderMarkdown('# Hello\n\nA *small* renderer.');
// -> "<h1>Hello</h1>\n<p>A <em>small</em> renderer.</p>"
```

In the browser, drop the string into an element:

```html
<div id="out"></div>
<script type="module">
  import { renderMarkdown } from './md-mini.js';
  document.getElementById('out').innerHTML = renderMarkdown(source);
</script>
```

`renderMarkdown(md)` is a pure function: same input, same output, no options and
no global state.

## What it renders

| Construct      | Notes                                                    |
|----------------|:--------------------------------------------------------:|
| Headings       | ATX `#` through `######`                                 |
| Tables         | pipe tables, with per-column alignment                   |
| Code blocks    | fenced, optional language becomes a `lang-` class        |
| Lists          | ordered, unordered, nested, task lists, multi-line items |
| Blockquotes    | rendered recursively                                     |
| Horizontal rule| `---`, `***`, or `___`                                   |
| Inline         | code, bold, italic, strikethrough, links                 |

The Markdown for those looks like this:

```md
# Heading 1
## Heading 2

| name  | qty |
|-------|----:|
| apple |   3 |

- bullet one
- bullet two

1. step one
2. step two

> a quotation

Inline **bold**, *italic*, `code`, and a [link](https://example.com).
```

### Headings

Use one to six `#` characters. This section title is a level-three heading.

### Lists

Unordered lists accept `-`, `*`, or `+`:

- first item
- second item, whose text wraps onto a second line and is folded back together
- third item

Ordered lists use `1.`-style markers:

1. preheat
2. mix
3. bake

Lists nest by indentation, and each level keeps its own ordered-ness:

- top level
  - nested under it
  - still nested
- back to the top

Task lists render a disabled checkbox per item:

- [x] done item
- [ ] pending item

### Blockquotes

Blockquote contents are themselves rendered as Markdown:

> Quoted text can contain *emphasis* and `code`.
> A second line stays in the same quote.

### Code

Inline code uses backticks, like `renderMarkdown(md)`. Fenced blocks preserve
their contents verbatim and escape them, so a block can safely show characters
such as `<`, `&`, and `*` without them being interpreted:

```text
<not-a-tag> & literal *asterisks*
```

### Inline formatting

Text can be **bold** (or __bold__), *italic* (or _italic_), contain `inline
code`, and link to an [external site](https://example.com) (external links open
in a new tab) or to a [relative path](./md-mini.js) (which does not). Emphasis
markers must hug their text, so a spaced `*` (as in `2 * 3`) stays literal, and
underscores emphasize only at word boundaries so `snake_case` is left alone.
Text can also be ~~struck through~~ with tildes. A link target may contain
balanced parentheses, e.g.
[Wikipedia](https://en.wikipedia.org/wiki/Markup_(disambiguation)).

## What it does not render

Deliberately out of scope; reach for a full Markdown engine if you need these:

- Setext headings (underlined with `===` or `---`)
- Images, reference-style links, autolinks, footnotes
- Raw HTML passthrough (HTML in the source is escaped, not interpreted)

---

## Security

Every run escapes `&`, `<`, and `>` in text *before* emitting any HTML;
attribute values (link URLs) additionally have `"` neutralized — their `&`, `<`,
and `>` are already escaped by that text pass. A `<script>` tag in the input is
rendered inert.

> Keep it that way. Any new feature must preserve the escape-before-markup
> order, or it becomes an injection vector.

## Versioning

The file carries an inline version stamp near the top:

```text
// Version (ts6): <token>  (<date> America/New_York). Bump on every change.
```

The token is a compact reversible encoding of the release timestamp. It tells
you which revision you copied; bump it whenever the file changes.

## Distribution (copy-in)

md-mini.js is distributed by copying the one file into the project that needs
it. There is no package to install and nothing to deploy:

```bash
cp md-mini.js  path/in/your/project/
```

There is no automatic propagation. When the renderer is updated, re-copy the
file to pick up the new revision; the version stamp tells you what you have.
