Skip to content

Commit

Permalink
Add improved docs
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Mar 30, 2023
1 parent 70da951 commit eef0600
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 61 deletions.
6 changes: 4 additions & 2 deletions dev/lib/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

/**
* @typedef {Omit<KatexOptions, 'displayMode'>} Options
* Configuration.
* Configuration for HTML output.
*
* This is the same as `KatexOptions` but w/o `displayMode`.
* > 👉 **Note**: passed to `katex.renderToString`.
* > `displayMode` is overwritten by this plugin, to `false` for math in
* > text, and `true` for math in flow.
*/

import katex from 'katex'
Expand Down
6 changes: 3 additions & 3 deletions dev/lib/math-text.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
* @typedef Options
* Configuration.
* @property {boolean | null | undefined} [singleDollarTextMath=true]
* Whether to support math (text) with a single dollar (`boolean`, default:
* `true`).
*
* Whether to support math (text) with a single dollar.
* Single dollars work in Pandoc and many other places, but often interfere
* with “normal” dollars in text.
* If you turn this off, you can use two or more dollars for text math.
*/

// To do: next major: clean spaces in HTML compiler.
Expand Down
242 changes: 186 additions & 56 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
[![Backers][backers-badge]][collective]
[![Chat][chat-badge]][chat]

[micromark][] extension to support math (`$C_L$`).
[micromark][] extensions to support math (`$C_L$`).

## Contents

