/** * @typedef {import('micromark-util-types').Chunk} Chunk * @typedef {import('micromark-util-types').Code} Code * @typedef {import('micromark-util-types').Encoding} Encoding * @typedef {import('micromark-util-types').Value} Value */ /** * @callback Preprocessor * @param {Value} value * @param {Encoding | null | undefined} [encoding] * @param {boolean | null | undefined} [end=false] * @returns {Array} */ const search = /[\0\t\n\r]/g /** * @returns {Preprocessor} */ export function preprocess() { let column = 1 let buffer = '' /** @type {boolean | undefined} */ let start = true /** @type {boolean | undefined} */ let atCarriageReturn return preprocessor /** @type {Preprocessor} */ // eslint-disable-next-line complexity function preprocessor(value, encoding, end) { /** @type {Array} */ const chunks = [] /** @type {RegExpMatchArray | null} */ let match /** @type {number} */ let next /** @type {number} */ let startPosition /** @type {number} */ let endPosition /** @type {Code} */ let code value = buffer + (typeof value === 'string' ? value.toString() : new TextDecoder(encoding || undefined).decode(value)) startPosition = 0 buffer = '' if (start) { // To do: `markdown-rs` actually parses BOMs (byte order mark). if (value.charCodeAt(0) === 65279) { startPosition++ } start = undefined } while (startPosition < value.length) { search.lastIndex = startPosition match = search.exec(value) endPosition = match && match.index !== undefined ? match.index : value.length code = value.charCodeAt(endPosition) if (!match) { buffer = value.slice(startPosition) break } if (code === 10 && startPosition === endPosition && atCarriageReturn) { chunks.push(-3) atCarriageReturn = undefined } else { if (atCarriageReturn) { chunks.push(-5) atCarriageReturn = undefined } if (startPosition < endPosition) { chunks.push(value.slice(startPosition, endPosition)) column += endPosition - startPosition } switch (code) { case 0: { chunks.push(65533) column++ break } case 9: { next = Math.ceil(column / 4) * 4 chunks.push(-2) while (column++ < next) chunks.push(-1) break } case 10: { chunks.push(-4) column = 1 break } default: { atCarriageReturn = true column = 1 } } } startPosition = endPosition + 1 } if (end) { if (atCarriageReturn) chunks.push(-5) if (buffer) chunks.push(buffer) chunks.push(null) } return chunks } }