{"version":3,"sources":["../src/utils/htmlLineBreaks.ts"],"sourcesContent":["/**\n * Block-level containers that indicate the content is already structured HTML.\n * Void/inline elements (img, br, b, span) are deliberately excluded: content can\n * mix them with plain-text line breaks and still need normalization.\n */\nconst BLOCK_LEVEL_TAG =\n  /<(p|div|h[1-6]|ul|ol|li|blockquote|pre|table|figure|section|article)\\b/i;\n\n/** A block whose entire content is a single image tag. */\nconst STANDALONE_IMAGE = /^<img\\b[^>]*\\/?>$/i;\n\nexport interface NormalizeLineBreaksOptions {\n  /**\n   * Render breaks using only `<br>` instead of `<p>` blocks. Required when the\n   * output is placed inside phrasing content (a `<span>` or `<label>`), where\n   * block elements are invalid HTML.\n   */\n  inline?: boolean;\n}\n\n/**\n * Converte quebras de linha de texto puro em estrutura HTML.\n *\n * Parte do conteúdo das questões é armazenada como texto puro com `\\n`,\n * misturado a tags inline soltas (`<b>`) e LaTeX. Como `\\n` é espaço em branco\n * insignificante em HTML, os parsers colapsam tudo em uma única linha corrida.\n * Esta função restaura a intenção antes da renderização.\n *\n * Conteúdo que já possui blocos é devolvido intacto — reconvertê-lo duplicaria\n * parágrafos e corromperia o que já está correto.\n */\nexport function normalizeLineBreaksInHtml(\n  html: string,\n  options: NormalizeLineBreaksOptions = {}\n): string {\n  if (!html?.includes('\\n')) return html;\n\n  // Content imported from CSV/XLSX arrives with CRLF. Without this the `\\r`\n  // sits between the two `\\n`, so `\\n{2,}` never matches and a paragraph break\n  // degrades into a soft break with a stray `\\r` left in the output.\n  const normalizedHtml = html.replaceAll('\\r\\n', '\\n');\n  if (BLOCK_LEVEL_TAG.test(normalizedHtml)) return normalizedHtml;\n\n  const blocks = normalizedHtml\n    .split(/\\n{2,}/)\n    .map((block) => block.trim())\n    .filter(Boolean);\n\n  if (blocks.length === 0) return normalizedHtml;\n\n  if (options.inline) {\n    // A blank line still reads as a stronger separation than a soft break.\n    return blocks\n      .map((block) => block.replaceAll('\\n', '<br>'))\n      .join('<br><br>');\n  }\n\n  return blocks\n    .map((block) => {\n      // Images are block-level nodes: wrapping one in <p> makes editors lift it\n      // out and leave an empty paragraph behind.\n      if (STANDALONE_IMAGE.test(block)) return block;\n      // A single newline is a soft break inside the same paragraph.\n      return `<p>${block.replaceAll('\\n', '<br>')}</p>`;\n    })\n    .join('');\n}\n"],"mappings":";AAKA,IAAM,kBACJ;AAGF,IAAM,mBAAmB;AAsBlB,SAAS,0BACd,MACA,UAAsC,CAAC,GAC/B;AACR,MAAI,CAAC,MAAM,SAAS,IAAI,EAAG,QAAO;AAKlC,QAAM,iBAAiB,KAAK,WAAW,QAAQ,IAAI;AACnD,MAAI,gBAAgB,KAAK,cAAc,EAAG,QAAO;AAEjD,QAAM,SAAS,eACZ,MAAM,QAAQ,EACd,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAC3B,OAAO,OAAO;AAEjB,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,MAAI,QAAQ,QAAQ;AAElB,WAAO,OACJ,IAAI,CAAC,UAAU,MAAM,WAAW,MAAM,MAAM,CAAC,EAC7C,KAAK,UAAU;AAAA,EACpB;AAEA,SAAO,OACJ,IAAI,CAAC,UAAU;AAGd,QAAI,iBAAiB,KAAK,KAAK,EAAG,QAAO;AAEzC,WAAO,MAAM,MAAM,WAAW,MAAM,MAAM,CAAC;AAAA,EAC7C,CAAC,EACA,KAAK,EAAE;AACZ;","names":[]}