diff --git a/.gitignore b/.gitignore
index 582c65b..0e3bead 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,18 @@
node_modules/
-report.docx
-presentation.pptx
-DocxGenerator.exe
*.log
*.pdf
.plantuml-cache/
tools/plantuml.jar
+
+# Сгенерированные документы и презентации
+report.docx
+presentation.pptx
+
+# Пользовательские проекты в content/; в репозитории хранится только пример
+content/*
+!content/example/
+!content/example/**
+
+# Сгенерированные файлы примера тоже не коммитим
+content/example/*.docx
+content/example/*.pptx
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..dba63bd
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,111 @@
+# AGENTS.md — управление проектом SSAU Generator
+
+Репозиторий содержит два независимых генератора отчётных документов из Markdown.
+Этот файл описывает управление проектом в целом. Правила работы с конкретным
+документом — в [`docx/AGENTS.md`](docx/AGENTS.md) и [`pptx/AGENTS.md`](pptx/AGENTS.md).
+
+## Что использовать по запросу пользователя
+
+- Просит **сгенерировать документ** (отчёт, DOCX, пояснительную записку,
+ лабораторную работу) — используйте генератор в папке `docx/`.
+- Просит **сгенерировать презентацию** (PPTX, слайды) — используйте генератор в
+ папке `pptx/`.
+
+Команды запускаются из корня репозитория; генератору указывается `config.yaml`
+нужного проекта. Содержимое документа задаётся Markdown-файлами и `config.yaml`
+проекта, а не кодом генератора.
+
+## Правила работы над проектом
+
+- **Уточните название проекта.** Если пользователь не указал, над каким проектом
+ ведётся работа, сначала спросите его. Проект — это папка `content/<проект>/`.
+- **Один проект за сессию.** В рамках одной сессии работайте только над одним
+ проектом.
+- **Создание — только через `--init`.** Новый проект создавайте командами с флагом
+ `--init` (см. ниже): они формируют правильную структуру и общий каталог
+ ресурсов.
+- **Имя результата = имя проекта.** Документ и презентация собираются в папку
+ проекта, а имя файла совпадает с именем проекта:
+ `content/<проект>/<проект>.docx` и `content/<проект>/<проект>.pptx`.
+ Соответствующий путь задаётся ключом `output` в `config.yaml`.
+- **Пересобирайте после правок.** При любом изменении исходных файлов
+ (`config.yaml`, `*.md`, ресурсов в `assets/`) заново запускайте сборку docx
+ и/или pptx, чтобы результат соответствовал исходникам.
+
+## Структура репозитория
+
+```
+ssau-generator/
+├── docx/ # генератор DOCX (только код)
+├── pptx/ # генератор PPTX (только код)
+├── tools/ # общий plantuml.jar (не в git)
+├── content/ # проекты (в git хранится только example)
+│ └── example/
+│ ├── assets/ # общие ресурсы проекта (для docx и pptx)
+│ ├── docx/ # config.yaml + *.md
+│ └── pptx/ # config.yaml + slides/
+├── AGENTS.md # этот файл
+└── README.md
+```
+
+## Проекты и каталог content
+
+- **Один проект = одна папка** `content/<проект>/`.
+- Внутри проекта при необходимости лежат папки `docx/` и `pptx/`.
+- **Общие ресурсы проекта** (титульный лист, задники, изображения, исходники
+ `.puml`) размещаются в `content/<проект>/assets/` и используются обоими
+ генераторами. В `docx/` и `pptx/` внутри проекта хранятся только `config.yaml`
+ и Markdown.
+- Папки `content/*` добавлены в `.gitignore`; в репозитории хранится только
+ `content/example/`. Рабочие проекты пользователя коммитить не нужно.
+
+## Создание нового проекта
+
+Проект создаётся командами с флагом `--init` — они формируют структуру и общие
+ресурсы автоматически:
+
+```powershell
+# только документ DOCX
+node docx/src/cli.js --content content/<проект>/docx --init
+
+# только презентация PPTX
+node pptx/src/cli.js -c content/<проект>/pptx/config.yaml --init
+
+# оба генератора (каталог content/<проект>/assets/ создаётся первым вызовом
+# и переиспользуется вторым)
+```
+
+После создания отредактируйте `config.yaml` и Markdown; общие ресурсы
+(титульный лист, задники, изображения, `.puml`) положите в
+`content/<проект>/assets/`.
+
+## Сборка
+
+```powershell
+# Документ DOCX
+node docx/src/cli.js --content content/<проект>/docx --check
+node docx/src/cli.js --content content/<проект>/docx
+
+# Презентация PPTX
+node pptx/src/cli.js -c content/<проект>/pptx/config.yaml --check
+node pptx/src/cli.js -c content/<проект>/pptx/config.yaml
+```
+
+Результат: `content/<проект>/<проект>.docx` или
+`content/<проект>/<проект>.pptx` (имя и путь задаются ключом `output` в
+`config.yaml`). После правок исходников пересобирайте файлы.
+
+## Требования
+
+- Node.js 18+, зависимости устанавливаются командой `npm install` в `docx/` и
+ `pptx/`.
+- Java 11+ и файл `tools/plantuml.jar` (не хранится в git) — для рендеринга схем
+ PlantUML (`.puml`).
+
+## Правила
+
+- Для сборки документа не редактируйте код генераторов — меняйте `config.yaml`
+ и Markdown проекта.
+- Не коммитьте содержимое `content/`, кроме `content/example/`.
+- Не храните ресурсы внутри `docx/` и `pptx/` — общие файлы живут в
+ `content/<проект>/assets/`.
diff --git a/README.md b/README.md
index a056c3c..740b380 100644
--- a/README.md
+++ b/README.md
@@ -1,47 +1,125 @@
-# lab_gen — генераторы отчётных документов
+# 📄 SSAU Generator
-Монорепозиторий из двух независимых Node.js-генераторов, которые собирают
-отчётные документы из обычного Markdown по заданному шаблону/стандарту.
+> **SSAU Generator** — это два независимых генератора отчётных документов из обычного **Markdown**: **DOCX**-отчёт по СТО 02068410-004-2018 и **PPTX**-презентация по шаблону Самарского университета.
+>
+> Главное — это **модульность** и **воспроизводимая сборка**: содержимое задаётся Markdown и `config.yaml`, а не правками кода.
+
+---
+
+## 📦 Состав
+
+- **`docx/`** — генератор документов **DOCX** по дизайну СТО 02068410-004-2018
+ - Титульный лист, оглавление, таблицы, рисунки (включая PlantUML), формулы, список источников и приложения
+- **`pptx/`** — генератор презентаций **PPTX** по фирменному шаблону Самарского университета
+ - 16:9, синий фон, задники, логотип и фирменный шрифт заданы в `config.yaml`
+- **`tools/plantuml.jar`** — общий рендерер схем PlantUML (не хранится в git)
+- **`content/`** — проекты пользователя: `content/<проект>/{docx,pptx}` и общие ресурсы `content/<проект>/assets/`
+
+---
+
+## 🚀 Возможности
+
+### 📄 Документ DOCX
+
+- Сборка из **обычного Markdown** по фиксированному дизайну СТО 02068410-004-2018
+- Готовый **титульный лист** (отдельный `.docx`) и **оглавление** (поле Word)
+- Автоматическая **нумерация** разделов, рисунков, таблиц, формул и приложений
+- **Таблицы** — обычные и с подписью и автономером
+- **Рисунки** — готовые PNG и схемы **PlantUML**, рендеримые автоматически
+- **Формулы** с пояснениями и нумерацией
+- **Ссылки на источники** и перекрёстные ссылки на номера объектов
+- Примечания, определения, приложения с буквенной нумерацией
+
+### 📽️ Презентация PPTX
+
+- Сборка из **Markdown**, по одному файлу на слайд
+- Четыре типа слайдов: **титульный, разделитель, контент, финальный** — каждый со своим фоном
+- **Богатая inline-разметка**: полужирный, курсив, акцент, моноширинный
+- **Таблицы, изображения и PlantUML**, схемы-цепочки, карточки-метрики, плашки-выводы
+- **Диаграммы** (bar, line, pie, doughnut, area, radar, scatter) из GFM-таблиц
+- **Заметки докладчика** как сценарий выступления
+- Двухколоночная вёрстка через параметр `side=left|right`
+
+---
+
+## 📂 Структура
```
-lab_gen/
-├── docx/ # генератор DOCX по СТО 02068410-004-2018 (отчёт)
-├── pptx/ # генератор PPTX по шаблону Самарского университета (презентация)
-└── tools/ # общие внешние инструменты (plantuml.jar)
+ssau-generator/
+├── docx/ # генератор DOCX (только код)
+├── pptx/ # генератор PPTX (только код)
+├── tools/ # общий plantuml.jar (не в git)
+├── content/ # проекты (в git хранится только example)
+│ └── example/
+│ ├── assets/ # общие ресурсы проекта (для docx и pptx)
+│ ├── docx/ # config.yaml + *.md
+│ └── pptx/ # config.yaml + slides/
+├── AGENTS.md # инструкции по управлению проектом
+└── README.md
```
-## docx/ — DocxGenerator
+> Каждый проект — отдельная папка `content/<проект>/`. Готовый пример со всеми возможностями — [`content/example/`](content/example/).
-Автономный генератор отчётов **DOCX** из Markdown по дизайну
-СТО 02068410-004-2018. Поддерживает титульный лист, оглавление, таблицы, рисунки
-(включая PlantUML), формулы, список источников и приложения.
+---
+
+## 🛠 Требования
+
+- **Node.js 18+** и зависимости, устанавливаемые командой `npm install` в `docx/` и `pptx/`
+- **Java 11+** и файл `tools/plantuml.jar` — для рендеринга схем PlantUML (`.puml`)
+
+---
+
+## 📝 Быстрый старт
```powershell
-cd docx
-npm install
-npm run check # проверка конфига и ссылок
-npm run generate # собрать report.docx
+npm install --prefix docx
+npm install --prefix pptx
+
+# Документ DOCX
+node docx/src/cli.js --content content/example/docx
+
+# Презентация PPTX
+node pptx/src/cli.js -c content/example/pptx/config.yaml
```
-Полная документация — [docx/AGENTS.md](docx/AGENTS.md).
+Готовый пример со всеми возможностями — [`content/example/`](content/example/).
-## pptx/ — lab-gen-pptx
+---
-Генератор презентаций **PPTX** из Markdown по фирменному шаблону Самарского
-университета (16:9, синий фон, логотип, фирменный шрифт). Задники и правила
-оформления извлечены из `presentation_16.pptx` и заданы в `config.yaml`.
+## 🎯 Использование
+
+### Новый проект
+
+Проект создаётся командами с флагом `--init` — они формируют структуру и общий каталог ресурсов `content/<проект>/assets/`:
```powershell
-cd pptx
-npm install
-npm run check # проверка конфига и ссылок
-npm run generate # собрать presentation.pptx
+# только документ DOCX
+node docx/src/cli.js --content content/<проект>/docx --init
+
+# только презентация PPTX
+node pptx/src/cli.js -c content/<проект>/pptx/config.yaml --init
```
-Формат слайдов, схема конфига и CLI описаны в [pptx/AGENTS.md](pptx/AGENTS.md).
+### Сборка
-## Требования
+```powershell
+# Документ DOCX
+node docx/src/cli.js --content content/<проект>/docx --check
+node docx/src/cli.js --content content/<проект>/docx
-- Node.js 18+ (для локальной сборки).
-- Java 11+ и `tools/plantuml.jar` — для рендеринга схем PlantUML (`.puml`)
- в обоих генераторах. Путь задаётся ключом `plantuml.jar` в `config.yaml`.
+# Презентация PPTX
+node pptx/src/cli.js -c content/<проект>/pptx/config.yaml --check
+node pptx/src/cli.js -c content/<проект>/pptx/config.yaml
+```
+
+Результат собирается в папку проекта и называется по имени проекта: `content/<проект>/<проект>.docx` и `content/<проект>/<проект>.pptx`.
+
+---
+
+## 📚 Документация
+
+- Управление проектом: [AGENTS.md](AGENTS.md)
+- Формат DOCX-документа: [docx/AGENTS.md](docx/AGENTS.md)
+- Формат PPTX-презентации: [pptx/AGENTS.md](pptx/AGENTS.md)
+
+> 💡 **Важно:** Документ и презентация используют общий каталог ресурсов `content/<проект>/assets/`, поэтому титульный лист, задники и изображения переиспользуются обоими генераторами.
diff --git a/pptx/content/assets/content-bg.jpg b/content/example/assets/content-bg.jpg
similarity index 100%
rename from pptx/content/assets/content-bg.jpg
rename to content/example/assets/content-bg.jpg
diff --git a/pptx/content/assets/final-bg.jpeg b/content/example/assets/final-bg.jpeg
similarity index 100%
rename from pptx/content/assets/final-bg.jpeg
rename to content/example/assets/final-bg.jpeg
diff --git a/content/example/assets/images/chart.png b/content/example/assets/images/chart.png
new file mode 100644
index 0000000..b4089f8
Binary files /dev/null and b/content/example/assets/images/chart.png differ
diff --git a/content/example/assets/images/diagram.png b/content/example/assets/images/diagram.png
new file mode 100644
index 0000000..fe00700
Binary files /dev/null and b/content/example/assets/images/diagram.png differ
diff --git a/content/example/assets/images/flow.puml b/content/example/assets/images/flow.puml
new file mode 100644
index 0000000..e5f2c5a
--- /dev/null
+++ b/content/example/assets/images/flow.puml
@@ -0,0 +1,18 @@
+@startuml
+skinparam backgroundColor #FFFFFF
+skinparam defaultFontName "Times New Roman"
+skinparam shadowing false
+
+title Пример схемы PlantUML
+
+start
+:Исходный Markdown;
+:Разбор директив;
+if (Есть схема .puml?) then (да)
+ :Рендеринг через plantuml.jar;
+else (нет)
+ :Вставка готового PNG;
+endif
+:Сборка документа;
+stop
+@enduml
diff --git a/content/example/assets/images/scheme.png b/content/example/assets/images/scheme.png
new file mode 100644
index 0000000..ab6a3a7
Binary files /dev/null and b/content/example/assets/images/scheme.png differ
diff --git a/pptx/content/assets/title-bg.jpeg b/content/example/assets/title-bg.jpeg
similarity index 100%
rename from pptx/content/assets/title-bg.jpeg
rename to content/example/assets/title-bg.jpeg
diff --git a/content/example/assets/title-page.docx b/content/example/assets/title-page.docx
new file mode 100644
index 0000000..d37a675
Binary files /dev/null and b/content/example/assets/title-page.docx differ
diff --git a/content/example/docx/01-introduction.md b/content/example/docx/01-introduction.md
new file mode 100644
index 0000000..c3a2f47
--- /dev/null
+++ b/content/example/docx/01-introduction.md
@@ -0,0 +1,24 @@
+Настоящий документ — демонстрационный пример, который перечисляет все возможности
+генератора DOCX. Исходный текст набирается в обычных Markdown-файлах, а оформление
+полностью задаётся файлом `config.yaml` в соответствии с требованиями
+СТО 02068410-004-2018 [@1].
+
+Документ собирается из отдельных частей, перечисленных в разделе `sections`:
+
+- структурные разделы без номера (введение, заключение);
+- нумеруемые разделы с автоматической нумерацией заголовков;
+- список использованных источников;
+- приложения с буквенной нумерацией объектов.
+
+Основные группы возможностей:
+
+- форматирование текста и заголовков;
+- списки, в том числе многоуровневые;
+- таблицы — обычные и с подписью;
+- рисунки — готовые изображения и схемы PlantUML;
+- формулы с пояснениями;
+- примечания, определения и перекрёстные ссылки.
+
+Подробное описание каждого элемента приведено в разделе 1, примеры таблиц — в
+разделе 2, сводные материалы — в приложении А. Оформление ссылок на источники
+приведено в соответствии с действующими стандартами [@2], [@3].
diff --git a/content/example/docx/02-features.md b/content/example/docx/02-features.md
new file mode 100644
index 0000000..0e5e013
--- /dev/null
+++ b/content/example/docx/02-features.md
@@ -0,0 +1,104 @@
+# ВОЗМОЖНОСТИ ГЕНЕРАТОРА
+
+Раздел перечисляет все поддерживаемые элементы и показывает соответствующий
+синтаксис Markdown. Нумерация заголовков, рисунков, таблиц и формул выполняется
+автоматически.
+
+## Заголовки и абзацы
+
+Заголовок раздела задаётся одним символом `#`, подраздел — двумя `##`, пункт —
+тремя `###`. Обычные абзацы разделяются пустой строкой.
+
+### Третий уровень
+
+Полужирный и курсив в оформлении по стандарту отключены, поэтому `**жирный**` и
+`*курсив*` выводятся как обычный текст.
+
+## Списки
+
+- первый элемент списка;
+- второй элемент с вложенными пунктами:
+ 1. вложенный элемент, выводимый как «а)»;
+ 2. ещё один вложенный элемент.
+
+## Таблицы
+
+Обычная таблица (без подписи и номера):
+
+| Столбец A | Столбец B | Столбец C |
+|---|---|---|
+| 1 | 2 | 3 |
+| 4 | 5 | 6 |
+
+Таблица с подписью и автоматическим номером (ссылка — @tbl:features):
+
+::: table "Возможности оформления" id=features note="Состав приведён условно"
+| Элемент | Синтаксис | Результат |
+|---|---|---|
+| Таблица | `::: table` | Таблица с подписью |
+| Рисунок | `::: figure` | Рисунок с подписью |
+| Формула | `::: formula` | Нумерованная формула |
+| Примечание | `::: note` | Примечание |
+| Определения | `::: definitions` | Список терминов |
+:::
+
+## Рисунки
+
+Готовое изображение вставляется директивой `figure`; файл ищется относительно
+каталога `paths.assets`. Пример — рисунок @fig:diagram:
+
+::: figure "Готовое изображение" id=diagram file=images/diagram.png
+а) функциональные блоки;
+б) направления связей.
+:::
+
+Схема PlantUML рендерится автоматически из исходного файла `.puml` — рисунок
+@fig:flow:
+
+::: figure "Схема PlantUML" id=flow file=images/flow.puml
+:::
+
+## Формулы
+
+Формула с автоматическим номером и списком пояснений:
+
+::: formula id=efficiency
+K = (T_base - T_new)/T_base
+:::
+
+::: where
+K — коэффициент снижения затрат;
+T_base — исходное значение показателя;
+T_new — достигнутое значение показателя.
+:::
+
+Ссылка на формулу: @eq:efficiency.
+
+## Примечания и определения
+
+::: note
+Одиночное примечание к тексту.
+:::
+
+::: notes
+- первое примечание;
+- второе примечание.
+:::
+
+::: definitions
+Термин — краткое определение термина;
+Второй термин — ещё одно определение.
+:::
+
+## Перекрёстные ссылки
+
+Записи @fig:diagram, @tbl:features и @eq:efficiency подставляют актуальные номера
+рисунка, таблицы и формулы. Ссылки на источники оформляются как [@1] или
+[@2, с. 10].
+
+## Разрыв страницы
+
+::: pagebreak
+:::
+
+Тематический разрыв `---` также трактуется как разрыв страницы.
diff --git a/content/example/docx/03-tables.md b/content/example/docx/03-tables.md
new file mode 100644
index 0000000..d6e59b4
--- /dev/null
+++ b/content/example/docx/03-tables.md
@@ -0,0 +1,18 @@
+# ПРИМЕРЫ ТАБЛИЦ
+
+Раздел показывает таблицы разной размерности. Широкая таблица @tbl:wide
+заполняется данными из Markdown-строк.
+
+::: table "Таблица с несколькими столбцами" id=wide
+| № | Наименование | Тип | Значение | Единица |
+|---|---|---|---|---|
+| 1 | Первый параметр | Числовой | 125 | шт. |
+| 2 | Второй параметр | Строковый | 18 | — |
+| 3 | Третий параметр | Логический | да | — |
+| 4 | Четвёртый параметр | Числовой | 420 | руб. |
+:::
+
+После таблицы можно продолжать обычный текст и списки:
+
+- перечисление подтабличных пояснений;
+- ещё один элемент списка.
diff --git a/content/example/docx/04-conclusion.md b/content/example/docx/04-conclusion.md
new file mode 100644
index 0000000..2e7840f
--- /dev/null
+++ b/content/example/docx/04-conclusion.md
@@ -0,0 +1,14 @@
+Демонстрационный документ перечислил все поддерживаемые генератором элементы
+оформления по СТО 02068410-004-2018 [@1].
+
+Основные результаты:
+
+- показаны заголовки, абзацы и многоуровневые списки;
+- приведены обычные и подписанные таблицы;
+- вставлены готовое изображение и схема PlantUML;
+- продемонстрированы формулы, примечания и определения;
+- проверены ссылки на источники и перекрёстные ссылки на объекты.
+
+Полный набор параметров оформления задаётся в файле `config.yaml`, а состав
+документа — списком `sections`. Единицы измерений приведены в соответствии с
+действующим стандартом [@4].
diff --git a/content/example/docx/05-bibliography.md b/content/example/docx/05-bibliography.md
new file mode 100644
index 0000000..5d47c0e
--- /dev/null
+++ b/content/example/docx/05-bibliography.md
@@ -0,0 +1,4 @@
+- ГОСТ 7.32-2017. Система стандартов по информации, библиотечному и издательскому делу. Отчёт о научно-исследовательской работе. Структура и правила оформления. — М. : Стандартинформ, 2017. — 32 с.
+- ГОСТ Р 7.0.5-2008. Библиографическая ссылка. Общие требования и правила составления. — М. : Стандартинформ, 2008. — 23 с.
+- Иванов, И. И. Оформление отчётных документов : учебное пособие / И. И. Иванов. — Самара : Изд-во Самарского университета, 2019. — 184 с.
+- ГОСТ 8.417-2002. Государственная система обеспечения единства измерений. Единицы величин. — М. : Стандартинформ, 2002. — 32 с.
diff --git a/content/example/docx/06-appendix-a.md b/content/example/docx/06-appendix-a.md
new file mode 100644
index 0000000..2aecee9
--- /dev/null
+++ b/content/example/docx/06-appendix-a.md
@@ -0,0 +1,17 @@
+Сводные данные приведены в таблице @tbl:app-a. Номер таблицы в приложении
+получает префикс буквы приложения.
+
+::: table "Сводная таблица" id=app-a
+| Показатель | Значение | Комментарий |
+|---|---|---|
+| Рисунков в приложении | 1 | См. @fig:app-a |
+| Таблиц в приложении | 1 | Текущая таблица |
+| Формул в приложении | 0 | — |
+:::
+
+Схема приложения приведена на рисунке @fig:app-a:
+
+::: figure "Схема приложения" id=app-a file=images/scheme.png
+а) элементы схемы;
+б) связи между элементами.
+:::
diff --git a/content/example/docx/config.yaml b/content/example/docx/config.yaml
new file mode 100644
index 0000000..9bcee9b
--- /dev/null
+++ b/content/example/docx/config.yaml
@@ -0,0 +1,47 @@
+# Демонстрационный проект генератора DOCX.
+# Показывает все возможности оформления отчёта по СТО 02068410-004-2018.
+# Все относительные пути считаются от каталога этого файла.
+# Общие ресурсы проекта лежат выше, в ../assets, и используются и для docx, и для pptx.
+
+document:
+ # Имя файла = имя проекта = имя папки проекта, в папке проекта.
+ output: ../example.docx
+ # Титульный лист — общий ресурс проекта.
+ titlePage: ../assets/title-page.docx
+ features:
+ updateFields: true
+
+paths:
+ # Каталог рисунков; file=images/x.png ищется здесь.
+ assets: ../assets
+
+plantuml:
+ enabled: true
+ java: auto
+ # plantuml.jar лежит в корне репозитория.
+ jar: ../../../tools/plantuml.jar
+ format: png
+ charset: UTF-8
+ cache: true
+ cacheDir: .plantuml-cache
+ timeoutMs: 30000
+
+# Структура документа: порядок частей и их типы.
+sections:
+ - type: toc
+ - file: 01-introduction.md
+ type: structural
+ title: Введение
+ - file: 02-features.md
+ type: numbered
+ - file: 03-tables.md
+ type: numbered
+ - file: 04-conclusion.md
+ type: structural
+ title: Заключение
+ - file: 05-bibliography.md
+ type: bibliography
+ - file: 06-appendix-a.md
+ type: appendix
+ letter: А
+ title: Демонстрационные материалы
diff --git a/content/example/pptx/config.yaml b/content/example/pptx/config.yaml
new file mode 100644
index 0000000..816c413
--- /dev/null
+++ b/content/example/pptx/config.yaml
@@ -0,0 +1,51 @@
+# Демонстрационный проект генератора PPTX.
+# Показывает все типы слайдов и все доступные блоки разметки.
+# Все относительные пути считаются от каталога этого файла.
+# Общие ресурсы проекта лежат выше, в ../assets, и используются и для docx, и для pptx.
+
+presentation:
+ # Имя файла = имя проекта = имя папки проекта, в папке проекта.
+ output: ../example.pptx
+ author: "Автор примера"
+ track: "Название трека"
+
+theme:
+ width: 13.333
+ height: 7.5
+ font: "Segoe UI"
+ backgrounds:
+ # Задники — общие ресурсы проекта.
+ title: ../assets/title-bg.jpeg
+ content: ../assets/content-bg.jpg
+ final: ../assets/final-bg.jpeg
+
+plantuml:
+ enabled: true
+ java: auto
+ # plantuml.jar лежит в корне репозитория.
+ jar: ../../../tools/plantuml.jar
+ format: png
+ charset: UTF-8
+ cache: true
+ cacheDir: .plantuml-cache
+ timeoutMs: 30000
+
+# Каталог контента — папка этого config.yaml.
+content:
+ dir: .
+
+# Список слайдов: тип задаёт макет, file — Markdown-файл слайда.
+slides:
+ - { type: title, file: slides/00-title.md }
+ - { type: content, file: slides/01-text.md }
+ - { type: content, file: slides/02-lists.md }
+ - { type: content, file: slides/03-table.md }
+ - { type: content, file: slides/04-image.md }
+ - { type: content, file: slides/05-puml.md }
+ - { type: content, file: slides/06-metrics.md }
+ - { type: content, file: slides/07-flow.md }
+ - { type: content, file: slides/08-chart.md }
+ - { type: content, file: slides/09-columns.md }
+ - { type: content, file: slides/10-notes.md }
+ - { type: section, file: slides/11-section.md }
+ - { type: final, file: slides/12-final.md }
diff --git a/content/example/pptx/slides/00-title.md b/content/example/pptx/slides/00-title.md
new file mode 100644
index 0000000..5e9c120
--- /dev/null
+++ b/content/example/pptx/slides/00-title.md
@@ -0,0 +1,3 @@
+# Генератор презентаций
+
+## Демонстрация возможностей
diff --git a/content/example/pptx/slides/01-text.md b/content/example/pptx/slides/01-text.md
new file mode 100644
index 0000000..d46f3c8
--- /dev/null
+++ b/content/example/pptx/slides/01-text.md
@@ -0,0 +1,5 @@
+# Форматирование текста
+
+Абзацы и inline-разметка: **полужирный**, *курсив*, ==акцент== и `код`.
+
+Строки автоматически переносятся и подгоняются под ширину слайда.
diff --git a/content/example/pptx/slides/02-lists.md b/content/example/pptx/slides/02-lists.md
new file mode 100644
index 0000000..659123c
--- /dev/null
+++ b/content/example/pptx/slides/02-lists.md
@@ -0,0 +1,6 @@
+# Списки
+
+- пункт первого уровня;
+- второй пункт с вложенными элементами:
+ - вложенный пункт;
+ - ещё один вложенный пункт.
diff --git a/content/example/pptx/slides/03-table.md b/content/example/pptx/slides/03-table.md
new file mode 100644
index 0000000..e29d983
--- /dev/null
+++ b/content/example/pptx/slides/03-table.md
@@ -0,0 +1,10 @@
+# Таблицы
+
+::: table
+| Блок | Директива | Назначение |
+|---|---|---|
+| Таблица | ::: table | Данные в виде таблицы |
+| Метрики | ::: metrics | Карточки с числами |
+| Схема | ::: flow | Цепочка блоков |
+| Диаграмма | ::: chart | График или диаграмма |
+:::
diff --git a/content/example/pptx/slides/04-image.md b/content/example/pptx/slides/04-image.md
new file mode 100644
index 0000000..d5fcace
--- /dev/null
+++ b/content/example/pptx/slides/04-image.md
@@ -0,0 +1,5 @@
+# Изображения
+
+::: image ../assets/images/diagram.png height=3.6
+Подпись под рисунком выводится курсивом.
+:::
diff --git a/content/example/pptx/slides/05-puml.md b/content/example/pptx/slides/05-puml.md
new file mode 100644
index 0000000..98cd5ae
--- /dev/null
+++ b/content/example/pptx/slides/05-puml.md
@@ -0,0 +1,5 @@
+# PlantUML
+
+::: image ../assets/images/flow.puml height=4.6
+Схема собрана автоматически из исходного файла .puml.
+:::
diff --git a/content/example/pptx/slides/06-metrics.md b/content/example/pptx/slides/06-metrics.md
new file mode 100644
index 0000000..915bb2e
--- /dev/null
+++ b/content/example/pptx/slides/06-metrics.md
@@ -0,0 +1,8 @@
+# Метрики
+
+::: metrics
+4 | типа слайдов
+8 | типов блоков
+12 | директив разметки
+100% | возможностей
+:::
diff --git a/content/example/pptx/slides/07-flow.md b/content/example/pptx/slides/07-flow.md
new file mode 100644
index 0000000..5daa179
--- /dev/null
+++ b/content/example/pptx/slides/07-flow.md
@@ -0,0 +1,5 @@
+# Схема-цепочка
+
+::: flow
+Markdown -> Разбор -> Рендеринг -> PPTX
+:::
diff --git a/content/example/pptx/slides/08-chart.md b/content/example/pptx/slides/08-chart.md
new file mode 100644
index 0000000..6f68d48
--- /dev/null
+++ b/content/example/pptx/slides/08-chart.md
@@ -0,0 +1,9 @@
+# Диаграммы
+
+::: chart bar "Пример столбчатой диаграммы"
+| Категория | Значение |
+|---|---|
+| Блок | 8 |
+| Типы слайдов | 4 |
+| Директивы | 12 |
+:::
diff --git a/content/example/pptx/slides/09-columns.md b/content/example/pptx/slides/09-columns.md
new file mode 100644
index 0000000..17f5fed
--- /dev/null
+++ b/content/example/pptx/slides/09-columns.md
@@ -0,0 +1,12 @@
+# Две колонки
+
+::: image ../assets/images/scheme.png side=left height=3.6
+Рисунок в левой колонке.
+:::
+
+::: callout "Плашка-вывод" side=right
+Внутри плашки работает ==выделение== и списки:
+
+- первый пункт;
+- второй пункт.
+:::
diff --git a/content/example/pptx/slides/10-notes.md b/content/example/pptx/slides/10-notes.md
new file mode 100644
index 0000000..61caaea
--- /dev/null
+++ b/content/example/pptx/slides/10-notes.md
@@ -0,0 +1,7 @@
+# Заметки докладчика
+
+Текст слайда набирается как обычно, а сценарий выступления — в директиве notes.
+
+::: notes
+Эти строки видны только в режиме заметок и не попадают на слайд.
+:::
diff --git a/content/example/pptx/slides/11-section.md b/content/example/pptx/slides/11-section.md
new file mode 100644
index 0000000..f39a697
--- /dev/null
+++ b/content/example/pptx/slides/11-section.md
@@ -0,0 +1,3 @@
+# Раздел
+
+## Разделительный слайд
diff --git a/content/example/pptx/slides/12-final.md b/content/example/pptx/slides/12-final.md
new file mode 100644
index 0000000..bd3c628
--- /dev/null
+++ b/content/example/pptx/slides/12-final.md
@@ -0,0 +1,3 @@
+# Спасибо за внимание
+
+Демонстрация возможностей генератора завершена.
diff --git a/docx/AGENTS.md b/docx/AGENTS.md
index bd6fdac..102508c 100644
--- a/docx/AGENTS.md
+++ b/docx/AGENTS.md
@@ -1,145 +1,123 @@
-# AGENTS.md — генератор DocxGenerator
+# AGENTS.md — работа с документом DOCX
-`DocxGenerator` — автономный инструмент, который собирает отчёт в формате **DOCX** из обычных
-**Markdown**-файлов по фиксированному дизайну СТО 02068410-004-2018. Поведение полностью
-задаётся файлом `config.yaml`.
-
-Документ создан и для людей, и для ИИ-агентов: он описывает CLI, формат контента, схему
-конфига и порядок сборки `.exe`.
-
----
+Генератор `docx/` собирает отчёт в формате **DOCX** из обычных **Markdown**-файлов
+по фиксированному дизайну СТО 02068410-004-2018. Этот файл — инструкция агенту по
+созданию и правке конкретного документа. Поведение полностью задаётся `config.yaml`
+проекта, менять код генератора не нужно.
## 1. Требования
-- Windows (собранный `.exe` под `win-x64`).
-- Node.js **только для сборки** `.exe` из исходников. Конечному пользователю Node.js не нужен.
-- Готовые PNG вставляются без внешних зависимостей. Для рендеринга PlantUML (`.puml`)
- нужны установленная Java (JRE 11+) и файл `plantuml.jar` (см. п. 4, `plantuml`).
+- Node.js 18+, зависимости ставятся командой `npm install` в папке `docx/`.
+- Windows/macOS/Linux.
+- Готовые PNG вставляются без внешних зависимостей. Для рендеринга PlantUML
+ (`.puml`) нужны Java 11+ и файл `plantuml.jar` (см. `plantuml` в конфиге).
-## 2. Состав дистрибутива
+## 2. Раскладка проекта
+
+Проект лежит в `content/<проект>/docx/` рядом с `config.yaml`:
```
-DocxGenerator.exe # исполняемый файл
-config.yaml # настройки (создаётся автоматически при первом запуске)
-content/ # Markdown-файлы документа и ресурсы
- *.md
- assets/
- images/ # PNG для рисунков (готовятся заранее) и исходники .puml
- title-page.docx # титульный лист (по умолчанию content/assets/title-page.docx)
-tools/
- plantuml.jar # рендерер PlantUML (для файлов .puml)
-report.docx # результат сборки (путь задаётся document.output)
+content/<проект>/
+├── assets/ # общие ресурсы проекта (общие с pptx)
+│ ├── title-page.docx # титульный лист
+│ └── images/ # PNG-рисунки и исходники .puml
+└── docx/
+ ├── config.yaml # настройки документа
+ ├── 01-introduction.md
+ ├── 02-*.md
+ └── 05-bibliography.md
```
-Все относительные пути в `config.yaml` считаются **от каталога самого `config.yaml`**.
-Сам `config.yaml` и папки ищутся **рядом с `DocxGenerator.exe`**.
+Все относительные пути в `config.yaml` считаются **от каталога самого
+`config.yaml`**. Если ресурсы общие с презентацией, указывайте их через `../assets`
+(например, `paths.assets: ../assets`, `document.titlePage: ../assets/title-page.docx`).
-В монорепозитории общий `plantuml.jar` лежит в корне, в `tools/plantuml.jar`,
-поэтому репозиторный `config.yaml` задаёт `plantuml.jar: ../tools/plantuml.jar`.
-Для автономного дистрибутива положите `tools/plantuml.jar` рядом с `.exe`
-(значение по умолчанию при `--init` — `tools/plantuml.jar`).
+Отчёт собирается в папку проекта и называется по имени проекта:
+`content/<проект>/<проект>.docx`. Значение ключа `document.output` при такой
+раскладке — `../<проект>.docx`.
+
+Структуру проекта создавайте командой `--init`: она формирует `config.yaml`,
+примеры `*.md` и общий каталог `content/<проект>/assets/` (титульный лист,
+изображения), который используется и генератором `pptx`.
+
+Готовый пример со всеми возможностями — `content/example/docx/`.
## 3. Командная строка
-```
-DocxGenerator [опции]
+Из корня репозитория:
- --config <путь> путь к config.yaml (по умолчанию рядом с exe)
- --content
каталог с config.yaml, content/ и assets/ (по умолчанию рядом с exe)
+```
+node docx/src/cli.js [опции]
+
+ --config <путь> путь к config.yaml (по умолчанию config.yaml в текущем каталоге)
+ --content каталог проекта: config.yaml, *.md и assets/ (по умолчанию текущий)
--output <путь> переопределить путь выходного .docx
--check только проверить конфиг и ссылки, без записи файла
- --init создать шаблон config.yaml/content/assets и выйти
+ --init создать шаблон config.yaml/*.md/assets и выйти
--verbose подробный вывод
--version показать версию
--help справка
```
-Поведение:
-
-- Если `config.yaml` не найден, инструмент **сам создаёт** `config.yaml`, примеры `content/*.md`
- и `assets/images/placeholder.png`, печатает подсказку и завершается.
-- `--check` не пишет DOCX, но сообщает обо всех ошибках (битые ссылки, выход `[@n]` за границы
- списка источников, отсутствующие картинки и т.п.).
-
-Типичный цикл работы:
+Типичный цикл:
```powershell
-.\DocxGenerator.exe --init # первый запуск: получить шаблон
-# ... правим config.yaml и content/*.md ...
-.\DocxGenerator.exe --check # проверить
-.\DocxGenerator.exe # собрать report.docx
+node docx/src/cli.js --content content/<проект>/docx --init # создать структуру проекта
+node docx/src/cli.js --content content/<проект>/docx --check # проверить
+node docx/src/cli.js --content content/<проект>/docx # собрать
```
+После любого изменения исходников (`config.yaml`, `*.md`, ресурсов `assets/`)
+**пересоберите документ**, чтобы результат соответствовал исходникам.
+
+Если `config.yaml` не найден, инструмент сам создаёт шаблон (`config.yaml`,
+примеры Markdown и общий `assets/`) и завершается.
+
## 4. Схема `config.yaml`
-Любой ключ можно опустить — берётся значение по умолчанию (см. `src/config/defaults.js`).
+Любой ключ можно опустить — берётся значение по умолчанию (см.
+`docx/src/config/defaults.js`).
### document
| Ключ | Тип | Смысл |
|------|-----|-------|
-| `output` | string | путь выходного `.docx` |
-| `titlePage` | string/null | путь к готовому `title-page.docx` (по умолчанию `content/assets/title-page.docx`); `null` — без титульника |
+| `output` | string | путь выходного `.docx` (относительно `config.yaml`) |
+| `titlePage` | string/null | путь к готовому `title-page.docx`; `null` — без титульника |
| `features.updateFields` | bool | обновлять поля (в т.ч. оглавление) при открытии в Word |
-**Титульный лист.** Берётся готовый DOCX по пути `document.titlePage` и склеивается перед
-документом; между титульником и основным текстом вставляется разрыв страницы. При `--init`
-создаётся пример `content/assets/title-page.docx` — замените его своим. Значение `null`
-отключает титульный лист.
+Титульный лист склеивается перед документом, между ним и текстом вставляется
+разрыв страницы. При `--init` создаётся пример `assets/title-page.docx`.
### paths
| Ключ | Смысл |
|------|-------|
-| `assets` | корень ресурсов; `file=images/x.png` в директивах ищется здесь (по умолчанию `content/assets`) |
+| `assets` | корень ресурсов; `file=images/x.png` в директивах ищется здесь |
-### output
-Путь и имя выходного `.docx` задаются ключом `document.output` (по умолчанию
-`report.docx`). Путь считается от каталога `config.yaml` и может быть переопределён
-флагом `--output`.
+### Структура и оформление
-### page
-`width`, `height` (DXA, 1/20 pt), `margins: {left,right,top,bottom}` (twips). A4 и поля СТО
-заданы по умолчанию.
-
-### typography
-| Ключ | Смысл |
-|------|-------|
-| `font` | гарнитура (по умолчанию Times New Roman) |
-| `sizeBody` / `sizeTable` / `sizeSmall` | размеры в half-points (28 = 14 pt) |
-| `lineSpacing` | множитель межстрочного интервала (1.5 = полуторный) |
-| `color` | цвет текста (hex, без `#`) |
-| `useBold` | разрешить полужирный (СТО: `false`) |
-| `allowEmphasis` | разрешить курсив (СТО: `false`) |
-
-### headings
-Интервалы/выравнивание для `struct`, `section`, `subsection`, `point` (twips).
-
-### captions
-`figure`, `table`, `tableContinue` — префиксы и тире подписей (`Рисунок`, `Таблица`, `—`).
-
-### lists
-`bulletChar`, `letterSuffix`, `numberSuffix`, `nestedLevelStep`, `forbiddenLetters`.
-
-### numbering
-`figures`, `tables`, `formulas`: `global` (сквозная по документу) или `section` (в пределах
-раздела, вид `1.1`). Приложения всегда имеют префикс буквы (`А.1`).
-
-### formula
-`spacingBeforeAfter`, `whereTabPosition`.
-
-### table
-`font`, `size`, `borderColor`, `borderSize`, `cellMargins: {top,bottom,left,right}`,
-`headerFill`, `cellFill`.
-
-### figure
-`maxWidth` (px; `null` — по ширине полосы), `maxHeight` (px).
+| Раздел | Назначение |
+|--------|-----------|
+| `page` | `width`, `height` (DXA), `margins` (twips) |
+| `typography` | `font`, `sizeBody`/`sizeTable`/`sizeSmall`, `lineSpacing`, `color`, `useBold`, `allowEmphasis`, `language` |
+| `headings` | интервалы/выравнивание `struct`, `section`, `subsection`, `point` |
+| `captions` | префиксы и тире подписей `figure`, `table`, `tableContinue` |
+| `lists` | `bulletChar`, `letterSuffix`, `numberSuffix`, `nestedLevelStep`, `forbiddenLetters` |
+| `numbering` | `figures`, `tables`, `formulas`: `global` или `section` |
+| `formula` | `spacingBeforeAfter`, `whereTabPosition` |
+| `table` | `font`, `size`, `borderColor`, `borderSize`, `cellMargins`, `headerFill`, `cellFill` |
+| `figure` | `maxWidth` (px, `null` — по ширине), `maxHeight` (px) |
+| `pageNumber` | `align`, `format`, `startFrom` |
+| `toc` | `enabled`, `title`, `depth` (1..3) |
+| `bibliography` | `title` |
+| `citation` | `bracketOpen`, `bracketClose`, `pagePrefix` |
+| `appendix` | `labelPrefix`, `forbiddenLetters` |
### plantuml
-Генерация рисунков из исходников PlantUML (см. п. 5, «Рисунки»).
| Ключ | Тип | Смысл |
|------|-----|-------|
-| `enabled` | bool | включить рендеринг `.puml`; `false` — считать ошибкой при наличии `.puml` |
-| `java` | string | исполняемый файл Java; `auto` — `%JAVA_HOME%\bin\java`, иначе `java` из PATH |
+| `enabled` | bool | включить рендеринг `.puml`; `false` — считать ошибкой |
+| `java` | string | `auto` — `%JAVA_HOME%\bin\java`, иначе `java` из PATH |
| `jar` | string | путь к `plantuml.jar` (относительно `config.yaml`) |
| `format` | string | только `png` |
| `charset` | string | кодировка исходника (по умолчанию `UTF-8`) |
@@ -147,43 +125,31 @@ DocxGenerator [опции]
| `cacheDir` | string | каталог кэша PNG (относительно `config.yaml`) |
| `timeoutMs` | int | таймаут рендера одной диаграммы, мс |
-Ошибки рендера (нет `jar`, нет Java, синтаксическая ошибка) — **фатальные**: сборка
-прекращается с кодом выхода `1`. Требуется установленная Java (JRE 11+) и файл
-`plantuml.jar`; для части типов диаграмм нужен Graphviz либо встроенный Smlayout.
-
-### pageNumber
-`align`, `format`, `startFrom`.
-
-### toc
-`enabled` (bool), `title`, `depth` (1..3). Оглавление вставляется записью
-`sections: [{ type: toc }]`.
-
-### bibliography / citation / appendix
-`bibliography.title`, `citation: {bracketOpen,bracketClose,pagePrefix}`,
-`appendix: {labelPrefix, forbiddenLetters}`.
+Общий `plantuml.jar` репозитория лежит в `tools/plantuml.jar`; из проекта путь
+вида `../../../tools/plantuml.jar`. Ошибки рендера (нет `jar`, нет Java,
+синтаксическая ошибка) — фатальные: сборка останавливается с кодом `1`.
### sections — структура документа
+
Упорядоченный список частей:
```yaml
sections:
- - { type: toc } # поле оглавления
- - { file: content/01-introduction.md, type: structural, title: Введение }
- - { file: content/02-main.md, type: numbered } # # = 1, ## = 1.1, ### = 1.1.1
- - { file: content/03-conclusion.md, type: structural, title: Заключение }
- - { file: content/04-bibliography.md, type: bibliography }
- - { file: content/05-appendix-a.md, type: appendix, letter: А, title: Приложение }
+ - { type: toc } # поле оглавления
+ - { file: 01-introduction.md, type: structural, title: Введение }
+ - { file: 02-main.md, type: numbered } # # = 1, ## = 1.1, ### = 1.1.1
+ - { file: 04-conclusion.md, type: structural, title: Заключение }
+ - { file: 05-bibliography.md, type: bibliography }
+ - { file: 06-appendix-a.md, type: appendix, letter: А, title: Приложение }
```
-Типы частей:
-
| type | Поведение |
|------|-----------|
| `toc` | вставляет оглавление (не требует `file`) |
| `structural` | ненумерованный раздел (Введение/Заключение): заголовок = `title`, ЗАГЛАВНЫМИ, по центру, с новой страницы |
| `numbered` | нумеруемый раздел; `#` = раздел, `##`/`###` = подраздел/пункт |
| `bibliography` | список источников; нумеруется автоматически |
-| `appendix` | приложение: заголовок «ПРИЛОЖЕНИЕ » + `title`, нумерация рисунков/таблиц с префиксом буквы |
+| `appendix` | приложение: заголовок «ПРИЛОЖЕНИЕ » + `title`, буквенный префикс у рисунков/таблиц |
## 5. Формат контента
@@ -197,12 +163,12 @@ sections:
### Пункт -> 1.1.1 Пункт
```
-Номера подставляются автоматически (Word-numbering). В `structural`/`appendix` заголовок
-берётся из конфига, а заголовки внутри файла рендерятся как обычные заголовки без номера.
+Номера подставляются автоматически (Word-numbering). В `structural`/`appendix`
+заголовок берётся из `title`, а заголовки внутри файла рендерятся без номера.
-### Абзацы, списки
+### Абзацы и списки
-Обычные абзацы и списки Markdown. Списки:
+Обычные абзацы и списки Markdown. Пример:
```md
- первый пункт;
@@ -211,8 +177,8 @@ sections:
2. ещё один.
```
-Маркер вложенности выбирается автоматически: тире → `а)` → `1)`. Полужирный/курсив по
-умолчанию игнорируются (СТО).
+Маркер вложенности выбирается автоматически: тире → `а)` → `1)`. Полужирный и
+курсив по умолчанию игнорируются (СТО).
### Таблицы
@@ -237,13 +203,18 @@ sections:
:::
```
-`file` — относительно `config.paths.assets`. Если файла нет — предупреждение, подпись
-всё равно выводится.
+`file` — относительно `paths.assets`. Если файла нет — предупреждение, подпись
+всё равно выводится. Подпись ставится под рисунком по центру:
+`Рисунок N — Наименование`. Если пояснять нечего, тело директивы оставляют
+пустым:
-**PlantUML.** Если `file` оканчивается на `.puml` (`.plantuml`, `.pu`, `.iuml`), то файл
-считается исходником PlantUML: инструмент рендерит его в PNG через локальный
-`plantuml.jar` (см. `plantuml` в конфиге) и вставляет результат как обычный рисунок.
-Нумерация, ссылки `@fig:id` и примечания работают так же. Пример:
+```md
+::: figure "Общая схема системы" id=common file=images/common.png
+:::
+```
+
+**PlantUML.** Если `file` оканчивается на `.puml` (`.plantuml`, `.pu`, `.iuml`),
+файл рендерится в PNG через `plantuml.jar` и вставляется как обычный рисунок:
```md
::: figure "Диаграмма последовательности" id=seq file=images/seq.puml
@@ -252,18 +223,7 @@ sections:
:::
```
-Ошибка рендера — фатальная (код выхода `1`), `--check` тоже рендерит `.puml`.
-
-**Подписи по СТО.** Подпись ставится **под** рисунком по центру: `Рисунок N — Наименование`
-(с прописной буквы, без точки в конце). Если на рисунке обозначены отдельные детали,
-пояснительные данные размещают **над подписью** и оформляют перечислением `а)`, `б)`, `в)` —
-именно так, как показано в примере выше. Если рисунок общий и пояснять нечего, указывают
-только подпись `Рисунок N — Наименование`, а тело директивы оставляют пустым:
-
-```md
-::: figure "Общая схема системы" id=common file=images/common.png
-:::
-```
+Ошибка рендера фатальна, `--check` тоже рендерит `.puml`.
В приложениях номер рисунка получает префикс буквы: `Рисунок А.1 — Наименование`.
@@ -281,8 +241,8 @@ a — коэффициент.
:::
```
-В формулах поддерживается простой синтаксис: `^` (степень), `_` (индекс), `/` (дробь).
-Номер формулы ставится автоматически справа.
+Поддерживается простой синтаксис: `^` (степень), `_` (индекс), `/` (дробь). Номер
+формулы ставится автоматически справа.
### Примечания и термины
@@ -313,56 +273,44 @@ a — коэффициент.
### Ссылки на источники
-`[@1]` — ссылка на 1-й источник, `[@1, с. 96]` — с номером страницы. Список источников —
-это Markdown-список в файле `type: bibliography`; порядок строк = номера источников.
+`[@1]` — ссылка на 1-й источник, `[@1, с. 96]` — с номером страницы. Список
+источников — Markdown-список в файле `type: bibliography`; порядок строк = номера.
Ссылка вне диапазона — ошибка в `--check`.
### Перекрёстные ссылки
-`@fig:id`, `@tbl:id`, `@eq:id` подставляют актуальный номер рисунка/таблицы/формулы
-(например `2`, `1.1`, `А.1`). `id` задаётся в директиве.
+`@fig:id`, `@tbl:id`, `@eq:id` подставляют актуальный номер рисунка/таблицы/
+формулы (например `2`, `1.1`, `А.1`). `id` задаётся в директиве.
### Блоки кода
-Функция листингов удалена: fenced-блоки ``` игнорируются с предупреждением.
+Fenced-блоки ``` игнорируются с предупреждением (функция листингов удалена).
## 6. Проверка и ошибки
-`DocxGenerator --check` проверяет:
+`--check` проверяет:
-- корректность `config.yaml` (типы, существование файлов, допустимые буквы приложений);
+- корректность `config.yaml` (типы, существование файлов, буквы приложений);
- наличие всех `sections[].file`;
- существование меток в `@fig/@tbl/@eq`;
- диапазон ссылок `[@n]`;
-- рендеринг всех `::: figure ... file=*.puml` (PlantUML).
+- рендеринг всех `::: figure ... file=*.puml`.
Ошибки печатаются списком и возвращают код выхода `1`. Предупреждения (например,
отсутствующий PNG) не останавливают сборку; ошибки PlantUML — фатальные.
-## 7. Сборка `.exe` из исходников
+## 7. Подготовка диаграмм
-```powershell
-npm install
-npm run build:exe # -> DocxGenerator.exe в корне (target node24-win-x64)
-npm run generate # локальная сборка (node src/cli.js)
-npm run check # проверка конфига и ссылок
-```
-
-Упаковка выполняется через `@yao-pkg/pkg`. Чтобы уменьшить размер, можно добавить
-`--compress Brotli` в команду `build:exe`.
-
-### Подготовка диаграмм
-
-Готовые PNG кладутся в `content/assets/images/`. Для исходников PlantUML (`*.puml`)
-инструмент рендерит PNG сам: положите исходник в `content/assets/images/`, укажите его в
-`::: figure ... file=images/<имя>.puml` и поместите `plantuml.jar` в `tools/plantuml.jar`
-(или задайте путь в `plantuml.jar`). Диаграммы других форматов (Mermaid, draw.io) готовятся
-внешними средствами и вставляются как PNG.
+Готовые PNG кладутся в общий каталог ресурсов (`content/<проект>/assets/images/`).
+Исходники PlantUML (`.puml`) кладутся туда же и указываются в
+`::: figure ... file=images/<имя>.puml`. Диаграммы других форматов (Mermaid,
+draw.io) готовятся внешними средствами и вставляются как PNG.
## 8. Замечания по дизайну
-- Дизайн фиксирован под СТО 02068410-004-2018; меняются только параметры из `config.yaml`.
-- Полужирный и курсив по умолчанию отключены (`typography.useBold`, `allowEmphasis`).
-- Шрифт, размеры, интервалы, отступы и подписи настраиваются в конфиге.
-- Оглавление — поле Word; при открытии нажмите «Обновить поле», либо включено
+- Дизайн фиксирован под СТО 02068410-004-2018; меняются только параметры из
+ `config.yaml`.
+- Полужирный и курсив по умолчанию отключены (`typography.useBold`,
+ `allowEmphasis`).
+- Оглавление — поле Word; при открытии нажмите «Обновить поле» либо включите
`document.features.updateFields`.
diff --git a/docx/README.md b/docx/README.md
index a7784d8..90cd1cc 100644
--- a/docx/README.md
+++ b/docx/README.md
@@ -1,44 +1,29 @@
-# DocxGenerator
+# SSAU Generator DOCX
-Автономный генератор отчётов **DOCX** из **Markdown** по дизайну
+Генератор отчётов **DOCX** из **Markdown** по дизайну
[СТО 02068410-004-2018](documentation/STO_SGAU_02068410-004-2018.md).
-Поведение полностью задаётся файлом `config.yaml`; путь выходного файла — ключ
-`document.output`.
+Содержимое задаётся Markdown-файлами и `config.yaml` проекта; путь выходного
+файла — ключ `document.output`.
-Полная документация: **[AGENTS.md](AGENTS.md)** — CLI, схема конфига, формат контента,
-директивы и сборка `.exe`.
+Полная инструкция по работе с документом: **[AGENTS.md](AGENTS.md)** — CLI, схема
+конфига, формат контента, директивы и PlantUML.
## Быстрый старт
```powershell
-.\DocxGenerator.exe --init # создать config.yaml, примеры content/ и content/assets/
-# ... правим config.yaml и content/*.md ...
-.\DocxGenerator.exe --check # проверить ссылки и конфиг
-.\DocxGenerator.exe # собрать report.docx
+node docx/src/cli.js --content content/example/docx --check # проверка
+node docx/src/cli.js --content content/example/docx # собрать report.docx
```
## Разработка
```powershell
npm install
-npm run generate # локальная сборка report.docx
-npm run check # проверка конфига и ссылок
-npm run build:exe # собрать DocxGenerator.exe в корне (@yao-pkg/pkg, node24-win-x64)
+npm run generate # локальная сборка (node src/cli.js)
+npm run check # проверка конфига и ссылок
+npm run init # создать шаблон проекта
```
-## Структура репозитория
-
-| Путь | Назначение |
-|------|------------|
-| `src/cli.js` | точка входа, разбор аргументов |
-| `src/config/` | дефолты, загрузка и валидация `config.yaml`, шаблон |
-| `src/markdown/` | markdown-it, директивы `:::`, инлайн-ссылки `[@n]`, `@fig/@tbl/@eq` |
-| `src/render/` | сборка DOCX: стили, примитивы, нумерация, слияние титульника |
-| `src/build.js` | оркестрация сборки |
-| `content/` | примеры Markdown |
-| `content/assets/` | PNG для рисунков, опциональный `title-page.docx` |
-| `documentation/` | стандарт СТО |
-
-Готовые PNG кладутся в `content/assets/images/`. Исходники PlantUML (`*.puml`) можно указать
-в `::: figure ... file=images/x.puml` — генератор отрендерит их в PNG через локальный
-`plantuml.jar` (требуется Java 11+).
+Структура кода: `src/cli.js` (точка входа), `src/config/` (дефолты, загрузка и
+валидация `config.yaml`, шаблон), `src/markdown/` (markdown-it и директивы),
+`src/render/` (сборка DOCX), `src/plantuml/` (рендеринг схем).
diff --git a/docx/config.yaml b/docx/config.yaml
deleted file mode 100644
index d36f0d2..0000000
--- a/docx/config.yaml
+++ /dev/null
@@ -1,145 +0,0 @@
-# Конфигурация генератора lab-gen.
-# Все относительные пути считаются от каталога этого файла.
-# Любой ключ можно опустить — будет использовано значение по умолчанию.
-
-document:
- output: report.docx
- titlePage: content/assets/title-page.docx
- features:
- updateFields: true
-paths:
- assets: content/assets
-page:
- width: 11906
- height: 16838
- margins:
- left: 1701
- right: 851
- top: 1134
- bottom: 1134
-typography:
- font: Times New Roman
- sizeBody: 28
- sizeTable: 28
- sizeSmall: 24
- lineSpacing: 1.5
- indentFirst: 709
- color: '000000'
- useBold: false
- allowEmphasis: false
-headings:
- struct:
- spacingBefore: 360
- spacingAfter: 560
- align: center
- section:
- spacingBefore: 920
- spacingAfter: 0
- align: left
- subsection:
- spacingBefore: 284
- spacingBeforeAfterSection: 240
- spacingAfter: 0
- align: left
- point:
- spacingBefore: 360
- spacingAfter: 0
-captions:
- figure:
- prefix: Рисунок
- dash: —
- align: center
- table:
- prefix: Таблица
- dash: —
- align: left
- tableContinue:
- prefix: Продолжение таблицы
-lists:
- bulletChar: '-'
- letterSuffix: )
- numberSuffix: )
- forbiddenLetters:
- - ё
- - з
- - й
- - о
- - ч
- - ь
- - ы
- - ъ
- nestedLevelStep: 360
-numbering:
- figures: global
- tables: global
- formulas: global
-formula:
- spacingBeforeAfter: 360
- whereTabPosition: 720
-table:
- font: Times New Roman
- size: 28
- borderColor: '000000'
- borderSize: 1
- cellMargins:
- top: 57
- bottom: 57
- left: 113
- right: 113
- headerFill: FFFFFF
- cellFill: FFFFFF
-figure:
- maxWidth: null
- maxHeight: 620
-plantuml:
- enabled: true
- java: auto
- jar: ../tools/plantuml.jar
- format: png
- charset: UTF-8
- cache: true
- cacheDir: .plantuml-cache
- timeoutMs: 30000
-pageNumber:
- align: center
- format: decimal
- startFrom: 1
-toc:
- enabled: true
- title: Содержание
- depth: 3
-bibliography:
- title: Список использованных источников
-citation:
- bracketOpen: '['
- bracketClose: ']'
- pagePrefix: с.
-appendix:
- labelPrefix: ПРИЛОЖЕНИЕ
- forbiddenLetters:
- - Ё
- - З
- - Й
- - О
- - Ч
- - Ъ
- - Ы
- - Ь
-sections:
- - type: toc
- - file: content/01-introduction.md
- type: structural
- title: Введение
- - file: content/02-method.md
- type: numbered
- - file: content/03-spheres.md
- type: numbered
- - file: content/04-conclusion.md
- type: structural
- title: Заключение
- - file: content/05-bibliography.md
- type: bibliography
- - file: content/06-appendix-a.md
- type: appendix
- letter: А
- title: Сводная таблица применения метода
diff --git a/docx/content/01-introduction.md b/docx/content/01-introduction.md
deleted file mode 100644
index 9737791..0000000
--- a/docx/content/01-introduction.md
+++ /dev/null
@@ -1,41 +0,0 @@
-Объектом исследования выступает процесс выведения нового товара на рынок,
-предметом — выбор метода реализации проекта по выводу новинки и его обоснование
-в различных сферах деятельности.
-
-Актуальность работы обусловлена тем, что запуск нового товара сопровождается
-высоким риском: значительная доля новинок не достигает устойчивых продаж, а
-неудачный запуск приводит к прямым убыткам, потерям доли рынка и подрыву доверия
-к бренду. По разным оценкам, до семи из десяти новых товаров уходят с рынка в
-первые годы после появления, поэтому цена ошибки при выводе новинки особенно
-велика [@1], [@2]. В этих условиях выбор управляемого и повторяемого метода
-вывода товара на рынок становится практически значимой задачей: он позволяет
-снизить неопределённость, распределить ресурсы проекта и своевременно отказаться
-от бесперспективного направления [@7].
-
-Под новым товаром в работе понимается продукт, услуга или их значимая
-модификация, ранее не предлагавшиеся компанией целевой аудитории. Выведение
-такого товара на рынок охватывает исследование спроса, разработку предложения,
-его продвижение и получение обратной связи от клиентов. Именно комплексность
-этих этапов и их взаимное влияние порождают основные риски: чем позже компания
-узнаёт реакцию рынка, тем дороже исправлять допущенные ошибки [@5], [@7].
-
-Целью работы является выбор метода реализации проекта по выведению нового товара
-на рынок и обоснование его применимости в десяти сферах деятельности. Для
-достижения цели необходимо решить следующие задачи:
-
-- изучить классические и гибкие методы выведения товара на рынок и их основные
- ограничения;
-- обосновать выбор метода Agile/Scrum применительно к запуску новинки;
-- описать роли, артефакты и события выбранной методологии;
-- раскрыть механизм проверки спроса через спринты и инкременты;
-- обосновать применимость метода в производстве, связи, на транспорте, в
- строительстве, коммерческой деятельности, юридических услугах, организации
- праздников, бытовых услугах, IT-услугах и банковской сфере;
-- сформулировать выводы об универсальности выбранного метода и условиях его
- эффективного применения.
-
-При выполнении работы использованы методы системного анализа, сравнительного
-анализа методов управления проектами, проектного моделирования и обобщения
-практики [@3], [@4]. Структура работы соответствует поставленным задачам: первый
-раздел посвящён обоснованию выбора метода, второй — его проверке в десяти сферах
-деятельности, заключение содержит основные результаты и выводы.
diff --git a/docx/content/02-method.md b/docx/content/02-method.md
deleted file mode 100644
index 93622ab..0000000
--- a/docx/content/02-method.md
+++ /dev/null
@@ -1,154 +0,0 @@
-# ВЫБОР МЕТОДА ВЫВЕДЕНИЯ НОВОГО ТОВАРА НА РЫНОК
-
-В разделе рассматриваются основные методы реализации проекта по выведению нового
-товара на рынок, формулируются критерии их сравнения и обосновывается выбор
-методологии Agile/Scrum [@1], [@5].
-
-## Обзор методов выведения товара на рынок
-
-В практике управления проектами сложились как классические, так и гибкие методы
-вывода новинки на рынок. Классические подходы (Waterfall, Stage-Gate) строятся на
-последовательном прохождении этапов и предполагают, что требования известны
-заранее, а результат оценивается на завершающей стадии. Гибкие подходы
-(Design Thinking, Lean Startup, Agile/Scrum) переносят проверку спроса внутрь
-процесса и позволяют уточнять требования по мере получения отклика рынка. Краткая
-характеристика методов приведена в таблице @tbl:methods.
-
-::: table "Сравнение методов выведения товара на рынок" id=methods
-| Метод | Сущность | Основное ограничение |
-|---|---|---|
-| Waterfall (водопад) | последовательные этапы от идеи до запуска | поздняя обратная связь рынка |
-| Stage-Gate | этапы с контрольными «воротами» go/kill | высокая стоимость стадии |
-| Design Thinking | старт от потребности клиента, прототип и тест | не задаёт процесс управления |
-| Lean Startup | минимальный продукт (MVP) и цикл «создать — измерить — научиться» | требует зрелой аналитики |
-| Agile/Scrum | короткие итерации — спринты, готовый инкремент | нужна дисциплина команды |
-| 4P (маркетинг-микс) | проработка товара, цены, каналов, продвижения | не покрывает разработку |
-:::
-
-Сравнение методов проводится по четырём критериям: скорость получения обратной
-связи, способность реагировать на изменения, стоимость проверки спроса и
-прозрачность управления. Как видно из таблицы @tbl:methods, классические методы
-предполагают длительный цикл и получают обратную связь рынка лишь на финальной
-стадии. Для запуска нового товара, спрос на который ещё не подтверждён, это
-создаёт повышенный риск: к моменту первых продаж значительная часть ресурсов уже
-израсходована, а изменение требований требует дорогостоящей переработки.
-Наиболее подходящим признан гибкий подход Agile и его методология Scrum [@2],
-[@6]. Ключевые различия классического и гибкого подходов сведены в таблице
-@tbl:compare.
-
-::: table "Сравнение классического и гибкого подходов" id=compare
-| Критерий | Waterfall | Agile/Scrum |
-|---|---|---|
-| Обратная связь рынка | в конце проекта | в каждом спринте |
-| Реакция на изменения | низкая | высокая |
-| Готовый продукт | к концу проекта | в конце каждого спринта |
-| Стоимость проверки спроса | высокая | низкая (пилотный инкремент) |
-| Требования | фиксируются заранее | уточняются итеративно |
-| Риск неудачного запуска | высокий | снижается поэтапно |
-:::
-
-## Сущность методологии Agile/Scrum
-
-Agile — это гибкий подход к управлению проектами, закреплённый в «Манифесте
-гибкой разработки» 2001 года. Манифест ставит в приоритет людей и взаимодействие
-над процессами и инструментами, работающий продукт над исчерпывающей
-документацией, сотрудничество с заказчиком над согласованием условий и готовность
-к изменениям над следованиям первоначальному плану [@1]. На этих ценностях
-строятся двенадцать принципов, важнейшими из которых для вывода нового товара
-являются ранняя и частая поставка ценности, неразрывная работа бизнеса и
-исполнителей и постоянная адаптация к меняющимся условиям рынка.
-
-Scrum — наиболее распространённая методология Agile: работа разбивается на
-короткие итерации — спринты длительностью от одной до четырёх недель, каждая из
-которых завершается готовым приростом продукта (инкрементом) [@2], [@3]. В основе
-Scrum лежат три идеи: прозрачность (все участники видят состояние работы),
-инспекция (результат регулярно проверяется) и адаптация (процесс меняется по
-результатам проверки). Такой цикл «планирование — работа — проверка — улучшение»
-позволяет проверять спрос небольшими порциями и снижать стоимость ошибки, что
-особенно важно при запуске товара на непроверенном рынке [@3], [@4].
-
-## Роли, артефакты и события Scrum
-
-Методология Scrum опирается на три роли, три артефакта и четыре события. Роли
-отвечают за постановку целей и организацию работы, артефакты фиксируют требования
-и прогресс, а события задают ритм и обеспечивают регулярную обратную связь. Роли
-и артефакты приведены в таблице @tbl:scrum.
-
-::: table "Роли и артефакты методологии Scrum" id=scrum
-| Элемент | Назначение |
-|---|---|
-| Product Owner | отвечает за ценность товара и ведёт Product Backlog |
-| Scrum Master | убирает препятствия, следит за процессом |
-| Команда разработки | 5–9 специалистов, создающих продукт |
-| Product Backlog | перечень всех требований к новому товару |
-| Sprint Backlog | план работ текущего спринта |
-| Increment | готовый к показу прирост продукта |
-:::
-
-Product Owner формирует и упорядочивает Product Backlog по ценности, принимает
-результат спринта и представляет интересы заказчика. Scrum Master отвечает за
-соблюдение правил методологии, помогает команде убирать препятствия и защищает
-спринт от незапланированных работ. Команда разработки — самоорганизующаяся
-группа из пяти–девяти специалистов, которая самостоятельно определяет, сколько
-задач войдёт в спринт, и отвечает за качество инкремента. Каждый артефакт имеет
-своё назначение: Product Backlog хранит все требования к товару, Sprint Backlog —
-план текущей итерации, а Increment — готовую к показу часть продукта. Единое
-понимание готовности фиксируется в критериях Definition of Done, что делает
-результат спринта проверяемым.
-
-Цикл работы методологии при выводе товара на рынок приведён на рисунке
-@fig:scrum-cycle.
-
-::: figure "Цикл Scrum при выводе нового товара на рынок" id=scrum-cycle file=images/scrum-cycle.puml
-а) Product Backlog фиксирует требования к товару;
-б) спринт завершается инкрементом;
-в) Sprint Review даёт обратную связь рынка;
-г) по результатам Review выполняется следующий спринт или масштабирование.
-:::
-
-События Scrum задают ритм работы и обеспечивают инспекцию результата. Sprint
-Planning открывает спринт и определяет его цель и состав работ. Daily Scrum —
-короткая ежедневная встреча для синхронизации команды и выявления препятствий.
-Sprint Review завершает спринт демонстрацией инкремента заказчику и рынку, а
-Sprint Retrospective позволяет команде улучшить собственный процесс. Поскольку
-каждый спринт заканчивается инкрементом, рынок получает способ проверить товар
-до полного запуска производства и масштабных вложений.
-
-Результативность спринта оценивается по величине созданного инкремента и
-получаемому эффекту. Скорость команды — суммарный объём задач, выполненных за
-итерацию, — позволяет прогнозировать сроки вывода товара, а ожидаемый эффект
-инкремента помогает сравнивать ценность планируемых улучшений с затратами на
-спринт. Ожидаемый эффект рассчитывается по формуле @eq:effect.
-
-::: formula id=effect
-E = C * V - Z
-:::
-
-::: where
-E — ожидаемый эффект спринта;
-C — ценность инкремента для клиента;
-V — вероятность подтверждения спроса;
-Z — затраты на проведение спринта.
-:::
-
-Положительный ожидаемый эффект служит основанием для развития товара, а
-отрицательный — для корректировки состава требований. Такой расчёт делает
-решение о продолжении или изменении проекта более обоснованным [@5].
-
-## Обоснование выбора Scrum
-
-Выбор Scrum определяется рядом преимуществ применительно к выводу нового товара на
-рынок [@3], [@4]:
-
-- рынок проверяется дешёвым инкрементом, а не дорогим запуском «с нуля»;
-- обратная связь собирается в каждом спринте, что снижает риск ошибки;
-- требования уточняются итеративно, поэтому изменения не приводят к переработке
- всего проекта;
-- прозрачность процесса обеспечивается ролями, артефактами и событиями;
-- ранние пилотные продажи формируют выручку ещё до полного запуска;
-- метод не зависит от отрасли и применим там, где есть клиент и обратная связь;
-- скорость команды и результаты спринтов делают план развития измеримым.
-
-Таким образом, Agile/Scrum выбран в качестве метода реализации проекта по
-выведению нового товара на рынок. Его применимость в десяти сферах деятельности
-обоснована в следующем разделе.
diff --git a/docx/content/03-spheres.md b/docx/content/03-spheres.md
deleted file mode 100644
index 3005438..0000000
--- a/docx/content/03-spheres.md
+++ /dev/null
@@ -1,105 +0,0 @@
-# ОБОСНОВАНИЕ МЕТОДА AGILE/SCRUM В СФЕРАХ ДЕЯТЕЛЬНОСТИ
-
-В разделе обосновывается применимость метода Agile/Scrum в десяти сферах
-деятельности. В каждой сфере рассматривается пример нового товара и показывается,
-как его вывод на рынок организуется через спринты, пилотный инкремент и обратную
-связь [@3], [@6]. Общая логика одинакова для всех сфер: сначала создаётся
-ограниченный пробный продукт, затем замеряется результат, и только после этого
-принимается решение о масштабировании (рисунок @fig:funnel).
-
-::: figure "Воронка вывода нового товара на рынок" id=funnel file=images/product-funnel.puml
-а) спринт 0 уточняет требования и сегмент рынка;
-б) спринты 1–2 создают минимальную версию товара;
-в) спринты 3–4 проверяют спрос на ограниченной аудитории;
-г) начиная со спринта 5 товар масштабируется по подтверждённым метрикам.
-:::
-
-## Производство
-
-Новым товаром выступает линейка упаковки. Вместо единовременного перезапуска всех
-линий выпускается пробная партия на одной линии, которая играет роль инкремента.
-В ходе спринта замеряются себестоимость партии, доля брака и скорость переналадки
-оборудования. Sprint Review с оптовыми покупателями показывает востребованность
-новой упаковки, после чего производство масштабируется на остальные линии, а
-замечания клиентов становятся задачами следующего спринта.
-
-## Связь
-
-Новый товар — тариф «Умный дом». Пилотный спринт запускает тариф для ста
-абонентов, в ходе Sprint Review анализируются подключения, средний чек и отток.
-Обратная связь абонентов позволяет скорректировать состав услуг и условия
-подключения. По результатам обратной связи тариф дорабатывается и выводится на
-массовый рынок без риска массового оттока при неудачной конфигурации.
-
-## Транспорт
-
-Новым товаром является сервис каршеринга мини-фургонов. Пилот реализуется пятью
-машинами в одном районе; метрики загрузки, среднего времени аренды и спроса
-оцениваются в конце спринта. Если загрузка подтверждает спрос, инкремент
-признаётся успешным, и автопарк расширяется за счёт новых районов. Такой подход
-позволяет проверить экономику сервиса до крупных капитальных вложений в технику.
-
-## Строительство
-
-Новый товар — модульные дома. Первый спринт предполагает возведение одного
-пилотного модуля и его показ заказчикам. На Sprint Review фиксируются затраты на
-монтаж, сроки и замечания по проекту, после чего они учитываются в следующем
-инкременте — серийном модуле. Итеративная проверка снижает риск ошибок в типовом
-проекте, который затем тиражируется на серию.
-
-## Коммерческая деятельность
-
-Новым товаром выступает подписка на наборы продуктов. Бокс-пилот на пятидесяти
-клиентах позволяет измерить конверсию, средний чек и удержание. Обратная связь
-покупателей формирует Sprint Backlog для доработки ассортимента и условий
-подписки. Если удержание растёт, объём подписки увеличивается, а состав наборов
-уточняется по отклику клиентов.
-
-## Предоставление юридических услуг
-
-Новый товар — пакет «юрфирма на аутсорсе». Пробный месяц для пяти клиентов даёт
-инкремент услуги; на Sprint Review оцениваются востребованность, трудозатраты и
-повторные обращения. На основе отзывов формируются тарифы и состав пакета.
-Поэтапная проверка позволяет выстроить услугу под реальные ожидания клиентов, не
-вкладываясь сразу в расширение штата юристов.
-
-## Организация праздников
-
-Новым товаром является онлайн-конструктор мероприятий. Один сценарий тестируется
-на пробной группе клиентов; метрики вовлечённости, повторных заказов и средней
-стоимости мероприятия анализируются в конце спринта. Успешный сценарий
-становится основой каталога и автоматизации заказов, а непопулярные сценарии
-исключаются без затрат на массовое продвижение.
-
-## Предоставление бытовых услуг
-
-Новый товар — подписка на уборку. Пилот с двадцатью подписчиками в одном районе
-позволяет измерить удержание, среднее число заказов и загрузку исполнителей. По
-результатам спринта сервис дорабатывается и масштабируется на другие районы.
-Пилотный формат помогает наладить логистику и стандарты качества до выхода на
-городской уровень.
-
-## IT-услуги
-
-Новым товаром выступает модуль SaaS-платформы. Бета-версия для десяти клиентов
-является инкрементом; на Sprint Review собираются метрики использования, частоты
-ошибок и NPS. Обратная связь определяет состав следующего релиза и приоритеты
-доработки. Такой цикл соответствует самой природе гибкой разработки и позволяет
-выпускать ценность небольшими, но регулярными порциями.
-
-## Банковские услуги
-
-Новый товар — вклад «Цель» в мобильном приложении. Тест на ограниченной группе
-пользователей позволяет оценить долю открытий, средний срок и удержание. Даже в
-регулируемой сфере спринты обеспечивают безопасную проверку спроса до полного
-внедрения: пилот проводится в контролируемых условиях, а результат проходит
-согласование с подразделениями банка.
-
-## Обобщение по сферам
-
-Рассмотренные примеры показывают, что различия между сферами касаются в первую
-очередь содержания товара и применяемых метрик, тогда как структура процесса
-остаётся общей. Везде выделяются заказчик, готовый участвовать в проверке
-инкремента, и измеримый результат спринта, на основании которого принимается
-решение о продолжении работы. Именно эта общность позволяет считать Agile/Scrum
-универсальным методом выведения нового товара на рынок [@3], [@6].
diff --git a/docx/content/04-conclusion.md b/docx/content/04-conclusion.md
deleted file mode 100644
index 6f6bbc1..0000000
--- a/docx/content/04-conclusion.md
+++ /dev/null
@@ -1,37 +0,0 @@
-В работе выбран метод реализации проекта по выведению нового товара на рынок и
-обоснована его применимость в десяти сферах деятельности.
-
-В результате сравнительного анализа методов установлено, что классические подходы
-(Waterfall, Stage-Gate) предполагают длительный цикл и позднюю обратную связь
-рынка, что повышает риск запуска новинки. Сравнение по критериям скорости
-обратной связи, реакции на изменения, стоимости проверки спроса и прозрачности
-управления (таблица @tbl:compare) показало, что для непроверенного рынка
-предпочтителен гибкий подход. В качестве метода выбран Agile/Scrum, поскольку он
-проверяет спрос дешёвым инкрементом в каждом спринте и позволяет корректировать
-товар по отклику рынка.
-
-Показано, что методология Scrum опирается на роли (Product Owner, Scrum Master,
-команда разработки), артефакты (Product Backlog, Sprint Backlog, Increment) и
-события (Sprint Planning, Daily Scrum, Sprint Review, Sprint Retrospective), что
-делает процесс прозрачным и управляемым [@2], [@3]. В работе раскрыт механизм
-оценки результативности итераций: ожидаемый эффект спринта рассчитывается по
-формуле @eq:effect, а решение о развитии товара принимается по результатам Sprint
-Review. Такой подход заменяет один дорогой запуск серией последовательных
-проверок и снижает стоимость возможной ошибки.
-
-Обоснована применимость метода в производстве, связи, на транспорте, в
-строительстве, коммерческой деятельности, юридических услугах, организации
-праздников, бытовых услугах, IT-услугах и банковских услугах. В каждой сфере
-вывод товара на рынок строится по единой логике: ограниченный пробный продукт —
-замер результата — масштабирование. Различия касаются содержания товара и набора
-метрик, тогда как структура процесса и роль обратной связи остаются неизменными.
-
-Практическая значимость работы состоит в том, что предложенный метод можно
-применять как типовой алгоритм: выделить сегмент и требования, создать MVP,
-провести пилот, измерить результат и принять решение о масштабировании. Это
-позволяет компании управлять риском запуска новинки и обосновывать вложения
-перед расширением производства или сервиса.
-
-Таким образом, выбранный метод Agile/Scrum является универсальным и позволяет
-снизить риск и стоимость ошибки при выведении нового товара на рынок в различных
-сферах деятельности.
diff --git a/docx/content/05-bibliography.md b/docx/content/05-bibliography.md
deleted file mode 100644
index ead8926..0000000
--- a/docx/content/05-bibliography.md
+++ /dev/null
@@ -1,7 +0,0 @@
-- Манифест гибкой разработки программного обеспечения. — 2001. — URL: https://agilemanifesto.org (дата обращения: 01.10.2026).
-- Schwaber K., Sutherland J. The Scrum Guide: The Definitive Guide to Scrum. — 2020. — URL: https://scrumguides.org (дата обращения: 01.10.2026).
-- Сазерленд Дж. Scrum. Революционный метод управления проектами. — М.: Манн, Иванов и Фербер, 2016. — 288 с.
-- ГОСТ Р 54869-2011. Проектный менеджмент. Требования к управлению проектом. — М.: Стандартинформ, 2011. — 9 с.
-- Cooper R. G. Perspective: The Stage-Gate Idea-to-Launch Process. — Journal of Product Innovation Management, 2008. — Vol. 25. — P. 213–232.
-- Рис Э. Бизнес с нуля. Lean Startup для быстрого тестирования идей. — М.: Альпина Паблишер, 2014. — 253 с.
-- Котлер Ф. Основы маркетинга. Краткий курс. — М.: Вильямс, 2019. — 496 с.
diff --git a/docx/content/06-appendix-a.md b/docx/content/06-appendix-a.md
deleted file mode 100644
index d118f10..0000000
--- a/docx/content/06-appendix-a.md
+++ /dev/null
@@ -1,17 +0,0 @@
-Сводная характеристика применения метода Agile/Scrum в десяти сферах деятельности
-приведена в таблице @tbl:sphere-summary.
-
-::: table "Применение метода Agile/Scrum в сферах деятельности" id=sphere-summary
-| № | Сфера | Новый товар | Пилотный инкремент спринта |
-|---|---|---|---|
-| 1 | Производство | новая линейка упаковки | пробная партия на одной линии |
-| 2 | Связь | тариф «Умный дом» | пилот на 100 абонентов |
-| 3 | Транспорт | каршеринг мини-фургонов | пять машин в одном районе |
-| 4 | Строительство | модульные дома | один пилотный модуль |
-| 5 | Коммерческая деятельность | подписка на наборы продуктов | бокс-пилот на 50 клиентов |
-| 6 | Юридические услуги | пакет «юрфирма на аутсорсе» | пробный месяц для 5 клиентов |
-| 7 | Организация праздников | онлайн-конструктор мероприятий | один сценарий на пробной группе |
-| 8 | Бытовые услуги | подписка на уборку | 20 подписчиков в одном районе |
-| 9 | IT-услуги | модуль SaaS-платформы | бета на 10 клиентов |
-| 10 | Банковские услуги | вклад «Цель» в приложении | тест на группе пользователей |
-:::
diff --git a/docx/content/assets/images/product-funnel.puml b/docx/content/assets/images/product-funnel.puml
deleted file mode 100644
index 8d70ad1..0000000
--- a/docx/content/assets/images/product-funnel.puml
+++ /dev/null
@@ -1,19 +0,0 @@
-@startuml
-skinparam defaultFontName "Times New Roman"
-skinparam defaultFontSize 13
-skinparam shadowing false
-skinparam ArrowColor #1B87C9
-skinparam rectangleBorderColor #1B87C9
-skinparam rectangleBackgroundColor #EAF4FB
-
-title Воронка вывода нового товара на рынок
-
-rectangle "Идея и исследование рынка\nСпринт 0" as A
-rectangle "MVP — минимальный товар\nСпринты 1–2" as B
-rectangle "Пилот на ограниченной аудитории\nСпринты 3–4" as C
-rectangle "Масштабирование товара\nСпринты 5 и далее" as D
-
-A --> B : спрос подтверждён
-B --> C : инкремент принят
-C --> D : метрики достигнуты
-@enduml
diff --git a/docx/content/assets/images/scrum-cycle.puml b/docx/content/assets/images/scrum-cycle.puml
deleted file mode 100644
index 0791e3e..0000000
--- a/docx/content/assets/images/scrum-cycle.puml
+++ /dev/null
@@ -1,26 +0,0 @@
-@startuml
-skinparam defaultFontName "Times New Roman"
-skinparam defaultFontSize 13
-skinparam shadowing false
-skinparam ArrowColor #1B87C9
-skinparam rectangleBorderColor #1B87C9
-skinparam rectangleBackgroundColor #EAF4FB
-
-title Цикл Scrum при выводе нового товара на рынок
-
-rectangle "Product Backlog — требования к товару" as PB
-rectangle "Sprint Planning" as SP
-rectangle "Спринт 1–4 недели" as S
-rectangle "Increment — пробный продукт" as I
-rectangle "Sprint Review — обратная связь рынка" as R
-rectangle "Sprint Retrospective" as RET
-rectangle "Масштабирование товара" as M
-
-PB --> SP
-SP --> S
-S --> I
-I --> R
-R --> RET
-RET --> SP : следующий спринт
-R --> M : спрос подтверждён
-@enduml
diff --git a/docx/content/assets/title-page.docx b/docx/content/assets/title-page.docx
deleted file mode 100644
index ad44a2c..0000000
Binary files a/docx/content/assets/title-page.docx and /dev/null differ
diff --git a/docx/package-lock.json b/docx/package-lock.json
index 2554eff..3e7b99f 100644
--- a/docx/package-lock.json
+++ b/docx/package-lock.json
@@ -1,11 +1,11 @@
{
- "name": "docxgenerator",
+ "name": "ssau-generator-docx",
"version": "2.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "docxgenerator",
+ "name": "ssau-generator-docx",
"version": "2.0.0",
"dependencies": {
"docx": "^9.5.0",
@@ -15,640 +15,7 @@
"markdown-it": "^14.1.0"
},
"bin": {
- "docxgenerator": "src/cli.js"
- },
- "devDependencies": {
- "@yao-pkg/pkg": "^6.23.0"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
- "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.29.7",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.1.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/generator": {
- "version": "7.29.8",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz",
- "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.29.8",
- "@babel/types": "^7.29.8",
- "@jridgewell/gen-mapping": "^0.3.12",
- "@jridgewell/trace-mapping": "^0.3.28",
- "jsesc": "^3.0.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-globals": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
- "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
- "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
- "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.29.9",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz",
- "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.29.8"
- },
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
- "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.7",
- "@babel/parser": "^7.29.7",
- "@babel/types": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.29.8",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz",
- "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.7",
- "@babel/generator": "^7.29.8",
- "@babel/helper-globals": "^7.29.7",
- "@babel/parser": "^7.29.8",
- "@babel/template": "^7.29.7",
- "@babel/types": "^7.29.8",
- "debug": "^4.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/types": {
- "version": "7.29.8",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
- "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.29.7",
- "@babel/helper-validator-identifier": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",
- "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz",
- "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz",
- "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz",
- "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz",
- "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz",
- "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz",
- "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz",
- "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz",
- "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz",
- "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz",
- "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz",
- "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz",
- "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz",
- "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz",
- "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz",
- "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",
- "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz",
- "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz",
- "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz",
- "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz",
- "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openharmony-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz",
- "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz",
- "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz",
- "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz",
- "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz",
- "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@isaacs/fs-minipass": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
- "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "minipass": "^7.0.4"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.13",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
- "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
- "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.31",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
- "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@roberts_lando/vfs": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/@roberts_lando/vfs/-/vfs-0.3.3.tgz",
- "integrity": "sha512-YjkxVSLw5WMZQoARaryRAjcxA+GbBzWMJdwYZX5oLUt9cC/gew9as4Dn7tcLzPp7BPoR221VpTZ+78TRPawnjg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 22"
+ "ssau-generator-docx": "src/cli.js"
}
},
"node_modules/@types/node": {
@@ -660,382 +27,18 @@
"undici-types": ">=7.24.0 <7.24.7"
}
},
- "node_modules/@yao-pkg/pkg": {
- "version": "6.23.0",
- "resolved": "https://registry.npmjs.org/@yao-pkg/pkg/-/pkg-6.23.0.tgz",
- "integrity": "sha512-+d8iqRcmDxPpTE5fbSmsn1rShktIKvMcQGcFhwLdH15A4g2fBcRVLXppeQmu9fbF98bhYXjCOj6UTf3odXxWiA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/generator": "^7.23.0",
- "@babel/parser": "^7.23.0",
- "@babel/traverse": "^7.23.0",
- "@babel/types": "^7.23.0",
- "@roberts_lando/vfs": "^0.3.3",
- "@yao-pkg/pkg-fetch": "3.6.6",
- "esbuild": "^0.28.1",
- "into-stream": "^9.1.0",
- "multistream": "^4.1.0",
- "picocolors": "^1.1.0",
- "picomatch": "^4.0.2",
- "postject": "^1.0.0-alpha.6",
- "prebuild-install": "^7.1.1",
- "resolve": "^1.22.10",
- "resolve.exports": "^2.0.3",
- "stream-meter": "^1.0.4",
- "tar": "^7.5.7",
- "tinyglobby": "^0.2.11",
- "unzipper": "^0.12.3"
- },
- "bin": {
- "pkg": "lib-es5/bin.js"
- },
- "engines": {
- "node": ">=22.0.0"
- }
- },
- "node_modules/@yao-pkg/pkg-fetch": {
- "version": "3.6.6",
- "resolved": "https://registry.npmjs.org/@yao-pkg/pkg-fetch/-/pkg-fetch-3.6.6.tgz",
- "integrity": "sha512-Nu9ytHewcV6FuH4WvdpYZxz2XwiP2p30jlPBzbvwsS3OPYN7RRTyGrXhcmhS59O3AdXz/LW+4bozhV3alN+MEA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "picocolors": "^1.1.0",
- "progress": "^2.0.3",
- "semver": "^7.3.5",
- "tar-fs": "^3.1.1",
- "undici": "^7.28.0",
- "yargs": "^16.2.0"
- },
- "bin": {
- "pkg-fetch": "lib-es5/bin.js"
- }
- },
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"license": "Python-2.0"
},
- "node_modules/b4a": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.9.0.tgz",
- "integrity": "sha512-dpfcF9fDNR6++cthXR67iyhgqWy9CBouAvIWhIntzBG6cvK/cnIPiZQjBwi/ZqjjBEDGfoNDtmB0kTjroOJ3pQ==",
- "dev": true,
- "license": "Apache-2.0",
- "peerDependencies": {
- "react-native-b4a": "*"
- },
- "peerDependenciesMeta": {
- "react-native-b4a": {
- "optional": true
- }
- }
- },
- "node_modules/bare-events": {
- "version": "2.9.2",
- "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.9.2.tgz",
- "integrity": "sha512-AIPKioV7/Y/8KfZ3AAhjPJxLLbY49S64Ym5DakZlUg75qQiTgUq9hEJoEwa4eUezPUlXRy/i5NpsKvo9jgKmoA==",
- "dev": true,
- "license": "Apache-2.0",
- "peerDependencies": {
- "bare-abort-controller": "*"
- },
- "peerDependenciesMeta": {
- "bare-abort-controller": {
- "optional": true
- }
- }
- },
- "node_modules/bare-fs": {
- "version": "4.8.2",
- "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.8.2.tgz",
- "integrity": "sha512-+ZI68KHMUvosXfKbg/UOHK0tbCdRnegbvPEdEcZ3Nd6TetieQsJPRXBRXPdLyy8+3VSEbPXtsumTpEtt78xv9w==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "bare-events": "^2.5.4",
- "bare-path": "^3.0.0",
- "bare-stream": "^2.6.4",
- "bare-url": "^2.2.2",
- "fast-fifo": "^1.3.2"
- },
- "engines": {
- "bare": ">=1.28.0"
- },
- "peerDependencies": {
- "bare-buffer": "*"
- },
- "peerDependenciesMeta": {
- "bare-buffer": {
- "optional": true
- }
- }
- },
- "node_modules/bare-path": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.1.2.tgz",
- "integrity": "sha512-ZyKbsuuqK6Ag0K8pX6V5Txq6XeJRvY+wXucnFGRjiyVYP9YWDpIQugk/b+enRYrEYBJaqLzghRQpXPMR7341Nw==",
- "dev": true,
- "license": "Apache-2.0"
- },
- "node_modules/bare-stream": {
- "version": "2.13.4",
- "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.4.tgz",
- "integrity": "sha512-PcrQ8lVLbiJscNm1Kez+Yp4Gy4AHGcN1lzwjvf5NybWen7VvEgUfyfnXYJ2zNqWnzOfCb1Abq6lH8ti0syQszA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "b4a": "^1.8.1",
- "streamx": "^2.25.0",
- "teex": "^1.0.1"
- },
- "peerDependencies": {
- "bare-abort-controller": "*",
- "bare-buffer": "*",
- "bare-events": "*"
- },
- "peerDependenciesMeta": {
- "bare-abort-controller": {
- "optional": true
- },
- "bare-buffer": {
- "optional": true
- },
- "bare-events": {
- "optional": true
- }
- }
- },
- "node_modules/bare-url": {
- "version": "2.5.4",
- "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.5.4.tgz",
- "integrity": "sha512-Gxa7UVWBr0/edU1b+TJhn/AZvMQUj9OGspvYsaTYQrAbZA4BOTZGL3LiZxvD+CeMlDH4juwD84+eTAp/bLYW5g==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "bare-path": "^3.0.0"
- }
- },
- "node_modules/base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/bl": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
- "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "buffer": "^5.5.0",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
- }
- },
- "node_modules/bl/node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/bluebird": {
- "version": "3.7.2",
- "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
- "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/buffer": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
- "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.1.13"
- }
- },
- "node_modules/chownr": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
- "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/cliui": {
- "version": "7.0.4",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
- "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.0",
- "wrap-ansi": "^7.0.0"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/commander": {
- "version": "9.5.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
- "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.20.0 || >=14"
- }
- },
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"license": "MIT"
},
- "node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/decompress-response": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
- "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mimic-response": "^3.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/detect-libc": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
- "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/docx": {
"version": "9.7.1",
"resolved": "https://registry.npmjs.org/docx/-/docx-9.7.1.tgz",
@@ -1072,33 +75,6 @@
"pako": "~1.0.2"
}
},
- "node_modules/duplexer2": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
- "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "readable-stream": "^2.0.2"
- }
- },
- "node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/end-of-stream": {
- "version": "1.4.5",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
- "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "once": "^1.4.0"
- }
- },
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
@@ -1111,169 +87,6 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/esbuild": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
- "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.28.2",
- "@esbuild/android-arm": "0.28.2",
- "@esbuild/android-arm64": "0.28.2",
- "@esbuild/android-x64": "0.28.2",
- "@esbuild/darwin-arm64": "0.28.2",
- "@esbuild/darwin-x64": "0.28.2",
- "@esbuild/freebsd-arm64": "0.28.2",
- "@esbuild/freebsd-x64": "0.28.2",
- "@esbuild/linux-arm": "0.28.2",
- "@esbuild/linux-arm64": "0.28.2",
- "@esbuild/linux-ia32": "0.28.2",
- "@esbuild/linux-loong64": "0.28.2",
- "@esbuild/linux-mips64el": "0.28.2",
- "@esbuild/linux-ppc64": "0.28.2",
- "@esbuild/linux-riscv64": "0.28.2",
- "@esbuild/linux-s390x": "0.28.2",
- "@esbuild/linux-x64": "0.28.2",
- "@esbuild/netbsd-arm64": "0.28.2",
- "@esbuild/netbsd-x64": "0.28.2",
- "@esbuild/openbsd-arm64": "0.28.2",
- "@esbuild/openbsd-x64": "0.28.2",
- "@esbuild/openharmony-arm64": "0.28.2",
- "@esbuild/sunos-x64": "0.28.2",
- "@esbuild/win32-arm64": "0.28.2",
- "@esbuild/win32-ia32": "0.28.2",
- "@esbuild/win32-x64": "0.28.2"
- }
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/events-universal": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz",
- "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "bare-events": "^2.7.0"
- }
- },
- "node_modules/expand-template": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
- "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
- "dev": true,
- "license": "(MIT OR WTFPL)",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/fast-fifo": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
- "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/fs-constants": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
- "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fs-extra": {
- "version": "11.3.1",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz",
- "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=14.14"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
- "node_modules/github-from-package": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
- "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/hash.js": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
@@ -1284,40 +97,6 @@
"minimalistic-assert": "^1.0.1"
}
},
- "node_modules/hasown": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
- "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "BSD-3-Clause"
- },
"node_modules/immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
@@ -1330,65 +109,12 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
- "node_modules/ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/into-stream": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-9.1.0.tgz",
- "integrity": "sha512-DRsRnQrbzdFjaQ1oe4C6/EIUymIOEix1qROEJTF9dbMq+M4Zrm6VaLp6SD/B9IsiEjPZuBSnWWFN+udajugdWA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.17.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.17.0.tgz",
- "integrity": "sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "hasown": "^2.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"license": "MIT"
},
- "node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/js-yaml": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz",
@@ -1411,32 +137,6 @@
"js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/jsesc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
- "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/jsonfile": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz",
- "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
"node_modules/jszip": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
@@ -1510,112 +210,12 @@
"integrity": "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==",
"license": "MIT"
},
- "node_modules/mimic-response": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
- "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
"license": "ISC"
},
- "node_modules/minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/minipass": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
- "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/minizlib": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
- "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "minipass": "^7.1.2"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/mkdirp-classic": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
- "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/multistream": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/multistream/-/multistream-4.1.0.tgz",
- "integrity": "sha512-J1XDiAmmNpRCBfIWJv+n0ymC4ABcf/Pl+5YvC5B/D2f/2+8PtHvCNxMPKiQcZyi922Hq69J2YOpb1pTywfifyw==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "once": "^1.4.0",
- "readable-stream": "^3.6.0"
- }
- },
- "node_modules/multistream/node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/nanoid": {
"version": "5.1.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.11.tgz",
@@ -1634,200 +234,18 @@
"node": "^18 || >=20"
}
},
- "node_modules/napi-build-utils": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
- "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/node-abi": {
- "version": "3.96.0",
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.96.0.tgz",
- "integrity": "sha512-rebQ/lz7i0EkoLzUVSrKRzA69zMkwLp95kKMWoMDkkM00Suxz0D7zEQPwRml5fQum24mj7bPvmlgLAmu2JCiYg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "semver": "^7.3.5"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/node-int64": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
- "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "wrappy": "1"
- }
- },
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
"license": "(MIT AND Zlib)"
},
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/picocolors": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/picomatch": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
- "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/postject": {
- "version": "1.0.0-alpha.6",
- "resolved": "https://registry.npmjs.org/postject/-/postject-1.0.0-alpha.6.tgz",
- "integrity": "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "commander": "^9.4.0"
- },
- "bin": {
- "postject": "dist/cli.js"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/prebuild-install": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
- "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
- "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "detect-libc": "^2.0.0",
- "expand-template": "^2.0.3",
- "github-from-package": "0.0.0",
- "minimist": "^1.2.3",
- "mkdirp-classic": "^0.5.3",
- "napi-build-utils": "^2.0.0",
- "node-abi": "^3.3.0",
- "pump": "^3.0.0",
- "rc": "^1.2.7",
- "simple-get": "^4.0.0",
- "tar-fs": "^2.0.0",
- "tunnel-agent": "^0.6.0"
- },
- "bin": {
- "prebuild-install": "bin.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/prebuild-install/node_modules/chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/prebuild-install/node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/prebuild-install/node_modules/tar-fs": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz",
- "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chownr": "^1.1.1",
- "mkdirp-classic": "^0.5.2",
- "pump": "^3.0.0",
- "tar-stream": "^2.1.4"
- }
- },
- "node_modules/prebuild-install/node_modules/tar-stream": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
- "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "bl": "^4.0.3",
- "end-of-stream": "^1.4.1",
- "fs-constants": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.1.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"license": "MIT"
},
- "node_modules/progress": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
- "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/pump": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
- "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
"node_modules/punycode.js": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
@@ -1837,22 +255,6 @@
"node": ">=6"
}
},
- "node_modules/rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "dev": true,
- "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
- "dependencies": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "bin": {
- "rc": "cli.js"
- }
- },
"node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
@@ -1868,48 +270,6 @@
"util-deprecate": "~1.0.1"
}
},
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/resolve": {
- "version": "1.22.12",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
- "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "is-core-module": "^2.16.1",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/resolve.exports": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
- "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -1925,94 +285,12 @@
"node": ">=11.0.0"
}
},
- "node_modules/semver": {
- "version": "7.8.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
- "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
"license": "MIT"
},
- "node_modules/simple-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
- "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/simple-get": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
- "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "decompress-response": "^6.0.0",
- "once": "^1.3.1",
- "simple-concat": "^1.0.0"
- }
- },
- "node_modules/stream-meter": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/stream-meter/-/stream-meter-1.0.4.tgz",
- "integrity": "sha512-4sOEtrbgFotXwnEuzzsQBYEV1elAeFSO8rSGeTwabuX1RRn/kEq9JVH7I0MRBhKVRR0sJkr0M0QCH7yOLf9fhQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "readable-stream": "^2.1.4"
- }
- },
- "node_modules/streamx": {
- "version": "2.28.1",
- "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.28.1.tgz",
- "integrity": "sha512-zEzXb0s5Cds7tqMH6rhZ05lcJydCWiQPEwiNngVqzsxCc962vLY4Uw+mW7od8kDH258k2Uz/JrOkdIAAhSh9VA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "events-universal": "^1.0.0",
- "fast-fifo": "^1.3.2",
- "text-decoder": "^1.1.0"
- }
- },
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -2022,229 +300,24 @@
"safe-buffer": "~5.1.0"
}
},
- "node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/tar": {
- "version": "7.5.22",
- "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz",
- "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "@isaacs/fs-minipass": "^4.0.0",
- "chownr": "^3.0.0",
- "minipass": "^7.1.2",
- "minizlib": "^3.1.0",
- "yallist": "^5.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tar-fs": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.3.tgz",
- "integrity": "sha512-/hU4AXnIdZu+Gvl1pk0oI5f5HxWsCJRtY2aFaJdk9VvyL48DWU6iU5WAIPG+wIi1YvWA6eTJvIviP/tMAZZNwQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pump": "^3.0.0",
- "tar-stream": "^3.1.5"
- },
- "optionalDependencies": {
- "bare-fs": "^4.0.1",
- "bare-path": "^3.0.0"
- }
- },
- "node_modules/tar-stream": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.2.2.tgz",
- "integrity": "sha512-+8NeqHRjQWH9nYlwo2gamAMImZCVzI4UoEgDpWorBt9OEfppiZn+uSkskzQKPWIZyji/C8fpWO7u69G0DX0tbg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "b4a": "^1.9.0",
- "bare-fs": "^4.8.2",
- "fast-fifo": "^1.3.2",
- "streamx": "^2.28.1"
- }
- },
- "node_modules/teex": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz",
- "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "streamx": "^2.12.5"
- }
- },
- "node_modules/text-decoder": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz",
- "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "b4a": "^1.6.4"
- }
- },
- "node_modules/tinyglobby": {
- "version": "0.2.17",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
- "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fdir": "^6.5.0",
- "picomatch": "^4.0.4"
- },
- "engines": {
- "node": ">=12.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/SuperchupuDev"
- }
- },
- "node_modules/tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/uc.micro": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
"license": "MIT"
},
- "node_modules/undici": {
- "version": "7.30.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-7.30.0.tgz",
- "integrity": "sha512-dkrQXeHSaoamnItlYbmzG0wFYrM0ZwDxCIg0A7aKjTyyhh9svRzCNFEzV+Vm05/yehjCzjDZ31KXfGEjYSztDQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=20.18.1"
- }
- },
"node_modules/undici-types": {
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
"integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
"license": "MIT"
},
- "node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/unzipper": {
- "version": "0.12.5",
- "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.12.5.tgz",
- "integrity": "sha512-tXYOi9R57Uj/2Z25SOs5RRSzq886MBQj2gY8dPL+xl/kv6s6SvByoKfAtvfVeEuhntWDgjd2o9p2lb4TVPAz0A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "bluebird": "~3.7.2",
- "duplexer2": "~0.1.4",
- "fs-extra": "11.3.1",
- "graceful-fs": "^4.2.2",
- "node-int64": "^0.4.0"
- }
- },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT"
},
- "node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/xml": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
@@ -2272,55 +345,6 @@
"engines": {
"node": ">=0.1"
}
- },
- "node_modules/y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yallist": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
- "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/yargs": {
- "version": "16.2.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.2.tgz",
- "integrity": "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cliui": "^7.0.2",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.0",
- "y18n": "^5.0.5",
- "yargs-parser": "^20.2.2"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yargs-parser": {
- "version": "20.2.9",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
- "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
}
}
}
diff --git a/docx/package.json b/docx/package.json
index 9eff14d..358b98e 100644
--- a/docx/package.json
+++ b/docx/package.json
@@ -1,16 +1,16 @@
{
- "name": "docxgenerator",
+ "name": "ssau-generator-docx",
"version": "2.0.0",
"private": true,
- "description": "DocxGenerator — автономный генератор отчётов DOCX из Markdown по СТО 02068410-004-2018",
+ "description": "SSAU Generator DOCX — автономный генератор отчётов DOCX из Markdown по СТО 02068410-004-2018",
"bin": {
- "docxgenerator": "src/cli.js"
+ "ssau-generator-docx": "src/cli.js"
},
"main": "src/index.js",
"scripts": {
"generate": "node src/cli.js",
"check": "node src/cli.js --check",
- "build:exe": "pkg . --targets node24-win-x64 --compress Brotli --output DocxGenerator.exe"
+ "init": "node src/cli.js --init"
},
"dependencies": {
"docx": "^9.5.0",
@@ -18,16 +18,5 @@
"js-yaml": "^4.1.0",
"jszip": "^3.10.1",
"markdown-it": "^14.1.0"
- },
- "devDependencies": {
- "@yao-pkg/pkg": "^6.23.0"
- },
- "pkg": {
- "scripts": [
- "src/**/*.js"
- ],
- "targets": [
- "node24-win-x64"
- ]
}
}
diff --git a/docx/src/cli.js b/docx/src/cli.js
index ad3aa04..2cb1f2e 100644
--- a/docx/src/cli.js
+++ b/docx/src/cli.js
@@ -14,17 +14,17 @@ const { ConfigError } = require('./util/errors');
const VERSION = '2.0.0';
-const HELP = `DocxGenerator ${VERSION} — генератор DOCX из Markdown (СТО 02068410-004-2018)
+const HELP = `SSAU Generator DOCX ${VERSION} — генератор DOCX из Markdown (СТО 02068410-004-2018)
Использование:
- DocxGenerator.exe [опции]
+ node docx/src/cli.js [опции]
Опции:
- --config <путь> Путь к config.yaml (по умолчанию рядом с exe)
- --content Каталог с config.yaml, content/ и assets/ (по умолчанию рядом с exe)
+ --config <путь> Путь к config.yaml (по умолчанию config.yaml в текущем каталоге)
+ --content Каталог проекта: config.yaml, *.md и assets/ (по умолчанию текущий)
--output <путь> Переопределить путь выходного .docx
--check Только проверить конфиг и ссылки, без записи
- --init Создать шаблон config.yaml/content/assets и выйти
+ --init Создать шаблон config.yaml/*.md/assets и выйти
--verbose Подробный вывод
--version Показать версию
--help Показать эту справку
@@ -70,7 +70,7 @@ function parseArgs(argv) {
}
function defaultBaseDir() {
- return process.pkg ? path.dirname(process.execPath) : process.cwd();
+ return process.cwd();
}
async function main() {
@@ -101,7 +101,7 @@ async function main() {
logger.info('Файлы уже существуют, ничего не создано.');
}
logger.info('');
- logger.info('Отредактируйте config.yaml и файлы в content/, затем запустите DocxGenerator.exe снова.');
+ logger.info('Отредактируйте config.yaml и файлы *.md, затем запустите генератор снова.');
return 0;
}
diff --git a/docx/src/config/defaults.js b/docx/src/config/defaults.js
index f4d37af..29283c3 100644
--- a/docx/src/config/defaults.js
+++ b/docx/src/config/defaults.js
@@ -7,12 +7,12 @@
const DEFAULT_CONFIG = {
document: {
output: 'report.docx',
- titlePage: 'content/assets/title-page.docx',
+ titlePage: 'assets/title-page.docx',
features: { updateFields: true },
},
paths: {
- assets: 'content/assets',
+ assets: 'assets',
},
page: {
@@ -28,6 +28,7 @@ const DEFAULT_CONFIG = {
sizeSmall: 24,
lineSpacing: 1.5,
indentFirst: 709,
+ language: 'ru-RU',
color: '000000',
useBold: false,
allowEmphasis: false,
@@ -111,19 +112,19 @@ const DEFAULT_CONFIG = {
sections: [
{ type: 'toc' },
- { file: 'content/01-introduction.md', type: 'structural', title: 'Введение' },
- { file: 'content/02-analysis.md', type: 'numbered' },
- { file: 'content/03-design.md', type: 'numbered' },
- { file: 'content/04-conclusion.md', type: 'structural', title: 'Заключение' },
- { file: 'content/05-bibliography.md', type: 'bibliography' },
+ { file: '01-introduction.md', type: 'structural', title: 'Введение' },
+ { file: '02-analysis.md', type: 'numbered' },
+ { file: '03-design.md', type: 'numbered' },
+ { file: '04-conclusion.md', type: 'structural', title: 'Заключение' },
+ { file: '05-bibliography.md', type: 'bibliography' },
{
- file: 'content/06-appendix-a.md',
+ file: '06-appendix-a.md',
type: 'appendix',
letter: 'А',
title: 'Сводные таблицы',
},
{
- file: 'content/07-appendix-b.md',
+ file: '07-appendix-b.md',
type: 'appendix',
letter: 'Б',
title: 'Вспомогательные материалы',
diff --git a/docx/src/config/template.js b/docx/src/config/template.js
index f77b280..c9e0af8 100644
--- a/docx/src/config/template.js
+++ b/docx/src/config/template.js
@@ -8,21 +8,53 @@ const { DEFAULT_CONFIG } = require('./defaults');
const { diagramPng, chartPng } = require('../util/png');
const { buildSampleTitlePage } = require('../render/sample-titlepage');
-const CONFIG_HEADER = `# Конфигурация генератора DocxGenerator.
+const CONFIG_HEADER = `# Конфигурация генератора SSAU Generator DOCX.
# Все относительные пути считаются от каталога этого файла.
# Любой ключ можно опустить — будет использовано значение по умолчанию.
`;
-function defaultConfigYaml() {
+/** Каталог генератора внутри проекта (docx/ или pptx/). */
+function isGeneratorDir(baseDir) {
+ const base = path.basename(baseDir).toLowerCase();
+ return base === 'docx' || base === 'pptx';
+}
+
+/**
+ * Раскладка проекта: имя проекта = имя папки проекта, общие ресурсы в
+ * content/<проект>/assets/, результат — content/<проект>/<проект>.docx.
+ */
+function projectLayout(baseDir) {
+ const isSub = isGeneratorDir(baseDir);
+ const projectDir = isSub ? path.dirname(baseDir) : baseDir;
+ const projectName = path.basename(projectDir) || 'project';
+ return {
+ projectDir,
+ projectName,
+ assetsRel: isSub ? '../assets' : 'assets',
+ assetsDir: path.join(projectDir, 'assets'),
+ outputRel: isSub ? `../${projectName}.docx` : `${projectName}.docx`,
+ };
+}
+
+function defaultConfigYaml(layout) {
+ const config = {
+ ...DEFAULT_CONFIG,
+ document: {
+ ...DEFAULT_CONFIG.document,
+ output: layout.outputRel,
+ titlePage: `${layout.assetsRel}/title-page.docx`,
+ },
+ paths: { assets: layout.assetsRel },
+ };
return (
CONFIG_HEADER +
- yaml.dump(DEFAULT_CONFIG, { noRefs: true, lineWidth: -1, sortKeys: false })
+ yaml.dump(config, { noRefs: true, lineWidth: -1, sortKeys: false })
);
}
const SAMPLE = {
- 'content/01-introduction.md': `Целью работы является разработка информационной системы учёта
+ '01-introduction.md': `Целью работы является разработка информационной системы учёта
заявок для отдела технической поддержки. Актуальность темы обусловлена ростом числа обращений и
необходимостью их оперативной обработки [@1].
@@ -38,7 +70,7 @@ const SAMPLE = {
действующими стандартами [@3], [@4].
`,
- 'content/02-analysis.md': `# АНАЛИЗ ПРЕДМЕТНОЙ ОБЛАСТИ
+ '02-analysis.md': `# АНАЛИЗ ПРЕДМЕТНОЙ ОБЛАСТИ
Раздел посвящён анализу процесса обработки обращений и обоснованию требований к информационной
системе. Рассматриваются участники процесса, информационные потоки и ограничения предметной
@@ -147,7 +179,7 @@ T_new — среднее время обработки заявки после
:::
`,
- 'content/03-design.md': `# ПРОЕКТИРОВАНИЕ ИНФОРМАЦИОННОЙ СИСТЕМЫ
+ '03-design.md': `# ПРОЕКТИРОВАНИЕ ИНФОРМАЦИОННОЙ СИСТЕМЫ
В разделе описаны архитектура, модель данных и пользовательские сценарии разрабатываемой
информационной системы.
@@ -275,7 +307,7 @@ N — число обращений в месяц.
:::
`,
- 'content/04-conclusion.md': `В ходе работы проанализирована предметная область, спроектирована архитектура информационной
+ '04-conclusion.md': `В ходе работы проанализирована предметная область, спроектирована архитектура информационной
системы и определены показатели эффективности [@6], [@7].
Основные результаты работы:
@@ -289,7 +321,7 @@ N — число обращений в месяц.
соответствии с действующим стандартом [@8].
`,
- 'content/05-bibliography.md': `- ГОСТ 7.32-2017. Система стандартов по информации, библиотечному и издательскому делу. Отчёт о научно-исследовательской работе. Структура и правила оформления. — М. : Стандартинформ, 2017. — 32 с.
+ '05-bibliography.md': `- ГОСТ 7.32-2017. Система стандартов по информации, библиотечному и издательскому делу. Отчёт о научно-исследовательской работе. Структура и правила оформления. — М. : Стандартинформ, 2017. — 32 с.
- ГОСТ Р 7.0.5-2008. Библиографическая ссылка. Общие требования и правила составления. — М. : Стандартинформ, 2008. — 23 с.
- Иванов, И. И. Управление ИТ-сервисами : учебное пособие / И. И. Иванов. — Самара : Изд-во Самарского университета, 2019. — 184 с.
- Петров, П. П. Обзор систем Service Desk / П. П. Петров // Информационные технологии. — 2020. — № 4. — С. 25–33.
@@ -299,7 +331,7 @@ N — число обращений в месяц.
- ГОСТ 8.417-2002. Государственная система обеспечения единства измерений. Единицы величин. — М. : Стандартинформ, 2002. — 32 с.
`,
- 'content/06-appendix-a.md': `Сводные данные по обращениям за отчётный период приведены в таблице @tbl:app-a1.
+ '06-appendix-a.md': `Сводные данные по обращениям за отчётный период приведены в таблице @tbl:app-a1.
::: table "Сводные данные по обращениям" id=app-a1
| Номер | Дата регистрации | Категория | Приоритет | Исполнитель | Статус | Время, мин |
@@ -339,7 +371,7 @@ N — число обращений в месяц.
:::
`,
- 'content/07-appendix-b.md': `Схема размещения компонентов системы приведена на рисунке @fig:app-b1.
+ '07-appendix-b.md': `Схема размещения компонентов системы приведена на рисунке @fig:app-b1.
::: figure "Схема размещения компонентов" id=app-b1 file=images/appendix-scheme.png
а) узлы развёртывания;
@@ -361,29 +393,22 @@ N — число обращений в месяц.
};
const IMAGES = {
- 'content/assets/images/architecture.png': () => diagramPng(900, 420, [46, 94, 170]),
- 'content/assets/images/data-flow.png': () => diagramPng(900, 380, [28, 140, 96]),
- 'content/assets/images/interface.png': () => diagramPng(820, 480, [196, 120, 32]),
- 'content/assets/images/chart.png': () => chartPng(820, 420, [122, 70, 190]),
- 'content/assets/images/appendix-scheme.png': () => diagramPng(900, 520, [176, 48, 64]),
+ 'images/architecture.png': () => diagramPng(900, 420, [46, 94, 170]),
+ 'images/data-flow.png': () => diagramPng(900, 380, [28, 140, 96]),
+ 'images/interface.png': () => diagramPng(820, 480, [196, 120, 32]),
+ 'images/chart.png': () => chartPng(820, 420, [122, 70, 190]),
+ 'images/appendix-scheme.png': () => diagramPng(900, 520, [176, 48, 64]),
};
-function scaffoldFiles() {
- const files = { 'config.yaml': defaultConfigYaml() };
- for (const [name, content] of Object.entries(SAMPLE)) files[name] = content;
- for (const [name, make] of Object.entries(IMAGES)) {
- files[name] = { binary: make() };
- }
- return files;
-}
-
-/** Создаёт config.yaml, примеры content/ и ассеты, если их ещё нет. */
+/**
+ * Создаёт config.yaml, примеры Markdown и общие ресурсы проекта
+ * (content/<проект>/assets/), если их ещё нет.
+ */
async function ensureScaffold(baseDir) {
- const files = scaffoldFiles();
+ const layout = projectLayout(baseDir);
const created = [];
- for (const [name, content] of Object.entries(files)) {
- const target = path.join(baseDir, name);
- if (fs.existsSync(target)) continue;
+ const write = (target, content) => {
+ if (fs.existsSync(target)) return;
fs.mkdirSync(path.dirname(target), { recursive: true });
if (content && typeof content === 'object' && content.binary) {
fs.writeFileSync(target, content.binary);
@@ -391,15 +416,17 @@ async function ensureScaffold(baseDir) {
fs.writeFileSync(target, content, 'utf8');
}
created.push(target);
- }
+ };
- const titlePage = path.join(baseDir, 'content', 'assets', 'title-page.docx');
- if (!fs.existsSync(titlePage)) {
- fs.mkdirSync(path.dirname(titlePage), { recursive: true });
- fs.writeFileSync(titlePage, await buildSampleTitlePage());
- created.push(titlePage);
+ write(path.join(baseDir, 'config.yaml'), defaultConfigYaml(layout));
+ for (const [name, content] of Object.entries(SAMPLE)) {
+ write(path.join(baseDir, name), content);
}
+ for (const [name, make] of Object.entries(IMAGES)) {
+ write(path.join(layout.assetsDir, name), { binary: make() });
+ }
+ write(path.join(layout.assetsDir, 'title-page.docx'), await buildSampleTitlePage());
return created;
}
-module.exports = { defaultConfigYaml, scaffoldFiles, ensureScaffold, SAMPLE };
+module.exports = { defaultConfigYaml, projectLayout, ensureScaffold, SAMPLE };
diff --git a/docx/src/config/validate.js b/docx/src/config/validate.js
index 6e94084..6edc91e 100644
--- a/docx/src/config/validate.js
+++ b/docx/src/config/validate.js
@@ -69,6 +69,9 @@ function validateConfig(config) {
if (!(typeof typography.lineSpacing === 'number' && typography.lineSpacing > 0)) {
errors.push('typography.lineSpacing: ожидалось положительное число');
}
+ if (typography.language != null && typeof typography.language !== 'string') {
+ errors.push('typography.language: ожидалась строка (например, ru-RU)');
+ }
for (const [key, value] of Object.entries(page.margins)) {
if (!Number.isInteger(value) || value < 0) {
diff --git a/docx/src/render/document.js b/docx/src/render/document.js
index 3e7f8c8..1ddd63d 100644
--- a/docx/src/render/document.js
+++ b/docx/src/render/document.js
@@ -104,7 +104,14 @@ function renderInline(ctx, inlineToken, state) {
push(textRun(ctx, ' '));
break;
case 'hardbreak':
- push(new TextRun({ break: 1, font: ctx.typography.font, size: ctx.typography.sizeBody }));
+ push(
+ new TextRun({
+ break: 1,
+ font: ctx.typography.font,
+ size: ctx.typography.sizeBody,
+ ...(ctx.typography.language ? { language: { value: ctx.typography.language } } : {}),
+ })
+ );
break;
case 'strong_open':
flags.bold = true;
diff --git a/docx/src/render/primitives.js b/docx/src/render/primitives.js
index d38ed6f..14763de 100644
--- a/docx/src/render/primitives.js
+++ b/docx/src/render/primitives.js
@@ -46,7 +46,7 @@ function alignmentOf(name) {
function textRun(ctx, text, opts = {}) {
const t = ctx.typography;
- return new TextRun({
+ const run = {
text: text == null ? '' : String(text),
font: t.font,
size: opts.size || t.sizeBody,
@@ -54,7 +54,9 @@ function textRun(ctx, text, opts = {}) {
italics: t.allowEmphasis ? Boolean(opts.italics) : false,
subScript: opts.subScript || false,
superScript: opts.superScript || false,
- });
+ };
+ if (t.language) run.language = { value: t.language };
+ return new TextRun(run);
}
function flatten(...blocks) {
@@ -325,7 +327,7 @@ function tableRow(ctx, cells, isHeader = false) {
children: [textRun(ctx, line, { size: t.size })],
spacing: { ...ctx.typography.lineSpacingSingle, before: 0, after: 0 },
alignment: AlignmentType.LEFT,
- indent: {},
+ indent: { left: 0, firstLine: 0, hanging: 0 },
})
),
})
@@ -388,12 +390,22 @@ function parseSimpleFormula(text) {
let last = 0;
let match;
while ((match = re.exec(trimmed)) !== null) {
- if (match.index > last) children.push(new MathRun(trimmed.slice(last, match.index)));
- const run = new MathRun(match[2]);
+ let prefix = trimmed.slice(last, match.index);
+ const token = match[2];
+ // Основание — завершающий идентификатор текста перед оператором.
+ const tail = /^([\s\S]*?)([A-Za-zА-Яа-я0-9]+)$/.exec(prefix);
+ let base = '';
+ if (tail) {
+ base = tail[2];
+ prefix = tail[1];
+ }
+ if (prefix) children.push(new MathRun(prefix));
+ const baseRuns = base ? [new MathRun(base)] : [];
+ const scriptRun = new MathRun(token);
children.push(
match[1] === '_'
- ? new MathSubScript({ children: [run] })
- : new MathSuperScript({ children: [run] })
+ ? new MathSubScript({ children: baseRuns, subScript: [scriptRun] })
+ : new MathSuperScript({ children: baseRuns, superScript: [scriptRun] })
);
last = re.lastIndex;
}
@@ -580,6 +592,7 @@ function pageNumberFooter(ctx) {
children: [PageNumber.CURRENT],
font: ctx.typography.font,
size: ctx.typography.sizeBody,
+ ...(ctx.typography.language ? { language: { value: ctx.typography.language } } : {}),
}),
],
}),
diff --git a/docx/src/render/styles.js b/docx/src/render/styles.js
index da78114..d1a7361 100644
--- a/docx/src/render/styles.js
+++ b/docx/src/render/styles.js
@@ -36,6 +36,7 @@ function buildContext(config) {
lineSpacing,
lineSpacingSingle,
indentFirst: typography.indentFirst,
+ language: typography.language,
},
figureMaxWidthPx:
figure.maxWidth != null
diff --git a/pptx/AGENTS.md b/pptx/AGENTS.md
index 9c97910..8d4b0f3 100644
--- a/pptx/AGENTS.md
+++ b/pptx/AGENTS.md
@@ -1,66 +1,94 @@
-# AGENTS.md — генератор lab-gen-pptx
+# AGENTS.md — работа с презентацией PPTX
-`lab-gen-pptx` собирает презентацию **PPTX** из обычных **Markdown**-файлов по
-шаблону Самарского университета. Поведение задаётся файлом `config.yaml`.
+Генератор `pptx/` собирает презентацию **PPTX** из обычных **Markdown**-файлов по
+шаблону Самарского университета. Этот файл — инструкция агенту по созданию и
+правке конкретной презентации. Поведение задаётся `config.yaml` проекта, менять код
+генератора не нужно.
## 1. Требования
-- Node.js 18+.
+- Node.js 18+, зависимости ставятся командой `npm install` в папке `pptx/`.
- Зависимости: `pptxgenjs`, `js-yaml`.
-- Для директив `::: image` с файлами `.puml` — Java 11+ (берётся из
- `JAVA_HOME`, иначе `java` из PATH) и файл `plantuml.jar` (см. `config.plantuml`).
+- Для директив `::: image` с файлами `.puml` — Java 11+ (из `JAVA_HOME`, иначе
+ `java` из PATH) и файл `plantuml.jar` (см. `config.plantuml`).
-## 2. Состав
+## 2. Раскладка проекта
+
+Проект лежит в `content/<проект>/pptx/` рядом с `config.yaml`:
```
-config.yaml # настройки (тема, тексты, таблицы, список слайдов)
-content/
- slides/*.md # по одному Markdown-файлу на слайд
- assets/ # задники (title-bg.jpeg, content-bg.jpg, final-bg.jpeg),
- # готовые PNG/JPEG и исходники PlantUML (*.puml)
-presentation.pptx # результат сборки (ключ presentation.output)
-.plantuml-cache/ # кэш отрендеренных PlantUML (ключ plantuml.cacheDir)
-src/ # cli.js, config.js, parse.js, render.js, plantuml.js, build.js
+content/<проект>/
+├── assets/ # общие ресурсы проекта (общие с docx)
+│ ├── title-bg.jpeg # задники
+│ ├── content-bg.jpg
+│ ├── final-bg.jpeg
+│ └── images/ # готовые PNG/JPEG и исходники .puml
+└── pptx/
+ ├── config.yaml
+ └── slides/
+ ├── 00-title.md
+ └── 01-*.md
```
-Все относительные пути считаются **от каталога `config.yaml`**.
+Все относительные пути считаются **от каталога `config.yaml`**. Общие с документом
+ресурсы указывайте через `../assets` (например,
+`backgrounds.title: ../assets/title-bg.jpeg`). Каталог контента — ключ
+`content.dir` (по умолчанию `.` — папка самого `config.yaml`).
-Общий `plantuml.jar` монорепозитория лежит в корне, в `tools/plantuml.jar`
-(`plantuml.jar: ../tools/plantuml.jar`). Для автономного дистрибутива положите
-`tools/plantuml.jar` рядом с `config.yaml` и задайте путь `tools/plantuml.jar`.
+Презентация собирается в папку проекта и называется по имени проекта:
+`content/<проект>/<проект>.pptx`. Значение ключа `presentation.output` при такой
+раскладке — `../<проект>.pptx`.
+
+Структуру проекта создавайте командой `--init`: она формирует `config.yaml`,
+примеры слайдов и общий каталог `content/<проект>/assets/` (задники), который
+используется и генератором `docx`.
+
+Готовый пример со всеми возможностями — `content/example/pptx/`.
## 3. Командная строка
+Из корня репозитория:
+
```
-lab-gen-pptx [config.yaml] [опции]
+node pptx/src/cli.js [config.yaml] [опции]
-c, --config путь к config.yaml (по умолчанию config.yaml)
-o, --output переопределить имя выходного файла
--check только проверить конфиг и ссылки
+ --init создать шаблон config.yaml/slides/assets и выйти
-v, --verbose подробный вывод
-h, --help справка
--version версия
```
+Типичный цикл:
+
```powershell
-npm run check
-npm run generate
+node pptx/src/cli.js -c content/<проект>/pptx/config.yaml --init # создать структуру проекта
+node pptx/src/cli.js -c content/<проект>/pptx/config.yaml --check # проверить
+node pptx/src/cli.js -c content/<проект>/pptx/config.yaml # собрать
```
+После любого изменения исходников (`config.yaml`, слайдов, ресурсов `assets/`)
+**пересоберите презентацию**, чтобы результат соответствовал исходникам.
+
+Если `config.yaml` не найден, инструмент сам создаёт шаблон (`config.yaml`,
+примеры слайдов и общий `assets/`) и завершается.
+
## 4. Схема `config.yaml`
| Раздел | Назначение |
|---|---|
| `presentation` | `output`, `author`, `track` |
| `theme` | `width`/`height` (дюймы), `font`, `colors`, `backgrounds`, `slideNumber` |
-| `text` | макеты текста для типов слайдов `titleSlide`, `section`, `content`, `final` |
+| `text` | макеты текста для типов `titleSlide`, `section`, `content`, `final` |
| `table` | размер шрифта, цвета шапки/ячеек/границ |
| `callout` | плашка-вывод: заливка, рамка, цвета и размеры шрифтов |
| `metrics` | карточки-метрики: заливка, цвета, размеры значения и подписи |
-| `flow` | нативная схема-цепочка: заливка, рамка, стрелки, размер |
+| `flow` | схема-цепочка: заливка, рамка, стрелки, размер |
| `chart` | палитра, размер шрифта, легенда, высота диаграммы |
| `plantuml` | рендеринг `*.puml` (см. п. 5) |
-| `content.dir` | каталог контента |
+| `content.dir` | каталог контента (по умолчанию `.`) |
| `slides` | список слайдов: `{ type, file }` |
Типы слайдов: `title`, `section`, `content`, `final`. Каждому типу соответствует
@@ -93,7 +121,7 @@ npm run generate
| 1 | 2 |
:::
-::: image assets/pic.png
+::: image ../assets/images/pic.png
подпись под рисунком
:::
@@ -127,9 +155,9 @@ npm run generate
```
Параметр `side=left|right` ставит плашку в левую или правую колонку слайда.
-Если у слайда есть блоки с `side`, они верстаются в две колонки (левая/правая),
-а остальные блоки — как обычно. Типовое сочетание: `::: image ... side=left`
-и `::: callout ... side=right`.
+Если у слайда есть блоки с `side`, они верстаются в две колонки, а остальные
+блоки — как обычно. Не смешивайте на одном слайде обычный текст и колонки
+(`side`) — они накладываются.
### Директива `::: metrics`
@@ -145,8 +173,7 @@ npm run generate
### Директива `::: flow`
-Нативная схема-цепочка из скруглённых блоков со стрелками. Шаги разделяются
-`->` (или `→`), можно писать по одному на строку:
+Схема-цепочка из скруглённых блоков со стрелками. Шаги разделяются `->` (или `→`):
```md
::: flow
@@ -154,14 +181,14 @@ Sprint Planning -> Спринт -> Sprint Review -> Ретроспектива
:::
```
-Если ширина блока становится малой, схема автоматически разворачивается
+Если блоки становятся слишком узкими, схема автоматически разворачивается
вертикально.
### Директива `::: chart <тип> "Заголовок"`
Диаграмма на основе GFM-таблицы: первая колонка — категории, остальные —
-числовые ряды (заголовки колонок = имена рядов). Поддерживаемые типы:
-`bar`, `bar3d`, `line`, `pie`, `doughnut`, `area`, `radar`, `scatter`.
+числовые ряды (заголовки колонок = имена рядов). Типы: `bar`, `bar3d`, `line`,
+`pie`, `doughnut`, `area`, `radar`, `scatter`.
```md
::: chart doughnut "Новинки, которые не выживают"
@@ -174,38 +201,38 @@ Sprint Planning -> Спринт -> Sprint Review -> Ретроспектива
### Директива `::: image` и PlantUML
-`file` — относительно `content.dir` (`content/`). Если файл оканчивается на
-`.puml` (`.plantuml`, `.pu`, `.iuml`), он рендерится в PNG через `plantuml.jar`
-(см. `config.plantuml`) и вставляется как обычный рисунок:
+`file` — относительно `content.dir`. Если файл оканчивается на `.puml`
+(`.plantuml`, `.pu`, `.iuml`), он рендерится в PNG через `plantuml.jar` и
+вставляется как обычный рисунок:
```md
-::: image assets/scrum-cycle.puml height=3.2
+::: image ../assets/images/scrum-cycle.puml height=3.2
Цикл Scrum: от Product Backlog до масштабирования товара
:::
```
Подпись (строка под директивой) выводится под рисунком курсивом. Растровые
-PNG/JPEG вставляются как есть. Необязательный параметр `height=<дюймы>`
-(`h=`) ограничивает высоту рисунка, чтобы уместить под ним другие блоки;
-пропорции сохраняются, рисунок центрируется. Параметр `side=left|right`
-ставит рисунок в колонку (см. `::: callout`).
+PNG/JPEG вставляются как есть. Параметр `height=<дюймы>` (`h=`) ограничивает
+высоту рисунка (пропорции сохраняются, рисунок центрируется). `side=left|right`
+ставит рисунок в колонку.
## 6. Задники
-Изображения-задники извлечены из `presentation_16.pptx` в
-`content/assets/` (`title-bg.jpeg`, `content-bg.jpg`, `final-bg.jpeg`). При замене
-шаблона положите новые файлы и обновите пути в `theme.backgrounds`.
+Задники лежат в общем каталоге ресурсов проекта
+(`content/<проект>/assets/`: `title-bg.jpeg`, `content-bg.jpg`, `final-bg.jpeg`).
+При замене шаблона положите новые файлы и обновите пути в `theme.backgrounds`.
## 7. Шрифт
-В шаблоне используется фирменный `Elektra Text Pro`, который обычно не установлен
-в системе (иначе Word подставляет случайный шрифт). Поэтому по умолчанию задан
-`Segoe UI` — близкий современный sans. Альтернативы: `Calibri`, `Candara`,
-`Corbel`, `Noto Sans`, `Arial`. Смените `theme.font` при необходимости.
+В исходном шаблоне используется фирменный `Elektra Text Pro`, который обычно не
+установлен в системе. Поэтому по умолчанию задан `Segoe UI` — близкий современный
+sans. Альтернативы: `Calibri`, `Candara`, `Corbel`, `Noto Sans`, `Arial`.
+Смените `theme.font` при необходимости.
## 8. Проверка результата
-Презентацию можно отрендерить для визуальной проверки через LibreOffice:
+`--check` проверяет конфиг и наличие слайдов/ресурсов. Презентацию можно
+отрендерить для визуальной проверки через LibreOffice:
```powershell
soffice --headless --convert-to pdf --outdir . presentation.pptx
diff --git a/pptx/config.yaml b/pptx/config.yaml
deleted file mode 100644
index 31a02df..0000000
--- a/pptx/config.yaml
+++ /dev/null
@@ -1,130 +0,0 @@
-# Конфигурация генератора презентаций lab-gen-pptx.
-# Шаблон: Самарский университет, presentation_16.pptx.
-# Все относительные пути считаются от каталога этого файла.
-
-presentation:
- output: presentation.pptx
- author: "Степанов П.А."
- track: "ДОП 11"
- group: "6403-020302D"
-
-theme:
- width: 13.333
- height: 7.5
- # Шрифт презентации. Elektra Text Pro (фирменный) не установлен в системе,
- # поэтому используется близкий современный sans. Замените при необходимости.
- font: "Segoe UI"
- colors:
- white: "FFFFFF"
- ink: "1F2933"
- brand: "1B87C9"
- muted: "6B7280"
- accent: "0E6BA8"
- tint: "EAF4FB"
- line: "BFD3DD"
- backgrounds:
- title: content/assets/title-bg.jpeg
- content: content/assets/content-bg.jpg
- final: content/assets/final-bg.jpeg
- slideNumber:
- show: true
- x: 12.17
- y: 6.86
- w: 0.5
- h: 0.42
- fontSize: 14
- # color — для тёмных фонов (разделитель), contentColor — для белых (контент)
- color: "FFFFFF"
- contentColor: "FFFFFF"
- bold: true
- align: "center"
-
-text:
- titleSlide:
- title: { x: 6.7, y: 1.85, w: 5.95, h: 1.9, fontSize: 28, align: center, color: white }
- subtitle: { x: 6.7, y: 3.75, w: 5.95, h: 0.7, fontSize: 16, align: center, color: white }
- body: { x: 6.7, y: 4.65, w: 5.95, h: 1.7, fontSize: 14, align: center, color: white }
- section:
- title: { x: 6.4, y: 2.55, w: 6.35, h: 2.4, fontSize: 26, bold: true, align: center, color: white }
- content:
- title: { x: 0.6, y: 0.20, w: 12.15, h: 0.66, fontSize: 24, align: center, color: white, valign: middle }
- body: { x: 0.75, y: 0.98, w: 11.85, h: 5.7, fontSize: 18, align: left, color: ink, valign: top }
- bulletSize: 18
- subBulletSize: 16
- final:
- title: { x: 6.7, y: 2.85, w: 5.95, h: 1.6, fontSize: 28, bold: true, align: center, color: white }
- body: { x: 6.7, y: 4.65, w: 5.95, h: 1.7, fontSize: 14, align: center, color: white }
-
-table:
- fontSize: 14
- headerFill: "1B87C9"
- headerColor: "FFFFFF"
- cellColor: "1F2933"
- borderColor: "BFD3DD"
-
-callout:
- fill: "EAF4FB"
- border: "1B87C9"
- titleColor: "0E6BA8"
- textColor: "1F2933"
- titleFontSize: 18
- fontSize: 15
- lineWidth: 1.25
-
-metrics:
- fill: "1B87C9"
- valueColor: "FFFFFF"
- labelColor: "EAF4FB"
- valueFontSize: 30
- labelFontSize: 13
- gap: 0.2
- height: 1.25
-
-flow:
- fill: "EAF4FB"
- border: "1B87C9"
- textColor: "1F2933"
- arrowColor: "1B87C9"
- fontSize: 13
- height: 1.0
- gap: 0.4
-
-chart:
- palette: ["1B87C9", "7FB2D9", "0E6BA8", "BFD3DD"]
- fontSize: 12
- legend: true
- height: 3.4
-
-# Рендеринг PlantUML (::: image assets/schema.puml).
-# Требуется Java 11+ (берётся из JAVA_HOME, иначе java из PATH) и plantuml.jar.
-# Общий jar монорепозитория лежит в корне: tools/plantuml.jar.
-plantuml:
- enabled: true
- java: auto
- jar: ../tools/plantuml.jar
- format: png
- charset: UTF-8
- cache: true
- cacheDir: .plantuml-cache
- timeoutMs: 30000
-
-content:
- dir: content
-
-slides:
- - { type: title, file: slides/00-title.md }
- - { type: content, file: slides/01-agenda.md }
- - { type: content, file: slides/01-task.md }
- - { type: content, file: slides/02-why-scrum.md }
- - { type: content, file: slides/03-roles.md }
- - { type: content, file: slides/04-events.md }
- - { type: content, file: slides/12-scrum-cycle.md }
- - { type: content, file: slides/05-launch.md }
- - { type: section, file: slides/06-spheres.md }
- - { type: content, file: slides/07a-spheres-1-2.md }
- - { type: content, file: slides/07b-spheres-3-4.md }
- - { type: content, file: slides/07c-spheres-5-6.md }
- - { type: content, file: slides/07d-spheres-7-8.md }
- - { type: content, file: slides/07e-spheres-9-10.md }
- - { type: content, file: slides/10-conclusion.md }
- - { type: final, file: slides/11-final.md }
diff --git a/pptx/content/assets/scrum-cycle.puml b/pptx/content/assets/scrum-cycle.puml
deleted file mode 100644
index cd0600c..0000000
--- a/pptx/content/assets/scrum-cycle.puml
+++ /dev/null
@@ -1,24 +0,0 @@
-@startuml
-skinparam defaultFontName "Times New Roman"
-skinparam defaultFontSize 13
-skinparam shadowing false
-skinparam ArrowColor #1B87C9
-skinparam rectangleBorderColor #1B87C9
-skinparam rectangleBackgroundColor #EAF4FB
-
-rectangle "Product Backlog — требования к товару" as PB
-rectangle "Sprint Planning" as SP
-rectangle "Спринт 1–4 недели" as S
-rectangle "Increment — пробный продукт" as I
-rectangle "Sprint Review — обратная связь рынка" as R
-rectangle "Sprint Retrospective" as RET
-rectangle "Масштабирование товара" as M
-
-PB --> SP
-SP --> S
-S --> I
-I --> R
-R --> RET
-RET --> SP : следующий спринт
-R --> M : спрос подтверждён
-@enduml
diff --git a/pptx/content/slides/00-title.md b/pptx/content/slides/00-title.md
deleted file mode 100644
index f7be6c0..0000000
--- a/pptx/content/slides/00-title.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Современные проектные технологии
-
-## Метод выведения нового товара на рынок: Agile / Scrum
-
-Степанов П.А., группа 6403-020302D
-
-Слушатель программы профессиональной переподготовки «Современные проектные технологии»
-
-ИОТ-трек «ДОП 11»
-
-::: notes
-Добрый день, уважаемые члены итоговой аттестационной комиссии. Меня зовут Степанов П.А., я слушатель программы профессиональной переподготовки «Современные проектные технологии», ИОТ-трек «ДОП 11», группа 6403-020302D. Разрешите представить решение итогового задания по теме «Современные проектные технологии» — метод выведения нового товара на рынок.
-:::
diff --git a/pptx/content/slides/01-agenda.md b/pptx/content/slides/01-agenda.md
deleted file mode 100644
index a968cd7..0000000
--- a/pptx/content/slides/01-agenda.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# План доклада
-
-- ==Метод== выведения нового товара: Agile / Scrum
-- Почему выбран именно Scrum
-- Роли, артефакты и события методологии
-- Как спринты проверяют спрос на рынке
-- Применение в ==десяти сферах== деятельности
-- Выводы и практический результат
-
-::: notes
-Структура доклада. Сначала я обосную выбор метода — Agile и Scrum. Затем покажу, как устроена методология: роли, артефакты и события. Отдельно объясню, как спринты позволяют проверять спрос на рынке. После этого докажу универсальность метода на десяти сферах деятельности: от производства до банковских услуг. В завершение приведу выводы и практический результат.
-:::
diff --git a/pptx/content/slides/01-task.md b/pptx/content/slides/01-task.md
deleted file mode 100644
index f3fd8b6..0000000
--- a/pptx/content/slides/01-task.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Постановка задачи
-
-- Выбрать метод выведения нового товара на рынок
-- Обосновать его применимость в ==десяти сферах== деятельности
-- Показать, как метод работает в каждой сфере
-
-::: metrics
-70% | новых товаров уходят с рынка
-10 | сфер применения метода
-4 | недели — максимальная длина спринта
-:::
-
-::: callout "Проблема и решение"
-Запуск новинки — это **высокий риск**. Нужен управляемый и повторяемый процесс вывода товара — таким процессом является **Agile / Scrum**.
-:::
-
-::: notes
-Задача итогового задания — выбрать метод выведения нового товара на рынок и обосновать его в десяти сферах: от производства до банковских услуг. Запуск новинки всегда сопряжён с риском: до семи из десяти новых товаров не выживают на рынке. Поэтому нужен управляемый и повторяемый процесс, и в качестве такого метода я выбрал Agile и его самую популярную методологию — Scrum.
-:::
diff --git a/pptx/content/slides/02-why-scrum.md b/pptx/content/slides/02-why-scrum.md
deleted file mode 100644
index d68e907..0000000
--- a/pptx/content/slides/02-why-scrum.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Почему выбран Agile / Scrum
-
-- Agile — гибкий подход к управлению проектами, закреплён в ==манифесте 2001 года==
-- Scrum — самая распространённая Agile-методология в мире
-- Работа идёт короткими итерациями — *спринтами* от одной до четырёх недель
-- Каждый спринт даёт готовый прирост продукта — ==инкремент==
-- Обратная связь с рынком собирается на каждом шаге, а не в конце проекта
-
-::: chart doughnut "Новинки, которые не выживают на рынке"
-| Итог | Доля, % |
-|---|---|
-| Успешные новинки | 30 |
-| Уходят с рынка | 70 |
-:::
-
-::: notes
-Почему именно Agile и Scrum. Agile — это гибкий подход к управлению проектами, закреплённый в манифесте 2001 года. Scrum — самая распространённая Agile-методология. Работа разбивается на короткие спринты длиной от одной до четырёх недель. Каждый спринт завершается готовым приростом продукта. Благодаря этому обратная связь с рынком собирается постоянно, а не только в конце. Именно поэтому гибкий подход снижает риск: как показывают оценки, до семи из десяти новинок не выживают при традиционном запуске.
-:::
diff --git a/pptx/content/slides/03-roles.md b/pptx/content/slides/03-roles.md
deleted file mode 100644
index cd9ddcc..0000000
--- a/pptx/content/slides/03-roles.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Scrum: роли и артефакты
-
-- **Product Owner** — отвечает за ценность товара и ведёт Product Backlog
-- **Scrum Master** — убирает препятствия и следит за соблюдением процесса
-- **Команда разработки** — от пяти до девяти специалистов, создающих продукт
-
-::: table
-| Артефакт Scrum | Назначение |
-|---|---|
-| Product Backlog | все требования к новому товару |
-| Sprint Backlog | план работ текущего спринта |
-| Increment | готовый к показу прирост продукта |
-:::
-
-::: callout "Прозрачность"
-Все артефакты видны команде и заказчику, а критерии готовности зафиксированы в ==Definition of Done==.
-:::
-
-::: notes
-В Scrum три роли. Product Owner отвечает за ценность товара и ведёт Product Backlog — список всех требований. Scrum Master убирает препятствия и следит за соблюдением процесса. Команда разработки из пяти–девяти специалистов создаёт продукт. Три артефакта: Product Backlog со всеми требованиями, Sprint Backlog с планом текущего спринта и Increment — готовый прирост продукта. Единое понимание готовности фиксируется в критериях Definition of Done.
-:::
diff --git a/pptx/content/slides/04-events.md b/pptx/content/slides/04-events.md
deleted file mode 100644
index 66d0ee6..0000000
--- a/pptx/content/slides/04-events.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Scrum: события спринта
-
-::: flow
-Sprint Planning -> Спринт -> Sprint Review -> Ретроспектива
-:::
-
-- **Sprint Planning** — планируем, что войдёт в спринт
-- **Daily Scrum** — пятнадцать минут на синхронизацию команды
-- **Sprint Review** — показываем прирост заказчику и рынку
-- **Sprint Retrospective** — улучшаем процесс работы команды
-
-::: callout "Результат спринта"
-Каждый спринт заканчивается рабочим ==инкрементом== — кандидатом на рынок.
-:::
-
-::: notes
-Спринт состоит из четырёх событий. На Sprint Planning команда решает, что войдёт в спринт. Daily Scrum — пятнадцатиминутная синхронизация каждый день. На Sprint Review прирост показывают заказчику и рынку. На Sprint Retrospective команда улучшает свой процесс. Каждый спринт заканчивается рабочим инкрементом, который можно показать рынку. Далее цикл повторяется: планирование, спринт, демонстрация, ретроспектива.
-:::
diff --git a/pptx/content/slides/05-launch.md b/pptx/content/slides/05-launch.md
deleted file mode 100644
index 11ee86a..0000000
--- a/pptx/content/slides/05-launch.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Как Scrum выводит товар на рынок
-
-::: flow
-Спринт 0: исследование -> MVP -> Пилот и метрики -> Масштабирование
-:::
-
-- **Спринт 0** — исследование рынка, выбор сегмента, формирование Product Backlog
-- **Спринты 1–2** — создание MVP: минимальной версии товара для первых клиентов
-- **Спринты 3–4** — пилот на ограниченной аудитории и сбор метрик
-- **Спринт 5 и далее** — доработка по обратной связи и масштабирование
-
-::: callout "Итог"
-Рынок проверяется ==дешёвым инкрементом==, а не дорогим запуском «с нуля».
-:::
-
-::: notes
-Как Scrum выводит товар на рынок. Спринт ноль — исследование рынка и формирование списка требований. Спринты один и два — создание минимального продукта для первых клиентов. Спринты три и четыре — пилот на ограниченной аудитории и сбор метрик. Дальше — доработка по обратной связи и масштабирование. Демонстрация реальным клиентам позволяет проверить спрос до крупных вложений. Итог: рынок проверяется дешёвым инкрементом, а не дорогим запуском с нуля.
-:::
diff --git a/pptx/content/slides/06-spheres.md b/pptx/content/slides/06-spheres.md
deleted file mode 100644
index e34fee5..0000000
--- a/pptx/content/slides/06-spheres.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# Agile / Scrum в десяти сферах деятельности
-
-Обоснование универсальности выбранного метода
-
-::: notes
-Теперь покажу, что метод Agile и Scrum применим не только в IT, но и в десяти различных сферах деятельности.
-:::
diff --git a/pptx/content/slides/07a-spheres-1-2.md b/pptx/content/slides/07a-spheres-1-2.md
deleted file mode 100644
index 56b58d2..0000000
--- a/pptx/content/slides/07a-spheres-1-2.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Сферы 1–2: производство и связь
-
-::: callout "1. Производство — новая линейка упаковки"
-- Новый товар: линейка упаковки для розницы.
-- Пилотный спринт: пробная партия на ==одной линии==.
-- Метрика Sprint Review: себестоимость, доля брака, скорость переналадки.
-- Решение: масштабирование на остальные линии по подтверждённому спросу.
-- Особенность: переналадка одной линии дешевле полного перезапуска.
-:::
-
-::: callout "2. Связь — тариф «Умный дом»"
-- Новый товар: тариф «Умный дом» для абонентов.
-- Пилотный спринт: подключение ==100 абонентов==.
-- Метрика Sprint Review: число подключений, средний чек, отток.
-- Решение: доработка состава услуг и вывод тарифа на массовый рынок.
-- Особенность: пилот ограничен абонентской базой и не грозит массовым оттоком.
-:::
-
-::: notes
-Первые две сферы. В производстве новая линейка упаковки запускается пробной партией на одной линии: замеряют себестоимость, долю брака и скорость переналадки. По результатам Sprint Review производство масштабируется на остальные линии. В связи тариф «Умный дом» тестируется на ста абонентах: анализируют подключения, средний чек и отток, после чего состав услуг уточняется и тариф выводится на массовый рынок. Общая логика: ограниченный пилот, замер метрики, затем масштабирование.
-:::
diff --git a/pptx/content/slides/07b-spheres-3-4.md b/pptx/content/slides/07b-spheres-3-4.md
deleted file mode 100644
index 060080a..0000000
--- a/pptx/content/slides/07b-spheres-3-4.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Сферы 3–4: транспорт и строительство
-
-::: callout "3. Транспорт — каршеринг мини-фургонов"
-- Новый товар: сервис каршеринга мини-фургонов.
-- Пилотный спринт: ==пять машин== в одном районе.
-- Метрика Sprint Review: загрузка, среднее время аренды, спрос.
-- Решение: расширение автопарка и запуск в новых районах.
-- Особенность: экономика сервиса проверяется до закупки техники.
-:::
-
-::: callout "4. Строительство — модульные дома"
-- Новый товар: модульные дома для застройки.
-- Пилотный спринт: возведение ==одного пилотного модуля== и показ заказчикам.
-- Метрика Sprint Review: затраты на монтаж, сроки, замечания.
-- Решение: серийный модуль с учётом правок и тиражирование.
-- Особенность: типовой проект снижает стоимость серии.
-:::
-
-::: notes
-Транспорт и строительство. В транспорте сервис каршеринга мини-фургонов стартует с пяти машин в одном районе: оценивают загрузку, среднее время аренды и спрос. Если экономика подтверждается, автопарк расширяется. В строительстве сначала возводится один пилотный модульный дом и показывается заказчикам: фиксируют затраты, сроки и замечания, после чего серийный модуль тиражируется. Итеративная проверка снижает риск ошибок в типовом проекте.
-:::
diff --git a/pptx/content/slides/07c-spheres-5-6.md b/pptx/content/slides/07c-spheres-5-6.md
deleted file mode 100644
index d076692..0000000
--- a/pptx/content/slides/07c-spheres-5-6.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Сферы 5–6: коммерция и юридические услуги
-
-::: callout "5. Коммерция — подписка на наборы продуктов"
-- Новый товар: подписка на наборы продуктов.
-- Пилотный спринт: бокс-пилот на ==50 клиентах==.
-- Метрика Sprint Review: конверсия, средний чек, удержание.
-- Решение: доработка ассортимента и условий подписки.
-- Особенность: состав набора гибко меняется по спросу.
-:::
-
-::: callout "6. Юридические услуги — пакет «юрфирма на аутсорсе»"
-- Новый товар: пакет «юрфирма на аутсорсе».
-- Пилотный спринт: пробный месяц для ==5 клиентов==.
-- Метрика Sprint Review: востребованность, трудозатраты, повторные обращения.
-- Решение: тарифы и состав пакета формируются по отзывам.
-- Особенность: расширение штата юристов только после подтверждения спроса.
-:::
-
-::: notes
-Коммерция и юридические услуги. В коммерции подписка на продуктовые наборы запускается бокс-пилотом на пятидесяти клиентах: измеряют конверсию, средний чек и удержание, после чего уточняют ассортимент и условия. В юридических услугах пакет «юрфирма на аутсорсе» предлагается пяти клиентам на пробный месяц: оценивают востребованность и трудозатраты. Пилот позволяет выстроить услугу под реальные ожидания клиентов, не вкладываясь сразу в расширение штата.
-:::
diff --git a/pptx/content/slides/07d-spheres-7-8.md b/pptx/content/slides/07d-spheres-7-8.md
deleted file mode 100644
index d498e7f..0000000
--- a/pptx/content/slides/07d-spheres-7-8.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Сферы 7–8: организация праздников и бытовые услуги
-
-::: callout "7. Организация праздников — онлайн-конструктор мероприятий"
-- Новый товар: онлайн-конструктор мероприятий.
-- Пилотный спринт: ==один сценарий== на пробной группе.
-- Метрика Sprint Review: вовлечённость, повторные заказы, средняя стоимость.
-- Решение: каталог успешных сценариев и автоматизация заказов.
-- Особенность: непопулярные сценарии не масштабируются и не продвигаются.
-:::
-
-::: callout "8. Бытовые услуги — подписка на уборку"
-- Новый товар: подписка на уборку.
-- Пилотный спринт: ==20 подписчиков== в одном районе.
-- Метрика Sprint Review: удержание, число заказов, загрузка исполнителей.
-- Решение: стандарты качества и масштабирование на другие районы.
-- Особенность: логистика и качество отрабатываются в пилоте.
-:::
-
-::: notes
-Организация праздников и бытовые услуги. Онлайн-конструктор мероприятий тестируется на одной пробной группе: смотрят вовлечённость, повторные заказы и среднюю стоимость. Успешный сценарий становится основой каталога. Подписка на уборку стартует с двадцати подписчиков в одном районе: измеряют удержание, число заказов и загрузку исполнителей, после чего налаживают логистику и стандарты качества и выходят на другие районы.
-:::
diff --git a/pptx/content/slides/07e-spheres-9-10.md b/pptx/content/slides/07e-spheres-9-10.md
deleted file mode 100644
index 9d9c9c2..0000000
--- a/pptx/content/slides/07e-spheres-9-10.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Сферы 9–10: IT-услуги и банки
-
-::: callout "9. IT-услуги — модуль SaaS-платформы"
-- Новый товар: новый модуль SaaS-платформы.
-- Пилотный спринт: ==бета на 10 клиентов==.
-- Метрика Sprint Review: использование, частота ошибок, NPS.
-- Решение: состав следующего релиза по обратной связи.
-- Особенность: регулярные релизы — естественный режим гибкой разработки.
-:::
-
-::: callout "10. Банковские услуги — вклад «Цель»"
-- Новый товар: вклад «Цель» в мобильном приложении.
-- Пилотный спринт: тест на ==ограниченной группе пользователей==.
-- Метрика Sprint Review: доля открытий, средний срок, удержание.
-- Решение: полное внедрение после согласования с подразделениями банка.
-- Особенность: пилот проводится в контролируемых регулируемых условиях.
-:::
-
-::: notes
-Последние две сферы. В IT новый модуль SaaS-платформы выходит в бету на десять клиентов: измеряют использование, частоту ошибок и NPS, а обратная связь определяет состав следующего релиза — это естественный режим гибкой разработки. В банковских услугах вклад «Цель» тестируется на ограниченной группе пользователей приложения: оценивают долю открытий, срок и удержание. Даже в регулируемой сфере пилот в контролируемых условиях позволяет безопасно проверить спрос до полного внедрения.
-:::
diff --git a/pptx/content/slides/10-conclusion.md b/pptx/content/slides/10-conclusion.md
deleted file mode 100644
index a052590..0000000
--- a/pptx/content/slides/10-conclusion.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Выводы
-
-- Agile/Scrum — ==универсальный метод== выведения товара на рынок
-- Спринты заменяют один дорогой запуск серией дешёвых проверок
-- Роли, артефакты и события делают процесс прозрачным и управляемым
-- Метод работает везде, где есть клиент и обратная связь — от производства до банков
-- Результат — снижение риска и стоимости ошибки при запуске новинки
-
-::: metrics
-10 | сфер применения
-30% | новинок выживают
-4 | недели — длина спринта
-:::
-
-::: notes
-Таким образом, Agile и Scrum — универсальный метод выведения товара на рынок. Спринты заменяют один дорогой запуск серией дешёвых проверок. Роли, артефакты и события делают процесс прозрачным и управляемым. Метод работает везде, где есть клиент и обратная связь: от производства до банковских услуг. Результат — снижение риска и стоимости ошибки при запуске новинки.
-:::
diff --git a/pptx/content/slides/11-final.md b/pptx/content/slides/11-final.md
deleted file mode 100644
index 561018e..0000000
--- a/pptx/content/slides/11-final.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Спасибо за внимание
-
-Степанов П.А., группа 6403-020302D
-
-Слушатель программы профессиональной переподготовки «Современные проектные технологии», ИОТ-трек «ДОП 11»
-
-::: notes
-На этом мой доклад закончен, спасибо за внимание. Готов ответить на ваши вопросы.
-:::
diff --git a/pptx/content/slides/12-scrum-cycle.md b/pptx/content/slides/12-scrum-cycle.md
deleted file mode 100644
index 394dfd5..0000000
--- a/pptx/content/slides/12-scrum-cycle.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Жизненный цикл Scrum
-
-::: image assets/scrum-cycle.puml side=left
-Цикл Scrum: от Product Backlog до масштабирования товара
-:::
-
-::: callout "Как замкнут цикл" side=right
-- Product Backlog фиксирует требования к товару.
-- Спринт длится 1–4 недели и завершается готовым ==инкрементом==.
-- Sprint Review показывает инкремент рынку, ретроспектива улучшает процесс.
-- Подтверждённый спрос ведёт к масштабированию, иначе цикл повторяется.
-- Каждый виток спирали снижает неопределённость и стоимость ошибки.
-:::
-
-::: notes
-На этой схеме слева показан цикл Scrum. Из Product Backlog формируется план спринта. Спринт длится от одной до четырёх недель и завершается инкрементом — готовым пробным продуктом. На Sprint Review рынок даёт обратную связь, после чего команда проводит ретроспективу. Если спрос подтверждён, товар масштабируется; если нет — цикл повторяется с уточнёнными требованиями. Каждый виток снижает неопределённость.
-:::
diff --git a/pptx/package-lock.json b/pptx/package-lock.json
index e101935..79f20ef 100644
--- a/pptx/package-lock.json
+++ b/pptx/package-lock.json
@@ -1,18 +1,18 @@
{
- "name": "lab-gen-pptx",
+ "name": "ssau-generator-pptx",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "lab-gen-pptx",
+ "name": "ssau-generator-pptx",
"version": "1.0.0",
"dependencies": {
"js-yaml": "^4.1.0",
"pptxgenjs": "^3.12.0"
},
"bin": {
- "lab-gen-pptx": "src/cli.js"
+ "ssau-generator-pptx": "src/cli.js"
}
},
"node_modules/@types/node": {
diff --git a/pptx/package.json b/pptx/package.json
index 9e7f179..2d12b16 100644
--- a/pptx/package.json
+++ b/pptx/package.json
@@ -1,10 +1,10 @@
{
- "name": "lab-gen-pptx",
+ "name": "ssau-generator-pptx",
"version": "1.0.0",
"private": true,
- "description": "Генератор презентаций PPTX из Markdown по шаблону Самарского университета",
+ "description": "SSAU Generator PPTX — генератор презентаций PPTX из Markdown по шаблону Самарского университета",
"bin": {
- "lab-gen-pptx": "src/cli.js"
+ "ssau-generator-pptx": "src/cli.js"
},
"main": "src/index.js",
"scripts": {
diff --git a/pptx/src/cli.js b/pptx/src/cli.js
index 24f968b..cd84a03 100644
--- a/pptx/src/cli.js
+++ b/pptx/src/cli.js
@@ -1,8 +1,10 @@
#!/usr/bin/env node
"use strict";
+const fs = require("fs");
const path = require("path");
const { build } = require("./build");
+const { ensureScaffold } = require("./scaffold");
function parseArgs(argv) {
const options = { config: "config.yaml" };
@@ -20,6 +22,9 @@ function parseArgs(argv) {
case "--check":
options.check = true;
break;
+ case "--init":
+ options.init = true;
+ break;
case "--verbose":
case "-v":
options.verbose = true;
@@ -43,15 +48,16 @@ function parseArgs(argv) {
}
function printHelp() {
- console.log(`lab-gen-pptx — генератор презентаций PPTX из Markdown
+ console.log(`SSAU Generator PPTX — генератор презентаций PPTX из Markdown
Использование:
- lab-gen-pptx [config.yaml] [опции]
+ node pptx/src/cli.js [config.yaml] [опции]
Опции:
-c, --config путь к config.yaml (по умолчанию config.yaml)
-o, --output переопределить имя выходного файла
--check только проверить конфигурацию и ссылки
+ --init создать шаблон config.yaml/slides/assets и выйти
-v, --verbose подробный вывод
-h, --help показать справку
--version показать версию
@@ -68,6 +74,26 @@ async function main() {
}
const configPath = path.resolve(options.config);
+
+ if (options.init || !fs.existsSync(configPath)) {
+ const targetDir = path.dirname(configPath);
+ try {
+ const created = await ensureScaffold(targetDir);
+ if (created.length) {
+ console.log("Создан шаблон генератора:");
+ created.forEach((file) => console.log(" " + path.relative(targetDir, file)));
+ } else {
+ console.log("Файлы уже существуют, ничего не создано.");
+ }
+ console.log("");
+ console.log("Отредактируйте config.yaml и файлы в slides/, затем запустите генератор снова.");
+ } catch (error) {
+ console.error(error.message);
+ process.exitCode = 1;
+ }
+ return undefined;
+ }
+
try {
const result = await build({ config: configPath, check: options.check, output: options.output });
const { config, issues } = result;
diff --git a/pptx/src/config.js b/pptx/src/config.js
index 448a3d4..2f54763 100644
--- a/pptx/src/config.js
+++ b/pptx/src/config.js
@@ -24,9 +24,9 @@ const DEFAULTS = {
line: "BFD3DD",
},
backgrounds: {
- title: "content/assets/title-bg.jpeg",
- content: "content/assets/content-bg.jpg",
- final: "content/assets/final-bg.jpeg",
+ title: "assets/title-bg.jpeg",
+ content: "assets/content-bg.jpg",
+ final: "assets/final-bg.jpeg",
},
slideNumber: {
show: true,
@@ -110,7 +110,7 @@ const DEFAULTS = {
timeoutMs: 30000,
},
content: {
- dir: "content",
+ dir: ".",
},
slides: [],
};
diff --git a/pptx/src/plantuml.js b/pptx/src/plantuml.js
index 2d79d4b..19f246d 100644
--- a/pptx/src/plantuml.js
+++ b/pptx/src/plantuml.js
@@ -114,7 +114,7 @@ function cacheFileName(sourceBuffer, cfg) {
}
async function renderCached(sourceBuffer, cfg) {
- const dir = cfg.cacheDir || path.join(os.tmpdir(), "lab-gen-pptx-plantuml");
+ const dir = cfg.cacheDir || path.join(os.tmpdir(), "ssau-generator-pptx-plantuml");
const target = path.join(dir, cacheFileName(sourceBuffer, cfg));
if (cfg.cache && fs.existsSync(target)) {
diff --git a/pptx/src/png.js b/pptx/src/png.js
new file mode 100644
index 0000000..4e8d6f0
--- /dev/null
+++ b/pptx/src/png.js
@@ -0,0 +1,68 @@
+"use strict";
+
+const zlib = require("zlib");
+
+const CRC_TABLE = (() => {
+ const table = new Int32Array(256);
+ for (let n = 0; n < 256; n += 1) {
+ let c = n;
+ for (let k = 0; k < 8; k += 1) {
+ c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
+ }
+ table[n] = c;
+ }
+ return table;
+})();
+
+function crc32(buffer) {
+ let crc = -1;
+ for (let i = 0; i < buffer.length; i += 1) {
+ crc = CRC_TABLE[(crc ^ buffer[i]) & 0xff] ^ (crc >>> 8);
+ }
+ return (crc ^ -1) >>> 0;
+}
+
+function chunk(type, data) {
+ const length = Buffer.alloc(4);
+ length.writeUInt32BE(data.length, 0);
+ const typeBuf = Buffer.from(type, "ascii");
+ const crc = Buffer.alloc(4);
+ crc.writeUInt32BE(crc32(Buffer.concat([typeBuf, data])), 0);
+ return Buffer.concat([length, typeBuf, data, crc]);
+}
+
+/** Кодирует PNG, получая цвет пикселя через getPixel(x, y) -> [r,g,b]. */
+function encodePng(width, height, getPixel) {
+ const signature = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
+ const ihdr = Buffer.alloc(13);
+ ihdr.writeUInt32BE(width, 0);
+ ihdr.writeUInt32BE(height, 4);
+ ihdr[8] = 8;
+ ihdr[9] = 2;
+
+ const rowLength = width * 3;
+ const raw = Buffer.alloc((rowLength + 1) * height);
+ for (let y = 0; y < height; y += 1) {
+ const offset = y * (rowLength + 1);
+ for (let x = 0; x < width; x += 1) {
+ const [r, g, b] = getPixel(x, y);
+ const px = offset + 1 + x * 3;
+ raw[px] = r;
+ raw[px + 1] = g;
+ raw[px + 2] = b;
+ }
+ }
+
+ return Buffer.concat([
+ signature,
+ chunk("IHDR", ihdr),
+ chunk("IDAT", zlib.deflateSync(raw, { level: 9 })),
+ chunk("IEND", Buffer.alloc(0)),
+ ]);
+}
+
+function solidPng(width, height, color) {
+ return encodePng(width, height, () => color);
+}
+
+module.exports = { solidPng, encodePng };
diff --git a/pptx/src/scaffold.js b/pptx/src/scaffold.js
new file mode 100644
index 0000000..a160768
--- /dev/null
+++ b/pptx/src/scaffold.js
@@ -0,0 +1,115 @@
+"use strict";
+
+const fs = require("fs");
+const path = require("path");
+const yaml = require("js-yaml");
+
+const { DEFAULTS, deepMerge } = require("./config");
+const { solidPng } = require("./png");
+
+const CONFIG_HEADER = `# Конфигурация генератора SSAU Generator PPTX.
+# Все относительные пути считаются от каталога этого файла.
+# Любой ключ можно опустить — будет использовано значение по умолчанию.
+
+`;
+
+const SAMPLE = {
+ "slides/00-title.md": `# Название презентации
+
+## Подзаголовок
+`,
+ "slides/01-content.md": `# Первый слайд
+
+- первый пункт списка;
+- второй пункт списка:
+
+ - вложенный пункт;
+
+Обычный абзац с **полужирным**, *курсивом* и ==выделением==.
+`,
+ "slides/02-final.md": `# Спасибо за внимание
+`,
+};
+
+// Цвета задников: [R, G, B].
+const BRAND = [27, 135, 201];
+const BACKGROUNDS = {
+ "title-bg.png": BRAND,
+ "content-bg.png": [255, 255, 255],
+ "final-bg.png": BRAND,
+};
+
+function isGeneratorDir(baseDir) {
+ const base = path.basename(baseDir).toLowerCase();
+ return base === "docx" || base === "pptx";
+}
+
+/**
+ * Раскладка проекта: имя проекта = имя папки проекта, общие ресурсы в
+ * content/<проект>/assets/, результат — content/<проект>/<проект>.pptx.
+ */
+function projectLayout(baseDir) {
+ const isSub = isGeneratorDir(baseDir);
+ const projectDir = isSub ? path.dirname(baseDir) : baseDir;
+ const projectName = path.basename(projectDir) || "project";
+ return {
+ projectDir,
+ projectName,
+ assetsRel: isSub ? "../assets" : "assets",
+ assetsDir: path.join(projectDir, "assets"),
+ outputRel: isSub ? `../${projectName}.pptx` : `${projectName}.pptx`,
+ };
+}
+
+function defaultConfigYaml(layout) {
+ const config = deepMerge(DEFAULTS, {
+ presentation: { output: layout.outputRel },
+ theme: {
+ backgrounds: {
+ title: `${layout.assetsRel}/title-bg.png`,
+ content: `${layout.assetsRel}/content-bg.png`,
+ final: `${layout.assetsRel}/final-bg.png`,
+ },
+ },
+ content: { dir: "." },
+ slides: [
+ { type: "title", file: "slides/00-title.md" },
+ { type: "content", file: "slides/01-content.md" },
+ { type: "final", file: "slides/02-final.md" },
+ ],
+ });
+ return (
+ CONFIG_HEADER +
+ yaml.dump(config, { noRefs: true, lineWidth: -1, sortKeys: false })
+ );
+}
+
+/**
+ * Создаёт config.yaml, примеры слайдов и общие ресурсы проекта
+ * (content/<проект>/assets/), если их ещё нет.
+ */
+async function ensureScaffold(baseDir) {
+ const layout = projectLayout(baseDir);
+ const created = [];
+ const write = (target, content) => {
+ if (fs.existsSync(target)) return;
+ fs.mkdirSync(path.dirname(target), { recursive: true });
+ if (content && typeof content === "object" && content.binary) {
+ fs.writeFileSync(target, content.binary);
+ } else {
+ fs.writeFileSync(target, content, "utf8");
+ }
+ created.push(target);
+ };
+
+ write(path.join(baseDir, "config.yaml"), defaultConfigYaml(layout));
+ for (const [name, content] of Object.entries(SAMPLE)) {
+ write(path.join(baseDir, name), content);
+ }
+ for (const [name, color] of Object.entries(BACKGROUNDS)) {
+ write(path.join(layout.assetsDir, name), { binary: solidPng(1920, 1080, color) });
+ }
+ return created;
+}
+
+module.exports = { projectLayout, defaultConfigYaml, ensureScaffold, SAMPLE };
diff --git a/video-script.md b/video-script.md
deleted file mode 100644
index e4d9f8f..0000000
--- a/video-script.md
+++ /dev/null
@@ -1,98 +0,0 @@
-# Сценарий видеодоклада (≈5 минут)
-
-Докладчик: **Степанов П.А.**, группа **6403-020302D**, ИОТ-трек **«ДОП 11»**,
-программа **«Современные проектные технологии»**.
-Слайды — файл `pptx/presentation.pptx` (заметки докладчика дублируют этот текст).
-
----
-
-## 0:00–0:20. Приветствие (с паспортом)
-
-> Добрый день, уважаемые члены итоговой аттестационной комиссии. Меня зовут
-> Степанов П.А. *(показать в камеру разворот паспорта)*, группа 6403-020302D, я
-> являюсь слушателем программы профессиональной переподготовки «Современные
-> проектные технологии», ИОТ-трек «ДОП 11». Разрешите представить решение
-> итогового задания по теме «Современные проектные технологии».
-
-*(Слайд 1 — титульный.)*
-
-## 0:20–0:45. План доклада
-
-Сначала обосную выбор метода, затем покажу устройство методологии, проверку
-спроса через спринты и применение в десяти сферах деятельности. *(Слайд 2.)*
-
-## 0:45–1:20. Постановка задачи
-
-Задача итогового задания — выбрать метод выведения нового товара на рынок и
-обосновать его применимость в десяти сферах деятельности. Запуск новинки всегда
-сопряжён с риском: до семи из десяти новых товаров не выживают на рынке. Поэтому
-нужен управляемый и повторяемый процесс. В качестве такого метода я выбрал Agile
-и его самую популярную методологию — Scrum. *(Слайд 3.)*
-
-## 1:20–2:30. Метод: Agile и Scrum
-
-Agile — это гибкий подход к управлению проектами, закреплённый в манифесте
-2001 года. Scrum — самая распространённая Agile-методология. Работа разбивается на
-короткие спринты длиной от одной до четырёх недель, каждый из которых завершается
-готовым приростом продукта. *(Слайд 4.)*
-
-В Scrum три роли: Product Owner отвечает за ценность товара, Scrum Master убирает
-препятствия, команда разработки создаёт продукт. Три артефакта — Product Backlog,
-Sprint Backlog и Increment. Четыре события — планирование, ежедневная встреча,
-обзор спринта и ретроспектива. *(Слайды 5–6.)*
-
-Весь цикл замкнут: из Product Backlog формируется спринт, который завершается
-инкрементом; Sprint Review показывает результат рынку, а подтверждённый спрос ведёт
-к масштабированию. *(Слайд 7.)*
-
-Ключевое преимущество: рынок проверяется дешёвым инкрементом — сначала минимальный
-продукт, затем развитие по отклику реальных клиентов. *(Слайд 8.)*
-
-## 2:30–4:10. Применение в десяти сферах
-
-Покажу, что метод работает не только в IT. *(Слайд 9.)* В каждой сфере — свой
-пилотный инкремент и своя метрика спринта.
-
-- **Производство** — линейка упаковки запускается пробной партией на одной линии;
- метрики — себестоимость и доля брака. **Связь** — тариф «Умный дом» тестируется
- на ста абонентах; смотрят подключения и отток. *(Слайд 10.)*
-- **Транспорт** — каршеринг мини-фургонов стартует с пяти машин в одном районе;
- метрики — загрузка и спрос. **Строительство** — сначала возводится один пилотный
- модуль; оценивают затраты и сроки монтажа. *(Слайд 11.)*
-- **Коммерция** — подписка на продуктовые наборы запускается бокс-пилотом на
- пятидесяти клиентах; метрики — конверсия и удержание. **Юридические услуги** —
- пакет «юрфирма на аутсорсе» предлагается пяти клиентам на пробный месяц.
- *(Слайд 12.)*
-- **Организация праздников** — онлайн-конструктор тестируется на одной группе по
- вовлечённости и заказам. **Бытовые услуги** — подписка на уборку стартует с
- двадцати подписчиков; важны удержание и загрузка. *(Слайд 13.)*
-- **IT-услуги** — новый модуль SaaS выходит в бету на десять клиентов; метрики —
- использование и NPS. **Банковские услуги** — вклад «Цель» тестируется на
- ограниченной группе приложения. *(Слайд 14.)*
-
-Везде логика одна: ограниченный пробный продукт — замер метрики на Sprint Review —
-масштабирование.
-
-## 4:10–4:45. Выводы
-
-Agile и Scrum — универсальный метод выведения товара на рынок. Спринты заменяют
-один дорогой запуск серией дешёвых проверок. Метод работает везде, где есть клиент
-и обратная связь: от производства до банковских услуг. Результат — снижение риска
-и стоимости ошибки при запуске новинки. *(Слайд 15.)*
-
-## 4:45–5:00. Заключение
-
-> На этом мой доклад закончен, спасибо за внимание.
-
-*(Слайд 16.)*
-
----
-
-## Чек-лист записи
-
-- [ ] В начале доклада — **демонстрация паспорта** в камеру.
-- [ ] В кадре одновременно видны **вы и презентация**.
-- [ ] Приветствие, основная часть и заключение — по формулировкам выше.
-- [ ] Формат файла — **mp4**, имя: `Видео защита Фамилия И.О.mp4`.
-- [ ] Загрузить в облако: https://disk.ssau.ru/s/s8dSapsJ7bbn8yb
-- [ ] PDF ответа: `Итоговое задание Фамилия И.О.pdf` — в «Материалы итогового задания».