fix(cfe-borrow): strip CommandSet, ExcludedCommand and RowPictureDataPath from borrowed forms

ФормаСписка (list forms) contain elements invalid in extensions:
- <CommandSet><ExcludedCommand>Create</ExcludedCommand></CommandSet> at form root
- <ExcludedCommand> in nested AutoCommandBars within ChildItems
- <RowPictureDataPath> in table elements (e.g. Список.СостояниеДокумента)

All three cause "Неверное имя команды элемента формы" on load.
Verified against Configurator reference dump (ref-ext-dump-6).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-03-10 22:05:33 +03:00
parent 84d078bd05
commit 7abe26afee
2 changed files with 14 additions and 2 deletions
@@ -489,7 +489,7 @@ function Borrow-Form {
if ($fc.LocalName -eq 'ChildItems' -and -not $srcChildItems) {
$reachedVisual = $true; $srcChildItems = $fc; continue
}
if ($fc.LocalName -eq 'Events' -or $fc.LocalName -eq 'Attributes' -or $fc.LocalName -eq 'Commands' -or $fc.LocalName -eq 'Parameters') {
if ($fc.LocalName -eq 'Events' -or $fc.LocalName -eq 'Attributes' -or $fc.LocalName -eq 'Commands' -or $fc.LocalName -eq 'Parameters' -or $fc.LocalName -eq 'CommandSet') {
$reachedVisual = $true; continue
}
if (-not $reachedVisual) {
@@ -507,6 +507,8 @@ function Borrow-Form {
$autoCmdXml = [regex]::Replace($autoCmdXml, $nsStripPattern, '')
$autoCmdXml = [regex]::Replace($autoCmdXml, '<CommandName>[^<]*</CommandName>', '<CommandName>0</CommandName>')
$autoCmdXml = $autoCmdXml -replace '<Autofill>true</Autofill>', '<Autofill>false</Autofill>'
# Strip ExcludedCommand (references to standard commands invalid in extension)
$autoCmdXml = [regex]::Replace($autoCmdXml, '\s*<ExcludedCommand>[^<]*</ExcludedCommand>', '')
}
# ChildItems: copy full tree, clean up base-config references
@@ -520,6 +522,10 @@ function Borrow-Form {
$childItemsXml = [regex]::Replace($childItemsXml, '\s*<DataPath>[^<]*</DataPath>', '')
# Strip TitleDataPath (e.g. Объект.Товары.RowsCount — invalid without base attributes)
$childItemsXml = [regex]::Replace($childItemsXml, '\s*<TitleDataPath>[^<]*</TitleDataPath>', '')
# Strip RowPictureDataPath (e.g. Список.СостояниеДокумента — invalid in extension)
$childItemsXml = [regex]::Replace($childItemsXml, '\s*<RowPictureDataPath>[^<]*</RowPictureDataPath>', '')
# Strip ExcludedCommand in nested AutoCommandBars (references to standard commands invalid in extension)
$childItemsXml = [regex]::Replace($childItemsXml, '\s*<ExcludedCommand>[^<]*</ExcludedCommand>', '')
# Strip TypeLink blocks with human-readable DataPath (Items.XXX — can't convert to UUID)
$childItemsXml = [regex]::Replace($childItemsXml, '(?s)\s*<TypeLink>\s*<xr:DataPath>Items\.[^<]*</xr:DataPath>.*?</TypeLink>', '')
# Strip element-level Events (base form handlers not in extension)
@@ -662,7 +662,7 @@ def main():
reached_visual = True
src_auto_cmd = fc
continue
if ln in ("ChildItems", "Events", "Attributes", "Commands", "Parameters"):
if ln in ("ChildItems", "Events", "Attributes", "Commands", "Parameters", "CommandSet"):
reached_visual = True
continue
if not reached_visual:
@@ -678,6 +678,8 @@ def main():
auto_cmd_xml = ns_strip_pattern.sub("", auto_cmd_xml)
auto_cmd_xml = re.sub(r'<CommandName>[^<]*</CommandName>', '<CommandName>0</CommandName>', auto_cmd_xml)
auto_cmd_xml = auto_cmd_xml.replace('<Autofill>true</Autofill>', '<Autofill>false</Autofill>')
# Strip ExcludedCommand (references to standard commands invalid in extension)
auto_cmd_xml = re.sub(r'\s*<ExcludedCommand>[^<]*</ExcludedCommand>', '', auto_cmd_xml)
# ChildItems: copy full tree, clean up base-config references
child_items_xml = ""
@@ -696,6 +698,10 @@ def main():
child_items_xml = re.sub(r'\s*<DataPath>[^<]*</DataPath>', '', child_items_xml)
# Strip TitleDataPath
child_items_xml = re.sub(r'\s*<TitleDataPath>[^<]*</TitleDataPath>', '', child_items_xml)
# Strip RowPictureDataPath (e.g. Список.СостояниеДокумента — invalid in extension)
child_items_xml = re.sub(r'\s*<RowPictureDataPath>[^<]*</RowPictureDataPath>', '', child_items_xml)
# Strip ExcludedCommand in nested AutoCommandBars (references to standard commands invalid in extension)
child_items_xml = re.sub(r'\s*<ExcludedCommand>[^<]*</ExcludedCommand>', '', child_items_xml)
# Strip TypeLink blocks with human-readable DataPath (Items.XXX)
child_items_xml = re.sub(r'\s*<TypeLink>\s*<xr:DataPath>Items\.[^<]*</xr:DataPath>.*?</TypeLink>', '', child_items_xml, flags=re.DOTALL)
# Strip element-level Events