/** * @import {EncodeSides} from '../types.js' */ import {classifyCharacter} from 'micromark-util-classify-character' /** * Check whether to encode (as a character reference) the characters * surrounding an attention run. * * Which characters are around an attention run influence whether it works or * not. * * See for more info. * See this markdown in a particular renderer to see what works: * * ```markdown * | | A (letter inside) | B (punctuation inside) | C (whitespace inside) | D (nothing inside) | * | ----------------------- | ----------------- | ---------------------- | --------------------- | ------------------ | * | 1 (letter outside) | x*y*z | x*.*z | x* *z | x**z | * | 2 (punctuation outside) | .*y*. | .*.*. | .* *. | .**. | * | 3 (whitespace outside) | x *y* z | x *.* z | x * * z | x ** z | * | 4 (nothing outside) | *x* | *.* | * * | ** | * ``` * * @param {number} outside * Code point on the outer side of the run. * @param {number} inside * Code point on the inner side of the run. * @param {'*' | '_'} marker * Marker of the run. * Underscores are handled more strictly (they form less often) than * asterisks. * @returns {EncodeSides} * Whether to encode characters. */ // Important: punctuation must never be encoded. // Punctuation is solely used by markdown constructs. // And by encoding itself. // Encoding them will break constructs or double encode things. export function encodeInfo(outside, inside, marker) { const outsideKind = classifyCharacter(outside) const insideKind = classifyCharacter(inside) // Letter outside: if (outsideKind === undefined) { return insideKind === undefined ? // Letter inside: // we have to encode *both* letters for `_` as it is looser. // it already forms for `*` (and GFMs `~`). marker === '_' ? {inside: true, outside: true} : {inside: false, outside: false} : insideKind === 1 ? // Whitespace inside: encode both (letter, whitespace). {inside: true, outside: true} : // Punctuation inside: encode outer (letter) {inside: false, outside: true} } // Whitespace outside: if (outsideKind === 1) { return insideKind === undefined ? // Letter inside: already forms. {inside: false, outside: false} : insideKind === 1 ? // Whitespace inside: encode both (whitespace). {inside: true, outside: true} : // Punctuation inside: already forms. {inside: false, outside: false} } // Punctuation outside: return insideKind === undefined ? // Letter inside: already forms. {inside: false, outside: false} : insideKind === 1 ? // Whitespace inside: encode inner (whitespace). {inside: true, outside: false} : // Punctuation inside: already forms. {inside: false, outside: false} }