CoolFace
Apppublic

AK-21/Graphite-Industrial-Intelligence

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
setext-underline.js185 linesDownload Raw Back to lib
1/**2 * @import {3 *   Code,4 *   Construct,5 *   Resolver,6 *   State,7 *   TokenizeContext,8 *   Tokenizer9 * } from 'micromark-util-types'10 */11 12import { factorySpace } from 'micromark-factory-space';13import { markdownLineEnding, markdownSpace } from 'micromark-util-character';14/** @type {Construct} */15export const setextUnderline = {16  name: 'setextUnderline',17  resolveTo: resolveToSetextUnderline,18  tokenize: tokenizeSetextUnderline19};20 21/** @type {Resolver} */22function resolveToSetextUnderline(events, context) {23  // To do: resolve like `markdown-rs`.24  let index = events.length;25  /** @type {number | undefined} */26  let content;27  /** @type {number | undefined} */28  let text;29  /** @type {number | undefined} */30  let definition;31 32  // Find the opening of the content.33  // It’ll always exist: we don’t tokenize if it isn’t there.34  while (index--) {35    if (events[index][0] === 'enter') {36      if (events[index][1].type === "content") {37        content = index;38        break;39      }40      if (events[index][1].type === "paragraph") {41        text = index;42      }43    }44    // Exit45    else {46      if (events[index][1].type === "content") {47        // Remove the content end (if needed we’ll add it later)48        events.splice(index, 1);49      }50      if (!definition && events[index][1].type === "definition") {51        definition = index;52      }53    }54  }55  const heading = {56    type: "setextHeading",57    start: {58      ...events[content][1].start59    },60    end: {61      ...events[events.length - 1][1].end62    }63  };64 65  // Change the paragraph to setext heading text.66  events[text][1].type = "setextHeadingText";67 68  // If we have definitions in the content, we’ll keep on having content,69  // but we need move it.70  if (definition) {71    events.splice(text, 0, ['enter', heading, context]);72    events.splice(definition + 1, 0, ['exit', events[content][1], context]);73    events[content][1].end = {74      ...events[definition][1].end75    };76  } else {77    events[content][1] = heading;78  }79 80  // Add the heading exit at the end.81  events.push(['exit', heading, context]);82  return events;83}84 85/**86 * @this {TokenizeContext}87 *   Context.88 * @type {Tokenizer}89 */90function tokenizeSetextUnderline(effects, ok, nok) {91  const self = this;92  /** @type {NonNullable<Code>} */93  let marker;94  return start;95 96  /**97   * At start of heading (setext) underline.98   *99   * ```markdown100   *   | aa101   * > | ==102   *     ^103   * ```104   *105   * @type {State}106   */107  function start(code) {108    let index = self.events.length;109    /** @type {boolean | undefined} */110    let paragraph;111    // Find an opening.112    while (index--) {113      // Skip enter/exit of line ending, line prefix, and content.114      // We can now either have a definition or a paragraph.115      if (self.events[index][1].type !== "lineEnding" && self.events[index][1].type !== "linePrefix" && self.events[index][1].type !== "content") {116        paragraph = self.events[index][1].type === "paragraph";117        break;118      }119    }120 121    // To do: handle lazy/pierce like `markdown-rs`.122    // To do: parse indent like `markdown-rs`.123    if (!self.parser.lazy[self.now().line] && (self.interrupt || paragraph)) {124      effects.enter("setextHeadingLine");125      marker = code;126      return before(code);127    }128    return nok(code);129  }130 131  /**132   * After optional whitespace, at `-` or `=`.133   *134   * ```markdown135   *   | aa136   * > | ==137   *     ^138   * ```139   *140   * @type {State}141   */142  function before(code) {143    effects.enter("setextHeadingLineSequence");144    return inside(code);145  }146 147  /**148   * In sequence.149   *150   * ```markdown151   *   | aa152   * > | ==153   *     ^154   * ```155   *156   * @type {State}157   */158  function inside(code) {159    if (code === marker) {160      effects.consume(code);161      return inside;162    }163    effects.exit("setextHeadingLineSequence");164    return markdownSpace(code) ? factorySpace(effects, after, "lineSuffix")(code) : after(code);165  }166 167  /**168   * After sequence, after optional whitespace.169   *170   * ```markdown171   *   | aa172   * > | ==173   *       ^174   * ```175   *176   * @type {State}177   */178  function after(code) {179    if (code === null || markdownLineEnding(code)) {180      effects.exit("setextHeadingLine");181      return ok(code);182    }183    return nok(code);184  }185}