/
indievid
/
GigaStudio-e019bd12
Обзор
Документация
Войти
/
indievid
/
GigaStudio-e019bd12
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
dev
src/lib/markdown-export.ts
110 строк
6 KB
studio-agent
Squash 'studio-workflow-75590c30-d1f0-4ca2-80c3-dc0ba87c97fc' into dev
25 июл 2026, 13:34
25 июл 2026, 13:34
2a2178c
Код
Авторство
О чём код?
import type { Topic } from "./interview-data"; function formatDateRu(d: Date): string { return d.toLocaleDateString("ru-RU", { year: "numeric", month: "long", day: "2-digit", }); } function extractProductName(topics: Topic[]): string { const first = topics.find((t) => t.id === 1); const raw = first?.rawAnswer?.trim(); if (!raw) return "Новый цифровой продукт"; // Берём только первое предложение/строку, до точки или переноса. const firstLine = raw.split(/\n/)[0]?.trim() ?? ""; const firstSentence = firstLine.split(/[.!?]/)[0]?.trim() ?? ""; // Отбрасываем слово «Пример:» если оно затесалось. const cleaned = firstSentence.replace(/^пример[:\s]*/i, "").trim(); // Берём «название» — первое «слово с заглавной» или просто первые 5 слов. const tokens = cleaned.split(/\s+/).filter(Boolean); if (tokens.length === 0) return "Новый цифровой продукт"; return tokens.slice(0, 6).join(" ").replace(/[«»"]/g, ""); } function composeLockedAnswer(topic: Topic): string { if (topic.lockedAnswer) return topic.lockedAnswer; return ""; } export function buildMarkdown(topics: Topic[]): string { const date = formatDateRu(new Date()); const productName = extractProductName(topics); const lines: string[] = []; lines.push(`# 📄 ТЕХНИЧЕСКОЕ ЗАДАНИЕ (ТЗ) НА РАЗРАБОТКУ ЦИФРОВОГО ПРОДУКТА`); lines.push(""); lines.push(`**Продукт:** ${productName}`); lines.push(`**Подготовлено по методике «Индивид СтуИИя» через ИИ Бизнес-технолога**`); lines.push(`*Дата формирования:* ${date}`); lines.push(""); lines.push("> Документ собран автоматически на основе интервью с заказчиком. Каждый раздел — это отдельная тема (вопрос ИИ + ваши ответы на основной и уточняющие вопросы)."); lines.push(""); lines.push("---"); lines.push(""); for (const topic of topics) { lines.push(`## [${topic.role}] — ${topic.id}. ${topic.title}`); lines.push(""); if (!topic.lockedAnswer && !topic.rawAnswer) { lines.push("_(ответ не зафиксирован)_"); lines.push(""); } else { lines.push(`### Основной ответ`); lines.push(""); lines.push(topic.rawAnswer?.trim() || "_(пусто)_"); lines.push(""); const clarifications = (topic.clarifications ?? []) .map((c) => c.trim()) .filter(Boolean); if (clarifications.length > 0) { lines.push(`### Уточнения`); lines.push(""); for (let i = 0; i < clarifications.length; i++) { const step = topic.steps[i + 1]; const q = step?.question ?? `Уточняющий вопрос №${i + 1}`; lines.push(`- **${q}** — ${clarifications[i]}`); } lines.push(""); } } lines.push("---"); lines.push(""); } lines.push("## 🛠️ СТАНДАРТЫ И РЕКОМЕНДАЦИИ ДЛЯ ИИ-РАЗРАБОТЧИКА (LLM / CURSOR / N8N)"); lines.push(""); lines.push("1. **Clean Code & SOLID.** Соблюдать принципы чистой архитектуры, разделение ответственности и понятные именования на русском языке в пользовательских данных."); lines.push("2. **Безопасность.** Все ключи API и пароли хранить только в серверных переменных окружения, без публикации в клиентском коде и публичных репозиториях."); lines.push("3. **Адаптивность.** 100% корректная работа интерфейса на мобильных устройствах (Android + iOS), проверка на разрешениях от 320 px."); lines.push("4. **Обработка ошибок.** Понятные статусы ответов сервера, валидация всех входящих данных и дружелюбные сообщения пользователю без технических терминов."); lines.push("5. **Производительность.** Время первой загрузки — не более 2 секунд на 4G, ленивая загрузка тяжёлых модулей."); lines.push("6. **Доступность.** Контрастность по WCAG AA, клавиатурная навигация, alt-тексты у изображений."); lines.push(""); lines.push("---"); lines.push(""); lines.push(`_Документ сформирован автоматически помощником «Индивид СтуИИя»._`); lines.push(`_Количество разделов: ${topics.filter((t) => t.lockedAnswer).length} из ${topics.length}._`); return lines.join("\n"); } export function downloadMarkdown( content: string, filename = "TZ-IndividStuIIa.md" ): void { const blob = new Blob([content], { type: "text/markdown;charset=utf-8" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); setTimeout(() => URL.revokeObjectURL(url), 1000); }