@dzhechkov/keysarium 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -3
- package/bin/cli.js +0 -0
- package/package.json +5 -3
- package/templates/.claude/commands/analyst-manual.md +38 -0
- package/templates/.claude/commands/casarium.md +55 -4
- package/templates/.claude/commands/feature-adr.md +8 -0
- package/templates/.claude/rules/trust-tiers.md +5 -0
- package/templates/.claude/shards/feature-adr.shard.md +64 -10
- package/templates/.claude/shards/phase-ai-factory.shard.md +109 -0
- package/templates/.claude/skills/ai-factory-mapper/README.md +90 -0
- package/templates/.claude/skills/ai-factory-mapper/SKILL.md +309 -0
- package/templates/.claude/skills/ai-factory-mapper/assets/report-template.md +123 -0
- package/templates/.claude/skills/ai-factory-mapper/references/catalog.md +230 -0
- package/templates/.claude/skills/ai-factory-mapper/references/coverage-formula.md +219 -0
- package/templates/.claude/skills/ai-factory-mapper/references/decomposition-checklist.md +183 -0
- package/templates/.claude/skills/ai-factory-mapper/references/pattern-library.md +312 -0
- package/templates/.claude/skills/ai-factory-mapper/scripts/build_docx_report.js +423 -0
- package/templates/.claude/skills/analyst-manual-full/SKILL.md +286 -0
- package/templates/.claude/skills/edu-site-generator/SKILL.md +254 -0
- package/templates/.claude/skills/edu-site-generator/examples/sample-course-structure.md +116 -0
- package/templates/.claude/skills/edu-site-generator/modules/00-content-analysis.md +84 -0
- package/templates/.claude/skills/edu-site-generator/modules/01-course-structure.md +75 -0
- package/templates/.claude/skills/edu-site-generator/modules/02-data-generation.md +186 -0
- package/templates/.claude/skills/edu-site-generator/modules/03-scaffold.md +249 -0
- package/templates/.claude/skills/edu-site-generator/modules/04-components.md +130 -0
- package/templates/.claude/skills/edu-site-generator/modules/05-gamification.md +163 -0
- package/templates/.claude/skills/edu-site-generator/modules/06-deploy.md +88 -0
- package/templates/.claude/skills/edu-site-generator/modules/07-verification.md +97 -0
- package/templates/.claude/skills/edu-site-generator/references/component-templates.md +436 -0
- package/templates/.claude/skills/edu-site-generator/references/data-schemas.md +164 -0
- package/templates/.claude/skills/edu-site-generator/references/exercise-catalog.md +110 -0
- package/templates/.claude/skills/edu-site-generator/references/tech-stack.md +69 -0
- package/templates/.claude/skills/feature-adr/SKILL.md +245 -59
- package/templates/.claude/skills/feature-adr/modules/03-adr.md +43 -0
- package/templates/.claude/skills/feature-adr/modules/03.5-ideation-swarm.md +180 -0
- package/templates/.claude/skills/feature-adr/modules/06-implementation-plan.md +56 -7
- package/templates/.claude/skills/feature-adr/modules/08-qe.md +87 -23
- package/templates/.claude/skills/feature-adr/modules/09-fleet-qe.md +305 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/README.md +143 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/brutal-honesty-review.md +240 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/chaos-engineering-resilience.md +163 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/code-goal-planner.md +446 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/enterprise-integration-testing.md +111 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/mutation-testing.md +236 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/performance-testing.md +315 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/qcsd-ideation-swarm.md +126 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/qcsd-production-swarm.md +108 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/qe-coverage-analysis.md +193 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/qe-requirements-validation.md +254 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/regression-testing.md +233 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/risk-based-testing.md +212 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/security-testing.md +311 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/shift-left-testing.md +231 -0
- package/templates/.claude/skills/feature-adr/references/agentic-qe/tdd-london-chicago.md +249 -0
- package/templates/.claude/skills/transcript-site-generator/SKILL.md +287 -0
- package/templates/.claude/skills/transcript-site-generator/examples/sample-text-only-site.md +123 -0
- package/templates/.claude/skills/transcript-site-generator/examples/sample-transcript-site.md +134 -0
- package/templates/.claude/skills/transcript-site-generator/modules/00-input-analysis.md +132 -0
- package/templates/.claude/skills/transcript-site-generator/modules/01-content-parsing.md +117 -0
- package/templates/.claude/skills/transcript-site-generator/modules/02-site-generation.md +293 -0
- package/templates/.claude/skills/transcript-site-generator/modules/03-interactivity.md +406 -0
- package/templates/.claude/skills/transcript-site-generator/modules/04-deploy.md +130 -0
- package/templates/.claude/skills/transcript-site-generator/modules/05-verification.md +155 -0
- package/templates/.claude/skills/transcript-site-generator/references/component-catalog.md +86 -0
- package/templates/.claude/skills/transcript-site-generator/references/data-schemas.md +123 -0
- package/templates/.claude/skills/transcript-site-generator/references/tech-stack.md +132 -0
- package/templates/CLAUDE.md +9 -2
- package/templates/docs/edu-site-generator/01-deployment-guide.md +911 -0
- package/templates/docs/edu-site-generator/02-admin-guide.md +901 -0
- package/templates/docs/edu-site-generator/03-user-guide.md +1008 -0
- package/templates/docs/edu-site-generator/04-infrastructure-requirements.md +489 -0
- package/templates/docs/edu-site-generator/05-architecture.md +902 -0
- package/templates/docs/edu-site-generator/06-user-flows.md +759 -0
- package/templates/docs/transcript-site-generator/01-deployment-guide.md +1042 -0
- package/templates/docs/transcript-site-generator/02-admin-guide.md +918 -0
- package/templates/docs/transcript-site-generator/03-user-guide.md +925 -0
- package/templates/docs/transcript-site-generator/04-infrastructure-requirements.md +482 -0
- package/templates/docs/transcript-site-generator/05-architecture.md +1068 -0
- package/templates/docs/transcript-site-generator/06-user-flows.md +855 -0
|
@@ -0,0 +1,855 @@
|
|
|
1
|
+
# Пользовательские потоки @dzhechkov/skills-transcript-site
|
|
2
|
+
|
|
3
|
+
## Содержание
|
|
4
|
+
|
|
5
|
+
1. [Flow: Полный пайплайн (6 шагов)](#1-flow-полный-пайплайн-6-шагов)
|
|
6
|
+
2. [Flow: YouTube URL](#2-flow-youtube-url)
|
|
7
|
+
3. [Flow: Text-only](#3-flow-text-only)
|
|
8
|
+
4. [Flow: Search](#4-flow-search)
|
|
9
|
+
5. [Flow: Dark Mode](#5-flow-dark-mode)
|
|
10
|
+
6. [Flow: TOC Scroll-Spy](#6-flow-toc-scroll-spy)
|
|
11
|
+
7. [Flow: Copy Quote](#7-flow-copy-quote)
|
|
12
|
+
8. [Flow: Mobile Navigation](#8-flow-mobile-navigation)
|
|
13
|
+
9. [Flow: YouTube Timestamp Sync](#9-flow-youtube-timestamp-sync)
|
|
14
|
+
10. [Flow: GitHub Pages Deployment](#10-flow-github-pages-deployment)
|
|
15
|
+
11. [Flow: Error Handling](#11-flow-error-handling)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 1. Flow: Полный пайплайн (6 шагов)
|
|
20
|
+
|
|
21
|
+
### Sequence Diagram
|
|
22
|
+
|
|
23
|
+
```mermaid
|
|
24
|
+
sequenceDiagram
|
|
25
|
+
actor U as Пользователь
|
|
26
|
+
participant C as Claude (/transcript-site)
|
|
27
|
+
participant YT as yt-dlp
|
|
28
|
+
participant FS as File System
|
|
29
|
+
|
|
30
|
+
U->>C: /transcript-site [source]
|
|
31
|
+
|
|
32
|
+
Note over C: === Шаг 1: INPUT ANALYSIS ===
|
|
33
|
+
|
|
34
|
+
alt YouTube URL
|
|
35
|
+
C->>YT: yt-dlp --dump-json [URL]
|
|
36
|
+
YT-->>C: Метаданные (title, duration, channel, date)
|
|
37
|
+
C->>YT: yt-dlp --write-auto-sub [URL]
|
|
38
|
+
YT-->>C: Субтитры (VTT/SRT)
|
|
39
|
+
else Текст или файл
|
|
40
|
+
C->>FS: Прочитать входные данные
|
|
41
|
+
FS-->>C: Сырой текст
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
C->>C: Language detection
|
|
45
|
+
C-->>U: Checkpoint 1/6: Input Analysis Complete
|
|
46
|
+
|
|
47
|
+
U->>C: "ok"
|
|
48
|
+
|
|
49
|
+
Note over C: === Шаг 2: CONTENT PARSING ===
|
|
50
|
+
|
|
51
|
+
C->>C: Разбиение на секции
|
|
52
|
+
C->>C: Определение спикеров
|
|
53
|
+
C->>C: Маппинг временных меток
|
|
54
|
+
C->>C: Извлечение ключевых цитат
|
|
55
|
+
C-->>U: Checkpoint 2/6: Content Parsing Complete<br/>Sections: N, Speakers: M
|
|
56
|
+
|
|
57
|
+
U->>C: "ok"
|
|
58
|
+
|
|
59
|
+
Note over C: === Шаг 3: SITE GENERATION ===
|
|
60
|
+
|
|
61
|
+
C->>C: Загрузить references/html-template.md
|
|
62
|
+
C->>C: Загрузить references/tailwind-config.md
|
|
63
|
+
C->>C: Загрузить references/seo-checklist.md
|
|
64
|
+
C->>C: Генерация HTML структуры
|
|
65
|
+
C->>C: Добавление SEO мета-тегов
|
|
66
|
+
C->>FS: Записать docs/index.html
|
|
67
|
+
C-->>U: Checkpoint 3/6: Site Generation Complete
|
|
68
|
+
|
|
69
|
+
U->>C: "ok"
|
|
70
|
+
|
|
71
|
+
Note over C: === Шаг 4: INTERACTIVITY ===
|
|
72
|
+
|
|
73
|
+
C->>C: Добавить Search (Ctrl+K)
|
|
74
|
+
C->>C: Добавить Dark Mode
|
|
75
|
+
C->>C: Добавить TOC scroll-spy
|
|
76
|
+
C->>C: Добавить YouTube sync (если YouTube)
|
|
77
|
+
C->>C: Добавить Copy quote buttons
|
|
78
|
+
C->>C: Добавить Back-to-top
|
|
79
|
+
C->>C: Добавить Progress bar
|
|
80
|
+
C->>C: Добавить Reading stats
|
|
81
|
+
C->>FS: Обновить docs/index.html
|
|
82
|
+
C-->>U: Checkpoint 4/6: Interactivity Complete
|
|
83
|
+
|
|
84
|
+
U->>C: "ok"
|
|
85
|
+
|
|
86
|
+
Note over C: === Шаг 5: DEPLOY ===
|
|
87
|
+
|
|
88
|
+
C->>FS: Записать docs/robots.txt
|
|
89
|
+
C->>FS: Записать docs/sitemap.xml
|
|
90
|
+
C-->>U: Checkpoint 5/6: Deploy Config Complete
|
|
91
|
+
|
|
92
|
+
U->>C: "ok"
|
|
93
|
+
|
|
94
|
+
Note over C: === Шаг 6: VERIFICATION ===
|
|
95
|
+
|
|
96
|
+
C->>FS: Прочитать docs/index.html
|
|
97
|
+
C->>C: HTML checks (8)
|
|
98
|
+
C->>C: JS checks (6)
|
|
99
|
+
C->>C: CSS checks (4)
|
|
100
|
+
C->>C: SEO checks (5)
|
|
101
|
+
C->>C: A11y checks (5)
|
|
102
|
+
C->>C: Security checks (4)
|
|
103
|
+
C->>C: Performance checks (3)
|
|
104
|
+
C-->>U: Verification: 35/35 passed
|
|
105
|
+
|
|
106
|
+
C-->>U: PIPELINE COMPLETE<br/>Output: docs/index.html
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Flowchart с точками принятия решений
|
|
110
|
+
|
|
111
|
+
```mermaid
|
|
112
|
+
flowchart TD
|
|
113
|
+
START(["/transcript-site [source]"]) --> DETECT{"Тип<br/>источника?"}
|
|
114
|
+
|
|
115
|
+
DETECT -->|"YouTube URL"| YTDLP["yt-dlp extraction"]
|
|
116
|
+
DETECT -->|"Файл"| FREAD["Чтение файла"]
|
|
117
|
+
DETECT -->|"Текст"| TREAD["Чтение ввода"]
|
|
118
|
+
DETECT -->|"URL + text"| COMBINED["YouTube meta +<br/>текстовый контент"]
|
|
119
|
+
|
|
120
|
+
YTDLP --> HAS_SUBS{"Есть<br/>субтитры?"}
|
|
121
|
+
HAS_SUBS -->|"Да"| LANG["Language Detection"]
|
|
122
|
+
HAS_SUBS -->|"Нет"| MANUAL["Запросить текст<br/>у пользователя"]
|
|
123
|
+
MANUAL --> LANG
|
|
124
|
+
|
|
125
|
+
FREAD --> LANG
|
|
126
|
+
TREAD --> LANG
|
|
127
|
+
COMBINED --> LANG
|
|
128
|
+
|
|
129
|
+
LANG --> CP1["Checkpoint 1/6"]
|
|
130
|
+
CP1 --> PARSE["Content Parsing:<br/>Секции + Спикеры +<br/>Timestamps + Цитаты"]
|
|
131
|
+
|
|
132
|
+
PARSE --> CP2["Checkpoint 2/6"]
|
|
133
|
+
CP2 --> EMBED{"YouTube<br/>источник?"}
|
|
134
|
+
|
|
135
|
+
EMBED -->|"Да"| GEN_YT["Генерация HTML<br/>с YouTube embed"]
|
|
136
|
+
EMBED -->|"Нет"| GEN_TEXT["Генерация HTML<br/>без embed"]
|
|
137
|
+
|
|
138
|
+
GEN_YT --> CP3["Checkpoint 3/6"]
|
|
139
|
+
GEN_TEXT --> CP3
|
|
140
|
+
|
|
141
|
+
CP3 --> FEATURES["Добавление фич:<br/>Search, Dark Mode, TOC,<br/>Copy, Back-to-top,<br/>Progress, Stats"]
|
|
142
|
+
|
|
143
|
+
FEATURES --> HAS_YT{"YouTube<br/>embed?"}
|
|
144
|
+
HAS_YT -->|"Да"| ADD_SYNC["+ YouTube Sync<br/>(seekTo)"]
|
|
145
|
+
HAS_YT -->|"Нет"| CP4
|
|
146
|
+
|
|
147
|
+
ADD_SYNC --> CP4["Checkpoint 4/6"]
|
|
148
|
+
|
|
149
|
+
CP4 --> DEPLOY["Генерация:<br/>robots.txt + sitemap.xml"]
|
|
150
|
+
DEPLOY --> CP5["Checkpoint 5/6"]
|
|
151
|
+
|
|
152
|
+
CP5 --> VERIFY["Verification:<br/>35 checks"]
|
|
153
|
+
VERIFY --> PASS{"Все<br/>прошли?"}
|
|
154
|
+
|
|
155
|
+
PASS -->|"Да"| DONE(["PIPELINE COMPLETE<br/>docs/index.html"])
|
|
156
|
+
PASS -->|"Нет"| FIX["Отчёт ошибок +<br/>рекомендации"]
|
|
157
|
+
FIX --> VERIFY
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 2. Flow: YouTube URL
|
|
163
|
+
|
|
164
|
+
### Sequence Diagram
|
|
165
|
+
|
|
166
|
+
```mermaid
|
|
167
|
+
sequenceDiagram
|
|
168
|
+
actor U as Пользователь
|
|
169
|
+
participant C as Claude
|
|
170
|
+
participant YT as yt-dlp
|
|
171
|
+
participant API as YouTube API
|
|
172
|
+
|
|
173
|
+
U->>C: /transcript-site https://youtube.com/watch?v=VIDEO_ID
|
|
174
|
+
|
|
175
|
+
C->>C: Определить: YouTube URL<br/>Извлечь VIDEO_ID
|
|
176
|
+
|
|
177
|
+
Note over C,YT: Извлечение метаданных
|
|
178
|
+
|
|
179
|
+
C->>YT: yt-dlp --dump-json --no-download URL
|
|
180
|
+
YT->>API: HTTP GET (video info)
|
|
181
|
+
API-->>YT: JSON metadata
|
|
182
|
+
YT-->>C: {title, duration, channel,<br/>upload_date, thumbnail_url}
|
|
183
|
+
|
|
184
|
+
Note over C,YT: Извлечение субтитров
|
|
185
|
+
|
|
186
|
+
C->>YT: yt-dlp --write-auto-sub --sub-lang en,ru<br/>--sub-format vtt --skip-download URL
|
|
187
|
+
YT->>API: HTTP GET (subtitles)
|
|
188
|
+
API-->>YT: VTT subtitles
|
|
189
|
+
YT-->>C: transcript.vtt
|
|
190
|
+
|
|
191
|
+
Note over C: Парсинг VTT
|
|
192
|
+
|
|
193
|
+
C->>C: Удалить дубли строк<br/>(YouTube auto-subs часто дублируют)
|
|
194
|
+
C->>C: Нормализовать timestamps<br/>(HH:MM:SS.mmm -> секунды)
|
|
195
|
+
C->>C: Объединить фрагменты<br/>(каждые 3-5 сек -> одно предложение)
|
|
196
|
+
|
|
197
|
+
C-->>U: Метаданные извлечены:<br/>Title: "...", Duration: MM:SS<br/>Language: en, Words: N
|
|
198
|
+
|
|
199
|
+
Note over C: Генерация HTML с embed
|
|
200
|
+
|
|
201
|
+
C->>C: Создать iframe:<br/>src=youtube.com/embed/VIDEO_ID<br/>?enablejsapi=1&origin=...
|
|
202
|
+
|
|
203
|
+
C->>C: Добавить data-seek атрибуты<br/>на все timestamp links
|
|
204
|
+
|
|
205
|
+
C->>C: Добавить YouTube API JS:<br/>- YT.Player initialization<br/>- seekTo() handler<br/>- postMessage origin check
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Обработка edge cases
|
|
209
|
+
|
|
210
|
+
```mermaid
|
|
211
|
+
flowchart TD
|
|
212
|
+
URL["YouTube URL"] --> VALID{"URL<br/>валидный?"}
|
|
213
|
+
VALID -->|"Нет"| ERR_URL["Ошибка: невалидный URL<br/>Предложить проверить формат"]
|
|
214
|
+
VALID -->|"Да"| YTDLP_RUN["yt-dlp extraction"]
|
|
215
|
+
|
|
216
|
+
YTDLP_RUN --> YTDLP_OK{"yt-dlp<br/>установлен?"}
|
|
217
|
+
YTDLP_OK -->|"Нет"| ERR_YTDLP["Ошибка: yt-dlp not found<br/>Предложить: pip install yt-dlp<br/>Или вставить текст вручную"]
|
|
218
|
+
YTDLP_OK -->|"Да"| EXTRACT["Извлечение"]
|
|
219
|
+
|
|
220
|
+
EXTRACT --> SUBS_OK{"Субтитры<br/>найдены?"}
|
|
221
|
+
SUBS_OK -->|"Нет"| NO_SUBS["Субтитры не найдены.<br/>Запросить текст вручную."]
|
|
222
|
+
SUBS_OK -->|"Да"| QUALITY{"Качество<br/>субтитров?"}
|
|
223
|
+
|
|
224
|
+
QUALITY -->|"Авто-генерированные"| WARN["Предупреждение:<br/>авто-субтитры могут<br/>содержать ошибки"]
|
|
225
|
+
QUALITY -->|"Ручные"| GOOD["Ручные субтитры:<br/>высокое качество"]
|
|
226
|
+
|
|
227
|
+
NO_SUBS --> MANUAL["Пользователь вставляет<br/>текст вручную"]
|
|
228
|
+
WARN --> CONTINUE["Продолжить с<br/>авто-субтитрами"]
|
|
229
|
+
GOOD --> CONTINUE
|
|
230
|
+
MANUAL --> CONTINUE
|
|
231
|
+
|
|
232
|
+
CONTINUE --> PARSE["Content Parsing"]
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## 3. Flow: Text-only
|
|
238
|
+
|
|
239
|
+
### Flowchart
|
|
240
|
+
|
|
241
|
+
```mermaid
|
|
242
|
+
flowchart TD
|
|
243
|
+
START(["/transcript-site [text or file]"]) --> TYPE{"Тип<br/>ввода?"}
|
|
244
|
+
|
|
245
|
+
TYPE -->|"Путь к файлу"| READ_FILE["Прочитать файл"]
|
|
246
|
+
TYPE -->|"Текст в чате"| READ_TEXT["Прочитать текст из чата"]
|
|
247
|
+
|
|
248
|
+
READ_FILE --> FORMAT{"Формат<br/>файла?"}
|
|
249
|
+
READ_TEXT --> FORMAT
|
|
250
|
+
|
|
251
|
+
FORMAT -->|".txt"| PLAIN["Plain text"]
|
|
252
|
+
FORMAT -->|".srt"| SRT["SRT subtitles"]
|
|
253
|
+
FORMAT -->|".vtt"| VTT["VTT subtitles"]
|
|
254
|
+
FORMAT -->|".md"| MD["Markdown"]
|
|
255
|
+
FORMAT -->|"auto-detect"| AUTO["Автоопределение<br/>по содержимому"]
|
|
256
|
+
|
|
257
|
+
PLAIN --> NORMALIZE["Нормализация"]
|
|
258
|
+
SRT --> SRT_PARSE["Парсинг SRT:<br/>номер, timestamps, текст"]
|
|
259
|
+
VTT --> VTT_PARSE["Парсинг VTT:<br/>timestamps, текст, voice tags"]
|
|
260
|
+
MD --> MD_PARSE["Парсинг Markdown:<br/>заголовки = секции"]
|
|
261
|
+
AUTO --> NORMALIZE
|
|
262
|
+
|
|
263
|
+
SRT_PARSE --> NORMALIZE
|
|
264
|
+
VTT_PARSE --> NORMALIZE
|
|
265
|
+
MD_PARSE --> NORMALIZE
|
|
266
|
+
|
|
267
|
+
NORMALIZE --> LANG["Language Detection"]
|
|
268
|
+
LANG --> SECTIONS["Разбиение на секции"]
|
|
269
|
+
SECTIONS --> SPEAKERS["Определение спикеров"]
|
|
270
|
+
SPEAKERS --> GEN["Генерация HTML<br/>(без YouTube embed)"]
|
|
271
|
+
|
|
272
|
+
GEN --> FEATURES["Добавление фич:<br/>Search, Dark Mode, TOC,<br/>Copy, Back-to-top,<br/>Progress, Stats<br/>(БЕЗ YouTube sync)"]
|
|
273
|
+
|
|
274
|
+
FEATURES --> OUTPUT(["docs/index.html<br/>(text-only site)"])
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Отличия от YouTube flow
|
|
278
|
+
|
|
279
|
+
| Компонент | YouTube flow | Text-only flow |
|
|
280
|
+
|-----------|-------------|----------------|
|
|
281
|
+
| YouTube embed | Да (iframe) | Нет |
|
|
282
|
+
| Timestamp links | Кликабельные (seekTo) | Текстовые метки (нет seekTo) |
|
|
283
|
+
| YouTube sync JS | Да | Нет |
|
|
284
|
+
| postMessage handler | Да | Нет |
|
|
285
|
+
| og:type | video | article |
|
|
286
|
+
| JSON-LD | VideoObject | Article |
|
|
287
|
+
| Thumbnail | YouTube maxresdefault | Placeholder или пользовательское |
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## 4. Flow: Search
|
|
292
|
+
|
|
293
|
+
### Sequence Diagram
|
|
294
|
+
|
|
295
|
+
```mermaid
|
|
296
|
+
sequenceDiagram
|
|
297
|
+
actor U as Пользователь
|
|
298
|
+
participant K as Keyboard
|
|
299
|
+
participant M as Search Modal
|
|
300
|
+
participant S as performSearch()
|
|
301
|
+
participant DOM as DOM
|
|
302
|
+
|
|
303
|
+
U->>K: Ctrl+K (или Cmd+K)
|
|
304
|
+
K->>M: Открыть modal<br/>(display: flex)
|
|
305
|
+
M->>M: Focus на input поле
|
|
306
|
+
|
|
307
|
+
U->>M: Ввод "machine learning"
|
|
308
|
+
|
|
309
|
+
Note over M,S: Debounce: 300ms
|
|
310
|
+
|
|
311
|
+
M->>M: Запустить таймер 300ms
|
|
312
|
+
U->>M: Ввод "s" (ещё символ)
|
|
313
|
+
M->>M: Сбросить таймер, начать заново
|
|
314
|
+
|
|
315
|
+
Note over M,S: 300ms прошло без новых символов
|
|
316
|
+
|
|
317
|
+
M->>S: performSearch("machine learnings")
|
|
318
|
+
|
|
319
|
+
S->>S: Проверка: length >= 2
|
|
320
|
+
S->>S: escapeRegex("machine learnings")
|
|
321
|
+
S->>S: regex = new RegExp(escaped, 'gi')
|
|
322
|
+
|
|
323
|
+
S->>DOM: Удалить все существующие <mark>
|
|
324
|
+
S->>DOM: Найти все .transcript-text элементы
|
|
325
|
+
S->>DOM: textContent.match(regex)
|
|
326
|
+
|
|
327
|
+
loop Для каждого совпадения (max 50)
|
|
328
|
+
S->>DOM: Обернуть в <mark class="bg-yellow-200<br/>dark:bg-yellow-800">
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
S->>M: Обновить счётчик: "Найдено: 12"
|
|
332
|
+
S->>DOM: scrollIntoView(первый <mark>)
|
|
333
|
+
S->>DOM: Добавить ring на текущий <mark>
|
|
334
|
+
|
|
335
|
+
U->>K: Enter
|
|
336
|
+
K->>S: navigateToNext()
|
|
337
|
+
S->>DOM: scrollIntoView(следующий <mark>)
|
|
338
|
+
S->>DOM: Переместить ring
|
|
339
|
+
|
|
340
|
+
U->>K: Shift+Enter
|
|
341
|
+
K->>S: navigateToPrev()
|
|
342
|
+
S->>DOM: scrollIntoView(предыдущий <mark>)
|
|
343
|
+
|
|
344
|
+
U->>K: Escape
|
|
345
|
+
K->>DOM: Удалить все <mark>
|
|
346
|
+
K->>M: Скрыть modal (display: none)
|
|
347
|
+
K->>M: Очистить input
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Flowchart обработки поиска
|
|
351
|
+
|
|
352
|
+
```mermaid
|
|
353
|
+
flowchart TD
|
|
354
|
+
INPUT["Ввод в search input"] --> CHECK_LEN{"Длина >= 2<br/>символов?"}
|
|
355
|
+
|
|
356
|
+
CHECK_LEN -->|"Нет"| CLEAR["Удалить все <mark><br/>Сбросить счётчик"]
|
|
357
|
+
CHECK_LEN -->|"Да"| DEBOUNCE["Debounce 300ms"]
|
|
358
|
+
|
|
359
|
+
DEBOUNCE --> ESCAPE_REGEX["escapeRegex(query)"]
|
|
360
|
+
ESCAPE_REGEX --> CREATE_REGEX["new RegExp(escaped, 'gi')"]
|
|
361
|
+
|
|
362
|
+
CREATE_REGEX --> CLEAR_OLD["Удалить старые <mark>"]
|
|
363
|
+
CLEAR_OLD --> FIND["Найти совпадения<br/>в .transcript-text"]
|
|
364
|
+
|
|
365
|
+
FIND --> COUNT{"Количество<br/>совпадений?"}
|
|
366
|
+
|
|
367
|
+
COUNT -->|"0"| NO_RESULTS["Показать: Ничего не найдено"]
|
|
368
|
+
COUNT -->|"1-50"| HIGHLIGHT["Обернуть в <mark>"]
|
|
369
|
+
COUNT -->|"> 50"| LIMIT["Обернуть первые 50<br/>Показать: 50+ найдено"]
|
|
370
|
+
|
|
371
|
+
HIGHLIGHT --> SCROLL["scrollIntoView<br/>первого результата"]
|
|
372
|
+
LIMIT --> SCROLL
|
|
373
|
+
|
|
374
|
+
SCROLL --> COUNTER["Обновить счётчик:<br/>Найдено: N"]
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## 5. Flow: Dark Mode
|
|
380
|
+
|
|
381
|
+
### Flowchart
|
|
382
|
+
|
|
383
|
+
```mermaid
|
|
384
|
+
flowchart TD
|
|
385
|
+
PAGE_LOAD["Загрузка страницы"] --> CHECK_LS{"localStorage<br/>theme?"}
|
|
386
|
+
|
|
387
|
+
CHECK_LS -->|"'dark'"| SET_DARK["document.documentElement<br/>.classList.add('dark')"]
|
|
388
|
+
CHECK_LS -->|"'light'"| SET_LIGHT["Оставить без dark class"]
|
|
389
|
+
CHECK_LS -->|"не установлен"| CHECK_SYSTEM{"System prefers<br/>dark?"}
|
|
390
|
+
|
|
391
|
+
CHECK_SYSTEM -->|"Да"| SET_DARK
|
|
392
|
+
CHECK_SYSTEM -->|"Нет"| SET_LIGHT
|
|
393
|
+
|
|
394
|
+
SET_DARK --> SHOW_SUN["Показать иконку солнца<br/>(переключить на light)"]
|
|
395
|
+
SET_LIGHT --> SHOW_MOON["Показать иконку луны<br/>(переключить на dark)"]
|
|
396
|
+
|
|
397
|
+
SHOW_SUN --> READY["Страница готова"]
|
|
398
|
+
SHOW_MOON --> READY
|
|
399
|
+
|
|
400
|
+
READY --> CLICK["Клик на toggle button"]
|
|
401
|
+
|
|
402
|
+
CLICK --> TOGGLE["classList.toggle('dark')"]
|
|
403
|
+
TOGGLE --> IS_DARK{"classList<br/>contains<br/>'dark'?"}
|
|
404
|
+
|
|
405
|
+
IS_DARK -->|"Да"| STORE_DARK["localStorage.setItem<br/>('theme', 'dark')"]
|
|
406
|
+
IS_DARK -->|"Нет"| STORE_LIGHT["localStorage.setItem<br/>('theme', 'light')"]
|
|
407
|
+
|
|
408
|
+
STORE_DARK --> UPDATE_ICON["Показать солнце"]
|
|
409
|
+
STORE_LIGHT --> UPDATE_ICON_2["Показать луну"]
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Sequence Diagram
|
|
413
|
+
|
|
414
|
+
```mermaid
|
|
415
|
+
sequenceDiagram
|
|
416
|
+
participant B as Браузер
|
|
417
|
+
participant LS as localStorage
|
|
418
|
+
participant DOM as DOM
|
|
419
|
+
participant CSS as Tailwind CSS
|
|
420
|
+
|
|
421
|
+
Note over B: Загрузка страницы
|
|
422
|
+
|
|
423
|
+
B->>LS: getItem('theme')
|
|
424
|
+
LS-->>B: 'dark' / 'light' / null
|
|
425
|
+
|
|
426
|
+
alt theme === 'dark'
|
|
427
|
+
B->>DOM: html.classList.add('dark')
|
|
428
|
+
else theme === null
|
|
429
|
+
B->>B: matchMedia('(prefers-color-scheme: dark)')
|
|
430
|
+
alt System dark mode
|
|
431
|
+
B->>DOM: html.classList.add('dark')
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
DOM->>CSS: Применить dark: утилиты<br/>bg-white -> bg-gray-900<br/>text-gray-900 -> text-gray-100
|
|
436
|
+
|
|
437
|
+
Note over B: Пользователь нажимает toggle
|
|
438
|
+
|
|
439
|
+
B->>DOM: html.classList.toggle('dark')
|
|
440
|
+
DOM->>CSS: Мгновенно переключить стили
|
|
441
|
+
B->>LS: setItem('theme', 'dark' | 'light')
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## 6. Flow: TOC Scroll-Spy
|
|
447
|
+
|
|
448
|
+
### Sequence Diagram
|
|
449
|
+
|
|
450
|
+
```mermaid
|
|
451
|
+
sequenceDiagram
|
|
452
|
+
participant IO as IntersectionObserver
|
|
453
|
+
participant SEC as Section Elements
|
|
454
|
+
participant TOC as TOC Links
|
|
455
|
+
participant U as Пользователь
|
|
456
|
+
|
|
457
|
+
Note over IO: Инициализация при загрузке
|
|
458
|
+
|
|
459
|
+
IO->>SEC: observer.observe(section-01)
|
|
460
|
+
IO->>SEC: observer.observe(section-02)
|
|
461
|
+
IO->>SEC: observer.observe(section-03)
|
|
462
|
+
IO->>SEC: ...
|
|
463
|
+
|
|
464
|
+
Note over U: Пользователь скроллит
|
|
465
|
+
|
|
466
|
+
U->>SEC: scroll -> section-02 enters viewport
|
|
467
|
+
|
|
468
|
+
SEC->>IO: IntersectionObserver callback<br/>entry.isIntersecting = true<br/>entry.target.id = "section-02"
|
|
469
|
+
|
|
470
|
+
IO->>TOC: Убрать подсветку со всех links
|
|
471
|
+
IO->>TOC: Найти [data-section="section-02"]
|
|
472
|
+
IO->>TOC: Добавить: bg-primary-100, font-bold
|
|
473
|
+
|
|
474
|
+
Note over U: Скролл продолжается
|
|
475
|
+
|
|
476
|
+
U->>SEC: scroll -> section-03 enters viewport
|
|
477
|
+
|
|
478
|
+
SEC->>IO: callback: section-03 isIntersecting
|
|
479
|
+
|
|
480
|
+
IO->>TOC: Убрать подсветку со всех
|
|
481
|
+
IO->>TOC: Подсветить section-03
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
### Flowchart
|
|
485
|
+
|
|
486
|
+
```mermaid
|
|
487
|
+
flowchart TD
|
|
488
|
+
INIT["Инициализация<br/>IntersectionObserver"] --> CONFIG["Конфигурация:<br/>rootMargin: -20% 0px -70% 0px<br/>threshold: 0"]
|
|
489
|
+
|
|
490
|
+
CONFIG --> OBSERVE["Observe все section[id]"]
|
|
491
|
+
OBSERVE --> SCROLL["Пользователь скроллит"]
|
|
492
|
+
|
|
493
|
+
SCROLL --> CALLBACK["Observer callback"]
|
|
494
|
+
CALLBACK --> IS_INTERSECTING{"entry<br/>isIntersecting?"}
|
|
495
|
+
|
|
496
|
+
IS_INTERSECTING -->|"Нет"| IGNORE["Игнорировать"]
|
|
497
|
+
IS_INTERSECTING -->|"Да"| REMOVE_ALL["Убрать подсветку<br/>со всех TOC links"]
|
|
498
|
+
|
|
499
|
+
REMOVE_ALL --> FIND_LINK["Найти TOC link<br/>с data-section = entry.target.id"]
|
|
500
|
+
|
|
501
|
+
FIND_LINK --> HIGHLIGHT["Добавить классы:<br/>bg-primary-100<br/>dark:bg-primary-900<br/>font-bold"]
|
|
502
|
+
|
|
503
|
+
HIGHLIGHT --> SCROLL_TOC["Если TOC scrollable:<br/>scrollIntoView(link)"]
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
---
|
|
507
|
+
|
|
508
|
+
## 7. Flow: Copy Quote
|
|
509
|
+
|
|
510
|
+
### Sequence Diagram
|
|
511
|
+
|
|
512
|
+
```mermaid
|
|
513
|
+
sequenceDiagram
|
|
514
|
+
actor U as Пользователь
|
|
515
|
+
participant BTN as Copy Button
|
|
516
|
+
participant CB as Clipboard API
|
|
517
|
+
participant FB as Feedback
|
|
518
|
+
|
|
519
|
+
U->>BTN: Клик на кнопку копирования
|
|
520
|
+
|
|
521
|
+
Note over BTN: Event delegation:<br/>e.target.closest('[data-copy]')
|
|
522
|
+
|
|
523
|
+
BTN->>BTN: text = dataset.copy
|
|
524
|
+
BTN->>CB: navigator.clipboard.writeText(text)
|
|
525
|
+
|
|
526
|
+
alt Clipboard API доступен
|
|
527
|
+
CB-->>BTN: Promise resolved
|
|
528
|
+
BTN->>FB: Сменить текст кнопки:<br/>"Копировать" -> "Скопировано!"
|
|
529
|
+
FB->>FB: setTimeout(2000ms)
|
|
530
|
+
FB->>BTN: Вернуть текст:<br/>"Скопировано!" -> "Копировать"
|
|
531
|
+
else Clipboard API недоступен (HTTP)
|
|
532
|
+
BTN->>BTN: Fallback: document.execCommand('copy')
|
|
533
|
+
Note over BTN: Создать textarea,<br/>select, execCommand, remove
|
|
534
|
+
BTN->>FB: Сменить текст кнопки
|
|
535
|
+
end
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
### Flowchart
|
|
539
|
+
|
|
540
|
+
```mermaid
|
|
541
|
+
flowchart TD
|
|
542
|
+
CLICK["Клик на [data-copy]"] --> GET_TEXT["text = dataset.copy"]
|
|
543
|
+
GET_TEXT --> CHECK_API{"navigator.clipboard<br/>доступен?"}
|
|
544
|
+
|
|
545
|
+
CHECK_API -->|"Да"| CLIPBOARD["clipboard.writeText(text)"]
|
|
546
|
+
CHECK_API -->|"Нет"| FALLBACK["Fallback:<br/>textarea + execCommand"]
|
|
547
|
+
|
|
548
|
+
CLIPBOARD --> SUCCESS["Успех"]
|
|
549
|
+
FALLBACK --> SUCCESS
|
|
550
|
+
|
|
551
|
+
SUCCESS --> FEEDBACK["Сменить текст кнопки<br/>на 'Скопировано!'"]
|
|
552
|
+
FEEDBACK --> TIMEOUT["setTimeout 2000ms"]
|
|
553
|
+
TIMEOUT --> RESTORE["Восстановить<br/>исходный текст кнопки"]
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
## 8. Flow: Mobile Navigation
|
|
559
|
+
|
|
560
|
+
### Flowchart
|
|
561
|
+
|
|
562
|
+
```mermaid
|
|
563
|
+
flowchart TD
|
|
564
|
+
LOAD["Загрузка на мобильном<br/>(viewport < 768px)"] --> HIDE_ASIDE["aside: hidden<br/>(transform: translateX(-100%))"]
|
|
565
|
+
|
|
566
|
+
HIDE_ASIDE --> SHOW_HAMBURGER["Показать кнопку<br/>hamburger в nav"]
|
|
567
|
+
|
|
568
|
+
SHOW_HAMBURGER --> CLICK_HAMBURGER["Клик на hamburger"]
|
|
569
|
+
CLICK_HAMBURGER --> OPEN_DRAWER["aside: transform translateX(0)<br/>+ overlay backdrop"]
|
|
570
|
+
|
|
571
|
+
OPEN_DRAWER --> USER_CHOICE{"Действие<br/>пользователя?"}
|
|
572
|
+
|
|
573
|
+
USER_CHOICE -->|"Клик на секцию<br/>в TOC"| SCROLL_SECTION["scrollIntoView(section)<br/>Закрыть drawer"]
|
|
574
|
+
USER_CHOICE -->|"Клик на overlay"| CLOSE_DRAWER["Закрыть drawer:<br/>translateX(-100%)<br/>Убрать overlay"]
|
|
575
|
+
USER_CHOICE -->|"Escape"| CLOSE_DRAWER
|
|
576
|
+
|
|
577
|
+
SCROLL_SECTION --> HIDE_ASIDE
|
|
578
|
+
CLOSE_DRAWER --> HIDE_ASIDE
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### Sequence Diagram
|
|
582
|
+
|
|
583
|
+
```mermaid
|
|
584
|
+
sequenceDiagram
|
|
585
|
+
actor U as Пользователь (мобильный)
|
|
586
|
+
participant NAV as Nav Bar
|
|
587
|
+
participant ASIDE as Sidebar (aside)
|
|
588
|
+
participant OVERLAY as Overlay
|
|
589
|
+
participant SECTION as Section
|
|
590
|
+
|
|
591
|
+
Note over NAV: Viewport < 768px
|
|
592
|
+
|
|
593
|
+
U->>NAV: Тап на hamburger icon
|
|
594
|
+
|
|
595
|
+
NAV->>ASIDE: classList.remove('translate-x-full')<br/>classList.add('translate-x-0')
|
|
596
|
+
NAV->>OVERLAY: display: block<br/>opacity: 0.5
|
|
597
|
+
|
|
598
|
+
Note over ASIDE: Sidebar выезжает слева<br/>поверх контента
|
|
599
|
+
|
|
600
|
+
U->>ASIDE: Тап на "Section 3" в TOC
|
|
601
|
+
|
|
602
|
+
ASIDE->>SECTION: scrollIntoView({ behavior: 'smooth' })
|
|
603
|
+
ASIDE->>ASIDE: classList.add('translate-x-full')
|
|
604
|
+
ASIDE->>OVERLAY: display: none
|
|
605
|
+
|
|
606
|
+
Note over NAV: Sidebar скрыт,<br/>страница проскроллена к Section 3
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
---
|
|
610
|
+
|
|
611
|
+
## 9. Flow: YouTube Timestamp Sync
|
|
612
|
+
|
|
613
|
+
### Sequence Diagram
|
|
614
|
+
|
|
615
|
+
```mermaid
|
|
616
|
+
sequenceDiagram
|
|
617
|
+
actor U as Пользователь
|
|
618
|
+
participant LINK as Timestamp Link
|
|
619
|
+
participant JS as Event Handler
|
|
620
|
+
participant IFRAME as YouTube iframe
|
|
621
|
+
participant YT as YouTube Player API
|
|
622
|
+
|
|
623
|
+
Note over IFRAME: При загрузке страницы
|
|
624
|
+
|
|
625
|
+
JS->>IFRAME: Create iframe with enablejsapi=1
|
|
626
|
+
IFRAME->>YT: Load YouTube IFrame API
|
|
627
|
+
YT-->>JS: onYouTubeIframeAPIReady()
|
|
628
|
+
JS->>YT: new YT.Player('yt-player', {...})
|
|
629
|
+
YT-->>JS: player ready
|
|
630
|
+
|
|
631
|
+
Note over U: Клик на timestamp
|
|
632
|
+
|
|
633
|
+
U->>LINK: Клик на [2:05]
|
|
634
|
+
|
|
635
|
+
Note over LINK: HTML:<br/>a data-seek="125"
|
|
636
|
+
|
|
637
|
+
LINK->>JS: click event (delegation)
|
|
638
|
+
JS->>JS: e.target.closest('[data-seek]')
|
|
639
|
+
JS->>JS: seconds = parseInt(dataset.seek) = 125
|
|
640
|
+
|
|
641
|
+
JS->>YT: player.seekTo(125, true)
|
|
642
|
+
YT->>IFRAME: Перемотка на 2:05
|
|
643
|
+
|
|
644
|
+
JS->>IFRAME: scrollIntoView({ behavior: 'smooth' })<br/>(если iframe не в viewport)
|
|
645
|
+
|
|
646
|
+
Note over U: Видео начинает воспроизведение с 2:05
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
### Flowchart с обработкой ошибок
|
|
650
|
+
|
|
651
|
+
```mermaid
|
|
652
|
+
flowchart TD
|
|
653
|
+
CLICK["Клик на [data-seek]"] --> PREVENT["e.preventDefault()"]
|
|
654
|
+
PREVENT --> PARSE["seconds = parseInt(dataset.seek)"]
|
|
655
|
+
|
|
656
|
+
PARSE --> CHECK_PLAYER{"player<br/>ready?"}
|
|
657
|
+
|
|
658
|
+
CHECK_PLAYER -->|"Да"| SEEK["player.seekTo(seconds, true)"]
|
|
659
|
+
CHECK_PLAYER -->|"Нет (player undefined)"| FALLBACK_1["Открыть YouTube URL<br/>с параметром t=seconds<br/>в новой вкладке"]
|
|
660
|
+
|
|
661
|
+
SEEK --> IN_VIEW{"iframe<br/>в viewport?"}
|
|
662
|
+
|
|
663
|
+
IN_VIEW -->|"Да"| DONE["Видео перемотано"]
|
|
664
|
+
IN_VIEW -->|"Нет"| SCROLL["scrollIntoView(iframe,<br/>{ behavior: 'smooth' })"]
|
|
665
|
+
SCROLL --> DONE
|
|
666
|
+
|
|
667
|
+
FALLBACK_1 --> DONE_ALT["YouTube открыт<br/>в новой вкладке"]
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
---
|
|
671
|
+
|
|
672
|
+
## 10. Flow: GitHub Pages Deployment
|
|
673
|
+
|
|
674
|
+
### Flowchart
|
|
675
|
+
|
|
676
|
+
```mermaid
|
|
677
|
+
flowchart TD
|
|
678
|
+
GEN["Сайт сгенерирован<br/>docs/index.html"] --> GIT_INIT{"git repo<br/>инициализирован?"}
|
|
679
|
+
|
|
680
|
+
GIT_INIT -->|"Нет"| INIT["git init"]
|
|
681
|
+
GIT_INIT -->|"Да"| ADD
|
|
682
|
+
|
|
683
|
+
INIT --> ADD["git add docs/"]
|
|
684
|
+
ADD --> COMMIT["git commit -m<br/>'add transcript site'"]
|
|
685
|
+
COMMIT --> REMOTE{"Remote<br/>настроен?"}
|
|
686
|
+
|
|
687
|
+
REMOTE -->|"Нет"| ADD_REMOTE["git remote add origin<br/>https://github.com/USER/REPO"]
|
|
688
|
+
REMOTE -->|"Да"| PUSH
|
|
689
|
+
|
|
690
|
+
ADD_REMOTE --> PUSH["git push origin main"]
|
|
691
|
+
PUSH --> GITHUB["GitHub Repository"]
|
|
692
|
+
GITHUB --> SETTINGS["Settings > Pages"]
|
|
693
|
+
|
|
694
|
+
SETTINGS --> CONFIG["Source: Deploy from branch<br/>Branch: main<br/>Folder: /docs"]
|
|
695
|
+
CONFIG --> BUILD["GitHub Pages build<br/>(~1-2 минуты)"]
|
|
696
|
+
BUILD --> LIVE["Сайт доступен:<br/>https://USER.github.io/REPO/"]
|
|
697
|
+
|
|
698
|
+
LIVE --> VERIFY_LIVE["Проверить:<br/>открыть URL в браузере"]
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### Sequence Diagram с GitHub Actions
|
|
702
|
+
|
|
703
|
+
```mermaid
|
|
704
|
+
sequenceDiagram
|
|
705
|
+
actor D as Разработчик
|
|
706
|
+
participant GIT as git
|
|
707
|
+
participant GH as GitHub
|
|
708
|
+
participant GA as GitHub Actions
|
|
709
|
+
participant GP as GitHub Pages
|
|
710
|
+
|
|
711
|
+
D->>GIT: git add docs/
|
|
712
|
+
D->>GIT: git commit -m "add transcript site"
|
|
713
|
+
D->>GIT: git push origin main
|
|
714
|
+
|
|
715
|
+
GIT->>GH: Push docs/ файлы
|
|
716
|
+
|
|
717
|
+
alt GitHub Pages настроен на docs/
|
|
718
|
+
GH->>GP: Deploy из docs/ напрямую
|
|
719
|
+
GP-->>D: Сайт live через 1-2 минуты
|
|
720
|
+
else GitHub Actions workflow настроен
|
|
721
|
+
GH->>GA: Trigger workflow<br/>(on push, paths: docs/**)
|
|
722
|
+
GA->>GA: actions/checkout
|
|
723
|
+
GA->>GA: actions/upload-pages-artifact<br/>(path: docs/)
|
|
724
|
+
GA->>GP: actions/deploy-pages
|
|
725
|
+
GP-->>D: Сайт live через 2-3 минуты
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
D->>GP: Открыть https://USER.github.io/REPO/
|
|
729
|
+
GP-->>D: Интерактивный transcript сайт
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
---
|
|
733
|
+
|
|
734
|
+
## 11. Flow: Error Handling
|
|
735
|
+
|
|
736
|
+
### yt-dlp не найден
|
|
737
|
+
|
|
738
|
+
```mermaid
|
|
739
|
+
flowchart TD
|
|
740
|
+
URL["YouTube URL предоставлен"] --> CHECK{"yt-dlp<br/>в PATH?"}
|
|
741
|
+
|
|
742
|
+
CHECK -->|"Да"| EXTRACT["Извлечение субтитров"]
|
|
743
|
+
CHECK -->|"Нет"| ERROR["WARN: yt-dlp not found"]
|
|
744
|
+
|
|
745
|
+
ERROR --> OPTIONS{"Варианты:"}
|
|
746
|
+
|
|
747
|
+
OPTIONS -->|"Установить yt-dlp"| INSTALL["pip install yt-dlp<br/>Повторить запуск"]
|
|
748
|
+
OPTIONS -->|"Вставить текст"| MANUAL["Пользователь вставляет<br/>текст транскрипта<br/>в чат"]
|
|
749
|
+
|
|
750
|
+
MANUAL --> CONTINUE["Продолжить как<br/>text-only flow"]
|
|
751
|
+
INSTALL --> EXTRACT
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
### Транскрипт слишком короткий
|
|
755
|
+
|
|
756
|
+
```mermaid
|
|
757
|
+
flowchart TD
|
|
758
|
+
PARSE["Content Parsing"] --> COUNT{"Слов<br/>< 50?"}
|
|
759
|
+
|
|
760
|
+
COUNT -->|"Да"| SHORT["WARN: Транскрипт слишком короткий"]
|
|
761
|
+
COUNT -->|"Нет"| CONTINUE["Продолжить"]
|
|
762
|
+
|
|
763
|
+
SHORT --> OPTIONS{"Варианты:"}
|
|
764
|
+
|
|
765
|
+
OPTIONS -->|"Продолжить<br/>(small site)"| SMALL["Генерация minimal site:<br/>1 секция, без TOC"]
|
|
766
|
+
OPTIONS -->|"Добавить текст"| ADD["Пользователь добавляет<br/>ещё текст"]
|
|
767
|
+
OPTIONS -->|"Отмена"| CANCEL["Прервать пайплайн"]
|
|
768
|
+
|
|
769
|
+
ADD --> PARSE
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
### HTML validation failure
|
|
773
|
+
|
|
774
|
+
```mermaid
|
|
775
|
+
flowchart TD
|
|
776
|
+
VERIFY["Шаг 6: Verification"] --> CHECK{"Все 35<br/>проверок<br/>прошли?"}
|
|
777
|
+
|
|
778
|
+
CHECK -->|"Да"| DONE["PIPELINE COMPLETE"]
|
|
779
|
+
CHECK -->|"Нет"| REPORT["Отчёт ошибок"]
|
|
780
|
+
|
|
781
|
+
REPORT --> SEVERITY{"Уровень<br/>ошибок?"}
|
|
782
|
+
|
|
783
|
+
SEVERITY -->|"Critical<br/>(HTML, Security)"| BLOCK["BLOCK: Исправить<br/>перед деплоем"]
|
|
784
|
+
SEVERITY -->|"Warning<br/>(Performance)"| WARN["WARN: Рекомендации"]
|
|
785
|
+
SEVERITY -->|"Info<br/>(SEO optional)"| INFO["INFO: Опционально"]
|
|
786
|
+
|
|
787
|
+
BLOCK --> AUTO_FIX{"Авто-<br/>исправление<br/>возможно?"}
|
|
788
|
+
|
|
789
|
+
AUTO_FIX -->|"Да"| FIX["Автоматическое<br/>исправление"]
|
|
790
|
+
AUTO_FIX -->|"Нет"| MANUAL["Требуется ручное<br/>вмешательство"]
|
|
791
|
+
|
|
792
|
+
FIX --> REVERIFY["Повторная<br/>верификация"]
|
|
793
|
+
REVERIFY --> CHECK
|
|
794
|
+
|
|
795
|
+
WARN --> DONE_WARN["PIPELINE COMPLETE<br/>(с предупреждениями)"]
|
|
796
|
+
INFO --> DONE_INFO["PIPELINE COMPLETE"]
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
### Общая обработка ошибок
|
|
800
|
+
|
|
801
|
+
```mermaid
|
|
802
|
+
flowchart TD
|
|
803
|
+
ERROR["Ошибка на любом шаге"] --> TYPE{"Тип<br/>ошибки?"}
|
|
804
|
+
|
|
805
|
+
TYPE -->|"yt-dlp не найден"| YTDLP_ERR["Предложить установку<br/>или ручной ввод"]
|
|
806
|
+
TYPE -->|"Пустой транскрипт"| EMPTY_ERR["Запросить текст<br/>у пользователя"]
|
|
807
|
+
TYPE -->|"Файл не найден"| FILE_ERR["Проверить путь<br/>Показать ls директории"]
|
|
808
|
+
TYPE -->|"Кодировка"| ENC_ERR["Предложить конвертацию<br/>iconv -f WINDOWS-1251 -t UTF-8"]
|
|
809
|
+
TYPE -->|"Превышен размер"| SIZE_ERR["Предложить chunking<br/>--chunking multi"]
|
|
810
|
+
TYPE -->|"GitHub Pages 404"| GH_ERR["Проверить Settings > Pages<br/>Branch + Folder"]
|
|
811
|
+
TYPE -->|"Tailwind CDN offline"| CDN_ERR["Предложить --tailwind inline"]
|
|
812
|
+
|
|
813
|
+
YTDLP_ERR --> CONTINUE["Продолжить<br/>с fallback"]
|
|
814
|
+
EMPTY_ERR --> CONTINUE
|
|
815
|
+
FILE_ERR --> RETRY["Повторить<br/>с правильным путём"]
|
|
816
|
+
ENC_ERR --> RETRY
|
|
817
|
+
SIZE_ERR --> CONTINUE
|
|
818
|
+
GH_ERR --> MANUAL_FIX["Ручная настройка<br/>GitHub Pages"]
|
|
819
|
+
CDN_ERR --> CONTINUE
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
---
|
|
823
|
+
|
|
824
|
+
## Быстрый справочник команд
|
|
825
|
+
|
|
826
|
+
| Команда | Назначение | Минимальный вход | Результат |
|
|
827
|
+
|---------|-----------|-----------------|-----------|
|
|
828
|
+
| `/transcript-site [source]` | Полный пайплайн (6 шагов) | YouTube URL, текст или путь к файлу | docs/index.html + robots.txt + sitemap.xml |
|
|
829
|
+
| `/transcript-site-generate [source]` | Только генерация HTML (шаги 1-4) | YouTube URL, текст или путь к файлу | docs/index.html |
|
|
830
|
+
| `/transcript-site-deploy [path]` | Только деплой конфиг (шаги 5-6) | Путь к существующему HTML | robots.txt + sitemap.xml + verification |
|
|
831
|
+
|
|
832
|
+
## Частые сценарии
|
|
833
|
+
|
|
834
|
+
```
|
|
835
|
+
# YouTube видео -> интерактивный сайт
|
|
836
|
+
/transcript-site https://youtube.com/watch?v=VIDEO_ID
|
|
837
|
+
|
|
838
|
+
# Текстовый файл -> сайт
|
|
839
|
+
/transcript-site /path/to/transcript.txt
|
|
840
|
+
|
|
841
|
+
# Markdown файл -> сайт
|
|
842
|
+
/transcript-site researches/case/08_executive_summary.md
|
|
843
|
+
|
|
844
|
+
# YouTube + исправленный текст
|
|
845
|
+
/transcript-site https://youtube.com/watch?v=... --text corrected.txt
|
|
846
|
+
|
|
847
|
+
# Кастомная тема + язык
|
|
848
|
+
/transcript-site [source] --theme emerald --lang ru
|
|
849
|
+
|
|
850
|
+
# Полностью offline-совместимый сайт
|
|
851
|
+
/transcript-site [source] --tailwind inline --icons inline --no-embed
|
|
852
|
+
|
|
853
|
+
# Multi-page для длинного транскрипта
|
|
854
|
+
/transcript-site [source] --chunking multi --output docs/long-talk/
|
|
855
|
+
```
|