/** | |
* @typedef {import('micromark-util-types').Effects} Effects | |
* @typedef {import('micromark-util-types').State} State | |
* @typedef {import('micromark-util-types').TokenType} TokenType | |
*/ | |
import {markdownSpace} from 'micromark-util-character' | |
// To do: implement `spaceOrTab`, `spaceOrTabMinMax`, `spaceOrTabWithOptions`. | |
/** | |
* Parse spaces and tabs. | |
* | |
* There is no `nok` parameter: | |
* | |
* * spaces in markdown are often optional, in which case this factory can be | |
* used and `ok` will be switched to whether spaces were found or not | |
* * one line ending or space can be detected with `markdownSpace(code)` right | |
* before using `factorySpace` | |
* | |
* ###### Examples | |
* | |
* Where `β` represents a tab (plus how much it expands) and `β ` represents a | |
* single space. | |
* | |
* ```markdown | |
* β | |
* β β β β | |
* ββ | |
* ``` | |
* | |
* @param {Effects} effects | |
* Context. | |
* @param {State} ok | |
* State switched to when successful. | |
* @param {TokenType} type | |
* Type (`' \t'`). | |
* @param {number | undefined} [max=Infinity] | |
* Max (exclusive). | |
* @returns | |
* Start state. | |
*/ | |
export function factorySpace(effects, ok, type, max) { | |
const limit = max ? max - 1 : Number.POSITIVE_INFINITY | |
let size = 0 | |
return start | |
/** @type {State} */ | |
function start(code) { | |
if (markdownSpace(code)) { | |
effects.enter(type) | |
return prefix(code) | |
} | |
return ok(code) | |
} | |
/** @type {State} */ | |
function prefix(code) { | |
if (markdownSpace(code) && size++ < limit) { | |
effects.consume(code) | |
return prefix | |
} | |
effects.exit(type) | |
return ok(code) | |
} | |
} | |