dana-medical-site/web/src/lib/serviceContent.js
2026-10-14 13:33:13 +00:00

68 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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(`<!doctype html><html><body>${html}</body></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;