Support any 1C config dump and auto wiki URL from its git remote.
Add info command, -c/--config, derived repo.wiki.git target, and README for submodule/root workflows.
This commit is contained in:
+15
-30
@@ -2,45 +2,30 @@
|
|||||||
|
|
||||||
All notable changes to **export_1c_help** are documented in this file.
|
All notable changes to **export_1c_help** are documented in this file.
|
||||||
|
|
||||||
|
## [0.3.0] - 2026-07-23
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Export help from **any** 1C configuration dump (`-c` / `--config` or `-s` / `--src`)
|
||||||
|
- Auto wiki URL from the configuration git repo: `repo.git` → `repo.wiki.git` (Gitea/GitLab)
|
||||||
|
- Explicit `--wiki-url` still supported (any target wiki)
|
||||||
|
- `info` subcommand: src, version, git remote, derived wiki URL
|
||||||
|
- Per-config default output dirs: `out/wiki-md-<slug>`, `out/wiki_clone-<slug>`
|
||||||
|
- README: connect any submodule / root project to its wiki and run export
|
||||||
|
|
||||||
## [0.2.0] - 2026-07-23
|
## [0.2.0] - 2026-07-23
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Configuration version on each export (`VERSION` / `Configuration.xml`)
|
- Configuration version on each export (`VERSION` / `Configuration.xml`)
|
||||||
- Per-page lifecycle in wiki footer and `manifest.json`:
|
- Per-page lifecycle: `created_in` / `edited_in` / `deleted_in`
|
||||||
- `created_in` — версия конфигурации, в которой страница впервые попала в wiki
|
- `History.md`, `push` reads previous `manifest.json` from wiki
|
||||||
- `edited_in` — версия, в которой содержимое справки изменилось
|
|
||||||
- `deleted_in` — версия, в которой страница исчезла из `src`
|
|
||||||
- `History.md` — сводка выгрузки и накопительный список удалённых страниц
|
|
||||||
- `push` читает предыдущий `manifest.json` из wiki перед пересборкой
|
|
||||||
- CLI: `--prev-manifest`, `--config-version`
|
- CLI: `--prev-manifest`, `--config-version`
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Home / Sidebar показывают версию конфигурации и ссылку на History
|
|
||||||
|
|
||||||
## [0.1.0] - 2026-07-23
|
## [0.1.0] - 2026-07-23
|
||||||
|
|
||||||
### Status
|
Initial release: Help HTML → Markdown, Gitea wiki push, percent-encoded Cyrillic filenames.
|
||||||
|
|
||||||
**In development.** Full dump of configuration Help to Gitea wiki.
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Discovery of `**/Ext/Help/ru.html` in a 1C configuration `src/` tree (incl. nested `Subsystems`)
|
|
||||||
- HTML → Markdown converter (stdlib only): headings, lists, bold/italic, links
|
|
||||||
- Rewrite of 1C help links (`Catalog.X/Help`, `….Form.Y/Help`) to Gitea `[[wiki]]` links
|
|
||||||
- Unique wiki page titles (H1 / synonym / meta key) with collision suffixes
|
|
||||||
- Gitea-compatible **percent-encoded** filenames for Cyrillic titles
|
|
||||||
- `Home.md` index and `_Sidebar.md` navigation
|
|
||||||
- `manifest.json` (meta_key → title mapping)
|
|
||||||
- CLI: `convert`, `push` (clone/commit/push wiki git repo)
|
|
||||||
- Option `--objects-only` to skip form-level help
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Nested subsystem help paths (`Subsystems/A/Subsystems/B/…`) no longer collapse to the parent meta key
|
|
||||||
- Unicode wiki filenames replaced with percent-encoded slugs (Gitea UI returned HTTP 500)
|
|
||||||
|
|
||||||
|
[0.3.0]: https://git.p7net.ru/tools/export_1c_help/releases/tag/v0.3.0
|
||||||
[0.2.0]: https://git.p7net.ru/tools/export_1c_help/releases/tag/v0.2.0
|
[0.2.0]: https://git.p7net.ru/tools/export_1c_help/releases/tag/v0.2.0
|
||||||
[0.1.0]: https://git.p7net.ru/tools/export_1c_help/releases/tag/v0.1.0
|
[0.1.0]: https://git.p7net.ru/tools/export_1c_help/releases/tag/v0.1.0
|
||||||
|
|||||||
@@ -1,108 +1,187 @@
|
|||||||
# export_1c_help
|
# export_1c_help
|
||||||
|
|
||||||
**Версия:** см. [`VERSION`](VERSION) (текущая: **0.2.0**) · [CHANGELOG](CHANGELOG.md)
|
**Версия:** см. [`VERSION`](VERSION) (текущая: **0.3.0**) · [CHANGELOG](CHANGELOG.md)
|
||||||
**Лицензия:** [MIT](LICENSE)
|
**Лицензия:** [MIT](LICENSE)
|
||||||
|
|
||||||
Выгрузка встроенной справки конфигурации 1С (`**/Ext/Help/ru.html`) в Markdown и публикация в [Gitea Wiki](https://docs.gitea.com/usage/wiki).
|
Выгрузка встроенной справки **любой** конфигурации 1С (`**/Ext/Help/ru.html`) в Markdown и публикация в wiki git-репозитория (Gitea / GitLab: `*.wiki.git`).
|
||||||
|
|
||||||
Зависимости: **Python 3.10+**, только стандартная библиотека.
|
Зависимости: **Python 3.10+**, только стандартная библиотека.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Порядок обновления wiki (после доработки справки в конфигурации)
|
## Подключение произвольной конфигурации к wiki
|
||||||
|
|
||||||
Инструмент **всегда** пересобирает wiki из всего `src/` (инкрементального патча нет). Частичная правка Help в конфигураторе → полная перевыгрузка `src` → полный `push`.
|
Инструмент не привязан к `crm3-26`. Источник — каталог выгрузки конфигурации (подмодуль или корневой git-проект). Цель — wiki **этого** репозитория либо любой другой `*.wiki.git`.
|
||||||
|
|
||||||
1. Доработать справку в конфигураторе (нужные объекты/формы).
|
### 1. Подготовка репозитория конфигурации
|
||||||
2. Выгрузить конфигурацию в git (`crm3-26/`) и закоммитить/запушить, как обычно.
|
|
||||||
3. В монорепо: `git pull` (актуальный `crm3-26/src`, в т.ч. `VERSION` / `Configuration.xml`).
|
|
||||||
4. Синхронизировать wiki:
|
|
||||||
|
|
||||||
```bash
|
1. Конфигурация лежит в git (отдельный репозиторий или submodule), типичная структура:
|
||||||
cd tools/export_1c_help
|
|
||||||
python3 export_1c_help.py push \
|
```text
|
||||||
-s ../../crm3-26/src \
|
<config-root>/
|
||||||
--wiki-url https://git.p7net.ru/1c/crm3_26.wiki.git \
|
VERSION # опционально
|
||||||
-m "sync help after config update"
|
src/
|
||||||
|
Configuration.xml
|
||||||
|
Catalogs/…/Ext/Help/ru.html
|
||||||
|
…
|
||||||
```
|
```
|
||||||
|
|
||||||
Перед записью можно проверить без push:
|
2. На сервере (Gitea / GitLab) у репозитория конфигурации **включена Wiki**.
|
||||||
|
3. Убедитесь, что у вас есть права **push** в wiki (`…/repo.wiki.git`).
|
||||||
|
Первый push создаст/обновит страницы; на Gitea wiki должна быть уже инициализирована (хотя бы пустая/одна страница через UI, если сервер так требует).
|
||||||
|
|
||||||
|
Проверка путей и URL:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd tools/export_1c_help # или путь к клону export_1c_help
|
||||||
|
|
||||||
|
# подмодуль в монорепо
|
||||||
|
python3 export_1c_help.py info -c ../../crm3-26
|
||||||
|
|
||||||
|
# корневой клон конфигурации
|
||||||
|
python3 export_1c_help.py info -c /path/to/my_config
|
||||||
|
|
||||||
|
# только src
|
||||||
|
python3 export_1c_help.py info -s /path/to/my_config/src
|
||||||
|
```
|
||||||
|
|
||||||
|
Пример вывода:
|
||||||
|
|
||||||
|
```text
|
||||||
|
config_root: …/crm3-26
|
||||||
|
src: …/crm3-26/src
|
||||||
|
config_version: 3.1.36.33
|
||||||
|
git_remote(origin): https://git.p7net.ru/1c/crm3_26.git
|
||||||
|
wiki_url: https://git.p7net.ru/1c/crm3_26.wiki.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Правило авто-URL: `https://host/org/repo.git` → `https://host/org/repo.wiki.git`
|
||||||
|
(аналогично для `git@host:org/repo.git`).
|
||||||
|
|
||||||
|
### 2. Первая выгрузка в wiki репозитория конфигурации
|
||||||
|
|
||||||
|
Без `--wiki-url` цель берётся из `origin` git-репозитория, которому принадлежит `-c` / `-s`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# подмодуль
|
||||||
|
python3 export_1c_help.py push -c ../../crm3-26
|
||||||
|
|
||||||
|
# любой другой корень / submodule
|
||||||
|
python3 export_1c_help.py push -c /path/to/other_config
|
||||||
|
|
||||||
|
# dry-run (только сборка MD, без push)
|
||||||
|
python3 export_1c_help.py push -c ../../crm3-26 --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
Промежуточные каталоги по умолчанию (чтобы не смешивать конфигурации):
|
||||||
|
|
||||||
|
- `out/wiki-md-<имя-корня>/`
|
||||||
|
- `out/wiki_clone-<имя-корня>/`
|
||||||
|
|
||||||
|
### 3. Выгрузка в произвольный wiki
|
||||||
|
|
||||||
|
Если wiki не у того же репозитория (или remote не определяется):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 export_1c_help.py push \
|
python3 export_1c_help.py push \
|
||||||
-s ../../crm3-26/src \
|
-c /path/to/config \
|
||||||
--wiki-url https://git.p7net.ru/1c/crm3_26.wiki.git \
|
--wiki-url https://git.example/org/docs.wiki.git
|
||||||
--dry-run
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Канон текста** — HTML в конфигурации. Ручные правки страниц в wiki сотрутся при следующем `push` (если не указан `--keep-unmanaged`).
|
Можно указать и URL кода — он будет преобразован в `.wiki.git`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 export_1c_help.py push \
|
||||||
|
-c /path/to/config \
|
||||||
|
--wiki-url https://git.example/org/docs.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Другой remote (не `origin`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 export_1c_help.py push -c /path/to/config --remote upstream
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Обновление после доработки справки в конфигураторе
|
||||||
|
|
||||||
|
Инструмент **всегда** пересобирает wiki из всего `src/` (инкремента нет).
|
||||||
|
|
||||||
|
1. Доработать Help в конфигураторе.
|
||||||
|
2. Выгрузить конфигурацию в её git-репозиторий (`git commit` / `push`).
|
||||||
|
3. Обновить рабочую копию (`git pull` / `git submodule update`).
|
||||||
|
4. Снова:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 export_1c_help.py push -c /path/to/config
|
||||||
|
```
|
||||||
|
|
||||||
|
**Канон текста** — HTML в конфигурации. Ручные правки wiki сотрутся при следующем `push` (если нет `--keep-unmanaged`).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Версии конфигурации на страницах
|
## Версии конфигурации на страницах
|
||||||
|
|
||||||
| Где | Что фиксируется |
|
| Где | Что |
|
||||||
|-----|-----------------|
|
|-----|-----|
|
||||||
| `Home.md` | версия конфигурации **этой** выгрузки |
|
| `Home.md` | версия конфигурации **этой** выгрузки |
|
||||||
| подвал каждой страницы | версия выгрузки; **создана в** / **изменена в** |
|
| подвал страницы | версия выгрузки; **создана в** / **изменена в** |
|
||||||
| `History.md` | сводка +/−/~ и накопительный список **удалённых** (`deleted_in`) |
|
| `History.md` | сводка +/−/~ и удалённые (`deleted_in`) |
|
||||||
| `manifest.json` | те же поля + `content_hash`, история `exports[]` |
|
| `manifest.json` | lifecycle + `content_hash` + `exports[]` |
|
||||||
|
|
||||||
Версия берётся из `<config>/VERSION` или `<Version>` в `Configuration.xml` (можно переопределить `--config-version`).
|
Версия: `<config>/VERSION` или `<Version>` в `Configuration.xml` (`--config-version` перекрывает).
|
||||||
|
|
||||||
Жизненный цикл считается относительно предыдущего `manifest.json` в wiki (при `push` подтягивается автоматически).
|
При `push` предыдущий `manifest.json` читается из целевой wiki автоматически.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Быстрый старт
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd tools/export_1c_help
|
|
||||||
|
|
||||||
python3 export_1c_help.py convert \
|
|
||||||
-s ../../crm3-26/src \
|
|
||||||
-o ./out/wiki-md \
|
|
||||||
--clean
|
|
||||||
|
|
||||||
python3 export_1c_help.py push \
|
|
||||||
-s ../../crm3-26/src \
|
|
||||||
--wiki-url https://git.p7net.ru/1c/crm3_26.wiki.git
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python3 export_1c_help.py --version
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Команды
|
## Команды
|
||||||
|
|
||||||
### `convert`
|
| Команда | Назначение |
|
||||||
|
|---------|------------|
|
||||||
|
| `info` | пути, версия, remote, wiki URL |
|
||||||
|
| `convert` | только Markdown на диск |
|
||||||
|
| `push` | convert + commit/push в wiki |
|
||||||
|
|
||||||
|
Общие параметры источника (взаимоисключающие):
|
||||||
|
|
||||||
| Параметр | Описание |
|
| Параметр | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
| `-s` / `--src` | каталог `src` выгрузки конфигурации |
|
| `-c` / `--config` | корень конфигурации (`…/crm3-26`) **или** её `src/` |
|
||||||
| `-o` / `--out` | каталог результата |
|
| `-s` / `--src` | явно каталог `src` |
|
||||||
|
|
||||||
|
| Параметр | Описание |
|
||||||
|
|----------|----------|
|
||||||
|
| `--wiki-url` | явный wiki (иначе из git remote конфигурации) |
|
||||||
|
| `--remote` | имя remote для авто-URL (`origin`) |
|
||||||
| `--objects-only` | без справки форм |
|
| `--objects-only` | без справки форм |
|
||||||
| `--keep-empty` | не пропускать почти пустые страницы |
|
| `--dry-run` | без git push |
|
||||||
| `--clean` | очистить `--out` перед записью |
|
| `--prev-manifest` | свой предыдущий manifest |
|
||||||
| `--prev-manifest` | предыдущий `manifest.json` (lifecycle) |
|
| `--config-version` | явная версия |
|
||||||
| `--config-version` | явная версия конфигурации |
|
|
||||||
|
|
||||||
### `push`
|
|
||||||
|
|
||||||
`prepare wiki` → `convert` (с `manifest.json` из wiki) → `git commit` / `push`.
|
|
||||||
|
|
||||||
| Параметр | Описание |
|
|
||||||
|----------|----------|
|
|
||||||
| `--wiki-url` | URL `*.wiki.git` |
|
|
||||||
| `--dry-run` | только convert |
|
|
||||||
| `--keep-unmanaged` | не удалять чужие `.md` |
|
|
||||||
| `-m` / `--message` | сообщение коммита |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Репозиторий
|
## Примеры для монорепозитория миграции
|
||||||
|
|
||||||
- путь: `tools/export_1c_help/`
|
```bash
|
||||||
|
# целевая crm3-26 → её wiki
|
||||||
|
python3 export_1c_help.py push -c ../../crm3-26
|
||||||
|
|
||||||
|
# исходная crm3-dev → её wiki (если wiki включена у crm3_old)
|
||||||
|
python3 export_1c_help.py push -c ../../crm3-dev
|
||||||
|
|
||||||
|
# расширение — только если в выгрузке есть Ext/Help
|
||||||
|
python3 export_1c_help.py info -c ../../crm3-26.rhana
|
||||||
|
```
|
||||||
|
|
||||||
|
Только локальная конвертация:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 export_1c_help.py convert -c ../../crm3-26 -o ./out/wiki-md-crm3-26 --clean
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Репозиторий инструмента
|
||||||
|
|
||||||
|
- путь в монорепо: `tools/export_1c_help/`
|
||||||
- remote: https://git.p7net.ru/tools/export_1c_help.git
|
- remote: https://git.p7net.ru/tools/export_1c_help.git
|
||||||
|
|||||||
@@ -0,0 +1,137 @@
|
|||||||
|
"""Resolve configuration paths and Gitea/GitLab wiki clone URLs."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
class ResolveError(ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_src_root(config_or_src: Path) -> Path:
|
||||||
|
"""
|
||||||
|
Accept configuration root (…/crm3-26) or its src/ dump.
|
||||||
|
|
||||||
|
Returns absolute path to the directory that contains Catalogs/, Documents/, …
|
||||||
|
"""
|
||||||
|
path = Path(config_or_src).expanduser().resolve()
|
||||||
|
if not path.exists():
|
||||||
|
raise ResolveError(f"path does not exist: {path}")
|
||||||
|
|
||||||
|
if path.is_file():
|
||||||
|
raise ResolveError(f"expected directory, got file: {path}")
|
||||||
|
|
||||||
|
if _looks_like_src(path):
|
||||||
|
return path
|
||||||
|
|
||||||
|
src = path / "src"
|
||||||
|
if src.is_dir() and _looks_like_src(src):
|
||||||
|
return src.resolve()
|
||||||
|
|
||||||
|
raise ResolveError(
|
||||||
|
f"not a 1C configuration dump: {path} "
|
||||||
|
"(need …/src with Catalogs|Documents|Configuration.xml, or the src itself)"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_config_root(config_or_src: Path) -> Path:
|
||||||
|
"""Configuration root (parent of src when applicable)."""
|
||||||
|
src = resolve_src_root(config_or_src)
|
||||||
|
if src.name == "src":
|
||||||
|
return src.parent
|
||||||
|
return src
|
||||||
|
|
||||||
|
|
||||||
|
def _looks_like_src(path: Path) -> bool:
|
||||||
|
if (path / "Configuration.xml").is_file():
|
||||||
|
return True
|
||||||
|
markers = ("Catalogs", "Documents", "DataProcessors", "Reports", "CommonModules")
|
||||||
|
return any((path / name).is_dir() for name in markers)
|
||||||
|
|
||||||
|
|
||||||
|
def git_toplevel(path: Path) -> Path | None:
|
||||||
|
"""Nearest git work tree containing path (submodule or root project)."""
|
||||||
|
path = Path(path).resolve()
|
||||||
|
try:
|
||||||
|
proc = subprocess.run(
|
||||||
|
["git", "-C", str(path), "rev-parse", "--show-toplevel"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
except OSError:
|
||||||
|
return None
|
||||||
|
if proc.returncode != 0:
|
||||||
|
return None
|
||||||
|
top = proc.stdout.strip()
|
||||||
|
return Path(top) if top else None
|
||||||
|
|
||||||
|
|
||||||
|
def git_remote_url(path: Path, *, remote: str = "origin") -> str | None:
|
||||||
|
"""Clone URL of `remote` for the git repo that owns path."""
|
||||||
|
top = git_toplevel(path)
|
||||||
|
if top is None:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
proc = subprocess.run(
|
||||||
|
["git", "-C", str(top), "remote", "get-url", remote],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
except OSError:
|
||||||
|
return None
|
||||||
|
if proc.returncode != 0:
|
||||||
|
return None
|
||||||
|
url = proc.stdout.strip()
|
||||||
|
return url or None
|
||||||
|
|
||||||
|
|
||||||
|
def to_wiki_clone_url(repo_url: str) -> str:
|
||||||
|
"""
|
||||||
|
Map configuration repository URL → wiki git URL.
|
||||||
|
|
||||||
|
Gitea / GitLab: https://host/org/repo.git → https://host/org/repo.wiki.git
|
||||||
|
git@host:org/repo.git → git@host:org/repo.wiki.git
|
||||||
|
"""
|
||||||
|
url = repo_url.strip().rstrip("/")
|
||||||
|
if not url:
|
||||||
|
raise ResolveError("empty repository URL")
|
||||||
|
|
||||||
|
if url.endswith(".wiki.git"):
|
||||||
|
return url
|
||||||
|
|
||||||
|
if url.endswith(".git"):
|
||||||
|
return url[: -len(".git")] + ".wiki.git"
|
||||||
|
|
||||||
|
return url + ".wiki.git"
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_wiki_url(
|
||||||
|
config_or_src: Path,
|
||||||
|
*,
|
||||||
|
wiki_url: str | None = None,
|
||||||
|
remote: str = "origin",
|
||||||
|
) -> str:
|
||||||
|
"""Explicit --wiki-url, or derive from git remote of the configuration repo."""
|
||||||
|
if wiki_url:
|
||||||
|
return to_wiki_clone_url(wiki_url)
|
||||||
|
|
||||||
|
root = resolve_config_root(config_or_src)
|
||||||
|
repo = git_remote_url(root, remote=remote)
|
||||||
|
if not repo:
|
||||||
|
raise ResolveError(
|
||||||
|
f"cannot detect git remote '{remote}' for {root}; "
|
||||||
|
"pass --wiki-url explicitly (…/repo.wiki.git)"
|
||||||
|
)
|
||||||
|
return to_wiki_clone_url(repo)
|
||||||
|
|
||||||
|
|
||||||
|
def slug_for_path(path: Path) -> str:
|
||||||
|
"""Short filesystem-safe slug from config root name."""
|
||||||
|
name = resolve_config_root(path).name
|
||||||
|
slug = re.sub(r"[^\w.\-]+", "-", name, flags=re.UNICODE).strip("-")
|
||||||
|
return slug or "config"
|
||||||
+119
-23
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""CLI: export 1C Help (ru.html) to Markdown / Gitea wiki."""
|
"""CLI: export 1C Help (ru.html) to Markdown / Gitea/GitLab wiki."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -12,8 +12,20 @@ if str(TOOL_ROOT) not in sys.path:
|
|||||||
sys.path.insert(0, str(TOOL_ROOT))
|
sys.path.insert(0, str(TOOL_ROOT))
|
||||||
|
|
||||||
from export1c_help import __status__, __version__ # noqa: E402
|
from export1c_help import __status__, __version__ # noqa: E402
|
||||||
from export1c_help.config_version import read_config_version # noqa: E402
|
from export1c_help.config_version import ( # noqa: E402
|
||||||
|
read_config_name,
|
||||||
|
read_config_version,
|
||||||
|
)
|
||||||
from export1c_help.export import export_help # noqa: E402
|
from export1c_help.export import export_help # noqa: E402
|
||||||
|
from export1c_help.resolve import ( # noqa: E402
|
||||||
|
ResolveError,
|
||||||
|
git_remote_url,
|
||||||
|
git_toplevel,
|
||||||
|
resolve_config_root,
|
||||||
|
resolve_src_root,
|
||||||
|
resolve_wiki_url,
|
||||||
|
slug_for_path,
|
||||||
|
)
|
||||||
from export1c_help.wiki import WikiPushError, prepare_wiki_clone, push_wiki # noqa: E402
|
from export1c_help.wiki import WikiPushError, prepare_wiki_clone, push_wiki # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
@@ -21,7 +33,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
p = argparse.ArgumentParser(
|
p = argparse.ArgumentParser(
|
||||||
prog="export_1c_help",
|
prog="export_1c_help",
|
||||||
description=(
|
description=(
|
||||||
f"Выгрузка встроенной справки 1С (Ext/Help/ru.html) в Markdown / Gitea wiki. "
|
f"Выгрузка встроенной справки любой конфигурации 1С в Markdown / wiki. "
|
||||||
f"v{__version__} ({__status__})."
|
f"v{__version__} ({__status__})."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -29,29 +41,53 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
|
|
||||||
sub = p.add_subparsers(dest="cmd", required=True)
|
sub = p.add_subparsers(dest="cmd", required=True)
|
||||||
|
|
||||||
|
i = sub.add_parser(
|
||||||
|
"info",
|
||||||
|
help="Показать src, версию, git remote и wiki URL для конфигурации",
|
||||||
|
)
|
||||||
|
_add_config_path_args(i)
|
||||||
|
i.add_argument("--remote", default="origin", help="Git remote (по умолчанию origin)")
|
||||||
|
i.add_argument(
|
||||||
|
"--wiki-url",
|
||||||
|
default=None,
|
||||||
|
help="Явный wiki URL (иначе из remote конфигурации)",
|
||||||
|
)
|
||||||
|
i.set_defaults(func=cmd_info)
|
||||||
|
|
||||||
c = sub.add_parser("convert", help="Конвертация Help → Markdown в каталог")
|
c = sub.add_parser("convert", help="Конвертация Help → Markdown в каталог")
|
||||||
_add_convert_args(c)
|
_add_convert_args(c)
|
||||||
c.set_defaults(func=cmd_convert)
|
c.set_defaults(func=cmd_convert)
|
||||||
|
|
||||||
w = sub.add_parser("push", help="convert + push в Gitea wiki (.wiki.git)")
|
w = sub.add_parser(
|
||||||
|
"push",
|
||||||
|
help="convert + push в wiki (явный --wiki-url или wiki репозитория конфигурации)",
|
||||||
|
)
|
||||||
_add_convert_args(w, require_out=False)
|
_add_convert_args(w, require_out=False)
|
||||||
w.add_argument(
|
w.add_argument(
|
||||||
"--wiki-url",
|
"--wiki-url",
|
||||||
required=True,
|
default=None,
|
||||||
help="URL wiki-репозитория, напр. https://git.p7net.ru/1c/crm3_26.wiki.git",
|
help=(
|
||||||
|
"URL wiki-репозитория (…/repo.wiki.git). "
|
||||||
|
"Если не задан — берётся из git remote конфигурации (…/repo.git → …/repo.wiki.git)"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
w.add_argument(
|
||||||
|
"--remote",
|
||||||
|
default="origin",
|
||||||
|
help="Git remote конфигурации для авто-wiki URL (по умолчанию origin)",
|
||||||
)
|
)
|
||||||
w.add_argument(
|
w.add_argument(
|
||||||
"--work-dir",
|
"--work-dir",
|
||||||
type=Path,
|
type=Path,
|
||||||
default=None,
|
default=None,
|
||||||
help="Локальный clone wiki (по умолчанию: <out-parent>/wiki_clone)",
|
help="Локальный clone wiki (по умолчанию: out/wiki_clone-<slug>)",
|
||||||
)
|
)
|
||||||
w.add_argument(
|
w.add_argument(
|
||||||
"-o",
|
"-o",
|
||||||
"--out",
|
"--out",
|
||||||
type=Path,
|
type=Path,
|
||||||
default=None,
|
default=None,
|
||||||
help="Промежуточный каталог MD (по умолчанию: ./out/wiki-md)",
|
help="Промежуточный каталог MD (по умолчанию: out/wiki-md-<slug>)",
|
||||||
)
|
)
|
||||||
w.add_argument(
|
w.add_argument(
|
||||||
"--keep-unmanaged",
|
"--keep-unmanaged",
|
||||||
@@ -66,14 +102,25 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
return p
|
return p
|
||||||
|
|
||||||
|
|
||||||
def _add_convert_args(p: argparse.ArgumentParser, *, require_out: bool = True) -> None:
|
def _add_config_path_args(p: argparse.ArgumentParser) -> argparse._MutuallyExclusiveGroup:
|
||||||
p.add_argument(
|
g = p.add_mutually_exclusive_group(required=True)
|
||||||
|
g.add_argument(
|
||||||
|
"-c",
|
||||||
|
"--config",
|
||||||
|
type=Path,
|
||||||
|
help="Корень выгрузки конфигурации (каталог с src/) или сам src/",
|
||||||
|
)
|
||||||
|
g.add_argument(
|
||||||
"-s",
|
"-s",
|
||||||
"--src",
|
"--src",
|
||||||
type=Path,
|
type=Path,
|
||||||
required=True,
|
help="Каталог src выгрузки (эквивалент -c …/src)",
|
||||||
help="Каталог src выгрузки конфигурации (…/crm3-26/src)",
|
|
||||||
)
|
)
|
||||||
|
return g
|
||||||
|
|
||||||
|
|
||||||
|
def _add_convert_args(p: argparse.ArgumentParser, *, require_out: bool = True) -> None:
|
||||||
|
_add_config_path_args(p)
|
||||||
if require_out:
|
if require_out:
|
||||||
p.add_argument(
|
p.add_argument(
|
||||||
"-o",
|
"-o",
|
||||||
@@ -111,6 +158,14 @@ def _add_convert_args(p: argparse.ArgumentParser, *, require_out: bool = True) -
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _config_input(args: argparse.Namespace) -> Path:
|
||||||
|
return args.config if getattr(args, "config", None) else args.src
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_src(args: argparse.Namespace) -> Path:
|
||||||
|
return resolve_src_root(_config_input(args))
|
||||||
|
|
||||||
|
|
||||||
def _print_stats(stats, dest: Path) -> None:
|
def _print_stats(stats, dest: Path) -> None:
|
||||||
print(
|
print(
|
||||||
f"OK: config={stats.config_version} "
|
f"OK: config={stats.config_version} "
|
||||||
@@ -122,14 +177,42 @@ def _print_stats(stats, dest: Path) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_info(args: argparse.Namespace) -> int:
|
||||||
|
try:
|
||||||
|
src = _resolve_src(args)
|
||||||
|
root = resolve_config_root(src)
|
||||||
|
wiki = resolve_wiki_url(src, wiki_url=args.wiki_url, remote=args.remote)
|
||||||
|
except ResolveError as exc:
|
||||||
|
print(f"error: {exc}", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
top = git_toplevel(root)
|
||||||
|
remote_url = git_remote_url(root, remote=args.remote)
|
||||||
|
print(f"config_root: {root}")
|
||||||
|
print(f"src: {src}")
|
||||||
|
print(f"config_name: {read_config_name(src) or '—'}")
|
||||||
|
print(f"config_version: {read_config_version(src)}")
|
||||||
|
print(f"git_toplevel: {top or '—'}")
|
||||||
|
print(f"git_remote({args.remote}): {remote_url or '—'}")
|
||||||
|
print(f"wiki_url: {wiki}")
|
||||||
|
print(f"slug: {slug_for_path(src)}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def cmd_convert(args: argparse.Namespace) -> int:
|
def cmd_convert(args: argparse.Namespace) -> int:
|
||||||
|
try:
|
||||||
|
src = _resolve_src(args)
|
||||||
|
except ResolveError as exc:
|
||||||
|
print(f"error: {exc}", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
stats = export_help(
|
stats = export_help(
|
||||||
args.src,
|
src,
|
||||||
args.out,
|
args.out,
|
||||||
include_forms=not args.objects_only,
|
include_forms=not args.objects_only,
|
||||||
skip_empty=not args.keep_empty,
|
skip_empty=not args.keep_empty,
|
||||||
clean=args.clean,
|
clean=args.clean,
|
||||||
source_label=args.source_label,
|
source_label=args.source_label or str(src),
|
||||||
prev_manifest_path=args.prev_manifest,
|
prev_manifest_path=args.prev_manifest,
|
||||||
config_version=args.config_version,
|
config_version=args.config_version,
|
||||||
)
|
)
|
||||||
@@ -138,27 +221,40 @@ def cmd_convert(args: argparse.Namespace) -> int:
|
|||||||
|
|
||||||
|
|
||||||
def cmd_push(args: argparse.Namespace) -> int:
|
def cmd_push(args: argparse.Namespace) -> int:
|
||||||
out = args.out or (TOOL_ROOT / "out" / "wiki-md")
|
try:
|
||||||
work = args.work_dir or (out.parent / "wiki_clone")
|
src = _resolve_src(args)
|
||||||
|
wiki_url = resolve_wiki_url(
|
||||||
|
src, wiki_url=args.wiki_url, remote=args.remote
|
||||||
|
)
|
||||||
|
except ResolveError as exc:
|
||||||
|
print(f"error: {exc}", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
slug = slug_for_path(src)
|
||||||
|
out = args.out or (TOOL_ROOT / "out" / f"wiki-md-{slug}")
|
||||||
|
work = args.work_dir or (TOOL_ROOT / "out" / f"wiki_clone-{slug}")
|
||||||
branch = args.branch
|
branch = args.branch
|
||||||
|
|
||||||
|
print(f"wiki_url: {wiki_url}")
|
||||||
|
print(f"src: {src}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
prepare_wiki_clone(args.wiki_url, work, branch=branch)
|
prepare_wiki_clone(wiki_url, work, branch=branch)
|
||||||
except WikiPushError as exc:
|
except WikiPushError as exc:
|
||||||
print(f"wiki prepare failed:\n{exc}", file=sys.stderr)
|
print(f"wiki prepare failed:\n{exc}", file=sys.stderr)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
prev = args.prev_manifest or (work / "manifest.json")
|
prev = args.prev_manifest or (work / "manifest.json")
|
||||||
cfg = args.config_version or read_config_version(args.src)
|
cfg = args.config_version or read_config_version(src)
|
||||||
|
|
||||||
stats = export_help(
|
stats = export_help(
|
||||||
args.src,
|
src,
|
||||||
out,
|
out,
|
||||||
include_forms=not args.objects_only,
|
include_forms=not args.objects_only,
|
||||||
skip_empty=not args.keep_empty,
|
skip_empty=not args.keep_empty,
|
||||||
clean=True,
|
clean=True,
|
||||||
source_label=args.source_label or str(args.src),
|
source_label=args.source_label or str(src),
|
||||||
prev_manifest_path=prev if prev.is_file() else None,
|
prev_manifest_path=prev if Path(prev).is_file() else None,
|
||||||
config_version=cfg,
|
config_version=cfg,
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
@@ -178,7 +274,7 @@ def cmd_push(args: argparse.Namespace) -> int:
|
|||||||
try:
|
try:
|
||||||
push_wiki(
|
push_wiki(
|
||||||
out,
|
out,
|
||||||
args.wiki_url,
|
wiki_url,
|
||||||
work_dir=work,
|
work_dir=work,
|
||||||
message=message,
|
message=message,
|
||||||
branch=branch,
|
branch=branch,
|
||||||
@@ -188,7 +284,7 @@ def cmd_push(args: argparse.Namespace) -> int:
|
|||||||
except WikiPushError as exc:
|
except WikiPushError as exc:
|
||||||
print(f"push failed:\n{exc}", file=sys.stderr)
|
print(f"push failed:\n{exc}", file=sys.stderr)
|
||||||
return 1
|
return 1
|
||||||
print(f"OK: pushed → {args.wiki_url}")
|
print(f"OK: pushed → {wiki_url}")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user