knowledgebase_law/node_modules/micromark-factory-title/index.js

158 lines
3.0 KiB
JavaScript
Raw Normal View History

2025-04-11 23:47:09 +08:00
/**
* @import {
* Code,
* Effects,
* State,
* TokenType
* } from 'micromark-util-types'
*/
import { factorySpace } from 'micromark-factory-space';
import { markdownLineEnding } from 'micromark-util-character';
/**
* Parse titles.
*
* ###### Examples
*
* ```markdown
* "a"
* 'b'
* (c)
* "a
* b"
* 'a
* b'
* (a\)b)
* ```
*
* @param {Effects} effects
* Context.
* @param {State} ok
* State switched to when successful.
* @param {State} nok
* State switched to when unsuccessful.
* @param {TokenType} type
* Type of the whole title (`"a"`, `'b'`, `(c)`).
* @param {TokenType} markerType
* Type for the markers (`"`, `'`, `(`, and `)`).
* @param {TokenType} stringType
* Type for the value (`a`).
* @returns {State}
* Start state.
*/
export function factoryTitle(effects, ok, nok, type, markerType, stringType) {
/** @type {NonNullable<Code>} */
let marker;
return start;
/**
* Start of title.
*
* ```markdown
* > | "a"
* ^
* ```
*
* @type {State}
*/
function start(code) {
if (code === 34 || code === 39 || code === 40) {
effects.enter(type);
effects.enter(markerType);
effects.consume(code);
effects.exit(markerType);
marker = code === 40 ? 41 : code;
return begin;
}
return nok(code);
}
/**
* After opening marker.
*
* This is also used at the closing marker.
*
* ```markdown
* > | "a"
* ^
* ```
*
* @type {State}
*/
function begin(code) {
if (code === marker) {
effects.enter(markerType);
effects.consume(code);
effects.exit(markerType);
effects.exit(type);
return ok;
}
effects.enter(stringType);
return atBreak(code);
}
/**
* At something, before something else.
*
* ```markdown
* > | "a"
* ^
* ```
*
* @type {State}
*/
function atBreak(code) {
if (code === marker) {
effects.exit(stringType);
return begin(marker);
}
if (code === null) {
return nok(code);
}
// Note: blank lines cant exist in content.
if (markdownLineEnding(code)) {
// To do: use `space_or_tab_eol_with_options`, connect.
effects.enter("lineEnding");
effects.consume(code);
effects.exit("lineEnding");
return factorySpace(effects, atBreak, "linePrefix");
}
effects.enter("chunkString", {
contentType: "string"
});
return inside(code);
}
/**
*
*
* @type {State}
*/
function inside(code) {
if (code === marker || code === null || markdownLineEnding(code)) {
effects.exit("chunkString");
return atBreak(code);
}
effects.consume(code);
return code === 92 ? escape : inside;
}
/**
* After `\`, at a special character.
*
* ```markdown
* > | "a\*b"
* ^
* ```
*
* @type {State}
*/
function escape(code) {
if (code === marker || code === 92) {
effects.consume(code);
return inside;
}
return inside(code);
}
}