CoolFace
Apppublic

AK-21/Graphite-Industrial-Intelligence

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
list.js213 linesDownload Raw Back to lib
1/**2 * @import {3 *   Code,4 *   Construct,5 *   Exiter,6 *   State,7 *   TokenizeContext,8 *   Tokenizer9 * } from 'micromark-util-types'10 */11 12import { factorySpace } from 'micromark-factory-space';13import { asciiDigit, markdownSpace } from 'micromark-util-character';14import { blankLine } from './blank-line.js';15import { thematicBreak } from './thematic-break.js';16 17/** @type {Construct} */18export const list = {19  continuation: {20    tokenize: tokenizeListContinuation21  },22  exit: tokenizeListEnd,23  name: 'list',24  tokenize: tokenizeListStart25};26 27/** @type {Construct} */28const listItemPrefixWhitespaceConstruct = {29  partial: true,30  tokenize: tokenizeListItemPrefixWhitespace31};32 33/** @type {Construct} */34const indentConstruct = {35  partial: true,36  tokenize: tokenizeIndent37};38 39// To do: `markdown-rs` parses list items on their own and later stitches them40// together.41 42/**43 * @this {TokenizeContext}44 *   Context.45 * @type {Tokenizer}46 */47function tokenizeListStart(effects, ok, nok) {48  const self = this;49  const tail = self.events[self.events.length - 1];50  let initialSize = tail && tail[1].type === "linePrefix" ? tail[2].sliceSerialize(tail[1], true).length : 0;51  let size = 0;52  return start;53 54  /** @type {State} */55  function start(code) {56    const kind = self.containerState.type || (code === 42 || code === 43 || code === 45 ? "listUnordered" : "listOrdered");57    if (kind === "listUnordered" ? !self.containerState.marker || code === self.containerState.marker : asciiDigit(code)) {58      if (!self.containerState.type) {59        self.containerState.type = kind;60        effects.enter(kind, {61          _container: true62        });63      }64      if (kind === "listUnordered") {65        effects.enter("listItemPrefix");66        return code === 42 || code === 45 ? effects.check(thematicBreak, nok, atMarker)(code) : atMarker(code);67      }68      if (!self.interrupt || code === 49) {69        effects.enter("listItemPrefix");70        effects.enter("listItemValue");71        return inside(code);72      }73    }74    return nok(code);75  }76 77  /** @type {State} */78  function inside(code) {79    if (asciiDigit(code) && ++size < 10) {80      effects.consume(code);81      return inside;82    }83    if ((!self.interrupt || size < 2) && (self.containerState.marker ? code === self.containerState.marker : code === 41 || code === 46)) {84      effects.exit("listItemValue");85      return atMarker(code);86    }87    return nok(code);88  }89 90  /**91   * @type {State}92   **/93  function atMarker(code) {94    effects.enter("listItemMarker");95    effects.consume(code);96    effects.exit("listItemMarker");97    self.containerState.marker = self.containerState.marker || code;98    return effects.check(blankLine,99    // Can’t be empty when interrupting.100    self.interrupt ? nok : onBlank, effects.attempt(listItemPrefixWhitespaceConstruct, endOfPrefix, otherPrefix));101  }102 103  /** @type {State} */104  function onBlank(code) {105    self.containerState.initialBlankLine = true;106    initialSize++;107    return endOfPrefix(code);108  }109 110  /** @type {State} */111  function otherPrefix(code) {112    if (markdownSpace(code)) {113      effects.enter("listItemPrefixWhitespace");114      effects.consume(code);115      effects.exit("listItemPrefixWhitespace");116      return endOfPrefix;117    }118    return nok(code);119  }120 121  /** @type {State} */122  function endOfPrefix(code) {123    self.containerState.size = initialSize + self.sliceSerialize(effects.exit("listItemPrefix"), true).length;124    return ok(code);125  }126}127 128/**129 * @this {TokenizeContext}130 *   Context.131 * @type {Tokenizer}132 */133function tokenizeListContinuation(effects, ok, nok) {134  const self = this;135  self.containerState._closeFlow = undefined;136  return effects.check(blankLine, onBlank, notBlank);137 138  /** @type {State} */139  function onBlank(code) {140    self.containerState.furtherBlankLines = self.containerState.furtherBlankLines || self.containerState.initialBlankLine;141 142    // We have a blank line.143    // Still, try to consume at most the items size.144    return factorySpace(effects, ok, "listItemIndent", self.containerState.size + 1)(code);145  }146 147  /** @type {State} */148  function notBlank(code) {149    if (self.containerState.furtherBlankLines || !markdownSpace(code)) {150      self.containerState.furtherBlankLines = undefined;151      self.containerState.initialBlankLine = undefined;152      return notInCurrentItem(code);153    }154    self.containerState.furtherBlankLines = undefined;155    self.containerState.initialBlankLine = undefined;156    return effects.attempt(indentConstruct, ok, notInCurrentItem)(code);157  }158 159  /** @type {State} */160  function notInCurrentItem(code) {161    // While we do continue, we signal that the flow should be closed.162    self.containerState._closeFlow = true;163    // As we’re closing flow, we’re no longer interrupting.164    self.interrupt = undefined;165    // Always populated by defaults.166 167    return factorySpace(effects, effects.attempt(list, ok, nok), "linePrefix", self.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4)(code);168  }169}170 171/**172 * @this {TokenizeContext}173 *   Context.174 * @type {Tokenizer}175 */176function tokenizeIndent(effects, ok, nok) {177  const self = this;178  return factorySpace(effects, afterPrefix, "listItemIndent", self.containerState.size + 1);179 180  /** @type {State} */181  function afterPrefix(code) {182    const tail = self.events[self.events.length - 1];183    return tail && tail[1].type === "listItemIndent" && tail[2].sliceSerialize(tail[1], true).length === self.containerState.size ? ok(code) : nok(code);184  }185}186 187/**188 * @this {TokenizeContext}189 *   Context.190 * @type {Exiter}191 */192function tokenizeListEnd(effects) {193  effects.exit(this.containerState.type);194}195 196/**197 * @this {TokenizeContext}198 *   Context.199 * @type {Tokenizer}200 */201function tokenizeListItemPrefixWhitespace(effects, ok, nok) {202  const self = this;203 204  // Always populated by defaults.205 206  return factorySpace(effects, afterPrefix, "listItemPrefixWhitespace", self.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4 + 1);207 208  /** @type {State} */209  function afterPrefix(code) {210    const tail = self.events[self.events.length - 1];211    return !markdownSpace(code) && tail && tail[1].type === "listItemPrefixWhitespace" ? ok(code) : nok(code);212  }213}