AK-21/Graphite-Industrial-Intelligence
0
1/**2 * @import {3 * Code,4 * Construct,5 * State,6 * TokenizeContext,7 * Tokenizer8 * } from 'micromark-util-types'9 */10 11import { decodeNamedCharacterReference } from 'decode-named-character-reference';12import { asciiAlphanumeric, asciiDigit, asciiHexDigit } from 'micromark-util-character';13/** @type {Construct} */14export const characterReference = {15 name: 'characterReference',16 tokenize: tokenizeCharacterReference17};18 19/**20 * @this {TokenizeContext}21 * Context.22 * @type {Tokenizer}23 */24function tokenizeCharacterReference(effects, ok, nok) {25 const self = this;26 let size = 0;27 /** @type {number} */28 let max;29 /** @type {(code: Code) => boolean} */30 let test;31 return start;32 33 /**34 * Start of character reference.35 *36 * ```markdown37 * > | a&b38 * ^39 * > | a{b40 * ^41 * > | a	b42 * ^43 * ```44 *45 * @type {State}46 */47 function start(code) {48 effects.enter("characterReference");49 effects.enter("characterReferenceMarker");50 effects.consume(code);51 effects.exit("characterReferenceMarker");52 return open;53 }54 55 /**56 * After `&`, at `#` for numeric references or alphanumeric for named57 * references.58 *59 * ```markdown60 * > | a&b61 * ^62 * > | a{b63 * ^64 * > | a	b65 * ^66 * ```67 *68 * @type {State}69 */70 function open(code) {71 if (code === 35) {72 effects.enter("characterReferenceMarkerNumeric");73 effects.consume(code);74 effects.exit("characterReferenceMarkerNumeric");75 return numeric;76 }77 effects.enter("characterReferenceValue");78 max = 31;79 test = asciiAlphanumeric;80 return value(code);81 }82 83 /**84 * After `#`, at `x` for hexadecimals or digit for decimals.85 *86 * ```markdown87 * > | a{b88 * ^89 * > | a	b90 * ^91 * ```92 *93 * @type {State}94 */95 function numeric(code) {96 if (code === 88 || code === 120) {97 effects.enter("characterReferenceMarkerHexadecimal");98 effects.consume(code);99 effects.exit("characterReferenceMarkerHexadecimal");100 effects.enter("characterReferenceValue");101 max = 6;102 test = asciiHexDigit;103 return value;104 }105 effects.enter("characterReferenceValue");106 max = 7;107 test = asciiDigit;108 return value(code);109 }110 111 /**112 * After markers (`&#x`, `&#`, or `&`), in value, before `;`.113 *114 * The character reference kind defines what and how many characters are115 * allowed.116 *117 * ```markdown118 * > | a&b119 * ^^^120 * > | a{b121 * ^^^122 * > | a	b123 * ^124 * ```125 *126 * @type {State}127 */128 function value(code) {129 if (code === 59 && size) {130 const token = effects.exit("characterReferenceValue");131 if (test === asciiAlphanumeric && !decodeNamedCharacterReference(self.sliceSerialize(token))) {132 return nok(code);133 }134 135 // To do: `markdown-rs` uses a different name:136 // `CharacterReferenceMarkerSemi`.137 effects.enter("characterReferenceMarker");138 effects.consume(code);139 effects.exit("characterReferenceMarker");140 effects.exit("characterReference");141 return ok;142 }143 if (test(code) && size++ < max) {144 effects.consume(code);145 return value;146 }147 return nok(code);148 }149}