mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-04 01:00:52 +03:00
fix(17 навыков): CRLF в разделителях строк XML (#57)
Головной дефект тикета: cfe-init выдавал Configuration.xml с 10 CR на 70 строк, а роль и язык — вовсе без CR. Теперь 70/70, последний байт `>`. Правило: меняем только РАЗДЕЛИТЕЛИ строк, содержимое текстовых узлов не трогаем. Платформа его не трогает тоже — в запросах СКД из чистой выгрузки встречаются и CRLF, и одиночный LF. Поэтому сплошная нормализация файла применяется только там, где многострочных текстовых узлов нет по построению (скелеты), а в объектном XML и формах разделители правятся в точке сборки. Источников оказалось четыре, а не один: 1. Скелеты (cf-init, cfe-init, epf-init, erf-init, form-add, help-add, template-add) собираются here-string'ами, а .ps1/.py в репозитории хранятся с LF — отсюда LF и смешанный EOL. 2. py-порты склеивали документ через '\n'.join(lines); PS в тех же местах давал CRLF через AppendLine — порты расходились побайтово. 3. Билдеры Predefined в meta-compile собирались с явным LF и даже сворачивали CRLF→LF из общего эмиттера типов. 4. Чтение существующего файла в python БЕЗ newline='' молча схлопывает CRLF в LF (универсальные переводы строк), и запись потом кладёт LF. Так role-compile и subsystem-compile переписывали в LF весь Configuration.xml. meta-compile это уже делал правильно — там newline='' стоял с фикса #44/#46/#47. Отдельно: XML-парсер по спецификации схлопывает CRLF при разборе, поэтому lxml-порты (xdto-compile, xdto-edit) отдавали LF-документ там, где .NET возвращал CRLF через NewLineHandling. Восстанавливаем EOL исходного файла. Разделение канона и сохранения стиля: - файл СОЗДАЁМ — канон (CRLF, без хвоста); - существующий ПРАВИМ — наследуем его EOL, включая перевод строки вставки (контракт #44/#46/#47). Иначе LF-проект получал бы смешанные файлы — ровно то, на что заведён #57. Кейсы roundtrip-crlf-preserve остаются зелёными. Хелпер записи скопирован в каждый навык (навыки автономны). У meta-compile он называется Write-XmlFileKeepEol / write_xml_file_keep_eol: там нормализовать EOL НЕЛЬЗЯ (многострочные запрос, синоним, значение заполнения), и одинаковое имя при разном поведении было бы ловушкой. Заодно: имя временного файла батча в meta-compile.ps1 получило GUID. Фиксированное "meta-compile-batch-$idx.json" в общем %TEMP% сталкивало два параллельных запуска («file is being used by another process») — из-за этого полный набор приходилось гонять с урезанной параллельностью. py-порт уже брал mkstemp. Аудит: было ~250 файлов с дефектом EOL, стало 0 в обоих портах. Осталось четыре законных случая — фикстуры roundtrip-crlf-preserve (сохранение стиля) и запрос динсписка с многострочным текстом. Дрейф снэпшотов — 1 файл. Тесты 641/641. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
abe9431d8f
commit
0b8231c467
@@ -1,4 +1,4 @@
|
||||
# cf-edit v1.12 — Edit 1C configuration root (Configuration.xml)
|
||||
# cf-edit v1.14 — Edit 1C configuration root (Configuration.xml)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)][Alias('Path')][string]$ConfigPath,
|
||||
@@ -163,6 +163,11 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) {
|
||||
Assert-EditAllowed $resolvedPath 'editable'
|
||||
|
||||
# --- Load XML with PreserveWhitespace ---
|
||||
# EOL исходного файла запоминаем ДО разбора: парсер XML по спецификации схлопывает
|
||||
# CRLF в LF, а вставки ниже собираются с явным CRLF — без восстановления в точке
|
||||
# записи LF-файл стал бы смешанным. Канон CRLF относится к файлам, которые мы
|
||||
# СОЗДАЁМ; правка существующего сохраняет его стиль (#44/#46/#47).
|
||||
$script:srcEol = if (([System.IO.File]::ReadAllText($resolvedPath)) -match "`r`n") { "`r`n" } else { "`n" }
|
||||
$script:xmlDoc = New-Object System.Xml.XmlDocument
|
||||
$script:xmlDoc.PreserveWhitespace = $true
|
||||
$script:xmlDoc.Load($resolvedPath)
|
||||
@@ -691,7 +696,8 @@ $bodyBlock$declarations
|
||||
if (-not (Test-Path $extDir)) { New-Item -ItemType Directory -Path $extDir -Force | Out-Null }
|
||||
$caiPath = Join-Path $extDir "ClientApplicationInterface.xml"
|
||||
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
||||
[System.IO.File]::WriteAllText($caiPath, $caiXml, $utf8Bom)
|
||||
# Файл создаём мы — канон: CRLF в разделителях, без перевода строки в конце.
|
||||
[System.IO.File]::WriteAllText($caiPath, (($caiXml -replace "`r`n", "`n") -replace "`n", "`r`n").TrimEnd("`r", "`n"), $utf8Bom)
|
||||
$script:modifyCount++
|
||||
Info "Wrote panel layout: $caiPath"
|
||||
}
|
||||
@@ -880,7 +886,8 @@ $rightXml
|
||||
if (-not (Test-Path $extDir)) { New-Item -ItemType Directory -Path $extDir -Force | Out-Null }
|
||||
$hpPath = Join-Path $extDir "HomePageWorkArea.xml"
|
||||
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
||||
[System.IO.File]::WriteAllText($hpPath, $hpXml, $utf8Bom)
|
||||
# Файл создаём мы — канон: CRLF в разделителях, без перевода строки в конце.
|
||||
[System.IO.File]::WriteAllText($hpPath, (($hpXml -replace "`r`n", "`n") -replace "`n", "`r`n").TrimEnd("`r", "`n"), $utf8Bom)
|
||||
$script:modifyCount++
|
||||
Info "Wrote home page layout: $hpPath"
|
||||
}
|
||||
@@ -985,6 +992,8 @@ $text = $text.Replace('encoding="utf-8"', 'encoding="UTF-8"')
|
||||
# Пустой элемент: XmlWriter пишет `<a />`, Конфигуратор — `<a/>`. Гард на CDATA/комментарии:
|
||||
# только там `>` не экранируется, и ` />` может быть содержимым, а не концом тега.
|
||||
if ($text -notmatch '<!\[CDATA\[|<!--') { $text = [regex]::Replace($text, '(?<=\S) />', '/>') }
|
||||
# Возвращаем EOL исходного файла: вставки собраны с CRLF, а сам документ мог быть LF.
|
||||
$text = ($text -replace "`r`n", "`n") -replace "`n", $script:srcEol
|
||||
|
||||
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
||||
[System.IO.File]::WriteAllText($resolvedPath, $text, $utf8Bom)
|
||||
|
||||
Reference in New Issue
Block a user