fix(*-validate,*-init): проверенный диапазон версий формата 2.17–2.21

Валидаторы объявляли «ожидаемым» литеральный список версий и ругались на всё
остальное как на подозрительное. Но 2.13–2.16 не подозрительны — они просто не
проверялись, а form-validate вдобавок отстал на 2.21 и предупреждал о форме, которую
сам же создаёт цепочкой epf-init 2.21 → form-add (issue #63).

Теперь сравнение числовое, через общий Get-FormatRank, и исходов три: ниже 2.17 и
выше 2.21 — предупреждение «not verified on it», нечисловое значение — ошибка. Раньше
мусор вида «abc» и реальная версия 2.16 давали одно и то же предупреждение.

В *-init ValidateSet/choices сняты: версия вне диапазона больше не запрет, а
предупреждение в stderr — скаффолд выпускается. Опечатка (2,17) остаётся ошибкой.
Предупреждение печатается напрямую в stderr и после настройки кодировки консоли:
Write-Warning в PS 5.1 уходит в stdout, получает локализованный префикс и перенос по
80 символов, а до [Console]::OutputEncoding em-dash уезжал в вопросы — оба расхождения
ломали паритет с py-портом.

Отдельно в cf-init исправлен гейт TextToSpeech: свойство приезжает форматом 2.18
(8.3.25), а не 2.21. Замер: выгрузки пустой ИБ шести платформ — 37 записей
UsedMobileApplicationFunctionalities на 2.13/2.17 и 38 на 2.18–2.21. Ролики загрузки
показали, что это настоящее новое свойство, а не смена дефолта эмиссии: на 2.17 тег
роняет загрузку XDTO-ошибкой (8.3.24), значение значимо (true переживает роундтрип),
а пропуск на 2.18+ разводит роундтрип — платформа допишет тег сама. Снапшоты трёх
кейсов meta-compile обновлены: их фикстуры строятся cf-init, дельта — только вставка
тега.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-13 14:20:40 +03:00
co-authored by Claude Opus 5
parent 35c8618813
commit de76fde275
61 changed files with 2345 additions and 99 deletions
+36 -8
View File
@@ -1,4 +1,4 @@
# cf-init v1.11 — Create empty 1C configuration scaffold (+write_xml_file/write_utf8_bom: общий эталон записи)
# cf-init v1.13 — Create empty 1C configuration scaffold (+write_xml_file/write_utf8_bom: общий эталон записи)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -9,14 +9,26 @@ param(
[string]$Vendor,
[string]$CompatibilityMode = "Version8_3_24",
# Версия формата выгрузки (MDClasses). Её задаёт ПЛАТФОРМА, которой выгружают, и от режима
# совместимости она не зависит: 8.3.20-8.3.24 пишут 2.17, 8.3.25 — 2.18, 8.3.26 — 2.19,
# 8.3.27 — 2.20. Дефолт консервативный: 2.17 читается всеми поддерживаемыми платформами.
[ValidateSet("2.17", "2.18", "2.19", "2.20", "2.21")]
# совместимости она не зависит. Дефолт 2.17 — нижняя граница проверенного диапазона.
[string]$FormatVersion = "2.17"
)
$ErrorActionPreference = "Stop"
# --- Format version ---
# Проверенный диапазон: 2.17 (8.3.24) … 2.21 (8.5). Полная лестница — docs/1c-configuration-spec.md,
# «Лестница версий». Версии ниже 2.17 (платформы 8.3.23 и старше) реальны, поэтому запретом их не
# закрываем: за пределами диапазона — ПРЕДУПРЕЖДЕНИЕ, скаффолд всё равно выпускается. Ошибка — только
# на нечисловое значение: это опечатка, а не версия.
$formatVerifiedMin = "2.17"
$formatVerifiedMax = "2.21"
# Версия формата как число: "2.20" → 220. Строковое сравнение неверно ("2.9" > "2.17").
function Get-FormatRank([string]$ver) {
if ($ver -match '^(\d+)\.(\d+)$') { return [int]$Matches[1] * 100 + [int]$Matches[2] }
return 0
}
$formatRank = Get-FormatRank $FormatVersion
function Esc-XmlText {
param([string]$s)
# Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми.
@@ -24,6 +36,17 @@ function Esc-XmlText {
}
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# Проверка версии — ПОСЛЕ настройки кодировки консоли: иначе em-dash в сообщении уедет в вопросы.
# Пишем прямо в stderr, а не Write-Warning: в PS 5.1 предупреждение уходит в stdout, получает
# локализованный префикс и переносится по 80 символов — подстрока в тесте перестаёт находиться.
if ($formatRank -eq 0) {
[Console]::Error.WriteLine("Malformed -FormatVersion '$FormatVersion' (expected N.N, e.g. 2.17)")
exit 1
}
if ($formatRank -lt (Get-FormatRank $formatVerifiedMin) -or $formatRank -gt (Get-FormatRank $formatVerifiedMax)) {
[Console]::Error.WriteLine("WARNING: Format version '$FormatVersion' is outside the tested range $formatVerifiedMin-$formatVerifiedMax — the scaffold is emitted as requested but was not verified on that platform")
}
# --- Resolve output dir ---
if (-not [System.IO.Path]::IsPathRooted($OutputDir)) {
$OutputDir = Join-Path (Get-Location).Path $OutputDir
@@ -50,7 +73,9 @@ $co7 = [guid]::NewGuid().ToString()
# --- Mobile functionalities ---
# Версия формата как число — по ней ниже включаются вставки 2.21.
$is221 = (($FormatVersion -match '^(\d+)\.(\d+)$') -and ([int]$Matches[1] * 100 + [int]$Matches[2]) -ge 221)
$is221 = ($formatRank -ge 221)
# TextToSpeech приехал раньше остальных вставок 8.5 — своей ступенью, поэтому гейт отдельный.
$is218 = ($formatRank -ge 218)
$mobileFuncs = @(
@("Biometrics","true"), @("Location","false"), @("BackgroundLocation","false"),
@@ -68,9 +93,12 @@ $mobileFuncs = @(
@("DocumentScanning","false"), @("SpeechToText","false"), @("Geofences","false"),
@("IncomingShareRequests","false"), @("AllIncomingShareRequestsTypesProcessing","false")
)
# TextToSpeech — возможность мобильного приложения, добавленная форматом 2.21 (8.5),
# последней в списке. На младших форматах платформа её не пишет.
if ($is221) { $mobileFuncs += ,@("TextToSpeech","false") }
# TextToSpeech — возможность мобильного приложения, добавленная форматом 2.18 (8.3.25),
# последней в списке; в 2.21 список не менялся. Замерено выгрузками пустой ИБ шести платформ:
# 2.13/2.17 — 37 записей без неё, 2.18-2.21 — 38 с ней. Гейт обязателен и в обе стороны:
# на 2.17 тег ломает загрузку XDTO-ошибкой (проверено на 8.3.24), без тега на 2.18+ платформа
# подставит дефолт false и допишет его при выгрузке — то есть разойдётся роундтрип.
if ($is218) { $mobileFuncs += ,@("TextToSpeech","false") }
$mobileXml = ""
foreach ($mf in $mobileFuncs) {