| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- /**
- * @import {
- * Code,
- * Construct,
- * State,
- * TokenizeContext,
- * Tokenizer
- * } from 'micromark-util-types'
- */
- import { factorySpace } from 'micromark-factory-space';
- import { markdownLineEnding, markdownSpace } from 'micromark-util-character';
- /** @type {Construct} */
- export const thematicBreak = {
- name: 'thematicBreak',
- tokenize: tokenizeThematicBreak
- };
- /**
- * @this {TokenizeContext}
- * Context.
- * @type {Tokenizer}
- */
- function tokenizeThematicBreak(effects, ok, nok) {
- let size = 0;
- /** @type {NonNullable<Code>} */
- let marker;
- return start;
- /**
- * Start of thematic break.
- *
- * ```markdown
- * > | ***
- * ^
- * ```
- *
- * @type {State}
- */
- function start(code) {
- effects.enter("thematicBreak");
- // To do: parse indent like `markdown-rs`.
- return before(code);
- }
- /**
- * After optional whitespace, at marker.
- *
- * ```markdown
- * > | ***
- * ^
- * ```
- *
- * @type {State}
- */
- function before(code) {
- marker = code;
- return atBreak(code);
- }
- /**
- * After something, before something else.
- *
- * ```markdown
- * > | ***
- * ^
- * ```
- *
- * @type {State}
- */
- function atBreak(code) {
- if (code === marker) {
- effects.enter("thematicBreakSequence");
- return sequence(code);
- }
- if (size >= 3 && (code === null || markdownLineEnding(code))) {
- effects.exit("thematicBreak");
- return ok(code);
- }
- return nok(code);
- }
- /**
- * In sequence.
- *
- * ```markdown
- * > | ***
- * ^
- * ```
- *
- * @type {State}
- */
- function sequence(code) {
- if (code === marker) {
- effects.consume(code);
- size++;
- return sequence;
- }
- effects.exit("thematicBreakSequence");
- return markdownSpace(code) ? factorySpace(effects, atBreak, "whitespace")(code) : atBreak(code);
- }
- }
|