CoolFace
Apppublic

AK-21/Graphite-Industrial-Intelligence

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
code-fenced.js460 linesDownload Raw Back to lib
1/**2 * @import {3 *   Code,4 *   Construct,5 *   State,6 *   TokenizeContext,7 *   Tokenizer8 * } from 'micromark-util-types'9 */10 11import { factorySpace } from 'micromark-factory-space';12import { markdownLineEnding, markdownSpace } from 'micromark-util-character';13/** @type {Construct} */14const nonLazyContinuation = {15  partial: true,16  tokenize: tokenizeNonLazyContinuation17};18 19/** @type {Construct} */20export const codeFenced = {21  concrete: true,22  name: 'codeFenced',23  tokenize: tokenizeCodeFenced24};25 26/**27 * @this {TokenizeContext}28 *   Context.29 * @type {Tokenizer}30 */31function tokenizeCodeFenced(effects, ok, nok) {32  const self = this;33  /** @type {Construct} */34  const closeStart = {35    partial: true,36    tokenize: tokenizeCloseStart37  };38  let initialPrefix = 0;39  let sizeOpen = 0;40  /** @type {NonNullable<Code>} */41  let marker;42  return start;43 44  /**45   * Start of code.46   *47   * ```markdown48   * > | ~~~js49   *     ^50   *   | alert(1)51   *   | ~~~52   * ```53   *54   * @type {State}55   */56  function start(code) {57    // To do: parse whitespace like `markdown-rs`.58    return beforeSequenceOpen(code);59  }60 61  /**62   * In opening fence, after prefix, at sequence.63   *64   * ```markdown65   * > | ~~~js66   *     ^67   *   | alert(1)68   *   | ~~~69   * ```70   *71   * @type {State}72   */73  function beforeSequenceOpen(code) {74    const tail = self.events[self.events.length - 1];75    initialPrefix = tail && tail[1].type === "linePrefix" ? tail[2].sliceSerialize(tail[1], true).length : 0;76    marker = code;77    effects.enter("codeFenced");78    effects.enter("codeFencedFence");79    effects.enter("codeFencedFenceSequence");80    return sequenceOpen(code);81  }82 83  /**84   * In opening fence sequence.85   *86   * ```markdown87   * > | ~~~js88   *      ^89   *   | alert(1)90   *   | ~~~91   * ```92   *93   * @type {State}94   */95  function sequenceOpen(code) {96    if (code === marker) {97      sizeOpen++;98      effects.consume(code);99      return sequenceOpen;100    }101    if (sizeOpen < 3) {102      return nok(code);103    }104    effects.exit("codeFencedFenceSequence");105    return markdownSpace(code) ? factorySpace(effects, infoBefore, "whitespace")(code) : infoBefore(code);106  }107 108  /**109   * In opening fence, after the sequence (and optional whitespace), before info.110   *111   * ```markdown112   * > | ~~~js113   *        ^114   *   | alert(1)115   *   | ~~~116   * ```117   *118   * @type {State}119   */120  function infoBefore(code) {121    if (code === null || markdownLineEnding(code)) {122      effects.exit("codeFencedFence");123      return self.interrupt ? ok(code) : effects.check(nonLazyContinuation, atNonLazyBreak, after)(code);124    }125    effects.enter("codeFencedFenceInfo");126    effects.enter("chunkString", {127      contentType: "string"128    });129    return info(code);130  }131 132  /**133   * In info.134   *135   * ```markdown136   * > | ~~~js137   *        ^138   *   | alert(1)139   *   | ~~~140   * ```141   *142   * @type {State}143   */144  function info(code) {145    if (code === null || markdownLineEnding(code)) {146      effects.exit("chunkString");147      effects.exit("codeFencedFenceInfo");148      return infoBefore(code);149    }150    if (markdownSpace(code)) {151      effects.exit("chunkString");152      effects.exit("codeFencedFenceInfo");153      return factorySpace(effects, metaBefore, "whitespace")(code);154    }155    if (code === 96 && code === marker) {156      return nok(code);157    }158    effects.consume(code);159    return info;160  }161 162  /**163   * In opening fence, after info and whitespace, before meta.164   *165   * ```markdown166   * > | ~~~js eval167   *           ^168   *   | alert(1)169   *   | ~~~170   * ```171   *172   * @type {State}173   */174  function metaBefore(code) {175    if (code === null || markdownLineEnding(code)) {176      return infoBefore(code);177    }178    effects.enter("codeFencedFenceMeta");179    effects.enter("chunkString", {180      contentType: "string"181    });182    return meta(code);183  }184 185  /**186   * In meta.187   *188   * ```markdown189   * > | ~~~js eval190   *           ^191   *   | alert(1)192   *   | ~~~193   * ```194   *195   * @type {State}196   */197  function meta(code) {198    if (code === null || markdownLineEnding(code)) {199      effects.exit("chunkString");200      effects.exit("codeFencedFenceMeta");201      return infoBefore(code);202    }203    if (code === 96 && code === marker) {204      return nok(code);205    }206    effects.consume(code);207    return meta;208  }209 210  /**211   * At eol/eof in code, before a non-lazy closing fence or content.212   *213   * ```markdown214   * > | ~~~js215   *          ^216   * > | alert(1)217   *             ^218   *   | ~~~219   * ```220   *221   * @type {State}222   */223  function atNonLazyBreak(code) {224    return effects.attempt(closeStart, after, contentBefore)(code);225  }226 227  /**228   * Before code content, not a closing fence, at eol.229   *230   * ```markdown231   *   | ~~~js232   * > | alert(1)233   *             ^234   *   | ~~~235   * ```236   *237   * @type {State}238   */239  function contentBefore(code) {240    effects.enter("lineEnding");241    effects.consume(code);242    effects.exit("lineEnding");243    return contentStart;244  }245 246  /**247   * Before code content, not a closing fence.248   *249   * ```markdown250   *   | ~~~js251   * > | alert(1)252   *     ^253   *   | ~~~254   * ```255   *256   * @type {State}257   */258  function contentStart(code) {259    return initialPrefix > 0 && markdownSpace(code) ? factorySpace(effects, beforeContentChunk, "linePrefix", initialPrefix + 1)(code) : beforeContentChunk(code);260  }261 262  /**263   * Before code content, after optional prefix.264   *265   * ```markdown266   *   | ~~~js267   * > | alert(1)268   *     ^269   *   | ~~~270   * ```271   *272   * @type {State}273   */274  function beforeContentChunk(code) {275    if (code === null || markdownLineEnding(code)) {276      return effects.check(nonLazyContinuation, atNonLazyBreak, after)(code);277    }278    effects.enter("codeFlowValue");279    return contentChunk(code);280  }281 282  /**283   * In code content.284   *285   * ```markdown286   *   | ~~~js287   * > | alert(1)288   *     ^^^^^^^^289   *   | ~~~290   * ```291   *292   * @type {State}293   */294  function contentChunk(code) {295    if (code === null || markdownLineEnding(code)) {296      effects.exit("codeFlowValue");297      return beforeContentChunk(code);298    }299    effects.consume(code);300    return contentChunk;301  }302 303  /**304   * After code.305   *306   * ```markdown307   *   | ~~~js308   *   | alert(1)309   * > | ~~~310   *        ^311   * ```312   *313   * @type {State}314   */315  function after(code) {316    effects.exit("codeFenced");317    return ok(code);318  }319 320  /**321   * @this {TokenizeContext}322   *   Context.323   * @type {Tokenizer}324   */325  function tokenizeCloseStart(effects, ok, nok) {326    let size = 0;327    return startBefore;328 329    /**330     *331     *332     * @type {State}333     */334    function startBefore(code) {335      effects.enter("lineEnding");336      effects.consume(code);337      effects.exit("lineEnding");338      return start;339    }340 341    /**342     * Before closing fence, at optional whitespace.343     *344     * ```markdown345     *   | ~~~js346     *   | alert(1)347     * > | ~~~348     *     ^349     * ```350     *351     * @type {State}352     */353    function start(code) {354      // Always populated by defaults.355 356      // To do: `enter` here or in next state?357      effects.enter("codeFencedFence");358      return markdownSpace(code) ? factorySpace(effects, beforeSequenceClose, "linePrefix", self.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4)(code) : beforeSequenceClose(code);359    }360 361    /**362     * In closing fence, after optional whitespace, at sequence.363     *364     * ```markdown365     *   | ~~~js366     *   | alert(1)367     * > | ~~~368     *     ^369     * ```370     *371     * @type {State}372     */373    function beforeSequenceClose(code) {374      if (code === marker) {375        effects.enter("codeFencedFenceSequence");376        return sequenceClose(code);377      }378      return nok(code);379    }380 381    /**382     * In closing fence sequence.383     *384     * ```markdown385     *   | ~~~js386     *   | alert(1)387     * > | ~~~388     *     ^389     * ```390     *391     * @type {State}392     */393    function sequenceClose(code) {394      if (code === marker) {395        size++;396        effects.consume(code);397        return sequenceClose;398      }399      if (size >= sizeOpen) {400        effects.exit("codeFencedFenceSequence");401        return markdownSpace(code) ? factorySpace(effects, sequenceCloseAfter, "whitespace")(code) : sequenceCloseAfter(code);402      }403      return nok(code);404    }405 406    /**407     * After closing fence sequence, after optional whitespace.408     *409     * ```markdown410     *   | ~~~js411     *   | alert(1)412     * > | ~~~413     *        ^414     * ```415     *416     * @type {State}417     */418    function sequenceCloseAfter(code) {419      if (code === null || markdownLineEnding(code)) {420        effects.exit("codeFencedFence");421        return ok(code);422      }423      return nok(code);424    }425  }426}427 428/**429 * @this {TokenizeContext}430 *   Context.431 * @type {Tokenizer}432 */433function tokenizeNonLazyContinuation(effects, ok, nok) {434  const self = this;435  return start;436 437  /**438   *439   *440   * @type {State}441   */442  function start(code) {443    if (code === null) {444      return nok(code);445    }446    effects.enter("lineEnding");447    effects.consume(code);448    effects.exit("lineEnding");449    return lineStart;450  }451 452  /**453   *454   *455   * @type {State}456   */457  function lineStart(code) {458    return self.parser.lazy[self.now().line] ? nok(code) : ok(code);459  }460}