AK-21/Graphite-Industrial-Intelligence
0
1/**2 * @import {3 * Construct,4 * Previous,5 * Resolver,6 * State,7 * TokenizeContext,8 * Tokenizer,9 * Token10 * } from 'micromark-util-types'11 */12 13import { markdownLineEnding } from 'micromark-util-character';14/** @type {Construct} */15export const codeText = {16 name: 'codeText',17 previous,18 resolve: resolveCodeText,19 tokenize: tokenizeCodeText20};21 22// To do: next major: don’t resolve, like `markdown-rs`.23/** @type {Resolver} */24function resolveCodeText(events) {25 let tailExitIndex = events.length - 4;26 let headEnterIndex = 3;27 /** @type {number} */28 let index;29 /** @type {number | undefined} */30 let enter;31 32 // If we start and end with an EOL or a space.33 if ((events[headEnterIndex][1].type === "lineEnding" || events[headEnterIndex][1].type === 'space') && (events[tailExitIndex][1].type === "lineEnding" || events[tailExitIndex][1].type === 'space')) {34 index = headEnterIndex;35 36 // And we have data.37 while (++index < tailExitIndex) {38 if (events[index][1].type === "codeTextData") {39 // Then we have padding.40 events[headEnterIndex][1].type = "codeTextPadding";41 events[tailExitIndex][1].type = "codeTextPadding";42 headEnterIndex += 2;43 tailExitIndex -= 2;44 break;45 }46 }47 }48 49 // Merge adjacent spaces and data.50 index = headEnterIndex - 1;51 tailExitIndex++;52 while (++index <= tailExitIndex) {53 if (enter === undefined) {54 if (index !== tailExitIndex && events[index][1].type !== "lineEnding") {55 enter = index;56 }57 } else if (index === tailExitIndex || events[index][1].type === "lineEnding") {58 events[enter][1].type = "codeTextData";59 if (index !== enter + 2) {60 events[enter][1].end = events[index - 1][1].end;61 events.splice(enter + 2, index - enter - 2);62 tailExitIndex -= index - enter - 2;63 index = enter + 2;64 }65 enter = undefined;66 }67 }68 return events;69}70 71/**72 * @this {TokenizeContext}73 * Context.74 * @type {Previous}75 */76function previous(code) {77 // If there is a previous code, there will always be a tail.78 return code !== 96 || this.events[this.events.length - 1][1].type === "characterEscape";79}80 81/**82 * @this {TokenizeContext}83 * Context.84 * @type {Tokenizer}85 */86function tokenizeCodeText(effects, ok, nok) {87 const self = this;88 let sizeOpen = 0;89 /** @type {number} */90 let size;91 /** @type {Token} */92 let token;93 return start;94 95 /**96 * Start of code (text).97 *98 * ```markdown99 * > | `a`100 * ^101 * > | \`a`102 * ^103 * ```104 *105 * @type {State}106 */107 function start(code) {108 effects.enter("codeText");109 effects.enter("codeTextSequence");110 return sequenceOpen(code);111 }112 113 /**114 * In opening sequence.115 *116 * ```markdown117 * > | `a`118 * ^119 * ```120 *121 * @type {State}122 */123 function sequenceOpen(code) {124 if (code === 96) {125 effects.consume(code);126 sizeOpen++;127 return sequenceOpen;128 }129 effects.exit("codeTextSequence");130 return between(code);131 }132 133 /**134 * Between something and something else.135 *136 * ```markdown137 * > | `a`138 * ^^139 * ```140 *141 * @type {State}142 */143 function between(code) {144 // EOF.145 if (code === null) {146 return nok(code);147 }148 149 // To do: next major: don’t do spaces in resolve, but when compiling,150 // like `markdown-rs`.151 // Tabs don’t work, and virtual spaces don’t make sense.152 if (code === 32) {153 effects.enter('space');154 effects.consume(code);155 effects.exit('space');156 return between;157 }158 159 // Closing fence? Could also be data.160 if (code === 96) {161 token = effects.enter("codeTextSequence");162 size = 0;163 return sequenceClose(code);164 }165 if (markdownLineEnding(code)) {166 effects.enter("lineEnding");167 effects.consume(code);168 effects.exit("lineEnding");169 return between;170 }171 172 // Data.173 effects.enter("codeTextData");174 return data(code);175 }176 177 /**178 * In data.179 *180 * ```markdown181 * > | `a`182 * ^183 * ```184 *185 * @type {State}186 */187 function data(code) {188 if (code === null || code === 32 || code === 96 || markdownLineEnding(code)) {189 effects.exit("codeTextData");190 return between(code);191 }192 effects.consume(code);193 return data;194 }195 196 /**197 * In closing sequence.198 *199 * ```markdown200 * > | `a`201 * ^202 * ```203 *204 * @type {State}205 */206 function sequenceClose(code) {207 // More.208 if (code === 96) {209 effects.consume(code);210 size++;211 return sequenceClose;212 }213 214 // Done!215 if (size === sizeOpen) {216 effects.exit("codeTextSequence");217 effects.exit("codeText");218 return ok(code);219 }220 221 // More or less accents: mark as data.222 token.type = "codeTextData";223 return data(code);224 }225}