Expand All @@ -18,7 +18,9 @@
* [Use](#use)
* [API](#api)
* [`math(options?)`](#mathoptions)
* [`mathHtml(htmlOptions?)`](#mathhtmlhtmloptions)
* [`mathHtml(options?)`](#mathhtmloptions)
* [`Options`](#options)
* [`HtmlOptions`](#htmloptions)
* [Authoring](#authoring)
* [HTML](#html)
* [CSS](#css)
Expand All @@ -32,24 +34,33 @@

## What is this?

This package contains extensions that add support for math.
This package contains two extensions that add support for math syntax
in markdown to [`micromark`][micromark].

As there is no spec for math in markdown, this extension follows how code
(fenced and text) works in Commonmark, but uses dollars.

## When to use this

These tools are all low-level.
In many cases, you want to use [`remark-math`][plugin] with remark instead.
This project is useful when you want to support math in markdown.
Extending markdown with a syntax extension makes the markdown less portable.
LaTeX equations are also quite hard.
But this mechanism works well when you want authors, that have some LaTeX
experience, to be able to embed rich diagrams of math in scientific text.

When you do want to use `micromark`, you can use this.
When working with `mdast-util-from-markdown`, you must combine this package
with [`mdast-util-math`][util].
You can use these extensions when you are working with [`micromark`][micromark]
already.

When you need a syntax tree, you can combine this package with
[`mdast-util-math`][mdast-util-math].

All these packages are used [`remark-math`][remark-math], which focusses on
making it easier to transform content by abstracting these internals away.

## Install

This package is [ESM only][esm].
In Node.js (version 12.20+, 14.14+, 16.0+, or 18.0+), install with [npm][]:
In Node.js (version 14.14+), install with [npm][]:

[npm][]:

Expand Down Expand Up @@ -107,61 +118,92 @@ console.log(output)

## API

This package exports the identifiers `math` and `mathHtml`.
This package exports the identifiers [`math`][api-math] and
[`mathHtml`][api-math-html].
There is no default export.

The export map supports the endorsed [`development` condition][condition].
The export map supports the [`development` condition][development].
Run `node --conditions development module.js` to get instrumented dev code.
Without this condition, production code is loaded.

### `math(options?)`

Add support for parsing math in markdown.
Create an extension for `micromark` to enable math syntax.

###### Parameters

* `options` ([`Options`][api-options], optional)
— configuration

###### Returns

Extension for `micromark` that can be passed in `extensions`, to enable math
syntax ([`Extension`][micromark-extension]).

Function that can be called to get a syntax extension for micromark (passed
in `extensions`).
### `mathHtml(options?)`

##### `options`
Create an extension for `micromark` to support math when serializing to HTML.

Configuration (optional).
> 👉 **Note**: this uses KaTeX to render math.
###### `options.singleDollarTextMath`
###### Parameters

Whether to support math (text) with a single dollar (`boolean`, default:
`true`).
Single dollars work in Pandoc and many other places, but often interfere with
“normal” dollars in text.
* `options` ([`HtmlOptions`][api-html-options], optional)
— configuration

### `mathHtml(htmlOptions?)`
###### Returns

Add support for turning math in markdown to HTML with [KaTeX][].
Extension for `micromark` that can be passed in `htmlExtensions`, to support
math when serializing to HTML ([`HtmlExtension`][micromark-html-extension]).

Function that can be called to get an HTML extension for micromark (passed in
`htmlExtensions`).
### `Options`

##### `htmlOptions`
Configuration (TypeScript type).

Configuration (optional).
###### Fields

Passed to [`katex.renderToString`][katex-options].
`displayMode` is overwritten by this plugin, to `false` for math in text, and
`true` for math in flow.
Everything else can be passed.
* `singleDollarTextMath` (`boolean`, default: `true`)
— whether to support math (text) with a single dollar.
Single dollars work in Pandoc and many other places, but often interfere
with “normal” dollars in text.
If you turn this off, you can use two or more dollars for text math.

### `HtmlOptions`

Configuration for HTML output (optional).

> 👉 **Note**: passed to [`katex.renderToString`][katex-options].
> `displayMode` is overwritten by this plugin, to `false` for math in text, and
> `true` for math in flow.
###### Type

```ts
type Options = Omit<import('katex').KatexOptions, 'displayMode'>
```
## Authoring
When authoring markdown with math, keep in mind that math doesn’t work in most
places.
Notably, GitHub currently has a really weird crappy regex-based thing.
Notably, GitHub currently has a really weird crappy client-side regex-based
thing.
But on your own (math-heavy?) site it can be great!
You can use code (fenced) with an info string of `math` to improve this, as
that works in many places.
## HTML
Math does not relate to HTML elements.
MathML, which is sort of like SVG but for math, exists but it doesn’t work well
and isn’t widely supported.
Math (flow) does not relate to HTML elements.
`MathML`, which is sort of like SVG but for math, exists but it doesn’t work
well and isn’t widely supported.
Instead, this uses [KaTeX][], which generates MathML as a fallback but also
generates a bunch of divs and spans so math look pretty.
The KaTeX result is wrapped in `<div>` and `<span>` elements, with two classes:
`math` and either `math-display` or `math-inline`.
When turning markdown into HTML, each line ending in math (text) are turned
into a space.
## CSS
Expand All @@ -171,41 +213,115 @@ style it properly.
At the time of writing, the last version is:
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css">
```
## Syntax
Math forms with, roughly, the following BNF:
Math forms with the following BNF:
```bnf
; Restriction: the number of markers in the closing sequence must be equal
; to the number of markers in the opening sequence.
math_text ::= sequence_text 1*byte sequence_text
math_flow ::= fence_open *( eol *line ) [ eol fence_close ]

; Restriction: not preceded or followed by the marker.
sequence_text ::= 1*'$'

fence_open ::= sequence_flow meta
; Restriction: the number of markers in the closing fence sequence must be
; equal to or greater than the number of markers in the opening fence
; sequence.
math_flow ::= fence_open *( eol *line ) [ eol fence_close ]
; Restriction: the number of markers in the closing sequence must equal the
; number of markers in the opening sequence.
math_text ::= 1*'$' 1*code 1*'$'
fence_close ::= sequence_flow *space_or_tab
sequence_flow ::= 2*'$'
; Restriction: the marker cannot occur in `meta`
meta ::= 1*line

; Character groups for informational purposes.
byte ::= 0x00..=0xFFFF
eol ::= '\n' | '\r' | '\r\n'
line ::= byte - eol
```

The above grammar shows that it is not possible to create empty math (text).
It is possible to include the sequence marker (dollar) in math (text), by
wrapping it in bigger or smaller sequences:

```markdown
Include more: $a$$b$ or include less: $$a$b$$.
```

It is also possible to include just one marker:

```markdown
Include just one: $$ $ $$.
```

Sequences are “gready”, in that they cannot be preceded or followed by more
markers.
To illustrate:

```markdown
Not math: $$x$.

Not math: $x$$.

fence_open ::= 2*'$' [ 1*space_or_tab meta ] *space_or_tab
fence_close ::= 2*'$' *space_or_tab
meta ::= 1*(code - eol - space_or_tab - '$') *( *space_or_tab 1*text )
Escapes work, this is math: \$$x$.

eol ::= '\r' | '\r\n' | '\n'
space_or_tab ::= ' ' | '\t'
line ::= . - eol ; any unicode code point
Escapes work, this is math: $x$\$.
```

Yields:

```html
<p>Not math: $$x$.</p>
<p>Not math: $x$$.</p>
<p>Escapes work, this is math: $<span>…</span>.</p>
<p>Escapes work, this is math: <span>…</span>$.</p>
```

That is because, when turning markdown into HTML, the first and last space,
if both exist and there is also a non-space in the math, are removed.
Line endings, at that stage, are considered as spaces.

As the math (flow) construct occurs in flow, like all flow constructs, it must
be followed by an eol (line ending) or eof (end of file).

The above grammar does not show how indentation of each line is handled.
To parse math (flow), let `x` be the number of `space_or_tab` characters
before the opening fence sequence, after interpreting tabs based on how many
virtual spaces they represent.
Each line of text is then allowed (not required) to be indented with up
to `x` spaces or tabs, which are then ignored as an indent instead of being
considered as part of the content.
This indent does not affect the closing fence.
It can be indented up to a separate 3 real or virtual spaces.
A bigger indent makes it part of the content instead of a fence.

<!-- To do: update link to string-specific link when docs are updated. -->

The `meta` part is interpreted as the [string][micromark-content-types] content
type.
That means that character escapes and character references are allowed.

The optional `meta` part is ignored: it is not used when parsing or
rendering.

## Types

This package is fully typed with [TypeScript][].
It exports the additional types `Options` and `HtmlOptions`.
It exports the additional types [`HtmlOptions`][api-html-options]
and [`Options`][api-options].

## Compatibility

This package is at least compatible with all maintained versions of Node.js.
As of now, that is Node.js 12.20+, 14.14+, 16.0+, and 18.0+.
It also works in Deno and modern browsers.
Projects maintained by the unified collective are compatible with all maintained
versions of Node.js.
As of now, that is Node.js 14.14+.
Our projects sometimes work with older versions, but this is not guaranteed.

These extensions work with `micromark` version 3+.

## Security

Expand All @@ -215,9 +331,9 @@ attack.

## Related

* [`remarkjs/remark-math`][plugin]
* [`remark-math`][remark-math]
— remark (and rehype) plugins to support math
* [`syntax-tree/mdast-util-math`][util]
* [`mdast-util-math`][mdast-util-math]
— mdast utility to support math

## Contribute
Expand Down Expand Up @@ -280,16 +396,30 @@ abide by its terms.

[typescript]: https://www.typescriptlang.org

[condition]: https://nodejs.org/api/packages.html#packages_resolving_user_conditions
[development]: https://nodejs.org/api/packages.html#packages_resolving_user_conditions

[micromark]: https://github.com/micromark/micromark

[plugin]: https://github.com/remarkjs/remark-math
[micromark-content-types]: https://github.com/micromark/micromark#content-types

[micromark-html-extension]: https://github.com/micromark/micromark#htmlextension

[util]: https://github.com/syntax-tree/mdast-util-math
[micromark-extension]: https://github.com/micromark/micromark#syntaxextension

[mdast-util-math]: https://github.com/syntax-tree/mdast-util-math

[remark-math]: https://github.com/remarkjs/remark-math

[katex]: https://katex.org

[katex-options]: https://katex.org/docs/options.html

[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting

[api-math]: #mathoptions

[api-math-html]: #mathhtmloptions

[api-options]: #options

[api-html-options]: #htmloptions

0 comments on commit eef0600

Please sign in to comment.