CoolFace
Apppublic

AK-21/Graphite-Industrial-Intelligence

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
html-flow.js876 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 { asciiAlphanumeric, asciiAlpha, markdownLineEndingOrSpace, markdownLineEnding, markdownSpace } from 'micromark-util-character';13import { htmlBlockNames, htmlRawNames } from 'micromark-util-html-tag-name';14import { blankLine } from './blank-line.js';15 16/** @type {Construct} */17export const htmlFlow = {18  concrete: true,19  name: 'htmlFlow',20  resolveTo: resolveToHtmlFlow,21  tokenize: tokenizeHtmlFlow22};23 24/** @type {Construct} */25const blankLineBefore = {26  partial: true,27  tokenize: tokenizeBlankLineBefore28};29const nonLazyContinuationStart = {30  partial: true,31  tokenize: tokenizeNonLazyContinuationStart32};33 34/** @type {Resolver} */35function resolveToHtmlFlow(events) {36  let index = events.length;37  while (index--) {38    if (events[index][0] === 'enter' && events[index][1].type === "htmlFlow") {39      break;40    }41  }42  if (index > 1 && events[index - 2][1].type === "linePrefix") {43    // Add the prefix start to the HTML token.44    events[index][1].start = events[index - 2][1].start;45    // Add the prefix start to the HTML line token.46    events[index + 1][1].start = events[index - 2][1].start;47    // Remove the line prefix.48    events.splice(index - 2, 2);49  }50  return events;51}52 53/**54 * @this {TokenizeContext}55 *   Context.56 * @type {Tokenizer}57 */58function tokenizeHtmlFlow(effects, ok, nok) {59  const self = this;60  /** @type {number} */61  let marker;62  /** @type {boolean} */63  let closingTag;64  /** @type {string} */65  let buffer;66  /** @type {number} */67  let index;68  /** @type {Code} */69  let markerB;70  return start;71 72  /**73   * Start of HTML (flow).74   *75   * ```markdown76   * > | <x />77   *     ^78   * ```79   *80   * @type {State}81   */82  function start(code) {83    // To do: parse indent like `markdown-rs`.84    return before(code);85  }86 87  /**88   * At `<`, after optional whitespace.89   *90   * ```markdown91   * > | <x />92   *     ^93   * ```94   *95   * @type {State}96   */97  function before(code) {98    effects.enter("htmlFlow");99    effects.enter("htmlFlowData");100    effects.consume(code);101    return open;102  }103 104  /**105   * After `<`, at tag name or other stuff.106   *107   * ```markdown108   * > | <x />109   *      ^110   * > | <!doctype>111   *      ^112   * > | <!--xxx-->113   *      ^114   * ```115   *116   * @type {State}117   */118  function open(code) {119    if (code === 33) {120      effects.consume(code);121      return declarationOpen;122    }123    if (code === 47) {124      effects.consume(code);125      closingTag = true;126      return tagCloseStart;127    }128    if (code === 63) {129      effects.consume(code);130      marker = 3;131      // To do:132      // tokenizer.concrete = true133      // To do: use `markdown-rs` style interrupt.134      // While we’re in an instruction instead of a declaration, we’re on a `?`135      // right now, so we do need to search for `>`, similar to declarations.136      return self.interrupt ? ok : continuationDeclarationInside;137    }138 139    // ASCII alphabetical.140    if (asciiAlpha(code)) {141      // Always the case.142      effects.consume(code);143      buffer = String.fromCharCode(code);144      return tagName;145    }146    return nok(code);147  }148 149  /**150   * After `<!`, at declaration, comment, or CDATA.151   *152   * ```markdown153   * > | <!doctype>154   *       ^155   * > | <!--xxx-->156   *       ^157   * > | <![CDATA[>&<]]>158   *       ^159   * ```160   *161   * @type {State}162   */163  function declarationOpen(code) {164    if (code === 45) {165      effects.consume(code);166      marker = 2;167      return commentOpenInside;168    }169    if (code === 91) {170      effects.consume(code);171      marker = 5;172      index = 0;173      return cdataOpenInside;174    }175 176    // ASCII alphabetical.177    if (asciiAlpha(code)) {178      effects.consume(code);179      marker = 4;180      // // Do not form containers.181      // tokenizer.concrete = true182      return self.interrupt ? ok : continuationDeclarationInside;183    }184    return nok(code);185  }186 187  /**188   * After `<!-`, inside a comment, at another `-`.189   *190   * ```markdown191   * > | <!--xxx-->192   *        ^193   * ```194   *195   * @type {State}196   */197  function commentOpenInside(code) {198    if (code === 45) {199      effects.consume(code);200      // // Do not form containers.201      // tokenizer.concrete = true202      return self.interrupt ? ok : continuationDeclarationInside;203    }204    return nok(code);205  }206 207  /**208   * After `<![`, inside CDATA, expecting `CDATA[`.209   *210   * ```markdown211   * > | <![CDATA[>&<]]>212   *        ^^^^^^213   * ```214   *215   * @type {State}216   */217  function cdataOpenInside(code) {218    const value = "CDATA[";219    if (code === value.charCodeAt(index++)) {220      effects.consume(code);221      if (index === value.length) {222        // // Do not form containers.223        // tokenizer.concrete = true224        return self.interrupt ? ok : continuation;225      }226      return cdataOpenInside;227    }228    return nok(code);229  }230 231  /**232   * After `</`, in closing tag, at tag name.233   *234   * ```markdown235   * > | </x>236   *       ^237   * ```238   *239   * @type {State}240   */241  function tagCloseStart(code) {242    if (asciiAlpha(code)) {243      // Always the case.244      effects.consume(code);245      buffer = String.fromCharCode(code);246      return tagName;247    }248    return nok(code);249  }250 251  /**252   * In tag name.253   *254   * ```markdown255   * > | <ab>256   *      ^^257   * > | </ab>258   *       ^^259   * ```260   *261   * @type {State}262   */263  function tagName(code) {264    if (code === null || code === 47 || code === 62 || markdownLineEndingOrSpace(code)) {265      const slash = code === 47;266      const name = buffer.toLowerCase();267      if (!slash && !closingTag && htmlRawNames.includes(name)) {268        marker = 1;269        // // Do not form containers.270        // tokenizer.concrete = true271        return self.interrupt ? ok(code) : continuation(code);272      }273      if (htmlBlockNames.includes(buffer.toLowerCase())) {274        marker = 6;275        if (slash) {276          effects.consume(code);277          return basicSelfClosing;278        }279 280        // // Do not form containers.281        // tokenizer.concrete = true282        return self.interrupt ? ok(code) : continuation(code);283      }284      marker = 7;285      // Do not support complete HTML when interrupting.286      return self.interrupt && !self.parser.lazy[self.now().line] ? nok(code) : closingTag ? completeClosingTagAfter(code) : completeAttributeNameBefore(code);287    }288 289    // ASCII alphanumerical and `-`.290    if (code === 45 || asciiAlphanumeric(code)) {291      effects.consume(code);292      buffer += String.fromCharCode(code);293      return tagName;294    }295    return nok(code);296  }297 298  /**299   * After closing slash of a basic tag name.300   *301   * ```markdown302   * > | <div/>303   *          ^304   * ```305   *306   * @type {State}307   */308  function basicSelfClosing(code) {309    if (code === 62) {310      effects.consume(code);311      // // Do not form containers.312      // tokenizer.concrete = true313      return self.interrupt ? ok : continuation;314    }315    return nok(code);316  }317 318  /**319   * After closing slash of a complete tag name.320   *321   * ```markdown322   * > | <x/>323   *        ^324   * ```325   *326   * @type {State}327   */328  function completeClosingTagAfter(code) {329    if (markdownSpace(code)) {330      effects.consume(code);331      return completeClosingTagAfter;332    }333    return completeEnd(code);334  }335 336  /**337   * At an attribute name.338   *339   * At first, this state is used after a complete tag name, after whitespace,340   * where it expects optional attributes or the end of the tag.341   * It is also reused after attributes, when expecting more optional342   * attributes.343   *344   * ```markdown345   * > | <a />346   *        ^347   * > | <a :b>348   *        ^349   * > | <a _b>350   *        ^351   * > | <a b>352   *        ^353   * > | <a >354   *        ^355   * ```356   *357   * @type {State}358   */359  function completeAttributeNameBefore(code) {360    if (code === 47) {361      effects.consume(code);362      return completeEnd;363    }364 365    // ASCII alphanumerical and `:` and `_`.366    if (code === 58 || code === 95 || asciiAlpha(code)) {367      effects.consume(code);368      return completeAttributeName;369    }370    if (markdownSpace(code)) {371      effects.consume(code);372      return completeAttributeNameBefore;373    }374    return completeEnd(code);375  }376 377  /**378   * In attribute name.379   *380   * ```markdown381   * > | <a :b>382   *         ^383   * > | <a _b>384   *         ^385   * > | <a b>386   *         ^387   * ```388   *389   * @type {State}390   */391  function completeAttributeName(code) {392    // ASCII alphanumerical and `-`, `.`, `:`, and `_`.393    if (code === 45 || code === 46 || code === 58 || code === 95 || asciiAlphanumeric(code)) {394      effects.consume(code);395      return completeAttributeName;396    }397    return completeAttributeNameAfter(code);398  }399 400  /**401   * After attribute name, at an optional initializer, the end of the tag, or402   * whitespace.403   *404   * ```markdown405   * > | <a b>406   *         ^407   * > | <a b=c>408   *         ^409   * ```410   *411   * @type {State}412   */413  function completeAttributeNameAfter(code) {414    if (code === 61) {415      effects.consume(code);416      return completeAttributeValueBefore;417    }418    if (markdownSpace(code)) {419      effects.consume(code);420      return completeAttributeNameAfter;421    }422    return completeAttributeNameBefore(code);423  }424 425  /**426   * Before unquoted, double quoted, or single quoted attribute value, allowing427   * whitespace.428   *429   * ```markdown430   * > | <a b=c>431   *          ^432   * > | <a b="c">433   *          ^434   * ```435   *436   * @type {State}437   */438  function completeAttributeValueBefore(code) {439    if (code === null || code === 60 || code === 61 || code === 62 || code === 96) {440      return nok(code);441    }442    if (code === 34 || code === 39) {443      effects.consume(code);444      markerB = code;445      return completeAttributeValueQuoted;446    }447    if (markdownSpace(code)) {448      effects.consume(code);449      return completeAttributeValueBefore;450    }451    return completeAttributeValueUnquoted(code);452  }453 454  /**455   * In double or single quoted attribute value.456   *457   * ```markdown458   * > | <a b="c">459   *           ^460   * > | <a b='c'>461   *           ^462   * ```463   *464   * @type {State}465   */466  function completeAttributeValueQuoted(code) {467    if (code === markerB) {468      effects.consume(code);469      markerB = null;470      return completeAttributeValueQuotedAfter;471    }472    if (code === null || markdownLineEnding(code)) {473      return nok(code);474    }475    effects.consume(code);476    return completeAttributeValueQuoted;477  }478 479  /**480   * In unquoted attribute value.481   *482   * ```markdown483   * > | <a b=c>484   *          ^485   * ```486   *487   * @type {State}488   */489  function completeAttributeValueUnquoted(code) {490    if (code === null || code === 34 || code === 39 || code === 47 || code === 60 || code === 61 || code === 62 || code === 96 || markdownLineEndingOrSpace(code)) {491      return completeAttributeNameAfter(code);492    }493    effects.consume(code);494    return completeAttributeValueUnquoted;495  }496 497  /**498   * After double or single quoted attribute value, before whitespace or the499   * end of the tag.500   *501   * ```markdown502   * > | <a b="c">503   *            ^504   * ```505   *506   * @type {State}507   */508  function completeAttributeValueQuotedAfter(code) {509    if (code === 47 || code === 62 || markdownSpace(code)) {510      return completeAttributeNameBefore(code);511    }512    return nok(code);513  }514 515  /**516   * In certain circumstances of a complete tag where only an `>` is allowed.517   *518   * ```markdown519   * > | <a b="c">520   *             ^521   * ```522   *523   * @type {State}524   */525  function completeEnd(code) {526    if (code === 62) {527      effects.consume(code);528      return completeAfter;529    }530    return nok(code);531  }532 533  /**534   * After `>` in a complete tag.535   *536   * ```markdown537   * > | <x>538   *        ^539   * ```540   *541   * @type {State}542   */543  function completeAfter(code) {544    if (code === null || markdownLineEnding(code)) {545      // // Do not form containers.546      // tokenizer.concrete = true547      return continuation(code);548    }549    if (markdownSpace(code)) {550      effects.consume(code);551      return completeAfter;552    }553    return nok(code);554  }555 556  /**557   * In continuation of any HTML kind.558   *559   * ```markdown560   * > | <!--xxx-->561   *          ^562   * ```563   *564   * @type {State}565   */566  function continuation(code) {567    if (code === 45 && marker === 2) {568      effects.consume(code);569      return continuationCommentInside;570    }571    if (code === 60 && marker === 1) {572      effects.consume(code);573      return continuationRawTagOpen;574    }575    if (code === 62 && marker === 4) {576      effects.consume(code);577      return continuationClose;578    }579    if (code === 63 && marker === 3) {580      effects.consume(code);581      return continuationDeclarationInside;582    }583    if (code === 93 && marker === 5) {584      effects.consume(code);585      return continuationCdataInside;586    }587    if (markdownLineEnding(code) && (marker === 6 || marker === 7)) {588      effects.exit("htmlFlowData");589      return effects.check(blankLineBefore, continuationAfter, continuationStart)(code);590    }591    if (code === null || markdownLineEnding(code)) {592      effects.exit("htmlFlowData");593      return continuationStart(code);594    }595    effects.consume(code);596    return continuation;597  }598 599  /**600   * In continuation, at eol.601   *602   * ```markdown603   * > | <x>604   *        ^605   *   | asd606   * ```607   *608   * @type {State}609   */610  function continuationStart(code) {611    return effects.check(nonLazyContinuationStart, continuationStartNonLazy, continuationAfter)(code);612  }613 614  /**615   * In continuation, at eol, before non-lazy content.616   *617   * ```markdown618   * > | <x>619   *        ^620   *   | asd621   * ```622   *623   * @type {State}624   */625  function continuationStartNonLazy(code) {626    effects.enter("lineEnding");627    effects.consume(code);628    effects.exit("lineEnding");629    return continuationBefore;630  }631 632  /**633   * In continuation, before non-lazy content.634   *635   * ```markdown636   *   | <x>637   * > | asd638   *     ^639   * ```640   *641   * @type {State}642   */643  function continuationBefore(code) {644    if (code === null || markdownLineEnding(code)) {645      return continuationStart(code);646    }647    effects.enter("htmlFlowData");648    return continuation(code);649  }650 651  /**652   * In comment continuation, after one `-`, expecting another.653   *654   * ```markdown655   * > | <!--xxx-->656   *             ^657   * ```658   *659   * @type {State}660   */661  function continuationCommentInside(code) {662    if (code === 45) {663      effects.consume(code);664      return continuationDeclarationInside;665    }666    return continuation(code);667  }668 669  /**670   * In raw continuation, after `<`, at `/`.671   *672   * ```markdown673   * > | <script>console.log(1)</script>674   *                            ^675   * ```676   *677   * @type {State}678   */679  function continuationRawTagOpen(code) {680    if (code === 47) {681      effects.consume(code);682      buffer = '';683      return continuationRawEndTag;684    }685    return continuation(code);686  }687 688  /**689   * In raw continuation, after `</`, in a raw tag name.690   *691   * ```markdown692   * > | <script>console.log(1)</script>693   *                             ^^^^^^694   * ```695   *696   * @type {State}697   */698  function continuationRawEndTag(code) {699    if (code === 62) {700      const name = buffer.toLowerCase();701      if (htmlRawNames.includes(name)) {702        effects.consume(code);703        return continuationClose;704      }705      return continuation(code);706    }707    if (asciiAlpha(code) && buffer.length < 8) {708      // Always the case.709      effects.consume(code);710      buffer += String.fromCharCode(code);711      return continuationRawEndTag;712    }713    return continuation(code);714  }715 716  /**717   * In cdata continuation, after `]`, expecting `]>`.718   *719   * ```markdown720   * > | <![CDATA[>&<]]>721   *                  ^722   * ```723   *724   * @type {State}725   */726  function continuationCdataInside(code) {727    if (code === 93) {728      effects.consume(code);729      return continuationDeclarationInside;730    }731    return continuation(code);732  }733 734  /**735   * In declaration or instruction continuation, at `>`.736   *737   * ```markdown738   * > | <!-->739   *         ^740   * > | <?>741   *       ^742   * > | <!q>743   *        ^744   * > | <!--ab-->745   *             ^746   * > | <![CDATA[>&<]]>747   *                   ^748   * ```749   *750   * @type {State}751   */752  function continuationDeclarationInside(code) {753    if (code === 62) {754      effects.consume(code);755      return continuationClose;756    }757 758    // More dashes.759    if (code === 45 && marker === 2) {760      effects.consume(code);761      return continuationDeclarationInside;762    }763    return continuation(code);764  }765 766  /**767   * In closed continuation: everything we get until the eol/eof is part of it.768   *769   * ```markdown770   * > | <!doctype>771   *               ^772   * ```773   *774   * @type {State}775   */776  function continuationClose(code) {777    if (code === null || markdownLineEnding(code)) {778      effects.exit("htmlFlowData");779      return continuationAfter(code);780    }781    effects.consume(code);782    return continuationClose;783  }784 785  /**786   * Done.787   *788   * ```markdown789   * > | <!doctype>790   *               ^791   * ```792   *793   * @type {State}794   */795  function continuationAfter(code) {796    effects.exit("htmlFlow");797    // // Feel free to interrupt.798    // tokenizer.interrupt = false799    // // No longer concrete.800    // tokenizer.concrete = false801    return ok(code);802  }803}804 805/**806 * @this {TokenizeContext}807 *   Context.808 * @type {Tokenizer}809 */810function tokenizeNonLazyContinuationStart(effects, ok, nok) {811  const self = this;812  return start;813 814  /**815   * At eol, before continuation.816   *817   * ```markdown818   * > | * ```js819   *            ^820   *   | b821   * ```822   *823   * @type {State}824   */825  function start(code) {826    if (markdownLineEnding(code)) {827      effects.enter("lineEnding");828      effects.consume(code);829      effects.exit("lineEnding");830      return after;831    }832    return nok(code);833  }834 835  /**836   * A continuation.837   *838   * ```markdown839   *   | * ```js840   * > | b841   *     ^842   * ```843   *844   * @type {State}845   */846  function after(code) {847    return self.parser.lazy[self.now().line] ? nok(code) : ok(code);848  }849}850 851/**852 * @this {TokenizeContext}853 *   Context.854 * @type {Tokenizer}855 */856function tokenizeBlankLineBefore(effects, ok, nok) {857  return start;858 859  /**860   * Before eol, expecting blank line.861   *862   * ```markdown863   * > | <div>864   *          ^865   *   |866   * ```867   *868   * @type {State}869   */870  function start(code) {871    effects.enter("lineEnding");872    effects.consume(code);873    effects.exit("lineEnding");874    return effects.attempt(blankLine, ok, nok);875  }876}