/** * @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 {State} * 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) } }