"""Default HTML skeletons for ESPD rich-text editors (visible outlines).""" from __future__ import annotations from app.services.espd.models import DocumentType # Placeholder paragraph shown under each heading so the outline is obvious in TipTap. _HINT = "

Заполните раздел…

" def _h2(title: str) -> str: return f"

{title}

{_HINT}" def _h3(title: str) -> str: return f"

{title}

{_HINT}" SKELETONS: dict[str, str] = { DocumentType.RO.value: "\n".join( [ _h2("1. Назначение программы"), _h3("1.1. Функциональное назначение"), _h3("1.2. Эксплуатационное назначение"), _h2("2. Условия выполнения программы"), _h3("2.1. Требования к техническим средствам"), _h3("2.2. Требования к программным средствам"), _h3("2.3. Требования к персоналу"), _h2("3. Установка программы"), _h3("3.1. Состав дистрибутива"), _h3("3.2. Порядок установки"), _h2("4. Работа с программой"), _h3("4.1. Запуск программы"), _h3("4.2. Основные операции"), _h3("4.3. Завершение работы"), _h2("5. Сообщения оператору"), ] ), DocumentType.RP.value: "\n".join( [ _h2("1. Назначение программы"), _h2("2. Условия выполнения программы"), _h2("3. Характеристики программы"), _h2("4. Обращение к программе"), _h2("5. Входные и выходные данные"), _h2("6. Сообщения"), ] ), DocumentType.RSP.value: "\n".join( [ _h2("1. Общие сведения о программе"), _h2("2. Структура программы"), _h2("3. Настройка программы"), _h2("4. Проверка программы"), _h2("5. Дополнительные возможности"), _h2("6. Сообщения системному программисту"), ] ), DocumentType.PMI.value: "\n".join( [ _h2("1. Объект испытаний"), _h2("2. Цель испытаний"), _h2("3. Требования к программе"), _h2("4. Требования к программной документации"), _h2("5. Средства и порядок испытаний"), _h2("6. Методы испытаний"), ] ), DocumentType.TEXT.value: "\n".join( [ _h2("1. Общие сведения"), "

Краткое описание состава текста программы.

", _h2("2. Текст программы"), "
// Вставьте листинг или фрагменты исходного кода…\n
", _h2("3. Примечания"), ] ), DocumentType.IMP.value: "\n".join( [ _h2("1. Перечень исполняемых модулей"), "

Таблица файлов формируется из загруженного ZIP при генерации DOCX. " "Здесь можно указать пояснения к составу поставки.

", _h2("2. Инструкция по установке / размещению"), _h2("3. Проверка контрольных сумм"), "

Контрольная сумма ZIP подставляется автоматически при генерации.

", ] ), } def get_skeleton(doc_type: str | DocumentType) -> str: key = doc_type.value if isinstance(doc_type, DocumentType) else str(doc_type) return SKELETONS.get(key, "") def all_skeletons() -> dict[str, str]: return dict(SKELETONS) def is_blank_html(html: str | None) -> bool: """True if editor content is empty / only whitespace or empty tags.""" if not html or not str(html).strip(): return True import re from html import unescape text = re.sub(r"<[^>]+>", " ", str(html)) text = unescape(text) text = re.sub(r"\s+", " ", text).strip() return text == ""