/** * @typedef {import('mdast').Nodes} Nodes * * @typedef Options * Configuration (optional). * @property {boolean | null | undefined} [includeImageAlt=true] * Whether to use `alt` for `image`s (default: `true`). * @property {boolean | null | undefined} [includeHtml=true] * Whether to use `value` of HTML (default: `true`). */ /** @type {Options} */ const emptyOptions = {} /** * Get the text content of a node or list of nodes. * * Prefers the node’s plain-text fields, otherwise serializes its children, * and if the given value is an array, serialize the nodes in it. * * @param {unknown} [value] * Thing to serialize, typically `Node`. * @param {Options | null | undefined} [options] * Configuration (optional). * @returns {string} * Serialized `value`. */ export function toString(value, options) { const settings = options || emptyOptions const includeImageAlt = typeof settings.includeImageAlt === 'boolean' ? settings.includeImageAlt : true const includeHtml = typeof settings.includeHtml === 'boolean' ? settings.includeHtml : true return one(value, includeImageAlt, includeHtml) } /** * One node or several nodes. * * @param {unknown} value * Thing to serialize. * @param {boolean} includeImageAlt * Include image `alt`s. * @param {boolean} includeHtml * Include HTML. * @returns {string} * Serialized node. */ function one(value, includeImageAlt, includeHtml) { if (node(value)) { if ('value' in value) { return value.type === 'html' && !includeHtml ? '' : value.value } if (includeImageAlt && 'alt' in value && value.alt) { return value.alt } if ('children' in value) { return all(value.children, includeImageAlt, includeHtml) } } if (Array.isArray(value)) { return all(value, includeImageAlt, includeHtml) } return '' } /** * Serialize a list of nodes. * * @param {Array} values * Thing to serialize. * @param {boolean} includeImageAlt * Include image `alt`s. * @param {boolean} includeHtml * Include HTML. * @returns {string} * Serialized nodes. */ function all(values, includeImageAlt, includeHtml) { /** @type {Array} */ const result = [] let index = -1 while (++index < values.length) { result[index] = one(values[index], includeImageAlt, includeHtml) } return result.join('') } /** * Check if `value` looks like a node. * * @param {unknown} value * Thing. * @returns {value is Nodes} * Whether `value` is a node. */ function node(value) { return Boolean(value && typeof value === 'object') }