fix(template-add,help-add): закрыть находки ревью по коду языка и странице

help-add терял текст справки. Отказ смотрит только на Help.xml, а страница может
пережить его (удалённый дескриптор, частичная выгрузка, справка, сделанная руками):
тогда запись шла безусловно и стирала содержимое с кодом 0 и рапортом [OK].
Теперь существующая страница сохраняется, создаётся только дескриптор — та же
защита, что уже стоит в template-add. Прежняя оценка «в help-add потери данных нет»
была неверной: она опиралась на чтение кода, а не на замер.

Код языка: регулярка пропускала имена устройств Windows. При -Lang nul py-порт
молча писал <Page>nul</Page> и пустой каталог с кодом 0 (страница уходила в NUL),
а PS падал исключением — то есть порты ещё и расходились. Якоря \A…\z вместо ^…$:
последние в обоих языках допускают перевод строки в конце.

Проверка вынесена в Test-LangCode / is_valid_lang и внесена в реестр
check-inline-drift: inline-блок гард не видел, а копий у него две.

Плюс мелочи оттуда же: мёртвый дизъюнкт в $pageExists убран; полумигрированное
дерево (дескриптор есть, старый Ext/Template.html остался рядом) теперь получает
предупреждение, а не молчание; существование страницы в py сверяется без учёта
регистра — иначе на Linux -Lang RU писал бы вторую страницу мимо дескриптора.

Четыре кейса на каждый сценарий. Существующие эталоны не сдвинулись.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-09-22 18:50:58 +03:00
co-authored by Claude Opus 5
parent c619da4a0a
commit dc470a3803
20 changed files with 359 additions and 31 deletions
+30 -10
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# help-add v1.21 — Add built-in help to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи)
# help-add v1.22 — Add built-in help to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -293,6 +293,26 @@ def write_utf8_bom(path, content):
def is_valid_lang(code):
"""Код языка идёт и в текст XML, и в имя файла страницы.
Пустое значение дало бы файл «.html» и пустой <Page></Page>, разделитель пути — запись
мимо каталога страниц, а зарезервированное имя устройства (nul, con, prn, aux, com1…, lpt1…)
на Windows уводит запись в само устройство: при -Lang nul этот порт молча писал
<Page>nul</Page> и пустой каталог с кодом 0. Все отказы платформы были бы тихими.
fullmatch, а не match: последний с `$` допускает перевод строки в конце.
Копия этой функции есть в template-add (навыки автономны, формат «дескриптор + страница»
у них общий). Держать копии одинаковыми — сознательно; за дрейфом следит check-inline-drift.
"""
if not re.fullmatch(r"[A-Za-z0-9_-]+", code):
return False
if re.fullmatch(r"(?i)(con|prn|aux|nul|com[1-9]|lpt[1-9])", code):
return False
return True
def write_xml_file(path, content):
"""XML в каноне выгрузки Конфигуратора: CRLF в разделителях, без перевода в конце.
@@ -329,15 +349,9 @@ def main():
print(f"Каталог объекта не найден: {ext_dir}. Проверьте путь ObjectName (например Catalogs/МойСправочник).", file=sys.stderr)
sys.exit(1)
# Код языка идёт и в текст XML, и в имя файла страницы, поэтому проверяем его до записи:
# пустое значение дало бы файл «.html» и пустой <Page></Page>, а разделитель пути —
# запись мимо каталога Ext/Help. Оба отказа платформы были бы тихими.
#
# Копия этой проверки есть в template-add (навыки автономны, формат «дескриптор +
# страница» у них общий). Держать копии одинаковыми — сознательно.
if not re.match(r"^[A-Za-z0-9_-]+$", lang):
if not is_valid_lang(lang):
print(f"Недопустимый код языка: '{lang}'", file=sys.stderr)
print("Ожидается код вида ru, en (буквы, цифры, дефис, подчёркивание)", file=sys.stderr)
print("Ожидается код вида ru, en (буквы, цифры, дефис, подчёркивание; имена устройств Windows недопустимы)", file=sys.stderr)
sys.exit(1)
help_xml_path = os.path.join(ext_dir, "Help.xml")
@@ -382,7 +396,13 @@ def main():
'</html>'
)
write_utf8_bom(help_html_path, help_html)
# Файл страницы НЕ перезаписываем: отказ выше смотрит только на Help.xml, а страница может
# пережить его (удалённый дескриптор, частичная выгрузка, справка, сделанная руками) — и тогда
# безусловная запись молча стирала бы текст справки с кодом 0.
if os.path.exists(help_html_path):
print(f"[WARN] Страница {lang}.html уже лежала на диске — содержимое сохранено, создан только дескриптор.")
else:
write_utf8_bom(help_html_path, help_html)
# --- 3. Check IncludeHelpInContents in form metadata ---