(node: Node)
| 207 | } |
| 208 | |
| 209 | function serializeInline(node: Node): string { |
| 210 | if (node.nodeType === Node.TEXT_NODE) { |
| 211 | return normalizeText(node.textContent || ''); |
| 212 | } |
| 213 | |
| 214 | if (!(node instanceof Element)) { |
| 215 | return ''; |
| 216 | } |
| 217 | |
| 218 | const tagName = node.tagName.toLowerCase(); |
| 219 | const wrapLines = (value: string, marker: '**' | '_' | '~~') => { |
| 220 | if (!value.includes('\n')) { |
| 221 | return `${marker}${value}${marker}`; |
| 222 | } |
| 223 | |
| 224 | return value |
| 225 | .split('\n') |
| 226 | .map((line) => (line ? `${marker}${line}${marker}` : '')) |
| 227 | .join('\n'); |
| 228 | }; |
| 229 | |
| 230 | switch (tagName) { |
| 231 | case 'strong': |
| 232 | case 'b': |
| 233 | return wrapLines(serializeChildren(node), '**'); |
| 234 | case 'em': |
| 235 | case 'i': |
| 236 | return wrapLines(serializeChildren(node), '_'); |
| 237 | case 's': |
| 238 | case 'del': |
| 239 | case 'strike': |
| 240 | return wrapLines(serializeChildren(node), '~~'); |
| 241 | case 'a': { |
| 242 | const href = node.getAttribute('href') || ''; |
| 243 | const label = serializeChildren(node) || href; |
| 244 | return `[${label}](${href})`; |
| 245 | } |
| 246 | case 'code': |
| 247 | return `\`${serializeChildren(node)}\``; |
| 248 | case 'br': |
| 249 | return '\n'; |
| 250 | case 'img': { |
| 251 | const src = node.getAttribute('src') || ''; |
| 252 | const alt = node.getAttribute('alt') || ''; |
| 253 | return ``; |
| 254 | } |
| 255 | case 'video': { |
| 256 | const source = node.querySelector('source'); |
| 257 | const src = node.getAttribute('src') || source?.getAttribute('src') || ''; |
| 258 | const alt = node.getAttribute('aria-label') || ''; |
| 259 | return ``; |
| 260 | } |
| 261 | case 'p': |
| 262 | return serializeChildren(node).trim(); |
| 263 | case 'li': |
| 264 | return serializeChildren(node).trim(); |
| 265 | default: |
| 266 | return serializeChildren(node); |
no test coverage detected