File size: 1,610 Bytes
bc20498 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
/**
* @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)
}
}
|