# design-system.md Гайд по `lc-evo-deck/design-system.js` для тех, кто собирает слайды. ## Что внутри `design-system.js` экспортирует единый объект с тремя слоями: | Слой | Что лежит | | ---------- | --------------------------------------------------------------- | | `palette` | Цвета: фон, текст, акценты, код, состояния | | `fonts` | `code`, `ui`, `fallback` (Arial для кириллицы) | | `sizes` | Шкала шрифтов: `h1` ... `caption`, `eyebrow` | | `spacing` | Отступы: `page`, `card_pad`, `gap` | | `layouts` | Константы 16:9: `HEADER_Y`, `CONTENT_TOP`, `CONTENT_BOTTOM`, `FOOTER_Y` | | `theme` | Все перечисленное выше в одном объекте (удобно пробрасывать) | | `helpers` | Готовые функции для сборки слайда | Импорт: ```js const ds = require('./design-system'); const { theme, helpers, layouts } = ds; ``` ## Геометрия слайда (16:9, дюймы) ``` y=0.00 +-----------------------------------------------+ | HEADER_Y = 0.4 | | eyebrow (10pt, accent) | y=1.25 | --- hairline --- | | CONTENT_TOP = 1.4 <-- начинай контент тут | | | | контент | | | y=5.05 | CONTENT_BOTTOM = 5.05 | | FOOTER_Y = 5.25 <-- page number, source | y=5.625 +-----------------------------------------------+ x=0.5 x=9.5 ^ отступ `spacing.page` (0.5 дюйма) с обеих сторон ``` ## Минимальный слайд ```js const pptxgen = require('pptxgenjs'); const ds = require('./design-system'); const { theme, helpers, layouts } = ds; const pres = new pptxgen(); pres.layout = 'LAYOUT_16x9'; const slide = pres.addSlide(); helpers.slideBase(slide, pres, theme); helpers.addHeader(slide, pres, theme, { section: 'Stage 2: Chains', sectionNumber: 2, title: 'LCEL: composable expressions', eyebrow: 'STAGE 2', }); helpers.addPageNumber(slide, pres, theme, 1); await pres.writeFile({ fileName: 'lc-evolution.pptx' }); ``` ## Какой layout для какого случая | Слайд | Что использовать | | ------------------------------ | --------------------------------------------------------- | | Титул раздела / stage divider | `helpers.addSectionDivider` (большая цифра + заголовок) | | Текст + код | `addHeader` + `addCodeBlock` слева, `addCallout` справа | | Сравнение двух подходов | `addProsCons` (две колонки, + и -) | | Цитата / важное замечание | `addCallout` с `kind: 'info' | 'warning' | 'success' | 'danger'` | | Код с акцентом на строке | `addCodeBlockWithHighlight` + `lines: [3, 4]` | | Источник внизу | `addSourceLine` | | Любой слайд | `addPageNumber` в правом нижнем углу | ## Helper-функции -- короткая справка ### `slideBase(slide, pres, theme)` Закрашивает фон `bg.primary`. Вызывай первым на каждом слайде. ### `addHeader(slide, pres, theme, opts)` - `opts.eyebrow` -- маленький caps-ярлык сверху (например `STAGE 2: CHAINS`) - `opts.section` -- альтернатива eyebrow - `opts.sectionNumber` -- крупная цифра справа (необязательно) - `opts.title` -- h1 ### `addCodeBlock(slide, pres, theme, opts)` - `opts.code` -- строка кода (`\n` для переносов) - `opts.filePath` + `opts.startLine` -- подпись `// path/to/file.py:1-12` - `opts.highlightLines` -- массив 1-based номеров строк, которые подсветить - Если строк больше, чем влезает по высоте, внизу появится желтая плашка `// note: snippet has N lines, card fits ~M` -- уменьши `fontSize` или разбей сниппет. ### `addCodeBlockWithHighlight(slide, pres, theme, opts)` То же самое, но принимает `lines: [3, 4]` как алиас для `highlightLines`. ### `addCallout(slide, pres, theme, opts)` - `opts.kind` -- `info` | `warning` | `success` | `danger` - `opts.title` -- необязательный заголовок внутри плашки - `opts.text` -- основной текст ### `addProsCons(slide, pres, theme, opts)` - `opts.pros` -- массив строк - `opts.cons` -- массив строк - Плюсы слева (зелёная рамка), минусы справа (красная). ### `addPageNumber(slide, pres, theme, n)` Правый нижний угол, монохромный caption. ### `addSectionDivider(slide, pres, theme, opts)` - `opts.number` -- крупная цифра слева - `opts.title` -- заголовок справа - `opts.eyebrow` -- необязательный caps-ярлык - `opts.intro` -- абзац под заголовком ### `addSourceLine(slide, pres, theme, opts)` - `opts.source` -- URL или короткая ссылка - По умолчанию `x=0.5, y=5.30, w=7.0` ### `highlightPython(code)` (опционально) Если на машине стоит `pygmentize` (из пакета `pygments`), функция вернет массив `{ text, color }` токенов. Если бинарника нет -- вернется один токен с дефолтным цветом и весь код отрисуется моноширинно. Используй, когда нужна попроцедурная подсветка поверх `addCodeBlock`. ## Правила 1. Не вставляй em-dash (`--`) и en-dash (`-`) -- заменяй на `--` и `-`. 2. Не используй Unicode-кавычки -- только ASCII `"` и `'`. 3. Не используй `...` -- заменяй на `...`. 4. Шрифты -- всегда через `helpers.withFallback(name)`, чтобы Arial был гарантированным фолбэком. 5. Цвета бери из `palette.*` -- не хардкодь hex в слайдах. 6. Геометрия -- через `layouts.*` константы. 7. Любой новый слайд начинается с `slideBase(...)`. ## Частые ошибки | Симптом | Причина | Фикс | | -------------------------------------- | ------------------------------------ | --------------------------------------------------- | | Шрифт Arial вместо JetBrains Mono | PowerPoint не нашел шрифт | Установи `JetBrains Mono` в систему | | Кириллица в коде рендерится квадратами | Нет фолбэка | Используй `helpers.withFallback(t.fonts.code)` | | Код вылезает за карточку | Слишком много строк | Уменьши `sizes.code` или укороти сниппет | | Header и контент перекрываются | Контент начинается выше `CONTENT_TOP`| Подними `y` до `layouts.CONTENT_TOP` | | Плашка `note: snippet has N lines` | Сниппет не помещается | Разбей на 2 карточки или уменьши `sizes.code` |