knowledgebase_law/node_modules/micromark-extension-gfm-task-list-item/lib/syntax.js

158 lines
3.5 KiB
JavaScript
Raw Normal View History

2025-04-11 23:47:09 +08:00
/**
* @import {Extension, State, TokenizeContext, Tokenizer} from 'micromark-util-types'
*/
import { factorySpace } from 'micromark-factory-space';
import { markdownLineEnding, markdownLineEndingOrSpace, markdownSpace } from 'micromark-util-character';
const tasklistCheck = {
name: 'tasklistCheck',
tokenize: tokenizeTasklistCheck
};
/**
* Create an HTML extension for `micromark` to support GFM task list items
* syntax.
*
* @returns {Extension}
* Extension for `micromark` that can be passed in `htmlExtensions` to
* support GFM task list items when serializing to HTML.
*/
export function gfmTaskListItem() {
return {
text: {
[91]: tasklistCheck
}
};
}
/**
* @this {TokenizeContext}
* @type {Tokenizer}
*/
function tokenizeTasklistCheck(effects, ok, nok) {
const self = this;
return open;
/**
* At start of task list item check.
*
* ```markdown
* > | * [x] y.
* ^
* ```
*
* @type {State}
*/
function open(code) {
if (
// Exit if theres stuff before.
self.previous !== null ||
// Exit if not in the first content that is the first child of a list
// item.
!self._gfmTasklistFirstContentOfListItem) {
return nok(code);
}
effects.enter('taskListCheck');
effects.enter('taskListCheckMarker');
effects.consume(code);
effects.exit('taskListCheckMarker');
return inside;
}
/**
* In task list item check.
*
* ```markdown
* > | * [x] y.
* ^
* ```
*
* @type {State}
*/
function inside(code) {
// Currently we match how GH works in files.
// To match how GH works in comments, use `markdownSpace` (`[\t ]`) instead
// of `markdownLineEndingOrSpace` (`[\t\n\r ]`).
if (markdownLineEndingOrSpace(code)) {
effects.enter('taskListCheckValueUnchecked');
effects.consume(code);
effects.exit('taskListCheckValueUnchecked');
return close;
}
if (code === 88 || code === 120) {
effects.enter('taskListCheckValueChecked');
effects.consume(code);
effects.exit('taskListCheckValueChecked');
return close;
}
return nok(code);
}
/**
* At close of task list item check.
*
* ```markdown
* > | * [x] y.
* ^
* ```
*
* @type {State}
*/
function close(code) {
if (code === 93) {
effects.enter('taskListCheckMarker');
effects.consume(code);
effects.exit('taskListCheckMarker');
effects.exit('taskListCheck');
return after;
}
return nok(code);
}
/**
* @type {State}
*/
function after(code) {
// EOL in paragraph means there must be something else after it.
if (markdownLineEnding(code)) {
return ok(code);
}
// Space or tab?
// Check what comes after.
if (markdownSpace(code)) {
return effects.check({
tokenize: spaceThenNonSpace
}, ok, nok)(code);
}
// EOF, or non-whitespace, both wrong.
return nok(code);
}
}
/**
* @this {TokenizeContext}
* @type {Tokenizer}
*/
function spaceThenNonSpace(effects, ok, nok) {
return factorySpace(effects, after, "whitespace");
/**
* After whitespace, after task list item check.
*
* ```markdown
* > | * [x] y.
* ^
* ```
*
* @type {State}
*/
function after(code) {
// EOF means there was nothing, so bad.
// EOL means theres content after it, so good.
// Impossible to have more spaces.
// Anything else is good.
return code === null ? nok(code) : ok(code);
}
}