111 lines
4.6 KiB
Python
111 lines
4.6 KiB
Python
"""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 = "<p><em>Заполните раздел…</em></p>"
|
|
|
|
|
|
def _h2(title: str) -> str:
|
|
return f"<h2>{title}</h2>{_HINT}"
|
|
|
|
|
|
def _h3(title: str) -> str:
|
|
return f"<h3>{title}</h3>{_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. Общие сведения"),
|
|
"<p><em>Краткое описание состава текста программы.</em></p>",
|
|
_h2("2. Текст программы"),
|
|
"<pre><code>// Вставьте листинг или фрагменты исходного кода…\n</code></pre>",
|
|
_h2("3. Примечания"),
|
|
]
|
|
),
|
|
DocumentType.IMP.value: "\n".join(
|
|
[
|
|
_h2("1. Перечень исполняемых модулей"),
|
|
"<p><em>Таблица файлов формируется из загруженного ZIP при генерации DOCX. "
|
|
"Здесь можно указать пояснения к составу поставки.</em></p>",
|
|
_h2("2. Инструкция по установке / размещению"),
|
|
_h2("3. Проверка контрольных сумм"),
|
|
"<p><em>Контрольная сумма ZIP подставляется автоматически при генерации.</em></p>",
|
|
]
|
|
),
|
|
}
|
|
|
|
|
|
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 == ""
|