From b4603fbeccc47e5ae7d3593ee2418f453f8ac8b9 Mon Sep 17 00:00:00 2001 From: "s.zotov" Date: Sun, 12 Apr 2026 20:46:35 +0000 Subject: [PATCH] Add "Blocks" --- Blocks.md | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 Blocks.md diff --git a/Blocks.md b/Blocks.md new file mode 100644 index 0000000..2ab28b7 --- /dev/null +++ b/Blocks.md @@ -0,0 +1,153 @@ +# Блоки и шаблоны + +## Что такое блок + +Блок — единица конструктора. Каждый блок = фрагмент Pug-кода, который при сборке конкатенируется с другими блоками в итоговый PUG-файл. + +Блоки хранятся в `Block.pug` (файл `z51-pug-builder/public/Block.pug`), разделены комментариями `//Название блока`. + +## Как парсятся блоки + +Файл `parsing.js` → функция `parseBlocks(text)`: +1. Разбивает текст по строкам, начинающимся с `//` +2. Каждый `//` — начало нового блока, текст после `//` — имя +3. Содержимое до следующего `//` — контент блока +4. Блоки с именем "Доп. текст" фильтруются + +Результат: `[{name: "Заголовок", content: "+spacerLine(40)\ntr\n td..."}, ...]` + +## Типы полей + +При добавлении блока в конструктор, система строит **схему полей** (`buildBaseSchema`): + +| Тип поля | Описание | Пример в Pug | +|----------|----------|-------------| +| `raw` | Весь контент блока как есть | Блоки "3 товара в ряд" | +| `text` | Текстовое содержимое после тега | `span.font.h2 ТЕКСТ` | +| `mixin-text` | Текстовый аргумент миксина | `+buttonRounded("Текст", ...)` | +| `mixin-href` | URL-аргумент миксина | `+buttonRounded("...", "https://...")` | +| `mixin-ids` | Список ID (через запятую) | `+products4("123,456,789")` | +| `mixin-opts` | Объект опций в миксине | `+products4("...", {hidePrice: true})` | +| `href` | Атрибут href | `a(href="https://...")` | +| `src` | Атрибут src | `img(src="https://...")` | +| `list-item` | Элемент списка (tr+td+span) | Блоки с таблицами товаров | + +## Автоопределение полей + +Функция `guessAutoMixinField(rawArg, argIndex)` определяет тип аргумента миксина: +- Содержит запятые и цифры → `mixin-ids` +- Начинается с `{` → объект, парсится `parseMixinObjectArg` +- Начинается с `http`/`/` → `mixin-href` +- Иначе → `mixin-text` + +Для объектных аргументов (`{key: value}`) каждый ключ проверяется через `shouldExposeObjectField`: +- Пропускаются служебные: `class`, `style`, `id`, `data-*` +- Тип определяется по имени ключа (`guessObjectFieldByKey`): `url`/`href`/`link` → href, `src`/`image`/`img` → src, иначе → text + +## Секции блока + +Сложные блоки (карточки товаров) состоят из **секций** — повторяющихся групп строк внутри `tr`: + +```pug +tr ← колонка + td.paddingWrapper + +defaultTable("100%") + tr ← секция "Картинка" + td + img(src="...") + +spacerLine(10) + tr ← секция "Текст" + td + span.font ТЕКСТ +``` + +Функция `parseSections(content)` находит такие структуры и позволяет: +- **Перемещать секции** вверх/вниз внутри блока (`moveSectionInBlock`) +- **Удалять секции** с автоудалением спейсеров (`removeSectionFromBlock`) + +Типы секций определяются по содержимому (`guessSectionLabel`): Кнопка, Картинка, Товары, Заголовок, Текст, Ссылка. + +## Product Options + +Для блоков с товарами (миксины `+products*`) есть **опции** — ключи в объектном аргументе: + +```pug ++products4("123,456,789", {hidePrice: true, showOldPrice: false}) +``` + +Опции настраиваются в settings.json → `productOptions[]`: +```json +[ + {"key": "hidePrice", "label": "Скрыть цену", "default": false}, + {"key": "showOldPrice", "label": "Показать старую цену", "default": true} +] +``` + +Кнопки в UI: включить/выключить опцию для одного блока или всех блоков. + +## Mixin Rules + +Правила разметки аргументов миксинов (когда автоопределение не справляется): + +```json +{ + "mixin": "+products4", + "args": [ + {"index": 0, "type": "mixin-ids", "label": "ID товаров"}, + {"index": 1, "type": "mixin-opts", "label": "Опции"} + ] +} +``` + +## Кастомные блоки + +Пользователь может: +1. **Дублировать** существующий блок как кастомный (`duplicateBlockAsCustom`) +2. **Создать** новый в настройках (`addCustomBlock`) +3. **Переименовать** блок (`renameBlock`) + +Кастомные блоки хранятся в `settings.customBlocks[]` и мержатся с блоками из Block.pug. + +## Quick Blocks + +Быстрые блоки — панель кнопок над списком блоков для быстрого добавления: +- Настраиваются в settings → `quickBlocks[]` +- Поддерживают drag-and-drop для перестановки +- 3 цвета: White (default), Blue, Green → `quickBlockColors` + +## Шаблоны блоков + +Каждый блок может иметь **переопределённый шаблон** в settings: + +```json +{ + "blocks": { + "БАННЕР": { + "template": "+spacerLine(40)\ntr\n td\n a(href=\"\")\n img(src=\"\")", + "defaultSpacing": 0 + } + } +} +``` + +`getEffectiveTemplate(name)` — возвращает override из settings или оригинал из Block.pug. + +## Спейсеры между блоками + +- `globalSpacing` — отступ по умолчанию (обычно 40) +- Каждый блок может переопределить: `block.spacing` (ввод в UI) или `settings.blocks[name].defaultSpacing` +- `block.addSpacing` — флаг, добавлять ли спейсер перед блоком +- При сборке: `+spacerLine(spacing)` вставляется между блоками + +## Drag-and-Drop блоков + +Блоки в конструкторе перетаскиваются мышью: +- `handleBlockDragStart(index)` → `handleBlockDragOver(index)` → `handleBlockDrop(index)` +- Визуальная индикация: `dragging-block`, `drag-over-block` +- Обновляет массив `assembledBlocks[]` + +## Import/Export + +- `exportBlocksPug()` — экспорт всех шаблонов блоков в текст +- `importBlocksPug()` — импорт из текста (парсит и обновляет block.pug) +- `downloadBlocksPug()` — скачивание как файл