import { cleanText } from './text.js'; // Описание услуги в базе — HTML со старого сайта: абзацы, списки и подзаголовки, // набранные жирным span-ом с двоеточием в конце («Когда нужно срочно к врачу:»). // Разбираем его на секции и дальше рисуем их компонентами макета — сам HTML // в страницу не вставляем, поэтому стили и скрипты из старой вёрстки не протекают. const HEADING_MAX = 90; function capitalize(s) { return s ? s[0].toUpperCase() + s.slice(1) : s; } export function parseBlocks(blocks) { const html = (blocks || []) .map((b) => b?.html || '') .filter(Boolean) .join('\n'); if (!html.trim() || typeof DOMParser === 'undefined') return []; // An explicit body also makes fragment parsing identical in the build-time // DOM implementation and in browsers. const doc = new DOMParser().parseFromString(`${html}`, 'text/html'); const sections = [{ title: '', paragraphs: [], items: [] }]; const current = () => sections[sections.length - 1]; const visit = (node) => { const isElement = node.nodeType === 1; if (isElement && /^(SCRIPT|STYLE|NOSCRIPT)$/.test(node.tagName)) return; if (isElement && (node.tagName === 'UL' || node.tagName === 'OL')) { node.querySelectorAll('li').forEach((li) => { const text = cleanText(li.textContent).replace(/[;.,]+$/, ''); if (text) current().items.push(capitalize(text)); }); return; } // обёртка со списком внутри — разбираем по дочерним узлам if (isElement && node.querySelector('ul, ol, h2, h3, h4, h5, h6')) { node.childNodes.forEach(visit); return; } const text = cleanText(node.textContent); if (!text) return; if (text.length <= HEADING_MAX && text.endsWith(':') && current().title && !current().paragraphs.length && !current().items.length && !(isElement && /^H[2-6]$/.test(node.tagName))) { current().paragraphs.push(text); return; } if ((isElement && /^H[2-6]$/.test(node.tagName)) || (text.length <= HEADING_MAX && text.endsWith(':'))) { sections.push({ title: text.replace(/:$/, '').trim(), paragraphs: [], items: [] }); return; } // текст после списка без нового подзаголовка — отдельная секция, чтобы не склеить порядок if (current().items.length) { sections.push({ title: '', paragraphs: [text], items: [] }); return; } current().paragraphs.push(text); }; doc.body.childNodes.forEach(visit); return sections.filter((s) => s.title || s.paragraphs.length || s.items.length); } export const URGENT_TITLE = /срочн/i;